Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index ce780ef..ce5d2c0 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -199,7 +199,7 @@
     modifications are prevented
 - saves the compiler work to optimize redundant code away ;)
 
-int fun(int )
+int fun(int a)
 {
 	int result = 0;
 	char *buffer = kmalloc(SIZE);
diff --git a/Documentation/DocBook/.gitignore b/Documentation/DocBook/.gitignore
new file mode 100644
index 0000000..c102c02
--- /dev/null
+++ b/Documentation/DocBook/.gitignore
@@ -0,0 +1,6 @@
+*.xml
+*.ps
+*.pdf
+*.html
+*.9.gz
+*.9
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 3c47a3f..8c9c670 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -54,6 +54,11 @@
 !Ekernel/sched.c
 !Ekernel/timer.c
      </sect1>
+     <sect1><title>High-resolution timers</title>
+!Iinclude/linux/ktime.h
+!Iinclude/linux/hrtimer.h
+!Ekernel/hrtimer.c
+     </sect1>
      <sect1><title>Internal Functions</title>
 !Ikernel/exit.c
 !Ikernel/signal.c
diff --git a/Documentation/applying-patches.txt b/Documentation/applying-patches.txt
index 05a08c2..a083ba3 100644
--- a/Documentation/applying-patches.txt
+++ b/Documentation/applying-patches.txt
@@ -3,8 +3,7 @@
 	------------------------------------
 
 	Original by: Jesper Juhl, August 2005
-	Last update: 2005-12-02
-
+	Last update: 2006-01-05
 
 
 A frequently asked question on the Linux Kernel Mailing List is how to apply
@@ -77,7 +76,7 @@
 
 If you wish to uncompress the patch file by hand first before applying it
 (what I assume you've done in the examples below), then you simply run
-gunzip or bunzip2 on the file - like this:
+gunzip or bunzip2 on the file -- like this:
 	gunzip patch-x.y.z.gz
 	bunzip2 patch-x.y.z.bz2
 
@@ -95,7 +94,7 @@
 ---
  When patch applies a patch file it attempts to verify the sanity of the
 file in different ways.
-Checking that the file looks like a valid patch file, checking the code
+Checking that the file looks like a valid patch file & checking the code
 around the bits being modified matches the context provided in the patch are
 just two of the basic sanity checks patch does.
 
@@ -122,7 +121,7 @@
 read this file to see exactly what change couldn't be applied, so you can
 go fix it up by hand if you wish.
 
-If you don't have any third party patches applied to your kernel source, but
+If you don't have any third-party patches applied to your kernel source, but
 only patches from kernel.org and you apply the patches in the correct order,
 and have made no modifications yourself to the source files, then you should
 never see a fuzz or reject message from patch. If you do see such messages
@@ -137,7 +136,7 @@
 find a file to be patched. Most likely you forgot to specify -p1 or you are
 in the wrong directory. Less often, you'll find patches that need to be
 applied with -p0 instead of -p1 (reading the patch file should reveal if
-this is the case - if so, then this is an error by the person who created
+this is the case -- if so, then this is an error by the person who created
 the patch but is not fatal).
 
 If you get "Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines)." or a
@@ -168,13 +167,17 @@
 
 A message similar to "patch: **** unexpected end of file in patch" or "patch
 unexpectedly ends in middle of line" means that patch could make no sense of
-the file you fed to it. Either your download is broken or you tried to feed
-patch a compressed patch file without uncompressing it first.
+the file you fed to it. Either your download is broken, you tried to feed
+patch a compressed patch file without uncompressing it first, or the patch
+file that you are using has been mangled by a mail client or mail transfer
+agent along the way somewhere, e.g., by splitting a long line into two lines.
+Often these warnings can easily be fixed by joining (concatenating) the
+two lines that had been split.
 
 As I already mentioned above, these errors should never happen if you apply
 a patch from kernel.org to the correct version of an unmodified source tree.
 So if you get these errors with kernel.org patches then you should probably
-assume that either your patch file or your tree is broken and I'd advice you
+assume that either your patch file or your tree is broken and I'd advise you
 to start over with a fresh download of a full kernel tree and the patch you
 wish to apply.
 
@@ -200,10 +203,10 @@
  Another alternative is `ketchup', which is a python script for automatic
 downloading and applying of patches (http://www.selenic.com/ketchup/).
 
- Other nice tools are diffstat which shows a summary of changes made by a
-patch, lsdiff which displays a short listing of affected files in a patch
-file, along with (optionally) the line numbers of the start of each patch
-and grepdiff which displays a list of the files modified by a patch where
+ Other nice tools are diffstat, which shows a summary of changes made by a
+patch; lsdiff, which displays a short listing of affected files in a patch
+file, along with (optionally) the line numbers of the start of each patch;
+and grepdiff, which displays a list of the files modified by a patch where
 the patch contains a given regular expression.
 
 
@@ -228,8 +231,8 @@
 In place of ftp.kernel.org you can use ftp.cc.kernel.org, where cc is a
 country code. This way you'll be downloading from a mirror site that's most
 likely geographically closer to you, resulting in faster downloads for you,
-less bandwidth used globally and less load on the main kernel.org servers -
-these are good things, do use mirrors when possible.
+less bandwidth used globally and less load on the main kernel.org servers --
+these are good things, so do use mirrors when possible.
 
 
 The 2.6.x kernels
@@ -237,14 +240,14 @@
  These are the base stable releases released by Linus. The highest numbered
 release is the most recent.
 
-If regressions or other serious flaws are found then a -stable fix patch
+If regressions or other serious flaws are found, then a -stable fix patch
 will be released (see below) on top of this base. Once a new 2.6.x base
 kernel is released, a patch is made available that is a delta between the
 previous 2.6.x kernel and the new one.
 
-To apply a patch moving from 2.6.11 to 2.6.12 you'd do the following (note
+To apply a patch moving from 2.6.11 to 2.6.12, you'd do the following (note
 that such patches do *NOT* apply on top of 2.6.x.y kernels but on top of the
-base 2.6.x kernel - if you need to move from 2.6.x.y to 2.6.x+1 you need to
+base 2.6.x kernel -- if you need to move from 2.6.x.y to 2.6.x+1 you need to
 first revert the 2.6.x.y patch).
 
 Here are some examples:
@@ -266,7 +269,7 @@
 
 The 2.6.x.y kernels
 ---
- Kernels with 4 digit versions are -stable kernels. They contain small(ish)
+ Kernels with 4-digit versions are -stable kernels. They contain small(ish)
 critical fixes for security problems or significant regressions discovered
 in a given 2.6.x kernel.
 
@@ -277,9 +280,14 @@
 If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is
 the current stable kernel.
 
+ note: the -stable team usually do make incremental patches available as well
+ as patches against the latest mainline release, but I only cover the
+ non-incremental ones below. The incremental ones can be found at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/incr/
+
 These patches are not incremental, meaning that for example the 2.6.12.3
 patch does not apply on top of the 2.6.12.2 kernel source, but rather on top
-of the base 2.6.12 kernel source.
+of the base 2.6.12 kernel source .
 So, in order to apply the 2.6.12.3 patch to your existing 2.6.12.2 kernel
 source you have to first back out the 2.6.12.2 patch (so you are left with a
 base 2.6.12 kernel source) and then apply the new 2.6.12.3 patch.
@@ -345,12 +353,12 @@
 repository, hence the name).
 
 These patches are usually released daily and represent the current state of
-Linus' tree. They are more experimental than -rc kernels since they are
+Linus's tree. They are more experimental than -rc kernels since they are
 generated automatically without even a cursory glance to see if they are
 sane.
 
 -git patches are not incremental and apply either to a base 2.6.x kernel or
-a base 2.6.x-rc kernel - you can see which from their name.
+a base 2.6.x-rc kernel -- you can see which from their name.
 A patch named 2.6.12-git1 applies to the 2.6.12 kernel source and a patch
 named 2.6.13-rc3-git2 applies to the source of the 2.6.13-rc3 kernel.
 
@@ -393,12 +401,12 @@
 ensure maximum testing.
 
 This branch is in constant flux and contains many experimental features, a
-lot of debugging patches not appropriate for mainline etc and is the most
+lot of debugging patches not appropriate for mainline etc., and is the most
 experimental of the branches described in this document.
 
 These kernels are not appropriate for use on systems that are supposed to be
 stable and they are more risky to run than any of the other branches (make
-sure you have up-to-date backups - that goes for any experimental kernel but
+sure you have up-to-date backups -- that goes for any experimental kernel but
 even more so for -mm kernels).
 
 These kernels in addition to all the other experimental patches they contain
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 22e4040..f4d0de6 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -2,11 +2,11 @@
 Ext3 Filesystem
 ===============
 
-ext3 was originally released in September 1999. Written by Stephen Tweedie
-for 2.2 branch, and ported to 2.4 kernels by Peter Braam, Andreas Dilger, 
+Ext3 was originally released in September 1999. Written by Stephen Tweedie
+for the 2.2 branch, and ported to 2.4 kernels by Peter Braam, Andreas Dilger,
 Andrew Morton, Alexander Viro, Ted Ts'o and Stephen Tweedie.
 
-ext3 is ext2 filesystem enhanced with journalling capabilities. 
+Ext3 is the ext2 filesystem enhanced with journalling capabilities.
 
 Options
 =======
@@ -14,69 +14,71 @@
 When mounting an ext3 filesystem, the following option are accepted:
 (*) == default
 
-jounal=update		Update the ext3 file system's journal to the 
-			current format.
+journal=update		Update the ext3 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 ext3 file
-			system's journal file.
+journal=inum		When a journal already exists, this option is ignored.
+			Otherwise, it specifies the number of the inode which
+			will represent the ext3 file system's journal file.
 
 journal_dev=devnum	When the external journal device's major/minor numbers
-			have changed, this option allows to specify the new
-			journal location. The journal device is identified
-			through its new major/minor numbers encoded in devnum.
+			have changed, this option allows the user to specify
+			the new journal location.  The journal device is
+			identified through its new major/minor numbers encoded
+			in devnum.
 
 noload			Don't load the journal on mounting.
 
-data=journal		All data are committed into the journal prior
-			to being written into the main file system.
+data=journal		All data are committed into the journal prior to being
+			written into the main file system.
 
 data=ordered	(*)	All data are forced directly out to the main file
-			system prior to its metadata being committed to
-			the journal.
+			system prior to its metadata being committed to the
+			journal.
 
-data=writeback		Data ordering is not preserved, data may be
-			written into the main file system after its
-			metadata has been committed to the journal.
+data=writeback		Data ordering is not preserved, data may be written
+			into the main file system after its metadata has been
+			committed to the journal.
 
 commit=nrsec	(*)	Ext3 can be told to sync all its data and metadata
 			every 'nrsec' seconds. The default value is 5 seconds.
-			This means that if you lose your power, you will lose,
-			as much, the latest 5 seconds of work (your filesystem
-			will not be damaged though, thanks to journaling). This
-			default value (or any low value) will hurt performance,
-			but it's good for data-safety. Setting it to 0 will
-			have the same effect than leaving the default 5 sec.
+			This means that if you lose your power, you will lose
+			as much as the latest 5 seconds of work (your
+			filesystem will not be damaged though, thanks to the
+			journaling).  This default value (or any low value)
+			will hurt performance, but it's good for data-safety.
+			Setting it to 0 will have the same effect as leaving
+			it at the default (5 seconds).
 			Setting it to very large values will improve
 			performance.
 
-barrier=1		This enables/disables barriers. barrier=0 disables it,
-			barrier=1 enables it.
+barrier=1		This enables/disables barriers.  barrier=0 disables
+			it, barrier=1 enables it.
 
-orlov		(*)	This enables the new Orlov block allocator. It's enabled
-			by default.
+orlov		(*)	This enables the new Orlov block allocator. It is
+			enabled by default.
 
-oldalloc		This disables the Orlov block allocator and enables the
-			old block allocator. Orlov should have better performance,
-			we'd like to get some feedback if it's the contrary for
-			you.
+oldalloc		This disables the Orlov block allocator and enables
+			the old block allocator.  Orlov should have better
+			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_EXT3_FS_XATTR). See the attr(5)
-			manual page and http://acl.bestbits.at to learn more
-			about extended attributes.
+user_xattr		Enables Extended User Attributes.  Additionally, you
+			need to have extended attribute support enabled in the
+			kernel configuration (CONFIG_EXT3_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_EXT3_FS_POSIX_ACL). See the acl(5)
-			manual page and http://acl.bestbits.at for more
-			information.
+acl			Enables POSIX Access Control Lists support.
+			Additionally, you need to have ACL support enabled in
+			the kernel configuration (CONFIG_EXT3_FS_POSIX_ACL).
+			See the acl(5) manual page and http://acl.bestbits.at/
+			for more information.
 
-noacl			This option disables POSIX Access Control List support.
+noacl			This option disables POSIX Access Control List
+			support.
 
 reservation
 
@@ -88,7 +90,7 @@
 minixdf			Make 'df' act like Minix.
 
 check=none		Don't do extra checking of bitmaps on mount.
-nocheck		
+nocheck
 
 debug			Extra debugging information is sent to syslog.
 
@@ -97,7 +99,7 @@
 errors=panic		Panic and halt the machine if an error occurs.
 
 grpid			Give objects the same group ID as their creator.
-bsdgroups		
+bsdgroups
 
 nogrpid		(*)	New objects have the group ID of their creator.
 sysvgroups
@@ -108,81 +110,81 @@
 
 sb=n			Use alternate superblock at this location.
 
-quota			Quota options are currently silently ignored.
-noquota			(see fs/ext3/super.c, line 594)
+quota
+noquota
 grpquota
 usrquota
 
 
 Specification
 =============
-ext3 shares all disk implementation with ext2 filesystem, and add
-transactions capabilities to ext2.  Journaling is done by the
-Journaling block device layer.
+Ext3 shares all disk implementation with the ext2 filesystem, and adds
+transactions capabilities to ext2.  Journaling is done by the Journaling Block
+Device layer.
 
 Journaling Block Device layer
 -----------------------------
-The Journaling Block Device layer (JBD) isn't ext3 specific.  It was
-design to add journaling capabilities on a block device.  The ext3
-filesystem code will inform the JBD of modifications it is performing
-(Call a transaction).  the journal support the transactions start and
-stop, and in case of crash, the journal can replayed the transactions
-to put the partition on a consistent state fastly.
+The Journaling Block Device layer (JBD) isn't ext3 specific.  It was design to
+add journaling capabilities on a block device.  The ext3 filesystem code will
+inform the JBD of modifications it is performing (called a transaction).  The
+journal supports the transactions start and stop, and in case of crash, the
+journal can replayed the transactions to put the partition back in a
+consistent state fast.
 
-handles represent a single atomic update to a filesystem.  JBD can
-handle external journal on a block device.
+Handles represent a single atomic update to a filesystem.  JBD can handle an
+external journal on a block device.
 
 Data Mode
 ---------
-There's 3 different data modes:
+There are 3 different data modes:
 
 * writeback mode
-In data=writeback mode, ext3 does not journal data at all.  This mode
-provides a similar level of journaling as XFS, JFS, and ReiserFS in its
-default mode - metadata journaling.  A crash+recovery can cause
-incorrect data to appear in files which were written shortly before the
-crash.  This mode will typically provide the best ext3 performance.
+In data=writeback mode, ext3 does not journal data at all.  This mode provides
+a similar level of journaling as that of XFS, JFS, and ReiserFS in its default
+mode - metadata journaling.  A crash+recovery can cause incorrect data to
+appear in files which were written shortly before the crash.  This mode will
+typically provide the best ext3 performance.
 
 * ordered mode
-In data=ordered mode, ext3 only officially journals metadata, but it
-logically groups metadata and data blocks into a single unit called a
-transaction.  When it's time to write the new metadata out to disk, the
-associated data blocks are written first.  In general, this mode
-perform slightly slower than writeback but significantly faster than
-journal mode.
+In data=ordered mode, ext3 only officially journals metadata, but it logically
+groups metadata and data blocks into a single unit called a transaction.  When
+it's time to write the new metadata out to disk, the associated data blocks
+are written first.  In general, this mode performs slightly slower than
+writeback but significantly faster than journal mode.
 
 * journal mode
-data=journal mode provides full data and metadata journaling.  All new
-data is 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 outperform all others mode.
+data=journal mode provides full data and metadata journaling.  All new data is
+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.
 
 Compatibility
 -------------
 
 Ext2 partitions can be easily convert to ext3, with `tune2fs -j <dev>`.
-Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
-mounted as Ext2.
+Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be mounted as
+Ext2.
+
 
 External Tools
 ==============
-see manual pages to know more.
+See manual pages to learn more.
 
-tune2fs: 	create a ext3 journal on a ext2 partition with the -j flags
-mke2fs: 	create a ext3 partition with the -j flags
-debugfs: 	ext2 and ext3 file system debugger
+tune2fs: 	create a ext3 journal on a ext2 partition with the -j flag.
+mke2fs: 	create a ext3 partition with the -j flag.
+debugfs: 	ext2 and ext3 file system debugger.
+
 
 References
 ==========
 
-kernel source:	file:/usr/src/linux/fs/ext3
-		file:/usr/src/linux/fs/jbd
+kernel source:	<file:fs/ext3/>
+		<file:fs/jbd/>
 
-programs: 	http://e2fsprogs.sourceforge.net
+programs: 	http://e2fsprogs.sourceforge.net/
 
-useful link:
-		http://www.zip.com.au/~akpm/linux/ext3/ext3-usage.html
+useful links:	http://www.zip.com.au/~akpm/linux/ext3/ext3-usage.html
 		http://www-106.ibm.com/developerworks/linux/library/l-fs7/
 		http://www-106.ibm.com/developerworks/linux/library/l-fs8/
diff --git a/Documentation/hrtimers.txt b/Documentation/hrtimers.txt
new file mode 100644
index 0000000..7620ff7
--- /dev/null
+++ b/Documentation/hrtimers.txt
@@ -0,0 +1,178 @@
+
+hrtimers - subsystem for high-resolution kernel timers
+----------------------------------------------------
+
+This patch introduces a new subsystem for high-resolution kernel timers.
+
+One might ask the question: we already have a timer subsystem
+(kernel/timers.c), why do we need two timer subsystems? After a lot of
+back and forth trying to integrate high-resolution and high-precision
+features into the existing timer framework, and after testing various
+such high-resolution timer implementations in practice, we came to the
+conclusion that the timer wheel code is fundamentally not suitable for
+such an approach. We initially didnt believe this ('there must be a way
+to solve this'), and spent a considerable effort trying to integrate
+things into the timer wheel, but we failed. In hindsight, there are
+several reasons why such integration is hard/impossible:
+
+- the forced handling of low-resolution and high-resolution timers in
+  the same way leads to a lot of compromises, macro magic and #ifdef
+  mess. The timers.c code is very "tightly coded" around jiffies and
+  32-bitness assumptions, and has been honed and micro-optimized for a
+  relatively narrow use case (jiffies in a relatively narrow HZ range)
+  for many years - and thus even small extensions to it easily break
+  the wheel concept, leading to even worse compromises. The timer wheel
+  code is very good and tight code, there's zero problems with it in its
+  current usage - but it is simply not suitable to be extended for
+  high-res timers.
+
+- the unpredictable [O(N)] overhead of cascading leads to delays which
+  necessiate a more complex handling of high resolution timers, which
+  in turn decreases robustness. Such a design still led to rather large
+  timing inaccuracies. Cascading is a fundamental property of the timer
+  wheel concept, it cannot be 'designed out' without unevitably
+  degrading other portions of the timers.c code in an unacceptable way.
+
+- the implementation of the current posix-timer subsystem on top of
+  the timer wheel has already introduced a quite complex handling of
+  the required readjusting of absolute CLOCK_REALTIME timers at
+  settimeofday or NTP time - further underlying our experience by
+  example: that the timer wheel data structure is too rigid for high-res
+  timers.
+
+- the timer wheel code is most optimal for use cases which can be
+  identified as "timeouts". Such timeouts are usually set up to cover
+  error conditions in various I/O paths, such as networking and block
+  I/O. The vast majority of those timers never expire and are rarely
+  recascaded because the expected correct event arrives in time so they
+  can be removed from the timer wheel before any further processing of
+  them becomes necessary. Thus the users of these timeouts can accept
+  the granularity and precision tradeoffs of the timer wheel, and
+  largely expect the timer subsystem to have near-zero overhead.
+  Accurate timing for them is not a core purpose - in fact most of the
+  timeout values used are ad-hoc. For them it is at most a necessary
+  evil to guarantee the processing of actual timeout completions
+  (because most of the timeouts are deleted before completion), which
+  should thus be as cheap and unintrusive as possible.
+
+The primary users of precision timers are user-space applications that
+utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
+users like drivers and subsystems which require precise timed events
+(e.g. multimedia) can benefit from the availability of a seperate
+high-resolution timer subsystem as well.
+
+While this subsystem does not offer high-resolution clock sources just
+yet, the hrtimer subsystem can be easily extended with high-resolution
+clock capabilities, and patches for that exist and are maturing quickly.
+The increasing demand for realtime and multimedia applications along
+with other potential users for precise timers gives another reason to
+separate the "timeout" and "precise timer" subsystems.
+
+Another potential benefit is that such a seperation allows even more
+special-purpose optimization of the existing timer wheel for the low
+resolution and low precision use cases - once the precision-sensitive
+APIs are separated from the timer wheel and are migrated over to
+hrtimers. E.g. we could decrease the frequency of the timeout subsystem
+from 250 Hz to 100 HZ (or even smaller).
+
+hrtimer subsystem implementation details
+----------------------------------------
+
+the basic design considerations were:
+
+- simplicity
+
+- data structure not bound to jiffies or any other granularity. All the
+  kernel logic works at 64-bit nanoseconds resolution - no compromises.
+
+- simplification of existing, timing related kernel code
+
+another basic requirement was the immediate enqueueing and ordering of
+timers at activation time. After looking at several possible solutions
+such as radix trees and hashes, we chose the red black tree as the basic
+data structure. Rbtrees are available as a library in the kernel and are
+used in various performance-critical areas of e.g. memory management and
+file systems. The rbtree is solely used for time sorted ordering, while
+a separate list is used to give the expiry code fast access to the
+queued timers, without having to walk the rbtree.
+
+(This seperate list is also useful for later when we'll introduce
+high-resolution clocks, where we need seperate pending and expired
+queues while keeping the time-order intact.)
+
+Time-ordered enqueueing is not purely for the purposes of
+high-resolution clocks though, it also simplifies the handling of
+absolute timers based on a low-resolution CLOCK_REALTIME. The existing
+implementation needed to keep an extra list of all armed absolute
+CLOCK_REALTIME timers along with complex locking. In case of
+settimeofday and NTP, all the timers (!) had to be dequeued, the
+time-changing code had to fix them up one by one, and all of them had to
+be enqueued again. The time-ordered enqueueing and the storage of the
+expiry time in absolute time units removes all this complex and poorly
+scaling code from the posix-timer implementation - the clock can simply
+be set without having to touch the rbtree. This also makes the handling
+of posix-timers simpler in general.
+
+The locking and per-CPU behavior of hrtimers was mostly taken from the
+existing timer wheel code, as it is mature and well suited. Sharing code
+was not really a win, due to the different data structures. Also, the
+hrtimer functions now have clearer behavior and clearer names - such as
+hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
+equivalent to del_timer() and del_timer_sync()] - so there's no direct
+1:1 mapping between them on the algorithmical level, and thus no real
+potential for code sharing either.
+
+Basic data types: every time value, absolute or relative, is in a
+special nanosecond-resolution type: ktime_t. The kernel-internal
+representation of ktime_t values and operations is implemented via
+macros and inline functions, and can be switched between a "hybrid
+union" type and a plain "scalar" 64bit nanoseconds representation (at
+compile time). The hybrid union type optimizes time conversions on 32bit
+CPUs. This build-time-selectable ktime_t storage format was implemented
+to avoid the performance impact of 64-bit multiplications and divisions
+on 32bit CPUs. Such operations are frequently necessary to convert
+between the storage formats provided by kernel and userspace interfaces
+and the internal time format. (See include/linux/ktime.h for further
+details.)
+
+hrtimers - rounding of timer values
+-----------------------------------
+
+the hrtimer code will round timer events to lower-resolution clocks
+because it has to. Otherwise it will do no artificial rounding at all.
+
+one question is, what resolution value should be returned to the user by
+the clock_getres() interface. This will return whatever real resolution
+a given clock has - be it low-res, high-res, or artificially-low-res.
+
+hrtimers - testing and verification
+----------------------------------
+
+We used the high-resolution clock subsystem ontop of hrtimers to verify
+the hrtimer implementation details in praxis, and we also ran the posix
+timer tests in order to ensure specification compliance. We also ran
+tests on low-resolution clocks.
+
+The hrtimer patch converts the following kernel functionality to use
+hrtimers:
+
+ - nanosleep
+ - itimers
+ - posix-timers
+
+The conversion of nanosleep and posix-timers enabled the unification of
+nanosleep and clock_nanosleep.
+
+The code was successfully compiled for the following platforms:
+
+ i386, x86_64, ARM, PPC, PPC64, IA64
+
+The code was run-tested on the following platforms:
+
+ i386(UP/SMP), x86_64(UP/SMP), ARM, PPC
+
+hrtimers were also integrated into the -rt tree, along with a
+hrtimers-based high-resolution clock implementation, so the hrtimers
+code got a healthy amount of testing and use in practice.
+
+	Thomas Gleixner, Ingo Molnar
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index d802ce8..443230b 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1033,9 +1033,9 @@
 
 	Example:
 		#arch/i386/Makefile
-		GCC_VERSION := $(call cc-version)
 		cflags-y += $(shell \
-		if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+		if [ $(call cc-version) -ge 0300 ] ; then \
+			echo "-mregparm=3"; fi ;)
 
 	In the above example -mregparm=3 is only used for gcc version greater
 	than or equal to gcc 3.0.
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 5f08f9c..212cf3c 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -4,10 +4,10 @@
 DESIGN
 ======
 
-Kdump uses kexec to reboot to a second kernel whenever a dump needs to be taken.
-This second kernel is booted with very little memory. The first kernel reserves
-the section of memory that the second kernel uses. This ensures that on-going
-DMA from the first kernel does not corrupt the second kernel.
+Kdump uses kexec to reboot to a second kernel whenever a dump needs to be
+taken. This second kernel is booted with very little memory. The first kernel
+reserves the section of memory that the second kernel uses. This ensures that
+on-going DMA from the first kernel does not corrupt the second kernel.
 
 All the necessary information about Core image is encoded in ELF format and
 stored in reserved area of memory before crash. Physical address of start of
@@ -35,77 +35,82 @@
 SETUP
 =====
 
-1) Download http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
-   and apply http://lse.sourceforge.net/kdump/patches/kexec-tools-1.101-kdump.patch
-   and after that build the source.
+1) Download the upstream kexec-tools userspace package from
+   http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz.
 
-2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernel.
+   Apply the latest consolidated kdump patch on top of kexec-tools-1.101
+   from http://lse.sourceforge.net/kdump/. This arrangment has been made
+   till all the userspace patches supporting kdump are integrated with
+   upstream kexec-tools userspace.
 
+2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernels.
    Two kernels need to be built in order to get this feature working.
+   Following are the steps to properly configure the two kernels specific
+   to kexec and kdump features:
 
-  A) First kernel:
+  A) First kernel or regular kernel:
+  ----------------------------------
    a) Enable "kexec system call" feature (in Processor type and features).
-	CONFIG_KEXEC=y
-   b) This kernel's physical load address should be the default value of
-      0x100000 (0x100000, 1 MB) (in Processor type and features).
-	CONFIG_PHYSICAL_START=0x100000
-   c) Enable "sysfs file system support" (in Pseudo filesystems).
-	CONFIG_SYSFS=y
+      CONFIG_KEXEC=y
+   b) Enable "sysfs file system support" (in Pseudo filesystems).
+      CONFIG_SYSFS=y
+   c) make
    d) Boot into first kernel with the command line parameter "crashkernel=Y@X".
       Use appropriate values for X and Y. Y denotes how much memory to reserve
-      for the second kernel, and X denotes at what physical address the reserved
-      memory section starts. For example: "crashkernel=64M@16M".
+      for the second kernel, and X denotes at what physical address the
+      reserved memory section starts. For example: "crashkernel=64M@16M".
 
-  B) Second kernel:
-   a) Enable "kernel crash dumps" feature (in Processor type and features).
-	CONFIG_CRASH_DUMP=y
-   b) Specify a suitable value for "Physical address where the kernel is
-      loaded" (in Processor type and features). Typically this value
-      should be same as X (See option d) above, e.g., 16 MB or 0x1000000.
-	CONFIG_PHYSICAL_START=0x1000000
-   c) Enable "/proc/vmcore support" (Optional, in Pseudo filesystems).
-	CONFIG_PROC_VMCORE=y
-   d) Disable SMP support and build a UP kernel (Until it is fixed).
-	CONFIG_SMP=n
-   e) Enable "Local APIC support on uniprocessors".
-	CONFIG_X86_UP_APIC=y
-   f) Enable "IO-APIC support on uniprocessors"
-	CONFIG_X86_UP_IOAPIC=y
 
-  Note:   i) Options a) and b) depend upon "Configure standard kernel features
-	     (for small systems)" (under General setup).
-	 ii) Option a) also depends on CONFIG_HIGHMEM (under Processor
-		type and features).
-	iii) Both option a) and b) are under "Processor type and features".
+  B) Second kernel or dump capture kernel:
+  ---------------------------------------
+   a) For i386 architecture enable Highmem support
+      CONFIG_HIGHMEM=y
+   b) Enable "kernel crash dumps" feature (under "Processor type and features")
+      CONFIG_CRASH_DUMP=y
+   c) Make sure a suitable value for "Physical address where the kernel is
+      loaded" (under "Processor type and features"). By default this value
+      is 0x1000000 (16MB) and it should be same as X (See option d above),
+      e.g., 16 MB or 0x1000000.
+      CONFIG_PHYSICAL_START=0x1000000
+   d) Enable "/proc/vmcore support" (Optional, under "Pseudo filesystems").
+      CONFIG_PROC_VMCORE=y
 
-3) Boot into the first kernel. You are now ready to try out kexec-based crash
-   dumps.
-
-4) Load the second kernel to be booted using:
+3) After booting to regular kernel or first kernel, load the second kernel
+   using the following command:
 
    kexec -p <second-kernel> --args-linux --elf32-core-headers
-   --append="root=<root-dev> init 1 irqpoll"
+   --append="root=<root-dev> init 1 irqpoll maxcpus=1"
 
-   Note: i) <second-kernel> has to be a vmlinux image. bzImage will not work,
-	    as of now.
-	ii) By default ELF headers are stored in ELF64 format. Option
-	    --elf32-core-headers forces generation of ELF32 headers. gdb can
-	    not open ELF64 headers on 32 bit systems. So creating ELF32
-	    headers can come handy for users who have got non-PAE systems and
-	    hence have memory less than 4GB.
-       iii) Specify "irqpoll" as command line parameter. This reduces driver
-            initialization failures in second kernel due to shared interrupts.
-        iv) <root-dev> needs to be specified in a format corresponding to
-            the root device name in the output of mount command.
-         v) If you have built the drivers required to mount root file
-            system as modules in <second-kernel>, then, specify
-            --initrd=<initrd-for-second-kernel>.
+   Notes:
+   ======
+     i) <second-kernel> has to be a vmlinux image ie uncompressed elf image.
+        bzImage will not work, as of now.
+    ii) --args-linux has to be speicfied as if kexec it loading an elf image,
+        it needs to know that the arguments supplied are of linux type.
+   iii) By default ELF headers are stored in ELF64 format to support systems
+        with more than 4GB memory. Option --elf32-core-headers forces generation
+        of ELF32 headers. The reason for this option being, as of now gdb can
+        not open vmcore file with ELF64 headers on a 32 bit systems. So ELF32
+        headers can be used if one has non-PAE systems and hence memory less
+        than 4GB.
+    iv) Specify "irqpoll" as command line parameter. This reduces driver
+         initialization failures in second kernel due to shared interrupts.
+     v) <root-dev> needs to be specified in a format corresponding to the root
+        device name in the output of mount command.
+    vi) If you have built the drivers required to mount root file system as
+        modules in <second-kernel>, then, specify
+        --initrd=<initrd-for-second-kernel>.
+   vii) Specify maxcpus=1 as, if during first kernel run, if panic happens on
+        non-boot cpus, second kernel doesn't seem to be boot up all the cpus.
+        The other option is to always built the second kernel without SMP
+        support ie CONFIG_SMP=n
 
-5) System reboots into the second kernel when a panic occurs. A module can be
-   written to force the panic or "ALT-SysRq-c" can be used initiate a crash
-   dump for testing purposes.
+4) After successfully loading the second kernel as above, if a panic occurs
+   system reboots into the second kernel. A module can be written to force
+   the panic or "ALT-SysRq-c" can be used initiate a crash dump for testing
+   purposes.
 
-6) Write out the dump file using
+5) Once the second kernel has booted, write out the dump file using
 
    cp /proc/vmcore <dump-file>
 
@@ -119,9 +124,9 @@
 
    Entire memory:  dd if=/dev/oldmem of=oldmem.001
 
+
 ANALYSIS
 ========
-
 Limited analysis can be done using gdb on the dump file copied out of
 /proc/vmcore. Use vmlinux built with -g and run
 
@@ -132,15 +137,19 @@
 
 Note: gdb cannot analyse core files generated in ELF64 format for i386.
 
+Latest "crash" (crash-4.0-2.18) as available on Dave Anderson's site
+http://people.redhat.com/~anderson/ works well with kdump format.
+
+
 TODO
 ====
-
 1) Provide a kernel pages filtering mechanism so that core file size is not
    insane on systems having huge memory banks.
-2) Modify "crash" tool to make it recognize this dump.
+2) Relocatable kernel can help in maintaining multiple kernels for crashdump
+   and same kernel as the first kernel can be used to capture the dump.
+
 
 CONTACT
 =======
-
 Vivek Goyal (vgoyal@in.ibm.com)
 Maneesh Soni (maneesh@in.ibm.com)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 0dc848b..dd0bfc2 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -475,10 +475,11 @@
 			See Documentation/block/as-iosched.txt and
 			Documentation/block/deadline-iosched.txt for details.
 
-	elfcorehdr=	[IA-32]
+	elfcorehdr=	[IA-32, X86_64]
 			Specifies physical address of start of kernel core
-			image elf header.
-			See Documentation/kdump.txt for details.
+			image elf header. Generally kexec loader will
+			pass this option to capture kernel.
+			See Documentation/kdump/kdump.txt for details.
 
 	enforcing	[SELINUX] Set initial enforcing status.
 			Format: {"0" | "1"}
@@ -832,7 +833,7 @@
 	mem=nopentium	[BUGS=IA-32] Disable usage of 4MB pages for kernel
 			memory.
 
-	memmap=exactmap	[KNL,IA-32] Enable setting of an exact
+	memmap=exactmap	[KNL,IA-32,X86_64] Enable setting of an exact
 			E820 memory map, as specified by the user.
 			Such memmap=exactmap lines can be constructed based on
 			BIOS output or other requirements. See the memmap=nn@ss
diff --git a/Documentation/locks.txt b/Documentation/locks.txt
index ce1be79..e3b402e 100644
--- a/Documentation/locks.txt
+++ b/Documentation/locks.txt
@@ -65,20 +65,3 @@
 mandatory locking only be enabled on a local filesystem as the specific need
 arises.
 
-Until an updated version of mount(8) becomes available you may have to apply
-this patch to the mount sources (based on the version distributed with Rick
-Faith's util-linux-2.5 package):
-
-*** mount.c.orig	Sat Jun  8 09:14:31 1996
---- mount.c	Sat Jun  8 09:13:02 1996
-***************
-*** 100,105 ****
---- 100,107 ----
-    { "noauto",	0, MS_NOAUTO	},	/* Can  only be mounted explicitly */
-    { "user",	0, MS_USER	},	/* Allow ordinary user to mount */
-    { "nouser",	1, MS_USER	},	/* Forbid ordinary user to mount */
-+   { "mand",	0, MS_MANDLOCK	},	/* Allow mandatory locks on this FS */
-+   { "nomand",	1, MS_MANDLOCK	},	/* Forbid mandatory locks on this FS */
-    /* add new options here */
-  #ifdef MS_NOSUB
-    { "sub",	1, MS_NOSUB	},	/* allow submounts */
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index 2c81305..e409e5d 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -1,58 +1,56 @@
 Everything you ever wanted to know about Linux 2.6 -stable releases.
 
-Rules on what kind of patches are accepted, and what ones are not, into
-the "-stable" tree:
+Rules on what kind of patches are accepted, and which ones are not, into the
+"-stable" tree:
 
  - It must be obviously correct and tested.
- - It can not bigger than 100 lines, with context.
+ - It can not be bigger than 100 lines, with context.
  - It must fix only one thing.
  - It must fix a real bug that bothers people (not a, "This could be a
-   problem..." type thing.)
+   problem..." type thing).
  - It must fix a problem that causes a build error (but not for things
    marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
-   security issue, or some "oh, that's not good" issue.  In short,
-   something critical.
- - No "theoretical race condition" issues, unless an explanation of how
-   the race can be exploited.
+   security issue, or some "oh, that's not good" issue.  In short, something
+   critical.
+ - No "theoretical race condition" issues, unless an explanation of how the
+   race can be exploited is also provided.
  - It can not contain any "trivial" fixes in it (spelling changes,
-   whitespace cleanups, etc.)
+   whitespace cleanups, etc).
  - It must be accepted by the relevant subsystem maintainer.
- - It must follow Documentation/SubmittingPatches rules.
+ - It must follow the Documentation/SubmittingPatches rules.
 
 
 Procedure for submitting patches to the -stable tree:
 
  - Send the patch, after verifying that it follows the above rules, to
    stable@kernel.org.
- - The sender will receive an ack when the patch has been accepted into
-   the queue, or a nak if the patch is rejected.  This response might
-   take a few days, according to the developer's schedules.
- - If accepted, the patch will be added to the -stable queue, for review
-   by other developers.
+ - The sender will receive an ACK when the patch has been accepted into the
+   queue, or a NAK if the patch is rejected.  This response might take a few
+   days, according to the developer's schedules.
+ - If accepted, the patch will be added to the -stable queue, for review by
+   other developers.
  - Security patches should not be sent to this alias, but instead to the
-   documented security@kernel.org.
+   documented security@kernel.org address.
 
 
 Review cycle:
 
- - When the -stable maintainers decide for a review cycle, the patches
-   will be sent to the review committee, and the maintainer of the
-   affected area of the patch (unless the submitter is the maintainer of
-   the area) and CC: to the linux-kernel mailing list.
- - The review committee has 48 hours in which to ack or nak the patch.
+ - When the -stable maintainers decide for a review cycle, the patches will be
+   sent to the review committee, and the maintainer of the affected area of
+   the patch (unless the submitter is the maintainer of the area) and CC: to
+   the linux-kernel mailing list.
+ - The review committee has 48 hours in which to ACK or NAK the patch.
  - If the patch is rejected by a member of the committee, or linux-kernel
-   members object to the patch, bringing up issues that the maintainers
-   and members did not realize, the patch will be dropped from the
-   queue.
- - At the end of the review cycle, the acked patches will be added to
-   the latest -stable release, and a new -stable release will happen.
- - Security patches will be accepted into the -stable tree directly from
-   the security kernel team, and not go through the normal review cycle.
+   members object to the patch, bringing up issues that the maintainers and
+   members did not realize, the patch will be dropped from the queue.
+ - At the end of the review cycle, the ACKed patches will be added to the
+   latest -stable release, and a new -stable release will happen.
+ - Security patches will be accepted into the -stable tree directly from the
+   security kernel team, and not go through the normal review cycle.
    Contact the kernel security team for more details on this procedure.
 
 
 Review committe:
 
- - This will be made up of a number of kernel developers who have
-   volunteered for this task, and a few that haven't.
-
+ - This is made up of a number of kernel developers who have volunteered for
+   this task, and a few that haven't.
diff --git a/Kbuild b/Kbuild
index 7900391..95d6a00 100644
--- a/Kbuild
+++ b/Kbuild
@@ -22,8 +22,6 @@
 
 quiet_cmd_offsets = GEN     $@
 define cmd_offsets
-	mkdir -p $(dir $@); \
-	cat $< | \
 	(set -e; \
 	 echo "#ifndef __ASM_OFFSETS_H__"; \
 	 echo "#define __ASM_OFFSETS_H__"; \
@@ -34,7 +32,7 @@
 	 echo " *"; \
 	 echo " */"; \
 	 echo ""; \
-	 sed -ne $(sed-y); \
+	 sed -ne $(sed-y) $<; \
 	 echo ""; \
 	 echo "#endif" ) > $@
 endef
@@ -45,5 +43,6 @@
 	$(call if_changed_dep,cc_s_c)
 
 $(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild
+	$(Q)mkdir -p $(dir $@)
 	$(call cmd,offsets)
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 0742016..090e10b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -804,6 +804,7 @@
 DOCBOOK FOR DOCUMENTATION
 P:	Martin Waitz
 M:	tali@admingilde.org
+T:	git http://tali.admingilde.org/git/linux-docbook.git
 S:	Maintained
 
 DOUBLETALK DRIVER
diff --git a/Makefile b/Makefile
index fb497ea..deedaf7 100644
--- a/Makefile
+++ b/Makefile
@@ -141,24 +141,6 @@
 
 export srctree objtree VPATH TOPDIR
 
-nullstring :=
-space      := $(nullstring) # end of line
-
-# Take the contents of any files called localversion* and the config
-# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be
-# careful not to include files twice if building in the source
-# directory. LOCALVERSION from the command line override all of this
-
-localver := $(objtree)/localversion* $(srctree)/localversion*
-localver := $(sort $(wildcard $(localver)))
-# skip backup files (containing '~')
-localver := $(foreach f, $(localver), $(if $(findstring ~, $(f)),,$(f)))
-
-LOCALVERSION = $(subst $(space),, \
-	       $(shell cat /dev/null $(localver)) \
-	       $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-
-KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
 
 # SUBARCH tells the usermode build what the underlying arch is.  That is set
 # first, and if a usermode build is happening, the "ARCH=um" on the command
@@ -353,7 +335,10 @@
 		   -ffreestanding
 AFLAGS		:= -D__ASSEMBLY__
 
-export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \
+# Read KERNELRELEASE from .kernelrelease (if it exists)
+KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
+
+export	VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE \
 	ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
 	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
 	HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
@@ -551,26 +536,6 @@
 # images. Default is /boot, but you can set it to other values
 export	INSTALL_PATH ?= /boot
 
-# If CONFIG_LOCALVERSION_AUTO is set, we automatically perform some tests
-# and try to determine if the current source tree is a release tree, of any sort,
-# or if is a pure development tree.
-#
-# A 'release tree' is any tree with a git TAG associated
-# with it.  The primary goal of this is to make it safe for a native
-# git/CVS/SVN user to build a release tree (i.e, 2.6.9) and also to
-# continue developing against the current Linus tree, without having the Linus
-# tree overwrite the 2.6.9 tree when installed.
-#
-# Currently, only git is supported.
-# Other SCMs can edit scripts/setlocalversion and add the appropriate
-# checks as needed.
-
-
-ifdef CONFIG_LOCALVERSION_AUTO
-	localversion-auto := $(shell $(PERL) $(srctree)/scripts/setlocalversion $(srctree))
-	LOCALVERSION := $(LOCALVERSION)$(localversion-auto)
-endif
-
 #
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
 # relocations required by build roots.  This is not defined in the
@@ -782,6 +747,50 @@
 $(vmlinux-dirs): prepare scripts
 	$(Q)$(MAKE) $(build)=$@
 
+# Build the kernel release string
+# The KERNELRELEASE is stored in a file named .kernelrelease
+# to be used when executing for example make install or make modules_install
+#
+# Take the contents of any files called localversion* and the config
+# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE.
+# LOCALVERSION from the command line override all of this
+
+nullstring :=
+space      := $(nullstring) # end of line
+
+___localver = $(objtree)/localversion* $(srctree)/localversion*
+__localver  = $(sort $(wildcard $(___localver)))
+# skip backup files (containing '~')
+_localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f)))
+
+localver = $(subst $(space),, \
+	   $(shell cat /dev/null $(_localver)) \
+	   $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
+	       
+# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
+# and if the SCM is know a tag from the SCM is appended.
+# The appended tag is determinded by the SCM used.
+#
+# Currently, only git is supported.
+# Other SCMs can edit scripts/setlocalversion and add the appropriate
+# checks as needed.
+ifdef CONFIG_LOCALVERSION_AUTO
+	_localver-auto = $(shell $(CONFIG_SHELL) \
+	                  $(srctree)/scripts/setlocalversion $(srctree))
+	localver-auto  = $(LOCALVERSION)$(_localver-auto)
+endif
+
+localver-full = $(localver)$(localver-auto)
+
+# Store (new) KERNELRELASE string in .kernelrelease
+kernelrelease = \
+       $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(localver-full)
+.kernelrelease: FORCE
+	$(Q)rm -f .kernelrelease
+	$(Q)echo $(kernelrelease) > .kernelrelease
+	$(Q)echo "  Building kernel $(kernelrelease)"
+
+
 # Things we need to do before we recursively start building the kernel
 # or the modules are listed in "prepare".
 # A multi level approach is used. prepareN is processed before prepareN-1.
@@ -798,8 +807,7 @@
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
 # 2) Create the include2 directory, used for the second asm symlink
-
-prepare3:
+prepare3: .kernelrelease
 ifneq ($(KBUILD_SRC),)
 	@echo '  Using $(srctree) as source for kernel'
 	$(Q)if [ -f $(srctree)/.config ]; then \
@@ -984,9 +992,9 @@
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_DIRS  += include/config include2
-MRPROPER_FILES += .config .config.old include/asm .version \
+MRPROPER_FILES += .config .config.old include/asm .version .old_version \
                   include/linux/autoconf.h include/linux/version.h \
-                  Module.symvers tags TAGS cscope*
+		  .kernelrelease Module.symvers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1072,6 +1080,7 @@
 	@echo  '  tags/TAGS	  - Generate tags file for editors'
 	@echo  '  cscope	  - Generate cscope index'
 	@echo  '  kernelrelease	  - Output the release version string'
+	@echo  '  kernelversion	  - Output the version stored in Makefile'
 	@echo  ''
 	@echo  'Static analysers'
 	@echo  '  buildcheck      - List dangling references to vmlinux discarded sections'
@@ -1293,6 +1302,8 @@
 
 kernelrelease:
 	@echo $(KERNELRELEASE)
+kernelversion:
+	@echo $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
 # FIXME Should go into a make.lib or something 
 # ===========================================================================
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index f3e98f8..1898ea7 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -40,7 +40,6 @@
 #include <asm/unistd.h>
 
 extern struct hwrpb_struct *hwrpb;
-extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
 
 /* these are C runtime functions with special calling conventions: */
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 90752f6..486d794 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -7,6 +7,7 @@
 /* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */
 
 #include <linux/config.h>
+#include <linux/pagemap.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index f5cc21a..a4e5ac7 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -64,7 +64,7 @@
 static spinlock_t dma_chan_lock;
 static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT];
 
-const static u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
+static const u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
 	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
 	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
 	INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10,
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index 35514b3..811a6376c 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -35,7 +35,6 @@
 #include <asm/checksum.h>
 #include <asm/mach-types.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
 extern void inswb(unsigned int port, void *to, int len);
 extern void outswb(unsigned int port, const void *to, int len);
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 85833d7..de39725 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -21,7 +21,6 @@
 #include <asm/pgtable.h>
 #include <asm/fasttimer.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern unsigned long get_cmos_time(void);
 extern void __Udiv(void);
 extern void __Umod(void);
@@ -33,7 +32,6 @@
 extern void iounmap(volatile void * __iomem);
 
 /* Platform dependent support */
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(get_cmos_time);
 EXPORT_SYMBOL(loops_per_usec);
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 7c80afb..4ab3e87 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -257,34 +257,6 @@
 {
 }
 
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-#if 0
-	int i;
-
-	/* changed the size calculations - should hopefully work better. lbt */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-	for (i = 0; i < 8; i++)
-		dump->u_debugreg[i] = current->debugreg[i];  
-
-	if (dump->start_stack < TASK_SIZE)
-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
-	dump->regs = *regs;
-
-	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
-#endif 
-}
-
 /* Fill in the fpu structure for a core dump. */
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 {
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 61261b7..60a617a 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -6,10 +6,6 @@
 	bool
 	default y
 
-config UID16
-	bool
-	default y
-
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile
index d75e0d7..5dfc93f 100644
--- a/arch/frv/boot/Makefile
+++ b/arch/frv/boot/Makefile
@@ -57,10 +57,10 @@
 # installation
 #
 install: $(CONFIGURE) Image
-	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
+	sh ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
 zinstall: $(CONFIGURE) zImage
-	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
+	sh ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
 #
 # miscellany
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 5f118c8..0f1c6cb 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -18,7 +18,6 @@
 #include <asm/hardirq.h>
 #include <asm/cacheflush.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern long __memcpy_user(void *dst, const void *src, size_t count);
 extern long __memset_user(void *dst, const void *src, size_t count);
 
@@ -27,7 +26,6 @@
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 54a4521..c448837 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -244,28 +244,6 @@
 } /* end copy_thread() */
 
 /*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs *regs, struct user *dump)
-{
-#if 0
-	/* changed the size calculations - should hopefully work better. lbt */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = user_stack(regs) & ~(PAGE_SIZE - 1);
-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-
-	if (dump->start_stack < TASK_SIZE)
-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
-	dump->regs = *(struct user_context *) regs;
-#endif
-}
-
-/*
  * sys_execve() executes a new program.
  */
 asmlinkage int sys_execve(char *name, char **argv, char **envp)
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
index 795682b..d195568 100644
--- a/arch/h8300/kernel/gpio.c
+++ b/arch/h8300/kernel/gpio.c
@@ -122,7 +122,7 @@
 static char *port_status(int portno)
 {
 	static char result[10];
-	const static char io[2]={'I','O'};
+	static const char io[2]={'I','O'};
 	char *rp;
 	int c;
 	unsigned char used,ddr;
@@ -143,7 +143,7 @@
                           int len, int *unused_i, void *unused_v)
 {
 	int c,outlen;
-	const static char port_name[]="123456789ABCDEFGH";
+	static const char port_name[]="123456789ABCDEFGH";
 	outlen = 0;
 	for (c = 0; c < MAX_PORT; c++) {
 		if (ddrs[c] == NULL)
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 5a63023..3e0d80e 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -22,11 +22,8 @@
 //asmlinkage long long __lshrdi3 (long long, int);
 extern char h8300_debug_device[];
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 /* platform dependent support */
 
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index fe21adf..585ed5e 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -208,34 +208,6 @@
 }
 
 /*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-/* changed the size calculations - should hopefully work better. lbt */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
-	dump->u_dsize = ((unsigned long) (current->mm->brk +
-					  (PAGE_SIZE-1))) >> PAGE_SHIFT;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-
-	dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump)));
-	dump->regs.er0 = regs->er0;
-	dump->regs.er1 = regs->er1;
-	dump->regs.er2 = regs->er2;
-	dump->regs.er3 = regs->er3;
-	dump->regs.er4 = regs->er4;
-	dump->regs.er5 = regs->er5;
-	dump->regs.er6 = regs->er6;
-	dump->regs.orig_er0 = regs->orig_er0;
-	dump->regs.ccr = regs->ccr;
-	dump->regs.pc  = regs->pc;
-}
-
-/*
  * sys_execve() executes a new program.
  */
 asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...)
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
index 6ac93c0..746b1ae 100644
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c
@@ -98,7 +98,7 @@
 		.type       = jmp, \
 	}
 
-const static struct optable optable_0[] = {
+static const struct optable optable_0[] = {
 	OPTABLE(0x00,0xff, 1,none), /* 0x00 */
 	OPTABLE(0x01,0xff,-1,none), /* 0x01 */
 	OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
@@ -131,31 +131,31 @@
 	OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
 };
 
-const static struct optable optable_1[] = {
+static const struct optable optable_1[] = {
 	OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
 	OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
 	OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
 	OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
 };
 
-const static struct optable optable_2[] = {
+static const struct optable optable_2[] = {
 	OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
 	OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
 };
 
-const static struct optable optable_3[] = {
+static const struct optable optable_3[] = {
 	OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
 	OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
 	OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
 	OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
 };
 
-const static struct optable optable_4[] = {
+static const struct optable optable_4[] = {
 	OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
 	OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
 };
 
-const static struct optables_list {
+static const struct optables_list {
 	const struct optable *ptr;
 	int size;
 } optables[] = {
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index 5441cdd..f6ed663 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -52,7 +52,7 @@
 	unsigned char bit_no;
 };
 /* ISTR = 0 */
-const static struct irq_pins irq_assign_table0[16]={
+static const struct irq_pins irq_assign_table0[16]={
         {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1},
 	{H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3},
 	{H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5},
@@ -63,7 +63,7 @@
 	{H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},
 };
 /* ISTR = 1 */
-const static struct irq_pins irq_assign_table1[16]={
+static const struct irq_pins irq_assign_table1[16]={
 	{H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1},
 	{H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3},
 	{H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5},
diff --git a/arch/h8300/platform/h8s/ints_h8s.c b/arch/h8300/platform/h8s/ints_h8s.c
index f53de49..8268dfd 100644
--- a/arch/h8300/platform/h8s/ints_h8s.c
+++ b/arch/h8300/platform/h8s/ints_h8s.c
@@ -42,7 +42,7 @@
 	unsigned char bit_no;
 } __attribute__((aligned(1),packed));
 /* ISTR = 0 */
-const static struct irq_pins irq_assign_table0[16]={
+static const struct irq_pins irq_assign_table0[16]={
         {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1},
 	{H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3},
 	{H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5},
@@ -53,7 +53,7 @@
 	{H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},
 }; 
 /* ISTR = 1 */
-const static struct irq_pins irq_assign_table1[16]={
+static const struct irq_pins irq_assign_table1[16]={
 	{H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1},
 	{H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3},
 	{H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5},
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index d849c68..815878e 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -645,17 +645,6 @@
 
 source kernel/Kconfig.hz
 
-config PHYSICAL_START
-	hex "Physical address where the kernel is loaded" if EMBEDDED
-	default "0x100000"
-	help
-	  This gives the physical address where the kernel is loaded.
-	  Primarily used in the case of kexec on panic where the
-	  fail safe kernel needs to run at a different address than
-	  the panic-ed kernel.
-
-	  Don't change this unless you know what you are doing.
-
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -675,11 +664,31 @@
 
 config CRASH_DUMP
 	bool "kernel crash dumps (EXPERIMENTAL)"
-	depends on EMBEDDED
 	depends on EXPERIMENTAL
 	depends on HIGHMEM
 	help
 	  Generate crash dump after being started by kexec.
+
+config PHYSICAL_START
+	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+
+	default "0x1000000" if CRASH_DUMP
+	default "0x100000"
+	help
+	  This gives the physical address where the kernel is loaded. Normally
+	  for regular kernels this value is 0x100000 (1MB). But in the case
+	  of kexec on panic the fail safe kernel needs to run at a different
+	  address than the panic-ed kernel. This option is used to set the load
+	  address for kernels used to capture crash dump on being kexec'ed
+	  after panic. The default value for crash dump kernels is
+	  0x1000000 (16MB). This can also be set based on the "X" value as
+	  specified in the "crashkernel=YM@XM" command line boot parameter
+	  passed to the panic-ed kernel. Typically this parameter is set as
+	  crashkernel=64M@16M. Please take a look at
+	  Documentation/kdump/kdump.txt for more details about crash dumps.
+
+	  Don't change this unless you know what you are doing.
+
 endmenu
 
 
@@ -1051,3 +1060,7 @@
 	bool
 	depends on X86_SMP || (X86_VOYAGER && SMP)
 	default y
+
+config KTIME_SCALAR
+	bool
+	default y
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index b84119f..d3c0409 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -37,7 +37,10 @@
 # CPU-specific tuning. Anything which can be shared with UML should go here.
 include $(srctree)/arch/i386/Makefile.cpu
 
-cflags-$(CONFIG_REGPARM) 	+= -mregparm=3
+# -mregparm=3 works ok on gcc-3.0 and later
+#
+cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \
+                            echo "-mregparm=3"; fi ;)
 
 # Disable unit-at-a-time mode, it makes gcc use a lot more stack
 # due to the lack of sharing of stacklots.
@@ -100,7 +103,7 @@
 boot := arch/i386/boot
 
 .PHONY: zImage bzImage compressed zlilo bzlilo \
-	zdisk bzdisk fdimage fdimage144 fdimage288 install kernel_install
+	zdisk bzdisk fdimage fdimage144 fdimage288 install
 
 all: bzImage
 
@@ -122,8 +125,7 @@
 fdimage fdimage144 fdimage288: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
 
-install: vmlinux
-install kernel_install:
+install:
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
 
 archclean:
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index 1e71382..0fea75d 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -100,5 +100,5 @@
 	cp System.map $(INSTALL_PATH)/
 	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
 
-install: $(BOOTIMAGE)
+install:
 	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
diff --git a/arch/i386/boot/install.sh b/arch/i386/boot/install.sh
index f17b40d..5e44c73 100644
--- a/arch/i386/boot/install.sh
+++ b/arch/i386/boot/install.sh
@@ -19,6 +19,20 @@
 #   $4 - default install path (blank if root directory)
 #
 
+verify () {
+	if [ ! -f "$1" ]; then
+		echo ""                                                   1>&2
+		echo " *** Missing file: $1"                              1>&2
+		echo ' *** You need to run "make" before "make install".' 1>&2
+		echo ""                                                   1>&2
+		exit 1
+ 	fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
 # User may have a custom install script
 
 if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 92f6694..2ac40c8 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -97,7 +97,6 @@
 #define PARAM_VESAPM_OFF	0x30
 #define PARAM_LFB_PAGES		0x32
 #define PARAM_VESA_ATTRIB	0x34
-#define PARAM_CAPABILITIES      0x36
 
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
@@ -234,10 +233,6 @@
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
 
-# store mode capabilities
-	movl    10(%di), %eax
-	movl    %eax, %fs:(PARAM_CAPABILITIES)
-
 # switching the DAC to 8-bit is for <= 8 bpp only
 	movw	%fs:(PARAM_LFB_DEPTH), %ax
 	cmpw	$8, %ax
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index be1880b..60c3f76 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -25,6 +25,7 @@
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index 0248e08..d49dbe8 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -25,7 +25,6 @@
 #include <mach_ipi.h>
 
 
-note_buf_t crash_notes[NR_CPUS];
 /* This keeps a track of which one is crashing cpu. */
 static int crashing_cpu;
 
@@ -72,7 +71,9 @@
 	 * squirrelled away.  ELF notes happen to provide
 	 * all of that that no need to invent something new.
 	 */
-	buf = &crash_notes[cpu][0];
+	buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+	if (!buf)
+		return;
 	memset(&prstatus, 0, sizeof(prstatus));
 	prstatus.pr_pid = current->pid;
 	elf_core_copy_regs(&prstatus.pr_reg, regs);
@@ -81,51 +82,12 @@
 	final_note(buf);
 }
 
-static void crash_get_current_regs(struct pt_regs *regs)
+static void crash_save_self(struct pt_regs *regs)
 {
-	__asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
-	__asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
-	__asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
-	__asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
-	__asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
-	__asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
-	__asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
-	__asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
-	__asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
-	__asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
-	__asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
-	__asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
-	__asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
-
-	regs->eip = (unsigned long)current_text_addr();
-}
-
-/* CPU does not save ss and esp on stack if execution is already
- * running in kernel mode at the time of NMI occurrence. This code
- * fixes it.
- */
-static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
-{
-	memcpy(newregs, oldregs, sizeof(*newregs));
-	newregs->esp = (unsigned long)&(oldregs->esp);
-	__asm__ __volatile__("xorl %eax, %eax;");
-	__asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss));
-}
-
-/* We may have saved_regs from where the error came from
- * or it is NULL if via a direct panic().
- */
-static void crash_save_self(struct pt_regs *saved_regs)
-{
-	struct pt_regs regs;
 	int cpu;
 
 	cpu = smp_processor_id();
-	if (saved_regs)
-		crash_setup_regs(&regs, saved_regs);
-	else
-		crash_get_current_regs(&regs);
-	crash_save_this_cpu(&regs, cpu);
+	crash_save_this_cpu(regs, cpu);
 }
 
 #ifdef CONFIG_SMP
@@ -144,7 +106,7 @@
 	local_irq_disable();
 
 	if (!user_mode(regs)) {
-		crash_setup_regs(&fixed_regs, regs);
+		crash_fixup_ss_esp(&fixed_regs, regs);
 		regs = &fixed_regs;
 	}
 	crash_save_this_cpu(regs, cpu);
diff --git a/arch/i386/kernel/crash_dump.c b/arch/i386/kernel/crash_dump.c
new file mode 100644
index 0000000..3f532df
--- /dev/null
+++ b/arch/i386/kernel/crash_dump.c
@@ -0,0 +1,74 @@
+/*
+ *	kernel/crash_dump.c - Memory preserving reboot related code.
+ *
+ *	Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *	Copyright (C) IBM Corporation, 2004. All rights reserved
+ */
+
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
+
+#include <asm/uaccess.h>
+
+static void *kdump_buf_page;
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ *	space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ *	otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+                               size_t csize, unsigned long offset, int userbuf)
+{
+	void  *vaddr;
+
+	if (!csize)
+		return 0;
+
+	vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+
+	if (!userbuf) {
+		memcpy(buf, (vaddr + offset), csize);
+		kunmap_atomic(vaddr, KM_PTE0);
+	} else {
+		if (!kdump_buf_page) {
+			printk(KERN_WARNING "Kdump: Kdump buffer page not"
+				" allocated\n");
+			return -EFAULT;
+		}
+		copy_page(kdump_buf_page, vaddr);
+		kunmap_atomic(vaddr, KM_PTE0);
+		if (copy_to_user(buf, (kdump_buf_page + offset), csize))
+			return -EFAULT;
+	}
+
+	return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+	int ret = 0;
+
+	kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!kdump_buf_page) {
+		printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer"
+			 " page\n");
+		ret = -ENOMEM;
+	}
+
+	return ret;
+}
+arch_initcall(kdump_buf_page_init);
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 19edcd5..2f372db 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -58,13 +58,9 @@
 
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
-	return 0;
-}
-
-void __kprobes arch_copy_kprobe(struct kprobe *p)
-{
 	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 	p->opcode = *p->addr;
+	return 0;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -81,10 +77,6 @@
 			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-}
-
 static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 27c956d..f685637 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -898,7 +898,7 @@
 			}
 		}
 #endif
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_PROC_VMCORE
 		/* elfcorehdr= specifies the location of elf core header
 		 * stored by the crashed kernel.
 		 */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 53ad954..b9f0030 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -120,7 +120,7 @@
 #ifdef	CONFIG_FRAME_POINTER
 	while (valid_stack_ptr(tinfo, (void *)ebp)) {
 		addr = *(unsigned long *)(ebp + 4);
-		printk(" [<%08lx>] ", addr);
+		printk(KERN_EMERG " [<%08lx>] ", addr);
 		print_symbol("%s", addr);
 		printk("\n");
 		ebp = *(unsigned long *)ebp;
@@ -129,7 +129,7 @@
 	while (valid_stack_ptr(tinfo, stack)) {
 		addr = *stack++;
 		if (__kernel_text_address(addr)) {
-			printk(" [<%08lx>]", addr);
+			printk(KERN_EMERG " [<%08lx>]", addr);
 			print_symbol(" %s", addr);
 			printk("\n");
 		}
@@ -161,7 +161,7 @@
 		stack = (unsigned long*)context->previous_esp;
 		if (!stack)
 			break;
-		printk(" =======================\n");
+		printk(KERN_EMERG " =======================\n");
 	}
 }
 
@@ -178,14 +178,15 @@
 	}
 
 	stack = esp;
+	printk(KERN_EMERG);
 	for(i = 0; i < kstack_depth_to_print; i++) {
 		if (kstack_end(stack))
 			break;
 		if (i && ((i % 8) == 0))
-			printk("\n       ");
+			printk("\n" KERN_EMERG "       ");
 		printk("%08lx ", *stack++);
 	}
-	printk("\nCall Trace:\n");
+	printk("\n" KERN_EMERG "Call Trace:\n");
 	show_trace(task, esp);
 }
 
@@ -216,18 +217,18 @@
 		ss = regs->xss & 0xffff;
 	}
 	print_modules();
-	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\nEFLAGS: %08lx"
-			"   (%s) \n",
+	printk(KERN_EMERG "CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\n"
+			"EFLAGS: %08lx   (%s) \n",
 		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
 		print_tainted(), regs->eflags, system_utsname.release);
-	print_symbol("EIP is at %s\n", regs->eip);
-	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
+	print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
+	printk(KERN_EMERG "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
-	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
+	printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
 		regs->esi, regs->edi, regs->ebp, esp);
-	printk("ds: %04x   es: %04x   ss: %04x\n",
+	printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
 		regs->xds & 0xffff, regs->xes & 0xffff, ss);
-	printk("Process %s (pid: %d, threadinfo=%p task=%p)",
+	printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)",
 		current->comm, current->pid, current_thread_info(), current);
 	/*
 	 * When in-kernel, we also print out the stack and code at the
@@ -236,10 +237,10 @@
 	if (in_kernel) {
 		u8 __user *eip;
 
-		printk("\nStack: ");
+		printk("\n" KERN_EMERG "Stack: ");
 		show_stack(NULL, (unsigned long*)esp);
 
-		printk("Code: ");
+		printk(KERN_EMERG "Code: ");
 
 		eip = (u8 __user *)regs->eip - 43;
 		for (i = 0; i < 64; i++, eip++) {
@@ -280,15 +281,15 @@
 		(unsigned long)file < PAGE_OFFSET || __get_user(c, file))
 		file = "<bad filename>";
 
-	printk("------------[ cut here ]------------\n");
-	printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
+	printk(KERN_EMERG "------------[ cut here ]------------\n");
+	printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
 
 no_bug:
 	return;
 
 	/* Here we know it was a BUG but file-n-line is unavailable */
 bug:
-	printk("Kernel BUG\n");
+	printk(KERN_EMERG "Kernel BUG\n");
 }
 
 /* This is gone through when something in the kernel
@@ -321,16 +322,20 @@
 	if (++die.lock_owner_depth < 3) {
 		int nl = 0;
 		handle_BUG(regs);
-		printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
-		printk("PREEMPT ");
+		printk(KERN_EMERG "PREEMPT ");
 		nl = 1;
 #endif
 #ifdef CONFIG_SMP
+		if (!nl)
+			printk(KERN_EMERG);
 		printk("SMP ");
 		nl = 1;
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
+		if (!nl)
+			printk(KERN_EMERG);
 		printk("DEBUG_PAGEALLOC");
 		nl = 1;
 #endif
@@ -339,7 +344,7 @@
 	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
 		show_registers(regs);
   	} else
-		printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+		printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
 
 	bust_spinlocks(0);
 	die.lock_owner = -1;
@@ -527,8 +532,10 @@
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
-	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
-	printk("You probably have a hardware problem with your RAM chips\n");
+	printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying "
+			"to continue\n");
+	printk(KERN_EMERG "You probably have a hardware problem with your RAM "
+			"chips\n");
 
 	/* Clear and disable the memory parity error line. */
 	clear_mem_error(reason);
@@ -538,7 +545,7 @@
 {
 	unsigned long i;
 
-	printk("NMI: IOCK error (debug interrupt?)\n");
+	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
 	show_registers(regs);
 
 	/* Re-enable the IOCK line, wait for a few seconds */
@@ -580,11 +587,11 @@
 	* to get a message out.
 	*/
 	bust_spinlocks(1);
-	printk(msg);
+	printk(KERN_EMERG "%s", msg);
 	printk(" on CPU%d, eip %08lx, registers:\n",
 		smp_processor_id(), regs->eip);
 	show_registers(regs);
-	printk("console shuts up ...\n");
+	printk(KERN_EMERG "console shuts up ...\n");
 	console_silent();
 	spin_unlock(&nmi_print_lock);
 	bust_spinlocks(0);
@@ -990,8 +997,8 @@
 
 asmlinkage void math_emulate(long arg)
 {
-	printk("math-emulation not enabled and no coprocessor found.\n");
-	printk("killing %s.\n",current->comm);
+	printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n");
+	printk(KERN_EMERG "killing %s.\n",current->comm);
 	force_sig(SIGFPE,current);
 	schedule();
 }
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 57b047c..f722e1a 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -25,7 +25,6 @@
 		   -falign-functions=32 -frename-registers -fno-optimize-sibling-calls
 CFLAGS_KERNEL	:= -mconstant-gp
 
-GCC_VERSION     := $(call cc-version)
 GAS_STATUS	= $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
 CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
 
@@ -37,7 +36,7 @@
 		ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
 endif
 
-ifeq ($(GCC_VERSION),0304)
+ifeq ($(call cc-version),0304)
 	cflags-$(CONFIG_ITANIUM)	+= -mtune=merced
 	cflags-$(CONFIG_MCKINLEY)	+= -mtune=mckinley
 endif
diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile
index 2ed90da..61cb60a 100644
--- a/arch/ia64/ia32/Makefile
+++ b/arch/ia64/ia32/Makefile
@@ -2,11 +2,9 @@
 # Makefile for the ia32 kernel emulation subsystem.
 #
 
-obj-y := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o \
+obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \
 	 ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o
 
-CFLAGS_ia32_ioctl.o += -Ifs/
-
 # Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and
 # restore_ia32_fpstate_live() can be sure the live register contain user-level state.
 CFLAGS_ia32_signal.o += -mfixed-range=f16-f31
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 494fad6..95fe044 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -469,7 +469,7 @@
 	data8 sys32_epoll_wait
 	data8 sys_remap_file_pages
 	data8 sys_set_tid_address
- 	data8 sys32_timer_create
+ 	data8 compat_sys_timer_create
  	data8 compat_sys_timer_settime	/* 260 */
  	data8 compat_sys_timer_gettime
  	data8 sys_timer_getoverrun
diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
deleted file mode 100644
index 8873939..0000000
--- a/arch/ia64/ia32/ia32_ioctl.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * IA32 Architecture-specific ioctl shim code
- *
- * Copyright (C) 2000 VA Linux Co
- * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
- * Copyright (C) 2001-2003 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/signal.h>	/* argh, msdos_fs.h isn't self-contained... */
-#include <linux/syscalls.h>
-#include "ia32priv.h"
-  
-#define	INCLUDES
-#include "compat_ioctl.c"
-
-#define IOCTL_NR(a)	((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
-
-#define DO_IOCTL(fd, cmd, arg) ({			\
-	int _ret;					\
-	mm_segment_t _old_fs = get_fs();		\
-							\
-	set_fs(KERNEL_DS);				\
-	_ret = sys_ioctl(fd, cmd, (unsigned long)arg);	\
-	set_fs(_old_fs);				\
-	_ret;						\
-})
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define COMPATIBLE_IOCTL(cmd)		HANDLE_IOCTL((cmd),sys_ioctl)
-#define HANDLE_IOCTL(cmd,handler)	{ (cmd), (ioctl_trans_handler_t)(handler), NULL },
-#define IOCTL_TABLE_START \
-	struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
-	};
-
-IOCTL_TABLE_START
-#define DECLARES
-#include "compat_ioctl.c"
-#include <linux/compat_ioctl.h>
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 9f8e8d5..5ea3828 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2553,34 +2553,6 @@
 	return 0;
 }
 
-asmlinkage long
-sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
-{
-	struct sigevent se;
-	mm_segment_t oldfs;
-	timer_t t;
-	long err;
-
-	if (se32 == NULL)
-		return sys_timer_create(clock, NULL, timer_id);
-
-	if (get_compat_sigevent(&se, se32))
-		return -EFAULT;
-
-	if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
-		return -EFAULT;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t);
-	set_fs(oldfs);
-
-	if (!err)
-		err = __put_user (t, timer_id);
-
-	return err;
-}
-
 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
 			__u32 len_low, __u32 len_high, int advice)
 { 
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 89a7040..4de7f67 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -467,10 +467,6 @@
 	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
 }
 
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-}
-
 /*
  * We are resuming execution after a single step fault, so the pt_regs
  * structure reflects the register state after we executed the instruction
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index fae67bb..a3dcc3f 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -12,10 +12,6 @@
 config SBUS
 	bool
 
-config UID16
-	bool
-	default n
-
 config GENERIC_ISA_DMA
 	bool
 	default y
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index e5ec134..dbc8a39 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -18,8 +18,6 @@
 #include <asm/irq.h>
 #include <asm/tlbflush.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
 extern struct drive_info_struct drive_info;
 EXPORT_SYMBOL(drive_info);
@@ -27,7 +25,6 @@
 
 /* platform dependent support */
 EXPORT_SYMBOL(boot_cpu_data);
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 3bf55d9..2a1f250 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -261,14 +261,6 @@
 }
 
 /*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-	/* M32R_FIXME */
-}
-
-/*
  * Capture the user space registers if the task is not running (in user space)
  */
 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 73e2f5e..3d7f200 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -23,8 +23,6 @@
 asmlinkage long long __muldi3 (long long, long long);
 extern char m68k_debug_device[];
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 /* platform dependent support */
 
 EXPORT_SYMBOL(m68k_machtype);
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index b2c62ee..eddb8d3e 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -18,7 +18,6 @@
 #include <asm/checksum.h>
 #include <asm/current.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 
 /* platform dependent support */
@@ -26,7 +25,6 @@
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 82e7ec8..8b3cf57 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -276,52 +276,6 @@
 }
 
 /*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-	struct switch_stack *sw;
-
-	/* changed the size calculations - should hopefully work better. lbt */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
-	dump->u_dsize = ((unsigned long) (current->mm->brk +
-					  (PAGE_SIZE-1))) >> PAGE_SHIFT;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-
-	if (dump->start_stack < TASK_SIZE)
-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
-	dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
-	sw = ((struct switch_stack *)regs) - 1;
-	dump->regs.d1 = regs->d1;
-	dump->regs.d2 = regs->d2;
-	dump->regs.d3 = regs->d3;
-	dump->regs.d4 = regs->d4;
-	dump->regs.d5 = regs->d5;
-	dump->regs.d6 = sw->d6;
-	dump->regs.d7 = sw->d7;
-	dump->regs.a0 = regs->a0;
-	dump->regs.a1 = regs->a1;
-	dump->regs.a2 = regs->a2;
-	dump->regs.a3 = sw->a3;
-	dump->regs.a4 = sw->a4;
-	dump->regs.a5 = sw->a5;
-	dump->regs.a6 = sw->a6;
-	dump->regs.d0 = regs->d0;
-	dump->regs.orig_d0 = regs->orig_d0;
-	dump->regs.stkadj = regs->stkadj;
-	dump->regs.sr = regs->sr;
-	dump->regs.pc = regs->pc;
-	dump->regs.fmtvec = (regs->format << 12) | regs->vector;
-	/* dump floating point stuff */
-	dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
-}
-
-/*
  *	Generic dumping code. Used for panic and debug.
  */
 void dump(struct pt_regs *fp)
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 72f2126..f36c4f2 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -50,7 +50,7 @@
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
 obj-$(CONFIG_64BIT)		+= scall64-64.o
 obj-$(CONFIG_BINFMT_IRIX)	+= binfmt_irix.o
-obj-$(CONFIG_MIPS32_COMPAT)	+= ioctl32.o linux32.o signal32.o
+obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o signal32.o
 obj-$(CONFIG_MIPS32_N32)	+= binfmt_elfn32.o scall64-n32.o signal_n32.o
 obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o ptrace32.o
 
@@ -60,6 +60,5 @@
 obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
 
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
-CFLAGS_ioctl32.o	+= -Ifs/
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c
deleted file mode 100644
index 9ea1fc7..0000000
--- a/arch/mips/kernel/ioctl32.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 2000 Silicon Graphics, Inc.
- * Written by Ulf Carlsson (ulfc@engr.sgi.com)
- * Copyright (C) 2000, 2004 Ralf Baechle
- * Copyright (C) 2002, 2003  Maciej W. Rozycki
- */
-#define INCLUDES
-#include "compat_ioctl.c"
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/compat.h>
-#include <linux/ioctl32.h>
-#include <linux/syscalls.h>
-
-#ifdef CONFIG_SIBYTE_TBPROF
-#include <asm/sibyte/trace_prof.h>
-#endif
-
-#define A(__x) ((unsigned long)(__x))
-
-long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define COMPATIBLE_IOCTL(cmd)		HANDLE_IOCTL((cmd),sys_ioctl)
-#define HANDLE_IOCTL(cmd,handler)	{ (cmd), (ioctl_trans_handler_t)(handler), NULL },
-#define IOCTL_TABLE_START \
-	struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
-	};
-
-IOCTL_TABLE_START
-
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-
-/*HANDLE_IOCTL(RTC_IRQP_READ, w_long)
-COMPATIBLE_IOCTL(RTC_IRQP_SET)
-HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
-COMPATIBLE_IOCTL(RTC_EPOCH_SET)
-*/
-
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index 171f9c2..27827bc 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -6,7 +6,6 @@
 
 AFLAGS_entry.o	:= -traditional
 AFLAGS_pacache.o := -traditional
-CFLAGS_ioctl32.o := -Ifs/
 
 obj-y	     	:= cache.o pacache.o setup.o traps.o time.o irq.o \
 		   pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
@@ -19,6 +18,6 @@
 obj-$(CONFIG_PA11)	+= pci-dma.o
 obj-$(CONFIG_PCI)	+= pci.o
 obj-$(CONFIG_MODULES)	+= module.o
-obj-$(CONFIG_64BIT)	+= binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
+obj-$(CONFIG_64BIT)	+= binfmt_elf32.o sys_parisc32.o signal32.o
 # only supported for PCX-W/U in 64-bit mode at the moment
 obj-$(CONFIG_64BIT)	+= perf.o perf_asm.o
diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
deleted file mode 100644
index 4eada1b..0000000
--- a/arch/parisc/kernel/ioctl32.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#include <linux/syscalls.h>
-
-#define INCLUDES
-#include "compat_ioctl.c"
-
-#include <asm/perf.h>
-#include <asm/ioctls.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) 
-
-#define IOCTL_TABLE_START  struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END    };
-
-IOCTL_TABLE_START
-#include <linux/compat_ioctl.h>
-
-#define DECLARES
-#include "compat_ioctl.c"
-
-/* And these ioctls need translation */
-HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
-
-#if defined(CONFIG_GEN_RTC)
-COMPATIBLE_IOCTL(RTC_AIE_ON)
-COMPATIBLE_IOCTL(RTC_AIE_OFF)
-COMPATIBLE_IOCTL(RTC_UIE_ON)
-COMPATIBLE_IOCTL(RTC_UIE_OFF)
-COMPATIBLE_IOCTL(RTC_PIE_ON)
-COMPATIBLE_IOCTL(RTC_PIE_OFF)
-COMPATIBLE_IOCTL(RTC_WIE_ON)
-COMPATIBLE_IOCTL(RTC_WIE_OFF)
-COMPATIBLE_IOCTL(RTC_ALM_SET)   /* struct rtc_time only has ints */
-COMPATIBLE_IOCTL(RTC_ALM_READ)  /* struct rtc_time only has ints */
-COMPATIBLE_IOCTL(RTC_RD_TIME)   /* struct rtc_time only has ints */
-COMPATIBLE_IOCTL(RTC_SET_TIME)  /* struct rtc_time only has ints */
-HANDLE_IOCTL(RTC_IRQP_READ, w_long)
-COMPATIBLE_IOCTL(RTC_IRQP_SET)
-HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
-COMPATIBLE_IOCTL(RTC_EPOCH_SET)
-#endif
-
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 28004f0..935d965 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -275,6 +275,7 @@
 	select PPC_I8259
 	select PPC_RTAS
 	select RTAS_ERROR_LOGGING
+	select PPC_UDBG_16550
 	default y
 
 config PPC_CHRP
@@ -284,6 +285,7 @@
 	select PPC_INDIRECT_PCI
 	select PPC_RTAS
 	select PPC_MPC106
+	select PPC_UDBG_16550
 	default y
 
 config PPC_PMAC
@@ -306,6 +308,7 @@
 	depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
+	select PPC_UDBG_16550
 	default y
 
 config PPC_MAPLE
@@ -314,6 +317,7 @@
 	select U3_DART
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
+	select PPC_UDBG_16550
 	default n
 	help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -324,6 +328,7 @@
 	depends on PPC_MULTIPLATFORM && PPC64
 	select PPC_RTAS
 	select MMIO_NVRAM
+	select PPC_UDBG_16550
 
 config PPC_OF
 	def_bool y
@@ -370,6 +375,10 @@
 	depends on PPC_MAPLE
 	default y
 
+config PPC_UDBG_16550
+	bool
+	default n
+
 config CELL_IIC
 	depends on PPC_CELL
 	bool
@@ -403,7 +412,7 @@
 
 config GENERIC_TBSYNC
 	bool
-	default y if CONFIG_PPC32 && CONFIG_SMP
+	default y if PPC32 && SMP
 	default n
 
 source "drivers/cpufreq/Kconfig"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 5f80e58..d3654a2 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -76,8 +76,7 @@
 CHECKFLAGS	+= -m$(SZ) -D__powerpc__ -D__powerpc$(SZ)__
 
 ifeq ($(CONFIG_PPC64),y)
-GCC_VERSION     := $(call cc-version)
-GCC_BROKEN_VEC	:= $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi)
+GCC_BROKEN_VEC	:= $(shell if [ $(call cc-version) -lt 0400 ] ; then echo "y"; fi)
 
 ifeq ($(CONFIG_POWER4_ONLY),y)
 ifeq ($(CONFIG_ALTIVEC),y)
@@ -189,10 +188,9 @@
 # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
 # instructions.
 # gcc-3.4 and binutils-2.14 are a fatal combination.
-GCC_VERSION	:= $(call cc-version)
 
 checkbin:
-	@if test "$(GCC_VERSION)" = "0304" ; then \
+	@if test "$(call cc-version)" = "0304" ; then \
 		if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
 			echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
 			echo 'correctly with gcc-3.4 and your version of binutils.'; \
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 509399e..347f439 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -861,7 +861,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
 CONFIG_SERIAL_ICOM=m
-CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 6e03b59..144e284 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -4,7 +4,6 @@
 
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS	+= -mno-minimal-toc
-CFLAGS_ioctl32.o += -Ifs/
 endif
 ifeq ($(CONFIG_PPC32),y)
 CFLAGS_prom_init.o      += -fPIC
@@ -16,7 +15,7 @@
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 				   signal_64.o ptrace32.o systbl.o \
-				   paca.o ioctl32.o cpu_setup_power4.o \
+				   paca.o cpu_setup_power4.o \
 				   firmware.o sysfs.o idle_64.o
 obj-$(CONFIG_PPC64)		+= vdso64/
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
@@ -55,7 +54,7 @@
 obj-$(CONFIG_6xx)		+= idle_6xx.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
-obj-$(CONFIG_SERIAL_8250)	+= legacy_serial.o udbg_16550.o
+obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
 
diff --git a/arch/powerpc/kernel/ioctl32.c b/arch/powerpc/kernel/ioctl32.c
deleted file mode 100644
index 0fa3d27..0000000
--- a/arch/powerpc/kernel/ioctl32.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Based on sparc64 ioctl32.c by:
- *
- * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- *
- * ppc64 changes:
- *
- * Copyright (C) 2000  Ken Aaker (kdaaker@rchland.vnet.ibm.com)
- * Copyright (C) 2001  Anton Blanchard (antonb@au.ibm.com)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- *
- * 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.
- */
-
-#define INCLUDES
-#include "compat_ioctl.c"
-#include <linux/syscalls.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
-
-#define IOCTL_TABLE_START \
-	struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
-	};
-
-IOCTL_TABLE_START
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 5368f9c..27b0c40 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -35,7 +35,6 @@
 #include <asm/kdebug.h>
 #include <asm/sstep.h>
 
-static DECLARE_MUTEX(kprobe_mutex);
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
@@ -54,19 +53,17 @@
 
 	/* insn must be on a special executable page on ppc64 */
 	if (!ret) {
-		down(&kprobe_mutex);
 		p->ainsn.insn = get_insn_slot();
-		up(&kprobe_mutex);
 		if (!p->ainsn.insn)
 			ret = -ENOMEM;
 	}
-	return ret;
-}
 
-void __kprobes arch_copy_kprobe(struct kprobe *p)
-{
-	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-	p->opcode = *p->addr;
+	if (!ret) {
+		memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+		p->opcode = *p->addr;
+	}
+
+	return ret;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index fc60a77..ba21a6c 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -381,7 +381,7 @@
 	dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
 	dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
 
-	dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+	dev->cfg_size = pci_cfg_space_size(dev);
 
 	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
 		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index b275814..16d9a90 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -244,7 +244,6 @@
 extern long mol_trampoline;
 EXPORT_SYMBOL(mol_trampoline); /* For MOL */
 EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
-EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
 #ifdef CONFIG_SMP
 extern int mmu_hash_lock;
 EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 45b8109..5579f65 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -72,7 +72,7 @@
         return 0;
 }
 
-static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
+int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
 {
 	int returnval = -1;
 	unsigned long buid, addr;
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index e5d285a..db72a92 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -299,9 +299,7 @@
 	if (ppc_md.init_early)
 		ppc_md.init_early();
 
-#ifdef CONFIG_SERIAL_8250
 	find_legacy_serial_ports();
-#endif
 	finish_device_tree();
 
 	smp_setup_cpu_maps();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 81567e9..c4b7696 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -472,9 +472,7 @@
 	 * hash table management for us, thus ioremap works. We do that early
 	 * so that further code can be debugged
 	 */
-#ifdef CONFIG_SERIAL_8250
 	find_legacy_serial_ports();
-#endif
 
 	/*
 	 * "Finish" the device-tree, that is do the actual parsing of
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 9c921d1..475249d 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -552,30 +552,6 @@
 	return ret;
 }
 
-asmlinkage int compat_sys_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
-	return sys_pciconfig_read((unsigned long) bus,
-				  (unsigned long) dfn,
-				  (unsigned long) off,
-				  (unsigned long) len,
-				  compat_ptr(ubuf));
-}
-
-asmlinkage int compat_sys_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
-	return sys_pciconfig_write((unsigned long) bus,
-				   (unsigned long) dfn,
-				   (unsigned long) off,
-				   (unsigned long) len,
-				   compat_ptr(ubuf));
-}
-
-asmlinkage int compat_sys_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
-{
-	return sys_pciconfig_iobase(which, in_bus, in_devfn);
-}
-
-
 /* Note: it is necessary to treat mode as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -956,38 +932,6 @@
 			     advice);
 }
 
-long ppc32_timer_create(clockid_t clock,
-			struct compat_sigevent __user *ev32,
-			timer_t __user *timer_id)
-{
-	sigevent_t event;
-	timer_t t;
-	long err;
-	mm_segment_t savefs;
-
-	if (ev32 == NULL)
-		return sys_timer_create(clock, NULL, timer_id);
-
-	if (get_compat_sigevent(&event, ev32))
-		return -EFAULT;
-
-	if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
-		return -EFAULT;
-
-	savefs = get_fs();
-	set_fs(KERNEL_DS);
-	/* The __user pointer casts are valid due to the set_fs() */
-	err = sys_timer_create(clock,
-		(sigevent_t __user *) &event,
-		(timer_t __user *) &t);
-	set_fs(savefs);
-
-	if (err == 0)
-		err = __put_user(t, timer_id);
-
-	return err;
-}
-
 asmlinkage long compat_sys_add_key(const char __user *_type,
 			      const char __user *_description,
 			      const void __user *_payload,
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 65463a1..6801317 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -239,9 +239,9 @@
 SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
 SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
 SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
-COMPAT_SYS(pciconfig_read)
-COMPAT_SYS(pciconfig_write)
-COMPAT_SYS(pciconfig_iobase)
+SYSCALL(pciconfig_read)
+SYSCALL(pciconfig_write)
+SYSCALL(pciconfig_iobase)
 SYSCALL(ni_syscall)
 SYSCALL(getdents64)
 SYSCALL(pivot_root)
@@ -281,7 +281,7 @@
 SYSCALL(epoll_ctl)
 SYSCALL(epoll_wait)
 SYSCALL(remap_file_pages)
-SYSX(sys_timer_create,ppc32_timer_create,sys_timer_create)
+SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create)
 COMPAT_SYS(timer_settime)
 COMPAT_SYS(timer_gettime)
 SYSCALL(timer_getoverrun)
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 2ffca63..7b278d83 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -174,7 +174,7 @@
 	pa = addr & PAGE_MASK;
 	size = PAGE_ALIGN(addr + size) - pa;
 
-	if (size == 0)
+	if ((size == 0) || (pa == 0))
 		return NULL;
 
 	if (mem_init_done) {
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index d2ba358..b3962c3 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -138,7 +138,7 @@
 {
 	struct dentry *dentry, *tmp;
 	mutex_lock(&dir->d_inode->i_mutex);
-	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
+	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
 		spin_lock(&dcache_lock);
 		spin_lock(&dentry->d_lock);
 		if (!(d_unhashed(dentry)) && dentry->d_inode) {
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index dd73e38..a1cb4d2 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -71,9 +71,6 @@
 #define DBG(fmt...)
 #endif
 
-extern void generic_find_legacy_serial_ports(u64 *physport,
-		unsigned int *default_speed);
-
 static void maple_restart(char *cmd)
 {
 	unsigned int maple_nvram_base;
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 6accdd1..61616d1 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -4,7 +4,7 @@
 obj-$(CONFIG_IBMVIO)	+= vio.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
-obj-$(CONFIG_EEH)	+= eeh.o eeh_event.o
+obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 7fbfd16..17cea7f 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -76,15 +76,14 @@
  */
 #define EEH_MAX_FAILS	100000
 
-/* Misc forward declaraions */
-static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn);
-
 /* RTAS tokens */
 static int ibm_set_eeh_option;
 static int ibm_set_slot_reset;
 static int ibm_read_slot_reset_state;
 static int ibm_read_slot_reset_state2;
 static int ibm_slot_error_detail;
+static int ibm_get_config_addr_info;
+static int ibm_configure_bridge;
 
 int eeh_subsystem_enabled;
 EXPORT_SYMBOL(eeh_subsystem_enabled);
@@ -98,308 +97,23 @@
 static int eeh_error_buf_size;
 
 /* System monitoring statistics */
-static DEFINE_PER_CPU(unsigned long, no_device);
-static DEFINE_PER_CPU(unsigned long, no_dn);
-static DEFINE_PER_CPU(unsigned long, no_cfg_addr);
-static DEFINE_PER_CPU(unsigned long, ignored_check);
-static DEFINE_PER_CPU(unsigned long, total_mmio_ffs);
-static DEFINE_PER_CPU(unsigned long, false_positives);
-static DEFINE_PER_CPU(unsigned long, ignored_failures);
-static DEFINE_PER_CPU(unsigned long, slot_resets);
+static unsigned long no_device;
+static unsigned long no_dn;
+static unsigned long no_cfg_addr;
+static unsigned long ignored_check;
+static unsigned long total_mmio_ffs;
+static unsigned long false_positives;
+static unsigned long ignored_failures;
+static unsigned long slot_resets;
 
-/**
- * The pci address cache subsystem.  This subsystem places
- * PCI device address resources into a red-black tree, sorted
- * according to the address range, so that given only an i/o
- * address, the corresponding PCI device can be **quickly**
- * found. It is safe to perform an address lookup in an interrupt
- * context; this ability is an important feature.
- *
- * Currently, the only customer of this code is the EEH subsystem;
- * thus, this code has been somewhat tailored to suit EEH better.
- * In particular, the cache does *not* hold the addresses of devices
- * for which EEH is not enabled.
- *
- * (Implementation Note: The RB tree seems to be better/faster
- * than any hash algo I could think of for this problem, even
- * with the penalty of slow pointer chases for d-cache misses).
- */
-struct pci_io_addr_range
-{
-	struct rb_node rb_node;
-	unsigned long addr_lo;
-	unsigned long addr_hi;
-	struct pci_dev *pcidev;
-	unsigned int flags;
-};
-
-static struct pci_io_addr_cache
-{
-	struct rb_root rb_root;
-	spinlock_t piar_lock;
-} pci_io_addr_cache_root;
-
-static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
-{
-	struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
-
-	while (n) {
-		struct pci_io_addr_range *piar;
-		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-
-		if (addr < piar->addr_lo) {
-			n = n->rb_left;
-		} else {
-			if (addr > piar->addr_hi) {
-				n = n->rb_right;
-			} else {
-				pci_dev_get(piar->pcidev);
-				return piar->pcidev;
-			}
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * pci_get_device_by_addr - Get device, given only address
- * @addr: mmio (PIO) phys address or i/o port number
- *
- * Given an mmio phys address, or a port number, find a pci device
- * that implements this address.  Be sure to pci_dev_put the device
- * when finished.  I/O port numbers are assumed to be offset
- * from zero (that is, they do *not* have pci_io_addr added in).
- * It is safe to call this function within an interrupt.
- */
-static struct pci_dev *pci_get_device_by_addr(unsigned long addr)
-{
-	struct pci_dev *dev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-	dev = __pci_get_device_by_addr(addr);
-	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-	return dev;
-}
-
-#ifdef DEBUG
-/*
- * Handy-dandy debug print routine, does nothing more
- * than print out the contents of our addr cache.
- */
-static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
-{
-	struct rb_node *n;
-	int cnt = 0;
-
-	n = rb_first(&cache->rb_root);
-	while (n) {
-		struct pci_io_addr_range *piar;
-		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-		printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n",
-		       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
-		       piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
-		cnt++;
-		n = rb_next(n);
-	}
-}
-#endif
-
-/* Insert address range into the rb tree. */
-static struct pci_io_addr_range *
-pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
-		      unsigned long ahi, unsigned int flags)
-{
-	struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
-	struct rb_node *parent = NULL;
-	struct pci_io_addr_range *piar;
-
-	/* Walk tree, find a place to insert into tree */
-	while (*p) {
-		parent = *p;
-		piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
-		if (ahi < piar->addr_lo) {
-			p = &parent->rb_left;
-		} else if (alo > piar->addr_hi) {
-			p = &parent->rb_right;
-		} else {
-			if (dev != piar->pcidev ||
-			    alo != piar->addr_lo || ahi != piar->addr_hi) {
-				printk(KERN_WARNING "PIAR: overlapping address range\n");
-			}
-			return piar;
-		}
-	}
-	piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
-	if (!piar)
-		return NULL;
-
-	piar->addr_lo = alo;
-	piar->addr_hi = ahi;
-	piar->pcidev = dev;
-	piar->flags = flags;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
-	                  alo, ahi, pci_name (dev));
-#endif
-
-	rb_link_node(&piar->rb_node, parent, p);
-	rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
-
-	return piar;
-}
-
-static void __pci_addr_cache_insert_device(struct pci_dev *dev)
-{
-	struct device_node *dn;
-	struct pci_dn *pdn;
-	int i;
-	int inserted = 0;
-
-	dn = pci_device_to_OF_node(dev);
-	if (!dn) {
-		printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev));
-		return;
-	}
-
-	/* Skip any devices for which EEH is not enabled. */
-	pdn = PCI_DN(dn);
-	if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
-	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
-#ifdef DEBUG
-		printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n",
-		       pci_name(dev), pdn->node->full_name);
-#endif
-		return;
-	}
-
-	/* The cache holds a reference to the device... */
-	pci_dev_get(dev);
-
-	/* Walk resources on this device, poke them into the tree */
-	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-		unsigned long start = pci_resource_start(dev,i);
-		unsigned long end = pci_resource_end(dev,i);
-		unsigned int flags = pci_resource_flags(dev,i);
-
-		/* We are interested only bus addresses, not dma or other stuff */
-		if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-			continue;
-		if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
-			 continue;
-		pci_addr_cache_insert(dev, start, end, flags);
-		inserted = 1;
-	}
-
-	/* If there was nothing to add, the cache has no reference... */
-	if (!inserted)
-		pci_dev_put(dev);
-}
-
-/**
- * pci_addr_cache_insert_device - Add a device to the address cache
- * @dev: PCI device whose I/O addresses we are interested in.
- *
- * In order to support the fast lookup of devices based on addresses,
- * we maintain a cache of devices that can be quickly searched.
- * This routine adds a device to that cache.
- */
-static void pci_addr_cache_insert_device(struct pci_dev *dev)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-	__pci_addr_cache_insert_device(dev);
-	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-}
-
-static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
-{
-	struct rb_node *n;
-	int removed = 0;
-
-restart:
-	n = rb_first(&pci_io_addr_cache_root.rb_root);
-	while (n) {
-		struct pci_io_addr_range *piar;
-		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-
-		if (piar->pcidev == dev) {
-			rb_erase(n, &pci_io_addr_cache_root.rb_root);
-			removed = 1;
-			kfree(piar);
-			goto restart;
-		}
-		n = rb_next(n);
-	}
-
-	/* The cache no longer holds its reference to this device... */
-	if (removed)
-		pci_dev_put(dev);
-}
-
-/**
- * pci_addr_cache_remove_device - remove pci device from addr cache
- * @dev: device to remove
- *
- * Remove a device from the addr-cache tree.
- * This is potentially expensive, since it will walk
- * the tree multiple times (once per resource).
- * But so what; device removal doesn't need to be that fast.
- */
-static void pci_addr_cache_remove_device(struct pci_dev *dev)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-	__pci_addr_cache_remove_device(dev);
-	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-}
-
-/**
- * pci_addr_cache_build - Build a cache of I/O addresses
- *
- * Build a cache of pci i/o addresses.  This cache will be used to
- * find the pci device that corresponds to a given address.
- * This routine scans all pci busses to build the cache.
- * Must be run late in boot process, after the pci controllers
- * have been scaned for devices (after all device resources are known).
- */
-void __init pci_addr_cache_build(void)
-{
-	struct device_node *dn;
-	struct pci_dev *dev = NULL;
-
-	if (!eeh_subsystem_enabled)
-		return;
-
-	spin_lock_init(&pci_io_addr_cache_root.piar_lock);
-
-	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		/* Ignore PCI bridges ( XXX why ??) */
-		if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
-			continue;
-		}
-		pci_addr_cache_insert_device(dev);
-
-		/* Save the BAR's; firmware doesn't restore these after EEH reset */
-		dn = pci_device_to_OF_node(dev);
-		eeh_save_bars(dev, PCI_DN(dn));
-	}
-
-#ifdef DEBUG
-	/* Verify tree built up above, echo back the list of addrs. */
-	pci_addr_cache_print(&pci_io_addr_cache_root);
-#endif
-}
+#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
 
 /* --------------------------------------------------------------- */
-/* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */
+/* Below lies the EEH event infrastructure */
 
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
 {
+	int config_addr;
 	unsigned long flags;
 	int rc;
 
@@ -407,8 +121,13 @@
 	spin_lock_irqsave(&slot_errbuf_lock, flags);
 	memset(slot_errbuf, 0, eeh_error_buf_size);
 
+	/* Use PE configuration address, if present */
+	config_addr = pdn->eeh_config_addr;
+	if (pdn->eeh_pe_config_addr)
+		config_addr = pdn->eeh_pe_config_addr;
+
 	rc = rtas_call(ibm_slot_error_detail,
-	               8, 1, NULL, pdn->eeh_config_addr,
+	               8, 1, NULL, config_addr,
 	               BUID_HI(pdn->phb->buid),
 	               BUID_LO(pdn->phb->buid), NULL, 0,
 	               virt_to_phys(slot_errbuf),
@@ -428,6 +147,7 @@
 static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
 {
 	int token, outputs;
+	int config_addr;
 
 	if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
 		token = ibm_read_slot_reset_state2;
@@ -438,7 +158,12 @@
 		outputs = 3;
 	}
 
-	return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr,
+	/* Use PE configuration address, if present */
+	config_addr = pdn->eeh_config_addr;
+	if (pdn->eeh_pe_config_addr)
+		config_addr = pdn->eeh_pe_config_addr;
+
+	return rtas_call(token, 3, outputs, rets, config_addr,
 			 BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
 }
 
@@ -462,7 +187,7 @@
 /** 
  * Return the "partitionable endpoint" (pe) under which this device lies
  */
-static struct device_node * find_device_pe(struct device_node *dn)
+struct device_node * find_device_pe(struct device_node *dn)
 {
 	while ((dn->parent) && PCI_DN(dn->parent) &&
 	      (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
@@ -485,6 +210,11 @@
 		if (PCI_DN(dn)) {
 			PCI_DN(dn)->eeh_mode |= mode_flag;
 
+			/* Mark the pci device driver too */
+			struct pci_dev *dev = PCI_DN(dn)->pcidev;
+			if (dev && dev->driver)
+				dev->error_state = pci_channel_io_frozen;
+
 			if (dn->child)
 				__eeh_mark_slot (dn->child, mode_flag);
 		}
@@ -495,6 +225,11 @@
 void eeh_mark_slot (struct device_node *dn, int mode_flag)
 {
 	dn = find_device_pe (dn);
+
+	/* Back up one, since config addrs might be shared */
+	if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+		dn = dn->parent;
+
 	PCI_DN(dn)->eeh_mode |= mode_flag;
 	__eeh_mark_slot (dn->child, mode_flag);
 }
@@ -516,7 +251,13 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&confirm_error_lock, flags);
+	
 	dn = find_device_pe (dn);
+	
+	/* Back up one, since config addrs might be shared */
+	if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+		dn = dn->parent;
+
 	PCI_DN(dn)->eeh_mode &= ~mode_flag;
 	PCI_DN(dn)->eeh_check_count = 0;
 	__eeh_clear_slot (dn->child, mode_flag);
@@ -544,15 +285,16 @@
 	int rets[3];
 	unsigned long flags;
 	struct pci_dn *pdn;
+	enum pci_channel_state state;
 	int rc = 0;
 
-	__get_cpu_var(total_mmio_ffs)++;
+	total_mmio_ffs++;
 
 	if (!eeh_subsystem_enabled)
 		return 0;
 
 	if (!dn) {
-		__get_cpu_var(no_dn)++;
+		no_dn++;
 		return 0;
 	}
 	pdn = PCI_DN(dn);
@@ -560,7 +302,7 @@
 	/* Access to IO BARs might get this far and still not want checking. */
 	if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
 	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
-		__get_cpu_var(ignored_check)++;
+		ignored_check++;
 #ifdef DEBUG
 		printk ("EEH:ignored check (%x) for %s %s\n", 
 		        pdn->eeh_mode, pci_name (dev), dn->full_name);
@@ -568,8 +310,8 @@
 		return 0;
 	}
 
-	if (!pdn->eeh_config_addr) {
-		__get_cpu_var(no_cfg_addr)++;
+	if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) {
+		no_cfg_addr++;
 		return 0;
 	}
 
@@ -611,7 +353,7 @@
 	if (ret != 0) {
 		printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
 		       ret, dn->full_name);
-		__get_cpu_var(false_positives)++;
+		false_positives++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -620,14 +362,14 @@
 	if (rets[1] != 1) {
 		printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
 		       ret, dn->full_name);
-		__get_cpu_var(false_positives)++;
+		false_positives++;
 		rc = 0;
 		goto dn_unlock;
 	}
 
 	/* If not the kind of error we know about, punt. */
 	if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
-		__get_cpu_var(false_positives)++;
+		false_positives++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -635,12 +377,12 @@
 	/* Note that config-io to empty slots may fail;
 	 * we recognize empty because they don't have children. */
 	if ((rets[0] == 5) && (dn->child == NULL)) {
-		__get_cpu_var(false_positives)++;
+		false_positives++;
 		rc = 0;
 		goto dn_unlock;
 	}
 
-	__get_cpu_var(slot_resets)++;
+	slot_resets++;
  
 	/* Avoid repeated reports of this failure, including problems
 	 * with other functions on this device, and functions under
@@ -648,8 +390,13 @@
 	eeh_mark_slot (dn, EEH_MODE_ISOLATED);
 	spin_unlock_irqrestore(&confirm_error_lock, flags);
 
-	eeh_send_failure_event (dn, dev, rets[0], rets[2]);
-	
+	state = pci_channel_io_normal;
+	if ((rets[0] == 2) || (rets[0] == 4))
+		state = pci_channel_io_frozen;
+	if (rets[0] == 5)
+		state = pci_channel_io_perm_failure;
+	eeh_send_failure_event (dn, dev, state, rets[2]);
+
 	/* Most EEH events are due to device driver bugs.  Having
 	 * a stack trace will help the device-driver authors figure
 	 * out what happened.  So print that out. */
@@ -685,7 +432,7 @@
 	addr = eeh_token_to_phys((unsigned long __force) token);
 	dev = pci_get_device_by_addr(addr);
 	if (!dev) {
-		__get_cpu_var(no_device)++;
+		no_device++;
 		return val;
 	}
 
@@ -716,11 +463,16 @@
 	if (rc) return rc;
 
 	if (rets[1] == 0) return -1;  /* EEH is not supported */
-	if (rets[0] == 0)  return 0;  /* Oll Korrect */
+	if (rets[0] == 0) return 0;   /* Oll Korrect */
 	if (rets[0] == 5) {
 		if (rets[2] == 0) return -1; /* permanently unavailable */
 		return rets[2]; /* number of millisecs to wait */
 	}
+	if (rets[0] == 1)
+		return 250;
+
+	printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
+		rc, rets[0], rets[1], rets[2]);
 	return -1;
 }
 
@@ -737,6 +489,7 @@
 static void
 rtas_pci_slot_reset(struct pci_dn *pdn, int state)
 {
+	int config_addr;
 	int rc;
 
 	BUG_ON (pdn==NULL); 
@@ -747,8 +500,13 @@
 		return;
 	}
 
+	/* Use PE configuration address, if present */
+	config_addr = pdn->eeh_config_addr;
+	if (pdn->eeh_pe_config_addr)
+		config_addr = pdn->eeh_pe_config_addr;
+
 	rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
-	               pdn->eeh_config_addr,
+	               config_addr,
 	               BUID_HI(pdn->phb->buid),
 	               BUID_LO(pdn->phb->buid),
 	               state);
@@ -761,9 +519,11 @@
 
 /** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
  *  dn -- device node to be reset.
+ *
+ *  Return 0 if success, else a non-zero value.
  */
 
-void
+int
 rtas_set_slot_reset(struct pci_dn *pdn)
 {
 	int i, rc;
@@ -793,10 +553,21 @@
 	 * ready to be used; if not, wait for recovery. */
 	for (i=0; i<10; i++) {
 		rc = eeh_slot_availability (pdn);
-		if (rc <= 0) break;
+		if (rc < 0)
+			printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", rc, pdn->node->full_name);
+		if (rc == 0)
+			return 0;
+		if (rc < 0)
+			return -1;
 
 		msleep (rc+100);
 	}
+
+	rc = eeh_slot_availability (pdn);
+	if (rc)
+		printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name);
+
+	return rc;
 }
 
 /* ------------------------------------------------------- */
@@ -851,7 +622,7 @@
 	if (!pdn) 
 		return;
 	
-	if (! pdn->eeh_is_bridge)
+	if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
 		__restore_bars (pdn);
 
 	dn = pdn->node->child;
@@ -869,30 +640,30 @@
  * PCI devices are added individuallly; but, for the restore,
  * an entire slot is reset at a time.
  */
-static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn)
+static void eeh_save_bars(struct pci_dn *pdn)
 {
 	int i;
 
-	if (!pdev || !pdn )
+	if (!pdn )
 		return;
 	
 	for (i = 0; i < 16; i++)
-		pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]);
-
-	if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-		pdn->eeh_is_bridge = 1;
+		rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
 }
 
 void
 rtas_configure_bridge(struct pci_dn *pdn)
 {
-	int token = rtas_token ("ibm,configure-bridge");
+	int config_addr;
 	int rc;
 
-	if (token == RTAS_UNKNOWN_SERVICE)
-		return;
-	rc = rtas_call(token,3,1, NULL,
-	               pdn->eeh_config_addr,
+	/* Use PE configuration address, if present */
+	config_addr = pdn->eeh_config_addr;
+	if (pdn->eeh_pe_config_addr)
+		config_addr = pdn->eeh_pe_config_addr;
+
+	rc = rtas_call(ibm_configure_bridge,3,1, NULL,
+	               config_addr,
 	               BUID_HI(pdn->phb->buid),
 	               BUID_LO(pdn->phb->buid));
 	if (rc) {
@@ -927,6 +698,7 @@
 	int enable;
 	struct pci_dn *pdn = PCI_DN(dn);
 
+	pdn->class_code = 0;
 	pdn->eeh_mode = 0;
 	pdn->eeh_check_count = 0;
 	pdn->eeh_freeze_count = 0;
@@ -943,6 +715,7 @@
 		pdn->eeh_mode |= EEH_MODE_NOCHECK;
 		return NULL;
 	}
+	pdn->class_code = *class_code;
 
 	/*
 	 * Now decide if we are going to "Disable" EEH checking
@@ -953,8 +726,10 @@
 	 * But there are a few cases like display devices that make sense.
 	 */
 	enable = 1;	/* i.e. we will do checking */
+#if 0
 	if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
 		enable = 0;
+#endif
 
 	if (!enable)
 		pdn->eeh_mode |= EEH_MODE_NOCHECK;
@@ -973,8 +748,22 @@
 			eeh_subsystem_enabled = 1;
 			pdn->eeh_mode |= EEH_MODE_SUPPORTED;
 			pdn->eeh_config_addr = regs[0];
+
+			/* If the newer, better, ibm,get-config-addr-info is supported, 
+			 * then use that instead. */
+			pdn->eeh_pe_config_addr = 0;
+			if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
+				unsigned int rets[2];
+				ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, 
+					pdn->eeh_config_addr, 
+					info->buid_hi, info->buid_lo,
+					0);
+				if (ret == 0)
+					pdn->eeh_pe_config_addr = rets[0];
+			}
 #ifdef DEBUG
-			printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name);
+			printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n",
+			       dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr);
 #endif
 		} else {
 
@@ -993,6 +782,7 @@
 		       dn->full_name);
 	}
 
+	eeh_save_bars(pdn);
 	return NULL;
 }
 
@@ -1026,6 +816,8 @@
 	ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");
 	ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
 	ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
+	ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
+	ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
 
 	if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
 		return;
@@ -1080,12 +872,10 @@
 	if (!dn || !PCI_DN(dn))
 		return;
 	phb = PCI_DN(dn)->phb;
-	if (NULL == phb || 0 == phb->buid) {
-		printk(KERN_WARNING "EEH: Expected buid but found none for %s\n",
-		       dn->full_name);
-		dump_stack();
+
+	/* USB Bus children of PCI devices will not have BUID's */
+	if (NULL == phb || 0 == phb->buid)
 		return;
-	}
 
 	info.buid_hi = BUID_HI(phb->buid);
 	info.buid_lo = BUID_LO(phb->buid);
@@ -1127,7 +917,6 @@
 	pdn->pcidev = dev;
 
 	pci_addr_cache_insert_device (dev);
-	eeh_save_bars(dev, pdn);
 }
 EXPORT_SYMBOL_GPL(eeh_add_device_late);
 
@@ -1175,25 +964,9 @@
 
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
-	unsigned int cpu;
-	unsigned long ffs = 0, positives = 0, failures = 0;
-	unsigned long resets = 0;
-	unsigned long no_dev = 0, no_dn = 0, no_cfg = 0, no_check = 0;
-
-	for_each_cpu(cpu) {
-		ffs += per_cpu(total_mmio_ffs, cpu);
-		positives += per_cpu(false_positives, cpu);
-		failures += per_cpu(ignored_failures, cpu);
-		resets += per_cpu(slot_resets, cpu);
-		no_dev += per_cpu(no_device, cpu);
-		no_dn += per_cpu(no_dn, cpu);
-		no_cfg += per_cpu(no_cfg_addr, cpu);
-		no_check += per_cpu(ignored_check, cpu);
-	}
-
 	if (0 == eeh_subsystem_enabled) {
 		seq_printf(m, "EEH Subsystem is globally disabled\n");
-		seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs);
+		seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs);
 	} else {
 		seq_printf(m, "EEH Subsystem is enabled\n");
 		seq_printf(m,
@@ -1205,8 +978,10 @@
 				"eeh_false_positives=%ld\n"
 				"eeh_ignored_failures=%ld\n"
 				"eeh_slot_resets=%ld\n",
-				no_dev, no_dn, no_cfg, no_check,
-				ffs, positives, failures, resets);
+				no_device, no_dn, no_cfg_addr, 
+				ignored_check, total_mmio_ffs, 
+				false_positives, ignored_failures, 
+				slot_resets);
 	}
 
 	return 0;
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
new file mode 100644
index 0000000..d4a402c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -0,0 +1,316 @@
+/*
+ * eeh_cache.c
+ * PCI address cache; allows the lookup of PCI devices based on I/O address
+ *
+ * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM 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
+ */
+
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+
+#undef DEBUG
+
+/**
+ * The pci address cache subsystem.  This subsystem places
+ * PCI device address resources into a red-black tree, sorted
+ * according to the address range, so that given only an i/o
+ * address, the corresponding PCI device can be **quickly**
+ * found. It is safe to perform an address lookup in an interrupt
+ * context; this ability is an important feature.
+ *
+ * Currently, the only customer of this code is the EEH subsystem;
+ * thus, this code has been somewhat tailored to suit EEH better.
+ * In particular, the cache does *not* hold the addresses of devices
+ * for which EEH is not enabled.
+ *
+ * (Implementation Note: The RB tree seems to be better/faster
+ * than any hash algo I could think of for this problem, even
+ * with the penalty of slow pointer chases for d-cache misses).
+ */
+struct pci_io_addr_range
+{
+	struct rb_node rb_node;
+	unsigned long addr_lo;
+	unsigned long addr_hi;
+	struct pci_dev *pcidev;
+	unsigned int flags;
+};
+
+static struct pci_io_addr_cache
+{
+	struct rb_root rb_root;
+	spinlock_t piar_lock;
+} pci_io_addr_cache_root;
+
+static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
+{
+	struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
+
+	while (n) {
+		struct pci_io_addr_range *piar;
+		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+		if (addr < piar->addr_lo) {
+			n = n->rb_left;
+		} else {
+			if (addr > piar->addr_hi) {
+				n = n->rb_right;
+			} else {
+				pci_dev_get(piar->pcidev);
+				return piar->pcidev;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * pci_get_device_by_addr - Get device, given only address
+ * @addr: mmio (PIO) phys address or i/o port number
+ *
+ * Given an mmio phys address, or a port number, find a pci device
+ * that implements this address.  Be sure to pci_dev_put the device
+ * when finished.  I/O port numbers are assumed to be offset
+ * from zero (that is, they do *not* have pci_io_addr added in).
+ * It is safe to call this function within an interrupt.
+ */
+struct pci_dev *pci_get_device_by_addr(unsigned long addr)
+{
+	struct pci_dev *dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+	dev = __pci_get_device_by_addr(addr);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+	return dev;
+}
+
+#ifdef DEBUG
+/*
+ * Handy-dandy debug print routine, does nothing more
+ * than print out the contents of our addr cache.
+ */
+static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
+{
+	struct rb_node *n;
+	int cnt = 0;
+
+	n = rb_first(&cache->rb_root);
+	while (n) {
+		struct pci_io_addr_range *piar;
+		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+		printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n",
+		       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
+		       piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
+		cnt++;
+		n = rb_next(n);
+	}
+}
+#endif
+
+/* Insert address range into the rb tree. */
+static struct pci_io_addr_range *
+pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
+		      unsigned long ahi, unsigned int flags)
+{
+	struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
+	struct rb_node *parent = NULL;
+	struct pci_io_addr_range *piar;
+
+	/* Walk tree, find a place to insert into tree */
+	while (*p) {
+		parent = *p;
+		piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
+		if (ahi < piar->addr_lo) {
+			p = &parent->rb_left;
+		} else if (alo > piar->addr_hi) {
+			p = &parent->rb_right;
+		} else {
+			if (dev != piar->pcidev ||
+			    alo != piar->addr_lo || ahi != piar->addr_hi) {
+				printk(KERN_WARNING "PIAR: overlapping address range\n");
+			}
+			return piar;
+		}
+	}
+	piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+	if (!piar)
+		return NULL;
+
+	piar->addr_lo = alo;
+	piar->addr_hi = ahi;
+	piar->pcidev = dev;
+	piar->flags = flags;
+
+#ifdef DEBUG
+	printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
+	                  alo, ahi, pci_name (dev));
+#endif
+
+	rb_link_node(&piar->rb_node, parent, p);
+	rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
+
+	return piar;
+}
+
+static void __pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+	struct device_node *dn;
+	struct pci_dn *pdn;
+	int i;
+	int inserted = 0;
+
+	dn = pci_device_to_OF_node(dev);
+	if (!dn) {
+		printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev));
+		return;
+	}
+
+	/* Skip any devices for which EEH is not enabled. */
+	pdn = PCI_DN(dn);
+	if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
+#ifdef DEBUG
+		printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n",
+		       pci_name(dev), pdn->node->full_name);
+#endif
+		return;
+	}
+
+	/* The cache holds a reference to the device... */
+	pci_dev_get(dev);
+
+	/* Walk resources on this device, poke them into the tree */
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		unsigned long start = pci_resource_start(dev,i);
+		unsigned long end = pci_resource_end(dev,i);
+		unsigned int flags = pci_resource_flags(dev,i);
+
+		/* We are interested only bus addresses, not dma or other stuff */
+		if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
+		if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
+			 continue;
+		pci_addr_cache_insert(dev, start, end, flags);
+		inserted = 1;
+	}
+
+	/* If there was nothing to add, the cache has no reference... */
+	if (!inserted)
+		pci_dev_put(dev);
+}
+
+/**
+ * pci_addr_cache_insert_device - Add a device to the address cache
+ * @dev: PCI device whose I/O addresses we are interested in.
+ *
+ * In order to support the fast lookup of devices based on addresses,
+ * we maintain a cache of devices that can be quickly searched.
+ * This routine adds a device to that cache.
+ */
+void pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+	__pci_addr_cache_insert_device(dev);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+	struct rb_node *n;
+	int removed = 0;
+
+restart:
+	n = rb_first(&pci_io_addr_cache_root.rb_root);
+	while (n) {
+		struct pci_io_addr_range *piar;
+		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+		if (piar->pcidev == dev) {
+			rb_erase(n, &pci_io_addr_cache_root.rb_root);
+			removed = 1;
+			kfree(piar);
+			goto restart;
+		}
+		n = rb_next(n);
+	}
+
+	/* The cache no longer holds its reference to this device... */
+	if (removed)
+		pci_dev_put(dev);
+}
+
+/**
+ * pci_addr_cache_remove_device - remove pci device from addr cache
+ * @dev: device to remove
+ *
+ * Remove a device from the addr-cache tree.
+ * This is potentially expensive, since it will walk
+ * the tree multiple times (once per resource).
+ * But so what; device removal doesn't need to be that fast.
+ */
+void pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+	__pci_addr_cache_remove_device(dev);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+/**
+ * pci_addr_cache_build - Build a cache of I/O addresses
+ *
+ * Build a cache of pci i/o addresses.  This cache will be used to
+ * find the pci device that corresponds to a given address.
+ * This routine scans all pci busses to build the cache.
+ * Must be run late in boot process, after the pci controllers
+ * have been scaned for devices (after all device resources are known).
+ */
+void __init pci_addr_cache_build(void)
+{
+	struct device_node *dn;
+	struct pci_dev *dev = NULL;
+
+	spin_lock_init(&pci_io_addr_cache_root.piar_lock);
+
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		/* Ignore PCI bridges */
+		if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+			continue;
+
+		pci_addr_cache_insert_device(dev);
+
+		dn = pci_device_to_OF_node(dev);
+		pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
+		PCI_DN(dn)->pcidev = dev;
+	}
+
+#ifdef DEBUG
+	/* Verify tree built up above, echo back the list of addrs. */
+	pci_addr_cache_print(&pci_io_addr_cache_root);
+#endif
+}
+
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
new file mode 100644
index 0000000..6373372
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -0,0 +1,376 @@
+/*
+ * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
+ * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+ *
+ * All rights reserved.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * Send feedback to <linas@us.ibm.com>
+ *
+ */
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/pci.h>
+#include <asm/eeh.h>
+#include <asm/eeh_event.h>
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+
+
+static inline const char * pcid_name (struct pci_dev *pdev)
+{
+	if (pdev->dev.driver)
+		return pdev->dev.driver->name;
+	return "";
+}
+
+#ifdef DEBUG
+static void print_device_node_tree (struct pci_dn *pdn, int dent)
+{
+	int i;
+	if (!pdn) return;
+	for (i=0;i<dent; i++)
+		printk(" ");
+	printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n",
+		pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr,
+		pdn->eeh_pe_config_addr, pdn->node->full_name);
+	dent += 3;
+	struct device_node *pc = pdn->node->child;
+	while (pc) {
+		print_device_node_tree(PCI_DN(pc), dent);
+		pc = pc->sibling;
+	}
+}
+#endif
+
+/** 
+ * irq_in_use - return true if this irq is being used 
+ */
+static int irq_in_use(unsigned int irq)
+{
+	int rc = 0;
+	unsigned long flags;
+   struct irq_desc *desc = irq_desc + irq;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	if (desc->action)
+		rc = 1;
+	spin_unlock_irqrestore(&desc->lock, flags);
+	return rc;
+}
+
+/* ------------------------------------------------------- */
+/** eeh_report_error - report an EEH error to each device,
+ *  collect up and merge the device responses.
+ */
+
+static void eeh_report_error(struct pci_dev *dev, void *userdata)
+{
+	enum pci_ers_result rc, *res = userdata;
+	struct pci_driver *driver = dev->driver;
+
+	dev->error_state = pci_channel_io_frozen;
+
+	if (!driver)
+		return;
+
+	if (irq_in_use (dev->irq)) {
+		struct device_node *dn = pci_device_to_OF_node(dev);
+		PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+		disable_irq_nosync(dev->irq);
+	}
+	if (!driver->err_handler)
+		return;
+	if (!driver->err_handler->error_detected)
+		return;
+
+	rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);
+	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+	if (*res == PCI_ERS_RESULT_NEED_RESET) return;
+	if (*res == PCI_ERS_RESULT_DISCONNECT &&
+	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
+}
+
+/** eeh_report_reset -- tell this device that the pci slot
+ *  has been reset.
+ */
+
+static void eeh_report_reset(struct pci_dev *dev, void *userdata)
+{
+	struct pci_driver *driver = dev->driver;
+	struct device_node *dn = pci_device_to_OF_node(dev);
+
+	if (!driver)
+		return;
+
+	if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+		PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+		enable_irq(dev->irq);
+	}
+	if (!driver->err_handler)
+		return;
+	if (!driver->err_handler->slot_reset)
+		return;
+
+	driver->err_handler->slot_reset(dev);
+}
+
+static void eeh_report_resume(struct pci_dev *dev, void *userdata)
+{
+	struct pci_driver *driver = dev->driver;
+
+	dev->error_state = pci_channel_io_normal;
+
+	if (!driver)
+		return;
+	if (!driver->err_handler)
+		return;
+	if (!driver->err_handler->resume)
+		return;
+
+	driver->err_handler->resume(dev);
+}
+
+static void eeh_report_failure(struct pci_dev *dev, void *userdata)
+{
+	struct pci_driver *driver = dev->driver;
+
+	dev->error_state = pci_channel_io_perm_failure;
+
+	if (!driver)
+		return;
+
+	if (irq_in_use (dev->irq)) {
+		struct device_node *dn = pci_device_to_OF_node(dev);
+		PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+		disable_irq_nosync(dev->irq);
+	}
+	if (!driver->err_handler)
+		return;
+	if (!driver->err_handler->error_detected)
+		return;
+	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
+}
+
+/* ------------------------------------------------------- */
+/**
+ * handle_eeh_events -- reset a PCI device after hard lockup.
+ *
+ * pSeries systems will isolate a PCI slot if the PCI-Host
+ * bridge detects address or data parity errors, DMA's
+ * occuring to wild addresses (which usually happen due to
+ * bugs in device drivers or in PCI adapter firmware).
+ * Slot isolations also occur if #SERR, #PERR or other misc
+ * PCI-related errors are detected.
+ *
+ * Recovery process consists of unplugging the device driver
+ * (which generated hotplug events to userspace), then issuing
+ * a PCI #RST to the device, then reconfiguring the PCI config
+ * space for all bridges & devices under this slot, and then
+ * finally restarting the device drivers (which cause a second
+ * set of hotplug events to go out to userspace).
+ */
+
+/**
+ * eeh_reset_device() -- perform actual reset of a pci slot
+ * Args: bus: pointer to the pci bus structure corresponding
+ *            to the isolated slot. A non-null value will
+ *            cause all devices under the bus to be removed
+ *            and then re-added.
+ *     pe_dn: pointer to a "Partionable Endpoint" device node.
+ *            This is the top-level structure on which pci
+ *            bus resets can be performed.
+ */
+
+static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
+{
+	int rc;
+	if (bus)
+		pcibios_remove_pci_devices(bus);
+
+	/* Reset the pci controller. (Asserts RST#; resets config space).
+	 * Reconfigure bridges and devices. Don't try to bring the system
+	 * up if the reset failed for some reason. */
+	rc = rtas_set_slot_reset(pe_dn);
+	if (rc)
+		return rc;
+
+ 	/* New-style config addrs might be shared across multiple devices,
+ 	 * Walk over all functions on this device */
+ 	if (pe_dn->eeh_pe_config_addr) {
+ 		struct device_node *pe = pe_dn->node;
+ 		pe = pe->parent->child;
+ 		while (pe) {
+ 			struct pci_dn *ppe = PCI_DN(pe);
+ 			if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
+ 				rtas_configure_bridge(ppe);
+ 				eeh_restore_bars(ppe);
+ 			}
+ 			pe = pe->sibling;
+ 		}
+ 	} else {
+ 		rtas_configure_bridge(pe_dn);
+ 		eeh_restore_bars(pe_dn);
+ 	}
+
+	/* Give the system 5 seconds to finish running the user-space
+	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes, 
+	 * this is a hack, but if we don't do this, and try to bring 
+	 * the device up before the scripts have taken it down, 
+	 * potentially weird things happen.
+	 */
+	if (bus) {
+		ssleep (5);
+		pcibios_add_pci_devices(bus);
+	}
+
+	return 0;
+}
+
+/* The longest amount of time to wait for a pci device
+ * to come back on line, in seconds.
+ */
+#define MAX_WAIT_FOR_RECOVERY 15
+
+void handle_eeh_events (struct eeh_event *event)
+{
+	struct device_node *frozen_dn;
+	struct pci_dn *frozen_pdn;
+	struct pci_bus *frozen_bus;
+	int rc = 0;
+	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
+
+	frozen_dn = find_device_pe(event->dn);
+	frozen_bus = pcibios_find_pci_bus(frozen_dn);
+
+	if (!frozen_dn) {
+		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
+		        pci_name(event->dev));
+		return;
+	}
+
+	/* There are two different styles for coming up with the PE.
+	 * In the old style, it was the highest EEH-capable device
+	 * which was always an EADS pci bridge.  In the new style,
+	 * there might not be any EADS bridges, and even when there are,
+	 * the firmware marks them as "EEH incapable". So another
+	 * two-step is needed to find the pci bus.. */
+	if (!frozen_bus)
+		frozen_bus = pcibios_find_pci_bus (frozen_dn->parent);
+
+	if (!frozen_bus) {
+		printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
+		        frozen_dn->full_name);
+		return;
+	}
+
+#if 0
+	/* We may get "permanent failure" messages on empty slots.
+	 * These are false alarms. Empty slots have no child dn. */
+	if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL))
+		return;
+#endif
+
+	frozen_pdn = PCI_DN(frozen_dn);
+	frozen_pdn->eeh_freeze_count++;
+	
+	if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
+		goto hard_fail;
+
+	/* If the reset state is a '5' and the time to reset is 0 (infinity)
+	 * or is more then 15 seconds, then mark this as a permanent failure.
+	 */
+	if ((event->state == pci_channel_io_perm_failure) &&
+	    ((event->time_unavail <= 0) ||
+	     (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000)))
+		goto hard_fail;
+
+	eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
+	printk(KERN_WARNING
+	   "EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
+		frozen_pdn->eeh_freeze_count,
+		pci_name (frozen_pdn->pcidev), 
+		pcid_name(frozen_pdn->pcidev));
+
+	/* Walk the various device drivers attached to this slot through
+	 * a reset sequence, giving each an opportunity to do what it needs
+	 * to accomplish the reset.  Each child gets a report of the
+	 * status ... if any child can't handle the reset, then the entire
+	 * slot is dlpar removed and added.
+	 */
+	pci_walk_bus(frozen_bus, eeh_report_error, &result);
+
+	/* If all device drivers were EEH-unaware, then shut
+	 * down all of the device drivers, and hope they
+	 * go down willingly, without panicing the system.
+	 */
+	if (result == PCI_ERS_RESULT_NONE) {
+		rc = eeh_reset_device(frozen_pdn, frozen_bus);
+		if (rc)
+			goto hard_fail;
+	}
+
+	/* If any device called out for a reset, then reset the slot */
+	if (result == PCI_ERS_RESULT_NEED_RESET) {
+		rc = eeh_reset_device(frozen_pdn, NULL);
+		if (rc)
+			goto hard_fail;
+		pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+	}
+
+	/* If all devices reported they can proceed, the re-enable PIO */
+	if (result == PCI_ERS_RESULT_CAN_RECOVER) {
+		/* XXX Not supported; we brute-force reset the device */
+		rc = eeh_reset_device(frozen_pdn, NULL);
+		if (rc)
+			goto hard_fail;
+		pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+	}
+
+	/* Tell all device drivers that they can resume operations */
+	pci_walk_bus(frozen_bus, eeh_report_resume, 0);
+
+	return;
+	
+hard_fail:
+	/*
+	 * About 90% of all real-life EEH failures in the field
+	 * are due to poorly seated PCI cards. Only 10% or so are
+	 * due to actual, failed cards.
+	 */
+	printk(KERN_ERR
+	   "EEH: PCI device %s - %s has failed %d times \n"
+	   "and has been permanently disabled.  Please try reseating\n"
+	   "this device or replacing it.\n",
+		pci_name (frozen_pdn->pcidev), 
+		pcid_name(frozen_pdn->pcidev), 
+		frozen_pdn->eeh_freeze_count);
+
+	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
+
+	/* Notify all devices that they're about to go down. */
+	pci_walk_bus(frozen_bus, eeh_report_failure, 0);
+
+	/* Shut down the device drivers for good. */
+	pcibios_remove_pci_devices(frozen_bus);
+}
+
+/* ---------- end of file ---------- */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 9249733..9a9961f 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <asm/eeh_event.h>
+#include <asm/ppc-pci.h>
 
 /** Overview:
  *  EEH error states may be detected within exception handlers;
@@ -37,31 +38,6 @@
 DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
 
 /**
- * eeh_panic - call panic() for an eeh event that cannot be handled.
- * The philosophy of this routine is that it is better to panic and
- * halt the OS than it is to risk possible data corruption by
- * oblivious device drivers that don't know better.
- *
- * @dev pci device that had an eeh event
- * @reset_state current reset state of the device slot
- */
-static void eeh_panic(struct pci_dev *dev, int reset_state)
-{
-	/*
-	 * Since the panic_on_oops sysctl is used to halt the system
-	 * in light of potential corruption, we can use it here.
-	 */
-	if (panic_on_oops) {
-		panic("EEH: MMIO failure (%d) on device:%s\n", reset_state,
-		      pci_name(dev));
-	}
-	else {
-		printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n",
-		       reset_state, pci_name(dev));
-	}
-}
-
-/**
  * eeh_event_handler - dispatch EEH events.  The detection of a frozen
  * slot can occur inside an interrupt, where it can be hard to do
  * anything about it.  The goal of this routine is to pull these
@@ -82,10 +58,16 @@
 
 		spin_lock_irqsave(&eeh_eventlist_lock, flags);
 		event = NULL;
+
+		/* Unqueue the event, get ready to process. */
 		if (!list_empty(&eeh_eventlist)) {
 			event = list_entry(eeh_eventlist.next, struct eeh_event, list);
 			list_del(&event->list);
 		}
+		
+		if (event)
+			eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+
 		spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
 		if (event == NULL)
 			break;
@@ -93,8 +75,11 @@
 		printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
 		       pci_name(event->dev));
 
-		eeh_panic (event->dev, event->state);
+		handle_eeh_events(event);
 
+		eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
+
+		pci_dev_put(event->dev);
 		kfree(event);
 	}
 
@@ -122,7 +107,7 @@
  */
 int eeh_send_failure_event (struct device_node *dn,
                             struct pci_dev *dev,
-                            int state,
+                            enum pci_channel_state state,
                             int time_unavail)
 {
 	unsigned long flags;
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index e719a49..98e940b 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -128,10 +128,9 @@
 # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
 # instructions.
 # gcc-3.4 and binutils-2.14 are a fatal combination.
-GCC_VERSION	:= $(call cc-version)
 
 checkbin:
-	@if test "$(GCC_VERSION)" = "0304" ; then \
+	@if test "$(call cc-version)" = "0304" ; then \
 		if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
 			echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
 			echo 'correctly with gcc-3.4 and your version of binutils.'; \
diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c
index a882b0d..84d65a8 100644
--- a/arch/ppc/kernel/machine_kexec.c
+++ b/arch/ppc/kernel/machine_kexec.c
@@ -28,12 +28,6 @@
 const extern unsigned char relocate_new_kernel[];
 const extern unsigned int relocate_new_kernel_size;
 
-/*
- * Provide a dummy crash_notes definition while crash dump arrives to ppc.
- * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- */
-note_buf_t crash_notes[NR_CPUS];
-
 void machine_shutdown(void)
 {
 	if (ppc_md.machine_shutdown)
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 6fe532d..b66602a 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -27,11 +27,6 @@
 	bool
 	default y
 
-config UID16
-	bool
-	default y
-	depends on !64BIT
-
 source "init/Kconfig"
 
 menu "Base setup"
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 4865e4b..9269b57 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -17,8 +17,7 @@
 obj-$(CONFIG_SMP)		+= smp.o
 
 obj-$(CONFIG_COMPAT)		+= compat_linux.o compat_signal.o \
-					compat_ioctl.o compat_wrapper.o \
-					compat_exec_domain.o
+					compat_wrapper.o compat_exec_domain.o
 obj-$(CONFIG_BINFMT_ELF32)	+= binfmt_elf32.o
 
 obj-$(CONFIG_VIRT_TIMER)	+= vtime.o
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
deleted file mode 100644
index 6504c4e..0000000
--- a/arch/s390/kernel/compat_ioctl.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- *  S390 version
- *    Copyright (C) 2000-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Gerhard Tonn (ton@de.ibm.com)
- *               Arnd Bergmann (arndb@de.ibm.com)
- *
- * Original implementation from 32-bit Sparc compat code which is
- * Copyright (C) 2000 Silicon Graphics, Inc.
- * Written by Ulf Carlsson (ulfc@engr.sgi.com) 
- */
-
-#include "compat_linux.h"
-#define INCLUDES
-#define CODE
-#include "../../../fs/compat_ioctl.c"
-#include <asm/dasd.h>
-#include <asm/cmb.h>
-#include <asm/tape390.h>
-#include <asm/ccwdev.h>
-#include "../../../drivers/s390/char/raw3270.h"
-
-static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
-				unsigned long arg, struct file *f)
-{
-	return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
-}
-
-static int do_ioctl32_ulong(unsigned int fd, unsigned int cmd,
-				unsigned long arg, struct file *f)
-{
-	return sys_ioctl(fd, cmd, arg);
-}
-
-#define COMPATIBLE_IOCTL(cmd)		HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_pointer)
-#define ULONG_IOCTL(cmd)		HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_ulong)
-#define HANDLE_IOCTL(cmd,handler)	{ (cmd), (ioctl_trans_handler_t)(handler), NULL },
-
-struct ioctl_trans ioctl_start[] = {
-/* architecture independent ioctls */
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "../../../fs/compat_ioctl.c"
-
-/* s390 only ioctls */
-COMPATIBLE_IOCTL(DASDAPIVER)
-COMPATIBLE_IOCTL(BIODASDDISABLE)
-COMPATIBLE_IOCTL(BIODASDENABLE)
-COMPATIBLE_IOCTL(BIODASDRSRV)
-COMPATIBLE_IOCTL(BIODASDRLSE)
-COMPATIBLE_IOCTL(BIODASDSLCK)
-COMPATIBLE_IOCTL(BIODASDINFO)
-COMPATIBLE_IOCTL(BIODASDINFO2)
-COMPATIBLE_IOCTL(BIODASDFMT)
-COMPATIBLE_IOCTL(BIODASDPRRST)
-COMPATIBLE_IOCTL(BIODASDQUIESCE)
-COMPATIBLE_IOCTL(BIODASDRESUME)
-COMPATIBLE_IOCTL(BIODASDPRRD)
-COMPATIBLE_IOCTL(BIODASDPSRD)
-COMPATIBLE_IOCTL(BIODASDGATTR)
-COMPATIBLE_IOCTL(BIODASDSATTR)
-COMPATIBLE_IOCTL(BIODASDCMFENABLE)
-COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
-COMPATIBLE_IOCTL(BIODASDREADALLCMB)
-
-COMPATIBLE_IOCTL(TUBICMD)
-COMPATIBLE_IOCTL(TUBOCMD)
-COMPATIBLE_IOCTL(TUBGETI)
-COMPATIBLE_IOCTL(TUBGETO)
-COMPATIBLE_IOCTL(TUBSETMOD)
-COMPATIBLE_IOCTL(TUBGETMOD)
-
-COMPATIBLE_IOCTL(TAPE390_DISPLAY)
-
-/* s390 doesn't need handlers here */
-COMPATIBLE_IOCTL(TIOCGSERIAL)
-COMPATIBLE_IOCTL(TIOCSSERIAL)
-};
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 41b197a..cd3b3c3 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -1014,38 +1014,6 @@
 }
 
 /*
- * Wrapper function for sys_timer_create.
- */
-extern asmlinkage long
-sys_timer_create(clockid_t, struct sigevent *, timer_t *);
-
-asmlinkage long
-sys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32,
-		timer_t *timer_id)
-{
-	struct sigevent se;
-	timer_t ktimer_id;
-	mm_segment_t old_fs;
-	long ret;
-
-	if (se32 == NULL)
-		return sys_timer_create(which_clock, NULL, timer_id);
-
-	if (get_compat_sigevent(&se, se32))
-		return -EFAULT;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_timer_create(which_clock, &se, &ktimer_id);
-	set_fs(old_fs);
-
-	if (!ret)
-		ret = put_user (ktimer_id, timer_id);
-
-	return ret;
-}
-
-/*
  * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64.
  * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}
  * because the 31 bit values differ from the 64 bit values.
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 23fe94e..cfde190 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1289,7 +1289,7 @@
 	lgfr	%r2,%r2			# timer_t (int)
 	llgtr	%r3,%r3			# struct compat_sigevent *
 	llgtr	%r4,%r4			# timer_t *
-	jg	sys32_timer_create
+	jg	compat_sys_timer_create
 
 	.globl	sys32_timer_settime_wrapper
 sys32_timer_settime_wrapper:
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
index 7bd169c..926ccee 100644
--- a/arch/s390/kernel/crash.c
+++ b/arch/s390/kernel/crash.c
@@ -10,8 +10,6 @@
 #include <linux/threads.h>
 #include <linux/kexec.h>
 
-note_buf_t crash_notes[NR_CPUS];
-
 void machine_crash_shutdown(struct pt_regs *regs)
 {
 }
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index a942bf2..7dd58f8 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -352,27 +352,6 @@
 	return 1;
 }
 
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-
-/* changed the size calculations - should hopefully work better. lbt */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = regs->gprs[15] & ~(PAGE_SIZE - 1);
-	dump->u_tsize = current->mm->end_code >> PAGE_SHIFT;
-	dump->u_dsize = (current->mm->brk + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-	if (dump->start_stack < TASK_SIZE)
-		dump->u_ssize = (TASK_SIZE - dump->start_stack) >> PAGE_SHIFT;
-	memcpy(&dump->regs, regs, sizeof(s390_regs));
-	dump_fpu (regs, &dump->regs.fp_regs);
-	dump->regs.per_info = current->thread.per_info;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stack_frame *sf, *low, *high;
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index bee654a..4176c77 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -10,7 +10,6 @@
 #include <linux/smp.h>
 #include <linux/syscalls.h>
 #include <linux/interrupt.h>
-#include <linux/ioctl32.h>
 #include <asm/checksum.h>
 #include <asm/cpcmd.h>
 #include <asm/delay.h>
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index fd4f240..8a2bea3 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -305,26 +305,6 @@
 	return 0;
 }
 
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-	dump->magic = CMAGIC;
-	dump->start_code = current->mm->start_code;
-	dump->start_data  = current->mm->start_data;
-	dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
-	dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
-	dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
-	dump->u_ssize = (current->mm->start_stack - dump->start_stack +
-			 PAGE_SIZE - 1) >> PAGE_SHIFT;
-	/* Debug registers will come here. */
-
-	dump->regs = *regs;
-
-	dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
-}
-
 /* Tracing by user break controller.  */
 static void
 ubc_set_tracing(int asid, unsigned long pc)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 6954fd6..1cf94a6 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -21,14 +21,12 @@
 #include <asm/cacheflush.h>
 #include <asm/checksum.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 extern struct hw_interrupt_type no_irq_type;
 
 EXPORT_SYMBOL(sh_mv);
 
 /* platform dependent support */
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(enable_irq);
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index fb35b45..07b172d 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -17,10 +17,6 @@
 	bool
 	default y
 
-config UID16
-	bool
-	default y
-
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
index b95d041..419b5a7 100644
--- a/arch/sh64/kernel/process.c
+++ b/arch/sh64/kernel/process.c
@@ -775,26 +775,6 @@
 	return 0;
 }
 
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-	dump->magic = CMAGIC;
-	dump->start_code = current->mm->start_code;
-	dump->start_data  = current->mm->start_data;
-	dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
-	dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
-	dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
-	dump->u_ssize = (current->mm->start_stack - dump->start_stack +
-			 PAGE_SIZE - 1) >> PAGE_SHIFT;
-	/* Debug registers will come here. */
-
-	dump->regs = *regs;
-
-	dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
-}
-
 asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
 			unsigned long r4, unsigned long r5,
 			unsigned long r6, unsigned long r7,
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index 0b5497d..472b450 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -29,7 +29,6 @@
 #include <asm/delay.h>
 #include <asm/irq.h>
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 
 #if 0
@@ -41,7 +40,6 @@
 #endif
 
 /* platform dependent support */
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(enable_irq);
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 1c8fd0f..0b0d492 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -82,8 +82,6 @@
 extern int __muldi3(int, int);
 extern int __divdi3(int, int);
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 /* Private functions with odd calling conventions. */
 extern void ___atomic24_add(void);
 extern void ___atomic24_sub(void);
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 6f00ab8..83d67eb 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -16,7 +16,7 @@
 obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o
 obj-$(CONFIG_SMP)	 += smp.o trampoline.o
-obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o
+obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
 obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
 obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
 obj-$(CONFIG_MODULES) += module.o
@@ -40,5 +40,3 @@
 
 head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \
 	etrap.S rtrap.S winfixup.S entry.S
-
-CFLAGS_ioctl32.o += -Ifs/
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index edf52d0..202a80c 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -36,8 +36,6 @@
 static int load_aout32_library(struct file*);
 static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 static struct linux_binfmt aout32_format = {
 	NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump,
 	PAGE_SIZE
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
deleted file mode 100644
index 196b208..0000000
--- a/arch/sparc64/kernel/ioctl32.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $Id: ioctl32.c,v 1.136 2002/01/14 09:49:52 davem Exp $
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 2003  Pavel Machek (pavel@suse.cz)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#define INCLUDES
-#include "compat_ioctl.c"
-#include <linux/syscalls.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define COMPATIBLE_IOCTL(cmd)		HANDLE_IOCTL((cmd),sys_ioctl)
-#define HANDLE_IOCTL(cmd,handler)	{ (cmd), (ioctl_trans_handler_t)(handler), NULL },
-#define IOCTL_TABLE_START \
-	struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
-	};
-
-IOCTL_TABLE_START
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-#if 0
-HANDLE_IOCTL(RTC32_IRQP_READ, do_rtc_ioctl)
-HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl)
-HANDLE_IOCTL(RTC32_EPOCH_READ, do_rtc_ioctl)
-HANDLE_IOCTL(RTC32_EPOCH_SET, do_rtc_ioctl)
-#endif
-/* take care of sizeof(sizeof()) breakage */
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index a97b0f0..ff5e9d5 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -43,14 +43,10 @@
 
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
-	return 0;
-}
-
-void __kprobes arch_copy_kprobe(struct kprobe *p)
-{
 	p->ainsn.insn[0] = *p->addr;
 	p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
 	p->opcode = *p->addr;
+	return 0;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -65,10 +61,6 @@
 	flushi(p->addr);
 }
 
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-}
-
 static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index fb7a537..d177d7e 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -94,7 +94,6 @@
 
 extern int __ashrdi3(int, int);
 
-extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
 
 extern unsigned long phys_base;
@@ -241,7 +240,6 @@
 EXPORT_SYMBOL(_sigpause_common);
 EXPORT_SYMBOL(verify_compat_iovec);
 
-EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(pte_alloc_one_kernel);
 #ifndef CONFIG_SMP
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 7f6239e..de342ee 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1120,39 +1120,3 @@
 	return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
 				  buf, len);
 }
-
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock,
-		 struct sigevent __user *timer_event_spec,
-		 timer_t __user *created_timer_id);
-
-long
-sys32_timer_create(u32 clock, struct compat_sigevent __user *se32,
-		   timer_t __user *timer_id)
-{
-	struct sigevent se;
-	mm_segment_t oldfs;
-	timer_t t;
-	long err;
-
-	if (se32 == NULL)
-		return sys_timer_create(clock, NULL, timer_id);
-
-	if (get_compat_sigevent(&se, se32))
-		return -EFAULT;
-
-	if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
-		return -EFAULT;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_timer_create(clock,
-			       (struct sigevent __user *) &se,
-			       (timer_t __user *) &t);
-	set_fs(oldfs);
-
-	if (!err)
-		err = __put_user (t, timer_id);
-
-	return err;
-}
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 4821ef1..98d24bc 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -73,7 +73,7 @@
 /*250*/	.word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
 	.word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
-	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
+	.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 	.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
 /*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index cd13b91..ab0d0b1 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -186,9 +186,6 @@
 		}
 	}
 
-	if((tty->flip.flag_buf_ptr == NULL) ||
-	   (tty->flip.char_buf_ptr == NULL))
-		return;
 	tty_insert_flip_char(tty, ch, TTY_NORMAL);
 }
 
@@ -653,8 +650,7 @@
 		chan = list_entry(ele, struct chan, list);
 		if(!chan->input || (chan->ops->read == NULL)) continue;
 		do {
-			if((tty != NULL) &&
-			   (tty->flip.count >= TTY_FLIPBUF_SIZE)){
+			if (tty && !tty_buffer_request_room(tty, 1)) {
 				schedule_delayed_work(task, 1);
 				goto out;
 			}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 11f518a..8fa2ae7 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -99,7 +99,8 @@
 	set_interval(ITIMER_REAL);
 }
 
-extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+extern void ktime_get_ts(struct timespec *ts);
+#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
 
 void time_init(void)
 {
@@ -114,8 +115,8 @@
 	wall_to_monotonic.tv_nsec = -now.tv_nsec;
 }
 
-/* Declared in linux/time.h, which can't be included here */
-extern void clock_was_set(void);
+/* Defined in linux/ktimer.h, which can't be included here */
+#define clock_was_set()		do { } while (0)
 
 void do_gettimeofday(struct timeval *tv)
 {
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
index 39cf247..062ffa0 100644
--- a/arch/v850/kernel/process.c
+++ b/arch/v850/kernel/process.c
@@ -164,30 +164,6 @@
 }
 
 /*
- * fill in the user structure for a core dump..
- */
-void dump_thread (struct pt_regs *regs, struct user *dump)
-{
-#if 0  /* Later.  XXX */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = regs->gpr[GPR_SP];
-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
-	dump->u_dsize = ((unsigned long) (current->mm->brk +
-					  (PAGE_SIZE-1))) >> PAGE_SHIFT;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-
-	if (dump->start_stack < TASK_SIZE)
-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
-	dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
-	dump->regs = *regs;
-	dump->u_fpvalid = 0;
-#endif
-}
-
-/*
  * sys_execve() executes a new program.
  */
 int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 0ca6490..8ffc29c 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -21,8 +21,6 @@
 EXPORT_SYMBOL (trap_table);
 
 /* platform dependent support */
-extern void dump_thread (struct pt_regs *, struct user *);
-EXPORT_SYMBOL (dump_thread);
 EXPORT_SYMBOL (kernel_thread);
 EXPORT_SYMBOL (enable_irq);
 EXPORT_SYMBOL (disable_irq);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 4f3e925..348b4a0 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -399,17 +399,6 @@
 	   Additional support for AMD specific MCE features such as
 	   the DRAM Error Threshold.
 
-config PHYSICAL_START
-	hex "Physical address where the kernel is loaded" if EMBEDDED
-	default "0x100000"
-	help
-	  This gives the physical address where the kernel is loaded.
-	  Primarily used in the case of kexec on panic where the
-	  fail safe kernel needs to run at a different address than
-	  the panic-ed kernel.
-
-	  Don't change this unless you know what you are doing.
-
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -427,6 +416,31 @@
 	  support.  As of this writing the exact hardware interface is
 	  strongly in flux, so no good recommendation can be made.
 
+config CRASH_DUMP
+	bool "kernel crash dumps (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+		Generate crash dump after being started by kexec.
+
+config PHYSICAL_START
+	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+	default "0x1000000" if CRASH_DUMP
+	default "0x100000"
+	help
+	  This gives the physical address where the kernel is loaded. Normally
+	  for regular kernels this value is 0x100000 (1MB). But in the case
+	  of kexec on panic the fail safe kernel needs to run at a different
+	  address than the panic-ed kernel. This option is used to set the load
+	  address for kernels used to capture crash dump on being kexec'ed
+	  after panic. The default value for crash dump kernels is
+	  0x1000000 (16MB). This can also be set based on the "X" value as
+	  specified in the "crashkernel=YM@XM" command line boot parameter
+	  passed to the panic-ed kernel. Typically this parameter is set as
+	  crashkernel=64M@16M. Please take a look at
+	  Documentation/kdump/kdump.txt for more details about crash dumps.
+
+	  Don't change this unless you know what you are doing.
+
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index a9cd42e..51d8328 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -80,9 +80,12 @@
 bzdisk: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
 
-install fdimage fdimage144 fdimage288: vmlinux
+fdimage fdimage144 fdimage288: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
 
+install:
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ 
+
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index 18c6e91..29f8396 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -98,5 +98,5 @@
 	cp System.map $(INSTALL_PATH)/
 	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
 
-install: $(BOOTIMAGE)
+install:
 	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
index 198af15..baaa236 100644
--- a/arch/x86_64/boot/install.sh
+++ b/arch/x86_64/boot/install.sh
@@ -1,40 +1,2 @@
 #!/bin/sh
-#
-# arch/x86_64/boot/install.sh
-#
-# 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) 1995 by Linus Torvalds
-#
-# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
-#
-# "make install" script for i386 architecture
-#
-# Arguments:
-#   $1 - kernel version
-#   $2 - kernel image file
-#   $3 - kernel map file
-#   $4 - default install path (blank if root directory)
-#
-
-# User may have a custom install script
-
-if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
-if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
-
-# Default install - same as make zlilo
-
-if [ -f $4/vmlinuz ]; then
-	mv $4/vmlinuz $4/vmlinuz.old
-fi
-
-if [ -f $4/System.map ]; then
-	mv $4/System.map $4/System.old
-fi
-
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
-
-if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+. $srctree/arch/i386/boot/install.sh
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index f76217d..051608d 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -2,8 +2,7 @@
 # Makefile for the ia32 kernel emulation subsystem.
 #
 
-obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \
-	ia32_signal.o tls32.o \
+obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \
 	ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o
 
 sysv-$(CONFIG_SYSVIPC) := ipc32.o
@@ -29,4 +28,3 @@
 
 AFLAGS_vsyscall-sysenter.o = -m32
 AFLAGS_vsyscall-syscall.o = -m32
-CFLAGS_ia32_ioctl.o += -Ifs/
diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
deleted file mode 100644
index e335bd0..0000000
--- a/arch/x86_64/ia32/ia32_ioctl.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $Id: ia32_ioctl.c,v 1.25 2002/10/11 07:17:06 ak Exp $
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#define INCLUDES
-#include <linux/syscalls.h>
-#include "compat_ioctl.c"
-#include <asm/ia32.h>
-
-#define CODE
-#include "compat_ioctl.c"
-  
-#define RTC_IRQP_READ32	_IOR('p', 0x0b, unsigned int)	 /* Read IRQ rate   */
-#define RTC_IRQP_SET32	_IOW('p', 0x0c, unsigned int)	 /* Set IRQ rate    */
-#define RTC_EPOCH_READ32	_IOR('p', 0x0d, unsigned)	 /* Read epoch      */
-#define RTC_EPOCH_SET32		_IOW('p', 0x0e, unsigned)	 /* Set epoch       */
-
-static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg) 
-{ 
-	unsigned long val;
-	mm_segment_t oldfs = get_fs(); 
-	int ret; 
-	
-	switch (cmd) { 
-	case RTC_IRQP_READ32: 
-		set_fs(KERNEL_DS); 
-		ret = sys_ioctl(fd, RTC_IRQP_READ, (unsigned long)&val); 
-		set_fs(oldfs); 
-		if (!ret)
-			ret = put_user(val, (unsigned int __user *) arg); 
-		return ret; 
-
-	case RTC_IRQP_SET32: 
-		cmd = RTC_IRQP_SET; 
-		break; 
-
-	case RTC_EPOCH_READ32:
-		set_fs(KERNEL_DS); 
-		ret = sys_ioctl(fd, RTC_EPOCH_READ, (unsigned long) &val); 
-		set_fs(oldfs); 
-		if (!ret)
-			ret = put_user(val, (unsigned int __user *) arg); 
-		return ret; 
-
-	case RTC_EPOCH_SET32:
-		cmd = RTC_EPOCH_SET; 
-		break; 
-	} 
-	return sys_ioctl(fd,cmd,arg); 
-} 
-
-
-#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) }, 
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
-
-struct ioctl_trans ioctl_start[] = { 
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-
-/* And these ioctls need translation */
-/* realtime device */
-HANDLE_IOCTL(RTC_IRQP_READ,  rtc32_ioctl)
-HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl)
-HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl)
-HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl)
-HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl)
-/* take care of sizeof(sizeof()) breakage */
-}; 
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
-
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 1f0ff5a..2ff07b4 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -608,7 +608,7 @@
 	.quad sys_epoll_wait
 	.quad sys_remap_file_pages
 	.quad sys_set_tid_address
-	.quad sys32_timer_create
+	.quad compat_sys_timer_create
 	.quad compat_sys_timer_settime	/* 260 */
 	.quad compat_sys_timer_gettime
 	.quad sys_timer_getoverrun
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 5389df6..54481af 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -969,25 +969,6 @@
 	return sys_kill(pid, sig);
 }
  
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock,
-		 struct sigevent __user *timer_event_spec,
-		 timer_t __user * created_timer_id);
-
-long
-sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
-{
-	struct sigevent __user *p = NULL;
-	if (se32) { 
-		struct sigevent se;
-		p = compat_alloc_user_space(sizeof(struct sigevent));
-		if (get_compat_sigevent(&se, se32) ||
-		    copy_to_user(p, &se, sizeof(se)))
-			return -EFAULT;
-	} 
-	return sys_timer_create(clock, p, timer_id);
-} 
-
 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
 			__u32 len_low, __u32 len_high, int advice)
 { 
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index fe4cbd1..12bc540 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o \
 		genapic.o genapic_cluster.o genapic_flat.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_PM)		+= suspend.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index 535e044..4e6c3b7 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -11,19 +11,156 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 #include <linux/reboot.h>
 #include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
 
 #include <asm/processor.h>
 #include <asm/hardirq.h>
 #include <asm/nmi.h>
 #include <asm/hw_irq.h>
+#include <asm/mach_apic.h>
 
-note_buf_t crash_notes[NR_CPUS];
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu;
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type,
+						void *data, size_t data_len)
+{
+	struct elf_note note;
+
+	note.n_namesz = strlen(name) + 1;
+	note.n_descsz = data_len;
+	note.n_type   = type;
+	memcpy(buf, &note, sizeof(note));
+	buf += (sizeof(note) +3)/4;
+	memcpy(buf, name, note.n_namesz);
+	buf += (note.n_namesz + 3)/4;
+	memcpy(buf, data, note.n_descsz);
+	buf += (note.n_descsz + 3)/4;
+
+	return buf;
+}
+
+static void final_note(u32 *buf)
+{
+	struct elf_note note;
+
+	note.n_namesz = 0;
+	note.n_descsz = 0;
+	note.n_type   = 0;
+	memcpy(buf, &note, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+	struct elf_prstatus prstatus;
+	u32 *buf;
+
+	if ((cpu < 0) || (cpu >= NR_CPUS))
+		return;
+
+	/* Using ELF notes here is opportunistic.
+	 * I need a well defined structure format
+	 * for the data I pass, and I need tags
+	 * on the data to indicate what information I have
+	 * squirrelled away.  ELF notes happen to provide
+	 * all of that that no need to invent something new.
+	 */
+
+	buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+
+	if (!buf)
+		return;
+
+	memset(&prstatus, 0, sizeof(prstatus));
+	prstatus.pr_pid = current->pid;
+	elf_core_copy_regs(&prstatus.pr_reg, regs);
+	buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+					sizeof(prstatus));
+	final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+	int cpu;
+
+	cpu = smp_processor_id();
+	crash_save_this_cpu(regs, cpu);
+}
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+{
+	/*
+	 * Don't do anything if this handler is invoked on crashing cpu.
+	 * Otherwise, system will completely hang. Crashing cpu can get
+	 * an NMI if system was initially booted with nmi_watchdog parameter.
+	 */
+	if (cpu == crashing_cpu)
+		return 1;
+	local_irq_disable();
+
+	crash_save_this_cpu(regs, cpu);
+	disable_local_APIC();
+	atomic_dec(&waiting_for_crash_ipi);
+	/* Assume hlt works */
+	for(;;)
+		asm("hlt");
+
+	return 1;
+}
+
+static void smp_send_nmi_allbutself(void)
+{
+	send_IPI_allbutself(APIC_DM_NMI);
+}
+
+/*
+ * This code is a best effort heuristic to get the
+ * other cpus to stop executing. So races with
+ * cpu hotplug shouldn't matter.
+ */
+
+static void nmi_shootdown_cpus(void)
+{
+	unsigned long msecs;
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	set_nmi_callback(crash_nmi_callback);
+
+	/*
+	 * Ensure the new callback function is set before sending
+	 * out the NMI
+	 */
+	wmb();
+
+	smp_send_nmi_allbutself();
+
+	msecs = 1000; /* Wait at most a second for the other cpus to stop */
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+		mdelay(1);
+		msecs--;
+	}
+	/* Leave the nmi callback set */
+	disable_local_APIC();
+}
+#else
+static void nmi_shootdown_cpus(void)
+{
+	/* There are no cpus to shootdown */
+}
+#endif
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
-	/* This function is only called after the system
+	/*
+	 * This function is only called after the system
 	 * has paniced or is otherwise in a critical state.
 	 * The minimum amount of code to allow a kexec'd kernel
 	 * to run successfully needs to happen here.
@@ -31,4 +168,19 @@
 	 * In practice this means shooting down the other cpus in
 	 * an SMP system.
 	 */
+	/* The kernel is broken so disable interrupts */
+	local_irq_disable();
+
+	/* Make a note of crashing cpu. Will be used in NMI callback.*/
+	crashing_cpu = smp_processor_id();
+	nmi_shootdown_cpus();
+
+	if(cpu_has_apic)
+		 disable_local_APIC();
+
+#if defined(CONFIG_X86_IO_APIC)
+	disable_IO_APIC();
+#endif
+
+	crash_save_self(regs);
 }
diff --git a/kernel/crash_dump.c b/arch/x86_64/kernel/crash_dump.c
similarity index 60%
rename from kernel/crash_dump.c
rename to arch/x86_64/kernel/crash_dump.c
index fccb27d..942deac 100644
--- a/kernel/crash_dump.c
+++ b/arch/x86_64/kernel/crash_dump.c
@@ -5,21 +5,12 @@
  *	Copyright (C) IBM Corporation, 2004. All rights reserved
  */
 
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
-#include <linux/proc_fs.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
 #include <linux/crash_dump.h>
 
-#include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/kexec.h>
+#include <asm/io.h>
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
-#ifndef HAVE_ARCH_COPY_OLDMEM_PAGE
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
@@ -34,31 +25,23 @@
  * in the current kernel. We stitch up a pte, similar to kmap_atomic.
  */
 ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
-				size_t csize, unsigned long offset, int userbuf)
+                               size_t csize, unsigned long offset, int userbuf)
 {
-	void *page, *vaddr;
+	void  *vaddr;
 
 	if (!csize)
 		return 0;
 
-	page = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
-	copy_page(page, vaddr);
-	kunmap_atomic(vaddr, KM_PTE0);
+	vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
 
 	if (userbuf) {
-		if (copy_to_user(buf, (page + offset), csize)) {
-			kfree(page);
+		if (copy_to_user(buf, (vaddr + offset), csize)) {
+			iounmap(vaddr);
 			return -EFAULT;
 		}
-	} else {
-		memcpy(buf, (page + offset), csize);
-	}
+	} else
+	memcpy(buf, (vaddr + offset), csize);
 
-	kfree(page);
+	iounmap(vaddr);
 	return csize;
 }
-#endif
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 17579a1..293cd71 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -559,6 +559,27 @@
 	end_user_pfn >>= PAGE_SHIFT;	
 } 
 
+void __init parse_memmapopt(char *p, char **from)
+{
+	unsigned long long start_at, mem_size;
+
+	mem_size = memparse(p, from);
+	p = *from;
+	if (*p == '@') {
+		start_at = memparse(p+1, from);
+		add_memory_region(start_at, mem_size, E820_RAM);
+	} else if (*p == '#') {
+		start_at = memparse(p+1, from);
+		add_memory_region(start_at, mem_size, E820_ACPI);
+	} else if (*p == '$') {
+		start_at = memparse(p+1, from);
+		add_memory_region(start_at, mem_size, E820_RESERVED);
+	} else {
+		end_user_pfn = (mem_size >> PAGE_SHIFT);
+	}
+	p = *from;
+}
+
 unsigned long pci_mem_start = 0xaeedbabe;
 
 /*
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index afe11f4..b7dc1f8 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -42,8 +42,8 @@
 #include <asm/pgtable.h>
 #include <asm/kdebug.h>
 
-static DECLARE_MUTEX(kprobe_mutex);
 void jprobe_return_end(void);
+static void __kprobes arch_copy_kprobe(struct kprobe *p);
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -69,12 +69,11 @@
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
 	/* insn: must be on special executable page on x86_64. */
-	down(&kprobe_mutex);
 	p->ainsn.insn = get_insn_slot();
-	up(&kprobe_mutex);
 	if (!p->ainsn.insn) {
 		return -ENOMEM;
 	}
+	arch_copy_kprobe(p);
 	return 0;
 }
 
@@ -181,7 +180,7 @@
 	return NULL;
 }
 
-void __kprobes arch_copy_kprobe(struct kprobe *p)
+static void __kprobes arch_copy_kprobe(struct kprobe *p)
 {
 	s32 *ripdisp;
 	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 64c4534..a0e0c9c 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -35,6 +35,7 @@
 #include <asm/processor.h>
 #include <linux/console.h>
 #include <linux/seq_file.h>
+#include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
@@ -275,6 +276,7 @@
 {
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
 	int len = 0;
+	int userdef = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
 	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
@@ -357,6 +359,28 @@
 		if (!memcmp(from, "mem=", 4))
 			parse_memopt(from+4, &from); 
 
+		if (!memcmp(from, "memmap=", 7)) {
+			/* exactmap option is for used defined memory */
+			if (!memcmp(from+7, "exactmap", 8)) {
+#ifdef CONFIG_CRASH_DUMP
+				/* If we are doing a crash dump, we
+				 * still need to know the real mem
+				 * size before original memory map is
+				 * reset.
+				 */
+				saved_max_pfn = e820_end_of_ram();
+#endif
+				from += 8+7;
+				end_pfn_map = 0;
+				e820.nr_map = 0;
+				userdef = 1;
+			}
+			else {
+				parse_memmapopt(from+7, &from);
+				userdef = 1;
+			}
+		}
+
 #ifdef CONFIG_NUMA
 		if (!memcmp(from, "numa=", 5))
 			numa_setup(from+5); 
@@ -395,6 +419,14 @@
 		}
 #endif
 
+#ifdef CONFIG_PROC_VMCORE
+		/* elfcorehdr= specifies the location of elf core header
+		 * stored by the crashed kernel. This option will be passed
+		 * by kexec loader to the capture kernel.
+		 */
+		else if(!memcmp(from, "elfcorehdr=", 11))
+			elfcorehdr_addr = memparse(from+11, &from);
+#endif
 	next_char:
 		c = *(from++);
 		if (!c)
@@ -403,6 +435,10 @@
 			break;
 		*(to++) = c;
 	}
+	if (userdef) {
+		printk(KERN_INFO "user-defined physical RAM map:\n");
+		e820_print_map("user");
+	}
 	*to = '\0';
 	*cmdline_p = command_line;
 }
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 4a54221..b7fd668 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -13,7 +13,6 @@
 #include <linux/string.h>
 #include <linux/syscalls.h>
 #include <linux/tty.h>
-#include <linux/ioctl32.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 7e841aa..7ee4a14 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -18,10 +18,6 @@
 	  with reasonable minimum requirements.  The Xtensa Linux project has
 	  a home page at <http://xtensa.sourceforge.net/>.
 
-config UID16
-	bool
-	default n
-
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
diff --git a/drivers/base/core.c b/drivers/base/core.c
index fd80599..6b355bd 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -161,8 +161,8 @@
 	return count;
 }
 
-/**
- *	device_subsys - structure to be registered with kobject core.
+/*
+ *	devices_subsys - structure to be registered with kobject core.
  */
 
 decl_subsys(devices, &ktype_device, &device_uevent_ops);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 281d267..07a7f97 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -83,6 +83,31 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+#ifdef CONFIG_KEXEC
+#include <linux/kexec.h>
+
+static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+	ssize_t rc;
+	unsigned long long addr;
+	int cpunum;
+
+	cpunum = cpu->sysdev.id;
+
+	/*
+	 * Might be reading other cpu's data based on which cpu read thread
+	 * has been scheduled. But cpu data (memory) is allocated once during
+	 * boot up and this data does not change there after. Hence this
+	 * operation should be safe. No locking required.
+	 */
+	addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+	rc = sprintf(buf, "%Lx\n", addr);
+	return rc;
+}
+static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+#endif
+
 /*
  * register_cpu - Setup a driverfs device for a CPU.
  * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to
@@ -108,6 +133,11 @@
 		register_cpu_control(cpu);
 	if (!error)
 		cpu_sys_devices[num] = &cpu->sysdev;
+
+#ifdef CONFIG_KEXEC
+	if (!error)
+		error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
+#endif
 	return error;
 }
 
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 573ff6c..613673b 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -279,6 +279,7 @@
 
 	tty->disc_data = hu;
 	hu->tty = tty;
+	tty->receive_room = 65536;
 
 	spin_lock_init(&hu->rx_lock);
 
@@ -348,20 +349,6 @@
 		hci_uart_tx_wakeup(hu);
 }
 
-/* hci_uart_tty_room()
- * 
- *    Callback function from tty driver. Return the amount of 
- *    space left in the receiver's buffer to decide if remote
- *    transmitter is to be throttled.
- *
- * Arguments:        tty    pointer to associated tty instance data
- * Return Value:    number of bytes left in receive buffer
- */
-static int hci_uart_tty_room (struct tty_struct *tty)
-{
-	return 65536;
-}
-
 /* hci_uart_tty_receive()
  * 
  *     Called by tty low level driver when receive data is
@@ -544,7 +531,6 @@
 	hci_uart_ldisc.write		= hci_uart_tty_write;
 	hci_uart_ldisc.ioctl		= hci_uart_tty_ioctl;
 	hci_uart_ldisc.poll		= hci_uart_tty_poll;
-	hci_uart_ldisc.receive_room	= hci_uart_tty_room;
 	hci_uart_ldisc.receive_buf	= hci_uart_tty_receive;
 	hci_uart_ldisc.write_wakeup	= hci_uart_tty_wakeup;
 	hci_uart_ldisc.owner		= THIS_MODULE;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index dd7e690..d6fcd0a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -80,7 +80,7 @@
 
 config COMPUTONE
 	tristate "Computone IntelliPort Plus serial support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD
 	---help---
 	  This driver supports the entire family of Intelliport II/Plus
 	  controllers with the exception of the MicroChannel controllers and
@@ -153,7 +153,7 @@
 
 config ESPSERIAL
 	tristate "Hayes ESP serial port support"
-	depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP && ISA_DMA_API
+	depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API
 	help
 	  This is a driver which supports Hayes ESP serial ports.  Both single
 	  port cards and multiport cards are supported.  Make sure to read
@@ -166,7 +166,7 @@
 
 config MOXA_INTELLIO
 	tristate "Moxa Intellio support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD
 	help
 	  Say Y here if you have a Moxa Intellio multiport serial card.
 
@@ -290,7 +290,7 @@
 
 config RIO
 	tristate "Specialix RIO system support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && !64BIT
 	help
 	  This is a driver for the Specialix RIO, a smart serial card which
 	  drives an outboard box that can support up to 128 ports.  Product
@@ -936,6 +936,15 @@
 
 	  If compiled as a module, it will be called scx200_gpio.
 
+config CS5535_GPIO
+	tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
+	depends on X86_32
+	help
+	  Give userspace access to the GPIO pins on the AMD CS5535 and
+	  CS5536 Geode companion devices.
+
+	  If compiled as a module, it will be called cs5535_gpio.
+
 config GPIO_VR41XX
 	tristate "NEC VR4100 series General-purpose I/O Unit support"
 	depends on CPU_VR41XX
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d973d14..503dd90 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -81,6 +81,7 @@
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
 obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
 obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
 obj-$(CONFIG_TELCLOCK) += tlclk.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a124f8c..869518e 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -116,7 +116,7 @@
 
 static struct serial_state rs_table[1];
 
-#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
+#define NR_PORTS ARRAY_SIZE(rs_table)
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
@@ -265,8 +265,9 @@
         int status;
 	int serdatr;
 	struct tty_struct *tty = info->tty;
-	unsigned char ch;
+	unsigned char ch, flag;
 	struct	async_icount *icount;
+	int oe = 0;
 
 	icount = &info->state->icount;
 
@@ -282,15 +283,12 @@
 	    status |= UART_LSR_OE;
 
 	ch = serdatr & 0xff;
-	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-	  goto ignore_char;
-	*tty->flip.char_buf_ptr = ch;
 	icount->rx++;
 
 #ifdef SERIAL_DEBUG_INTR
 	printk("DR%02x:%02x...", ch, status);
 #endif
-	*tty->flip.flag_buf_ptr = 0;
+	flag = TTY_NORMAL;
 
 	/*
 	 * We don't handle parity or frame errors - but I have left
@@ -319,7 +317,7 @@
 	   * should be ignored.
 	   */
 	  if (status & info->ignore_status_mask)
-	    goto ignore_char;
+	    goto out;
 
 	  status &= info->read_status_mask;
 
@@ -327,33 +325,28 @@
 #ifdef SERIAL_DEBUG_INTR
 	    printk("handling break....");
 #endif
-	    *tty->flip.flag_buf_ptr = TTY_BREAK;
+	    flag = TTY_BREAK;
 	    if (info->flags & ASYNC_SAK)
 	      do_SAK(tty);
 	  } else if (status & UART_LSR_PE)
-	    *tty->flip.flag_buf_ptr = TTY_PARITY;
+	    flag = TTY_PARITY;
 	  else if (status & UART_LSR_FE)
-	    *tty->flip.flag_buf_ptr = TTY_FRAME;
+	    flag = TTY_FRAME;
 	  if (status & UART_LSR_OE) {
 	    /*
 	     * Overrun is special, since it's
 	     * reported immediately, and doesn't
 	     * affect the current character
 	     */
-	    if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-	      tty->flip.count++;
-	      tty->flip.flag_buf_ptr++;
-	      tty->flip.char_buf_ptr++;
-	      *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-	    }
+	     oe = 1;
 	  }
 	}
-	tty->flip.flag_buf_ptr++;
-	tty->flip.char_buf_ptr++;
-	tty->flip.count++;
- ignore_char:
-
+	tty_insert_flip_char(tty, ch, flag);
+	if (oe == 1)
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	tty_flip_buffer_push(tty);
+out:
+	return;
 }
 
 static _INLINE_ void transmit_chars(struct async_struct *info)
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
new file mode 100644
index 0000000..5d72f50
--- /dev/null
+++ b/drivers/char/cs5535_gpio.c
@@ -0,0 +1,250 @@
+/*
+ * AMD CS5535/CS5536 GPIO driver.
+ * Allows a user space process to play with the GPIO pins.
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+
+#define NAME			"cs5535_gpio"
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO Pin Driver");
+MODULE_LICENSE("GPL");
+
+static int major;
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static ulong mask;
+module_param(mask, ulong, 0);
+MODULE_PARM_DESC(mask, "GPIO channel mask");
+
+#define MSR_LBAR_GPIO		0x5140000C
+
+static u32 gpio_base;
+
+static struct pci_device_id divil_pci[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+	{ } /* NULL entry */
+};
+
+static struct cdev cs5535_gpio_cdev;
+
+/* reserve 32 entries even though some aren't usable */
+#define CS5535_GPIO_COUNT	32
+
+/* IO block size */
+#define CS5535_GPIO_SIZE	256
+
+struct gpio_regmap {
+	u32	rd_offset;
+	u32	wr_offset;
+	char	on;
+	char	off;
+};
+static struct gpio_regmap rm[] =
+{
+	{ 0x30, 0x00, '1', '0' },	/* GPIOx_READ_BACK / GPIOx_OUT_VAL */
+	{ 0x20, 0x20, 'I', 'i' },	/* GPIOx_IN_EN */
+	{ 0x04, 0x04, 'O', 'o' },	/* GPIOx_OUT_EN */
+	{ 0x08, 0x08, 't', 'T' },	/* GPIOx_OUT_OD_EN */
+	{ 0x18, 0x18, 'P', 'p' },	/* GPIOx_OUT_PU_EN */
+	{ 0x1c, 0x1c, 'D', 'd' },	/* GPIOx_OUT_PD_EN */
+};
+
+
+/**
+ * Gets the register offset for the GPIO bank.
+ * Low (0-15) starts at 0x00, high (16-31) starts at 0x80
+ */
+static inline u32 cs5535_lowhigh_base(int reg)
+{
+	return (reg & 0x10) << 3;
+}
+
+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);
+	int	i, j;
+	u32	base = gpio_base + cs5535_lowhigh_base(m);
+	u32	m0, m1;
+	char	c;
+
+	/**
+	 * Creates the mask for atomic bit programming.
+	 * The high 16 bits and the low 16 bits are used to set the mask.
+	 * For example, GPIO 15 maps to 31,15: 0,1 => On; 1,0=> Off
+	 */
+	m1 = 1 << (m & 0x0F);
+	m0 = m1 << 16;
+
+	for (i = 0; i < len; ++i) {
+		if (get_user(c, data+i))
+			return -EFAULT;
+
+		for (j = 0; j < ARRAY_SIZE(rm); j++) {
+			if (c == rm[j].on) {
+				outl(m1, base + rm[j].wr_offset);
+				break;
+			} else if (c == rm[j].off) {
+				outl(m0, base + rm[j].wr_offset);
+				break;
+			}
+		}
+	}
+	*ppos = 0;
+	return len;
+}
+
+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	base = gpio_base + cs5535_lowhigh_base(m);
+	int	rd_bit = 1 << (m & 0x0f);
+	int	i;
+	char	ch;
+	ssize_t	count = 0;
+
+	if (*ppos >= ARRAY_SIZE(rm))
+		return 0;
+
+	for (i = *ppos; (i < (*ppos + len)) && (i < ARRAY_SIZE(rm)); i++) {
+		ch = (inl(base + rm[i].rd_offset) & rd_bit) ?
+		     rm[i].on : rm[i].off;
+
+		if (put_user(ch, buf+count))
+			return -EFAULT;
+
+		count++;
+	}
+
+	/* add a line-feed if there is room */
+	if ((i == ARRAY_SIZE(rm)) && (count < len)) {
+		put_user('\n', buf + count);
+		count++;
+	}
+
+	*ppos += count;
+	return count;
+}
+
+static int cs5535_gpio_open(struct inode *inode, struct file *file)
+{
+	u32 m = iminor(inode);
+
+	/* the mask says which pins are usable by this driver */
+	if ((mask & (1 << m)) == 0)
+		return -EINVAL;
+
+	return nonseekable_open(inode, file);
+}
+
+static struct file_operations cs5535_gpio_fops = {
+	.owner	= THIS_MODULE,
+	.write	= cs5535_gpio_write,
+	.read	= cs5535_gpio_read,
+	.open	= cs5535_gpio_open
+};
+
+static int __init cs5535_gpio_init(void)
+{
+	dev_t	dev_id;
+	u32	low, hi;
+	int	retval;
+
+	if (pci_dev_present(divil_pci) == 0) {
+		printk(KERN_WARNING NAME ": DIVIL not found\n");
+		return -ENODEV;
+	}
+
+	/* Grab the GPIO I/O range */
+	rdmsr(MSR_LBAR_GPIO, low, hi);
+
+	/* Check the mask and whether GPIO is enabled (sanity check) */
+	if (hi != 0x0000f001) {
+		printk(KERN_WARNING NAME ": GPIO not enabled\n");
+		return -ENODEV;
+	}
+
+	/* Mask off the IO base address */
+	gpio_base = low & 0x0000ff00;
+
+	/**
+	 * Some GPIO pins
+	 *  31-29,23 : reserved (always mask out)
+	 *  28       : Power Button
+	 *  26       : PME#
+	 *  22-16    : LPC
+	 *  14,15    : SMBus
+	 *  9,8      : UART1
+	 *  7        : PCI INTB
+	 *  3,4      : UART2/DDC
+	 *  2        : IDE_IRQ0
+	 *  0        : PCI INTA
+	 *
+	 * If a mask was not specified, be conservative and only allow:
+	 *  1,2,5,6,10-13,24,25,27
+	 */
+	if (mask != 0)
+		mask &= 0x1f7fffff;
+	else
+		mask = 0x0b003c66;
+
+	if (request_region(gpio_base, CS5535_GPIO_SIZE, NAME) == 0) {
+		printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n");
+		return -ENODEV;
+	}
+
+	if (major) {
+		dev_id = MKDEV(major, 0);
+		retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,
+						NAME);
+	} else {
+		retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT,
+					     NAME);
+		major = MAJOR(dev_id);
+	}
+
+	if (retval) {
+		release_region(gpio_base, CS5535_GPIO_SIZE);
+		return -1;
+	}
+
+	printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
+	       gpio_base, mask, major);
+
+	cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
+	cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
+
+	return 0;
+}
+
+static void __exit cs5535_gpio_cleanup(void)
+{
+	dev_t dev_id = MKDEV(major, 0);
+	unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
+	if (gpio_base != 0)
+		release_region(gpio_base, CS5535_GPIO_SIZE);
+}
+
+module_init(cs5535_gpio_init);
+module_exit(cs5535_gpio_cleanup);
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index c7f818c..39c61a7 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -641,6 +641,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/major.h>
 #include <linux/string.h>
@@ -723,7 +724,7 @@
         0xDE000,
         0,0,0,0,0,0,0,0
 };
-#define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
+#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
 
 #ifdef MODULE
 static long maddr[NR_CARDS] = { 0, };
@@ -1086,7 +1087,7 @@
   int had_work;
   int mdm_change;
   int mdm_status;
-
+  int len;
     if((cinfo = (struct cyclades_card *)dev_id) == 0){
 #ifdef CY_DEBUG_INTERRUPTS
 	printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
@@ -1163,63 +1164,43 @@
 				info->icount.rx++;
                                 continue;
                             }
-                            if (tty->flip.count < TTY_FLIPBUF_SIZE){
-                                tty->flip.count++;
+                            if (tty_buffer_request_room(tty, 1)) {
                                 if (data & info->read_status_mask){
                                     if(data & CyBREAK){
-                                        *tty->flip.flag_buf_ptr++ =
-	    						    TTY_BREAK;
-                                        *tty->flip.char_buf_ptr++ =
-					  cy_readb(base_addr+(CyRDSR<<index));
+                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_BREAK);
 					info->icount.rx++;
                                         if (info->flags & ASYNC_SAK){
                                             do_SAK(tty);
                                         }
                                     }else if(data & CyFRAME){
-                                        *tty->flip.flag_buf_ptr++ =
-							    TTY_FRAME;
-                                        *tty->flip.char_buf_ptr++ =
-					  cy_readb(base_addr+(CyRDSR<<index));
+                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
 					info->icount.rx++;
 					info->idle_stats.frame_errs++;
                                     }else if(data & CyPARITY){
-                                        *tty->flip.flag_buf_ptr++ =
-							    TTY_PARITY;
-                                        *tty->flip.char_buf_ptr++ =
-					  cy_readb(base_addr+(CyRDSR<<index));
+					/* Pieces of seven... */
+                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_PARITY);
 					info->icount.rx++;
 					info->idle_stats.parity_errs++;
                                     }else if(data & CyOVERRUN){
-                                        *tty->flip.flag_buf_ptr++ =
-							    TTY_OVERRUN;
-                                        *tty->flip.char_buf_ptr++ = 0;
+                                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 					info->icount.rx++;
                                         /* If the flip buffer itself is
                                            overflowing, we still lose
                                            the next incoming character.
                                          */
-                                        if(tty->flip.count
-					           < TTY_FLIPBUF_SIZE){
-                                            tty->flip.count++;
-                                            *tty->flip.flag_buf_ptr++ =
-							     TTY_NORMAL;
-                                           *tty->flip.char_buf_ptr++ =
-					    cy_readb(base_addr+(CyRDSR<<index));
-					    info->icount.rx++;
-                                        }
+                                        tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
+				        info->icount.rx++;
 					info->idle_stats.overruns++;
                                     /* These two conditions may imply */
                                     /* a normal read should be done. */
                                     /* }else if(data & CyTIMEOUT){ */
                                     /* }else if(data & CySPECHAR){ */
-                                    }else{
-                                        *tty->flip.flag_buf_ptr++ = 0;
-                                        *tty->flip.char_buf_ptr++ = 0;
-					info->icount.rx++;
+                                    }else {
+					tty_insert_flip_char(tty, 0, TTY_NORMAL);
+				        info->icount.rx++;
                                     }
                                 }else{
-                                    *tty->flip.flag_buf_ptr++ = 0;
-                                    *tty->flip.char_buf_ptr++ = 0;
+				    tty_insert_flip_char(tty, 0, TTY_NORMAL);
 				    info->icount.rx++;
                                 }
                             }else{
@@ -1240,14 +1221,10 @@
                                info->mon.char_max = char_count;
                             info->mon.char_last = char_count;
 #endif
-                            while(char_count--){
-                                if (tty->flip.count >= TTY_FLIPBUF_SIZE){
-                                        break;
-                                }
-                                tty->flip.count++;
+			    len = tty_buffer_request_room(tty, char_count);
+                            while(len--){
                                 data = cy_readb(base_addr+(CyRDSR<<index));
-                                *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-                                *tty->flip.char_buf_ptr++ = data;
+				tty_insert_flip_char(tty, data, TTY_NORMAL);
 				info->idle_stats.recv_bytes++;
 				info->icount.rx++;
 #ifdef CY_16Y_HACK
@@ -1256,7 +1233,7 @@
                             }
                              info->idle_stats.recv_idle = jiffies;
                         }
-                        schedule_delayed_work(&tty->flip.work, 1);
+                        schedule_delayed_work(&tty->buf.work, 1);
                     }
                     /* end of service */
                     cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
@@ -1551,6 +1528,7 @@
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
   volatile int char_count;
+  int len;
 #ifdef BLOCKMOVE
   int small_count;
 #else
@@ -1606,18 +1584,11 @@
 		tty->flip.count += small_count;
 	    }
 #else
-	    while(char_count--){
-		if (tty->flip.count >= N_TTY_BUF_SIZE - tty->read_cnt)
-                    break;
-
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-		    break;
-
+	    len = tty_buffer_request_room(tty, char_count);
+	    while(len--){
 		data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
 		new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
-		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-		*tty->flip.char_buf_ptr++ = data;
+		tty_insert_flip_char(tty, data, TTY_NORMAL);
 		info->idle_stats.recv_bytes++;
 		info->icount.rx++;
 	    }
@@ -1635,7 +1606,7 @@
 	    }
 #endif
 	    info->idle_stats.recv_idle = jiffies;
-	    schedule_delayed_work(&tty->flip.work, 1);
+	    schedule_delayed_work(&tty->buf.work, 1);
 	}
 	/* Update rx_get */
 	cy_writel(&buf_ctrl->rx_get, new_rx_get);
@@ -1763,23 +1734,17 @@
 
 	switch(cmd) {
 	    case C_CM_PR_ERROR:
-		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
-		*tty->flip.char_buf_ptr++ = 0;
+		tty_insert_flip_char(tty, 0, TTY_PARITY);
 		info->icount.rx++;
 		special_count++;
 		break;
 	    case C_CM_FR_ERROR:
-		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
-		*tty->flip.char_buf_ptr++ = 0;
+		tty_insert_flip_char(tty, 0, TTY_FRAME);
 		info->icount.rx++;
 		special_count++;
 		break;
 	    case C_CM_RXBRK:
-		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
-		*tty->flip.char_buf_ptr++ = 0;
+		tty_insert_flip_char(tty, 0, TTY_BREAK);
 		info->icount.rx++;
 		special_count++;
 		break;
@@ -1844,7 +1809,7 @@
 	if(delta_count)
 	    cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
 	if(special_count)
-	    schedule_delayed_work(&tty->flip.work, 1);
+	    schedule_delayed_work(&tty->buf.work, 1);
     }
 }
 
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index dd91ff6..e9e2db1 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -28,7 +28,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm_core.h"
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
index 2218a94..296248c 100644
--- a/drivers/char/drm/i915_ioc32.c
+++ b/drivers/char/drm/i915_ioc32.c
@@ -30,7 +30,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
index 24a9d4e..54a18eb 100644
--- a/drivers/char/drm/mga_ioc32.c
+++ b/drivers/char/drm/mga_ioc32.c
@@ -31,7 +31,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
index 1e2e367..9dd6d41 100644
--- a/drivers/char/drm/r128_ioc32.c
+++ b/drivers/char/drm/r128_ioc32.c
@@ -30,7 +30,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index fef4a2b..0ccfd361 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -28,7 +28,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 407708a..765c5c1 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1786,9 +1786,7 @@
 		if (tty)  { /* Begin if valid tty */
 			if (event & BREAK_IND)  { /* Begin if BREAK_IND */
 				/* A break has been indicated */
-				tty->flip.count++;
-				*tty->flip.flag_buf_ptr++ = TTY_BREAK;
-				*tty->flip.char_buf_ptr++ = 0;
+				tty_insert_flip_char(tty, 0, TTY_BREAK);
 				tty_schedule_flip(tty); 
 			} else if (event & LOWTX_IND)  { /* Begin LOWTX_IND */
 				if (ch->statusflags & LOWWAIT) 
@@ -2124,7 +2122,6 @@
 	int dataToRead, wrapgap, bytesAvailable;
 	unsigned int tail, head;
 	unsigned int wrapmask;
-	int rc;
 
 	/* ---------------------------------------------------------------
 		This routine is called by doint when a receive data event 
@@ -2162,16 +2159,15 @@
 		return;
 	}
 
-	if (tty->flip.count == TTY_FLIPBUF_SIZE) 
+	if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
 		return;
 
 	if (readb(&bc->orun)) {
 		writeb(0, &bc->orun);
 		printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	}
 	rxwinon(ch);
-	rptr = tty->flip.char_buf_ptr;
-	rc = tty->flip.count;
 	while (bytesAvailable > 0)  { /* Begin while there is data on the card */
 		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
 		/* ---------------------------------------------------------------
@@ -2183,8 +2179,7 @@
 		/* --------------------------------------------------------------
 		   Make sure we don't overflow the buffer
 		----------------------------------------------------------------- */
-		if ((rc + dataToRead) > TTY_FLIPBUF_SIZE)
-			dataToRead = TTY_FLIPBUF_SIZE - rc;
+		dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
 		if (dataToRead == 0)
 			break;
 		/* ---------------------------------------------------------------
@@ -2192,13 +2187,9 @@
 			for translation if necessary.
 		------------------------------------------------------------------ */
 		memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
-		rc   += dataToRead;
-		rptr += dataToRead;
 		tail = (tail + dataToRead) & wrapmask;
 		bytesAvailable -= dataToRead;
 	} /* End while there is data on the card */
-	tty->flip.count = rc;
-	tty->flip.char_buf_ptr = rptr;
 	globalwinon(ch);
 	writew(tail, &bc->rout);
 	/* Must be called with global data */
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 9f53d2fc..e469f64 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -345,26 +345,22 @@
 
 	for (i = 0; i < num_bytes; i++) {
 		if (!(err_buf->data[i] & status_mask)) {
-			*(tty->flip.char_buf_ptr++) = pio_buf->data[i];
+			int flag = 0;
 
 			if (err_buf->data[i] & 0x04) {
-				*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
-
+				flag = TTY_BREAK;
 				if (info->flags & ASYNC_SAK)
 					do_SAK(tty);
 			}
 			else if (err_buf->data[i] & 0x02)
-				*(tty->flip.flag_buf_ptr++) = TTY_FRAME;
+				flag = TTY_FRAME;
 			else if (err_buf->data[i] & 0x01)
-				*(tty->flip.flag_buf_ptr++) = TTY_PARITY;
-			else
-				*(tty->flip.flag_buf_ptr++) = 0;
-		
-			tty->flip.count++;
+				flag = TTY_PARITY;
+			tty_insert_flip_char(tty, pio_buf->data[i], flag);
 		}
 	}
 
-	schedule_delayed_work(&tty->flip.work, 1);
+	schedule_delayed_work(&tty->buf.work, 1);
 
 	info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
 	release_pio_buffer(pio_buf);
@@ -397,7 +393,6 @@
 	int num_bytes;
 	unsigned long flags;
 	
-	
 	flags=claim_dma_lock();
 	disable_dma(dma);
 	clear_dma_ff(dma);
@@ -408,38 +403,31 @@
 	
 	info->icount.rx += num_bytes;
 
-	memcpy(tty->flip.char_buf_ptr, dma_buffer, num_bytes);
-	tty->flip.char_buf_ptr += num_bytes;
-	tty->flip.count += num_bytes;
-	memset(tty->flip.flag_buf_ptr, 0, num_bytes);
-	tty->flip.flag_buf_ptr += num_bytes;
-
 	if (num_bytes > 0) {
-		tty->flip.flag_buf_ptr--;
+		tty_insert_flip_string(tty, dma_buffer, num_bytes - 1);
 
 		status &= (0x1c & info->read_status_mask);
-
-		if (status & info->ignore_status_mask) {
-			tty->flip.count--;
-			tty->flip.char_buf_ptr--;
-			tty->flip.flag_buf_ptr--;
-		} else if (status & 0x10) {
-			*tty->flip.flag_buf_ptr = TTY_BREAK;
-			(info->icount.brk)++;
-			if (info->flags & ASYNC_SAK)
-				do_SAK(tty);
-		} else if (status & 0x08) {
-			*tty->flip.flag_buf_ptr = TTY_FRAME;
-			(info->icount.frame)++;
-		}
-		else if (status & 0x04) {
-			*tty->flip.flag_buf_ptr = TTY_PARITY;
-			(info->icount.parity)++;
-		}
-
-		tty->flip.flag_buf_ptr++;
 		
-		schedule_delayed_work(&tty->flip.work, 1);
+		/* Is the status significant or do we throw the last byte ? */
+		if (!(status & info->ignore_status_mask)) {
+			int statflag = 0;
+
+			if (status & 0x10) {
+				statflag = TTY_BREAK;
+				(info->icount.brk)++;
+				if (info->flags & ASYNC_SAK)
+					do_SAK(tty);
+			} else if (status & 0x08) {
+				statflag = TTY_FRAME;
+				(info->icount.frame)++;
+			}
+			else if (status & 0x04) {
+				statflag = TTY_PARITY;
+				(info->icount.parity)++;
+			}
+			tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
+		}
+		schedule_delayed_work(&tty->buf.work, 1);
 	}
 
 	if (dma_bytes != num_bytes) {
@@ -693,8 +681,7 @@
 		num_bytes = serial_in(info, UART_ESI_STAT1) << 8;
 		num_bytes |= serial_in(info, UART_ESI_STAT2);
 
-		if (num_bytes > (TTY_FLIPBUF_SIZE - info->tty->flip.count))
-		  num_bytes = TTY_FLIPBUF_SIZE - info->tty->flip.count;
+		num_bytes = tty_buffer_request_room(info->tty, num_bytes);
 
 		if (num_bytes) {
 			if (dma_bytes ||
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f921776..1994a92 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -597,9 +597,7 @@
 
 	/* Read data if any */
 	for (;;) {
-		int count = N_INBUF;
-		if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
-			count = TTY_FLIPBUF_SIZE - tty->flip.count;
+		int count = tty_buffer_request_room(tty, N_INBUF);
 
 		/* If flip is full, just reschedule a later read */
 		if (count == 0) {
@@ -635,7 +633,7 @@
 			tty_insert_flip_char(tty, buf[i], 0);
 		}
 
-		if (tty->flip.count)
+		if (count)
 			tty_schedule_flip(tty);
 
 		/*
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 53dc77c..831eb4e 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -456,12 +456,11 @@
 	/* remove the read masks */
 	hvcsd->todo_mask &= ~(HVCS_READ_MASK);
 
-	if ((tty->flip.count + HVCS_BUFF_LEN) < TTY_FLIPBUF_SIZE) {
+	if (tty_buffer_request_room(tty, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
 		got = hvc_get_chars(unit_address,
 				&buf[0],
 				HVCS_BUFF_LEN);
-		for (i=0;got && i<got;i++)
-			tty_insert_flip_char(tty, buf[i], TTY_NORMAL);
+		tty_insert_flip_string(tty, buf, got);
 	}
 
 	/* Give the TTY time to process the data we just sent. */
@@ -469,10 +468,9 @@
 		hvcsd->todo_mask |= HVCS_QUICK_READ;
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	if (tty->flip.count) {
-		/* This is synch because tty->low_latency == 1 */
+	/* This is synch because tty->low_latency == 1 */
+	if(got)
 		tty_flip_buffer_push(tty);
-	}
 
 	if (!got) {
 		/* Do this _after_ the flip_buffer_push */
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index a22aa94..a952218 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -197,7 +197,7 @@
 	};
 	const char *name = state_names[hp->state];
 
-	if (hp->state > (sizeof(state_names)/sizeof(char*)))
+	if (hp->state > ARRAY_SIZE(state_names))
 		name = "UNKNOWN";
 
 	pr_debug("hvsi%i: state = %s\n", hp->index, name);
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index ba85eb1..fc944d3 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -854,7 +854,7 @@
 		count += IBUF_SIZE;
 	}
 	// Don't give more than can be taken by the line discipline
-	amountToMove = pCh->pTTY->ldisc.receive_room( pCh->pTTY );
+	amountToMove = pCh->pTTY->receive_room;
 	if (count > amountToMove) {
 		count = amountToMove;
 	}
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index d815d19..56e93a5 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -172,7 +172,7 @@
 /* Private (static) functions */
 static int  ip2_open(PTTY, struct file *);
 static void ip2_close(PTTY, struct file *);
-static int  ip2_write(PTTY, int, const unsigned char *, int);
+static int  ip2_write(PTTY, const unsigned char *, int);
 static void ip2_putchar(PTTY, unsigned char);
 static void ip2_flush_chars(PTTY);
 static int  ip2_write_room(PTTY);
@@ -1713,7 +1713,7 @@
 /*                                                                            */
 /******************************************************************************/
 static int
-ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
+ip2_write( PTTY tty, const unsigned char *pData, int count)
 {
 	i2ChanStrPtr  pCh = tty->driver_data;
 	int bytesSent = 0;
@@ -1726,7 +1726,7 @@
 
 	/* This is the actual move bit. Make sure it does what we need!!!!! */
 	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
-	bytesSent = i2Output( pCh, pData, count, user );
+	bytesSent = i2Output( pCh, pData, count, 0 );
 	WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
 
 	ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
@@ -2001,7 +2001,9 @@
 static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	i2ChanStrPtr pCh = DevTable[tty->index];
+#ifdef	ENABLE_DSSNOW
 	wait_queue_t wait;
+#endif
 
 	if (pCh == NULL)
 		return -ENODEV;
@@ -2089,15 +2091,17 @@
 {
 	wait_queue_t wait;
 	i2ChanStrPtr pCh = DevTable[tty->index];
+	i2eBordStrPtr pB;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct __user *p_cuser;
 	int rc = 0;
 	unsigned long flags;
 	void __user *argp = (void __user *)arg;
 
-	if ( pCh == NULL ) {
+	if ( pCh == NULL )
 		return -ENODEV;
-	}
+
+	pB = pCh->pMyBord;
 
 	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
 
@@ -2206,9 +2210,9 @@
 	 * for masking). Caller should use TIOCGICOUNT to see which one it was
 	 */
 	case TIOCMIWAIT:
-		save_flags(flags);cli();
+		WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
 		cprev = pCh->icount;	 /* note the counters on entry */
-		restore_flags(flags);
+		WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
 		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
 						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
 		init_waitqueue_entry(&wait, current);
@@ -2228,9 +2232,9 @@
 				rc = -ERESTARTSYS;
 				break;
 			}
-			save_flags(flags);cli();
+			WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
 			cnow = pCh->icount; /* atomic copy */
-			restore_flags(flags);
+			WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
 				rc =  -EIO; /* no change => rc */
@@ -2268,9 +2272,9 @@
 	case TIOCGICOUNT:
 		ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
 
-		save_flags(flags);cli();
+		WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
 		cnow = pCh->icount;
-		restore_flags(flags);
+		WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
 		p_cuser = argp;
 		rc = put_user(cnow.cts, &p_cuser->cts);
 		rc = put_user(cnow.dsr, &p_cuser->dsr);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 561430e..0097f06 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -57,6 +57,7 @@
 
 #ifdef CONFIG_PROC_FS
 struct proc_dir_entry *proc_ipmi_root = NULL;
+EXPORT_SYMBOL(proc_ipmi_root);
 #endif /* CONFIG_PROC_FS */
 
 #define MAX_EVENTS_IN_QUEUE	25
@@ -3295,6 +3296,5 @@
 EXPORT_SYMBOL(ipmi_set_my_LUN);
 EXPORT_SYMBOL(ipmi_get_my_LUN);
 EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
-EXPORT_SYMBOL(proc_ipmi_root);
 EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
 EXPORT_SYMBOL(ipmi_free_recv_msg);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e053ead..49c09ae 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -612,11 +612,14 @@
 #endif
 
 	rv = ipmi_smi_watcher_register(&smi_watcher);
+
+#ifdef CONFIG_PROC_FS
 	if (rv) {
 		unregister_sysctl_table(ipmi_table_header);
 		printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
 		goto out_err;
 	}
+#endif
 
  out_err:
 	return rv;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 1bbf507..e9ebaba 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -20,7 +20,7 @@
  *	3/9/99	sameer			Added support for ISI4616 cards.
  *
  *	16/9/99	sameer			We do not force RTS low anymore.
- *					This is to prevent the firmware 
+ *					This is to prevent the firmware
  *					from getting confused.
  *
  *	26/10/99 sameer			Cosmetic changes:The driver now
@@ -31,28 +31,28 @@
  *
  *	10/5/00  sameer			Fixed isicom_shutdown_board()
  *					to not lower DTR on all the ports
- *					when the last port on the card is 
+ *					when the last port on the card is
  *					closed.
  *
  *	10/5/00  sameer			Signal mask setup command added
- *					to  isicom_setup_port and 
+ *					to  isicom_setup_port and
  *					isicom_shutdown_port.
  *
  *	24/5/00  sameer			The driver is now SMP aware.
- *					
- *	
+ *
+ *
  *	27/11/00 Vinayak P Risbud	Fixed the Driver Crash Problem
- *	
- *	
+ *
+ *
  *	03/01/01  anil .s		Added support for resetting the
  *					internal modems on ISI cards.
  *
  *	08/02/01  anil .s		Upgraded the driver for kernel
  *					2.4.x
  *
- *      11/04/01  Kevin			Fixed firmware load problem with
+ *	11/04/01  Kevin			Fixed firmware load problem with
  *					ISIHP-4X card
- *	
+ *
  *	30/04/01  anil .s		Fixed the remote login through
  *					ISI port problem. Now the link
  *					does not go down before password
@@ -62,9 +62,9 @@
  *					among ISI-PCI cards.
  *
  *	03/05/01  anil .s		Added support to display the version
- *					info during insmod as well as module 
+ *					info during insmod as well as module
  *					listing by lsmod.
- *	
+ *
  *	10/05/01  anil .s		Done the modifications to the source
  *					file and Install script so that the
  *					same installation can be used for
@@ -73,19 +73,19 @@
  *	06/06/01  anil .s		Now we drop both dtr and rts during
  *					shutdown_port as well as raise them
  *					during isicom_config_port.
- *  	
+ *
  *	09/06/01 acme@conectiva.com.br	use capable, not suser, do
  *					restore_flags on failure in
  *					isicom_send_break, verify put_user
  *					result
  *
- *  	11/02/03  ranjeeth		Added support for 230 Kbps and 460 Kbps
- *  					Baud index extended to 21
- *  	
- *  	20/03/03  ranjeeth		Made to work for Linux Advanced server.
- *  					Taken care of license warning.	
- *      
- *	10/12/03  Ravindra		Made to work for Fedora Core 1 of 
+ *	11/02/03  ranjeeth		Added support for 230 Kbps and 460 Kbps
+ *					Baud index extended to 21
+ *
+ *	20/03/03  ranjeeth		Made to work for Linux Advanced server.
+ *					Taken care of license warning.
+ *
+ *	10/12/03  Ravindra		Made to work for Fedora Core 1 of
  *					Red Hat Distribution
  *
  *	06/01/05  Alan Cox 		Merged the ISI and base kernel strands
@@ -93,10 +93,10 @@
  *
  *	***********************************************************
  *
- *	To use this driver you also need the support package. You 
+ *	To use this driver you also need the support package. You
  *	can find this in RPM format on
  *		ftp://ftp.linux.org.uk/pub/linux/alan
- * 	
+ *
  *	You can find the original tools for this direct from Multitech
  *		ftp://ftp.multitech.com/ISI-Cards/
  *
@@ -107,20 +107,20 @@
  *	Omit those entries for boards you don't have installed.
  *
  *	TODO
- *		Hotplug
  *		Merge testing
  *		64-bit verification
  */
 
 #include <linux/module.h>
+#include <linux/firmware.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/termios.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/serial.h>
 #include <linux/mm.h>
-#include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
@@ -134,50 +134,62 @@
 
 #include <linux/isicom.h>
 
+#define InterruptTheCard(base) outw(0, (base) + 0xc)
+#define ClearInterrupt(base) inw((base) + 0x0a)
+
+#ifdef DEBUG
+#define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str)
+#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
+#else
+#define pr_dbg(str...) do { } while (0)
+#define isicom_paranoia_check(a, b, c) 0
+#endif
+
+static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
+static void __devexit isicom_remove(struct pci_dev *);
+
 static struct pci_device_id isicom_pci_tbl[] = {
-	{ VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2051) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2052) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2053) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2054) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2055) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2056) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2057) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2058) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
 
+static struct pci_driver isicom_driver = {
+	.name		= "isicom",
+	.id_table	= isicom_pci_tbl,
+	.probe		= isicom_probe,
+	.remove		= __devexit_p(isicom_remove)
+};
+
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
 static struct tty_driver *isicom_normal;
 
 static struct timer_list tx;
 static char re_schedule = 1;
-#ifdef ISICOM_DEBUG
-static unsigned long tx_count = 0;
-#endif
-
-static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned  int cmd, unsigned long arg);
 
 static void isicom_tx(unsigned long _data);
-static void isicom_start(struct tty_struct * tty);
-
-static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
+static void isicom_start(struct tty_struct *tty);
 
 /*   baud index mappings from linux defns to isi */
 
 static signed char linuxb_to_isib[] = {
-	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,     
-	18, 19
+	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19
 };
 
 struct	isi_board {
-	unsigned short		base;
+	unsigned long		base;
 	unsigned char		irq;
 	unsigned char		port_count;
 	unsigned short		status;
-	unsigned short		port_status; /* each bit represents a single port */
+	unsigned short		port_status; /* each bit for each port */
 	unsigned short		shift_count;
 	struct isi_port		* ports;
 	signed char		count;
@@ -192,9 +204,9 @@
 	int			count;
 	int			blocked_open;
 	int			close_delay;
-	unsigned short		channel;
-	unsigned short		status;
-	unsigned short		closing_wait;
+	u16			channel;
+	u16			status;
+	u16			closing_wait;
 	struct isi_board	* card;
 	struct tty_struct 	* tty;
 	wait_queue_head_t	close_wait;
@@ -215,35 +227,37 @@
  *	the kernel lock for the card and have the card in a position that
  *	it wants to talk.
  */
- 
+
 static int lock_card(struct isi_board *card)
 {
 	char		retries;
-	unsigned short base = card->base;
+	unsigned long base = card->base;
 
 	for (retries = 0; retries < 100; retries++) {
 		spin_lock_irqsave(&card->card_lock, card->flags);
 		if (inw(base + 0xe) & 0x1) {
-			return 1; 
+			return 1;
 		} else {
 			spin_unlock_irqrestore(&card->card_lock, card->flags);
 			udelay(1000);   /* 1ms */
 		}
 	}
-	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
+		card->base);
+
 	return 0;	/* Failed to aquire the card! */
 }
 
 static int lock_card_at_interrupt(struct isi_board *card)
 {
 	unsigned char		retries;
-	unsigned short 		base = card->base;
+	unsigned long base = card->base;
 
 	for (retries = 0; retries < 200; retries++) {
 		spin_lock_irqsave(&card->card_lock, card->flags);
 
 		if (inw(base + 0xe) & 0x1)
-			return 1; 
+			return 1;
 		else
 			spin_unlock_irqrestore(&card->card_lock, card->flags);
 	}
@@ -259,373 +273,141 @@
 /*
  *  ISI Card specific ops ...
  */
- 
-static void raise_dtr(struct isi_port * port)
+
+static void raise_dtr(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw(0x0504, base);
 	InterruptTheCard(base);
 	port->status |= ISI_DTR;
 	unlock_card(card);
 }
 
-static inline void drop_dtr(struct isi_port * port)
-{	
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+static inline void drop_dtr(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw(0x0404, base);
-	InterruptTheCard(base);	
+	InterruptTheCard(base);
 	port->status &= ~ISI_DTR;
 	unlock_card(card);
 }
 
-static inline void raise_rts(struct isi_port * port)
+static inline void raise_rts(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw(0x0a04, base);
-	InterruptTheCard(base);	
+	InterruptTheCard(base);
 	port->status |= ISI_RTS;
 	unlock_card(card);
 }
-static inline void drop_rts(struct isi_port * port)
+static inline void drop_rts(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw(0x0804, base);
-	InterruptTheCard(base);	
+	InterruptTheCard(base);
 	port->status &= ~ISI_RTS;
 	unlock_card(card);
 }
 
-static inline void raise_dtr_rts(struct isi_port * port)
+static inline void raise_dtr_rts(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw(0x0f04, base);
 	InterruptTheCard(base);
 	port->status |= (ISI_DTR | ISI_RTS);
 	unlock_card(card);
 }
 
-static void drop_dtr_rts(struct isi_port * port)
+static void drop_dtr_rts(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw(0x0c04, base);
-	InterruptTheCard(base);	
+	InterruptTheCard(base);
 	port->status &= ~(ISI_RTS | ISI_DTR);
 	unlock_card(card);
 }
 
-static inline void kill_queue(struct isi_port * port, short queue)
+static inline void kill_queue(struct isi_port *port, short queue)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;
-	unsigned char channel = port->channel;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
 
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
 	outw((queue << 8) | 0x06, base);
-	InterruptTheCard(base);	
+	InterruptTheCard(base);
 	unlock_card(card);
 }
 
-
-/* 
- *  Firmware loader driver specific routines. This needs to mostly die
- *  and be replaced with request_firmware.
- */
-
-static struct file_operations ISILoad_fops = {
-	.owner		= THIS_MODULE,
-	.ioctl		= ISILoad_ioctl,
-};
-
-static struct miscdevice isiloader_device = {
-	ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
-};
-
- 
-static inline int WaitTillCardIsFree(unsigned short base)
-{
-	unsigned long count=0;
-	while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
-	if (inw(base+0xe)&0x1)  
-		return 0;
-	else
-		return 1;
-}
-
-static int ISILoad_ioctl(struct inode *inode, struct file *filp,
-		         unsigned int cmd, unsigned long arg)
-{
-	unsigned int card, i, j, signature, status, portcount = 0;
-	unsigned long t;
-	unsigned short word_count, base;
-	bin_frame frame;
-	void __user *argp = (void __user *)arg;
-	/* exec_record exec_rec; */
-	
-	if(get_user(card, (int __user *)argp))
-		return -EFAULT;
-		
-	if(card < 0 || card >= BOARD_COUNT)
-		return -ENXIO;
-		
-	base=isi_card[card].base;
-	
-	if(base==0)
-		return -ENXIO;	/* disabled or not used */
-	
-	switch(cmd) {
-		case MIOCTL_RESET_CARD:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-			printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
-								
-			inw(base+0x8);
-			
-			for(t=jiffies+HZ/100;time_before(jiffies, t););
-				
-			outw(0,base+0x8); /* Reset */
-			
-			for(j=1;j<=3;j++) {
-				for(t=jiffies+HZ;time_before(jiffies, t););
-				printk(".");
-			}	
-			signature=(inw(base+0x4)) & 0xff;	
-			if (isi_card[card].isa) {
-					
-				if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
-#ifdef ISICOM_DEBUG				
-					printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif				
-					printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-					return -EIO;					
-				}
-			}	
-			else {
-				portcount = inw(base+0x2);
-				if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {	
-#ifdef ISICOM_DEBUG
-					printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif
-					printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-					return -EIO;
-				}
-			}	
-			switch(signature) {
-			case	0xa5:
-			case	0xbb:
-			case	0xdd:	
-					if (isi_card[card].isa) 
-						isi_card[card].port_count = 8;
-					else {
-						if (portcount == 4)
-							isi_card[card].port_count = 4;
-						else
-							isi_card[card].port_count = 8;
-					}	
-				     	isi_card[card].shift_count = 12;
-				     	break;
-				        
-			case	0xcc:	isi_card[card].port_count = 16;
-					isi_card[card].shift_count = 11;
-					break;  			
-					
-			default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-#ifdef ISICOM_DEBUG			
-				 printk("Sig=0x%x\n",signature);
-#endif				 
-				 return -EIO;
-			}
-			printk("-Done\n");
-			return put_user(signature,(unsigned __user *)argp);
-						
-	case	MIOCTL_LOAD_FIRMWARE:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-				
-			if(copy_from_user(&frame, argp, sizeof(bin_frame)))
-				return -EFAULT;
-			
-			if (WaitTillCardIsFree(base))
-				return -EIO;
-			
-			outw(0xf0,base);	/* start upload sequence */ 
-			outw(0x00,base);
-			outw((frame.addr), base);/*      lsb of adderess    */
-			
-			word_count=(frame.count >> 1) + frame.count % 2;
-			outw(word_count, base);
-			InterruptTheCard(base);
-			
-			for(i=0;i<=0x2f;i++);	/* a wee bit of delay */
-			
-			if (WaitTillCardIsFree(base)) 
-				return -EIO;
-				
-			if ((status=inw(base+0x4))!=0) {
-				printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
-				card+1, frame.addr, frame.count, status);
-				return -EIO;
-			}
-			outsw(base, (void *) frame.bin_data, word_count);
-			
-			InterruptTheCard(base);
-			
-			for(i=0;i<=0x0f;i++);	/* another wee bit of delay */ 
-			
-			if (WaitTillCardIsFree(base)) 
-				return -EIO;
-				
-			if ((status=inw(base+0x4))!=0) {
-				printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
-				return -EIO;
-			}	
-			return 0;
-						
-	case	MIOCTL_READ_FIRMWARE:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-				
-			if(copy_from_user(&frame, argp, sizeof(bin_header)))
-				return -EFAULT;
-			
-			if (WaitTillCardIsFree(base))
-				return -EIO;
-			
-			outw(0xf1,base);	/* start download sequence */ 
-			outw(0x00,base);
-			outw((frame.addr), base);/*      lsb of adderess    */
-			
-			word_count=(frame.count >> 1) + frame.count % 2;
-			outw(word_count+1, base);
-			InterruptTheCard(base);
-			
-			for(i=0;i<=0xf;i++);	/* a wee bit of delay */
-			
-			if (WaitTillCardIsFree(base)) 
-				return -EIO;
-				
-			if ((status=inw(base+0x4))!=0) {
-				printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
-				card+1, frame.addr, frame.count, status);
-				return -EIO;
-			}
-			
-			inw(base);
-			insw(base, frame.bin_data, word_count);
-			InterruptTheCard(base);
-			
-			for(i=0;i<=0x0f;i++);	/* another wee bit of delay */ 
-			
-			if (WaitTillCardIsFree(base)) 
-				return -EIO;
-				
-			if ((status=inw(base+0x4))!=0) {
-				printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
-				return -EIO;
-			}	
-			
-			if(copy_to_user(argp, &frame, sizeof(bin_frame)))
-				return -EFAULT;
-			return 0;
-	
-	case	MIOCTL_XFER_CTRL:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-			if (WaitTillCardIsFree(base)) 
-				return -EIO;
-					
-			outw(0xf2, base);
-			outw(0x800, base);
-			outw(0x0, base);
-			outw(0x0, base);
-			InterruptTheCard(base);
-			outw(0x0, base+0x4);    /* for ISI4608 cards */
-							
-			isi_card[card].status |= FIRMWARE_LOADED;
-			return 0;	
-			
-	default:
-#ifdef ISICOM_DEBUG	
-		printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd); 
-#endif
-		return -ENOIOCTLCMD;
-	
-	}
-	
-}
-		        	
-
 /*
  *	ISICOM Driver specific routines ...
  *
  */
- 
-static inline int isicom_paranoia_check(struct isi_port const * port, char *name, 
-					const char * routine)
+
+static inline int __isicom_paranoia_check(struct isi_port const *port,
+	char *name, const char *routine)
 {
-#ifdef ISICOM_DEBUG 
-	static const char * badmagic = 
-			KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
-	static const char * badport = 
-			KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";		
 	if (!port) {
-		printk(badport, name, routine);
+		printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
+			"dev %s in %s.\n", name, routine);
 		return 1;
 	}
 	if (port->magic != ISICOM_MAGIC) {
-		printk(badmagic, name, routine);
+		printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
+			"dev %s in %s.\n", name, routine);
 		return 1;
-	}	
-#endif	
+	}
+
 	return 0;
 }
-			
+
 /*
- *	Transmitter. 
+ *	Transmitter.
  *
  *	We shovel data into the card buffers on a regular basis. The card
  *	will do the rest of the work for us.
@@ -635,25 +417,21 @@
 {
 	short count = (BOARD_COUNT-1), card, base;
 	short txcount, wrd, residue, word_count, cnt;
-	struct isi_port * port;
-	struct tty_struct * tty;
-	
-#ifdef ISICOM_DEBUG
-	++tx_count;
-#endif	
-	
+	struct isi_port *port;
+	struct tty_struct *tty;
+
 	/*	find next active board	*/
 	card = (prev_card + 1) & 0x0003;
 	while(count-- > 0) {
-		if (isi_card[card].status & BOARD_ACTIVE) 
+		if (isi_card[card].status & BOARD_ACTIVE)
 			break;
-		card = (card + 1) & 0x0003;	
+		card = (card + 1) & 0x0003;
 	}
 	if (!(isi_card[card].status & BOARD_ACTIVE))
 		goto sched_again;
-		
+
 	prev_card = card;
-	
+
 	count = isi_card[card].port_count;
 	port = isi_card[card].ports;
 	base = isi_card[card].base;
@@ -662,18 +440,18 @@
 			continue;
 		/* port not active or tx disabled to force flow control */
 		if (!(port->flags & ASYNC_INITIALIZED) ||
-		 	!(port->status & ISI_TXOK))
+				!(port->status & ISI_TXOK))
 			unlock_card(&isi_card[card]);
 			continue;
-		
+
 		tty = port->tty;
-		
-		
-		if(tty == NULL) {
+
+
+		if (tty == NULL) {
 			unlock_card(&isi_card[card]);
 			continue;
 		}
-		
+
 		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
 		if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
 			unlock_card(&isi_card[card]);
@@ -681,44 +459,45 @@
 		}
 		if (!(inw(base + 0x02) & (1 << port->channel))) {
 			unlock_card(&isi_card[card]);
-			continue;		
+			continue;
 		}
-#ifdef ISICOM_DEBUG
-		printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n", 
-				txcount, port->channel+1); 
-#endif	
-		outw((port->channel << isi_card[card].shift_count) | txcount
-					, base);
+		pr_dbg("txing %d bytes, port%d.\n", txcount,
+			port->channel + 1);
+		outw((port->channel << isi_card[card].shift_count) | txcount,
+			base);
 		residue = NO;
-		wrd = 0;			
+		wrd = 0;
 		while (1) {
-			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
+					- port->xmit_tail));
 			if (residue == YES) {
 				residue = NO;
 				if (cnt > 0) {
-					wrd |= (port->xmit_buf[port->xmit_tail] << 8);
-					port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+					wrd |= (port->xmit_buf[port->xmit_tail]
+									<< 8);
+					port->xmit_tail = (port->xmit_tail + 1)
+						& (SERIAL_XMIT_SIZE - 1);
 					port->xmit_cnt--;
 					txcount--;
 					cnt--;
-					outw(wrd, base);			
-				}
-				else {
+					outw(wrd, base);
+				} else {
 					outw(wrd, base);
 					break;
 				}
-			}		
+			}
 			if (cnt <= 0) break;
 			word_count = cnt >> 1;
-			outsw(base, port->xmit_buf+port->xmit_tail, word_count);
-			port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
-						(SERIAL_XMIT_SIZE - 1);
+			outsw(base, port->xmit_buf+port->xmit_tail,word_count);
+			port->xmit_tail = (port->xmit_tail
+				+ (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
 			txcount -= (word_count << 1);
 			port->xmit_cnt -= (word_count << 1);
 			if (cnt & 0x0001) {
 				residue = YES;
 				wrd = port->xmit_buf[port->xmit_tail];
-				port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+				port->xmit_tail = (port->xmit_tail + 1)
+					& (SERIAL_XMIT_SIZE - 1);
 				port->xmit_cnt--;
 				txcount--;
 			}
@@ -730,81 +509,82 @@
 		if (port->xmit_cnt <= WAKEUP_CHARS)
 			schedule_work(&port->bh_tqueue);
 		unlock_card(&isi_card[card]);
-	}	
+	}
 
-	/*	schedule another tx for hopefully in about 10ms	*/	
-sched_again:	
-	if (!re_schedule)	
-		return;
+	/*	schedule another tx for hopefully in about 10ms	*/
+sched_again:
+	if (!re_schedule) {
+		re_schedule = 2;
+ 		return;
+	}
+
 	init_timer(&tx);
 	tx.expires = jiffies + HZ/100;
 	tx.data = 0;
 	tx.function = isicom_tx;
 	add_timer(&tx);
-	
-	return;	
-}		
- 
+
+	return;
+}
+
 /* 	Interrupt handlers 	*/
 
- 
-static void isicom_bottomhalf(void * data)
+
+static void isicom_bottomhalf(void *data)
 {
-	struct isi_port * port = (struct isi_port *) data;
-	struct tty_struct * tty = port->tty;
-	
+	struct isi_port *port = (struct isi_port *) data;
+	struct tty_struct *tty = port->tty;
+
 	if (!tty)
 		return;
 
-	tty_wakeup(tty);	
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
-} 		
- 		
+}
+
 /*
- *	Main interrupt handler routine 
+ *	Main interrupt handler routine
  */
- 
-static irqreturn_t isicom_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+
+static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct isi_board * card;
-	struct isi_port * port;
-	struct tty_struct * tty;
-	unsigned short base, header, word_count, count;
-	unsigned char channel;
+	struct isi_board *card = dev_id;
+	struct isi_port *port;
+	struct tty_struct *tty;
+	unsigned long base;
+	u16 header, word_count, count, channel;
 	short byte_count;
-	
-	card = (struct isi_board *) dev_id;
+	unsigned char *rp;
 
 	if (!card || !(card->status & FIRMWARE_LOADED))
 		return IRQ_NONE;
-	
+
 	base = card->base;
 	spin_lock(&card->card_lock);
-	
+
 	if (card->isa == NO) {
 		/*
-		 *      disable any interrupts from the PCI card and lower the
-		 *      interrupt line
+		 * disable any interrupts from the PCI card and lower the
+		 * interrupt line
 		 */
 		outw(0x8000, base+0x04);
 		ClearInterrupt(base);
 	}
-	
+
 	inw(base);		/* get the dummy word out */
 	header = inw(base);
 	channel = (header & 0x7800) >> card->shift_count;
 	byte_count = header & 0xff;
 
 	if (channel + 1 > card->port_count) {
-		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
-				base, channel+1);
+		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
+			"%d(channel) > port_count.\n", base, channel+1);
 		if (card->isa)
 			ClearInterrupt(base);
 		else
-			outw(0x0000, base+0x04); /* enable interrupts */		
+			outw(0x0000, base+0x04); /* enable interrupts */
 		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;			
+		return IRQ_HANDLED;
 	}
 	port = card->ports + channel;
 	if (!(port->flags & ASYNC_INITIALIZED)) {
@@ -813,8 +593,8 @@
 		else
 			outw(0x0000, base+0x04); /* enable interrupts */
 		return IRQ_HANDLED;
-	}	
-		
+	}
+
 	tty = port->tty;
 	if (tty == NULL) {
 		word_count = byte_count >> 1;
@@ -831,224 +611,204 @@
 		spin_unlock(&card->card_lock);
 		return IRQ_HANDLED;
 	}
-	
+
 	if (header & 0x8000) {		/* Status Packet */
 		header = inw(base);
 		switch(header & 0xff) {
-			case 0:	/* Change in EIA signals */
-				
-				if (port->flags & ASYNC_CHECK_CD) {
-					if (port->status & ISI_DCD) {
-						if (!(header & ISI_DCD)) {
-						/* Carrier has been lost  */
-#ifdef ISICOM_DEBUG						
-							printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
-#endif							
-							port->status &= ~ISI_DCD;
-							schedule_work(&port->hangup_tq);
-						}
-					}
-					else {
-						if (header & ISI_DCD) {
-						/* Carrier has been detected */
-#ifdef ISICOM_DEBUG
-							printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
-#endif							
-							port->status |= ISI_DCD;
-							wake_up_interruptible(&port->open_wait);
-						}
-					}
-				}
-				else {
-					if (header & ISI_DCD) 
-						port->status |= ISI_DCD;
-					else
+		case 0:	/* Change in EIA signals */
+			if (port->flags & ASYNC_CHECK_CD) {
+				if (port->status & ISI_DCD) {
+					if (!(header & ISI_DCD)) {
+					/* Carrier has been lost  */
+						pr_dbg("interrupt: DCD->low.\n"
+							);
 						port->status &= ~ISI_DCD;
-				}	
-				
-				if (port->flags & ASYNC_CTS_FLOW) {
-					if (port->tty->hw_stopped) {
-						if (header & ISI_CTS) {
-							port->tty->hw_stopped = 0;
-							/* start tx ing */
-							port->status |= (ISI_TXOK | ISI_CTS);
-							schedule_work(&port->bh_tqueue);
-						}
+						schedule_work(&port->hangup_tq);
 					}
-					else {
-						if (!(header & ISI_CTS)) {
-							port->tty->hw_stopped = 1;
-							/* stop tx ing */
-							port->status &= ~(ISI_TXOK | ISI_CTS);
-						}
+				} else if (header & ISI_DCD) {
+				/* Carrier has been detected */
+					pr_dbg("interrupt: DCD->high.\n");
+					port->status |= ISI_DCD;
+					wake_up_interruptible(&port->open_wait);
+				}
+			} else {
+				if (header & ISI_DCD)
+					port->status |= ISI_DCD;
+				else
+					port->status &= ~ISI_DCD;
+			}
+
+			if (port->flags & ASYNC_CTS_FLOW) {
+				if (port->tty->hw_stopped) {
+					if (header & ISI_CTS) {
+						port->tty->hw_stopped = 0;
+						/* start tx ing */
+						port->status |= (ISI_TXOK
+							| ISI_CTS);
+						schedule_work(&port->bh_tqueue);
 					}
+				} else if (!(header & ISI_CTS)) {
+					port->tty->hw_stopped = 1;
+					/* stop tx ing */
+					port->status &= ~(ISI_TXOK | ISI_CTS);
 				}
-				else {
-					if (header & ISI_CTS) 
-						port->status |= ISI_CTS;
-					else
-						port->status &= ~ISI_CTS;
-				}
-				
-				if (header & ISI_DSR) 
-					port->status |= ISI_DSR;
+			} else {
+				if (header & ISI_CTS)
+					port->status |= ISI_CTS;
 				else
-					port->status &= ~ISI_DSR;
-				
-				if (header & ISI_RI) 
-					port->status |= ISI_RI;
-				else
-					port->status &= ~ISI_RI;						
-				
-				break;
-				
-			case 1:	/* Received Break !!!	 */
-				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-					break;
-				*tty->flip.flag_buf_ptr++ = TTY_BREAK;
-				*tty->flip.char_buf_ptr++ = 0;
-				tty->flip.count++;
-				if (port->flags & ASYNC_SAK)
-					do_SAK(tty);
-				schedule_delayed_work(&tty->flip.work, 1);
-				break;
-				
-			case 2:	/* Statistics		 */
-				printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");			
-				break;
-				
-			default:
-				printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
-				break;
-		}	 
-	}
-	else {				/* Data   Packet */
-		count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
-#ifdef ISICOM_DEBUG
-		printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
-					count, byte_count);
-#endif			
+					port->status &= ~ISI_CTS;
+			}
+
+			if (header & ISI_DSR)
+				port->status |= ISI_DSR;
+			else
+				port->status &= ~ISI_DSR;
+
+			if (header & ISI_RI)
+				port->status |= ISI_RI;
+			else
+				port->status &= ~ISI_RI;
+
+			break;
+
+		case 1:	/* Received Break !!! */
+			tty_insert_flip_char(tty, 0, TTY_BREAK);
+			if (port->flags & ASYNC_SAK)
+				do_SAK(tty);
+			tty_flip_buffer_push(tty);
+			break;
+
+		case 2:	/* Statistics		 */
+			pr_dbg("isicom_interrupt: stats!!!.\n");
+			break;
+
+		default:
+			pr_dbg("Intr: Unknown code in status packet.\n");
+			break;
+		}
+	} else {				/* Data   Packet */
+
+		count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
+		pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
 		word_count = count >> 1;
-		insw(base, tty->flip.char_buf_ptr, word_count);
-		tty->flip.char_buf_ptr += (word_count << 1);		
+		insw(base, rp, word_count);
 		byte_count -= (word_count << 1);
 		if (count & 0x0001) {
-			*tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
+			tty_insert_flip_char(tty,  inw(base) & 0xff,
+				TTY_NORMAL);
 			byte_count -= 2;
-		}	
-		memset(tty->flip.flag_buf_ptr, 0, count);
-		tty->flip.flag_buf_ptr += count;
-		tty->flip.count += count;
-		
+		}
 		if (byte_count > 0) {
-			printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
-					base, channel+1);
+			pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
+				"bytes...\n", base, channel + 1);
 			while(byte_count > 0) { /* drain out unread xtra data */
 				inw(base);
 				byte_count -= 2;
 			}
 		}
-		schedule_delayed_work(&tty->flip.work, 1);
+		tty_flip_buffer_push(tty);
 	}
 	if (card->isa == YES)
 		ClearInterrupt(base);
 	else
-		outw(0x0000, base+0x04); /* enable interrupts */	
-	return IRQ_HANDLED;
-} 
+		outw(0x0000, base+0x04); /* enable interrupts */
 
-static void isicom_config_port(struct isi_port * port)
+	return IRQ_HANDLED;
+}
+
+static void isicom_config_port(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	struct tty_struct * tty;
+	struct isi_board *card = port->card;
+	struct tty_struct *tty;
 	unsigned long baud;
-	unsigned short channel_setup, base = card->base;
-	unsigned short channel = port->channel, shift_count = card->shift_count;
+	unsigned long base = card->base;
+	u16 channel_setup, channel = port->channel,
+		shift_count = card->shift_count;
 	unsigned char flow_ctrl;
-	
+
 	if (!(tty = port->tty) || !tty->termios)
 		return;
 	baud = C_BAUD(tty);
 	if (baud & CBAUDEX) {
 		baud &= ~CBAUDEX;
-		
+
 		/*  if CBAUDEX bit is on and the baud is set to either 50 or 75
 		 *  then the card is programmed for 57.6Kbps or 115Kbps
 		 *  respectively.
-		 */   
-		 
+		 */
+
 		if (baud < 1 || baud > 2)
 			port->tty->termios->c_cflag &= ~CBAUDEX;
 		else
 			baud += 15;
-	}	
+	}
 	if (baud == 15) {
-	
-		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set 
+
+		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
 		 *  by the set_serial_info ioctl ... this is done by
 		 *  the 'setserial' utility.
-		 */  
-			
+		 */
+
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud++;     /*  57.6 Kbps */
+			baud++; /*  57.6 Kbps */
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud +=2;   /*  115  Kbps */	 
+			baud +=2; /*  115  Kbps */
 	}
 	if (linuxb_to_isib[baud] == -1) {
 		/* hang up */
-	 	drop_dtr(port);
-	 	return;
-	}	
-	else  
+		drop_dtr(port);
+		return;
+	}
+	else
 		raise_dtr(port);
-		
+
 	if (lock_card(card)) {
 		outw(0x8000 | (channel << shift_count) |0x03, base);
 		outw(linuxb_to_isib[baud] << 8 | 0x03, base);
 		channel_setup = 0;
 		switch(C_CSIZE(tty)) {
-			case CS5:
-				channel_setup |= ISICOM_CS5;
-				break;
-			case CS6:
-				channel_setup |= ISICOM_CS6;
-				break;
-			case CS7:
-				channel_setup |= ISICOM_CS7;
-				break;
-			case CS8:
-				channel_setup |= ISICOM_CS8;
-				break;
+		case CS5:
+			channel_setup |= ISICOM_CS5;
+			break;
+		case CS6:
+			channel_setup |= ISICOM_CS6;
+			break;
+		case CS7:
+			channel_setup |= ISICOM_CS7;
+			break;
+		case CS8:
+			channel_setup |= ISICOM_CS8;
+			break;
 		}
-			
+
 		if (C_CSTOPB(tty))
 			channel_setup |= ISICOM_2SB;
 		if (C_PARENB(tty)) {
 			channel_setup |= ISICOM_EVPAR;
 			if (C_PARODD(tty))
-				channel_setup |= ISICOM_ODPAR;	
+				channel_setup |= ISICOM_ODPAR;
 		}
-		outw(channel_setup, base);	
+		outw(channel_setup, base);
 		InterruptTheCard(base);
-		unlock_card(card);	
-	}	
+		unlock_card(card);
+	}
 	if (C_CLOCAL(tty))
 		port->flags &= ~ASYNC_CHECK_CD;
 	else
-		port->flags |= ASYNC_CHECK_CD;	
-	
+		port->flags |= ASYNC_CHECK_CD;
+
 	/* flow control settings ...*/
 	flow_ctrl = 0;
 	port->flags &= ~ASYNC_CTS_FLOW;
 	if (C_CRTSCTS(tty)) {
 		port->flags |= ASYNC_CTS_FLOW;
 		flow_ctrl |= ISICOM_CTSRTS;
-	}	
-	if (I_IXON(tty))	
+	}
+	if (I_IXON(tty))
 		flow_ctrl |= ISICOM_RESPOND_XONXOFF;
 	if (I_IXOFF(tty))
-		flow_ctrl |= ISICOM_INITIATE_XONXOFF;	
-		
+		flow_ctrl |= ISICOM_INITIATE_XONXOFF;
+
 	if (lock_card(card)) {
 		outw(0x8000 | (channel << shift_count) |0x04, base);
 		outw(flow_ctrl << 8 | 0x05, base);
@@ -1056,22 +816,22 @@
 		InterruptTheCard(base);
 		unlock_card(card);
 	}
-	
+
 	/*	rx enabled -> enable port for rx on the card	*/
 	if (C_CREAD(tty)) {
 		card->port_status |= (1 << channel);
 		outw(card->port_status, base + 0x02);
 	}
 }
- 
-/* open et all */ 
 
-static inline void isicom_setup_board(struct isi_board * bp)
+/* open et all */
+
+static inline void isicom_setup_board(struct isi_board *bp)
 {
 	int channel;
-	struct isi_port * port;
+	struct isi_port *port;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&bp->card_lock, flags);
 	if (bp->status & BOARD_ACTIVE) {
 		spin_unlock_irqrestore(&bp->card_lock, flags);
@@ -1080,53 +840,54 @@
 	port = bp->ports;
 	bp->status |= BOARD_ACTIVE;
 	spin_unlock_irqrestore(&bp->card_lock, flags);
-	for(channel = 0; channel < bp->port_count; channel++, port++)
+	for (channel = 0; channel < bp->port_count; channel++, port++)
 		drop_dtr_rts(port);
 	return;
 }
- 
-static int isicom_setup_port(struct isi_port * port)
+
+static int isicom_setup_port(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
+	struct isi_board *card = port->card;
 	unsigned long flags;
-	
+
 	if (port->flags & ASYNC_INITIALIZED) {
 		return 0;
 	}
 	if (!port->xmit_buf) {
 		unsigned long page;
-		
+
 		if (!(page = get_zeroed_page(GFP_KERNEL)))
 			return -ENOMEM;
-		
+
 		if (port->xmit_buf) {
 			free_page(page);
 			return -ERESTARTSYS;
 		}
-		port->xmit_buf = (unsigned char *) page;	
-	}	
+		port->xmit_buf = (unsigned char *) page;
+	}
 
 	spin_lock_irqsave(&card->card_lock, flags);
 	if (port->tty)
 		clear_bit(TTY_IO_ERROR, &port->tty->flags);
 	if (port->count == 1)
 		card->count++;
-		
+
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	
+
 	/*	discard any residual data	*/
 	kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
-	
+
 	isicom_config_port(port);
 	port->flags |= ASYNC_INITIALIZED;
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	
-	return 0;		
-} 
- 
-static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
+
+	return 0;
+}
+
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+	struct isi_port *port)
 {
-	struct isi_board * card = port->card;
+	struct isi_board *card = port->card;
 	int do_clocal = 0, retval;
 	unsigned long flags;
 	DECLARE_WAITQUEUE(wait, current);
@@ -1134,30 +895,27 @@
 	/* block if port is in the process of being closed */
 
 	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-#ifdef ISICOM_DEBUG	
-		printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
-#endif		
+		pr_dbg("block_til_ready: close in progress.\n");
 		interruptible_sleep_on(&port->close_wait);
 		if (port->flags & ASYNC_HUP_NOTIFY)
 			return -EAGAIN;
 		else
 			return -ERESTARTSYS;
 	}
-	
+
 	/* if non-blocking mode is set ... */
-	
-	if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
-#ifdef ISICOM_DEBUG	
-		printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
-#endif		
+
+	if ((filp->f_flags & O_NONBLOCK) ||
+			(tty->flags & (1 << TTY_IO_ERROR))) {
+		pr_dbg("block_til_ready: non-block mode.\n");
 		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;	
-	}	
-	
+		return 0;
+	}
+
 	if (C_CLOCAL(tty))
 		do_clocal = 1;
-	
-	/* block waiting for DCD to be asserted, and while 
+
+	/* block waiting for DCD to be asserted, and while
 						callout dev is busy */
 	retval = 0;
 	add_wait_queue(&port->open_wait, &wait);
@@ -1167,27 +925,27 @@
 		port->count--;
 	port->blocked_open++;
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	
+
 	while (1) {
 		raise_dtr_rts(port);
 
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { 	
+		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
 				retval = -EAGAIN;
 			else
 				retval = -ERESTARTSYS;
 			break;
-		}	
+		}
 		if (!(port->flags & ASYNC_CLOSING) &&
-		    (do_clocal || (port->status & ISI_DCD))) {
+				(do_clocal || (port->status & ISI_DCD))) {
 			break;
-		}	
+		}
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			break;
 		}
-		schedule();		
+		schedule();
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->open_wait, &wait);
@@ -1201,11 +959,11 @@
 	port->flags |= ASYNC_NORMAL_ACTIVE;
 	return 0;
 }
- 
-static int isicom_open(struct tty_struct * tty, struct file * filp)
+
+static int isicom_open(struct tty_struct *tty, struct file *filp)
 {
-	struct isi_port * port;
-	struct isi_board * card;
+	struct isi_port *port;
+	struct isi_board *card;
 	unsigned int line, board;
 	int error;
 
@@ -1214,20 +972,20 @@
 		return -ENODEV;
 	board = BOARD(line);
 	card = &isi_card[board];
-	
+
 	if (!(card->status & FIRMWARE_LOADED))
 		return -ENODEV;
-	
+
 	/*  open on a port greater than the port count for the card !!! */
 	if (line > ((board * 16) + card->port_count - 1))
 		return -ENODEV;
 
-	port = &isi_ports[line];	
+	port = &isi_ports[line];
 	if (isicom_paranoia_check(port, tty->name, "isicom_open"))
 		return -ENODEV;
-		
-	isicom_setup_board(card);		
-	
+
+	isicom_setup_board(card);
+
 	port->count++;
 	tty->driver_data = port;
 	port->tty = tty;
@@ -1236,12 +994,12 @@
 	if ((error = block_til_ready(tty, filp, port))!=0)
 		return error;
 
-	return 0;      		
+	return 0;
 }
- 
+
 /* close et all */
 
-static inline void isicom_shutdown_board(struct isi_board * bp)
+static inline void isicom_shutdown_board(struct isi_board *bp)
 {
 	unsigned long flags;
 
@@ -1252,15 +1010,15 @@
 	spin_unlock_irqrestore(&bp->card_lock, flags);
 }
 
-static void isicom_shutdown_port(struct isi_port * port)
+static void isicom_shutdown_port(struct isi_port *port)
 {
-	struct isi_board * card = port->card;
-	struct tty_struct * tty;	
+	struct isi_board *card = port->card;
+	struct tty_struct *tty;
 	unsigned long flags;
-	
+
 	tty = port->tty;
 
-	spin_lock_irqsave(&card->card_lock, flags);	
+	spin_lock_irqsave(&card->card_lock, flags);
 	if (!(port->flags & ASYNC_INITIALIZED)) {
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		return;
@@ -1268,93 +1026,91 @@
 	if (port->xmit_buf) {
 		free_page((unsigned long) port->xmit_buf);
 		port->xmit_buf = NULL;
-	}	
+	}
 	port->flags &= ~ASYNC_INITIALIZED;
 	/* 3rd October 2000 : Vinayak P Risbud */
 	port->tty = NULL;
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	
+
 	/*Fix done by Anil .S on 30-04-2001
 	remote login through isi port has dtr toggle problem
 	due to which the carrier drops before the password prompt
-	appears on the remote end. Now we drop the dtr only if the 
+	appears on the remote end. Now we drop the dtr only if the
 	HUPCL(Hangup on close) flag is set for the tty*/
-	
-	if (C_HUPCL(tty)) 
+
+	if (C_HUPCL(tty))
 		/* drop dtr on this port */
 		drop_dtr(port);
-		
-	/* any other port uninits  */ 
+
+	/* any other port uninits  */
 	if (tty)
 		set_bit(TTY_IO_ERROR, &tty->flags);
-	
+
 	if (--card->count < 0) {
-		printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
+		pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
 			card->base, card->count);
-		card->count = 0;	
+		card->count = 0;
 	}
-	
-	/* last port was closed , shutdown that boad too */
-	if(C_HUPCL(tty)) {
+
+	/* last port was closed, shutdown that boad too */
+	if (C_HUPCL(tty)) {
 		if (!card->count)
 			isicom_shutdown_board(card);
 	}
 }
 
-static void isicom_close(struct tty_struct * tty, struct file * filp)
+static void isicom_close(struct tty_struct *tty, struct file *filp)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
 	unsigned long flags;
-	
+
 	if (!port)
 		return;
 	if (isicom_paranoia_check(port, tty->name, "isicom_close"))
 		return;
-	
-#ifdef ISICOM_DEBUG		
-	printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
-#endif	
-	
+
+	pr_dbg("Close start!!!.\n");
+
 	spin_lock_irqsave(&card->card_lock, flags);
 	if (tty_hung_up_p(filp)) {
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		return;
 	}
-	
+
 	if (tty->count == 1 && port->count != 1) {
-		printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
-			"tty->count = 1	port count = %d.\n",
+		printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
+			"count tty->count = 1 port count = %d.\n",
 			card->base, port->count);
 		port->count = 1;
 	}
 	if (--port->count < 0) {
-		printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
-			"channel%d = %d", card->base, port->channel, 
+		printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
+			"count for channel%d = %d", card->base, port->channel,
 			port->count);
-		port->count = 0;	
+		port->count = 0;
 	}
-	
+
 	if (port->count) {
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		return;
-	} 	
+	}
 	port->flags |= ASYNC_CLOSING;
 	tty->closing = 1;
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	
+
 	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, port->closing_wait);
-	/* indicate to the card that no more data can be received 
+	/* indicate to the card that no more data can be received
 	   on this port */
 	spin_lock_irqsave(&card->card_lock, flags);
-	if (port->flags & ASYNC_INITIALIZED) {   
+	if (port->flags & ASYNC_INITIALIZED) {
 		card->port_status &= ~(1 << port->channel);
 		outw(card->port_status, card->base + 0x02);
-	}	
+	}
 	isicom_shutdown_port(port);
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	
+
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 	tty_ldisc_flush(tty);
@@ -1365,65 +1121,65 @@
 	if (port->blocked_open) {
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		if (port->close_delay) {
-#ifdef ISICOM_DEBUG			
-			printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
-#endif			
-			msleep_interruptible(jiffies_to_msecs(port->close_delay));
+			pr_dbg("scheduling until time out.\n");
+			msleep_interruptible(
+				jiffies_to_msecs(port->close_delay));
 		}
 		spin_lock_irqsave(&card->card_lock, flags);
 		wake_up_interruptible(&port->open_wait);
-	}	
+	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
 	wake_up_interruptible(&port->close_wait);
 	spin_unlock_irqrestore(&card->card_lock, flags);
 }
 
 /* write et all */
-static int isicom_write(struct tty_struct * tty,
-			const unsigned char * buf, int count)
+static int isicom_write(struct tty_struct *tty,	const unsigned char *buf,
+	int count)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
 	unsigned long flags;
 	int cnt, total = 0;
 
 	if (isicom_paranoia_check(port, tty->name, "isicom_write"))
 		return 0;
-	
-	if (!tty || !port->xmit_buf || !tmp_buf)
+
+	if (!tty || !port->xmit_buf)
 		return 0;
-		
+
 	spin_lock_irqsave(&card->card_lock, flags);
-	
-	while(1) {	
-		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					    SERIAL_XMIT_SIZE - port->xmit_head));
-		if (cnt <= 0) 
+
+	while(1) {
+		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
+				- 1, SERIAL_XMIT_SIZE - port->xmit_head));
+		if (cnt <= 0)
 			break;
-		
+
 		memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
-		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
+			- 1);
 		port->xmit_cnt += cnt;
 		buf += cnt;
 		count -= cnt;
 		total += cnt;
-	}		
+	}
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
 		port->status |= ISI_TXOK;
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	return total;	
+	return total;
 }
 
 /* put_char et all */
-static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
 	unsigned long flags;
-	
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
 		return;
-	
+
 	if (!tty || !port->xmit_buf)
 		return;
 
@@ -1432,7 +1188,7 @@
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		return;
 	}
-	
+
 	port->xmit_buf[port->xmit_head++] = ch;
 	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
 	port->xmit_cnt++;
@@ -1440,30 +1196,31 @@
 }
 
 /* flush_chars et all */
-static void isicom_flush_chars(struct tty_struct * tty)
+static void isicom_flush_chars(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	
+	struct isi_port *port = tty->driver_data;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
 		return;
-	
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !port->xmit_buf)
+
+	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+			!port->xmit_buf)
 		return;
-		
+
 	/* this tells the transmitter to consider this port for
 	   data output to the card ... that's the best we can do. */
-	port->status |= ISI_TXOK;	
+	port->status |= ISI_TXOK;
 }
 
 /* write_room et all */
-static int isicom_write_room(struct tty_struct * tty)
+static int isicom_write_room(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port *port = tty->driver_data;
 	int free;
 
 	if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
 		return 0;
-	
+
 	free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
 	if (free < 0)
 		free = 0;
@@ -1471,23 +1228,24 @@
 }
 
 /* chars_in_buffer et all */
-static int isicom_chars_in_buffer(struct tty_struct * tty)
+static int isicom_chars_in_buffer(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port *port = tty->driver_data;
 	if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
 		return 0;
 	return port->xmit_cnt;
 }
 
 /* ioctl et all */
-static inline void isicom_send_break(struct isi_port * port, unsigned long length)
+static inline void isicom_send_break(struct isi_port *port,
+	unsigned long length)
 {
-	struct isi_board * card = port->card;
-	unsigned short base = card->base;	
-	
-	if(!lock_card(card))
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+
+	if (!lock_card(card))
 		return;
-		
+
 	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
 	outw((length & 0xff) << 8 | 0x00, base);
 	outw((length & 0xff00), base);
@@ -1498,13 +1256,13 @@
 
 static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port *port = tty->driver_data;
 	/* just send the port status */
-	unsigned short status = port->status;
+	u16 status = port->status;
 
 	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
 		return -ENODEV;
-	
+
 	return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
 		((status & ISI_DTR) ? TIOCM_DTR : 0) |
 		((status & ISI_DCD) ? TIOCM_CAR : 0) |
@@ -1514,13 +1272,13 @@
 }
 
 static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
-			   unsigned int set, unsigned int clear)
+	unsigned int set, unsigned int clear)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	
+	struct isi_port *port = tty->driver_data;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
 		return -ENODEV;
-	
+
 	if (set & TIOCM_RTS)
 		raise_rts(port);
 	if (set & TIOCM_DTR)
@@ -1532,46 +1290,46 @@
 		drop_dtr(port);
 
 	return 0;
-}			
+}
 
-static int isicom_set_serial_info(struct isi_port * port,
-					struct serial_struct __user *info)
+static int isicom_set_serial_info(struct isi_port *port,
+	struct serial_struct __user *info)
 {
 	struct serial_struct newinfo;
 	int reconfig_port;
 
-	if(copy_from_user(&newinfo, info, sizeof(newinfo)))
+	if (copy_from_user(&newinfo, info, sizeof(newinfo)))
 		return -EFAULT;
-		
-	reconfig_port = ((port->flags & ASYNC_SPD_MASK) != 
-			 (newinfo.flags & ASYNC_SPD_MASK));
-	
+
+	reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
+		(newinfo.flags & ASYNC_SPD_MASK));
+
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((newinfo.close_delay != port->close_delay) ||
-		    (newinfo.closing_wait != port->closing_wait) ||
-		    ((newinfo.flags & ~ASYNC_USR_MASK) != 
-		     (port->flags & ~ASYNC_USR_MASK)))
+				(newinfo.closing_wait != port->closing_wait) ||
+				((newinfo.flags & ~ASYNC_USR_MASK) !=
+				(port->flags & ~ASYNC_USR_MASK)))
 			return -EPERM;
 		port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
 				(newinfo.flags & ASYNC_USR_MASK));
-	}	
+	}
 	else {
 		port->close_delay = newinfo.close_delay;
-		port->closing_wait = newinfo.closing_wait; 
-		port->flags = ((port->flags & ~ASYNC_FLAGS) | 
+		port->closing_wait = newinfo.closing_wait;
+		port->flags = ((port->flags & ~ASYNC_FLAGS) |
 				(newinfo.flags & ASYNC_FLAGS));
 	}
 	if (reconfig_port) {
 		isicom_config_port(port);
 	}
-	return 0;		 
-}		
+	return 0;
+}
 
-static int isicom_get_serial_info(struct isi_port * port, 
-					struct serial_struct __user *info)
+static int isicom_get_serial_info(struct isi_port *port,
+	struct serial_struct __user *info)
 {
 	struct serial_struct out_info;
-	
+
 	memset(&out_info, 0, sizeof(out_info));
 /*	out_info.type = ? */
 	out_info.line = port - isi_ports;
@@ -1581,15 +1339,15 @@
 /*	out_info.baud_base = ? */
 	out_info.close_delay = port->close_delay;
 	out_info.closing_wait = port->closing_wait;
-	if(copy_to_user(info, &out_info, sizeof(out_info)))
+	if (copy_to_user(info, &out_info, sizeof(out_info)))
 		return -EFAULT;
 	return 0;
-}					
+}
 
-static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
-			unsigned int cmd, unsigned long arg) 
+static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
+	unsigned int cmd, unsigned long arg)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port *port = tty->driver_data;
 	void __user *argp = (void __user *)arg;
 	int retval;
 
@@ -1597,139 +1355,141 @@
 		return -ENODEV;
 
 	switch(cmd) {
-		case TCSBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (!arg)
-				isicom_send_break(port, HZ/4);
-			return 0;
-			
-		case TCSBRKP:	
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
-			return 0;
-			
-		case TIOCGSOFTCAR:
-			return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
-			
-		case TIOCSSOFTCAR:
-			if(get_user(arg, (unsigned long __user *) argp))
-				return -EFAULT;
-			tty->termios->c_cflag =
-				((tty->termios->c_cflag & ~CLOCAL) |
-				(arg ? CLOCAL : 0));
-			return 0;	
-			
-		case TIOCGSERIAL:
-			return isicom_get_serial_info(port, argp);
-		
-		case TIOCSSERIAL:
-			return isicom_set_serial_info(port, argp);
-					
-		default:
-			return -ENOIOCTLCMD;						
+	case TCSBRK:
+		retval = tty_check_change(tty);
+		if (retval)
+			return retval;
+		tty_wait_until_sent(tty, 0);
+		if (!arg)
+			isicom_send_break(port, HZ/4);
+		return 0;
+
+	case TCSBRKP:
+		retval = tty_check_change(tty);
+		if (retval)
+			return retval;
+		tty_wait_until_sent(tty, 0);
+		isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+		return 0;
+
+	case TIOCGSOFTCAR:
+		return put_user(C_CLOCAL(tty) ? 1 : 0,
+				(unsigned long __user *)argp);
+
+	case TIOCSSOFTCAR:
+		if (get_user(arg, (unsigned long __user *) argp))
+			return -EFAULT;
+		tty->termios->c_cflag =
+			((tty->termios->c_cflag & ~CLOCAL) |
+			(arg ? CLOCAL : 0));
+		return 0;
+
+	case TIOCGSERIAL:
+		return isicom_get_serial_info(port, argp);
+
+	case TIOCSSERIAL:
+		return isicom_set_serial_info(port, argp);
+
+	default:
+		return -ENOIOCTLCMD;
 	}
 	return 0;
 }
 
 /* set_termios et all */
-static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void isicom_set_termios(struct tty_struct *tty,
+	struct termios *old_termios)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	
+	struct isi_port *port = tty->driver_data;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
 		return;
-	
+
 	if (tty->termios->c_cflag == old_termios->c_cflag &&
-	    tty->termios->c_iflag == old_termios->c_iflag)
+			tty->termios->c_iflag == old_termios->c_iflag)
 		return;
-		
+
 	isicom_config_port(port);
-	
+
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {	
+			!(tty->termios->c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
-		isicom_start(tty);   
-	}    
+		isicom_start(tty);
+	}
 }
 
 /* throttle et all */
-static void isicom_throttle(struct tty_struct * tty)
+static void isicom_throttle(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
-	
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
 		return;
-	
+
 	/* tell the card that this port cannot handle any more data for now */
 	card->port_status &= ~(1 << port->channel);
 	outw(card->port_status, card->base + 0x02);
 }
 
 /* unthrottle et all */
-static void isicom_unthrottle(struct tty_struct * tty)
+static void isicom_unthrottle(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
-	
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
 		return;
-	
+
 	/* tell the card that this port is ready to accept more data */
 	card->port_status |= (1 << port->channel);
 	outw(card->port_status, card->base + 0x02);
 }
 
 /* stop et all */
-static void isicom_stop(struct tty_struct * tty)
+static void isicom_stop(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port *port = tty->driver_data;
 
 	if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
 		return;
-	
+
 	/* this tells the transmitter not to consider this port for
 	   data output to the card. */
 	port->status &= ~ISI_TXOK;
 }
 
 /* start et all */
-static void isicom_start(struct tty_struct * tty)
+static void isicom_start(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	
+	struct isi_port *port = tty->driver_data;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_start"))
 		return;
-	
+
 	/* this tells the transmitter to consider this port for
 	   data output to the card. */
 	port->status |= ISI_TXOK;
 }
 
 /* hangup et all */
-static void do_isicom_hangup(void * data)
+static void do_isicom_hangup(void *data)
 {
-	struct isi_port * port = (struct isi_port *) data;
-	struct tty_struct * tty;
-	
+	struct isi_port *port = data;
+	struct tty_struct *tty;
+
 	tty = port->tty;
 	if (tty)
 		tty_hangup(tty);
 }
 
-static void isicom_hangup(struct tty_struct * tty)
+static void isicom_hangup(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	
+	struct isi_port *port = tty->driver_data;
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
 		return;
-	
+
 	isicom_shutdown_port(port);
 	port->count = 0;
 	port->flags &= ~ASYNC_NORMAL_ACTIVE;
@@ -1738,220 +1498,535 @@
 }
 
 /* flush_buffer et all */
-static void isicom_flush_buffer(struct tty_struct * tty)
+static void isicom_flush_buffer(struct tty_struct *tty)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
 	unsigned long flags;
-	
+
 	if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
 		return;
-	
+
 	spin_lock_irqsave(&card->card_lock, flags);
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	
+
 	wake_up_interruptible(&tty->write_wait);
 	tty_wakeup(tty);
 }
 
+/*
+ * Driver init and deinit functions
+ */
 
-static int __devinit register_ioregion(void)
+static int __devinit isicom_register_ioregion(struct pci_dev *pdev,
+	const unsigned int index)
 {
-	int count, done=0;
-	for (count=0; count < BOARD_COUNT; count++ ) {
-		if (isi_card[count].base)
-			if (!request_region(isi_card[count].base,16,ISICOM_NAME)) {
-				printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
-					isi_card[count].base,isi_card[count].base+15,count+1);
-				isi_card[count].base=0;
-				done++;
-			}
-	}
-	return done;
+	struct isi_board *board = pci_get_drvdata(pdev);
+
+	if (!board->base)
+		return -EINVAL;
+
+	if (!request_region(board->base, 16, ISICOM_NAME)) {
+		dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
+			"will be disabled.\n", board->base, board->base + 15,
+			index + 1);
+		return -EBUSY;
+ 	}
+
+	return 0;
 }
 
-static void unregister_ioregion(void)
+static void isicom_unregister_ioregion(struct pci_dev *pdev)
 {
-	int count;
-	for (count=0; count < BOARD_COUNT; count++ ) 
-		if (isi_card[count].base) {
-			release_region(isi_card[count].base,16);
-#ifdef ISICOM_DEBUG			
-			printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
-#endif			
-		}
+	struct isi_board *board = pci_get_drvdata(pdev);
+
+	if (!board->base)
+		return;
+
+	release_region(board->base, 16);
+	dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n",
+		board->base, board->base + 15);
+	board->base = 0;
 }
 
 static struct tty_operations isicom_ops = {
-	.open	= isicom_open,
-	.close	= isicom_close,
-	.write	= isicom_write,
-	.put_char	= isicom_put_char,
-	.flush_chars	= isicom_flush_chars,
-	.write_room	= isicom_write_room,
+	.open			= isicom_open,
+	.close			= isicom_close,
+	.write			= isicom_write,
+	.put_char		= isicom_put_char,
+	.flush_chars		= isicom_flush_chars,
+	.write_room		= isicom_write_room,
 	.chars_in_buffer	= isicom_chars_in_buffer,
-	.ioctl	= isicom_ioctl,
-	.set_termios	= isicom_set_termios,
-	.throttle	= isicom_throttle,
-	.unthrottle	= isicom_unthrottle,
-	.stop	= isicom_stop,
-	.start	= isicom_start,
-	.hangup	= isicom_hangup,
-	.flush_buffer	= isicom_flush_buffer,
-	.tiocmget	= isicom_tiocmget,
-	.tiocmset	= isicom_tiocmset,
+	.ioctl			= isicom_ioctl,
+	.set_termios		= isicom_set_termios,
+	.throttle		= isicom_throttle,
+	.unthrottle		= isicom_unthrottle,
+	.stop			= isicom_stop,
+	.start			= isicom_start,
+	.hangup			= isicom_hangup,
+	.flush_buffer		= isicom_flush_buffer,
+	.tiocmget		= isicom_tiocmget,
+	.tiocmset		= isicom_tiocmset,
 };
 
-static int __devinit register_drivers(void)
+static int __devinit isicom_register_tty_driver(void)
 {
-	int error;
+	int error = -ENOMEM;
 
 	/* tty driver structure initialization */
 	isicom_normal = alloc_tty_driver(PORT_COUNT);
 	if (!isicom_normal)
-		return -ENOMEM;
+		goto end;
 
-	isicom_normal->owner	= THIS_MODULE;
-	isicom_normal->name 	= "ttyM";
-	isicom_normal->devfs_name = "isicom/";
-	isicom_normal->major	= ISICOM_NMAJOR;
-	isicom_normal->minor_start	= 0;
-	isicom_normal->type	= TTY_DRIVER_TYPE_SERIAL;
-	isicom_normal->subtype	= SERIAL_TYPE_NORMAL;
-	isicom_normal->init_termios	= tty_std_termios;
-	isicom_normal->init_termios.c_cflag	= 
-				B9600 | CS8 | CREAD | HUPCL |CLOCAL;
-	isicom_normal->flags	= TTY_DRIVER_REAL_RAW;
+	isicom_normal->owner			= THIS_MODULE;
+	isicom_normal->name 			= "ttyM";
+	isicom_normal->devfs_name	 	= "isicom/";
+	isicom_normal->major			= ISICOM_NMAJOR;
+	isicom_normal->minor_start		= 0;
+	isicom_normal->type			= TTY_DRIVER_TYPE_SERIAL;
+	isicom_normal->subtype			= SERIAL_TYPE_NORMAL;
+	isicom_normal->init_termios		= tty_std_termios;
+	isicom_normal->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL |
+		CLOCAL;
+	isicom_normal->flags			= TTY_DRIVER_REAL_RAW;
 	tty_set_operations(isicom_normal, &isicom_ops);
-	
-	if ((error=tty_register_driver(isicom_normal))!=0) {
-		printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
+
+	if ((error = tty_register_driver(isicom_normal))) {
+		pr_dbg("Couldn't register the dialin driver, error=%d\n",
 			error);
 		put_tty_driver(isicom_normal);
-		return error;
 	}
-	return 0;
+end:
+	return error;
 }
 
-static void unregister_drivers(void)
+static void isicom_unregister_tty_driver(void)
 {
-	int error = tty_unregister_driver(isicom_normal);
-	if (error)
-		printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+	int error;
+
+	if ((error = tty_unregister_driver(isicom_normal)))
+		pr_dbg("couldn't unregister normal driver, error=%d.\n", error);
+
 	put_tty_driver(isicom_normal);
 }
 
-static int __devinit register_isr(void)
+static int __devinit isicom_register_isr(struct pci_dev *pdev,
+	const unsigned int index)
 {
-	int count, done=0;
-	unsigned long irqflags;
+	struct isi_board *board = pci_get_drvdata(pdev);
+	unsigned long irqflags = SA_INTERRUPT;
+	int retval = -EINVAL;
 
-	for (count=0; count < BOARD_COUNT; count++ ) {
-		if (isi_card[count].base) {
-			irqflags = (isi_card[count].isa == YES) ? 
-					SA_INTERRUPT : 
-					(SA_INTERRUPT | SA_SHIRQ);
+	if (!board->base)
+		goto end;
 
-			if (request_irq(isi_card[count].irq, 
-					isicom_interrupt, 
-					irqflags, 
-					ISICOM_NAME, &isi_card[count])) {
+	if (board->isa == NO)
+		irqflags |= SA_SHIRQ;
 
-				printk(KERN_WARNING "ISICOM: Could not"
-					" install handler at Irq %d."
-					" Card%d will be disabled.\n",
-					isi_card[count].irq, count+1);
+	retval = request_irq(board->irq, isicom_interrupt, irqflags,
+		ISICOM_NAME, board);
+	if (retval < 0)
+		dev_warn(&pdev->dev, "Could not install handler at Irq %d. "
+			"Card%d will be disabled.\n", board->irq, index + 1);
+ 	else
+		retval = 0;
+end:
+	return retval;
+}
 
-				release_region(isi_card[count].base,16);
-				isi_card[count].base=0;
+static int __devinit reset_card(struct pci_dev *pdev,
+	const unsigned int card, unsigned int *signature)
+{
+	struct isi_board *board = pci_get_drvdata(pdev);
+	unsigned long base = board->base;
+	unsigned int portcount = 0;
+	int retval = 0;
+
+	dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
+		base);
+
+	inw(base + 0x8);
+
+	mdelay(10);
+
+	outw(0, base + 0x8); /* Reset */
+
+	msleep(3000);
+
+	*signature = inw(base + 0x4) & 0xff;
+
+	if (board->isa == YES) {
+		if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) {
+			dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+				inw(base + 0x2), inw(base + 0xe));
+			dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure "
+				"(Possible bad I/O Port Address 0x%lx).\n",
+				card + 1, base);
+			retval = -EIO;
+			goto end;
+		}
+	} else {
+		portcount = inw(base + 0x2);
+		if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
+				(portcount != 4) && (portcount != 8))) {
+			dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+				inw(base + 0x2), inw(base + 0xe));
+			dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
+				"(Possible bad I/O Port Address 0x%lx).\n",
+				card + 1, base);
+			retval = -EIO;
+			goto end;
+		}
+	}
+
+	switch (*signature) {
+	case 0xa5:
+	case 0xbb:
+	case 0xdd:
+		board->port_count = (board->isa == NO && portcount == 4) ? 4 :
+			8;
+		board->shift_count = 12;
+		break;
+	case 0xcc:
+		board->port_count = 16;
+		board->shift_count = 11;
+		break;
+	default:
+		dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible "
+			"bad I/O Port Address 0x%lx).\n", card + 1, base);
+		dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature);
+		retval = -EIO;
+	}
+	dev_info(&pdev->dev, "-Done\n");
+
+end:
+	return retval;
+}
+
+static inline int WaitTillCardIsFree(u16 base)
+{
+	unsigned long count = 0;
+
+	while (!(inw(base + 0xe) & 0x1) && count++ < 100)
+		msleep(5);
+
+	return !(inw(base + 0xe) & 0x1);
+}
+
+static int __devinit load_firmware(struct pci_dev *pdev,
+	const unsigned int index, const unsigned int signature)
+{
+	struct isi_board *board = pci_get_drvdata(pdev);
+	const struct firmware *fw;
+	unsigned long base = board->base;
+	unsigned int a;
+	u16 word_count, status;
+	int retval = -EIO;
+	char *name;
+	u8 *data;
+
+	struct stframe {
+		u16	addr;
+		u16	count;
+		u8	data[0];
+	} *frame;
+
+	switch (signature) {
+	case 0xa5:
+		name = "isi608.bin";
+		break;
+	case 0xbb:
+		name = "isi608em.bin";
+		break;
+	case 0xcc:
+		name = "isi616em.bin";
+		break;
+	case 0xdd:
+		name = "isi4608.bin";
+		break;
+	case 0xee:
+		name = "isi4616.bin";
+		break;
+	default:
+		dev_err(&pdev->dev, "Unknown signature.\n");
+		goto end;
+ 	}
+
+	retval = request_firmware(&fw, name, &pdev->dev);
+	if (retval)
+		goto end;
+
+	for (frame = (struct stframe *)fw->data;
+			frame < (struct stframe *)(fw->data + fw->size);
+			frame++) {
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		outw(0xf0, base);	/* start upload sequence */
+		outw(0x00, base);
+		outw(frame->addr, base); /* lsb of address */
+
+		word_count = frame->count / 2 + frame->count % 2;
+		outw(word_count, base);
+		InterruptTheCard(base);
+
+		udelay(100); /* 0x2f */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		if ((status = inw(base + 0x4)) != 0) {
+			dev_warn(&pdev->dev, "Card%d rejected load header:\n"
+				"Address:0x%x\nCount:0x%x\nStatus:0x%x\n",
+				index + 1, frame->addr, frame->count, status);
+			goto errrelfw;
+		}
+		outsw(base, frame->data, word_count);
+
+		InterruptTheCard(base);
+
+		udelay(50); /* 0x0f */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		if ((status = inw(base + 0x4)) != 0) {
+			dev_err(&pdev->dev, "Card%d got out of sync.Card "
+				"Status:0x%x\n", index + 1, status);
+			goto errrelfw;
+		}
+ 	}
+
+	retval = -EIO;
+
+	if (WaitTillCardIsFree(base))
+		goto errrelfw;
+
+	outw(0xf2, base);
+	outw(0x800, base);
+	outw(0x0, base);
+	outw(0x0, base);
+	InterruptTheCard(base);
+	outw(0x0, base + 0x4); /* for ISI4608 cards */
+
+/* XXX: should we test it by reading it back and comparing with original like
+ * in load firmware package? */
+	for (frame = (struct stframe*)fw->data;
+			frame < (struct stframe*)(fw->data + fw->size);
+			frame++) {
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		outw(0xf1, base); /* start download sequence */
+		outw(0x00, base);
+		outw(frame->addr, base); /* lsb of address */
+
+		word_count = (frame->count >> 1) + frame->count % 2;
+		outw(word_count + 1, base);
+		InterruptTheCard(base);
+
+		udelay(50); /* 0xf */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		if ((status = inw(base + 0x4)) != 0) {
+			dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
+				"Address:0x%x\nCount:0x%x\nStatus: 0x%x\n",
+				index + 1, frame->addr, frame->count, status);
+			goto errrelfw;
+		}
+
+		data = kmalloc(word_count * 2, GFP_KERNEL);
+		inw(base);
+		insw(base, data, word_count);
+		InterruptTheCard(base);
+
+		for (a = 0; a < frame->count; a++)
+			if (data[a] != frame->data[a]) {
+				kfree(data);
+				dev_err(&pdev->dev, "Card%d, firmware upload "
+					"failed\n", index + 1);
+				goto errrelfw;
 			}
-			else
-				done++;
-		}	
-	}
-	return done;
-}
+		kfree(data);
 
-static void __exit unregister_isr(void)
-{
-	int count;
+		udelay(50); /* 0xf */
 
-	for (count=0; count < BOARD_COUNT; count++ ) {
-		if (isi_card[count].base)
-			free_irq(isi_card[count].irq, &isi_card[count]);
-	}
-}
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
 
-static int __devinit isicom_init(void)
-{
-	int card, channel, base;
-	struct isi_port * port;
-	unsigned long page;
-	
-	if (!tmp_buf) { 
-		page = get_zeroed_page(GFP_KERNEL);
-	      	if (!page) {
-#ifdef ISICOM_DEBUG	      	
-	      		printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
-#else
-			printk(KERN_ERR "ISICOM: Not enough memory...\n");
-#endif	      
-	      		return 0;
-	      	}	
-	      	tmp_buf = (unsigned char *) page;
+		if ((status = inw(base + 0x4)) != 0) {
+			dev_err(&pdev->dev, "Card%d verify got out of sync. "
+				"Card Status:0x%x\n", index + 1, status);
+			goto errrelfw;
+		}
 	}
-	
-	if (!register_ioregion()) 
-	{
-		printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
-		free_page((unsigned long)tmp_buf);
-		return 0;
-	}
-	if (register_drivers()) 
-	{
-		unregister_ioregion();
-		free_page((unsigned long)tmp_buf);
-		return 0;
-	}
-	if (!register_isr()) 
-	{
-		unregister_drivers();
-		/*  ioports already uregistered in register_isr */
-		free_page((unsigned long)tmp_buf);
-		return 0;		
-	}
-	
-	memset(isi_ports, 0, sizeof(isi_ports));
-	for (card = 0; card < BOARD_COUNT; card++) {
-		port = &isi_ports[card * 16];
-		isi_card[card].ports = port;
-		spin_lock_init(&isi_card[card].card_lock);
-		base = isi_card[card].base;
-		for (channel = 0; channel < 16; channel++, port++) {
-			port->magic = ISICOM_MAGIC;
-			port->card = &isi_card[card];
-			port->channel = channel;
-		 	port->close_delay = 50 * HZ/100;
-		 	port->closing_wait = 3000 * HZ/100;
-		 	INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
-		 	INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
-		 	port->status = 0;
-			init_waitqueue_head(&port->open_wait);	 				
-			init_waitqueue_head(&port->close_wait);
-			/*  . . .  */
- 		}
-	} 
-	
-	return 1;	
+
+	board->status |= FIRMWARE_LOADED;
+	retval = 0;
+
+errrelfw:
+	release_firmware(fw);
+end:
+	return retval;
 }
 
 /*
  *	Insmod can set static symbols so keep these static
  */
- 
 static int io[4];
 static int irq[4];
+static int card;
+
+static int __devinit isicom_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	unsigned int ioaddr, signature, index;
+	int retval = -EPERM;
+	u8 pciirq;
+	struct isi_board *board = NULL;
+
+	if (card >= BOARD_COUNT)
+		goto err;
+
+	ioaddr = pci_resource_start(pdev, 3);
+	/* i.e at offset 0x1c in the PCI configuration register space. */
+	pciirq = pdev->irq;
+	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
+
+	/* allot the first empty slot in the array */
+	for (index = 0; index < BOARD_COUNT; index++)
+		if (isi_card[index].base == 0) {
+			board = &isi_card[index];
+			break;
+		}
+
+	board->base = ioaddr;
+	board->irq = pciirq;
+	board->isa = NO;
+	card++;
+
+	pci_set_drvdata(pdev, board);
+
+	retval = isicom_register_ioregion(pdev, index);
+	if (retval < 0)
+		goto err;
+
+	retval = isicom_register_isr(pdev, index);
+	if (retval < 0)
+		goto errunrr;
+
+	retval = reset_card(pdev, index, &signature);
+	if (retval < 0)
+		goto errunri;
+
+	retval = load_firmware(pdev, index, signature);
+	if (retval < 0)
+		goto errunri;
+
+	return 0;
+
+errunri:
+	free_irq(board->irq, board);
+errunrr:
+	isicom_unregister_ioregion(pdev);
+err:
+	board->base = 0;
+	return retval;
+}
+
+static void __devexit isicom_remove(struct pci_dev *pdev)
+{
+	struct isi_board *board = pci_get_drvdata(pdev);
+
+	free_irq(board->irq, board);
+	isicom_unregister_ioregion(pdev);
+}
+
+static int __devinit isicom_setup(void)
+{
+	int retval, idx, channel;
+	struct isi_port *port;
+
+	card = 0;
+	memset(isi_ports, 0, sizeof(isi_ports));
+
+	for(idx = 0; idx < BOARD_COUNT; idx++) {
+		port = &isi_ports[idx * 16];
+		isi_card[idx].ports = port;
+		spin_lock_init(&isi_card[idx].card_lock);
+		for (channel = 0; channel < 16; channel++, port++) {
+			port->magic = ISICOM_MAGIC;
+			port->card = &isi_card[idx];
+			port->channel = channel;
+			port->close_delay = 50 * HZ/100;
+			port->closing_wait = 3000 * HZ/100;
+			INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
+			INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
+			port->status = 0;
+			init_waitqueue_head(&port->open_wait);
+			init_waitqueue_head(&port->close_wait);
+			/*  . . .  */
+ 		}
+		isi_card[idx].base = 0;
+		isi_card[idx].irq = 0;
+
+		if (!io[idx])
+			continue;
+
+		if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4	||
+				irq[idx] == 5	|| irq[idx] == 7	||
+				irq[idx] == 10	|| irq[idx] == 11	||
+				irq[idx] == 12	|| irq[idx] == 15) {
+			printk(KERN_ERR "ISICOM: ISA not supported yet.\n");
+			retval = -EINVAL;
+			goto error;
+		} else
+			printk(KERN_ERR "ISICOM: Irq %d unsupported. "
+				"Disabling Card%d...\n", irq[idx], idx + 1);
+	}
+
+	retval = isicom_register_tty_driver();
+	if (retval < 0)
+		goto error;
+
+	retval = pci_register_driver(&isicom_driver);
+	if (retval < 0) {
+		printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
+		goto errtty;
+	}
+
+	init_timer(&tx);
+	tx.expires = jiffies + 1;
+	tx.data = 0;
+	tx.function = isicom_tx;
+	re_schedule = 1;
+	add_timer(&tx);
+
+	return 0;
+errtty:
+	isicom_unregister_tty_driver();
+error:
+	return retval;
+}
+
+static void __exit isicom_exit(void)
+{
+	unsigned int index = 0;
+
+	re_schedule = 0;
+
+	while (re_schedule != 2 && index++ < 100)
+		msleep(10);
+
+	pci_unregister_driver(&isicom_driver);
+	isicom_unregister_tty_driver();
+}
+
+module_init(isicom_setup);
+module_exit(isicom_exit);
 
 MODULE_AUTHOR("MultiTech");
 MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
@@ -1960,120 +2035,3 @@
 MODULE_PARM_DESC(io, "I/O ports for the cards");
 module_param_array(irq, int, NULL, 0);
 MODULE_PARM_DESC(irq, "Interrupts for the cards");
-
-static int __devinit isicom_setup(void)
-{
-	struct pci_dev *dev = NULL;
-	int retval, card, idx, count;
-	unsigned char pciirq;
-	unsigned int ioaddr;
-	                
-	card = 0;
-	for(idx=0; idx < BOARD_COUNT; idx++) {	
-		if (io[idx]) {
-			isi_card[idx].base=io[idx];
-			isi_card[idx].irq=irq[idx];
-			isi_card[idx].isa=YES;
-			card++;
-		}
-		else {
-			isi_card[idx].base = 0;
-			isi_card[idx].irq = 0;
-		}
-	}
-	
-	for (idx=0 ;idx < card; idx++) {
-		if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
-		    (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
-		    (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
-		    (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
-		    (isi_card[idx].irq==15))) {
-			
-			if (isi_card[idx].base) {
-				printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
-					isi_card[idx].irq, idx+1);
-				isi_card[idx].base=0;
-				card--;
-			}	
-		}
-	}	
-	
-	if (card < BOARD_COUNT) {
-		for (idx=0; idx < DEVID_COUNT; idx++) {
-			dev = NULL;
-			for (;;){
-				if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev)))
-					break;
-				if (card >= BOARD_COUNT)
-					break;
-					
-				if (pci_enable_device(dev))
-					break;
-
-				/* found a PCI ISI card! */
-				ioaddr = pci_resource_start (dev, 3); /* i.e at offset 0x1c in the
-								       * PCI configuration register
-								       * space.
-								       */
-				pciirq = dev->irq;
-				printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl[idx].device);
-				/*
-				 * allot the first empty slot in the array
-				 */				
-				for (count=0; count < BOARD_COUNT; count++) {				
-					if (isi_card[count].base == 0) {
-						isi_card[count].base = ioaddr;
-						isi_card[count].irq = pciirq;
-						isi_card[count].isa = NO;
-						card++;
-						break;
-					}
-				}
-			}				
-			if (card >= BOARD_COUNT) break;
-		}
-	}
-	
-	if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
-		printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); 
-		return -EIO;
-	}	
-
-	retval = misc_register(&isiloader_device);
-	if (retval < 0) {
-		printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
-		return retval;
-	}
-	
-	if (!isicom_init()) {
-		if (misc_deregister(&isiloader_device)) 
-			printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
-		return -EIO;
-	}
-	
-	init_timer(&tx);
-	tx.expires = jiffies + 1;
-	tx.data = 0;
-	tx.function = isicom_tx;
-	re_schedule = 1;
-	add_timer(&tx);
-	
-	return 0;
-}
-
-static void __exit isicom_exit(void)
-{
-	re_schedule = 0;
-	/* FIXME */
-	msleep(1000);
-	unregister_isr();
-	unregister_drivers();
-	unregister_ioregion();	
-	if(tmp_buf)
-		free_page((unsigned long)tmp_buf);
-	if (misc_deregister(&isiloader_device))
-		printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
-}
-
-module_init(isicom_setup);
-module_exit(isicom_exit);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index ce3bc0d..28c5a31 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -135,7 +135,7 @@
 	/*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
 };
 
-static int	stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
+static int	stli_nrbrds = ARRAY_SIZE(stli_brdconf);
 
 /*
  *	There is some experimental EISA board detection code in this driver.
@@ -406,7 +406,7 @@
 	0xff000000, 0xff010000, 0xff020000, 0xff030000,
 };
 
-static int	stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
+static int	stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
 
 /*
  *	Define the Stallion PCI vendor and device IDs.
@@ -899,15 +899,13 @@
 {
 	stlconf_t	conf;
 	stlibrd_t	*brdp;
-	int		nrargs, i;
+	int		i;
 
 #ifdef DEBUG
 	printk("stli_argbrds()\n");
 #endif
 
-	nrargs = sizeof(stli_brdsp) / sizeof(char **);
-
-	for (i = stli_nrbrds; (i < nrargs); i++) {
+	for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) {
 		memset(&conf, 0, sizeof(conf));
 		if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
 			continue;
@@ -967,7 +965,7 @@
 static int stli_parsebrd(stlconf_t *confp, char **argp)
 {
 	char	*sp;
-	int	nrbrdnames, i;
+	int	i;
 
 #ifdef DEBUG
 	printk("stli_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
@@ -979,14 +977,13 @@
 	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
 		*sp = TOLOWER(*sp);
 
-	nrbrdnames = sizeof(stli_brdstr) / sizeof(stlibrdtype_t);
-	for (i = 0; (i < nrbrdnames); i++) {
+	for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
 		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
 			break;
 	}
-	if (i >= nrbrdnames) {
+	if (i == ARRAY_SIZE(stli_brdstr)) {
 		printk("STALLION: unknown board name, %s?\n", argp[0]);
-		return(0);
+		return 0;
 	}
 
 	confp->brdtype = stli_brdstr[i].type;
@@ -2714,17 +2711,13 @@
 		stlen = size - tail;
 	}
 
-	len = MIN(len, (TTY_FLIPBUF_SIZE - tty->flip.count));
+	len = tty_buffer_request_room(tty, len);
+	/* FIXME : iomap ? */
 	shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
 
 	while (len > 0) {
 		stlen = MIN(len, stlen);
-		memcpy(tty->flip.char_buf_ptr, (char *) (shbuf + tail), stlen);
-		memset(tty->flip.flag_buf_ptr, 0, stlen);
-		tty->flip.char_buf_ptr += stlen;
-		tty->flip.flag_buf_ptr += stlen;
-		tty->flip.count += stlen;
-
+		tty_insert_flip_string(tty, (char *)(shbuf + tail), stlen);
 		len -= stlen;
 		tail += stlen;
 		if (tail >= size) {
@@ -2909,16 +2902,12 @@
 
 		if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
 			if (tty != (struct tty_struct *) NULL) {
-				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-					tty->flip.count++;
-					*tty->flip.flag_buf_ptr++ = TTY_BREAK;
-					*tty->flip.char_buf_ptr++ = 0;
-					if (portp->flags & ASYNC_SAK) {
-						do_SAK(tty);
-						EBRDENABLE(brdp);
-					}
-					tty_schedule_flip(tty);
+				tty_insert_flip_char(tty, 0, TTY_BREAK);
+				if (portp->flags & ASYNC_SAK) {
+					do_SAK(tty);
+					EBRDENABLE(brdp);
 				}
+				tty_schedule_flip(tty);
 			}
 		}
 
@@ -4943,7 +4932,7 @@
 	if (portp->tty != (struct tty_struct *) NULL) {
 		if (portp->tty->driver_data == portp) {
 			stli_comstats.ttystate = portp->tty->flags;
-			stli_comstats.rxbuffered = portp->tty->flip.count;
+			stli_comstats.rxbuffered = -1 /*portp->tty->flip.count*/;
 			if (portp->tty->termios != (struct termios *) NULL) {
 				stli_comstats.cflags = portp->tty->termios->c_cflag;
 				stli_comstats.iflags = portp->tty->termios->c_iflag;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 79e490e..5e3ef55 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -269,7 +269,7 @@
 static int MoxaPortDCDON(int);
 static void MoxaPortFlushData(int, int);
 static int MoxaPortWriteData(int, unsigned char *, int);
-static int MoxaPortReadData(int, unsigned char *, int);
+static int MoxaPortReadData(int, struct tty_struct *tty);
 static int MoxaPortTxQueue(int);
 static int MoxaPortRxQueue(int);
 static int MoxaPortTxFree(int);
@@ -301,6 +301,8 @@
 	.tiocmset = moxa_tiocmset,
 };
 
+static spinlock_t moxa_lock = SPIN_LOCK_UNLOCKED;
+
 #ifdef CONFIG_PCI
 static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
 {
@@ -448,7 +450,7 @@
 #ifdef CONFIG_PCI
 	{
 		struct pci_dev *p = NULL;
-		int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
+		int n = ARRAY_SIZE(moxa_pcibrds) - 1;
 		i = 0;
 		while (i < n) {
 			while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
@@ -645,10 +647,10 @@
 	if (ch == NULL)
 		return (0);
 	port = ch->port;
-	save_flags(flags);
-	cli();
+
+	spin_lock_irqsave(&moxa_lock, flags);
 	len = MoxaPortWriteData(port, (unsigned char *) buf, count);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&moxa_lock, flags);
 
 	/*********************************************
 	if ( !(ch->statusflags & LOWWAIT) &&
@@ -723,11 +725,10 @@
 	if (ch == NULL)
 		return;
 	port = ch->port;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&moxa_lock, flags);
 	moxaXmitBuff[0] = c;
 	MoxaPortWriteData(port, moxaXmitBuff, 1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&moxa_lock, flags);
 	/************************************************
 	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
 	*************************************************/
@@ -1030,12 +1031,12 @@
 	printk("block_til_ready before block: ttys%d, count = %d\n",
 	       ch->line, ch->count);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&moxa_lock, flags);
 	if (!tty_hung_up_p(filp))
 		ch->count--;
-	restore_flags(flags);
 	ch->blocked_open++;
+	spin_unlock_irqrestore(&moxa_lock, flags);
+
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
@@ -1062,17 +1063,21 @@
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&ch->open_wait, &wait);
+
+	spin_lock_irqsave(&moxa_lock, flags);
 	if (!tty_hung_up_p(filp))
 		ch->count++;
 	ch->blocked_open--;
+	spin_unlock_irqrestore(&moxa_lock, flags);
 #ifdef SERIAL_DEBUG_OPEN
 	printk("block_til_ready after blocking: ttys%d, count = %d\n",
 	       ch->line, ch->count);
 #endif
 	if (retval)
 		return (retval);
+	/* FIXME: review to see if we need to use set_bit on these */
 	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-	return (0);
+	return 0;
 }
 
 static void setup_empty_event(struct tty_struct *tty)
@@ -1080,15 +1085,14 @@
 	struct moxa_str *ch = tty->driver_data;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&moxa_lock, flags);
 	ch->statusflags |= EMPTYWAIT;
 	moxaEmptyTimer_on[ch->port] = 0;
 	del_timer(&moxaEmptyTimer[ch->port]);
 	moxaEmptyTimer[ch->port].expires = jiffies + HZ;
 	moxaEmptyTimer_on[ch->port] = 1;
 	add_timer(&moxaEmptyTimer[ch->port]);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&moxa_lock, flags);
 }
 
 static void check_xmit_empty(unsigned long data)
@@ -1135,8 +1139,6 @@
 {
 	struct tty_struct *tp;
 	struct termios *ts;
-	int i, count, rc, space;
-	unsigned char *charptr, *flagptr;
 	unsigned long flags;
 
 	ts = NULL;
@@ -1150,24 +1152,10 @@
 		MoxaPortFlushData(ch->port, 0);
 		return;
 	}
-	space = TTY_FLIPBUF_SIZE - tp->flip.count;
-	if (space <= 0)
-		return;
-	charptr = tp->flip.char_buf_ptr;
-	flagptr = tp->flip.flag_buf_ptr;
-	rc = tp->flip.count;
-	save_flags(flags);
-	cli();
-	count = MoxaPortReadData(ch->port, charptr, space);
-	restore_flags(flags);
-	for (i = 0; i < count; i++)
-		*flagptr++ = 0;
-	charptr += count;
-	rc += count;
-	tp->flip.count = rc;
-	tp->flip.char_buf_ptr = charptr;
-	tp->flip.flag_buf_ptr = flagptr;
-	tty_schedule_flip(ch->tty);
+	spin_lock_irqsave(&moxa_lock, flags);
+	MoxaPortReadData(ch->port, tp);
+	spin_unlock_irqrestore(&moxa_lock, flags);
+	tty_schedule_flip(tp);
 }
 
 #define Magic_code	0x404
@@ -1774,7 +1762,7 @@
  *	14. MoxaPortDCDON(int port);					     *
  *	15. MoxaPortFlushData(int port, int mode);	                     *
  *	16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
- *	17. MoxaPortReadData(int port, unsigned char * buffer, int length);  *
+ *	17. MoxaPortReadData(int port, struct tty_struct *tty); 	     *
  *	18. MoxaPortTxBufSize(int port);				     *
  *	19. MoxaPortRxBufSize(int port);				     *
  *	20. MoxaPortTxQueue(int port);					     *
@@ -2003,10 +1991,9 @@
  *
  *      Function 21:    Read data.
  *      Syntax:
- *      int  MoxaPortReadData(int port, unsigned char * buffer, int length);
+ *      int  MoxaPortReadData(int port, struct tty_struct *tty);
  *           int port           : port number (0 - 127)
- *           unsigned char * buffer     : pointer to read data buffer.
- *           int length         : read data buffer length
+ *	     struct tty_struct *tty : tty for data
  *
  *           return:    0 - length      : real read data length
  *
@@ -2504,7 +2491,7 @@
 	return (total);
 }
 
-int MoxaPortReadData(int port, unsigned char * buffer, int space)
+int MoxaPortReadData(int port, struct tty_struct *tty)
 {
 	register ushort head, pageofs;
 	int i, count, cnt, len, total, remain;
@@ -2522,9 +2509,9 @@
 	count = (tail >= head) ? (tail - head)
 	    : (tail - head + rx_mask + 1);
 	if (count == 0)
-		return (0);
+		return 0;
 
-	total = (space > count) ? count : space;
+	total = count;
 	remain = count - total;
 	moxaLog.rxcnt[port] += total;
 	count = total;
@@ -2539,7 +2526,7 @@
 			len = (count > len) ? len : count;
 			ofs = baseAddr + DynPage_addr + bufhead + head;
 			for (i = 0; i < len; i++)
-				*buffer++ = readb(ofs + i);
+				tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
 			head = (head + len) & rx_mask;
 			count -= len;
 		}
@@ -2556,7 +2543,7 @@
 			writew(pageno, baseAddr + Control_reg);
 			ofs = baseAddr + DynPage_addr + pageofs;
 			for (i = 0; i < cnt; i++)
-				*buffer++ = readb(ofs + i);
+				tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
 			if (count == 0) {
 				writew((head + len) & rx_mask, ofsAddr + RXrptr);
 				break;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 26448f1..ea725a9 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -813,7 +813,7 @@
 
 	/* start finding PCI board here */
 #ifdef CONFIG_PCI
-	n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
+	n = ARRAY_SIZE(mxser_pcibrds) - 1;
 	index = 0;
 	b = 0;
 	while (b < n) {
@@ -1982,7 +1982,7 @@
 
 	spin_lock_irqsave(&info->slock, flags);
 
-	recv_room = tty->ldisc.receive_room(tty);
+	recv_room = tty->receive_room;
 	if ((recv_room == 0) && (!info->ldisc_stop_rx)) {
 		//mxser_throttle(tty);
 		mxser_stoprx(tty);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index a133a62..9f54733 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -191,7 +191,6 @@
 				    poll_table *wait);
 static int n_hdlc_tty_open(struct tty_struct *tty);
 static void n_hdlc_tty_close(struct tty_struct *tty);
-static int n_hdlc_tty_room(struct tty_struct *tty);
 static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp,
 			       char *fp, int count);
 static void n_hdlc_tty_wakeup(struct tty_struct *tty);
@@ -212,7 +211,6 @@
 	.ioctl		= n_hdlc_tty_ioctl,
 	.poll		= n_hdlc_tty_poll,
 	.receive_buf	= n_hdlc_tty_receive,
-	.receive_room	= n_hdlc_tty_room,
 	.write_wakeup	= n_hdlc_tty_wakeup,
 };
 
@@ -337,6 +335,7 @@
 		
 	tty->disc_data = n_hdlc;
 	n_hdlc->tty    = tty;
+	tty->receive_room = 65536;
 	
 #if defined(TTY_NO_WRITE_SPLIT)
 	/* change tty_io write() to not split large writes into 8K chunks */
@@ -478,22 +477,6 @@
 }	/* end of n_hdlc_tty_wakeup() */
 
 /**
- * n_hdlc_tty_room - Return the amount of space left in the receiver's buffer
- * @tty	- pointer to associated tty instance data
- *
- * Callback function from tty driver. Return the amount of space left in the
- * receiver's buffer to decide if remote transmitter is to be throttled.
- */
-static int n_hdlc_tty_room(struct tty_struct *tty)
-{
-	if (debuglevel >= DEBUG_LEVEL_INFO)	
-		printk("%s(%d)n_hdlc_tty_room() called\n",__FILE__,__LINE__);
-	/* always return a larger number to prevent */
-	/* throttling of remote transmitter. */
-	return 65536;
-}	/* end of n_hdlc_tty_root() */
-
-/**
  * n_hdlc_tty_receive - Called by tty driver when receive data is available
  * @tty	- pointer to tty instance data
  * @data - pointer to received data
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 853c98c..c48de09 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -147,7 +147,6 @@
 		      struct poll_table_struct  *wait);
 static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                               char *fp, int count);
-static int  r3964_receive_room(struct tty_struct *tty);
 
 static struct tty_ldisc tty_ldisc_N_R3964 = {
 	.owner	 = THIS_MODULE,
@@ -161,7 +160,6 @@
 	.set_termios = r3964_set_termios,
 	.poll	= r3964_poll,            
 	.receive_buf = r3964_receive_buf,
-	.receive_room = r3964_receive_room,
 };
 
 
@@ -1119,6 +1117,7 @@
    pInfo->nRetry = 0;
    
    tty->disc_data = pInfo;
+   tty->receive_room = 65536;
 
    init_timer(&pInfo->tmr);
    pInfo->tmr.data = (unsigned long)pInfo;
@@ -1405,12 +1404,5 @@
     }
 }
 
-static int r3964_receive_room(struct tty_struct *tty)
-{
-   TRACE_L("receive_room");
-   return -1;
-}
-
-
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_R3964);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index c556f4d..ccad7ae 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -78,7 +78,32 @@
 		free_page((unsigned long) buf);
 }
 
-static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+/**
+ *	n_tty_set__room	-	receive space
+ *	@tty: terminal
+ *
+ *	Called by the driver to find out how much data it is
+ *	permitted to feed to the line discipline without any being lost
+ *	and thus to manage flow control. Not serialized. Answers for the
+ *	"instant".
+ */
+
+static void n_tty_set_room(struct tty_struct *tty)
+{
+	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+	/*
+	 * If we are doing input canonicalization, and there are no
+	 * pending newlines, let characters through without limit, so
+	 * that erase characters will be handled.  Other excess
+	 * characters will be beeped.
+	 */
+	if (left <= 0)
+		left = tty->icanon && !tty->canon_data;
+	tty->receive_room = left;
+}
+
+static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
 {
 	if (tty->read_cnt < N_TTY_BUF_SIZE) {
 		tty->read_buf[tty->read_head] = c;
@@ -87,7 +112,7 @@
 	}
 }
 
-static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct tty_struct *tty)
 {
 	unsigned long flags;
 	/*
@@ -136,6 +161,7 @@
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 	tty->canon_head = tty->canon_data = tty->erasing = 0;
 	memset(&tty->read_flags, 0, sizeof tty->read_flags);
+	n_tty_set_room(tty);
 	check_unthrottle(tty);
 }
 
@@ -838,30 +864,6 @@
 	put_tty_queue(c, tty);
 }	
 
-/**
- *	n_tty_receive_room	-	receive space
- *	@tty: terminal
- *
- *	Called by the driver to find out how much data it is
- *	permitted to feed to the line discipline without any being lost
- *	and thus to manage flow control. Not serialized. Answers for the
- *	"instant".
- */
- 
-static int n_tty_receive_room(struct tty_struct *tty)
-{
-	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
-
-	/*
-	 * If we are doing input canonicalization, and there are no
-	 * pending newlines, let characters through without limit, so
-	 * that erase characters will be handled.  Other excess
-	 * characters will be beeped.
-	 */
-	if (left <= 0)
-		left = tty->icanon && !tty->canon_data;
-	return left;
-}
 
 /**
  *	n_tty_write_wakeup	-	asynchronous I/O notifier
@@ -953,6 +955,8 @@
 			tty->driver->flush_chars(tty);
 	}
 
+	n_tty_set_room(tty);
+
 	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
 		kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 		if (waitqueue_active(&tty->read_wait))
@@ -964,7 +968,7 @@
 	 * mode.  We don't want to throttle the driver if we're in
 	 * canonical mode and don't have a newline yet!
 	 */
-	if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
+	if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
 		/* check TTY_THROTTLED first so it indicates our state */
 		if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
 		    tty->driver->throttle)
@@ -999,6 +1003,7 @@
 	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
 		tty->raw = 1;
 		tty->real_raw = 1;
+		n_tty_set_room(tty);
 		return;
 	}
 	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1051,6 +1056,7 @@
 		else
 			tty->real_raw = 0;
 	}
+	n_tty_set_room(tty);
 }
 
 /**
@@ -1130,7 +1136,7 @@
  *
  */
  
-static inline int copy_from_read_buf(struct tty_struct *tty,
+static int copy_from_read_buf(struct tty_struct *tty,
 				      unsigned char __user **b,
 				      size_t *nr)
 
@@ -1308,6 +1314,7 @@
 				retval = -ERESTARTSYS;
 				break;
 			}
+			n_tty_set_room(tty);
 			clear_bit(TTY_DONT_FLIP, &tty->flags);
 			timeout = schedule_timeout(timeout);
 			set_bit(TTY_DONT_FLIP, &tty->flags);
@@ -1401,6 +1408,8 @@
 	} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
 		 goto do_it_again;
 
+	n_tty_set_room(tty);
+
 	return retval;
 }
 
@@ -1553,7 +1562,6 @@
 	normal_poll,		/* poll */
 	NULL,			/* hangup */
 	n_tty_receive_buf,	/* receive_buf */
-	n_tty_receive_room,	/* receive_room */
 	n_tty_write_wakeup	/* write_wakeup */
 };
 
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 1af733d..3556ccd 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -557,13 +557,13 @@
 	    (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
 	PRINT_PROC("Floppy 0 type  : ");
 	type = nvram[2] >> 4;
-	if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+	if (type < ARRAY_SIZE(floppy_types))
 		PRINT_PROC("%s\n", floppy_types[type]);
 	else
 		PRINT_PROC("%d (unknown)\n", type);
 	PRINT_PROC("Floppy 1 type  : ");
 	type = nvram[2] & 0x0f;
-	if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+	if (type < ARRAY_SIZE(floppy_types))
 		PRINT_PROC("%s\n", floppy_types[type]);
 	else
 		PRINT_PROC("%d (unknown)\n", type);
@@ -843,8 +843,6 @@
 	"2", "4", "16", "256", "65536", "??", "??", "??"
 };
 
-#define fieldsize(a)	(sizeof(a)/sizeof(*a))
-
 static int
 atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
     off_t *begin, off_t offset, int size)
@@ -856,7 +854,7 @@
 	PRINT_PROC("Checksum status  : %svalid\n", checksum ? "" : "not ");
 
 	PRINT_PROC("Boot preference  : ");
-	for (i = fieldsize(boot_prefs) - 1; i >= 0; --i) {
+	for (i = ARRAY_SIZE(boot_prefs) - 1; i >= 0; --i) {
 		if (nvram[1] == boot_prefs[i].val) {
 			PRINT_PROC("%s\n", boot_prefs[i].name);
 			break;
@@ -878,12 +876,12 @@
 		return 1;
 
 	PRINT_PROC("OS language      : ");
-	if (nvram[6] < fieldsize(languages))
+	if (nvram[6] < ARRAY_SIZE(languages))
 		PRINT_PROC("%s\n", languages[nvram[6]]);
 	else
 		PRINT_PROC("%u (undefined)\n", nvram[6]);
 	PRINT_PROC("Keyboard language: ");
-	if (nvram[7] < fieldsize(languages))
+	if (nvram[7] < ARRAY_SIZE(languages))
 		PRINT_PROC("%s\n", languages[nvram[7]]);
 	else
 		PRINT_PROC("%u (undefined)\n", nvram[7]);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index cf45b10..8a8ca32 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1007,8 +1007,9 @@
 
 static void rx_ready_async(MGSLPC_INFO *info, int tcd)
 {
-	unsigned char data, status;
+	unsigned char data, status, flag;
 	int fifo_count;
+	int work = 0;
  	struct tty_struct *tty = info->tty;
  	struct mgsl_icount *icount = &info->icount;
 
@@ -1023,20 +1024,16 @@
 			fifo_count = 32;
 	} else
 		fifo_count = 32;
-	
+
+	tty_buffer_request_room(tty, fifo_count);
 	/* Flush received async data to receive data buffer. */ 
 	while (fifo_count) {
 		data   = read_reg(info, CHA + RXFIFO);
 		status = read_reg(info, CHA + RXFIFO);
 		fifo_count -= 2;
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			break;
-			
-		*tty->flip.char_buf_ptr = data;
 		icount->rx++;
-		
-		*tty->flip.flag_buf_ptr = 0;
+		flag = TTY_NORMAL;
 
 		// if no frameing/crc error then save data
 		// BIT7:parity error
@@ -1055,26 +1052,23 @@
 			status &= info->read_status_mask;
 
 			if (status & BIT7)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (status & BIT6)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
-		
-		tty->flip.flag_buf_ptr++;
-		tty->flip.char_buf_ptr++;
-		tty->flip.count++;
+		work += tty_insert_flip_char(tty, data, flag);
 	}
 	issue_command(info, CHA, CMD_RXFIFO);
 
 	if (debug_level >= DEBUG_LEVEL_ISR) {
-		printk("%s(%d):rx_ready_async count=%d\n",
-			__FILE__,__LINE__,tty->flip.count);
+		printk("%s(%d):rx_ready_async",
+			__FILE__,__LINE__);
 		printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
 			__FILE__,__LINE__,icount->rx,icount->brk,
 			icount->parity,icount->frame,icount->overrun);
 	}
 			
-	if (tty->flip.count)
+	if (work)
 		tty_flip_buffer_push(tty);
 }
 
@@ -4005,7 +3999,7 @@
 {
 	static unsigned char patterns[] = 
 	    { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };
-	static unsigned int count = sizeof(patterns) / sizeof(patterns[0]);
+	static unsigned int count = ARRAY_SIZE(patterns);
 	unsigned int i;
 	BOOLEAN rc = TRUE;
 	unsigned long flags;
@@ -4016,7 +4010,7 @@
 	for (i = 0; i < count; i++) {
 		write_reg(info, XAD1, patterns[i]);
 		write_reg(info, XAD2, patterns[(i + 1) % count]);
-		if ((read_reg(info, XAD1) != patterns[i]) || 
+		if ((read_reg(info, XAD1) != patterns[i]) ||
 		    (read_reg(info, XAD2) != patterns[(i + 1) % count])) {
 			rc = FALSE;
 			break;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 49f3997..9b5a2c0 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -111,7 +111,7 @@
 	if (!to || tty->stopped)
 		return 0;
 
-	c = to->ldisc.receive_room(to);
+	c = to->receive_room;
 	if (c > count)
 		c = count;
 	to->ldisc.receive_buf(to, buf, NULL, c);
@@ -126,7 +126,7 @@
 	if (!to || tty->stopped)
 		return 0;
 
-	return to->ldisc.receive_room(to);
+	return to->receive_room;
 }
 
 /*
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d7d4840..7085a38 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -56,10 +56,6 @@
 #include <linux/generic_serial.h>
 #include <asm/uaccess.h>
 
-#if BITS_PER_LONG != 32
-#  error FIXME: this driver only works on 32-bit platforms
-#endif
-
 #include "linux_compat.h"
 #include "typdef.h"
 #include "pkt.h"
@@ -215,7 +211,7 @@
    or less.... */
 static int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000};
 
-#define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int))
+#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
 
 
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
index e42e7b5..ddda9c1 100644
--- a/drivers/char/rio/riointr.c
+++ b/drivers/char/rio/riointr.c
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/string.h>
@@ -560,6 +561,7 @@
   struct PKT *PacketP;
   register uint	DataCnt;
   uchar *	ptr;
+  unsigned char *buf;
   int copied =0;
 
   static int intCount, RxIntCnt;
@@ -657,8 +659,7 @@
 	  ** and available space.
 	  */
 			
-	  transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK,
-			   TTY_FLIPBUF_SIZE - TtyP->flip.count);
+	  transCount = tty_buffer_request_room(TtyP, PacketP->len & PKT_LEN_MASK);
 	  rio_dprintk (RIO_DEBUG_REC,  "port %d: Copy %d bytes\n", 
 				      PortP->PortNum, transCount);
 	  /*
@@ -678,9 +679,8 @@
 #endif
 	  ptr = (uchar *) PacketP->data + PortP->RxDataStart;
 
-	  rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount);
-	  memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);
-
+	  tty_prepare_flip_string(TtyP, &buf, transCount);
+	  rio_memcpy_fromio (buf, ptr, transCount);
 #ifdef STATS
 	  /*
 	  ** keep a count for statistical purposes
@@ -690,9 +690,6 @@
 	  PortP->RxDataStart	+= transCount;
 	  PacketP->len		-= transCount;
 	  copied += transCount;
-	  TtyP->flip.count += transCount;
-	  TtyP->flip.char_buf_ptr += transCount;
-	  TtyP->flip.flag_buf_ptr += transCount;
 
 
 #ifdef ___DEBUG_IT___
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 55a3a01..050e70e 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -46,6 +46,7 @@
 #include <linux/major.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/tty_flip.h>
 
 #include <asm/uaccess.h>
 
@@ -107,15 +108,15 @@
 
 /* RISCom/8 I/O ports addresses (without address translation) */
 static unsigned short rc_ioport[] =  {
-#if 1	
+#if 1
 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
-#else	
+#else
 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
 	0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
 	0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
-#endif	
+#endif
 };
-#define RC_NIOPORT	(sizeof(rc_ioport) / sizeof(rc_ioport[0]))
+#define RC_NIOPORT	ARRAY_SIZE(rc_ioport)
 
 
 static inline int rc_paranoia_check(struct riscom_port const * port,
@@ -354,28 +355,17 @@
 	struct riscom_port *port;
 	struct tty_struct *tty;
 	unsigned char status;
-	unsigned char ch;
+	unsigned char ch, flag;
 	
 	if (!(port = rc_get_port(bp, "Receive")))
 		return;
 
 	tty = port->tty;
-	if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
-		printk(KERN_WARNING "rc%d: port %d: Working around flip "
-				    "buffer overflow.\n",
-		       board_No(bp), port_No(port));
-		return;
-	}
 	
 #ifdef RC_REPORT_OVERRUN	
 	status = rc_in(bp, CD180_RCSR);
-	if (status & RCSR_OE)  {
+	if (status & RCSR_OE)
 		port->overrun++;
-#if 0		
-		printk(KERN_ERR "rc%d: port %d: Overrun. Total %ld overruns\n", 
-		       board_No(bp), port_No(port), port->overrun);
-#endif		
-	}
 	status &= port->mark_mask;
 #else	
 	status = rc_in(bp, CD180_RCSR) & port->mark_mask;
@@ -393,25 +383,24 @@
 	} else if (status & RCSR_BREAK)  {
 		printk(KERN_INFO "rc%d: port %d: Handling break...\n",
 		       board_No(bp), port_No(port));
-		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+		flag = TTY_BREAK;
 		if (port->flags & ASYNC_SAK)
 			do_SAK(tty);
 		
 	} else if (status & RCSR_PE) 
-		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+		flag = TTY_PARITY;
 	
 	else if (status & RCSR_FE) 
-		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+		flag = TTY_FRAME;
 	
         else if (status & RCSR_OE)
-		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+		flag = TTY_OVERRUN;
 	
 	else
-		*tty->flip.flag_buf_ptr++ = 0;
+		flag = TTY_NORMAL;
 	
-	*tty->flip.char_buf_ptr++ = ch;
-	tty->flip.count++;
-	schedule_delayed_work(&tty->flip.work, 1);
+	tty_insert_flip_char(tty, ch, flag);
+	tty_flip_buffer_push(tty);
 }
 
 static inline void rc_receive(struct riscom_board const * bp)
@@ -432,17 +421,15 @@
 #endif	
 	
 	while (count--)  {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
+		if (tty_buffer_request_room(tty, 1) == 0)  {
 			printk(KERN_WARNING "rc%d: port %d: Working around "
 					    "flip buffer overflow.\n",
 			       board_No(bp), port_No(port));
 			break;
 		}
-		*tty->flip.char_buf_ptr++ = rc_in(bp, CD180_RDR);
-		*tty->flip.flag_buf_ptr++ = 0;
-		tty->flip.count++;
+		tty_insert_flip_char(tty, rc_in(bp, CD180_RDR), TTY_NORMAL);
 	}
-	schedule_delayed_work(&tty->flip.work, 1);
+	tty_flip_buffer_push(tty);
 }
 
 static inline void rc_transmit(struct riscom_board const * bp)
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index d3bc731..0949dce 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -325,19 +325,16 @@
 {
 	unsigned int CharNStat;
 	int ToRecv, wRecv, space = 0, count;
-	unsigned char *cbuf;
-	char *fbuf;
+	unsigned char *cbuf, *chead;
+	char *fbuf, *fhead;
 	struct tty_ldisc *ld;
 
 	ld = tty_ldisc_ref(tty);
 
 	ToRecv = sGetRxCnt(cp);
-	if (ld)
-		space = ld->receive_room(tty);
+	space = tty->receive_room;
 	if (space > 2 * TTY_FLIPBUF_SIZE)
 		space = 2 * TTY_FLIPBUF_SIZE;
-	cbuf = tty->flip.char_buf;
-	fbuf = tty->flip.flag_buf;
 	count = 0;
 #ifdef ROCKET_DEBUG_INTR
 	printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
@@ -350,9 +347,13 @@
 	if (ToRecv > space)
 		ToRecv = space;
 
+	ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
 	if (ToRecv <= 0)
 		goto done;
 
+	cbuf = chead;
+	fbuf = fhead;
+
 	/*
 	 * if status indicates there are errored characters in the
 	 * FIFO, then enter status mode (a word in FIFO holds
@@ -399,7 +400,7 @@
 			else if (CharNStat & STMRCVROVRH)
 				*fbuf++ = TTY_OVERRUN;
 			else
-				*fbuf++ = 0;
+				*fbuf++ = TTY_NORMAL;
 			*cbuf++ = CharNStat & 0xff;
 			count++;
 			ToRecv--;
@@ -426,13 +427,13 @@
 			sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
 		if (ToRecv & 1)
 			cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
-		memset(fbuf, 0, ToRecv);
+		memset(fbuf, TTY_NORMAL, ToRecv);
 		cbuf += ToRecv;
 		fbuf += ToRecv;
 		count += ToRecv;
 	}
 	/*  Push the data up to the tty layer */
-	ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+	ld->receive_buf(tty, cbuf, fbuf, count);
 done:
 	tty_ldisc_deref(ld);
 }
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 5b187c8..71093a9 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -275,7 +275,8 @@
 int paste_selection(struct tty_struct *tty)
 {
 	struct vc_data *vc = (struct vc_data *)tty->driver_data;
-	int	pasted = 0, count;
+	int	pasted = 0;
+	unsigned int count;
 	struct  tty_ldisc *ld;
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -293,7 +294,7 @@
 			continue;
 		}
 		count = sel_buffer_lth - pasted;
-		count = min(count, tty->ldisc.receive_room(tty));
+		count = min(count, tty->receive_room);
 		tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
 		pasted += count;
 	}
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index dda30e4..80a5b84 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -194,11 +194,6 @@
 */
 	struct tty_struct *tty = port->gs.tty;
 
-	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-		return;
-
-	tty->flip.count++;
-
 #if 0
 	switch(err) {
 	case TTY_BREAK:
@@ -212,8 +207,7 @@
 	}
 #endif
 
-	*tty->flip.flag_buf_ptr++ = err;
-	*tty->flip.char_buf_ptr++ = ch;
+	tty_insert_flip_char(tty, ch, err);
 	tty_flip_buffer_push(tty);
 }
 
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index c2deac9..f36342a 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -117,7 +117,7 @@
         {-1 },      /* ttyS2 */
         {-1 },      /* ttyS3 */
 };
-#define NR_PORTS        (sizeof(cy_port)/sizeof(struct cyclades_port))
+#define NR_PORTS        ARRAY_SIZE(cy_port)
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
@@ -422,45 +422,35 @@
 	    base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
 	    return IRQ_HANDLED;
 	}
-	if (tty->flip.count < TTY_FLIPBUF_SIZE){
-	    tty->flip.count++;
+	if (tty_buffer_request_room(tty, 1) != 0){
 	    if (err & info->read_status_mask){
 		if(err & CyBREAK){
-		    *tty->flip.flag_buf_ptr++ = TTY_BREAK;
-		    *tty->flip.char_buf_ptr++ = data;
+		    tty_insert_flip_char(tty, data, TTY_BREAK);
 		    if (info->flags & ASYNC_SAK){
 			do_SAK(tty);
 		    }
 		}else if(err & CyFRAME){
-		    *tty->flip.flag_buf_ptr++ = TTY_FRAME;
-		    *tty->flip.char_buf_ptr++ = data;
+		    tty_insert_flip_char(tty, data, TTY_FRAME);
 		}else if(err & CyPARITY){
-		    *tty->flip.flag_buf_ptr++ = TTY_PARITY;
-		    *tty->flip.char_buf_ptr++ = data;
+		    tty_insert_flip_char(tty, data, TTY_PARITY);
 		}else if(err & CyOVERRUN){
-		    *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-		    *tty->flip.char_buf_ptr++ = 0;
+		    tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		    /*
 		       If the flip buffer itself is
 		       overflowing, we still loose
 		       the next incoming character.
 		     */
-		    if(tty->flip.count < TTY_FLIPBUF_SIZE){
-			tty->flip.count++;
-			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-			*tty->flip.char_buf_ptr++ = data;
-		    }
+		    tty_insert_flip_char(tty, data, TTY_NORMAL);
+		}
 		/* These two conditions may imply */
 		/* a normal read should be done. */
 		/* else if(data & CyTIMEOUT) */
 		/* else if(data & CySPECHAR) */
 		}else{
-		    *tty->flip.flag_buf_ptr++ = 0;
-		    *tty->flip.char_buf_ptr++ = 0;
+		    tty_insert_flip_char(tty, 0, TTY_NORMAL);
 		}
 	    }else{
-		*tty->flip.flag_buf_ptr++ = 0;
-		*tty->flip.char_buf_ptr++ = 0;
+		    tty_insert_flip_char(tty, data, TTY_NORMAL);
 	    }
 	}else{
 	    /* there was a software buffer overrun
@@ -692,12 +682,7 @@
 #endif
 	while(char_count--){
 	    data = base_addr[CyRDR];
-	    if (tty->flip.count >= TTY_FLIPBUF_SIZE){
-		continue;
-	    }
-	    tty->flip.count++;
-	    *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-	    *tty->flip.char_buf_ptr++ = data;
+	    tty_insert_flip_char(tty, data, TTY_NORMAL);
 #ifdef CYCLOM_16Y_HACK
 	    udelay(10L);
 #endif
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 0bbfce4..0a574bd 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -85,6 +85,7 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/mm.h>
 #include <linux/serial.h>
 #include <linux/fcntl.h>
@@ -665,7 +666,7 @@
 	struct specialix_port *port;
 	struct tty_struct *tty;
 	unsigned char status;
-	unsigned char ch;
+	unsigned char ch, flag;
 
 	func_enter();
 
@@ -676,8 +677,6 @@
 		return;
 	}
 	tty = port->tty;
-	dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n",
-		 port,  tty->flip.count, TTY_FLIPBUF_SIZE);
 
 	status = sx_in(bp, CD186x_RCSR);
 
@@ -691,7 +690,7 @@
 
 	/* This flip buffer check needs to be below the reading of the
 	   status register to reset the chip's IRQ.... */
-	if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+	if (tty_buffer_request_room(tty, 1) == 0) {
 		dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
 		       board_No(bp), port_No(port));
 		func_exit();
@@ -712,26 +711,24 @@
 	} else if (status & RCSR_BREAK) {
 		dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
 		       board_No(bp), port_No(port));
-		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+		flag = TTY_BREAK;
 		if (port->flags & ASYNC_SAK)
 			do_SAK(tty);
 
 	} else if (status & RCSR_PE)
-		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+		flag = TTY_PARITY;
 
 	else if (status & RCSR_FE)
-		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+		flag = TTY_FRAME;
 
 	else if (status & RCSR_OE)
-		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+		flag = TTY_OVERRUN;
 
 	else
-		*tty->flip.flag_buf_ptr++ = 0;
+		flag = TTY_NORMAL;
 
-	*tty->flip.char_buf_ptr++ = ch;
-	tty->flip.count++;
-	schedule_delayed_work(&tty->flip.work, 1);
-
+	if(tty_insert_flip_char(tty, ch, flag))
+		tty_flip_buffer_push(tty);
 	func_exit();
 }
 
@@ -755,18 +752,11 @@
 	dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
 	port->hits[count > 8 ? 9 : count]++;
 
-	while (count--) {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n",
-			       board_No(bp), port_No(port));
-			break;
-		}
-		*tty->flip.char_buf_ptr++ = sx_in(bp, CD186x_RDR);
-		*tty->flip.flag_buf_ptr++ = 0;
-		tty->flip.count++;
-	}
-	schedule_delayed_work(&tty->flip.work, 1);
+	tty_buffer_request_room(tty, count);
 
+	while (count--)
+		tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
+	tty_flip_buffer_push(tty);
 	func_exit();
 }
 
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 95af2a9..0e20780 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -103,7 +103,7 @@
 	/*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
 };
 
-static int	stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
+static int	stl_nrbrds = ARRAY_SIZE(stl_brdconf);
 
 /*****************************************************************************/
 
@@ -424,7 +424,7 @@
 	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
 };
 
-static int	stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t);
+static int	stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
 
 #endif
 
@@ -704,7 +704,7 @@
 	230400, 460800, 921600
 };
 
-#define	SC26198_NRBAUDS		(sizeof(sc26198_baudtable) / sizeof(unsigned int))
+#define	SC26198_NRBAUDS		ARRAY_SIZE(sc26198_baudtable)
 
 /*****************************************************************************/
 
@@ -901,7 +901,7 @@
 static int stl_parsebrd(stlconf_t *confp, char **argp)
 {
 	char	*sp;
-	int	nrbrdnames, i;
+	int	i;
 
 #ifdef DEBUG
 	printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
@@ -913,14 +913,13 @@
 	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
 		*sp = TOLOWER(*sp);
 
-	nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);
-	for (i = 0; (i < nrbrdnames); i++) {
+	for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
 		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
 			break;
 	}
-	if (i >= nrbrdnames) {
+	if (i == ARRAY_SIZE(stl_brdstr)) {
 		printk("STALLION: unknown board name, %s?\n", argp[0]);
-		return(0);
+		return 0;
 	}
 
 	confp->brdtype = stl_brdstr[i].type;
@@ -2902,7 +2901,8 @@
 	if (portp->tty != (struct tty_struct *) NULL) {
 		if (portp->tty->driver_data == portp) {
 			portp->stats.ttystate = portp->tty->flags;
-			portp->stats.rxbuffered = portp->tty->flip.count;
+			/* No longer available as a statistic */
+			portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
 			if (portp->tty->termios != (struct termios *) NULL) {
 				portp->stats.cflags = portp->tty->termios->c_cflag;
 				portp->stats.iflags = portp->tty->termios->c_iflag;
@@ -4046,9 +4046,7 @@
 	if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
 		outb((RDCR + portp->uartaddr), ioaddr);
 		len = inb(ioaddr + EREG_DATA);
-		if ((tty == (struct tty_struct *) NULL) ||
-		    (tty->flip.char_buf_ptr == (char *) NULL) ||
-		    ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
 			len = MIN(len, sizeof(stl_unwanted));
 			outb((RDSR + portp->uartaddr), ioaddr);
 			insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
@@ -4057,12 +4055,10 @@
 		} else {
 			len = MIN(len, buflen);
 			if (len > 0) {
+				unsigned char *ptr;
 				outb((RDSR + portp->uartaddr), ioaddr);
-				insb((ioaddr + EREG_DATA), tty->flip.char_buf_ptr, len);
-				memset(tty->flip.flag_buf_ptr, 0, len);
-				tty->flip.flag_buf_ptr += len;
-				tty->flip.char_buf_ptr += len;
-				tty->flip.count += len;
+				tty_prepare_flip_string(tty, &ptr, len);
+				insb((ioaddr + EREG_DATA), ptr, len);
 				tty_schedule_flip(tty);
 				portp->stats.rxtotal += len;
 			}
@@ -4086,8 +4082,7 @@
 				portp->stats.txxoff++;
 			goto stl_rxalldone;
 		}
-		if ((tty != (struct tty_struct *) NULL) &&
-		    ((portp->rxignoremsk & status) == 0)) {
+		if (tty != NULL && (portp->rxignoremsk & status) == 0) {
 			if (portp->rxmarkmsk & status) {
 				if (status & ST_BREAK) {
 					status = TTY_BREAK;
@@ -4107,14 +4102,8 @@
 			} else {
 				status = 0;
 			}
-			if (tty->flip.char_buf_ptr != (char *) NULL) {
-				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-					*tty->flip.flag_buf_ptr++ = status;
-					*tty->flip.char_buf_ptr++ = ch;
-					tty->flip.count++;
-				}
-				tty_schedule_flip(tty);
-			}
+			tty_insert_flip_char(tty, ch, status);
+			tty_schedule_flip(tty);
 		}
 	} else {
 		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
@@ -5013,9 +5002,7 @@
 	len = inb(ioaddr + XP_DATA) + 1;
 
 	if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
-		if ((tty == (struct tty_struct *) NULL) ||
-		    (tty->flip.char_buf_ptr == (char *) NULL) ||
-		    ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
 			len = MIN(len, sizeof(stl_unwanted));
 			outb(GRXFIFO, (ioaddr + XP_ADDR));
 			insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
@@ -5024,12 +5011,10 @@
 		} else {
 			len = MIN(len, buflen);
 			if (len > 0) {
+				unsigned char *ptr;
 				outb(GRXFIFO, (ioaddr + XP_ADDR));
-				insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len);
-				memset(tty->flip.flag_buf_ptr, 0, len);
-				tty->flip.flag_buf_ptr += len;
-				tty->flip.char_buf_ptr += len;
-				tty->flip.count += len;
+				tty_prepare_flip_string(tty, &ptr, len);
+				insb((ioaddr + XP_DATA), ptr, len);
 				tty_schedule_flip(tty);
 				portp->stats.rxtotal += len;
 			}
@@ -5097,14 +5082,8 @@
 			status = 0;
 		}
 
-		if (tty->flip.char_buf_ptr != (char *) NULL) {
-			if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-				*tty->flip.flag_buf_ptr++ = status;
-				*tty->flip.char_buf_ptr++ = ch;
-				tty->flip.count++;
-			}
-			tty_schedule_flip(tty);
-		}
+		tty_insert_flip_char(tty, ch, status);
+		tty_schedule_flip(tty);
 
 		if (status == 0)
 			portp->stats.rxtotal++;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 3ad758a..64bf89c 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -345,9 +345,9 @@
                               0xc8000, 0xd8000, 0xe8000, 0xa0000};
 static int si1_probe_addrs[]= { 0xd0000};
 
-#define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
-#define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
-#define NR_SI1_ADDRS (sizeof(si1_probe_addrs)/sizeof (int))
+#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
+#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
+#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
 
 
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
@@ -1085,6 +1085,7 @@
 	int rx_op;
 	struct tty_struct *tty;
 	int copied=0;
+	unsigned char *rp;
 
 	func_enter2 ();
 	tty = port->gs.tty;
@@ -1095,8 +1096,8 @@
 		sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); 
 
 		/* Don't copy more bytes than there is room for in the buffer */
-		if (tty->flip.count + c > TTY_FLIPBUF_SIZE) 
-			c = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+		c = tty_prepare_flip_string(tty, &rp, c);
 
 		sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); 
 
@@ -1111,14 +1112,8 @@
 		sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c, 
 		            read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op),
 		            CHAN_OFFSET(port, hi_rxbuf)); 
-		memcpy_fromio (tty->flip.char_buf_ptr, 
+		memcpy_fromio (rp,
 		               port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c);
-		memset(tty->flip.flag_buf_ptr, TTY_NORMAL, c);
-
-		/* Update the kernel buffer end */
-		tty->flip.count += c;
-		tty->flip.char_buf_ptr += c;
-		tty->flip.flag_buf_ptr += c;
 
 		/* This one last. ( Not essential.)
 		   It allows the card to start putting more data into the buffer! 
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 62aa0e5..9f1b466 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1467,6 +1467,7 @@
 {
 	int Fifocount;
 	u16 status;
+	int work = 0;
 	unsigned char DataByte;
  	struct tty_struct *tty = info->tty;
  	struct	mgsl_icount *icount = &info->icount;
@@ -1487,6 +1488,8 @@
 	/* flush the receive FIFO */
 
 	while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
+		int flag;
+
 		/* read one byte from RxFIFO */
 		outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
 		      info->io_base + CCAR );
@@ -1498,13 +1501,9 @@
 				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
 			usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
 		
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			continue;
-			
-		*tty->flip.char_buf_ptr = DataByte;
 		icount->rx++;
 		
-		*tty->flip.flag_buf_ptr = 0;
+		flag = 0;
 		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
 				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
 			printk("rxerr=%04X\n",status);					
@@ -1530,41 +1529,31 @@
 			status &= info->read_status_mask;
 		
 			if (status & RXSTATUS_BREAK_RECEIVED) {
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 				if (info->flags & ASYNC_SAK)
 					do_SAK(tty);
 			} else if (status & RXSTATUS_PARITY_ERROR)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (status & RXSTATUS_FRAMING_ERROR)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
-			if (status & RXSTATUS_OVERRUN) {
-				/* Overrun is special, since it's
-				 * reported immediately, and doesn't
-				 * affect the current character
-				 */
-				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-					tty->flip.count++;
-					tty->flip.flag_buf_ptr++;
-					tty->flip.char_buf_ptr++;
-					*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-				}
-			}
+				flag = TTY_FRAME;
 		}	/* end of if (error) */
-		
-		tty->flip.flag_buf_ptr++;
-		tty->flip.char_buf_ptr++;
-		tty->flip.count++;
+		tty_insert_flip_char(tty, DataByte, flag);
+		if (status & RXSTATUS_OVERRUN) {
+			/* Overrun is special, since it's
+			 * reported immediately, and doesn't
+			 * affect the current character
+			 */
+			work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		}
 	}
 
 	if ( debug_level >= DEBUG_LEVEL_ISR ) {
-		printk("%s(%d):mgsl_isr_receive_data flip count=%d\n",
-			__FILE__,__LINE__,tty->flip.count);
 		printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
 			__FILE__,__LINE__,icount->rx,icount->brk,
 			icount->parity,icount->frame,icount->overrun);
 	}
 			
-	if ( tty->flip.count )
+	if(work)
 		tty_flip_buffer_push(tty);
 }
 
@@ -7058,7 +7047,7 @@
 {
 	static unsigned short BitPatterns[] =
 		{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
-	static unsigned int Patterncount = sizeof(BitPatterns)/sizeof(unsigned short);
+	static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
 	unsigned int i;
 	BOOLEAN rc = TRUE;
 	unsigned long flags;
@@ -7501,9 +7490,9 @@
  */
 static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
 {
-	static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa,
-											0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
-	unsigned long Patterncount = sizeof(BitPatterns)/sizeof(unsigned long);
+	static unsigned long BitPatterns[] =
+		{ 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+	unsigned long Patterncount = ARRAY_SIZE(BitPatterns);
 	unsigned long i;
 	unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
 	unsigned long * TestAddr;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2b9cde9..79c81de 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -75,7 +75,6 @@
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
 
-#include <asm/serial.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -1750,6 +1749,9 @@
 	unsigned char status;
 	struct slgt_desc *bufs = info->rbufs;
 	int i, count;
+	int chars = 0;
+	int stat;
+	unsigned char ch;
 
 	start = end = info->rbuf_current;
 
@@ -1761,16 +1763,15 @@
 		DBGDATA(info, p, count, "rx");
 
 		for(i=0 ; i < count; i+=2, p+=2) {
-			if (tty) {
-				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-					tty_flip_buffer_push(tty);
-				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-					break;
-				*tty->flip.char_buf_ptr = *p;
-				*tty->flip.flag_buf_ptr = 0;
+			if (tty && chars) {
+				tty_flip_buffer_push(tty);
+				chars = 0;
 			}
+			ch = *p;
 			icount->rx++;
 
+			stat = 0;
+
 			if ((status = *(p+1) & (BIT9 + BIT8))) {
 				if (status & BIT9)
 					icount->parity++;
@@ -1779,17 +1780,14 @@
 				/* discard char if tty control flags say so */
 				if (status & info->ignore_status_mask)
 					continue;
-				if (tty) {
-					if (status & BIT9)
-						*tty->flip.flag_buf_ptr = TTY_PARITY;
-					else if (status & BIT8)
-						*tty->flip.flag_buf_ptr = TTY_FRAME;
-				}
+				if (status & BIT9)
+					stat = TTY_PARITY;
+				else if (status & BIT8)
+					stat = TTY_FRAME;
 			}
 			if (tty) {
-				tty->flip.flag_buf_ptr++;
-				tty->flip.char_buf_ptr++;
-				tty->flip.count++;
+				tty_insert_flip_char(tty, ch, stat);
+				chars++;
 			}
 		}
 
@@ -1812,7 +1810,7 @@
 			break;
 	}
 
-	if (tty && tty->flip.count)
+	if (tty && chars)
 		tty_flip_buffer_push(tty);
 }
 
@@ -2030,7 +2028,7 @@
 			if (info->tty) {
 				if (!(status & info->ignore_status_mask)) {
 					if (info->read_status_mask & MASK_BREAK) {
-						*info->tty->flip.flag_buf_ptr = TTY_BREAK;
+						tty_insert_flip_char(info->tty, 0, TTY_BREAK);
 						if (info->flags & ASYNC_SAK)
 							do_SAK(info->tty);
 					}
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ee5a40b..960adb2 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2196,7 +2196,7 @@
 			if ( tty ) {
 				if (!(status & info->ignore_status_mask1)) {
 					if (info->read_status_mask1 & BRKD) {
-						*tty->flip.flag_buf_ptr = TTY_BREAK;
+						tty_insert_flip_char(tty, 0, TTY_BREAK);
 						if (info->flags & ASYNC_SAK)
 							do_SAK(tty);
 					}
@@ -2240,16 +2240,10 @@
 
 	while((status = read_reg(info,CST0)) & BIT0)
 	{
+		int flag = 0;
+		int over = 0;
 		DataByte = read_reg(info,TRB);
 
-		if ( tty ) {
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				continue;
-
-			*tty->flip.char_buf_ptr = DataByte;
-			*tty->flip.flag_buf_ptr = 0;
-		}
-
 		icount->rx++;
 
 		if ( status & (PE + FRME + OVRN) ) {
@@ -2272,42 +2266,34 @@
 
 			if ( tty ) {
 				if (status & PE)
-					*tty->flip.flag_buf_ptr = TTY_PARITY;
+					flag = TTY_PARITY;
 				else if (status & FRME)
-					*tty->flip.flag_buf_ptr = TTY_FRAME;
+					flag = TTY_FRAME;
 				if (status & OVRN) {
 					/* Overrun is special, since it's
 					 * reported immediately, and doesn't
 					 * affect the current character
 					 */
-					if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-						tty->flip.count++;
-						tty->flip.flag_buf_ptr++;
-						tty->flip.char_buf_ptr++;
-						*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-					}
+					over = 1;
 				}
 			}
 		}	/* end of if (error) */
 
 		if ( tty ) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
+			tty_insert_flip_char(tty, DataByte, flag);
+			if (over)
+				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		}
 	}
 
 	if ( debug_level >= DEBUG_LEVEL_ISR ) {
-		printk("%s(%d):%s isr_rxrdy() flip count=%d\n",
-			__FILE__,__LINE__,info->device_name,
-			tty ? tty->flip.count : 0);
 		printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
 			__FILE__,__LINE__,info->device_name,
 			icount->rx,icount->brk,icount->parity,
 			icount->frame,icount->overrun);
 	}
 
-	if ( tty && tty->flip.count )
+	if ( tty )
 		tty_flip_buffer_push(tty);
 }
 
@@ -5104,7 +5090,7 @@
 int register_test(SLMP_INFO *info)
 {
 	static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
-	static unsigned int count = sizeof(testval)/sizeof(unsigned char);
+	static unsigned int count = ARRAY_SIZE(testval);
 	unsigned int i;
 	int rc = TRUE;
 	unsigned long flags;
@@ -5422,7 +5408,7 @@
 {
 	static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
 		0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
-	unsigned long count = sizeof(testval)/sizeof(unsigned long);
+	unsigned long count = ARRAY_SIZE(testval);
 	unsigned long i;
 	unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long);
 	unsigned long * addr = (unsigned long *)info->memory_base;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 4b1eef5..1eda82b 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -166,9 +166,12 @@
 	return tty;
 }
 
+static void tty_buffer_free_all(struct tty_struct *);
+
 static inline void free_tty_struct(struct tty_struct *tty)
 {
 	kfree(tty->write_buf);
+	tty_buffer_free_all(tty);
 	kfree(tty);
 }
 
@@ -231,6 +234,201 @@
 }
 
 /*
+ * Tty buffer allocation management
+ */
+
+static void tty_buffer_free_all(struct tty_struct *tty)
+{
+	struct tty_buffer *thead;
+	while((thead = tty->buf.head) != NULL) {
+		tty->buf.head = thead->next;
+		kfree(thead);
+	}
+	while((thead = tty->buf.free) != NULL) {
+		tty->buf.free = thead->next;
+		kfree(thead);
+	}
+	tty->buf.tail = NULL;
+}
+
+static void tty_buffer_init(struct tty_struct *tty)
+{
+	tty->buf.head = NULL;
+	tty->buf.tail = NULL;
+	tty->buf.free = NULL;
+}
+
+static struct tty_buffer *tty_buffer_alloc(size_t size)
+{
+	struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+	if(p == NULL)
+		return NULL;
+	p->used = 0;
+	p->size = size;
+	p->next = NULL;
+	p->char_buf_ptr = (char *)(p->data);
+	p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
+/* 	printk("Flip create %p\n", p); */
+	return p;
+}
+
+/* Must be called with the tty_read lock held. This needs to acquire strategy
+   code to decide if we should kfree or relink a given expired buffer */
+
+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+{
+	/* Dumb strategy for now - should keep some stats */
+/* 	printk("Flip dispose %p\n", b); */
+	if(b->size >= 512)
+		kfree(b);
+	else {
+		b->next = tty->buf.free;
+		tty->buf.free = b;
+	}
+}
+
+static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+{
+	struct tty_buffer **tbh = &tty->buf.free;
+	while((*tbh) != NULL) {
+		struct tty_buffer *t = *tbh;
+		if(t->size >= size) {
+			*tbh = t->next;
+			t->next = NULL;
+			t->used = 0;
+			/* DEBUG ONLY */
+			memset(t->data, '*', size);
+/* 			printk("Flip recycle %p\n", t); */
+			return t;
+		}
+		tbh = &((*tbh)->next);
+	}
+	/* Round the buffer size out */
+	size = (size + 0xFF) & ~ 0xFF;
+	return tty_buffer_alloc(size);
+	/* Should possibly check if this fails for the largest buffer we
+	   have queued and recycle that ? */
+}
+
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+	struct tty_buffer *b = tty->buf.head, *n;
+	int left = 0;
+
+	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+	   remove this conditional if its worth it. This would be invisible
+	   to the callers */
+	if(b != NULL)
+		left = b->size - b->used;
+	if(left >= size)
+		return size;
+	/* This is the slow path - looking for new buffers to use */
+	n = tty_buffer_find(tty, size);
+	if(n == NULL)
+		return left;
+	n->next = b;
+	if(b != NULL)
+		b->next = n;
+	else
+		tty->buf.head = n;
+	tty->buf.tail = n;
+	return size;
+}
+
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size)
+{
+	int copied = 0;
+	do {
+		int space = tty_buffer_request_room(tty, size - copied);
+		struct tty_buffer *tb = tty->buf.tail;
+		/* If there is no space then tb may be NULL */
+		if(unlikely(space == 0))
+			break;
+		memcpy(tb->char_buf_ptr + tb->used, chars, space);
+		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+		tb->used += space;
+		copied += space;
+		chars += space;
+/* 		printk("Flip insert %d.\n", space); */
+	}
+	/* There is a small chance that we need to split the data over
+	   several buffers. If this is the case we must loop */
+	while (unlikely(size > copied));
+	return copied;
+}
+
+EXPORT_SYMBOL_GPL(tty_insert_flip_string);
+
+int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size)
+{
+	int copied = 0;
+	do {
+		int space = tty_buffer_request_room(tty, size - copied);
+		struct tty_buffer *tb = tty->buf.tail;
+		/* If there is no space then tb may be NULL */
+		if(unlikely(space == 0))
+			break;
+		memcpy(tb->char_buf_ptr + tb->used, chars, space);
+		memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+		tb->used += space;
+		copied += space;
+		chars += space;
+		flags += space;
+	}
+	/* There is a small chance that we need to split the data over
+	   several buffers. If this is the case we must loop */
+	while (unlikely(size > copied));
+	return copied;
+}
+
+EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
+
+
+/*
+ *	Prepare a block of space in the buffer for data. Returns the length
+ *	available and buffer pointer to the space which is now allocated and
+ *	accounted for as ready for normal characters. This is used for drivers
+ *	that need their own block copy routines into the buffer. There is no
+ *	guarantee the buffer is a DMA target!
+ */
+
+int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
+{
+	int space = tty_buffer_request_room(tty, size);
+	struct tty_buffer *tb = tty->buf.tail;
+	*chars = tb->char_buf_ptr + tb->used;
+	memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+	tb->used += space;
+	return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
+
+/*
+ *	Prepare a block of space in the buffer for data. Returns the length
+ *	available and buffer pointer to the space which is now allocated and
+ *	accounted for as ready for characters. This is used for drivers
+ *	that need their own block copy routines into the buffer. There is no
+ *	guarantee the buffer is a DMA target!
+ */
+
+int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
+{
+	int space = tty_buffer_request_room(tty, size);
+	struct tty_buffer *tb = tty->buf.tail;
+	*chars = tb->char_buf_ptr + tb->used;
+	*flags = tb->flag_buf_ptr + tb->used;
+	tb->used += space;
+	return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
+
+
+
+/*
  *	This is probably overkill for real world processors but
  *	they are not on hot paths so a little discipline won't do 
  *	any harm.
@@ -492,6 +690,17 @@
 	if (ld == NULL)
 		return -EINVAL;
 
+	/*
+	 *	No more input please, we are switching. The new ldisc
+	 *	will update this value in the ldisc open function
+	 */
+
+	tty->receive_room = 0;
+
+	/*
+	 *	Problem: What do we do if this blocks ?
+	 */
+
 	tty_wait_until_sent(tty, 0);
 
 	if (tty->ldisc.num == ldisc) {
@@ -560,9 +769,9 @@
 	 *	we say so later on.
 	 */
 
-	work = cancel_delayed_work(&tty->flip.work);
+	work = cancel_delayed_work(&tty->buf.work);
 	/*
-	 * Wait for ->hangup_work and ->flip.work handlers to terminate
+	 * Wait for ->hangup_work and ->buf.work handlers to terminate
 	 */
 	 
 	flush_scheduled_work();
@@ -616,7 +825,7 @@
 	/* Restart it in case no characters kick it off. Safe if
 	   already running */
 	if (work)
-		schedule_delayed_work(&tty->flip.work, 1);
+		schedule_delayed_work(&tty->buf.work, 1);
 	return retval;
 }
 
@@ -1721,10 +1930,10 @@
 	 */
 	clear_bit(TTY_LDISC, &tty->flags);
 	clear_bit(TTY_DONT_FLIP, &tty->flags);
-	cancel_delayed_work(&tty->flip.work);
+	cancel_delayed_work(&tty->buf.work);
 
 	/*
-	 * Wait for ->hangup_work and ->flip.work handlers to terminate
+	 * Wait for ->hangup_work and ->buf.work handlers to terminate
 	 */
 	 
 	flush_scheduled_work();
@@ -2518,17 +2727,15 @@
 
 /*
  * This routine is called out of the software interrupt to flush data
- * from the flip buffer to the line discipline. 
+ * from the buffer chain to the line discipline.
  */
  
 static void flush_to_ldisc(void *private_)
 {
 	struct tty_struct *tty = (struct tty_struct *) private_;
-	unsigned char	*cp;
-	char		*fp;
-	int		count;
 	unsigned long 	flags;
 	struct tty_ldisc *disc;
+	struct tty_buffer *tbuf;
 
 	disc = tty_ldisc_ref(tty);
 	if (disc == NULL)	/*  !TTY_LDISC */
@@ -2538,28 +2745,22 @@
 		/*
 		 * Do it after the next timer tick:
 		 */
-		schedule_delayed_work(&tty->flip.work, 1);
+		schedule_delayed_work(&tty->buf.work, 1);
 		goto out;
 	}
 	spin_lock_irqsave(&tty->read_lock, flags);
-	if (tty->flip.buf_num) {
-		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
-		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
-		tty->flip.buf_num = 0;
-		tty->flip.char_buf_ptr = tty->flip.char_buf;
-		tty->flip.flag_buf_ptr = tty->flip.flag_buf;
-	} else {
-		cp = tty->flip.char_buf;
-		fp = tty->flip.flag_buf;
-		tty->flip.buf_num = 1;
-		tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
-		tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
+	while((tbuf = tty->buf.head) != NULL) {
+		tty->buf.head = tbuf->next;
+		spin_unlock_irqrestore(&tty->read_lock, flags);
+		/* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
+		disc->receive_buf(tty, tbuf->char_buf_ptr,
+				       tbuf->flag_buf_ptr,
+				       tbuf->used);
+		spin_lock_irqsave(&tty->read_lock, flags);
+		tty_buffer_free(tty, tbuf);
 	}
-	count = tty->flip.count;
-	tty->flip.count = 0;
+	tty->buf.tail = NULL;
 	spin_unlock_irqrestore(&tty->read_lock, flags);
-
-	disc->receive_buf(tty, cp, fp, count);
 out:
 	tty_ldisc_deref(disc);
 }
@@ -2654,11 +2855,12 @@
 	if (tty->low_latency)
 		flush_to_ldisc((void *) tty);
 	else
-		schedule_delayed_work(&tty->flip.work, 1);
+		schedule_delayed_work(&tty->buf.work, 1);
 }
 
 EXPORT_SYMBOL(tty_flip_buffer_push);
 
+
 /*
  * This subroutine initializes a tty structure.
  */
@@ -2669,10 +2871,10 @@
 	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
 	tty->pgrp = -1;
 	tty->overrun_time = jiffies;
-	tty->flip.char_buf_ptr = tty->flip.char_buf;
-	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
-	INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
-	init_MUTEX(&tty->flip.pty_sem);
+	tty->buf.head = tty->buf.tail = NULL;
+	tty_buffer_init(tty);
+	INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
+	init_MUTEX(&tty->buf.pty_sem);
 	init_MUTEX(&tty->termios_sem);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index 4d75c26..cb82ebf 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -993,11 +993,10 @@
 		 * Don't attempt to copy more data into the buffer than we
 		 * have room for because it would fail without indication.
 		 */
-		if ((tty->flip.count + 1) > TTY_FLIPBUF_SIZE) {
+		if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) {
 			printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
 			break;
 		}
-		tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL);
 	}
 
 	/* if cevent->len == 0 then no data was added to the buffer and flip.count == 0 */
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 19ba836..d932528 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -434,13 +434,7 @@
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 		return IRQ_HANDLED;
 	}
-	if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = 0;
-		tty->flip.flag_buf_ptr++;
-		tty->flip.char_buf_ptr++;
-		tty->flip.count++;
-	}
+	tty_insert_flip_char(tty, ch, 0);
 
 	/* Check if another character is already ready; in that case, the
 	 * spcond_int() function must be used, because this character may have an
@@ -487,13 +481,7 @@
 		else
 			err = 0;
 
-		if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-			*tty->flip.char_buf_ptr = ch;
-			*tty->flip.flag_buf_ptr = err;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
+		tty_insert_flip_char(tty, ch, err);
 
 		/* ++TeSche: *All* errors have to be cleared manually,
 		 * else the condition persists for the next chars
@@ -875,13 +863,13 @@
 		local_irq_save(flags);
 #if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
 		if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
-			for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)
+			for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
 				SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
 		}
 #endif
 #if defined(CONFIG_BVME6000_SCC)
 		if (MACH_IS_BVME6000) {
-			for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i)
+			for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
 				SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
 		}
 #endif
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
index 435b307..159acd8 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/char/vr41xx_rtc.c
@@ -127,8 +127,6 @@
 		.flags	= IORESOURCE_MEM,	},
 };
 
-#define RTC_NUM_RESOURCES	sizeof(rtc_resource) / sizeof(struct resource)
-
 static inline unsigned long read_elapsed_second(void)
 {
 	unsigned long first_low, first_mid, first_high;
@@ -686,7 +684,8 @@
 		break;
 	}
 
-	rtc_platform_device = platform_device_register_simple("RTC", -1, rtc_resource, RTC_NUM_RESOURCES);
+	rtc_platform_device = platform_device_register_simple("RTC", -1,
+			      rtc_resource, ARRAY_SIZE(rtc_resource));
 	if (IS_ERR(rtc_platform_device))
 		return PTR_ERR(rtc_platform_device);
 
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e91268e..f1d9cb7 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2758,29 +2758,6 @@
     vesa_blank_mode = (mode < 4) ? mode : 0;
 }
 
-/*
- * This is called by a timer handler
- */
-static void vesa_powerdown(void)
-{
-    struct vc_data *c = vc_cons[fg_console].d;
-    /*
-     *  Power down if currently suspended (1 or 2),
-     *  suspend if currently blanked (0),
-     *  else do nothing (i.e. already powered down (3)).
-     *  Called only if powerdown features are allowed.
-     */
-    switch (vesa_blank_mode) {
-    case VESA_NO_BLANKING:
-	    c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0);
-	    break;
-    case VESA_VSYNC_SUSPEND:
-    case VESA_HSYNC_SUSPEND:
-	    c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0);
-	    break;
-    }
-}
-
 void do_blank_screen(int entering_gfx)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
@@ -2791,8 +2768,7 @@
 	if (console_blanked) {
 		if (blank_state == blank_vesa_wait) {
 			blank_state = blank_off;
-			vesa_powerdown();
-
+			vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
 		}
 		return;
 	}
@@ -2822,7 +2798,7 @@
 
 	save_screen(vc);
 	/* In case we need to reset origin, blanking hook returns 1 */
-	i = vc->vc_sw->con_blank(vc, 1, 0);
+	i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
 	console_blanked = fg_console + 1;
 	if (i)
 		set_origin(vc);
@@ -2830,13 +2806,10 @@
 	if (console_blank_hook && console_blank_hook(1))
 		return;
 
-	if (vesa_off_interval) {
+	if (vesa_off_interval && vesa_blank_mode) {
 		blank_state = blank_vesa_wait;
 		mod_timer(&console_timer, jiffies + vesa_off_interval);
 	}
-
-    	if (vesa_blank_mode)
-		vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
 }
 EXPORT_SYMBOL(do_blank_screen);
 
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 385e529..4b4d7db 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -24,6 +24,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/ktime.h>
 #include <linux/init.h>
 #include <asm/atomic.h>
 
@@ -56,7 +57,7 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	get_seq(&msg->seq, &ev->cpu);
-	getnstimestamp(&ev->timestamp);
+	ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */
 	ev->what = PROC_EVENT_FORK;
 	ev->event_data.fork.parent_pid = task->real_parent->pid;
 	ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -82,7 +83,7 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	get_seq(&msg->seq, &ev->cpu);
-	getnstimestamp(&ev->timestamp);
+	ktime_get_ts(&ev->timestamp);
 	ev->what = PROC_EVENT_EXEC;
 	ev->event_data.exec.process_pid = task->pid;
 	ev->event_data.exec.process_tgid = task->tgid;
@@ -116,7 +117,7 @@
 	} else
 	     	return;
 	get_seq(&msg->seq, &ev->cpu);
-	getnstimestamp(&ev->timestamp);
+	ktime_get_ts(&ev->timestamp);
 
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
@@ -136,7 +137,7 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	get_seq(&msg->seq, &ev->cpu);
-	getnstimestamp(&ev->timestamp);
+	ktime_get_ts(&ev->timestamp);
 	ev->what = PROC_EVENT_EXIT;
 	ev->event_data.exit.process_pid = task->pid;
 	ev->event_data.exit.process_tgid = task->tgid;
@@ -169,7 +170,7 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	msg->seq = rcvd_seq;
-	getnstimestamp(&ev->timestamp);
+	ktime_get_ts(&ev->timestamp);
 	ev->cpu = -1;
 	ev->what = PROC_EVENT_NONE;
 	ev->event_data.ack.err = err;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 211641a..fe06ebb 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -39,7 +39,7 @@
 
 #define PDC202_DEBUG_CABLE	0
 
-const static char *pdc_quirk_drives[] = {
+static const char *pdc_quirk_drives[] = {
 	"QUANTUM FIREBALLlct08 08",
 	"QUANTUM FIREBALLP KA6.4",
 	"QUANTUM FIREBALLP KA9.1",
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 86fb1e0..c85b87c 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -439,7 +439,7 @@
 	hwif->speedproc = &via_set_drive;
 
 
-#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
+#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
 	if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) {
 		hwif->irq = hwif->channel ? 15 : 14;
 	}
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index 7589750..17390d7 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -80,7 +80,6 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
-#include <linux/ioctl32.h>
 #include <linux/compat.h>
 #include <linux/cdev.h>
 #include <asm/uaccess.h>
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 196db74..efeaa94 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -108,7 +108,6 @@
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
-#include <linux/ioctl32.h>
 #include <linux/compat.h>
 #include <linux/cdev.h>
 
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 608479b..39fb883 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -48,7 +48,6 @@
 #include <linux/vmalloc.h>
 #include <linux/timex.h>
 #include <linux/mm.h>
-#include <linux/ioctl32.h>
 #include <linux/compat.h>
 #include <linux/cdev.h>
 
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 1bd88fc..54a680c 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -96,6 +96,7 @@
 	init_waitqueue_head(&serport->wait);
 
 	tty->disc_data = serport;
+	tty->receive_room = 256;
 	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 
 	return 0;
@@ -140,17 +141,6 @@
 }
 
 /*
- * serport_ldisc_room() reports how much room we do have for receiving data.
- * Although we in fact have infinite room, we need to specify some value
- * here, and 256 seems to be reasonable.
- */
-
-static int serport_ldisc_room(struct tty_struct *tty)
-{
-	return 256;
-}
-
-/*
  * serport_ldisc_read() just waits indefinitely if everything goes well.
  * However, when the serio driver closes the serio port, it finishes,
  * returning 0 characters.
@@ -237,7 +227,6 @@
 	.read =		serport_ldisc_read,
 	.ioctl =	serport_ldisc_ioctl,
 	.receive_buf =	serport_ldisc_receive,
-	.receive_room =	serport_ldisc_room,
 	.write_wakeup =	serport_ldisc_write_wakeup
 };
 
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 11ae0fd..623adbb 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -463,8 +463,7 @@
 #endif
 		goto bad;
 	}
-	if (ld->receive_room &&
-	    ld->receive_room(mp->tty) < datalen) {
+	if (mp->tty->receive_room < datalen) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
 		printk(KERN_DEBUG "capi: no room in tty\n");
 #endif
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4643df0..22759c0 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -857,6 +857,118 @@
 	return count;
 }
 
+/*
+ * isdn_readbchan_tty() tries to get data from the read-queue.
+ * It MUST be called with interrupts off.
+ *
+ * Be aware that this is not an atomic operation when sleep != 0, even though
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he
+ */
+int
+isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack)
+{
+	int count;
+	int count_pull;
+	int count_put;
+	int dflag;
+	struct sk_buff *skb;
+	char last = 0;
+	int len;
+
+	if (!dev->drv[di])
+		return 0;
+	if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
+			return 0;
+
+	len = tty_buffer_request_room(tty, dev->drv[di]->rcvcount[channel]);
+	if(len == 0)
+		return len;
+
+	count = 0;
+	while (len) {
+		if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
+			break;
+#ifdef CONFIG_ISDN_AUDIO
+		if (ISDN_AUDIO_SKB_LOCK(skb))
+			break;
+		ISDN_AUDIO_SKB_LOCK(skb) = 1;
+		if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
+			char *p = skb->data;
+			unsigned long DLEmask = (1 << channel);
+
+			dflag = 0;
+			count_pull = count_put = 0;
+			while ((count_pull < skb->len) && (len > 0)) {
+				len--;
+				if (dev->drv[di]->DLEflag & DLEmask) {
+					last = DLE;
+					dev->drv[di]->DLEflag &= ~DLEmask;
+				} else {
+					last = *p;
+					if (last == DLE) {
+						dev->drv[di]->DLEflag |= DLEmask;
+						(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
+					}
+					p++;
+					count_pull++;
+				}
+				count_put++;
+			}
+			if (count_pull >= skb->len)
+				dflag = 1;
+		} else {
+#endif
+			/* No DLE's in buff, so simply copy it */
+			dflag = 1;
+			if ((count_pull = skb->len) > len) {
+				count_pull = len;
+				dflag = 0;
+			}
+			count_put = count_pull;
+			if(count_put > 1)
+				tty_insert_flip_string(tty, skb->data, count_put - 1);
+			last = skb->data[count_put] - 1;
+			len -= count_put;
+#ifdef CONFIG_ISDN_AUDIO
+		}
+#endif
+		count += count_put;
+		if (dflag) {
+			/* We got all the data in this buff.
+			 * Now we can dequeue it.
+			 */
+			if(cisco_hack)
+				tty_insert_flip_char(tty, last, 0xFF);
+			else
+				tty_insert_flip_char(tty, last, TTY_NORMAL);
+#ifdef CONFIG_ISDN_AUDIO
+			ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+			skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
+			dev_kfree_skb(skb);
+		} else {
+			tty_insert_flip_char(tty, last, TTY_NORMAL);
+			/* Not yet emptied this buff, so it
+			 * must stay in the queue, for further calls
+			 * but we pull off the data we got until now.
+			 */
+			skb_pull(skb, count_pull);
+#ifdef CONFIG_ISDN_AUDIO
+			ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+		}
+		dev->drv[di]->rcvcount[channel] -= count_put;
+	}
+	return count;
+}
+
+
 static __inline int
 isdn_minor2drv(int minor)
 {
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index e27e9c3..082735d 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -37,6 +37,7 @@
 extern void isdn_unexclusive_channel(int di, int ch);
 extern int  isdn_getnum(char **);
 extern int  isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+extern int  isdn_readbchan_tty(int, int, struct tty_struct *, int);
 extern int  isdn_get_free_channel(int, int, int, int, int, char *);
 extern int  isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int  register_isdn(isdn_if * i);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 8c404b4..f190a99 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -64,37 +64,42 @@
 	int c;
 	int len;
 	struct tty_struct *tty;
+	char last;
 
 	if (info->online) {
 		if ((tty = info->tty)) {
 			if (info->mcr & UART_MCR_RTS) {
-				c = TTY_FLIPBUF_SIZE - tty->flip.count;
 				len = skb->len
 #ifdef CONFIG_ISDN_AUDIO
 					+ ISDN_AUDIO_SKB_DLECOUNT(skb)
 #endif
 					;
+
+				c = tty_buffer_request_room(tty, len);
 				if (c >= len) {
 #ifdef CONFIG_ISDN_AUDIO
-					if (ISDN_AUDIO_SKB_DLECOUNT(skb))
-						while (skb->len--) {
+					if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+						int l = skb->len;
+						unsigned char *dp = skb->data;
+						while (--l) {
 							if (*skb->data == DLE)
 								tty_insert_flip_char(tty, DLE, 0);
-							tty_insert_flip_char(tty, *skb->data++, 0);
+							tty_insert_flip_char(tty, *dp++, 0);
+						}
+						last = *dp;
 					} else {
 #endif
-						memcpy(tty->flip.char_buf_ptr,
-						       skb->data, len);
-						tty->flip.count += len;
-						tty->flip.char_buf_ptr += len;
-						memset(tty->flip.flag_buf_ptr, 0, len);
-						tty->flip.flag_buf_ptr += len;
+						if(len > 1)
+							tty_insert_flip_string(tty, skb->data, len - 1);
+						last = skb->data[len - 1];
 #ifdef CONFIG_ISDN_AUDIO
 					}
 #endif
 					if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
-						tty->flip.flag_buf_ptr[len - 1] = 0xff;
-					schedule_delayed_work(&tty->flip.work, 1);
+						tty_insert_flip_char(tty, last, 0xFF);
+					else
+						tty_insert_flip_char(tty, last, TTY_NORMAL);
+					tty_flip_buffer_push(tty);
 					kfree_skb(skb);
 					return 1;
 				}
@@ -114,7 +119,6 @@
 	int resched = 0;
 	int midx;
 	int i;
-	int c;
 	int r;
 	struct tty_struct *tty;
 	modem_info *info;
@@ -131,20 +135,13 @@
 #endif
 				if ((tty = info->tty)) {
 					if (info->mcr & UART_MCR_RTS) {
-						c = TTY_FLIPBUF_SIZE - tty->flip.count;
-						if (c > 0) {
-							r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
-									   tty->flip.char_buf_ptr,
-									   tty->flip.flag_buf_ptr, c, NULL);
-							/* CISCO AsyncPPP Hack */
-							if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
-								memset(tty->flip.flag_buf_ptr, 0, r);
-							tty->flip.count += r;
-							tty->flip.flag_buf_ptr += r;
-							tty->flip.char_buf_ptr += r;
-							if (r)
-								schedule_delayed_work(&tty->flip.work, 1);
-						}
+						/* CISCO AsyncPPP Hack */
+						if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
+							r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0);
+						else
+							r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1);
+						if (r)
+							tty_flip_buffer_push(tty);
 					} else
 						r = 1;
 				} else
@@ -249,7 +246,7 @@
 	}
 #endif
 #endif
-	/* Try to deliver directly via tty-flip-buf if queue is empty */
+	/* Try to deliver directly via tty-buf if queue is empty */
 	spin_lock_irqsave(&info->readlock, flags);
 	if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
 		if (isdn_tty_try_read(info, skb)) {
@@ -534,7 +531,7 @@
 /* The next routine is called once from within timer-interrupt
  * triggered within isdn_tty_modem_ncarrier(). It calls
  * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
- * into the tty's flip-buffer.
+ * into the tty's buffer.
  */
 static void
 isdn_tty_modem_do_ncarrier(unsigned long data)
@@ -2347,6 +2344,7 @@
 	u_long flags;
 	struct sk_buff *skb = NULL;
 	char *sp = NULL;
+	int l = strlen(msg);
 
 	if (!msg) {
 		printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
@@ -2359,16 +2357,16 @@
 		return;
 	}
 
-	/* use queue instead of direct flip, if online and */
-	/* data is in queue or flip buffer is full */
-	if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
-	    (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
-		skb = alloc_skb(strlen(msg), GFP_ATOMIC);
+	/* use queue instead of direct, if online and */
+	/* data is in queue or buffer is full */
+	if ((info->online && tty_buffer_request_room(tty, l) < l) ||
+	    (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
+		skb = alloc_skb(l, GFP_ATOMIC);
 		if (!skb) {
 			spin_unlock_irqrestore(&info->readlock, flags);
 			return;
 		}
-		sp = skb_put(skb, strlen(msg));
+		sp = skb_put(skb, l);
 #ifdef CONFIG_ISDN_AUDIO
 		ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
 		ISDN_AUDIO_SKB_LOCK(skb) = 0;
@@ -2392,9 +2390,8 @@
 		if (skb) {
 			*sp++ = c;
 		} else {
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			if(tty_insert_flip_char(tty, c, TTY_NORMAL) == 0)
 				break;
-			tty_insert_flip_char(tty, c, 0);
 		}
 	}
 	if (skb) {
@@ -2402,12 +2399,12 @@
 		dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
 		spin_unlock_irqrestore(&info->readlock, flags);
 		/* Schedule dequeuing */
-		if ((dev->modempoll) && (info->rcvsched))
+		if (dev->modempoll && info->rcvsched)
 			isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 
 	} else {
 		spin_unlock_irqrestore(&info->readlock, flags);
-		schedule_delayed_work(&tty->flip.work, 1);
+		tty_flip_buffer_push(tty);
 	}
 }
 
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index e6aa309..96f7af4 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -303,6 +303,7 @@
 static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	multipath_conf_t *conf = mddev->private;
+	struct request_queue *q;
 	int found = 0;
 	int path;
 	struct multipath_info *p;
@@ -311,8 +312,8 @@
 
 	for (path=0; path<mddev->raid_disks; path++) 
 		if ((p=conf->multipaths+path)->rdev == NULL) {
-			blk_queue_stack_limits(mddev->queue,
-					       rdev->bdev->bd_disk->queue);
+			q = rdev->bdev->bd_disk->queue;
+			blk_queue_stack_limits(mddev->queue, q);
 
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, so limit ->max_sector to one PAGE, as
@@ -320,7 +321,7 @@
 		 * (Note: it is very unlikely that a device with
 		 * merge_bvec_fn will be involved in multipath.)
 		 */
-			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+			if (q->merge_bvec_fn &&
 			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
 				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index c30effd..36c9f5b 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -27,34 +27,30 @@
 #include <linux/pci.h>
 #include <linux/videodev.h>
 
-#define DRIVER_VERSION	"0.04"
+#define DRIVER_VERSION	"0.05"
 
-#define PCI_VENDOR_ESS                  0x125D
-#define PCI_DEVICE_ID_ESS_ESS1968       0x1968          /* Maestro 2    */
-#define PCI_DEVICE_ID_ESS_ESS1978       0x1978          /* Maestro 2E   */
-
-#define GPIO_DATA       0x60   /* port offset from ESS_IO_BASE */
+#define GPIO_DATA	0x60   /* port offset from ESS_IO_BASE */
 
 #define IO_MASK		4      /* mask      register offset from GPIO_DATA
 				bits 1=unmask write to given bit */
 #define IO_DIR		8      /* direction register offset from GPIO_DATA
 				bits 0/1=read/write direction */
 
-#define GPIO6           0x0040 /* mask bits for GPIO lines */
-#define GPIO7           0x0080
-#define GPIO8           0x0100
-#define GPIO9           0x0200
+#define GPIO6		0x0040 /* mask bits for GPIO lines */
+#define GPIO7		0x0080
+#define GPIO8		0x0100
+#define GPIO9		0x0200
 
-#define STR_DATA        GPIO6  /* radio TEA5757 pins and GPIO bits */
-#define STR_CLK         GPIO7
-#define STR_WREN        GPIO8
-#define STR_MOST        GPIO9
+#define STR_DATA	GPIO6  /* radio TEA5757 pins and GPIO bits */
+#define STR_CLK		GPIO7
+#define STR_WREN	GPIO8
+#define STR_MOST	GPIO9
 
 #define FREQ_LO		 50*16000
 #define FREQ_HI		150*16000
 
-#define FREQ_IF         171200 /* 10.7*16000   */
-#define FREQ_STEP       200    /* 12.5*16      */
+#define FREQ_IF		171200 /* 10.7*16000   */
+#define FREQ_STEP	200    /* 12.5*16      */
 
 #define FREQ2BITS(x)	((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
 			/(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
@@ -65,7 +61,27 @@
 module_param(radio_nr, int, 0);
 
 static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg);
+	unsigned int cmd, unsigned long arg);
+static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void maestro_remove(struct pci_dev *pdev);
+
+static struct pci_device_id maestro_r_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968),
+		.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+		.class_mask = 0xffff00 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978),
+		.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+		.class_mask = 0xffff00 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl);
+
+static struct pci_driver maestro_r_driver = {
+	.name		= "maestro_radio",
+	.id_table	= maestro_r_pci_tbl,
+	.probe		= maestro_probe,
+	.remove		= __devexit_p(maestro_remove),
+};
 
 static struct file_operations maestro_fops = {
 	.owner		= THIS_MODULE,
@@ -76,29 +92,27 @@
 	.llseek         = no_llseek,
 };
 
-static struct video_device maestro_radio=
-{
-	.owner		= THIS_MODULE,
+static struct video_device maestro_radio = {
 	.name		= "Maestro radio",
 	.type		= VID_TYPE_TUNER,
 	.hardware	= VID_HARDWARE_SF16MI,
-	.fops           = &maestro_fops,
+	.fops		= &maestro_fops,
 };
 
-static struct radio_device
-{
-	__u16	io,	/* base of Maestro card radio io (GPIO_DATA)*/
+struct radio_device {
+	u16	io,	/* base of Maestro card radio io (GPIO_DATA)*/
 		muted,	/* VIDEO_AUDIO_MUTE */
 		stereo,	/* VIDEO_TUNER_STEREO_ON */	
 		tuned;	/* signal strength (0 or 0xffff) */
-	struct  semaphore lock;
-} radio_unit = {0, 0, 0, 0, };
+	struct	semaphore lock;
+};
 
-static __u32 radio_bits_get(struct radio_device *dev)
+static u32 radio_bits_get(struct radio_device *dev)
 {
-	register __u16 io=dev->io, l, rdata;
-	register __u32 data=0;
-	__u16 omask;
+	register u16 io=dev->io, l, rdata;
+	register u32 data=0;
+	u16 omask;
+
 	omask = inw(io + IO_MASK);
 	outw(~(STR_CLK | STR_WREN), io + IO_MASK);
 	outw(0, io);
@@ -121,17 +135,21 @@
 				data++;
 		udelay(2);
 	}
+
 	if(dev->muted)
 		outw(STR_WREN, io);
+
 	udelay(4);
 	outw(omask, io + IO_MASK);
+
 	return data & 0x3ffe;
 }
 
-static void radio_bits_set(struct radio_device *dev, __u32 data)
+static void radio_bits_set(struct radio_device *dev, u32 data)
 {
-	register __u16 io=dev->io, l, bits;
-	__u16 omask, odir;
+	register u16 io=dev->io, l, bits;
+	u16 omask, odir;
+
 	omask = inw(io + IO_MASK);
 	odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
 	outw(odir | STR_DATA, io + IO_DIR);
@@ -147,8 +165,10 @@
 		outw(bits, io);			/* LO level */
 		udelay(4);
 	}
+
 	if(!dev->muted)
 		outw(0, io);
+
 	udelay(4);
 	outw(omask, io + IO_MASK);
 	outw(odir, io + IO_DIR);
@@ -156,141 +176,103 @@
 }
 
 static inline int radio_function(struct inode *inode, struct file *file,
-				 unsigned int cmd, void *arg)
+	unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
-	struct radio_device *card=dev->priv;
-	
-	switch(cmd) {
-		case VIDIOCGCAP: {
-			struct video_capability *v = arg;
-			memset(v,0,sizeof(*v));
-			strcpy(v->name, "Maestro radio");
-			v->type=VID_TYPE_TUNER;
-			v->channels=v->audios=1;
+	struct radio_device *card = video_get_drvdata(dev);
+
+	switch (cmd) {
+	case VIDIOCGCAP: {
+		struct video_capability *v = arg;
+		memset(v, 0, sizeof(*v));
+		strcpy(v->name, "Maestro radio");
+		v->type = VID_TYPE_TUNER;
+		v->channels = v->audios = 1;
+		return 0;
+	} case VIDIOCGTUNER: {
+		struct video_tuner *v = arg;
+		if (v->tuner)
+			return -EINVAL;
+		(void)radio_bits_get(card);
+		v->flags = VIDEO_TUNER_LOW | card->stereo;
+		v->signal = card->tuned;
+		strcpy(v->name, "FM");
+		v->rangelow = FREQ_LO;
+		v->rangehigh = FREQ_HI;
+		v->mode = VIDEO_MODE_AUTO;
+		return 0;
+	} case VIDIOCSTUNER: {
+		struct video_tuner *v = arg;
+		if (v->tuner != 0)
+			return -EINVAL;
+		return 0;
+	} case VIDIOCGFREQ: {
+		unsigned long *freq = arg;
+		*freq = BITS2FREQ(radio_bits_get(card));
+		return 0;
+	} case VIDIOCSFREQ: {
+		unsigned long *freq = arg;
+		if (*freq < FREQ_LO || *freq > FREQ_HI)
+			return -EINVAL;
+		radio_bits_set(card, FREQ2BITS(*freq));
+		return 0;
+	} case VIDIOCGAUDIO: {
+		struct video_audio *v = arg;
+		memset(v, 0, sizeof(*v));
+		strcpy(v->name, "Radio");
+		v->flags = VIDEO_AUDIO_MUTABLE | card->muted;
+		v->mode = VIDEO_SOUND_STEREO;
+		return 0;
+	} case VIDIOCSAUDIO: {
+		struct video_audio *v = arg;
+		if (v->audio)
+			return -EINVAL;
+		{
+			register u16 io = card->io;
+			register u16 omask = inw(io + IO_MASK);
+			outw(~STR_WREN, io + IO_MASK);
+			outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ?
+				STR_WREN : 0, io);
+			udelay(4);
+			outw(omask, io + IO_MASK);
+			msleep(125);
 			return 0;
 		}
-		case VIDIOCGTUNER: {
-			struct video_tuner *v = arg;
-			if(v->tuner)
-				return -EINVAL;
-			(void)radio_bits_get(card);
-			v->flags = VIDEO_TUNER_LOW | card->stereo;
-			v->signal = card->tuned;
-			strcpy(v->name, "FM");
-			v->rangelow = FREQ_LO;
-			v->rangehigh = FREQ_HI;
-			v->mode = VIDEO_MODE_AUTO;
-		        return 0;
-		}
-		case VIDIOCSTUNER: {
-			struct video_tuner *v = arg;
-			if(v->tuner!=0)
-				return -EINVAL;
-			return 0;
-		}
-		case VIDIOCGFREQ: {
-			unsigned long *freq = arg;
-			*freq = BITS2FREQ(radio_bits_get(card));
-			return 0;
-		}
-		case VIDIOCSFREQ: {
-			unsigned long *freq = arg;
-			if (*freq<FREQ_LO || *freq>FREQ_HI )
-				return -EINVAL;
-			radio_bits_set(card, FREQ2BITS(*freq));
-			return 0;
-		}
-		case VIDIOCGAUDIO: {	
-			struct video_audio *v = arg;
-			memset(v,0,sizeof(*v));
-			strcpy(v->name, "Radio");
-			v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
-			v->mode=VIDEO_SOUND_STEREO;
-			return 0;		
-		}
-		case VIDIOCSAUDIO: {
-			struct video_audio *v = arg;
-			if(v->audio)
-				return -EINVAL;
-			{
-				register __u16 io=card->io;
-				register __u16 omask = inw(io + IO_MASK);
-				outw(~STR_WREN, io + IO_MASK);
-				outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
-				     ? STR_WREN : 0, io);
-				udelay(4);
-				outw(omask, io + IO_MASK);
-				msleep(125);
-				return 0;
-			}
-		}
-		case VIDIOCGUNIT: {
-			struct video_unit *v = arg;
-			v->video=VIDEO_NO_UNIT;
-			v->vbi=VIDEO_NO_UNIT;
-			v->radio=dev->minor;
-			v->audio=0;
-			v->teletext=VIDEO_NO_UNIT;
-			return 0;		
-		}
-		default: return -ENOIOCTLCMD;
+	} case VIDIOCGUNIT: {
+		struct video_unit *v = arg;
+		v->video = VIDEO_NO_UNIT;
+		v->vbi = VIDEO_NO_UNIT;
+		v->radio = dev->minor;
+		v->audio = 0;
+		v->teletext = VIDEO_NO_UNIT;
+		return 0;
+	} default:
+		return -ENOIOCTLCMD;
 	}
 }
 
 static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+	unsigned int cmd, unsigned long arg)
 {
 	struct video_device *dev = video_devdata(file);
-	struct radio_device *card=dev->priv;
+	struct radio_device *card = video_get_drvdata(dev);
 	int ret;
 
 	down(&card->lock);
 	ret = video_usercopy(inode, file, cmd, arg, radio_function);
 	up(&card->lock);
+
 	return ret;
 }
 
-static __u16 radio_install(struct pci_dev *pcidev);
-
-MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
-MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
-MODULE_LICENSE("GPL");
-
-static void __exit maestro_radio_exit(void)
+static u16 __devinit radio_power_on(struct radio_device *dev)
 {
-	video_unregister_device(&maestro_radio);
-}
+	register u16 io = dev->io;
+	register u32 ofreq;
+	u16 omask, odir;
 
-static int __init maestro_radio_init(void)
-{
-	register __u16 found=0;
-	struct pci_dev *pcidev = NULL;
-	while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, 
-						  PCI_DEVICE_ID_ESS_ESS1968,
-						  pcidev)))
-		found |= radio_install(pcidev);
-	while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
-						  PCI_DEVICE_ID_ESS_ESS1978, 
-						  pcidev)))
-		found |= radio_install(pcidev);
-	if(!found) {
-		printk(KERN_INFO "radio-maestro: no devices found.\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-module_init(maestro_radio_init);
-module_exit(maestro_radio_exit);
-
-static inline __u16 radio_power_on(struct radio_device *dev)
-{
-	register __u16 io=dev->io;
-	register __u32 ofreq;
-	__u16 omask, odir;
 	omask = inw(io + IO_MASK);
-	odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
+	odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
 	outw(odir & ~STR_WREN, io + IO_DIR);
 	dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE;
 	outw(odir, io + IO_DIR);
@@ -299,35 +281,101 @@
 	udelay(16);
 	outw(omask, io + IO_MASK);
 	ofreq = radio_bits_get(dev);
-	if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
+
+	if ((ofreq < FREQ2BITS(FREQ_LO)) || (ofreq > FREQ2BITS(FREQ_HI)))
 		ofreq = FREQ2BITS(FREQ_LO);
 	radio_bits_set(dev, ofreq);
+
 	return (ofreq == radio_bits_get(dev));
 }
 
-static __u16 radio_install(struct pci_dev *pcidev)
+static int __devinit maestro_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
 {
-	if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
-		return 0;
-	
-	radio_unit.io = pcidev->resource[0].start + GPIO_DATA;
-	maestro_radio.priv = &radio_unit;
-	init_MUTEX(&radio_unit.lock);
-	
-	if(radio_power_on(&radio_unit)) {
-		if(video_register_device(&maestro_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
-			printk("radio-maestro: can't register device!");
-			return 0;
-		}
-		printk(KERN_INFO "radio-maestro: version "
-		       DRIVER_VERSION 
-		       " time " 
-		       __TIME__ "  "
-		       __DATE__
-		       "\n");
-		printk(KERN_INFO "radio-maestro: radio chip initialized\n");
-		return 1;
-	} else
-		return 0;   
+	struct radio_device *radio_unit;
+	struct video_device *maestro_radio_inst;
+	int retval;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "enabling pci device failed!\n");
+		goto err;
+	}
+
+	retval = -ENOMEM;
+
+	radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL);
+	if (radio_unit == NULL) {
+		dev_err(&pdev->dev, "not enough memory\n");
+		goto err;
+	}
+
+	radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
+	init_MUTEX(&radio_unit->lock);
+
+	maestro_radio_inst = video_device_alloc();
+	if (maestro_radio_inst == NULL) {
+		dev_err(&pdev->dev, "not enough memory\n");
+		goto errfr;
+	}
+
+	memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio));
+	video_set_drvdata(maestro_radio_inst, radio_unit);
+	pci_set_drvdata(pdev, maestro_radio_inst);
+
+	retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO,
+		radio_nr);
+	if (retval) {
+		printk(KERN_ERR "can't register video device!\n");
+		goto errfr1;
+	}
+
+	if (!radio_power_on(radio_unit)) {
+		retval = -EIO;
+		goto errunr;
+	}
+
+	dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ "  "
+		 __DATE__ "\n");
+	dev_info(&pdev->dev, "radio chip initialized\n");
+
+	return 0;
+errunr:
+	video_unregister_device(maestro_radio_inst);
+errfr1:
+	kfree(maestro_radio_inst);
+errfr:
+	kfree(radio_unit);
+err:
+	return retval;
+
 }
 
+static void __devexit maestro_remove(struct pci_dev *pdev)
+{
+	struct video_device *vdev = pci_get_drvdata(pdev);
+
+	video_unregister_device(vdev);
+}
+
+static int __init maestro_radio_init(void)
+{
+	int retval = pci_register_driver(&maestro_r_driver);
+
+	if (retval)
+		printk(KERN_ERR "error during registration pci driver\n");
+
+	return retval;
+}
+
+static void __exit maestro_radio_exit(void)
+{
+	pci_unregister_driver(&maestro_r_driver);
+}
+
+module_init(maestro_radio_init);
+module_exit(maestro_radio_exit);
+
+MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
+MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 959d2c5..7c34024 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2585,8 +2585,6 @@
 
 #ifdef CONFIG_COMPAT
 
-#include <linux/ioctl32.h>
-
 static int
 compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
 			unsigned long arg)
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 9c5945d..201e136 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -43,7 +43,7 @@
 /*
  * Define partitions for flash device
  */
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
 	{
 		.name 	= "NAND FS 0",
 	  	.offset = 0,
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 3a5841c..4129c03 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -96,7 +96,7 @@
  */
 static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
 
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
         {
                 .name   = "Renesas flash partition 1",
                 .offset = 0,
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 32541cb..9cf1ce7 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -67,7 +67,7 @@
 /*
  * Define partitions for flash device
  */
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
 	{
 		.name	= "SPIA flash partition 1",
 		.offset	= 0,
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index d2102a2..adfba44 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -505,7 +505,7 @@
 #define HW_REVID_MASK	HW_REVID(1, 1, 1, 1, 1, 1, 1)
 
 /* directly indexed by chip_t, above */
-const static struct {
+static const struct {
 	const char *name;
 	u32 version; /* from RTL8139C/RTL8139D docs */
 	u32 flags;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 9099986..102c1f0 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -456,11 +456,6 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int sixpack_receive_room(struct tty_struct *tty)
-{
-	return 65536;  /* We can handle an infinite amount of data. :-) */
-}
-
 /*
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
@@ -671,6 +666,7 @@
 
 	/* Done.  We have linked the TTY line to a channel. */
 	tty->disc_data = sp;
+	tty->receive_room = 65536;
 
 	/* Now we're ready to register. */
 	if (register_netdev(dev))
@@ -802,7 +798,6 @@
 	.close		= sixpack_close,
 	.ioctl		= sixpack_ioctl,
 	.receive_buf	= sixpack_receive_buf,
-	.receive_room	= sixpack_receive_room,
 	.write_wakeup	= sixpack_write_wakeup,
 };
 
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index f4424cf..dc5e9d5 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -753,6 +753,7 @@
 
 	ax->tty = tty;
 	tty->disc_data = ax;
+	tty->receive_room = 65535;
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
@@ -940,11 +941,6 @@
 		tty->driver->unthrottle(tty);
 }
 
-static int mkiss_receive_room(struct tty_struct *tty)
-{
-	return 65536;  /* We can handle an infinite amount of data. :-) */
-}
-
 /*
  * Called by the driver when there's room for more data.  If we have
  * more packets to send, we send them here.
@@ -983,7 +979,6 @@
 	.close		= mkiss_close,
 	.ioctl		= mkiss_ioctl,
 	.receive_buf	= mkiss_receive_buf,
-	.receive_room	= mkiss_receive_room,
 	.write_wakeup	= mkiss_write_wakeup
 };
 
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 3d016a4..6070195 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -285,19 +285,6 @@
 }
 
 /*
- * Function irport_probe (void)
- *
- *    Start IO port 
- *
- */
-int irport_probe(int iobase)
-{
-	IRDA_DEBUG(4, "%s(), iobase=%#x\n", __FUNCTION__, iobase);
-
-	return 0;
-}
-
-/*
  * Function irport_get_fcr (speed)
  *
  *    Compute value of fcr
@@ -382,7 +369,7 @@
  *    we cannot use schedule_timeout() when we are in interrupt context
  *
  */
-int __irport_change_speed(struct irda_task *task)
+static int __irport_change_speed(struct irda_task *task)
 {
 	struct irport_cb *self;
 	__u32 speed = (__u32) task->param;
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index b8d1123..101750b 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -289,22 +289,6 @@
 }
 
 /*
- * Function irtty_receive_room (tty)
- *
- *    Used by the TTY to find out how much data we can receive at a time
- * 
-*/
-static int irtty_receive_room(struct tty_struct *tty) 
-{
-	struct sirtty_cb *priv = tty->disc_data;
-
-	IRDA_ASSERT(priv != NULL, return 0;);
-	IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
-
-	return 65536;  /* We can handle an infinite amount of data. :-) */
-}
-
-/*
  * Function irtty_write_wakeup (tty)
  *
  *    Called by the driver when there's room for more data.  If we have
@@ -534,6 +518,7 @@
 
 	dev->priv = priv;
 	tty->disc_data = priv;
+	tty->receive_room = 65536;
 
 	up(&irtty_sem);
 
@@ -605,7 +590,6 @@
 	.ioctl		= irtty_ioctl,
  	.poll		= NULL,
 	.receive_buf	= irtty_receive_buf,
-	.receive_room	= irtty_receive_room,
 	.write_wakeup	= irtty_write_wakeup,
 	.owner		= THIS_MODULE,
 };
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index a1ac4bd..a7bb54d 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -415,7 +415,7 @@
 
 
 /* directly indexed by chip_t, above */
-const static struct {
+static const struct {
 	const char *name;
 	u8 version; /* from RTL8139C docs */
 	u32 RxConfigMask; /* should clear the bits supported by this chip */
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 400f652..aa6540b 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -189,7 +189,7 @@
 		goto out_free;
 
 	tty->disc_data = ap;
-
+	tty->receive_room = 65536;
 	return 0;
 
  out_free:
@@ -343,12 +343,6 @@
 	return 0;
 }
 
-static int
-ppp_asynctty_room(struct tty_struct *tty)
-{
-	return 65535;
-}
-
 /*
  * This can now be called from hard interrupt level as well
  * as soft interrupt level or mainline.
@@ -398,7 +392,6 @@
 	.write	= ppp_asynctty_write,
 	.ioctl	= ppp_asynctty_ioctl,
 	.poll	= ppp_asynctty_poll,
-	.receive_room = ppp_asynctty_room,
 	.receive_buf = ppp_asynctty_receive,
 	.write_wakeup = ppp_asynctty_wakeup,
 };
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 4d51c0c..33cb825 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -237,7 +237,7 @@
 		goto out_free;
 
 	tty->disc_data = ap;
-
+	tty->receive_room = 65536;
 	return 0;
 
  out_free:
@@ -384,12 +384,6 @@
 	return 0;
 }
 
-static int
-ppp_sync_room(struct tty_struct *tty)
-{
-	return 65535;
-}
-
 /*
  * This can now be called from hard interrupt level as well
  * as soft interrupt level or mainline.
@@ -439,7 +433,6 @@
 	.write	= ppp_sync_write,
 	.ioctl	= ppp_synctty_ioctl,
 	.poll	= ppp_sync_poll,
-	.receive_room = ppp_sync_room,
 	.receive_buf = ppp_sync_receive,
 	.write_wakeup = ppp_sync_wakeup,
 };
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 14a76f7..2e1bed15 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -170,7 +170,7 @@
 #define _R(NAME,MAC,MASK) \
 	{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
 
-const static struct {
+static const struct {
 	const char *name;
 	u8 mac_version;
 	u32 RxConfigMask;	/* Clears the bits supported by this chip */
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 478791e..b420182 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -329,7 +329,7 @@
 	{ NULL, }
 };
 
-const static struct {
+static const struct {
 	const char *name;
 } sis_chip_info[] = {
 	{ "SiS 190 PCI Fast Ethernet adapter" },
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 404ea42..b2e18d2 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -651,11 +651,6 @@
  ******************************************/
 
 
-static int slip_receive_room(struct tty_struct *tty)
-{
-	return 65536;  /* We can handle an infinite amount of data. :-) */
-}
-
 /*
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
@@ -869,10 +864,6 @@
 	sl->line = tty_devnum(tty);
 	sl->pid = current->pid;
 	
-	/* FIXME: already done before we were called - seems this can go */
-	if (tty->driver->flush_buffer)
-		tty->driver->flush_buffer(tty);
-		
 	if (!test_bit(SLF_INUSE, &sl->flags)) {
 		/* Perform the low-level SLIP initialization. */
 		if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -897,6 +888,7 @@
 
 	/* Done.  We have linked the TTY line to a channel. */
 	rtnl_unlock();
+	tty->receive_room = 65536;	/* We don't flow control */
 	return sl->dev->base_addr;
 
 err_free_bufs:
@@ -1329,7 +1321,6 @@
 	.close	 	= slip_close,
 	.ioctl		= slip_ioctl,
 	.receive_buf	= slip_receive_buf,
-	.receive_room	= slip_receive_room,
 	.write_wakeup	= slip_write_wakeup,
 };
 
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 52f26b9..931cbdf 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -689,7 +689,7 @@
 					}
 				}	
 				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
-				kfree(buf);
+				kfree((void *)buf);
 				buf = cpc_tty->buf_rx.first;
 				flg_rx = 1;
 			}
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index bdf672c..9c3ccc6 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -515,11 +515,6 @@
 	return 0;
 }
 
-static int x25_asy_receive_room(struct tty_struct *tty)
-{
-	return 65536;  /* We can handle an infinite amount of data. :-) */
-}
-
 /*
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
@@ -573,6 +568,7 @@
 
 	sl->tty = tty;
 	tty->disc_data = sl;
+	tty->receive_room = 65536;
 	if (tty->driver->flush_buffer)  {
 		tty->driver->flush_buffer(tty);
 	}
@@ -779,7 +775,6 @@
 	.close		= x25_asy_close_tty,
 	.ioctl		= x25_asy_ioctl,
 	.receive_buf	= x25_asy_receive_buf,
-	.receive_room	= x25_asy_receive_room,
 	.write_wakeup	= x25_asy_write_wakeup,
 };
 
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index d25264b..18baacf 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1675,11 +1675,6 @@
 /************************************************************************/
 /* Receiving routines							*/
 
-static int strip_receive_room(struct tty_struct *tty)
-{
-	return 0x10000;		/* We can handle an infinite amount of data. :-) */
-}
-
 /*
  * This function parses the response to the ATS300? command,
  * extracting the radio version and serial number.
@@ -2424,7 +2419,7 @@
 /*
  * Here's the order things happen:
  * When the user runs "slattach -p strip ..."
- *  1. The TTY module calls strip_open
+ *  1. The TTY module calls strip_open;;
  *  2. strip_open calls strip_alloc
  *  3.                  strip_alloc calls register_netdev
  *  4.                  register_netdev calls strip_dev_init
@@ -2652,6 +2647,8 @@
 
 	strip_info->tty = tty;
 	tty->disc_data = strip_info;
+	tty->receive_room = 65536;
+
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 
@@ -2762,7 +2759,6 @@
 	.close = strip_close,
 	.ioctl = strip_ioctl,
 	.receive_buf = strip_receive_buf,
-	.receive_room = strip_receive_room,
 	.write_wakeup = strip_write_some_more,
 };
 
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 2472fa1..9c25654 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1751,6 +1751,7 @@
 	.open		= dasd_open,
 	.release	= dasd_release,
 	.ioctl		= dasd_ioctl,
+	.compat_ioctl	= dasd_compat_ioctl,
 	.getgeo		= dasd_getgeo,
 };
 
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 2fb05c4..e4b4015 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -527,6 +527,7 @@
 int  dasd_ioctl_no_register(struct module *, int, dasd_ioctl_fn_t);
 int  dasd_ioctl_no_unregister(struct module *, int, dasd_ioctl_fn_t);
 int  dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+long dasd_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 /* externals in dasd_proc.c */
 int dasd_proc_init(void);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 8e4dcd5..9396fca 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -118,6 +118,18 @@
 	return -EINVAL;
 }
 
+long
+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);
+	unlock_kernel();
+
+	return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
+}
+
 static int
 dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
 {
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 75419cf..1f06091 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -16,6 +16,7 @@
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/vt_kern.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -432,8 +433,6 @@
 				if (count > slen)
 					count = slen;
 			} else
-			if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)
-				count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
 			EBCASC(raw->inbuf, count);
 			cchar = ctrlchar_handle(raw->inbuf, count, tty);
 			switch (cchar & CTRLCHAR_MASK) {
@@ -441,28 +440,20 @@
 				break;
 
 			case CTRLCHAR_CTRL:
-				tty->flip.count++;
-				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-				*tty->flip.char_buf_ptr++ = cchar;
+				tty_insert_flip_char(tty, cchar, TTY_NORMAL);
 				tty_flip_buffer_push(raw->tty);
 				break;
 
 			case CTRLCHAR_NONE:
-				memcpy(tty->flip.char_buf_ptr,
-				       raw->inbuf, count);
 				if (count < 2 ||
-				    (strncmp(raw->inbuf+count-2, "^n", 2) &&
-				    strncmp(raw->inbuf+count-2, "\252n", 2)) ) {
-					/* don't add the auto \n */
-					tty->flip.char_buf_ptr[count] = '\n';
-					memset(tty->flip.flag_buf_ptr,
-					       TTY_NORMAL, count + 1);
+				    (strncmp(raw->inbuf+count-2, "\252n", 2) &&
+				     strncmp(raw->inbuf+count-2, "^n", 2)) ) {
+					/* add the auto \n */
+					raw->inbuf[count] = '\n';
 					count++;
 				} else
-					count-=2;
-				tty->flip.char_buf_ptr += count;
-				tty->flip.flag_buf_ptr += count;
-				tty->flip.count += count;
+					count -= 2;
+				tty_insert_flip_string(tty, raw->inbuf, count);
 				tty_flip_buffer_push(raw->tty);
 				break;
 			}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 735a7fc..5f6fa4c 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -319,9 +319,8 @@
 /*
  * process ioctl commands for the tube driver
  */
-static int
-fs3270_ioctl(struct inode *inode, struct file *filp,
-	     unsigned int cmd, unsigned long arg)
+static long
+fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct fs3270 *fp;
 	struct raw3270_iocb iocb;
@@ -331,6 +330,7 @@
 	if (!fp)
 		return -ENODEV;
 	rc = 0;
+	lock_kernel();
 	switch (cmd) {
 	case TUBICMD:
 		fp->read_command = arg;
@@ -356,6 +356,7 @@
 			rc = -EFAULT;
 		break;
 	}
+	unlock_kernel();
 	return rc;
 }
 
@@ -491,12 +492,13 @@
 }
 
 static struct file_operations fs3270_fops = {
-	.owner	 = THIS_MODULE,		/* owner */
-	.read	 = fs3270_read,		/* read */
-	.write	 = fs3270_write,	/* write */
-	.ioctl	 = fs3270_ioctl,	/* ioctl */
-	.open	 = fs3270_open,		/* open */
-	.release = fs3270_close,	/* release */
+	.owner		 = THIS_MODULE,		/* owner */
+	.read		 = fs3270_read,		/* read */
+	.write		 = fs3270_write,	/* write */
+	.unlocked_ioctl	 = fs3270_ioctl,	/* ioctl */
+	.compat_ioctl	 = fs3270_ioctl,	/* ioctl */
+	.open	 	= fs3270_open,		/* open */
+	.release 	= fs3270_close,		/* release */
 };
 
 /*
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index a20d7c8..6cbf067 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -13,6 +13,7 @@
 #include <linux/kmod.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
@@ -496,25 +497,19 @@
 	case CTRLCHAR_SYSRQ:
 		break;
 	case CTRLCHAR_CTRL:
-		sclp_tty->flip.count++;
-		*sclp_tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-		*sclp_tty->flip.char_buf_ptr++ = cchar;
+		tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
 		tty_flip_buffer_push(sclp_tty);
 		break;
 	case CTRLCHAR_NONE:
 		/* send (normal) input to line discipline */
-		memcpy(sclp_tty->flip.char_buf_ptr, buf, count);
 		if (count < 2 ||
-		    (strncmp ((const char *) buf + count - 2, "^n", 2) &&
-		     strncmp ((const char *) buf + count - 2, "\0252n", 2))) {
-			sclp_tty->flip.char_buf_ptr[count] = '\n';
-			count++;
+		    (strncmp((const char *) buf + count - 2, "^n", 2) &&
+		     strncmp((const char *) buf + count - 2, "\252n", 2))) {
+			/* add the auto \n */
+			tty_insert_flip_string(sclp_tty, buf, count);
+			tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
 		} else
-			count -= 2;
-		memset(sclp_tty->flip.flag_buf_ptr, TTY_NORMAL, count);
-		sclp_tty->flip.char_buf_ptr += count;
-		sclp_tty->flip.flag_buf_ptr += count;
-		sclp_tty->flip.count += count;
+			tty_insert_flip_string(sclp_tty, buf, count - 2);
 		tty_flip_buffer_push(sclp_tty);
 		break;
 	}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 06bd858..9e02625 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
@@ -482,16 +483,7 @@
 		/* Send input to line discipline */
 		buffer++;
 		count--;
-		/* Prevent buffer overrun by discarding input. Note that
-		 * because buffer_push works asynchronously, we cannot wait
-		 * for the buffer to be emptied. */
-		if (count + sclp_vt220_tty->flip.count > TTY_FLIPBUF_SIZE)
-			count = TTY_FLIPBUF_SIZE - sclp_vt220_tty->flip.count;
-		memcpy(sclp_vt220_tty->flip.char_buf_ptr, buffer, count);
-		memset(sclp_vt220_tty->flip.flag_buf_ptr, TTY_NORMAL, count);
-		sclp_vt220_tty->flip.char_buf_ptr += count;
-		sclp_vt220_tty->flip.flag_buf_ptr += count;
-		sclp_vt220_tty->flip.count += count;
+		tty_insert_flip_string(sclp_vt220_tty, buffer, count);
 		tty_flip_buffer_push(sclp_vt220_tty);
 		break;
 	}
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 86262a1..5ce7ca3 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -37,6 +37,8 @@
 static int tapechar_release(struct inode *,struct file *);
 static int tapechar_ioctl(struct inode *, struct file *, unsigned int,
 			  unsigned long);
+static long tapechar_compat_ioctl(struct file *, unsigned int,
+			  unsigned long);
 
 static struct file_operations tape_fops =
 {
@@ -44,6 +46,7 @@
 	.read = tapechar_read,
 	.write = tapechar_write,
 	.ioctl = tapechar_ioctl,
+	.compat_ioctl = tapechar_compat_ioctl,
 	.open = tapechar_open,
 	.release = tapechar_release,
 };
@@ -463,6 +466,23 @@
 	return device->discipline->ioctl_fn(device, no, data);
 }
 
+static long
+tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+	struct tape_device *device = filp->private_data;
+	int rval = -ENOIOCTLCMD;
+
+	if (device->discipline->ioctl_fn) {
+		lock_kernel();
+		rval = device->discipline->ioctl_fn(device, no, data);
+		unlock_kernel();
+		if (rval == -EINVAL)
+			rval = -ENOIOCTLCMD;
+	}
+
+	return rval;
+}
+
 /*
  * Initialize character device frontend.
  */
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 135ae04..2f54d03 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -30,7 +30,6 @@
 #include <linux/delay.h>       // mdelay
 #include <linux/init.h>
 #include <linux/interrupt.h>   // for tasklets
-#include <linux/ioctl32.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 968f2c1..93d1725 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -25,6 +25,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -101,25 +102,17 @@
 static int
 ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
 {
-	int c;
 	int len;
 	struct tty_struct *tty;
 
 	DBF_TEXT(trace, 5, __FUNCTION__);
 	if ((tty = info->tty)) {
 		if (info->mcr & UART_MCR_RTS) {
-			c = TTY_FLIPBUF_SIZE - tty->flip.count;
 			len = skb->len;
-			if (c >= len) {
-				memcpy(tty->flip.char_buf_ptr, skb->data, len);
-				memset(tty->flip.flag_buf_ptr, 0, len);
-				tty->flip.count += len;
-				tty->flip.char_buf_ptr += len;
-				tty->flip.flag_buf_ptr += len;
-				tty_flip_buffer_push(tty);
-				kfree_skb(skb);
-				return 1;
-			}
+			tty_insert_flip_string(tty, skb->data, len);
+			tty_flip_buffer_push(tty);
+			kfree_skb(skb);
+			return 1;
 		}
 	}
 	return 0;
@@ -138,19 +131,12 @@
 	DBF_TEXT(trace, 5, __FUNCTION__);
 	if ((tty = info->tty)) {
 		if (info->mcr & UART_MCR_RTS) {
-			int c = TTY_FLIPBUF_SIZE - tty->flip.count;
 			struct sk_buff *skb;
 			
-			if ((c > 0) && (skb = skb_dequeue(&info->rx_queue))) {
+			if ((skb = skb_dequeue(&info->rx_queue))) {
 				int len = skb->len;
-				if (len > c)
-					len = c;
-				memcpy(tty->flip.char_buf_ptr, skb->data, len);
+				tty_insert_flip_string(tty, skb->data, len);
 				skb_pull(skb, len);
-				memset(tty->flip.flag_buf_ptr, 0, len);
-				tty->flip.count += len;
-				tty->flip.char_buf_ptr += len;
-				tty->flip.flag_buf_ptr += len;
 				tty_flip_buffer_push(tty);
 				if (skb->len > 0)
 					skb_queue_head(&info->rx_queue, skb);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 3cb68af..9b9062f 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
-#include <linux/ioctl32.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include <asm/semaphore.h>
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 0920220..4299fab 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/completion.h>
-#include <linux/ioctl32.h>
 #include <linux/compat.h>
 #include <linux/chio.h>			/* here are all the ioctls */
 
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index eb8c390..3d9e67d 100644
--- a/drivers/scsi/megaraid/megaraid_mm.h
+++ b/drivers/scsi/megaraid/megaraid_mm.h
@@ -22,7 +22,6 @@
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/list.h>
-#include <linux/ioctl32.h>
 
 #include "mbox_defs.h"
 #include "megaraid_ioctl.h"
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index b5cf394..221999b 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -94,15 +94,6 @@
 
 	status = *CSR_UARTFLG;
 	while (!(status & 0x10) && max_count--) {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts
-			 */
-		}
-
 		ch = *CSR_UARTDR;
 		flag = TTY_NORMAL;
 		port->icount.rx++;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 67e9afa..4dd5c3f 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -294,7 +294,7 @@
 {
 	struct tty_struct *tty = info->tty;
 	m68328_uart *uart = &uart_addr[info->line];
-	unsigned char ch;
+	unsigned char ch, flag;
 
 	/*
 	 * This do { } while() loop will get ALL chars out of Rx FIFO 
@@ -332,26 +332,24 @@
 		/*
 		 * Make sure that we do not overflow the buffer
 		 */
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+		if (tty_request_buffer_room(tty, 1) == 0) {
 			schedule_work(&tty->flip.work);
 			return;
 		}
 
+		flag = TTY_NORMAL;
+
 		if(rx & URX_PARITY_ERROR) {
-			*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+			flag = TTY_PARITY;
 			status_handle(info, rx);
 		} else if(rx & URX_OVRUN) {
-			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+			flag = TTY_OVERRUN;
 			status_handle(info, rx);
 		} else if(rx & URX_FRAME_ERROR) {
-			*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+			flag = TTY_FRAME;
 			status_handle(info, rx);
-		} else {
-			*tty->flip.flag_buf_ptr++ = 0; /* XXX */
 		}
-                *tty->flip.char_buf_ptr++ = ch;
-		tty->flip.count++;
-
+		tty_insert_flip_char(tty, ch, flag);
 #ifndef CONFIG_XCOPILOT_BUGS
 	} while((rx = uart->urx.w) & URX_DATA_READY);
 #endif
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 170c9d2..60f5a5d 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -394,7 +394,7 @@
 static _INLINE_ void receive_chars(ser_info_t *info)
 {
 	struct tty_struct *tty = info->tty;
-	unsigned char ch, *cp;
+	unsigned char ch, flag, *cp;
 	/*int	ignored = 0;*/
 	int	i;
 	ushort	status;
@@ -438,24 +438,15 @@
 		cp = (char *)bdp->buf;
 		status = bdp->status;
 
-		/* Check to see if there is room in the tty buffer for
-		 * the characters in our BD buffer.  If not, we exit
-		 * now, leaving the BD with the characters.  We'll pick
-		 * them up again on the next receive interrupt (which could
-		 * be a timeout).
-		 */
-		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
-			break;
-
 		while (i-- > 0) {
 			ch = *cp++;
-			*tty->flip.char_buf_ptr = ch;
 			icount->rx++;
 
 #ifdef SERIAL_DEBUG_INTR
 			printk("DR%02x:%02x...", ch, status);
 #endif
-			*tty->flip.flag_buf_ptr = 0;
+			flag = TTY_NORMAL;
+
 			if (status & (BD_SC_BR | BD_SC_FR |
 				       BD_SC_PR | BD_SC_OV)) {
 				/*
@@ -490,30 +481,18 @@
 					if (info->flags & ASYNC_SAK)
 						do_SAK(tty);
 				} else if (status & BD_SC_PR)
-					*tty->flip.flag_buf_ptr = TTY_PARITY;
+					flag = TTY_PARITY;
 				else if (status & BD_SC_FR)
-					*tty->flip.flag_buf_ptr = TTY_FRAME;
-				if (status & BD_SC_OV) {
-					/*
-					 * Overrun is special, since it's
-					 * reported immediately, and doesn't
-					 * affect the current character
-					 */
-					if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-						tty->flip.count++;
-						tty->flip.flag_buf_ptr++;
-						tty->flip.char_buf_ptr++;
-						*tty->flip.flag_buf_ptr =
-								TTY_OVERRUN;
-					}
-				}
+					flag = TTY_FRAME;
 			}
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				break;
-
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
+			tty_insert_flip_char(tty, ch, flag);
+			if (status & BD_SC_OV)
+				/*
+				 * Overrun is special, since it's
+				 * reported immediately, and doesn't
+				 * affect the current character
+				 */
+				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		}
 
 		/* This BD is ready to be used again.  Clear status.
@@ -541,12 +520,7 @@
 	/* Check to see if there is room in the tty buffer for
 	 * the break.  If not, we exit now, losing the break.  FIXME
 	 */
-	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
-		return;
-	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
-	*(tty->flip.char_buf_ptr++) = 0;
-	tty->flip.count++;
-
+	tty_insert_flip_char(tty, 0, TTY_BREAK);
 	schedule_work(&tty->flip.work);
 }
 
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index e845461..54e5cc0 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1142,19 +1142,6 @@
 	char flag;
 
 	do {
-		/* The following is not allowed by the tty layer and
-		   unsafe. It should be fixed ASAP */
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			if (tty->low_latency) {
-				spin_unlock(&up->port.lock);
-				tty_flip_buffer_push(tty);
-				spin_lock(&up->port.lock);
-			}
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts
-			 */
-		}
 		ch = serial_inp(up, UART_RX);
 		flag = TTY_NORMAL;
 		up->port.icount.rx++;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 1bae26a..698cb76 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -860,7 +860,7 @@
 
 config SERIAL_JSM
         tristate "Digi International NEO PCI Support"
-	depends on PCI
+	depends on PCI && BROKEN
         select SERIAL_CORE
         help
           This is a driver for Digi International's Neo series
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 48f6e87..3490022 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -154,15 +154,6 @@
 
 	status = UART_GET_FR(port);
 	while (UART_RX_DATA(status) && max_count--) {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts.
-			 */
-		}
-
 		ch = UART_GET_CHAR(port);
 		flag = TTY_NORMAL;
 
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 1296705..034a029 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -120,15 +120,6 @@
 
 	status = readw(uap->port.membase + UART01x_FR);
 	while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts
-			 */
-		}
-
 		ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
 		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index a274ebf..ceb5d7f 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -241,18 +241,12 @@
 receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
 {
 	struct tty_struct *tty = up->port.info->tty;
-	unsigned char ch;
+	unsigned char ch, flag;
 	int max_count = 256;
 
 	do {
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return; // if TTY_DONT_FLIP is set
-		}
 		ch = serial_inp(up, UART_RX);
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 
 		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -292,30 +286,23 @@
 #endif
 			if (*status & UART_LSR_BI) {
 				DEBUG_INTR("handling break....");
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			} else if (*status & UART_LSR_PE)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (*status & UART_LSR_FE)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
 			goto ignore_char;
-		if ((*status & up->port.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-		if ((*status & UART_LSR_OE) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+		if ((*status & up->port.ignore_status_mask) == 0)
+			tty_insert_flip_char(tty, ch, flag);
+		if (*status & UART_LSR_OE)
 			/*
 			 * Overrun is special, since it's reported
 			 * immediately, and doesn't affect the current
 			 * character.
 			 */
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		}
 	ignore_char:
 		*status = serial_inp(up, UART_LSR);
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 87ef368..8ef9994 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -104,8 +104,6 @@
 	while (!(status & SYSFLG_URXFE)) {
 		ch = clps_readl(UARTDR(port));
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			goto ignore_char;
 		port->icount.rx++;
 
 		flg = TTY_NORMAL;
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 4d8516d..a64ba26 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -216,8 +216,6 @@
 
 		if (!tty)
 			break;
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			break;
 
 		icount->rx++;
 
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index eb31125..144a7a3 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -729,19 +729,20 @@
 	unsigned short int status;
 	struct uart_icount *icount;
 	unsigned long offset;
+	unsigned char flag;
 
 	trace(icom_port, "RCV_COMPLETE", 0);
 	rcv_buff = icom_port->next_rcv;
 
 	status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
 	while (status & SA_FL_RCV_DONE) {
+		int first = -1;
 
 		trace(icom_port, "FID_STATUS", status);
 		count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
 
+                count = tty_buffer_request_room(tty, count);
 		trace(icom_port, "RCV_COUNT", count);
-		if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
-			count = TTY_FLIPBUF_SIZE - tty->flip.count;
 
 		trace(icom_port, "REAL_COUNT", count);
 
@@ -749,15 +750,10 @@
 			cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
 			icom_port->recv_buf_pci;
 
-		memcpy(tty->flip.char_buf_ptr,(unsigned char *)
-		       ((unsigned long)icom_port->recv_buf + offset), count);
-
+		/* Block copy all but the last byte as this may have status */
 		if (count > 0) {
-			tty->flip.count += count - 1;
-			tty->flip.char_buf_ptr += count - 1;
-
-			memset(tty->flip.flag_buf_ptr, 0, count);
-			tty->flip.flag_buf_ptr += count - 1;
+			first = icom_port->recv_buf[offset];
+			tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
 		}
 
 		icount = &icom_port->uart_port.icount;
@@ -765,12 +761,14 @@
 
 		/* Break detect logic */
 		if ((status & SA_FLAGS_FRAME_ERROR)
-		    && (tty->flip.char_buf_ptr[0] == 0x00)) {
+		    && first == 0) {
 			status &= ~SA_FLAGS_FRAME_ERROR;
 			status |= SA_FLAGS_BREAK_DET;
 			trace(icom_port, "BREAK_DET", 0);
 		}
 
+		flag = TTY_NORMAL;
+
 		if (status &
 		    (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
 		     SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
@@ -797,33 +795,26 @@
 			status &= icom_port->read_status_mask;
 
 			if (status & SA_FLAGS_BREAK_DET) {
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			} else if (status & SA_FLAGS_PARITY_ERROR) {
 				trace(icom_port, "PARITY_ERROR", 0);
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			} else if (status & SA_FLAGS_FRAME_ERROR)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 
-			if (status & SA_FLAGS_OVERRUN) {
-				/*
-				 * Overrun is special, since it's
-				 * reported immediately, and doesn't
-				 * affect the current character
-				 */
-				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-					tty->flip.count++;
-					tty->flip.flag_buf_ptr++;
-					tty->flip.char_buf_ptr++;
-					*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-				}
-			}
 		}
 
-		tty->flip.flag_buf_ptr++;
-		tty->flip.char_buf_ptr++;
-		tty->flip.count++;
-		ignore_char:
-			icom_port->statStg->rcv[rcv_buff].flags = 0;
+		tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
+
+		if (status & SA_FLAGS_OVERRUN)
+			/*
+			 * Overrun is special, since it's
+			 * reported immediately, and doesn't
+			 * affect the current character
+			 */
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ignore_char:
+		icom_port->statStg->rcv[rcv_buff].flags = 0;
 		icom_port->statStg->rcv[rcv_buff].leLength = 0;
 		icom_port->statStg->rcv[rcv_buff].WorkingLength =
 			(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 83c4c12..5c098be 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -256,9 +256,6 @@
 	error_return:
 		tty_insert_flip_char(tty, rx, flg);
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			goto out;
-
 	ignore_char:
 		rx = URXD0((u32)sport->port.membase);
 	} while(rx & URXD_CHARRDY);
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 771676a..1d85533 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -2327,19 +2327,13 @@
 	spin_lock_irqsave(&the_port->lock, pflags);
 	tty = info->tty;
 
-	if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count)
-		request_count = TTY_FLIPBUF_SIZE - tty->flip.count;
+	request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2);
 
 	if (request_count > 0) {
 		icount = &the_port->icount;
 		read_count = do_read(the_port, ch, request_count);
 		if (read_count > 0) {
-			flip = 1;
-			memcpy(tty->flip.char_buf_ptr, ch, read_count);
-			memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count);
-			tty->flip.char_buf_ptr += read_count;
-			tty->flip.flag_buf_ptr += read_count;
-			tty->flip.count += read_count;
+			tty_insert_flip_string(tty, ch, read_count);
 			icount->rx += read_count;
 		}
 	}
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index ef13234..66f117d 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -259,13 +259,7 @@
 	struct tty_struct *tty = up->port.info->tty;	/* XXX info==NULL? */
 
 	while (1) {
-		unsigned char ch, r1;
-
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return;		/* XXX Ignores SysRq when we need it most. Fix. */
-		}
+		unsigned char ch, r1, flag;
 
 		r1 = read_zsreg(channel, R1);
 		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -303,8 +297,7 @@
 		}
 
 		/* A real serial line, record the character and status.  */
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 		if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
 			if (r1 & BRK_ABRT) {
@@ -321,28 +314,21 @@
 				up->port.icount.overrun++;
 			r1 &= up->port.read_status_mask;
 			if (r1 & BRK_ABRT)
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			else if (r1 & PAR_ERR)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (r1 & CRC_ERR)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
 			goto next_char;
 
 		if (up->port.ignore_status_mask == 0xff ||
-		    (r1 & up->port.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-		if ((r1 & Rx_OVR) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
+		    (r1 & up->port.ignore_status_mask) == 0)
+		    	tty_insert_flip_char(tty, ch, flag);
+
+		if (r1 & Rx_OVR)
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	next_char:
 		ch = readb(&channel->control);
 		ZSDELAY();
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b0ecc75..b48066a 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -331,17 +331,12 @@
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned char ch;
+	unsigned char flag;
 	int max_count = 256;
 
 	do {
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return; // if TTY_DONT_FLIP is set
-		}
 		ch = sio_in(up, SIORXB);
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 
 		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -380,30 +375,24 @@
 
 			if (*status & UART_LSR_BI) {
 				DEBUG_INTR("handling break....");
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			} else if (*status & UART_LSR_PE)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (*status & UART_LSR_FE)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
 			goto ignore_char;
-		if ((*status & up->port.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-		if ((*status & UART_LSR_OE) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+		if ((*status & up->port.ignore_status_mask) == 0)
+			tty_insert_flip_char(tty, ch, flag);
+
+		if (*status & UART_LSR_OE) {
 			/*
 			 * Overrun is special, since it's reported
 			 * immediately, and doesn't affect the current
 			 * character.
 			 */
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		}
 	ignore_char:
 		*status = serial_in(up, UART_LSR);
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 47f7404..f2a51e6 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -313,7 +313,7 @@
 {
 	volatile unsigned char	*uartp;
 	struct tty_struct	*tty = info->tty;
-	unsigned char		status, ch;
+	unsigned char		status, ch, flag;
 
 	if (!tty)
 		return;
@@ -321,10 +321,6 @@
 	uartp = info->addr;
 
 	while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
-
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			break;
-
 		ch = uartp[MCFUART_URB];
 		info->stats.rx++;
 
@@ -335,29 +331,24 @@
 		}
 #endif
 
-		tty->flip.count++;
+		flag = TTY_NORMAL;
 		if (status & MCFUART_USR_RXERR) {
 			uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
 			if (status & MCFUART_USR_RXBREAK) {
 				info->stats.rxbreak++;
-				*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+				flag = TTY_BREAK;
 			} else if (status & MCFUART_USR_RXPARITY) {
 				info->stats.rxparity++;
-				*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+				flag = TTY_PARITY;
 			} else if (status & MCFUART_USR_RXOVERRUN) {
 				info->stats.rxoverrun++;
-				*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+				flag = TTY_OVERRUN;
 			} else if (status & MCFUART_USR_RXFRAMING) {
 				info->stats.rxframing++;
-				*tty->flip.flag_buf_ptr++ = TTY_FRAME;
-			} else {
-				/* This should never happen... */
-				*tty->flip.flag_buf_ptr++ = 0;
+				flag = TTY_FRAME;
 			}
-		} else {
-			*tty->flip.flag_buf_ptr++ = 0;
 		}
-		*tty->flip.char_buf_ptr++ = ch;
+		tty_insert_flip_char(tty, ch, flag);
 	}
 
 	schedule_work(&tty->flip.work);
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 1288d62..61dd17d 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -405,17 +405,13 @@
 mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
 {
 	struct tty_struct *tty = port->info->tty;
-	unsigned char ch;
+	unsigned char ch, flag;
 	unsigned short status;
 
 	/* While we can read, do so ! */
 	while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
 	        MPC52xx_PSC_SR_RXRDY) {
 
-		/* If we are full, just stop reading */
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			break;
-		
 		/* Get the char */
 		ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
 
@@ -428,45 +424,35 @@
 #endif
 
 		/* Store it */
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = 0;
+
+		flag = TTY_NORMAL;
 		port->icount.rx++;
 	
 		if ( status & (MPC52xx_PSC_SR_PE |
 		               MPC52xx_PSC_SR_FE |
-		               MPC52xx_PSC_SR_RB |
-		               MPC52xx_PSC_SR_OE) ) {
+		               MPC52xx_PSC_SR_RB) ) {
 			
 			if (status & MPC52xx_PSC_SR_RB) {
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 				uart_handle_break(port);
 			} else if (status & MPC52xx_PSC_SR_PE)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (status & MPC52xx_PSC_SR_FE)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
-			if (status & MPC52xx_PSC_SR_OE) {
-				/*
-				 * Overrun is special, since it's
-				 * reported immediately, and doesn't
-				 * affect the current character
-				 */
-				if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {
-					tty->flip.flag_buf_ptr++;
-					tty->flip.char_buf_ptr++;
-					tty->flip.count++;
-				}
-				*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			}
+				flag = TTY_FRAME;
 
 			/* Clear error condition */
 			out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);
 
 		}
-
-		tty->flip.char_buf_ptr++;
-		tty->flip.flag_buf_ptr++;
-		tty->flip.count++;
-
+		tty_insert_flip_char(tty, ch, flag);
+		if (status & MPC52xx_PSC_SR_OE) {
+			/*
+			 * Overrun is special, since it's
+			 * reported immediately, and doesn't
+			 * affect the current character
+			 */
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		}
 	}
 
 	tty_flip_buffer_push(tty);
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 8f83e40..0ca83ac 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -769,12 +769,12 @@
 		bytes_in = be16_to_cpu(rxre->bytecnt);
 
 		/* Following use of tty struct directly is deprecated */
-		if (unlikely((tty->flip.count + bytes_in) >= TTY_FLIPBUF_SIZE)){
+		if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) {
 			if (tty->low_latency)
 				tty_flip_buffer_push(tty);
 			/*
-			 * If this failed then we will throw awa the bytes
-			 * but mst do so to clear interrupts.
+			 * If this failed then we will throw away the bytes
+			 * but must do so to clear interrupts.
 			 */
 		}
 
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 7633132..4e49168 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -223,11 +223,6 @@
 		if (MUX_EOFIFO(data))
 			break;
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			continue;
-
-		*tty->flip.char_buf_ptr = data & 0xffu;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
 		port->icount.rx++;
 
 		if (MUX_BREAK(data)) {
@@ -239,9 +234,7 @@
 		if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
 			continue;
 
-		tty->flip.flag_buf_ptr++;
-		tty->flip.char_buf_ptr++;
-		tty->flip.count++;
+		tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
 	}
 	
 	if (start_count != port->icount.rx) {
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index ea24129..f330d6c 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -210,10 +210,9 @@
 					    struct pt_regs *regs)
 {
 	struct tty_struct *tty = NULL;
-	unsigned char ch, r1, drop, error;
+	unsigned char ch, r1, drop, error, flag;
 	int loops = 0;
 
- retry:
 	/* The interrupt can be enabled when the port isn't open, typically
 	 * that happens when using one port is open and the other closed (stale
 	 * interrupt) or when one port is used as a console.
@@ -246,20 +245,6 @@
 		error = 0;
 		drop = 0;
 
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			/* Have to drop the lock here */
-			pmz_debug("pmz: flip overflow\n");
-			spin_unlock(&uap->port.lock);
-			tty->flip.work.func((void *)tty);
-			spin_lock(&uap->port.lock);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				drop = 1;
-			if (ZS_IS_ASLEEP(uap))
-				return NULL;
-			if (!ZS_IS_OPEN(uap))
-				goto retry;
-		}
-
 		r1 = read_zsreg(uap, R1);
 		ch = read_zsdata(uap);
 
@@ -295,8 +280,7 @@
 		if (drop)
 			goto next_char;
 
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		uap->port.icount.rx++;
 
 		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
@@ -316,26 +300,19 @@
 				uap->port.icount.overrun++;
 			r1 &= uap->port.read_status_mask;
 			if (r1 & BRK_ABRT)
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			else if (r1 & PAR_ERR)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (r1 & CRC_ERR)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 
 		if (uap->port.ignore_status_mask == 0xff ||
 		    (r1 & uap->port.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
+		    	tty_insert_flip_char(tty, ch, flag);
 		}
-		if ((r1 & Rx_OVR) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
+		if (r1 & Rx_OVR)
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	next_char:
 		/* We can get stuck in an infinite loop getting char 0 when the
 		 * line is in a wrong HW state, we break that here.
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index cc998b9..10535f0 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -107,14 +107,6 @@
 	int max_count = 256;
 
 	do {
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts
-			 */
-		}
 		ch = serial_in(up, UART_RX);
 		flag = TTY_NORMAL;
 		up->port.icount.rx++;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index fe83ce6..eb4883e 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -323,16 +323,6 @@
 		if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
 			break;
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts
-			 */
-		}
-
 		uerstat = rd_regl(port, S3C2410_UERSTAT);
 		ch = rd_regb(port, S3C2410_URXH);
 
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 25a0864..1bd9316 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -201,8 +201,6 @@
 	while (status & UTSR1_TO_SM(UTSR1_RNE)) {
 		ch = UART_GET_CHAR(sport);
 
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			goto ignore_char;
 		sport->port.icount.rx++;
 
 		flg = TTY_NORMAL;
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index d01dbe5..d4a1f0e 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -148,15 +148,6 @@
 	unsigned int data, flag;/* Received data and status */
 
 	while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-			/*
-			 * If this failed then we will throw away the
-			 * bytes but must do so to clear interrupts
-			 */
-		}
-
 		data = UR (port, UART_R_DATA);
 		flag = TTY_NORMAL;
 		++port->icount.rx;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 995d9dd..fdd1f19 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -303,17 +303,6 @@
 	char flag;
 
 	do {
-		/* The following is not allowed by the tty layer and
-		   unsafe. It should be fixed ASAP */
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			if (tty->low_latency) {
-				spin_unlock(&up->port.lock);
-				tty_flip_buffer_push(tty);
-				spin_lock(&up->port.lock);
-			}
-			/* If this failed then we will throw away the
-			   bytes but must do so to clear interrupts */
-		}
 		ch = sio_in(up, TXX9_SIRFIFO);
 		flag = TTY_NORMAL;
 		up->port.icount.rx++;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 430754e..a9e0707 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -482,6 +482,7 @@
 	struct tty_struct *tty = port->info->tty;
 	int i, count, copied = 0;
 	unsigned short status;
+	unsigned char flag;
 
 	status = sci_in(port, SCxSR);
 	if (!(status & SCxSR_RDxF(port)))
@@ -499,8 +500,7 @@
 #endif
 
 		/* Don't copy more bytes than there is room for in the buffer */
-		if (tty->flip.count + count > TTY_FLIPBUF_SIZE)
-			count = TTY_FLIPBUF_SIZE - tty->flip.count;
+		count = tty_buffer_request_room(tty, count);
 
 		/* If for any reason we can't copy more data, we're done! */
 		if (count == 0)
@@ -512,8 +512,7 @@
 			    || uart_handle_sysrq_char(port, c, regs)) {
 				count = 0;
 			} else {
-			    tty->flip.char_buf_ptr[0] = c;
-			    tty->flip.flag_buf_ptr[0] = TTY_NORMAL;
+			    tty_insert_flip_char(tty, c, TTY_NORMAL);
 			}
 		} else {
 			for (i=0; i<count; i++) {
@@ -542,26 +541,21 @@
 				}
 
 				/* Store data and status */
-				tty->flip.char_buf_ptr[i] = c;
 				if (status&SCxSR_FER(port)) {
-					tty->flip.flag_buf_ptr[i] = TTY_FRAME;
+					flag = TTY_FRAME;
 					pr_debug("sci: frame error\n");
 				} else if (status&SCxSR_PER(port)) {
-					tty->flip.flag_buf_ptr[i] = TTY_PARITY;
+					flag = TTY_PARITY;
 					pr_debug("sci: parity error\n");
-				} else {
-					tty->flip.flag_buf_ptr[i] = TTY_NORMAL;
-				}
+				} else
+					flag = TTY_NORMAL;
+				tty_insert_flip_char(tty, c, flag);
 			}
 		}
 
 		sci_in(port, SCxSR); /* dummy read */
 		sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
 
-		/* Update the kernel buffer end */
-		tty->flip.count += count;
-		tty->flip.char_buf_ptr += count;
-		tty->flip.flag_buf_ptr += count;
 		copied += count;
 		port->icount.rx += count;
 	}
@@ -608,48 +602,45 @@
 	unsigned short status = sci_in(port, SCxSR);
 	struct tty_struct *tty = port->info->tty;
 
-	if (status&SCxSR_ORER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+	if (status&SCxSR_ORER(port)) {
 		/* overrun error */
-		copied++;
-		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+		if(tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+			copied++;
 		pr_debug("sci: overrun error\n");
 	}
 
-	if (status&SCxSR_FER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+	if (status&SCxSR_FER(port)) {
 		if (sci_rxd_in(port) == 0) {
 			/* Notify of BREAK */
 			struct sci_port * sci_port = (struct sci_port *)port;
-                       if(!sci_port->break_flag) {
-	                        sci_port->break_flag = 1;
-                               sci_schedule_break_timer((struct sci_port *)port);
+			if(!sci_port->break_flag) {
+	                	sci_port->break_flag = 1;
+	                	sci_schedule_break_timer((struct sci_port *)port);
 				/* Do sysrq handling. */
-				if(uart_handle_break(port)) {
+				if(uart_handle_break(port))
 					return 0;
-				}
 			        pr_debug("sci: BREAK detected\n");
-			        copied++;
-			        *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+			        if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+				        copied++;
                        }
 		}
 		else {
 			/* frame error */
-			copied++;
-			*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+			if(tty_insert_flip_char(tty, 0, TTY_FRAME))
+				copied++;
 			pr_debug("sci: frame error\n");
 		}
 	}
 
-	if (status&SCxSR_PER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+	if (status&SCxSR_PER(port)) {
+		if(tty_insert_flip_char(tty, 0, TTY_PARITY))
+			copied++;
 		/* parity error */
-		copied++;
-		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
 		pr_debug("sci: parity error\n");
 	}
 
-	if (copied) {
-		tty->flip.count += copied;
+	if (copied)
 		tty_flip_buffer_push(tty);
-	}
 
 	return copied;
 }
@@ -661,15 +652,14 @@
 	struct tty_struct *tty = port->info->tty;
 	struct sci_port *s = &sci_ports[port->line];
 
-	if (!s->break_flag && status & SCxSR_BRK(port) &&
-	    tty->flip.count < TTY_FLIPBUF_SIZE) {
+	if (!s->break_flag && status & SCxSR_BRK(port))
 #if defined(CONFIG_CPU_SH3)
 		/* Debounce break */
 		s->break_flag = 1;
 #endif
 		/* Notify of BREAK */
-		copied++;
-		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+		if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+			copied++;
 		pr_debug("sci: BREAK detected\n");
 	}
 
@@ -677,19 +667,15 @@
 	/* XXX: Handle SCIF overrun error */
 	if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
 		sci_out(port, SCLSR, 0);
-		if(tty->flip.count<TTY_FLIPBUF_SIZE) {
+		if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
 			copied++;
-			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
 			pr_debug("sci: overrun error\n");
 		}
 	}
 #endif
 
-	if (copied) {
-		tty->flip.count += copied;
+	if (copied)
 		tty_flip_buffer_push(tty);
-	}
-
 	return copied;
 }
 
@@ -732,12 +718,9 @@
 			struct tty_struct *tty = port->info->tty;
 
 			sci_out(port, SCLSR, 0);
-			if(tty->flip.count<TTY_FLIPBUF_SIZE) {
-				*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-				tty->flip.count++;
-				tty_flip_buffer_push(tty);
-				pr_debug("scif: overrun error\n");
-			}
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+			tty_flip_buffer_push(tty);
+			pr_debug("scif: overrun error\n");
 		}
 #endif
 		sci_rx_interrupt(irq, ptr, regs);
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 313f9df..5468e5a 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -519,11 +519,7 @@
 
 		/* record the character to pass up to the tty layer */
 		if (tty) {
-			*tty->flip.char_buf_ptr = ch;
-			*tty->flip.flag_buf_ptr = TTY_NORMAL;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-			if (tty->flip.count == TTY_FLIPBUF_SIZE)
+			if(tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
 				break;
 		}
 		port->sc_port.icount.rx++;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index ba9381f..7e773ff 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -159,21 +159,14 @@
 		saw_console_brk = 1;
 
 	for (i = 0; i < count; i++) {
-		unsigned char ch = buf[i];
+		unsigned char ch = buf[i], flag;
 
 		if (tty == NULL) {
 			uart_handle_sysrq_char(&up->port, ch, regs);
 			continue;
 		}
 
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return tty; // if TTY_DONT_FLIP is set
-		}
-
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 
 		if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR |
@@ -209,34 +202,21 @@
 			stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff);
 
 			if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			} else if (stat->sreg.isr0 & SAB82532_ISR0_PERR)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (stat->sreg.isr0 & SAB82532_ISR0_FERR)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
 			continue;
 
 		if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
-		    (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0){
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-		if ((stat->sreg.isr0 & SAB82532_ISR0_RFO) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
-			/*
-			 * Overrun is special, since it's reported
-			 * immediately, and doesn't affect the current
-			 * character.
-			 */
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
+		    (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0)
+			tty_insert_flip_char(tty, ch, flag);
+		if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	}
 
 	if (saw_console_brk)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f073853..9a3665b 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -323,19 +323,13 @@
 receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
 {
 	struct tty_struct *tty = up->port.info->tty;
-	unsigned char ch;
+	unsigned char ch, flag;
 	int max_count = 256;
 	int saw_console_brk = 0;
 
 	do {
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return tty; // if TTY_DONT_FLIP is set
-		}
 		ch = serial_inp(up, UART_RX);
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 
 		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -377,31 +371,23 @@
 			}
 
 			if (*status & UART_LSR_BI) {
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			} else if (*status & UART_LSR_PE)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (*status & UART_LSR_FE)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
 			goto ignore_char;
-		if ((*status & up->port.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-		if ((*status & UART_LSR_OE) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+		if ((*status & up->port.ignore_status_mask) == 0)
+			tty_insert_flip_char(tty, ch, flag);
+		if (*status & UART_LSR_OE)
 			/*
 			 * Overrun is special, since it's reported
 			 * immediately, and doesn't affect the current
 			 * character.
 			 */
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
+			 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	ignore_char:
 		*status = serial_inp(up, UART_LSR);
 	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 7653d6c..3c72484 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -319,7 +319,7 @@
 		       struct pt_regs *regs)
 {
 	struct tty_struct *tty;
-	unsigned char ch, r1;
+	unsigned char ch, r1, flag;
 
 	tty = NULL;
 	if (up->port.info != NULL &&		/* Unopened serial console */
@@ -362,19 +362,8 @@
 			continue;
 		}
 
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			/*
-			 * The 8250 bails out of the loop here,
-			 * but we need to read everything, or die.
-			 */
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				continue;
-		}
-
 		/* A real serial line, record the character and status.  */
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		flag = TTY_NORMAL;
 		up->port.icount.rx++;
 		if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
 			if (r1 & BRK_ABRT) {
@@ -391,28 +380,21 @@
 				up->port.icount.overrun++;
 			r1 &= up->port.read_status_mask;
 			if (r1 & BRK_ABRT)
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				flag = TTY_BREAK;
 			else if (r1 & PAR_ERR)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (r1 & CRC_ERR)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
+				flag = TTY_FRAME;
 		}
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
 			continue;
 
 		if (up->port.ignore_status_mask == 0xff ||
 		    (r1 & up->port.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
+		    	tty_insert_flip_char(tty, ch, flag);
 		}
-		if ((r1 & Rx_OVR) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
+		if (r1 & Rx_OVR)
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	}
 
 	return tty;
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 865d4de..0a28dee 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -371,11 +371,6 @@
 	lsr = *status;
 
 	do {
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			if (tty->low_latency)
-				tty_flip_buffer_push(tty);
-		}
-
 		ch = siu_read(port, UART_RX);
 		port->icount.rx++;
 		flag = TTY_NORMAL;
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index b283361..c1b47d7 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -532,9 +532,9 @@
 	int ret = int_urb->status;
 
 	/* The magic interrupt for "up state" */
-	const static unsigned char up_int[6]   = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
+	static const unsigned char up_int[6]   = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
 	/* The magic interrupt for "down state" */
-	const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	static const unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 	atm_dbg(usbatm, "%s entered\n", __func__);
 
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 248279e..b9fd39f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -335,14 +335,9 @@
 
 	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
 
-	for (i = 0; i < buf->size && !acm->throttle; i++) {
-		/* if we insert more than TTY_FLIPBUF_SIZE characters,
-		   we drop them. */
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			tty_flip_buffer_push(tty);
- 		}
-		tty_insert_flip_char(tty, buf->base[i], 0);
- 	}
+	tty_buffer_request_room(tty, buf->size);
+	if (!acm->throttle)
+		tty_insert_flip_string(tty, buf->base, buf->size);
 	tty_flip_buffer_push(tty);
 
 	spin_lock(&acm->throttle_lock);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 65e084a..2e6926b 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1271,6 +1271,7 @@
 	unsigned int len;
 	struct gs_port *port;
 	int ret;
+	struct tty_struct *tty;
 
 	/* TEMPORARY -- only port 0 is supported right now */
 	port = dev->dev_port[0];
@@ -1290,7 +1291,10 @@
 		goto exit;
 	}
 
-	if (port->port_tty == NULL) {
+
+	tty = port->port_tty;
+
+	if (tty == NULL) {
 		printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
 			port->port_num);
 		ret = -EIO;
@@ -1304,20 +1308,13 @@
 		goto exit;
 	}
 
-	len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count);
-	if (len < size)
-		size = len;
-
-	if (size > 0) {
-		memcpy(port->port_tty->flip.char_buf_ptr, packet, size);
-		port->port_tty->flip.char_buf_ptr += size;
-		port->port_tty->flip.count += size;
+	len = tty_buffer_request_room(tty, size);
+	if (len > 0) {
+		tty_insert_flip_string(tty, packet, len);
 		tty_flip_buffer_push(port->port_tty);
 		wake_up_interruptible(&port->port_tty->read_wait);
 	}
-
 	ret = 0;
-
 exit:
 	spin_unlock(&port->port_lock);
 	return ret;
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 458f2ac..28538db 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -674,7 +674,7 @@
 
 
 /* These are taken from the msmUSB.inf file on the Windows driver CD */
-const static struct vendor_product mts_supported_products[] =
+static const struct vendor_product mts_supported_products[] =
 {
 	{ "Phantom 336CX",	mts_sup_unknown},
 	{ "Phantom 336CX",	mts_sup_unknown},
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 14f55fd..be5dc80 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -84,7 +84,7 @@
 
 config USB_SERIAL_WHITEHEAT
 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
-	depends on USB_SERIAL && BROKEN_ON_SMP
+	depends on USB_SERIAL
 	help
 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
 	  USB to serial converter device.
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6d18d4e..2357b1d 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -364,7 +364,6 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	short todo;
-	int i;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -381,14 +380,8 @@
 		return;
 	}
 	if (urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 	  	tty_flip_buffer_push(tty);
 	}
 
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 4e9637e..68067fe 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1263,12 +1263,10 @@
 
 	/* process read if there is data other than line status */
 	if (tty && (bytes > i)) {
+		bytes = tty_buffer_request_room(tty, bytes);
 		for (; i < bytes ; ++i) {
 			dbg("pushing byte number %d - %d - %c", i, data[i],
 					data[i]);
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
 			tty_insert_flip_char(tty, data[i], tty_flag);
 		}
 		tty_flip_buffer_push(port->tty);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 8fc414b..b3f776a 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -946,13 +946,10 @@
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 
 	/* send any buffered chars from throttle time on to tty subsystem */
-	len = min(priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count );
+
+	len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
 	if( len > 0 ) {
-		memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len );
-		memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len );
-		tty->flip.char_buf_ptr += len;
-		tty->flip.flag_buf_ptr += len;
-		tty->flip.count += len;
+		tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
 		tty_flip_buffer_push( tty );
 	}
 
@@ -1827,6 +1824,7 @@
 	int status = ((unsigned char *)urb->transfer_buffer)[2];
 	unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
 	int flag,throttled;
+	int i;
 
 	/* do not process callbacks on closed ports */
 	/* but do continue the read chain */
@@ -1885,20 +1883,18 @@
 			}
 
 		} else {
-
-			len = min( len, TTY_FLIPBUF_SIZE - tty->flip.count );
-
+			len = tty_buffer_request_room(tty, len);
 			if( len > 0 ) {
-				memcpy( tty->flip.char_buf_ptr, data, len );
-				memset( tty->flip.flag_buf_ptr, flag, len );
-				tty->flip.char_buf_ptr += len;
-				tty->flip.flag_buf_ptr += len;
-				tty->flip.count += len;
+				/* Hot path */
+				if(flag == TTY_NORMAL)
+					tty_insert_flip_string(tty, data, len);
+				else {
+					for(i = 0; i < len; i++)
+						tty_insert_flip_char(tty, data[i], flag);
+				}
 				tty_flip_buffer_push( tty );
 			}
-
 		}
-
 	}
 
 	spin_unlock( &priv->dp_port_lock );
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 79a766e..63f7c78 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -344,7 +344,6 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
-	int i;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -359,19 +358,8 @@
 	tty = port->tty;
 
 	if (urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* gb - 2000/11/13
-			 * If we insert too many characters we'll overflow the buffer.
-			 * This means we'll lose bytes - Decidedly bad.
-			 */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-				}
-			tty_insert_flip_char(tty, data[i], 0);
-		}
-		/* gb - 2000/11/13
-		 * Goes straight through instead of scheduling - if tty->low_latency is set.
-		 */
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 		bytes_in += urb->actual_length;
 	}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index eb863b3..10bc1bf 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1610,24 +1610,11 @@
 			length = 0;
 		}
 
-		/* have to make sure we don't overflow the buffer
-		   with tty_insert_flip_char's */
-		if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
-			tty_flip_buffer_push(tty);
-			need_flip = 0;
-
-			if (tty->flip.count != 0) {
-				/* flip didn't work, this happens when ftdi_process_read() is
-				 * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
-				dbg("%s - flip buffer push failed", __FUNCTION__);
-				break;
-			}
-		}
 		if (priv->rx_flags & THROTTLED) {
 			dbg("%s - throttled", __FUNCTION__);
 			break;
 		}
-		if (tty->ldisc.receive_room(tty)-tty->flip.count < length) {
+		if (tty_buffer_request_room(tty, length) < length) {
 			/* break out & wait for throttling/unthrottling to happen */
 			dbg("%s - receive room low", __FUNCTION__);
 			break;
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 452efce..d6f55e9 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -275,23 +275,14 @@
                         char *data, unsigned int actual_length)
 {
 	struct tty_struct *tty = port->tty;
-	int i;
 
 	if (tty && actual_length) {
 
 		usb_serial_debug_data(debug, &port->dev, 
 					__FUNCTION__, actual_length, data);
 
-		for (i = 0; i < actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters,
-			   we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless
-			   tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, actual_length);
+		tty_insert_flip_string(tty, data, actual_length);
 		tty_flip_buffer_push(tty);
 	}
 }
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4ddac62..476cda1 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -254,7 +254,6 @@
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
-	int i;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -268,14 +267,8 @@
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 	  	tty_flip_buffer_push(tty);
 	}
 
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index faedbeb..3f29e6b 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1965,20 +1965,14 @@
 	int cnt;
 
 	do {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			tty_flip_buffer_push(tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				dev_err(dev, "%s - dropping data, %d bytes lost\n",
-					__FUNCTION__, length);
-				return;
-			}
+		cnt = tty_buffer_request_room(tty, length);
+		if (cnt < length) {
+			dev_err(dev, "%s - dropping data, %d bytes lost\n",
+					__FUNCTION__, length - cnt);
+			if(cnt == 0)
+				break;
 		}
-		cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
-		memcpy(tty->flip.char_buf_ptr, data, cnt);
-		memset(tty->flip.flag_buf_ptr, 0, cnt);
-		tty->flip.char_buf_ptr += cnt;
-		tty->flip.flag_buf_ptr += cnt;
-		tty->flip.count += cnt;
+		tty_insert_flip_string(tty, data, cnt);
 		data += cnt;
 		length -= cnt;
 	} while (length > 0);
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 2edf9cab..afc0f34 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1865,20 +1865,14 @@
 	int cnt;
 
 	do {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			tty_flip_buffer_push(tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				dev_err(dev, "%s - dropping data, %d bytes lost\n",
-					__FUNCTION__, length);
-				return;
-			}
+		cnt = tty_buffer_request_room(tty, length);
+		if (cnt < length) {
+			dev_err(dev, "%s - dropping data, %d bytes lost\n",
+				__FUNCTION__, length - cnt);
+			if(cnt == 0)
+				break;
 		}
-		cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
-		memcpy(tty->flip.char_buf_ptr, data, cnt);
-		memset(tty->flip.flag_buf_ptr, 0, cnt);
-		tty->flip.char_buf_ptr += cnt;
-		tty->flip.flag_buf_ptr += cnt;
-		tty->flip.count += cnt;
+		tty_insert_flip_string(tty, data, cnt);
 		data += cnt;
 		length -= cnt;
 	} while (length > 0);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 06d07ce..9a5c979 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -711,7 +711,7 @@
 	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
 	struct tty_struct	*tty;
 	unsigned char		*data = urb->transfer_buffer;
-	int			i, result;
+	int			result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -724,14 +724,8 @@
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 		bytes_in += urb->actual_length;
 	}
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 2dd191f..e760a70 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -166,7 +166,6 @@
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
 	struct tty_struct *tty;
-	int i;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -180,14 +179,8 @@
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 4e2f7df..78335a5 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -648,7 +648,6 @@
 		usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
 				      urb->actual_length, data);
 	} else {
-		int i;
 		int bytes_sent = ((__u8 *) data)[0] +
 				 ((unsigned int) ((__u8 *) data)[1] << 8);
 		tty = port->tty;
@@ -669,16 +668,8 @@
 			bytes_sent = urb->actual_length - 2;
 		}
 
-		for (i = 2; i < 2+bytes_sent; i++) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters,
-			 * we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless 
-			 * tty->low_latency is set */
-			tty_insert_flip_char(tty, ((__u8*) data)[i], 0);
-		}
+		tty_buffer_request_room(tty, bytes_sent);
+		tty_insert_flip_string(tty, data + 2, bytes_sent);
 		tty_flip_buffer_push(tty);
 
 		/* again lockless, but debug info only */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index d9c21e2..b8b2131 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -365,7 +365,6 @@
 
 static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
 {
-	int i;
 	int result;
 	struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
 	struct tty_struct *tty;
@@ -397,14 +396,8 @@
 		*/
 		// END DEBUG
 
-		for (i = 0; i < purb->actual_length; ++i) {
-			// if we insert more than TTY_FLIPBUF_SIZE characters, we drop them.
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			// this doesn't actually push the data through unless tty->low_latency is set
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, purb->actual_length);
+		tty_insert_flip_string(tty, data, purb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 3fd2405..52bdf6f 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -321,7 +321,7 @@
 
 static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
 {
-	int i, err;
+	int err;
 	int endpoint;
 	struct usb_serial_port *port;
 	struct tty_struct *tty;
@@ -338,11 +338,8 @@
 	} else {
 		tty = port->tty;
 		if (urb->actual_length) {
-			for (i = 0; i < urb->actual_length ; ++i) {
-				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-					tty_flip_buffer_push(tty);
-				tty_insert_flip_char(tty, data[i], 0);
-			}
+			tty_buffer_request_room(tty, urb->actual_length);
+			tty_insert_flip_string(tty, data, urb->actual_length);
 			tty_flip_buffer_push(tty);
 		} else {
 			dbg("%s: empty read urb received", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index f037210..9ffff19 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -924,16 +924,12 @@
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
+		tty_buffer_request_room(tty, urb->actual_length + 1);
 		/* overrun is special, not associated with a char */
 		if (status & UART_OVERRUN_ERROR)
 			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-
-		for (i = 0; i < urb->actual_length; ++i) {
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
+		for (i = 0; i < urb->actual_length; ++i)
 			tty_insert_flip_char (tty, data[i], tty_flag);
-		}
 		tty_flip_buffer_push (tty);
 	}
 
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index abb830c..c18db32 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1280,24 +1280,18 @@
 	int cnt;
 
 	do {
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-			tty_flip_buffer_push(tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length);
-				return;
-			}
+		cnt = tty_buffer_request_room(tty, length);
+		if (cnt < length) {
+			dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
+			if(cnt == 0)
+				break;
 		}
-		cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
-		memcpy(tty->flip.char_buf_ptr, data, cnt);
-		memset(tty->flip.flag_buf_ptr, 0, cnt);
-		tty->flip.char_buf_ptr += cnt;
-		tty->flip.flag_buf_ptr += cnt;
-		tty->flip.count += cnt;
+		tty_insert_flip_string(tty, data, cnt);
+		tty_flip_buffer_push(tty);
 		data += cnt;
 		length -= cnt;
 	} while (length > 0);
 
-	tty_flip_buffer_push(tty);
 }
 
 
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 49b1fbe..bce3d55 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -488,7 +488,6 @@
 	unsigned char *data = urb->transfer_buffer;
 	struct tty_struct *tty;
 	unsigned long flags;
-	int i;
 	int throttled;
 	int result;
 
@@ -503,14 +502,8 @@
 
 	tty = port->tty;
 	if (tty && urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 	spin_lock_irqsave(&priv->lock, flags);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index a7c3c47..557411c 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -1434,7 +1434,9 @@
 		urb = wrap->urb;
 
 		if (tty && urb->actual_length) {
-			if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {
+			int len = tty_buffer_request_room(tty, urb->actual_length);
+			/* This stuff can go away now I suspect */
+			if (unlikely(len < urb->actual_length)) {
 				spin_lock_irqsave(&info->lock, flags);
 				list_add(tmp, &info->rx_urb_q);
 				spin_unlock_irqrestore(&info->lock, flags);
@@ -1442,11 +1444,8 @@
 				schedule_work(&info->rx_work);
 				return;
 			}
-
-			memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);
-			tty->flip.char_buf_ptr += urb->actual_length;
-			tty->flip.count += urb->actual_length;
-			sent += urb->actual_length;
+			tty_insert_flip_string(tty, urb->transfer_buffer, len);
+			sent += len;
 		}
 
 		urb->dev = port->serial->dev;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3f04427..3e153d3 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -993,12 +993,6 @@
 	  Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
 	  Rage XC, or Rage XL chipset.
 
-config FB_ATY_XL_INIT
-	bool "Rage XL No-BIOS Init support"
-	depends on FB_ATY_CT
-	help
-	  Say Y here to support booting a Rage XL without BIOS support.
-
 config FB_ATY_GX
 	bool "Mach64 GX support" if PCI
 	depends on FB_ATY
@@ -1376,7 +1370,7 @@
 
 	  This driver is also available as a module ( = code which can be
 	  inserted and removed from the running kernel whenever you want). The
-	  module will be called vfb. If you want to compile it as a module,
+	  module will be called pxafb. If you want to compile it as a module,
 	  say M here and read <file:Documentation/modules.txt>.
 
 	  If unsure, say N.
@@ -1409,7 +1403,7 @@
 
 	  This driver is also available as a module ( = code which can be
 	  inserted and removed from the running kernel whenever you want). The
-	  module will be called vfb. If you want to compile it as a module,
+	  module will be called w100fb. If you want to compile it as a module,
 	  say M here and read <file:Documentation/modules.txt>.
 
 	  If unsure, say N.
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 2784f0a..89060b2 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -366,7 +366,8 @@
 	}
 }
 
-void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void arcfb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect)
 {
 	struct arcfb_par *par = info->par;
 
@@ -376,7 +377,8 @@
 	arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
 }
 
-void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void arcfb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *area)
 {
 	struct arcfb_par *par = info->par;
 
@@ -386,7 +388,7 @@
 	arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
 }
 
-void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct arcfb_par *par = info->par;
 
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index c64de59..69f7554 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -549,7 +549,7 @@
 	if (!request_mem_region(addr, size, "asiliantfb"))
 		return -EBUSY;
 
-	p = framebuffer_alloc(sizeof(u32) * 256, &dp->dev);
+	p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev);
 	if (!p)	{
 		release_mem_region(addr, size);
 		return -ENOMEM;
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
index 9dec962..1852139 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/aty/Makefile
@@ -5,7 +5,6 @@
 atyfb-y				:= atyfb_base.o mach64_accel.o mach64_cursor.o
 atyfb-$(CONFIG_FB_ATY_GX)	+= mach64_gx.o
 atyfb-$(CONFIG_FB_ATY_CT)	+= mach64_ct.o
-atyfb-$(CONFIG_FB_ATY_XL_INIT)  += xlinit.o
 
 atyfb-objs			:= $(atyfb-y)
 
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index 09de173..e9b7a64 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -50,6 +50,7 @@
 	int sclk, mclk, mclk_pm, xclk;
 	int ref_div;
 	int ref_clk;
+	int ecp_max;
 };
 
 typedef struct {
@@ -354,6 +355,5 @@
 
 extern void aty_reset_engine(const struct atyfb_par *par);
 extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
-extern int  atyfb_xl_init(struct fb_info *info);
 extern void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par);
 extern u8   aty_ld_pll_ct(int offset, const struct atyfb_par *par);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 3fefdb0c..e370125 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -109,9 +109,18 @@
 #define GUI_RESERVE	(1 * PAGE_SIZE)
 
 /* FIXME: remove the FAIL definition */
-#define FAIL(msg) do { printk(KERN_CRIT "atyfb: " msg "\n"); return -EINVAL; } while (0)
-#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0)
-
+#define FAIL(msg) do { \
+	if (!(var->activate & FB_ACTIVATE_TEST)) \
+		printk(KERN_CRIT "atyfb: " msg "\n"); \
+	return -EINVAL; \
+} while (0)
+#define FAIL_MAX(msg, x, _max_) do { \
+	if (x > _max_) { \
+		if (!(var->activate & FB_ACTIVATE_TEST)) \
+			printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
+		return -EINVAL; \
+	} \
+} while (0)
 #ifdef DEBUG
 #define DPRINTK(fmt, args...)	printk(KERN_DEBUG "atyfb: " fmt, ## args)
 #else
@@ -340,6 +349,7 @@
 #define ATI_CHIP_264VT3    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
 #define ATI_CHIP_264VT4    (M64F_VT | M64F_INTEGRATED               | M64F_GTB_DSP)
 
+/* FIXME what is this chip? */
 #define ATI_CHIP_264LT     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP)
 
 /* make sets shorter */
@@ -359,58 +369,60 @@
 static struct {
 	u16 pci_id;
 	const char *name;
-	int pll, mclk, xclk;
+	int pll, mclk, xclk, ecp_max;
 	u32 features;
 } aty_chips[] __devinitdata = {
 #ifdef CONFIG_FB_ATY_GX
 	/* Mach64 GX */
-	{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
-	{ PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, ATI_CHIP_88800CX },
+	{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
+	{ PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
 #endif /* CONFIG_FB_ATY_GX */
 
 #ifdef CONFIG_FB_ATY_CT
-	{ PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, ATI_CHIP_264CT },
-	{ PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, ATI_CHIP_264ET },
-	{ PCI_CHIP_MACH64VT, "ATI264VT? (Mach64 VT)", 170, 67, 67, ATI_CHIP_264VT },
-	{ PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, ATI_CHIP_264GT },
-	/* FIXME { ...ATI_264GU, maybe ATI_CHIP_264GTDVD }, */
-	{ PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GTB)", 200, 67, 67, ATI_CHIP_264GTB  },
-	{ PCI_CHIP_MACH64VU, "ATI264VTB (Mach64 VU)", 200, 67, 67, ATI_CHIP_264VT3 },
+	{ PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
+	{ PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
 
-	{ PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT },
-	 /* FIXME chipset maybe ATI_CHIP_264LTPRO ? */
-	{ PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
+	/* FIXME what is this chip? */
+	{ PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
 
-	{ PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 },
+	{ PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
+	{ PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
 
-	{ PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
-	{ PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
-	{ PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
-	{ PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
+	{ PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
 
-	{ PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, ATI_CHIP_264GTPRO },
-	{ PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, ATI_CHIP_264GTPRO },
-	{ PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
-	{ PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO },
-	{ PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
 
-	{ PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, ATI_CHIP_264LTPRO },
-	{ PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, ATI_CHIP_264LTPRO },
-	{ PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
-	{ PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
-	{ PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
 
-	{ PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 235, 83, 63, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
-	{ PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
 
-	{ PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
-	{ PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
-	{ PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
-	{ PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
+	{ PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+
+	{ PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+	{ PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+
+	{ PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
+	{ PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
+
+	{ PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
 #endif /* CONFIG_FB_ATY_CT */
 };
 
@@ -431,6 +443,7 @@
 	par->pll_limits.pll_max = aty_chips[i].pll;
 	par->pll_limits.mclk = aty_chips[i].mclk;
 	par->pll_limits.xclk = aty_chips[i].xclk;
+	par->pll_limits.ecp_max = aty_chips[i].ecp_max;
 	par->features = aty_chips[i].features;
 
 	chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
@@ -450,39 +463,63 @@
 #endif
 #ifdef CONFIG_FB_ATY_CT
 	case PCI_CHIP_MACH64VT:
-		rev &= 0xc7;
-		if(rev == 0x00) {
-			name = "ATI264VTA3 (Mach64 VT)";
-			par->pll_limits.pll_max = 170;
-			par->pll_limits.mclk = 67;
-			par->pll_limits.xclk = 67;
-			par->features = ATI_CHIP_264VT;
-		} else if(rev == 0x40) {
-			name = "ATI264VTA4 (Mach64 VT)";
+		switch (rev & 0x07) {
+		case 0x00:
+			switch (rev & 0xc0) {
+			case 0x00:
+				name = "ATI264VT (A3) (Mach64 VT)";
+				par->pll_limits.pll_max = 170;
+				par->pll_limits.mclk = 67;
+				par->pll_limits.xclk = 67;
+				par->pll_limits.ecp_max = 80;
+				par->features = ATI_CHIP_264VT;
+				break;
+			case 0x40:
+				name = "ATI264VT2 (A4) (Mach64 VT)";
+				par->pll_limits.pll_max = 200;
+				par->pll_limits.mclk = 67;
+				par->pll_limits.xclk = 67;
+				par->pll_limits.ecp_max = 80;
+				par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
+				break;
+			}
+			break;
+		case 0x01:
+			name = "ATI264VT3 (B1) (Mach64 VT)";
 			par->pll_limits.pll_max = 200;
 			par->pll_limits.mclk = 67;
 			par->pll_limits.xclk = 67;
-			par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
-		} else {
-			name = "ATI264VTB (Mach64 VT)";
-			par->pll_limits.pll_max = 200;
-			par->pll_limits.mclk = 67;
-			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 80;
 			par->features = ATI_CHIP_264VTB;
+			break;
+		case 0x02:
+			name = "ATI264VT3 (B2) (Mach64 VT)";
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 80;
+			par->features = ATI_CHIP_264VT3;
+			break;
 		}
 		break;
 	case PCI_CHIP_MACH64GT:
-		rev &= 0x07;
-		if(rev == 0x01) {
+		switch (rev & 0x07) {
+		case 0x01:
+			name = "3D RAGE II (Mach64 GT)";
 			par->pll_limits.pll_max = 170;
 			par->pll_limits.mclk = 67;
 			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 80;
 			par->features = ATI_CHIP_264GTB;
-		} else if(rev == 0x02) {
+			break;
+		case 0x02:
+			name = "3D RAGE II+ (Mach64 GT)";
 			par->pll_limits.pll_max = 200;
 			par->pll_limits.mclk = 67;
 			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 100;
 			par->features = ATI_CHIP_264GTB;
+			break;
 		}
 		break;
 #endif
@@ -692,7 +729,7 @@
 		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
 			(SHADOW_EN | SHADOW_RW_EN), par);
 
-		DPRINTK("set secondary CRT to %ix%i %c%c\n",
+		DPRINTK("set shadow CRT to %ix%i %c%c\n",
 		    ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
 		    (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
 
@@ -840,11 +877,14 @@
 			   know if one is connected. So it's better to fail then.
 			 */
 			if (crtc->lcd_gen_cntl & CRT_ON) {
-				PRINTKI("Disable lcd panel, because video mode does not fit.\n");
+				if (!(var->activate & FB_ACTIVATE_TEST))
+					PRINTKI("Disable LCD panel, because video mode does not fit.\n");
 				crtc->lcd_gen_cntl &= ~LCD_ON;
 				/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
 			} else {
-				FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode.");
+				if (!(var->activate & FB_ACTIVATE_TEST))
+					PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
+				return -EINVAL;
 			}
 		}
 	}
@@ -858,9 +898,9 @@
 		vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
 
 		/* This is horror! When we simulate, say 640x480 on an 800x600
-		   lcd monitor, the CRTC should be programmed 800x600 values for
+		   LCD monitor, the CRTC should be programmed 800x600 values for
 		   the non visible part, but 640x480 for the visible part.
-		   This code has been tested on a laptop with it's 1400x1050 lcd
+		   This code has been tested on a laptop with it's 1400x1050 LCD
 		   monitor and a conventional monitor both switched on.
 		   Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
 		    works with little glitches also with DOUBLESCAN modes
@@ -955,16 +995,6 @@
 		vdisplay = yres;
 		if(vmode & FB_VMODE_DOUBLE)
 			vdisplay <<= 1;
-		if(vmode & FB_VMODE_INTERLACED) {
-			vdisplay >>= 1;
-
-			/* The prefered mode for the lcd is not interlaced, so disable it if
-			   it was enabled. For doublescan there is no problem, because we can
-			   compensate for it in the hardware stretching (we stretch half as much)
-			 */
-			vmode &= ~FB_VMODE_INTERLACED;
-			/*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/
-		}
 		crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
 		crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
 			/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
@@ -980,7 +1010,7 @@
 		crtc->horz_stretching &=
 			~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
 			HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
-		if (xres < par->lcd_width) {
+		if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
 			do {
 				/*
 				* The horizontal blender misbehaves when HDisplay is less than a
@@ -1042,7 +1072,7 @@
 			} while (0);
 		}
 
-		if (vdisplay < par->lcd_height) {
+		if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
 			crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
 				(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
 
@@ -1065,9 +1095,8 @@
 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
 
 	if (M64_HAS(MAGIC_FIFO)) {
-		/* Not VTB/GTB */
-		/* FIXME: magic FIFO values */
-		crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH);
+		/* FIXME: display FIFO low watermark values */
+		crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
 	}
 	crtc->dp_pix_width = dp_pix_width;
 	crtc->dp_chain_mask = dp_chain_mask;
@@ -1184,7 +1213,8 @@
 		var->transp.length = 8;
 		break;
 	default:
-		FAIL("Invalid pixel width");
+		PRINTKE("Invalid pixel width\n");
+		return -EINVAL;
 	}
 
 	/* output */
@@ -1241,7 +1271,8 @@
 	pixclock = atyfb_get_pixclock(var, par);
 
 	if (pixclock == 0) {
-		FAIL("Invalid pixclock");
+		PRINTKE("Invalid pixclock\n");
+		return -EINVAL;
 	} else {
 		if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
 			return err;
@@ -1446,7 +1477,9 @@
 	pixclock = atyfb_get_pixclock(var, par);
 
 	if (pixclock == 0) {
-		FAIL("Invalid pixclock");
+		if (!(var->activate & FB_ACTIVATE_TEST))
+			PRINTKE("Invalid pixclock\n");
+		return -EINVAL;
 	} else {
 		if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
 			return err;
@@ -2291,10 +2324,6 @@
 		par->dac_ops = &aty_dac_ct;
 		par->pll_ops = &aty_pll_ct;
 		par->bus_type = PCI;
-#ifdef CONFIG_FB_ATY_XL_INIT
-		if (IS_XL(par->pci_id))
-			atyfb_xl_init(info);
-#endif
 		par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
 		ramname = aty_ct_ram[par->ram_type];
 		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
@@ -2638,16 +2667,16 @@
 static int atyfb_blank(int blank, struct fb_info *info)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u8 gen_cntl;
+	u32 gen_cntl;
 
 	if (par->lock_blank || par->asleep)
 		return 0;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && blank)
+	if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL)
 		set_backlight_enable(0);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
-	if (par->lcd_table && blank &&
+	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
 		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
 		pm &= ~PWR_BLON;
@@ -2655,31 +2684,31 @@
 	}
 #endif
 
-	gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
+	gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
 	switch (blank) {
         	case FB_BLANK_UNBLANK:
-			gen_cntl &= ~(0x4c);
+			gen_cntl &= ~0x400004c;
 			break;
 		case FB_BLANK_NORMAL:
-			gen_cntl |= 0x40;
+			gen_cntl |= 0x4000040;
 			break;
 		case FB_BLANK_VSYNC_SUSPEND:
-			gen_cntl |= 0x8;
+			gen_cntl |= 0x4000048;
 			break;
 		case FB_BLANK_HSYNC_SUSPEND:
-			gen_cntl |= 0x4;
+			gen_cntl |= 0x4000044;
 			break;
 		case FB_BLANK_POWERDOWN:
-			gen_cntl |= 0x4c;
+			gen_cntl |= 0x400004c;
 			break;
 	}
-	aty_st_8(CRTC_GEN_CNTL, gen_cntl, par);
+	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && !blank)
+	if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL)
 		set_backlight_enable(1);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
-	if (par->lcd_table && !blank &&
+	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
 		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
 		pm |= PWR_BLON;
@@ -3157,15 +3186,15 @@
 			refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
 		par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
 		/* We now need to determine the crtc parameters for the
-		 * lcd monitor. This is tricky, because they are not stored
+		 * LCD monitor. This is tricky, because they are not stored
 		 * individually in the BIOS. Instead, the BIOS contains a
 		 * table of display modes that work for this monitor.
 		 *
 		 * The idea is that we search for a mode of the same dimensions
-		 * as the dimensions of the lcd monitor. Say our lcd monitor
+		 * as the dimensions of the LCD monitor. Say our LCD monitor
 		 * is 800x600 pixels, we search for a 800x600 monitor.
 		 * The CRTC parameters we find here are the ones that we need
-		 * to use to simulate other resolutions on the lcd screen.
+		 * to use to simulate other resolutions on the LCD screen.
 		 */
 		lcdmodeptr = (u16 *)(par->lcd_table + 64);
 		while (*lcdmodeptr != 0) {
@@ -3692,9 +3721,7 @@
     atyfb_setup(option);
 #endif
 
-#ifdef CONFIG_PCI
     pci_register_driver(&atyfb_driver);
-#endif
 #ifdef CONFIG_ATARI
     atyfb_atari_probe();
 #endif
@@ -3703,9 +3730,7 @@
 
 static void __exit atyfb_exit(void)
 {
-#ifdef CONFIG_PCI
 	pci_unregister_driver(&atyfb_driver);
-#endif
 }
 
 module_init(atyfb_init);
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
index 9bdb2aa..e705693 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/aty/mach64_ct.c
@@ -206,9 +206,7 @@
 {
 	u32 q;
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef DEBUG
 	int pllvclk;
-#endif
 
 	/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
 	q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;
@@ -223,13 +221,26 @@
 	pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
 	//    pll->vclk_post_div <<= 6;
 	pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
-#ifdef DEBUG
 	pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
 		(par->ref_clk_per * pll->pll_ref_div);
+#ifdef DEBUG
 	printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
 		__FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real);
 #endif
 	pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
+
+	/* Set ECP (scaler/overlay clock) divider */
+	if (par->pll_limits.ecp_max) {
+		int ecp = pllvclk / pll->vclk_post_div_real;
+		int ecp_div = 0;
+
+		while (ecp > par->pll_limits.ecp_max && ecp_div < 2) {
+			ecp >>= 1;
+			ecp_div++;
+		}
+		pll->pll_vclk_cntl |= ecp_div << 4;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c
deleted file mode 100644
index a085cbf..0000000
--- a/drivers/video/aty/xlinit.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- *  ATI Rage XL Initialization. Support for Xpert98 and Victoria
- *  PCI cards.
- *
- *  Copyright (C) 2002 MontaVista Software Inc.
- *  Author: MontaVista Software, Inc.
- *         	stevel@mvista.com or source@mvista.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  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 AUTHOR  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.
- *
- *  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 <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h> 
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <video/mach64.h>
-#include "atyfb.h"
-
-#define MPLL_GAIN       0xad
-#define VPLL_GAIN       0xd5
-
-enum {
-	VICTORIA = 0,
-	XPERT98,
-	NUM_XL_CARDS
-};
-
-extern const struct aty_pll_ops aty_pll_ct;
-
-#define DEFAULT_CARD XPERT98
-static int xl_card = DEFAULT_CARD;
-
-static const struct xl_card_cfg_t {
-	int ref_crystal; // 10^4 Hz
-	int mem_type;
-	int mem_size;
-	u32 mem_cntl;
-	u32 ext_mem_cntl;
-	u32 mem_addr_config;
-	u32 bus_cntl;
-	u32 dac_cntl;
-	u32 hw_debug;
-	u32 custom_macro_cntl;
-	u8  dll2_cntl;
-	u8  pll_yclk_cntl;
-} card_cfg[NUM_XL_CARDS] = {
-	// VICTORIA
-	{	2700, SDRAM, 0x800000,
-		0x10757A3B, 0x64000C81, 0x00110202, 0x7b33A040,
-		0x82010102, 0x48803800, 0x005E0179,
-		0x50, 0x25
-	},
-	// XPERT98
-	{	1432,  WRAM, 0x800000,
-		0x00165A2B, 0xE0000CF1, 0x00200213, 0x7333A001,
-		0x8000000A, 0x48833800, 0x007F0779,
-		0x10, 0x19
-	}
-};
-	  
-typedef struct {
-	u8 lcd_reg;
-	u32 val;
-} lcd_tbl_t;
-
-static const lcd_tbl_t lcd_tbl[] = {
-	{ 0x01,	0x000520C0 },
-	{ 0x08,	0x02000408 },
-	{ 0x03,	0x00000F00 },
-	{ 0x00,	0x00000000 },
-	{ 0x02,	0x00000000 },
-	{ 0x04,	0x00000000 },
-	{ 0x05,	0x00000000 },
-	{ 0x06,	0x00000000 },
-	{ 0x33,	0x00000000 },
-	{ 0x34,	0x00000000 },
-	{ 0x35,	0x00000000 },
-	{ 0x36,	0x00000000 },
-	{ 0x37,	0x00000000 }
-};
-
-static void reset_gui(struct atyfb_par *par)
-{
-	aty_st_8(GEN_TEST_CNTL+1, 0x01, par);
-	aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
-	aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
-	mdelay(5);
-}
-
-static void reset_sdram(struct atyfb_par *par)
-{
-	u8 temp;
-
-	temp = aty_ld_8(EXT_MEM_CNTL, par);
-	temp |= 0x02;
-	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_RESET = 1b
-	temp |= 0x08;
-	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST    = 10b
-	temp |= 0x0c;
-	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST    = 11b
-	mdelay(5);
-	temp &= 0xf3;
-	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST    = 00b
-	temp &= 0xfd;
-	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_REST  = 0b
-	mdelay(5);
-}
-
-static void init_dll(struct atyfb_par *par)
-{
-	// enable DLL
-	aty_st_pll_ct(PLL_GEN_CNTL,
-		   aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f,
-		   par);
-
-	// reset DLL
-	aty_st_pll_ct(DLL_CNTL, 0x82, par);
-	aty_st_pll_ct(DLL_CNTL, 0xE2, par);
-	mdelay(5);
-	aty_st_pll_ct(DLL_CNTL, 0x82, par);
-	mdelay(6);
-}
-
-static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll,
-			 int hsync_enb)
-{
-	reset_gui(par);
-	aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par);
-	aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par);
-
-	mdelay(15);
-	init_dll(par);
-	aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
-	mdelay(5);
-	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
-	mdelay(6);
-	reset_sdram(par);
-	aty_st_8(CRTC_GEN_CNTL+3,
-		 hsync_enb ? 0x00 : 0x04, par);
-
-	aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par);
-	aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
-	aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
-}
-
-int atyfb_xl_init(struct fb_info *info)
-{
-	const struct xl_card_cfg_t * card = &card_cfg[xl_card];
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	union aty_pll pll;
-	int err;
-	u32 temp;
-	
-	aty_st_8(CONFIG_STAT0, 0x85, par);
-	mdelay(10);
-
-	/*
-	 * The following needs to be set before the call
-	 * to var_to_pll() below. They'll be re-set again
-	 * to the same values in aty_init().
-	 */
-	par->ref_clk_per = 100000000UL/card->ref_crystal;
-	par->ram_type = card->mem_type;
-	info->fix.smem_len = card->mem_size;
-	if (xl_card == VICTORIA) {
-		// the MCLK, XCLK are 120MHz on victoria card
-		par->mclk_per = 1000000/120;
-		par->xclk_per = 1000000/120;
-		par->features &= ~M64F_MFB_FORCE_4;
-	}
-	
-	/*
-	 * Calculate mclk and xclk dividers, etc. The passed
-	 * pixclock and bpp values don't matter yet, the vclk
-	 * isn't programmed until later.
-	 */
-	if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
-		return err;
-
-	aty_st_pll_ct(LVDS_CNTL0, 0x00, par);
-	aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par);
-	aty_st_pll_ct(V2PLL_CNTL, 0x10, par);
-	aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par);
-	aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par);
-	aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par);
-	aty_st_pll_ct(VFC_CNTL, 0x1B, par);
-	aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par);
-	aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
-	aty_st_pll_ct(SPLL_CNTL2, 0x03, par);
-	aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par);
-
-	reset_clocks(par, &pll.ct, 0);
-	mdelay(10);
-
-	aty_st_pll_ct(VCLK_POST_DIV, 0x03, par);
-	aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par);
-	aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par);
-	aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par);
-	aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par);
-	aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
-	aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par);
-	aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par);
-	aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
-	aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par);
-
-	aty_st_8(BUS_CNTL, 0x01, par);
-	aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par);
-
-	aty_st_le32(CRTC_GEN_CNTL, 0x04000200, par);
-	aty_st_le16(CONFIG_STAT0, 0x0020, par);
-	aty_st_le32(MEM_CNTL, 0x10151A33, par);
-	aty_st_le32(EXT_MEM_CNTL, 0xE0000C01, par);
-	aty_st_le16(CRTC_GEN_CNTL+2, 0x0000, par);
-	aty_st_le32(DAC_CNTL, card->dac_cntl, par);
-	aty_st_le16(GEN_TEST_CNTL, 0x0100, par);
-	aty_st_le32(CUSTOM_MACRO_CNTL, 0x003C0171, par);
-	aty_st_le32(MEM_BUF_CNTL, 0x00382848, par);
-
-	aty_st_le32(HW_DEBUG, card->hw_debug, par);
-	aty_st_le16(MEM_ADDR_CONFIG, 0x0000, par);
-	aty_st_le16(GP_IO+2, 0x0000, par);
-	aty_st_le16(GEN_TEST_CNTL, 0x0000, par);
-	aty_st_le16(EXT_DAC_REGS+2, 0x0000, par);
-	aty_st_le32(CRTC_INT_CNTL, 0x00000000, par);
-	aty_st_le32(TIMER_CONFIG, 0x00000000, par);
-	aty_st_le32(0xEC, 0x00000000, par);
-	aty_st_le32(0xFC, 0x00000000, par);
-
-#if defined (CONFIG_FB_ATY_GENERIC_LCD)
-	{
-		int i;
-
-		for (i = 0; i < ARRAY_SIZE(lcd_tbl); i++)
-			aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
-	}
-#endif
-
-	aty_st_le16(CONFIG_STAT0, 0x00A4, par);
-	mdelay(10);
-
-	aty_st_8(BUS_CNTL+1, 0xA0, par);
-	mdelay(10);
-	
-	reset_clocks(par, &pll.ct, 1);
-	mdelay(10);
-
-	// something about power management
-	aty_st_8(LCD_INDEX, 0x08, par);
-	aty_st_8(LCD_DATA, 0x0A, par);
-	aty_st_8(LCD_INDEX, 0x08, par);
-	aty_st_8(LCD_DATA+3, 0x02, par);
-	aty_st_8(LCD_INDEX, 0x08, par);
-	aty_st_8(LCD_DATA, 0x0B, par);
-	mdelay(2);
-	
-	// enable display requests, enable CRTC
-	aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
-	// disable display
-	aty_st_8(CRTC_GEN_CNTL, 0x40, par);
-	// disable display requests, disable CRTC
-	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
-	mdelay(10);
-
-	aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par);
-
-	aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par);
-	aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par);
-	aty_st_le16(CUSTOM_MACRO_CNTL+2, card->custom_macro_cntl>>16, par);
-	aty_st_8(CUSTOM_MACRO_CNTL+1,
-		 (card->custom_macro_cntl>>8) & 0xff, par);
-
-	aty_st_le32(MEM_ADDR_CONFIG, card->mem_addr_config, par);
-	aty_st_le32(MEM_CNTL, card->mem_cntl, par);
-	aty_st_le32(EXT_MEM_CNTL, card->ext_mem_cntl, par);
-
-	aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par);
-
-	aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par);
-	mdelay(15);
-	aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
-	mdelay(1);
-	
-	reset_clocks(par, &pll.ct, 0);
-	mdelay(50);
-	reset_clocks(par, &pll.ct, 0);
-	mdelay(50);
-
-	// enable extended register block
-	aty_st_8(BUS_CNTL+3, 0x7B, par);
-	mdelay(1);
-	// disable extended register block
-	aty_st_8(BUS_CNTL+3, 0x73, par);
-
-	aty_st_8(CONFIG_STAT0, 0x80 | card->mem_type, par);
-
-	// disable display requests, disable CRTC
-	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
-	// disable mapping registers in VGA aperture
-	aty_st_8(CONFIG_CNTL, aty_ld_8(CONFIG_CNTL, par) & ~0x04, par);
-	mdelay(50);
-	// enable display requests, enable CRTC
-	aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
-
-	// make GPIO's 14,15,16 all inputs
-	aty_st_8(LCD_INDEX, 0x07, par);
-	aty_st_8(LCD_DATA+3, 0x00, par);
-
-	// enable the display
-	aty_st_8(CRTC_GEN_CNTL, 0x00, par);
-	mdelay(17);
-	// reset the memory controller
-	aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
-	mdelay(15);
-	aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
-	mdelay(30);
-
-	// enable extended register block
-	aty_st_8(BUS_CNTL+3,
-		 (u8)(aty_ld_8(BUS_CNTL+3, par) | 0x08),
-		 par);
-	// set FIFO size to 512 (PIO)
-	aty_st_le32(GUI_CNTL,
-		    aty_ld_le32(GUI_CNTL, par) & ~0x3,
-		    par);
-
-	// enable CRT and disable lcd
-	aty_st_8(LCD_INDEX, 0x01, par);
-	temp = aty_ld_le32(LCD_DATA, par);
-	temp = (temp | 0x01) & ~0x02;
-	aty_st_le32(LCD_DATA, temp, par);
-	return 0;
-}
-
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index e65fc3e..eea422e 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -234,14 +234,14 @@
 	}
 }
 
-static void bit_cursor(struct vc_data *vc, struct fb_info *info,
-		       struct display *p, int mode, int softback_lines, int fg, int bg)
+static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+		       int softback_lines, int fg, int bg)
 {
 	struct fb_cursor cursor;
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int w = (vc->vc_font.width + 7) >> 3, c;
-	int y = real_y(p, vc->vc_y);
+	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1;
 	char *src;
@@ -310,7 +310,7 @@
 	}
 
 	if (cursor.set & FB_CUR_SETSIZE ||
-	    vc->vc_cursor_type != p->cursor_shape ||
+	    vc->vc_cursor_type != ops->p->cursor_shape ||
 	    ops->cursor_state.mask == NULL ||
 	    ops->cursor_reset) {
 		char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
@@ -323,10 +323,10 @@
 		kfree(ops->cursor_state.mask);
 		ops->cursor_state.mask = mask;
 
-		p->cursor_shape = vc->vc_cursor_type;
+		ops->p->cursor_shape = vc->vc_cursor_type;
 		cursor.set |= FB_CUR_SETSHAPE;
 
-		switch (p->cursor_shape & CUR_HWMASK) {
+		switch (ops->p->cursor_shape & CUR_HWMASK) {
 		case CUR_NONE:
 			cur_height = 0;
 			break;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 50e4c4e..041d069 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -209,13 +209,13 @@
 #endif
 
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
-static inline void fbcon_set_rotation(struct fb_info *info, struct display *p)
+static inline void fbcon_set_rotation(struct fb_info *info)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
 
 	if (!(info->flags & FBINFO_MISC_TILEBLITTING) &&
-	    p->con_rotate < 4)
-		ops->rotate = p->con_rotate;
+	    ops->p->con_rotate < 4)
+		ops->rotate = ops->p->con_rotate;
 	else
 		ops->rotate = 0;
 }
@@ -265,7 +265,7 @@
 	fbcon_set_all_vcs(info);
 }
 #else
-static inline void fbcon_set_rotation(struct fb_info *info, struct display *p)
+static inline void fbcon_set_rotation(struct fb_info *info)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
 
@@ -402,7 +402,7 @@
 	c = scr_readw((u16 *) vc->vc_pos);
 	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
 		CM_ERASE : CM_DRAW;
-	ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1),
+	ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
 		    get_color(vc, info, c, 0));
 	release_console_sem();
 }
@@ -647,29 +647,27 @@
 }
 
 #ifdef CONFIG_FB_TILEBLITTING
-static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
-			      struct display *p)
+static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
 
-	ops->p = (p) ? p : &fb_display[vc->vc_num];
+	ops->p = &fb_display[vc->vc_num];
 
 	if ((info->flags & FBINFO_MISC_TILEBLITTING))
-		fbcon_set_tileops(vc, info, p, ops);
+		fbcon_set_tileops(vc, info);
 	else {
-		fbcon_set_rotation(info, ops->p);
+		fbcon_set_rotation(info);
 		fbcon_set_bitops(ops);
 	}
 }
 #else
-static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
-			      struct display *p)
+static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
 
 	info->flags &= ~FBINFO_MISC_TILEBLITTING;
-	ops->p = (p) ? p : &fb_display[vc->vc_num];
-	fbcon_set_rotation(info, ops->p);
+	ops->p = &fb_display[vc->vc_num];
+	fbcon_set_rotation(info);
 	fbcon_set_bitops(ops);
 }
 #endif /* CONFIG_MISC_TILEBLITTING */
@@ -689,15 +687,14 @@
 		err = -ENODEV;
 
 	if (!err) {
-		ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+		ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
 		if (!ops)
 			err = -ENOMEM;
 	}
 
 	if (!err) {
-		memset(ops, 0, sizeof(struct fbcon_ops));
 		info->fbcon_par = ops;
-		set_blitting_type(vc, info, NULL);
+		set_blitting_type(vc, info);
 	}
 
 	if (err) {
@@ -921,19 +918,18 @@
 		return NULL;
 	}
 
-	ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+	ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
 	if (!ops) {
 		module_put(owner);
 		return NULL;
 	}
 
-	memset(ops, 0, sizeof(struct fbcon_ops));
 	ops->currcon = -1;
 	ops->graphics = 1;
 	ops->cur_rotate = -1;
 	info->fbcon_par = ops;
 	p->con_rotate = rotate;
-	set_blitting_type(vc, info, NULL);
+	set_blitting_type(vc, info);
 
 	if (info->fix.type != FB_TYPE_TEXT) {
 		if (fbcon_softback_size) {
@@ -1093,7 +1089,7 @@
 
 	ops = info->fbcon_par;
 	p->con_rotate = rotate;
-	set_blitting_type(vc, info, NULL);
+	set_blitting_type(vc, info);
 
 	cols = vc->vc_cols;
 	rows = vc->vc_rows;
@@ -1141,9 +1137,9 @@
 	if (vc == svc && softback_buf)
 		fbcon_update_softback(vc);
 
-	if (ops->rotate_font && ops->rotate_font(info, vc, p)) {
+	if (ops->rotate_font && ops->rotate_font(info, vc)) {
 		ops->rotate = FB_ROTATE_UR;
-		set_blitting_type(vc, info, p);
+		set_blitting_type(vc, info);
 	}
 
 }
@@ -1243,7 +1239,6 @@
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct fbcon_ops *ops = info->fbcon_par;
-	struct display *p = &fb_display[vc->vc_num];
 	int y;
  	int c = scr_readw((u16 *) vc->vc_pos);
 
@@ -1260,7 +1255,7 @@
 		y = 0;
 	}
 
-	ops->cursor(vc, info, p, mode, y, get_color(vc, info, c, 1),
+	ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
 		    get_color(vc, info, c, 0));
 	vbl_cursor_cnt = CURSOR_DRAW_DELAY;
 }
@@ -1411,16 +1406,13 @@
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct fbcon_ops *ops = info->fbcon_par;
 	struct display *p = &fb_display[vc->vc_num];
-	int redraw = 0;
 
 	p->yscroll += count;
+
 	if (p->yscroll > p->vrows - vc->vc_rows) {
 		p->yscroll -= p->vrows - vc->vc_rows;
-		redraw = 1;
-	}
-
-	if (redraw)
 		fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
+	}
 
 	ops->var.xoffset = 0;
 	ops->var.yoffset = p->yscroll * vc->vc_font.height;
@@ -1462,16 +1454,13 @@
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct fbcon_ops *ops = info->fbcon_par;
 	struct display *p = &fb_display[vc->vc_num];
-	int redraw = 0;
 
 	p->yscroll -= count;
+
 	if (p->yscroll < 0) {
 		p->yscroll += p->vrows - vc->vc_rows;
-		redraw = 1;
-	}
-
-	if (redraw)
 		fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
+	}
 
 	ops->var.xoffset = 0;
 	ops->var.yoffset = p->yscroll * vc->vc_font.height;
@@ -1968,7 +1957,8 @@
 		divides(ypan, vc->vc_font.height) && vyres > yres;
 	int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
 		divides(ywrap, vc->vc_font.height) &&
-		divides(vc->vc_font.height, vyres);
+		divides(vc->vc_font.height, vyres) &&
+		divides(vc->vc_font.height, yres);
 	int reading_fast = cap & FBINFO_READS_FAST;
 	int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) &&
 		!(cap & FBINFO_HWACCEL_DISABLED);
@@ -2107,16 +2097,19 @@
 				 info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
 		if (info->fbops->fb_set_par)
 			info->fbops->fb_set_par(info);
-		fbcon_del_cursor_timer(old_info);
-		fbcon_add_cursor_timer(info);
+
+		if (old_info != info) {
+			fbcon_del_cursor_timer(old_info);
+			fbcon_add_cursor_timer(info);
+		}
 	}
 
-	set_blitting_type(vc, info, p);
+	set_blitting_type(vc, info);
 	ops->cursor_reset = 1;
 
-	if (ops->rotate_font && ops->rotate_font(info, vc, p)) {
+	if (ops->rotate_font && ops->rotate_font(info, vc)) {
 		ops->rotate = FB_ROTATE_UR;
-		set_blitting_type(vc, info, p);
+		set_blitting_type(vc, info);
 	}
 
 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
@@ -2739,7 +2732,7 @@
 		return;
 
 	p = &fb_display[vc->vc_num];
-	set_blitting_type(vc, info, p);
+	set_blitting_type(vc, info);
 
 	if (CON_IS_VISIBLE(vc)) {
 		var_to_display(p, &info->var, info);
@@ -2781,7 +2774,7 @@
 			continue;
 
 		p = &fb_display[vc->vc_num];
-		set_blitting_type(vc, info, p);
+		set_blitting_type(vc, info);
 		var_to_display(p, &info->var, info);
 		cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
@@ -2806,6 +2799,8 @@
 				fbcon_update_softback(vc);
 		}
 	}
+
+	ops->p = &fb_display[ops->currcon];
 }
 
 static int fbcon_mode_deleted(struct fb_info *info,
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 6892e7f..c38c3d8 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -62,12 +62,10 @@
 		      int fg, int bg);
 	void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
 			      int bottom_only);
-	void (*cursor)(struct vc_data *vc, struct fb_info *info,
-		       struct display *p, int mode, int softback_lines,
-		       int fg, int bg);
+	void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
+		       int softback_lines, int fg, int bg);
 	int  (*update_start)(struct fb_info *info);
-	int  (*rotate_font)(struct fb_info *info, struct vc_data *vc,
-			    struct display *p);
+	int  (*rotate_font)(struct fb_info *info, struct vc_data *vc);
 	struct fb_var_screeninfo var;  /* copy of the current fb_var_screeninfo */
 	struct timer_list cursor_timer; /* Cursor timer */
 	struct fb_cursor cursor_state;
@@ -173,8 +171,7 @@
 #define SCROLL_PAN_REDRAW  0x005
 
 #ifdef CONFIG_FB_TILEBLITTING
-extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
-			      struct display *p, struct fbcon_ops *ops);
+extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
 #endif
 extern void fbcon_set_bitops(struct fbcon_ops *ops);
 extern int  soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 4952b66..990289a 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -219,19 +219,18 @@
 	}
 }
 
-static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
-		      struct display *p, int mode, int softback_lines,
-		      int fg, int bg)
+static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+		       int softback_lines, int fg, int bg)
 {
 	struct fb_cursor cursor;
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int w = (vc->vc_font.height + 7) >> 3, c;
-	int y = real_y(p, vc->vc_y);
+	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1, dx, dy;
 	char *src;
-	u32 vyres = GETVYRES(p->scrollmode, info);
+	u32 vyres = GETVYRES(ops->p->scrollmode, info);
 
 	if (!ops->fontbuffer)
 		return;
@@ -303,7 +302,7 @@
 	}
 
 	if (cursor.set & FB_CUR_SETSIZE ||
-	    vc->vc_cursor_type != p->cursor_shape ||
+	    vc->vc_cursor_type != ops->p->cursor_shape ||
 	    ops->cursor_state.mask == NULL ||
 	    ops->cursor_reset) {
 		char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
@@ -323,10 +322,10 @@
 		kfree(ops->cursor_state.mask);
 		ops->cursor_state.mask = mask;
 
-		p->cursor_shape = vc->vc_cursor_type;
+		ops->p->cursor_shape = vc->vc_cursor_type;
 		cursor.set |= FB_CUR_SETSHAPE;
 
-		switch (p->cursor_shape & CUR_HWMASK) {
+		switch (ops->p->cursor_shape & CUR_HWMASK) {
 		case CUR_NONE:
 			cur_height = 0;
 			break;
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6d92b84..d44c5fa 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -203,19 +203,18 @@
 	}
 }
 
-static void cw_cursor(struct vc_data *vc, struct fb_info *info,
-		      struct display *p, int mode, int softback_lines,
-		      int fg, int bg)
+static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+		      int softback_lines, int fg, int bg)
 {
 	struct fb_cursor cursor;
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int w = (vc->vc_font.height + 7) >> 3, c;
-	int y = real_y(p, vc->vc_y);
+	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1, dx, dy;
 	char *src;
-	u32 vxres = GETVXRES(p->scrollmode, info);
+	u32 vxres = GETVXRES(ops->p->scrollmode, info);
 
 	if (!ops->fontbuffer)
 		return;
@@ -287,7 +286,7 @@
 	}
 
 	if (cursor.set & FB_CUR_SETSIZE ||
-	    vc->vc_cursor_type != p->cursor_shape ||
+	    vc->vc_cursor_type != ops->p->cursor_shape ||
 	    ops->cursor_state.mask == NULL ||
 	    ops->cursor_reset) {
 		char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
@@ -307,10 +306,10 @@
 		kfree(ops->cursor_state.mask);
 		ops->cursor_state.mask = mask;
 
-		p->cursor_shape = vc->vc_cursor_type;
+		ops->p->cursor_shape = vc->vc_cursor_type;
 		cursor.set |= FB_CUR_SETSHAPE;
 
-		switch (p->cursor_shape & CUR_HWMASK) {
+		switch (ops->p->cursor_shape & CUR_HWMASK) {
 		case CUR_NONE:
 			cur_height = 0;
 			break;
diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c
index ec0dd8f..2dc091f 100644
--- a/drivers/video/console/fbcon_rotate.c
+++ b/drivers/video/console/fbcon_rotate.c
@@ -18,8 +18,7 @@
 #include "fbcon.h"
 #include "fbcon_rotate.h"
 
-static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc,
-			     struct display *p)
+static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
 	int len, err = 0;
@@ -28,12 +27,12 @@
 	u8 *dst;
 
 	if (vc->vc_font.data == ops->fontdata &&
-	    p->con_rotate == ops->cur_rotate)
+	    ops->p->con_rotate == ops->cur_rotate)
 		goto finished;
 
 	src = ops->fontdata = vc->vc_font.data;
-	ops->cur_rotate = p->con_rotate;
-	len = (!p->userfont) ? 256 : FNTCHARCNT(src);
+	ops->cur_rotate = ops->p->con_rotate;
+	len = (!ops->p->userfont) ? 256 : FNTCHARCNT(src);
 	s_cellsize = ((vc->vc_font.width + 7)/8) *
 		vc->vc_font.height;
 	d_cellsize = s_cellsize;
diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h
index 1b8f92f..75be5ce 100644
--- a/drivers/video/console/fbcon_rotate.h
+++ b/drivers/video/console/fbcon_rotate.h
@@ -11,8 +11,6 @@
 #ifndef _FBCON_ROTATE_H
 #define _FBCON_ROTATE_H
 
-#define FNTCHARCNT(fd)	(((int *)(fd))[-3])
-
 #define GETVYRES(s,i) ({                           \
         (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
         (i)->var.yres : (i)->var.yres_virtual; })
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index 9dd059e..f56ed06 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -249,20 +249,19 @@
 	}
 }
 
-static void ud_cursor(struct vc_data *vc, struct fb_info *info,
-		      struct display *p, int mode, int softback_lines,
-		      int fg, int bg)
+static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+		      int softback_lines, int fg, int bg)
 {
 	struct fb_cursor cursor;
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int w = (vc->vc_font.width + 7) >> 3, c;
-	int y = real_y(p, vc->vc_y);
+	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1, dx, dy;
 	char *src;
-	u32 vyres = GETVYRES(p->scrollmode, info);
-	u32 vxres = GETVXRES(p->scrollmode, info);
+	u32 vyres = GETVYRES(ops->p->scrollmode, info);
+	u32 vxres = GETVXRES(ops->p->scrollmode, info);
 
 	if (!ops->fontbuffer)
 		return;
@@ -334,7 +333,7 @@
 	}
 
 	if (cursor.set & FB_CUR_SETSIZE ||
-	    vc->vc_cursor_type != p->cursor_shape ||
+	    vc->vc_cursor_type != ops->p->cursor_shape ||
 	    ops->cursor_state.mask == NULL ||
 	    ops->cursor_reset) {
 		char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
@@ -347,10 +346,10 @@
 		kfree(ops->cursor_state.mask);
 		ops->cursor_state.mask = mask;
 
-		p->cursor_shape = vc->vc_cursor_type;
+		ops->p->cursor_shape = vc->vc_cursor_type;
 		cursor.set |= FB_CUR_SETSHAPE;
 
-		switch (p->cursor_shape & CUR_HWMASK) {
+		switch (ops->p->cursor_shape & CUR_HWMASK) {
 		case CUR_NONE:
 			cur_height = 0;
 			break;
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 8529bf0..3957fc7 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -17,6 +17,8 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+#include "fbcon.h"
+
 int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	unsigned int scan_align = info->pixmap.scan_align - 1;
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
index cb25324..153352c 100644
--- a/drivers/video/console/tileblit.c
+++ b/drivers/video/console/tileblit.c
@@ -80,9 +80,8 @@
 	return;
 }
 
-static void tile_cursor(struct vc_data *vc, struct fb_info *info,
-			struct display *p, int mode, int softback_lines,
-			int fg, int bg)
+static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+			int softback_lines, int fg, int bg)
 {
 	struct fb_tilecursor cursor;
 	int use_sw = (vc->vc_cursor_type & 0x01);
@@ -130,10 +129,10 @@
 	return err;
 }
 
-void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
-		       struct display *p, struct fbcon_ops *ops)
+void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
 {
 	struct fb_tilemap map;
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	ops->bmove = tile_bmove;
 	ops->clear = tile_clear;
@@ -142,13 +141,13 @@
 	ops->cursor = tile_cursor;
 	ops->update_start = tile_update_start;
 
-	if (p) {
+	if (ops->p) {
 		map.width = vc->vc_font.width;
 		map.height = vc->vc_font.height;
 		map.depth = 1;
-		map.length = (p->userfont) ?
-			FNTCHARCNT(p->fontdata) : 256;
-		map.data = p->fontdata;
+		map.length = (ops->p->userfont) ?
+			FNTCHARCNT(ops->p->fontdata) : 256;
+		map.data = ops->p->fontdata;
 		info->tileops->fb_settile(info, &map);
 	}
 }
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index 0b6af00..ac90883 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -214,12 +214,11 @@
 {
 	u32 pixcount, pixcount_mod;
 	int cnt = 255, offset = 0, read = 0;
-	u8 *buf = kmalloc(256, GFP_KERNEL);
+	u8 *buf = kzalloc(256, GFP_KERNEL);
 
 	if (!buf)
 		return;
 
-	memset(buf, 0, 256);
 	pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000;
 	pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
 	pixcount_mod /= 1000;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 10dfdf0..32a9b69 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -589,17 +589,19 @@
 		return info->fbops->fb_read(file, buf, count, ppos);
 	
 	total_size = info->screen_size;
+
 	if (total_size == 0)
 		total_size = info->fix.smem_len;
 
 	if (p >= total_size)
-	    return 0;
+		return 0;
+
 	if (count >= total_size)
-	    count = total_size;
+		count = total_size;
+
 	if (count + p > total_size)
 		count = total_size - p;
 
-	cnt = 0;
 	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
 			 GFP_KERNEL);
 	if (!buffer)
@@ -636,6 +638,7 @@
 	}
 
 	kfree(buffer);
+
 	return (err) ? err : cnt;
 }
 
@@ -648,7 +651,7 @@
 	struct fb_info *info = registered_fb[fbidx];
 	u32 *buffer, *src;
 	u32 __iomem *dst;
-	int c, i, cnt = 0, err;
+	int c, i, cnt = 0, err = 0;
 	unsigned long total_size;
 
 	if (!info || !info->screen_base)
@@ -661,19 +664,19 @@
 		return info->fbops->fb_write(file, buf, count, ppos);
 	
 	total_size = info->screen_size;
+
 	if (total_size == 0)
 		total_size = info->fix.smem_len;
 
 	if (p > total_size)
-	    return -ENOSPC;
+		return 0;
+
 	if (count >= total_size)
-	    count = total_size;
-	err = 0;
-	if (count + p > total_size) {
-	    count = total_size - p;
-	    err = -ENOSPC;
-	}
-	cnt = 0;
+		count = total_size;
+
+	if (count + p > total_size)
+		count = total_size - p;
+
 	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
 			 GFP_KERNEL);
 	if (!buffer)
@@ -687,12 +690,15 @@
 	while (count) {
 		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
 		src = buffer;
+
 		if (copy_from_user(src, buf, c)) {
 			err = -EFAULT;
 			break;
 		}
+
 		for (i = c >> 2; i--; )
 			fb_writel(*src++, dst++);
+
 		if (c & 3) {
 			u8 *src8 = (u8 *) src;
 			u8 __iomem *dst8 = (u8 __iomem *) dst;
@@ -702,11 +708,13 @@
 
 			dst = (u32 __iomem *) dst8;
 		}
+
 		*ppos += c;
 		buf += c;
 		cnt += c;
 		count -= c;
 	}
+
 	kfree(buffer);
 
 	return (err) ? err : cnt;
@@ -1226,6 +1234,7 @@
 		return -ENODEV;
 	if (!try_module_get(info->fbops->owner))
 		return -ENODEV;
+	file->private_data = info;
 	if (info->fbops->fb_open) {
 		res = info->fbops->fb_open(info,1);
 		if (res)
@@ -1237,11 +1246,9 @@
 static int 
 fb_release(struct inode *inode, struct file *file)
 {
-	int fbidx = iminor(inode);
-	struct fb_info *info;
+	struct fb_info * const info = file->private_data;
 
 	lock_kernel();
-	info = registered_fb[fbidx];
 	if (info->fbops->fb_release)
 		info->fbops->fb_release(info,1);
 	module_put(info->fbops->owner);
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index fc7965b..7c74e73 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -317,26 +317,29 @@
 static void calc_mode_timings(int xres, int yres, int refresh,
 			      struct fb_videomode *mode)
 {
-	struct fb_var_screeninfo var;
-	struct fb_info info;
+	struct fb_var_screeninfo *var;
 	
-	memset(&var, 0, sizeof(struct fb_var_screeninfo));
-	var.xres = xres;
-	var.yres = yres;
-	fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 
-		    refresh, &var, &info);
-	mode->xres = xres;
-	mode->yres = yres;
-	mode->pixclock = var.pixclock;
-	mode->refresh = refresh;
-	mode->left_margin = var.left_margin;
-	mode->right_margin = var.right_margin;
-	mode->upper_margin = var.upper_margin;
-	mode->lower_margin = var.lower_margin;
-	mode->hsync_len = var.hsync_len;
-	mode->vsync_len = var.vsync_len;
-	mode->vmode = 0;
-	mode->sync = 0;
+	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+
+	if (var) {
+		var->xres = xres;
+		var->yres = yres;
+		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
+			    refresh, var, NULL);
+		mode->xres = xres;
+		mode->yres = yres;
+		mode->pixclock = var->pixclock;
+		mode->refresh = refresh;
+		mode->left_margin = var->left_margin;
+		mode->right_margin = var->right_margin;
+		mode->upper_margin = var->upper_margin;
+		mode->lower_margin = var->lower_margin;
+		mode->hsync_len = var->hsync_len;
+		mode->vsync_len = var->vsync_len;
+		mode->vmode = 0;
+		mode->sync = 0;
+		kfree(var);
+	}
 }
 
 static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
@@ -525,10 +528,9 @@
 	unsigned char *block;
 	int num = 0, i;
 
-	mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+	mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
 	if (mode == NULL)
 		return NULL;
-	memset(mode, 0, 50 * sizeof(struct fb_videomode));
 
 	if (edid == NULL || !edid_checksum(edid) || 
 	    !edid_check_header(edid)) {
@@ -1105,15 +1107,21 @@
  */ 
 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct __fb_timings timings;
+	struct __fb_timings *timings;
 	u32 interlace = 1, dscan = 1;
-	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
+	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
+
+
+	timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
+
+	if (!timings)
+		return -ENOMEM;
 
 	/* 
 	 * If monspecs are invalid, use values that are enough
 	 * for 640x480@60
 	 */
-	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
 	    !info->monspecs.dclkmax ||
 	    info->monspecs.hfmax < info->monspecs.hfmin ||
 	    info->monspecs.vfmax < info->monspecs.vfmin ||
@@ -1130,65 +1138,66 @@
 		dclkmax = info->monspecs.dclkmax;
 	}
 
-	memset(&timings, 0, sizeof(struct __fb_timings));
-	timings.hactive = var->xres;
-	timings.vactive = var->yres;
+	timings->hactive = var->xres;
+	timings->vactive = var->yres;
 	if (var->vmode & FB_VMODE_INTERLACED) { 
-		timings.vactive /= 2;
+		timings->vactive /= 2;
 		interlace = 2;
 	}
 	if (var->vmode & FB_VMODE_DOUBLE) {
-		timings.vactive *= 2;
+		timings->vactive *= 2;
 		dscan = 2;
 	}
 
 	switch (flags & ~FB_IGNOREMON) {
 	case FB_MAXTIMINGS: /* maximize refresh rate */
-		timings.hfreq = hfmax;
-		fb_timings_hfreq(&timings);
-		if (timings.vfreq > vfmax) {
-			timings.vfreq = vfmax;
-			fb_timings_vfreq(&timings);
+		timings->hfreq = hfmax;
+		fb_timings_hfreq(timings);
+		if (timings->vfreq > vfmax) {
+			timings->vfreq = vfmax;
+			fb_timings_vfreq(timings);
 		}
-		if (timings.dclk > dclkmax) {
-			timings.dclk = dclkmax;
-			fb_timings_dclk(&timings);
+		if (timings->dclk > dclkmax) {
+			timings->dclk = dclkmax;
+			fb_timings_dclk(timings);
 		}
 		break;
 	case FB_VSYNCTIMINGS: /* vrefresh driven */
-		timings.vfreq = val;
-		fb_timings_vfreq(&timings);
+		timings->vfreq = val;
+		fb_timings_vfreq(timings);
 		break;
 	case FB_HSYNCTIMINGS: /* hsync driven */
-		timings.hfreq = val;
-		fb_timings_hfreq(&timings);
+		timings->hfreq = val;
+		fb_timings_hfreq(timings);
 		break;
 	case FB_DCLKTIMINGS: /* pixelclock driven */
-		timings.dclk = PICOS2KHZ(val) * 1000;
-		fb_timings_dclk(&timings);
+		timings->dclk = PICOS2KHZ(val) * 1000;
+		fb_timings_dclk(timings);
 		break;
 	default:
-		return -EINVAL;
+		err = -EINVAL;
 		
 	} 
 	
-	if (!(flags & FB_IGNOREMON) && 
-	    (timings.vfreq < vfmin || timings.vfreq > vfmax || 
-	     timings.hfreq < hfmin || timings.hfreq > hfmax ||
-	     timings.dclk < dclkmin || timings.dclk > dclkmax))
-		return -EINVAL;
-
-	var->pixclock = KHZ2PICOS(timings.dclk/1000);
-	var->hsync_len = (timings.htotal * 8)/100;
-	var->right_margin = (timings.hblank/2) - var->hsync_len;
-	var->left_margin = timings.hblank - var->right_margin - var->hsync_len;
+	if (err || (!(flags & FB_IGNOREMON) &&
+	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||
+	     timings->hfreq < hfmin || timings->hfreq > hfmax ||
+	     timings->dclk < dclkmin || timings->dclk > dclkmax))) {
+		err = -EINVAL;
+	} else {
+		var->pixclock = KHZ2PICOS(timings->dclk/1000);
+		var->hsync_len = (timings->htotal * 8)/100;
+		var->right_margin = (timings->hblank/2) - var->hsync_len;
+		var->left_margin = timings->hblank - var->right_margin -
+			var->hsync_len;
+		var->vsync_len = (3 * interlace)/dscan;
+		var->lower_margin = (1 * interlace)/dscan;
+		var->upper_margin = (timings->vblank * interlace)/dscan -
+			(var->vsync_len + var->lower_margin);
+	}
 	
-	var->vsync_len = (3 * interlace)/dscan;
-	var->lower_margin = (1 * interlace)/dscan;
-	var->upper_margin = (timings.vblank * interlace)/dscan - 
-		(var->vsync_len + var->lower_margin);
-	
-	return 0;
+	kfree(timings);
+	return err;
 }
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 08dac95..6d26057 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -43,10 +43,11 @@
 	if (size)
 		fb_info_size += PADDING;
 
-	p = kmalloc(fb_info_size + size, GFP_KERNEL);
+	p = kzalloc(fb_info_size + size, GFP_KERNEL);
+
 	if (!p)
 		return NULL;
-	memset(p, 0, fb_info_size + size);
+
 	info = (struct fb_info *) p;
 
 	if (size)
@@ -106,8 +107,7 @@
 static ssize_t store_mode(struct class_device *class_device, const char * buf,
 			  size_t count)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	char mstr[100];
 	struct fb_var_screeninfo var;
 	struct fb_modelist *modelist;
@@ -137,8 +137,7 @@
 
 static ssize_t show_mode(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 
 	if (!fb_info->mode)
 		return 0;
@@ -149,8 +148,7 @@
 static ssize_t store_modes(struct class_device *class_device, const char * buf,
 			   size_t count)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	LIST_HEAD(old_list);
 	int i = count / sizeof(struct fb_videomode);
 
@@ -174,8 +172,7 @@
 
 static ssize_t show_modes(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	unsigned int i;
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -193,8 +190,7 @@
 static ssize_t store_bpp(struct class_device *class_device, const char * buf,
 			 size_t count)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	struct fb_var_screeninfo var;
 	char ** last = NULL;
 	int err;
@@ -208,8 +204,7 @@
 
 static ssize_t show_bpp(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
 }
 
@@ -280,8 +275,7 @@
 static ssize_t store_virtual(struct class_device *class_device,
 			     const char * buf, size_t count)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	struct fb_var_screeninfo var;
 	char *last = NULL;
 	int err;
@@ -300,16 +294,14 @@
 
 static ssize_t show_virtual(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
 			fb_info->var.yres_virtual);
 }
 
 static ssize_t show_stride(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
 }
 
@@ -320,7 +312,7 @@
 static ssize_t store_cmap(struct class_device *class_device, const char *buf,
 			  size_t count)
 {
-	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	int rc, i, start, length, transp = 0;
 
 	if ((count > PAGE_SIZE) || ((count % 16) != 0))
@@ -380,8 +372,7 @@
 
 static ssize_t show_cmap(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	unsigned int i;
 
 	if (!fb_info->cmap.red || !fb_info->cmap.blue ||
@@ -405,8 +396,7 @@
 static ssize_t store_blank(struct class_device *class_device, const char * buf,
 			   size_t count)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	char *last = NULL;
 	int err;
 
@@ -422,41 +412,40 @@
 
 static ssize_t show_blank(struct class_device *class_device, char *buf)
 {
-//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+//	struct fb_info *fb_info = class_get_devdata(class_device);
 	return 0;
 }
 
 static ssize_t store_console(struct class_device *class_device,
 			     const char * buf, size_t count)
 {
-//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+//	struct fb_info *fb_info = class_get_devdata(class_device);
 	return 0;
 }
 
 static ssize_t show_console(struct class_device *class_device, char *buf)
 {
-//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+//	struct fb_info *fb_info = class_get_devdata(class_device);
 	return 0;
 }
 
 static ssize_t store_cursor(struct class_device *class_device,
 			    const char * buf, size_t count)
 {
-//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+//	struct fb_info *fb_info = class_get_devdata(class_device);
 	return 0;
 }
 
 static ssize_t show_cursor(struct class_device *class_device, char *buf)
 {
-//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+//	struct fb_info *fb_info = class_get_devdata(class_device);
 	return 0;
 }
 
 static ssize_t store_pan(struct class_device *class_device, const char * buf,
 			 size_t count)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	struct fb_var_screeninfo var;
 	char *last = NULL;
 	int err;
@@ -479,19 +468,40 @@
 
 static ssize_t show_pan(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info =
-		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
 			fb_info->var.xoffset);
 }
 
 static ssize_t show_name(struct class_device *class_device, char *buf)
 {
-	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	struct fb_info *fb_info = class_get_devdata(class_device);
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
 }
 
+static ssize_t store_fbstate(struct class_device *class_device,
+			const char *buf, size_t count)
+{
+	struct fb_info *fb_info = class_get_devdata(class_device);
+	u32 state;
+	char *last = NULL;
+
+	state = simple_strtoul(buf, &last, 0);
+
+	acquire_console_sem();
+	fb_set_suspend(fb_info, (int)state);
+	release_console_sem();
+
+	return count;
+}
+
+static ssize_t show_fbstate(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info = class_get_devdata(class_device);
+	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
+}
+
 static struct class_device_attribute class_device_attrs[] = {
 	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
 	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
@@ -507,6 +517,7 @@
 	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
 	__ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate),
 	__ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all),
+	__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
 };
 
 int fb_init_class_device(struct fb_info *fb_info)
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index b37cea7..4e39035 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -42,6 +42,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/vga.h>
 
@@ -107,7 +108,7 @@
 
 /* Framebuffer driver structures */
 
-static struct fb_var_screeninfo hga_default_var = {
+static struct fb_var_screeninfo __initdata hga_default_var = {
 	.xres		= 720,
 	.yres 		= 348,
 	.xres_virtual 	= 720,
@@ -121,7 +122,7 @@
 	.width 		= -1,
 };
 
-static struct fb_fix_screeninfo hga_fix = {
+static struct fb_fix_screeninfo __initdata hga_fix = {
 	.id 		= "HGA",
 	.type 		= FB_TYPE_PACKED_PIXELS,	/* (not sure) */
 	.visual 	= FB_VISUAL_MONO10,
@@ -131,8 +132,6 @@
 	.accel 		= FB_ACCEL_NONE
 };
 
-static struct fb_info fb_info;
-
 /* Don't assume that tty1 will be the initial current console. */
 static int release_io_port = 0;
 static int release_io_ports = 0;
@@ -549,10 +548,9 @@
 	 *  Initialization
 	 */
 
-static int __init hgafb_init(void)
+static int __init hgafb_probe(struct device *device)
 {
-	if (fb_get_options("hgafb", NULL))
-		return -ENODEV;
+	struct fb_info *info;
 
 	if (! hga_card_detect()) {
 		printk(KERN_INFO "hgafb: HGA card not detected.\n");
@@ -564,41 +562,95 @@
 	printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
 		hga_type_name, hga_vram_len/1024);
 
+	info = framebuffer_alloc(0, NULL);
+	if (!info) {
+		iounmap(hga_vram);
+		return -ENOMEM;
+	}
+
 	hga_fix.smem_start = (unsigned long)hga_vram;
 	hga_fix.smem_len = hga_vram_len;
 
-	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	fb_info.var = hga_default_var;
-	fb_info.fix = hga_fix;
-	fb_info.monspecs.hfmin = 0;
-	fb_info.monspecs.hfmax = 0;
-	fb_info.monspecs.vfmin = 10000;
-	fb_info.monspecs.vfmax = 10000;
-	fb_info.monspecs.dpms = 0;
-	fb_info.fbops = &hgafb_ops;
-	fb_info.screen_base = hga_vram;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->var = hga_default_var;
+	info->fix = hga_fix;
+	info->monspecs.hfmin = 0;
+	info->monspecs.hfmax = 0;
+	info->monspecs.vfmin = 10000;
+	info->monspecs.vfmax = 10000;
+	info->monspecs.dpms = 0;
+	info->fbops = &hgafb_ops;
+	info->screen_base = hga_vram;
 
-        if (register_framebuffer(&fb_info) < 0) {
+        if (register_framebuffer(info) < 0) {
+		framebuffer_release(info);
 		iounmap(hga_vram);
 		return -EINVAL;
 	}
 
         printk(KERN_INFO "fb%d: %s frame buffer device\n",
-               fb_info.node, fb_info.fix.id);
+               info->node, info->fix.id);
+	dev_set_drvdata(device, info);
 	return 0;
 }
 
-#ifdef MODULE
-static void __exit hgafb_exit(void)
+static int hgafb_remove(struct device *device)
 {
+	struct fb_info *info = dev_get_drvdata(device);
+
 	hga_txt_mode();
 	hga_clear_screen();
-	unregister_framebuffer(&fb_info);
+
+	if (info) {
+		unregister_framebuffer(info);
+		framebuffer_release(info);
+	}
+
 	iounmap(hga_vram);
-	if (release_io_ports) release_region(0x3b0, 12);
-	if (release_io_port) release_region(0x3bf, 1);
+
+	if (release_io_ports)
+		release_region(0x3b0, 12);
+
+	if (release_io_port)
+		release_region(0x3bf, 1);
+
+	return 0;
 }
-#endif
+
+static struct device_driver hgafb_driver = {
+	.name = "hgafb",
+	.bus  = &platform_bus_type,
+	.probe = hgafb_probe,
+	.remove = hgafb_remove,
+};
+
+static struct platform_device hgafb_device = {
+	.name = "hgafb",
+};
+
+static int __init hgafb_init(void)
+{
+	int ret;
+
+	if (fb_get_options("hgafb", NULL))
+		return -ENODEV;
+
+	ret = driver_register(&hgafb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&hgafb_device);
+		if (ret)
+			driver_unregister(&hgafb_driver);
+	}
+
+	return ret;
+}
+
+static void __exit hgafb_exit(void)
+{
+	platform_device_unregister(&hgafb_device);
+	driver_unregister(&hgafb_driver);
+}
 
 /* -------------------------------------------------------------------------
  *
@@ -613,7 +665,4 @@
 module_param(nologo, bool, 0);
 MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
 module_init(hgafb_init);
-
-#ifdef MODULE
 module_exit(hgafb_exit);
-#endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index c61bad0..bd410e0 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -17,6 +17,7 @@
 #include <linux/fb.h>
 #include "i810.h"
 #include "i810_regs.h"
+#include "i810_main.h"
 #include "../edid.h"
 
 #define I810_DDC 0x50
@@ -42,7 +43,7 @@
 
 static void i810i2c_setscl(void *data, int state)
 {
-        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_i2c_chan    *chan = data;
         struct i810fb_par         *par = chan->par;
 	u8                        __iomem *mmio = par->mmio_start_virtual;
 
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
index 64cd1c8..76764ea 100644
--- a/drivers/video/i810/i810_accel.c
+++ b/drivers/video/i810/i810_accel.c
@@ -14,6 +14,7 @@
 
 #include "i810_regs.h"
 #include "i810.h"
+#include "i810_main.h"
 
 static u32 i810fb_rop[] = {
 	COLOR_COPY_ROP, /* ROP_COPY */
@@ -57,7 +58,7 @@
  */	
 static inline int wait_for_space(struct fb_info *info, u32 space)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 head, count = WAIT_COUNT, tail;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 
@@ -88,7 +89,7 @@
  */
 static inline int wait_for_engine_idle(struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 	int count = WAIT_COUNT;
 
@@ -116,7 +117,7 @@
  */ 
 static inline u32 begin_iring(struct fb_info *info, u32 space)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	if (par->dev_flags & ALWAYS_SYNC) 
 		wait_for_engine_idle(info);
@@ -161,7 +162,7 @@
 				    int xdir, int src, int dest, int rop, 
 				    int blit_bpp, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	if (begin_iring(info, 24 + IRING_PAD)) return;
 
@@ -195,7 +196,7 @@
 			      int rop, int what, int blit_bpp, 
 			      struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	if (begin_iring(info, 24 + IRING_PAD)) return;
 
@@ -236,7 +237,7 @@
 					  int dest, const u32 *src, int bg,
 					  int fg, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
 
@@ -254,7 +255,7 @@
 
 static inline void load_front(int offset, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	if (begin_iring(info, 8 + IRING_PAD)) return;
 
@@ -296,7 +297,7 @@
 
 void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 dx, dy, width, height, dest, rop = 0, color = 0;
 
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -322,7 +323,7 @@
 	
 void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
 
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -361,7 +362,7 @@
 
 void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 fg = 0, bg = 0, size, dst;
 	
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -397,7 +398,7 @@
 
 int i810fb_sync(struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
 		return 0;
@@ -407,7 +408,7 @@
 
 void i810fb_load_front(u32 offset, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
@@ -427,7 +428,7 @@
  */
 void i810fb_init_ringbuffer(struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 tmp1, tmp2;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 	
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
index 64f087a..9743d51 100644
--- a/drivers/video/i810/i810_gtf.c
+++ b/drivers/video/i810/i810_gtf.c
@@ -14,6 +14,7 @@
 
 #include "i810_regs.h"
 #include "i810.h"
+#include "i810_main.h"
 
 /*
  * FIFO and Watermark tables - based almost wholly on i810_wmark.c in 
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index c0c974b..266d0ab 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -42,20 +42,62 @@
 #include <linux/pci_ids.h>
 #include <linux/resource.h>
 #include <linux/unistd.h>
+#include <linux/console.h>
 
 #include <asm/io.h>
 #include <asm/div64.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif 
-
 #include <asm/page.h>
 
 #include "i810_regs.h"
 #include "i810.h"
 #include "i810_main.h"
 
+/*
+ * voffset - framebuffer offset in MiB from aperture start address.  In order for
+ * the driver to work with X, we must try to use memory holes left untouched by X. The
+ * following table lists where X's different surfaces start at.
+ *
+ * ---------------------------------------------
+ * :                :  64 MiB     : 32 MiB      :
+ * ----------------------------------------------
+ * : FrontBuffer    :   0         :  0          :
+ * : DepthBuffer    :   48        :  16         :
+ * : BackBuffer     :   56        :  24         :
+ * ----------------------------------------------
+ *
+ * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
+ * 15 + 1 MiB of Framebuffer memory.  For 32 MiB Aperture sizes, a v_offset of 8 MiB should
+ * work, allowing 7 + 1 MiB of Framebuffer memory.
+ * Note, the size of the hole may change depending on how much memory you allocate to X,
+ * and how the memory is split up between these surfaces.
+ *
+ * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
+ * DRI disabled.  But if the Frontbuffer is overlapped, X will fail to load.
+ *
+ * Experiment with v_offset to find out which works best for you.
+ */
+static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset          __initdata = 0;
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int  __devinit i810fb_init_pci (struct pci_dev *dev,
+				       const struct pci_device_id *entry);
+static void __exit i810fb_remove_pci(struct pci_dev *dev);
+static int i810fb_resume(struct pci_dev *dev);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
+
+/* Chipset Specific Functions */
+static int i810fb_set_par    (struct fb_info *info);
+static int i810fb_getcolreg  (u8 regno, u8 *red, u8 *green, u8 *blue,
+			      u8 *transp, struct fb_info *info);
+static int i810fb_setcolreg  (unsigned regno, unsigned red, unsigned green, unsigned blue,
+			      unsigned transp, struct fb_info *info);
+static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int i810fb_blank      (int blank_mode, struct fb_info *info);
+
+/* Initialization */
+static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
+
 /* PCI */
 static const char *i810_pci_list[] __devinitdata = {
 	"Intel(R) 810 Framebuffer Device"                                 ,
@@ -776,7 +818,7 @@
 
 static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 	u8 red, green, blue, trans, temp;
 
@@ -949,7 +991,7 @@
 static int i810_check_params(struct fb_var_screeninfo *var, 
 			     struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	int line_length, vidmem, mode_valid = 0, retval = 0;
 	u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
 	/*
@@ -1043,7 +1085,7 @@
  */
 static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
     	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
@@ -1154,7 +1196,7 @@
 static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 
 			    u8 *transp, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 	u8 temp;
 
@@ -1193,7 +1235,7 @@
 
 static int i810fb_open(struct fb_info *info, int user)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 count = atomic_read(&par->use_count);
 	
 	if (count == 0) {
@@ -1212,7 +1254,7 @@
 
 static int i810fb_release(struct fb_info *info, int user)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 count;
 	
 	count = atomic_read(&par->use_count);
@@ -1234,7 +1276,7 @@
 			    unsigned blue, unsigned transp, 
 			    struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 	u8 temp;
 	int i;
@@ -1328,7 +1370,7 @@
 static int i810fb_pan_display(struct fb_var_screeninfo *var, 
 			      struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u32 total;
 	
 	total = var->xoffset * par->depth + 
@@ -1340,7 +1382,7 @@
 
 static int i810fb_blank (int blank_mode, struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 	int mode = 0, pwr, scr_off = 0;
 	
@@ -1385,7 +1427,7 @@
 
 static int i810fb_set_par(struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	decode_var(&info->var, par);
 	i810_load_regs(par);
@@ -1429,7 +1471,7 @@
 
 static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	struct i810fb_par *par = (struct i810fb_par *)info->par;
+	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 
 	if (!par->dev_flags & LOCKUP)
@@ -1516,36 +1558,29 @@
 static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
-	int blank = 0, prev_state = par->cur_state;
-
-	if (state.event == prev_state)
-		return 0;
+	struct i810fb_par *par = info->par;
 
 	par->cur_state = state.event;
 
-	switch (state.event) {
-	case 1:
-		blank = VESA_VSYNC_SUSPEND;
-		break;
-	case 2:
-		blank = VESA_HSYNC_SUSPEND;
-		break;
-	case 3:
-		blank = VESA_POWERDOWN;
-		break;
-	default:
-		return -EINVAL;
+	if (state.event == PM_EVENT_FREEZE) {
+		dev->dev.power.power_state = state;
+		return 0;
 	}
-	info->fbops->fb_blank(blank, info);
 
-	if (!prev_state) { 
-		agp_unbind_memory(par->i810_gtt.i810_fb_memory);
-		agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
-		pci_disable_device(dev);
-	}
+	acquire_console_sem();
+	fb_set_suspend(info, 1);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	i810fb_blank(FB_BLANK_POWERDOWN, info);
+	agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+	agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
+
 	pci_save_state(dev);
+	pci_disable_device(dev);
 	pci_set_power_state(dev, pci_choose_state(dev, state));
+	release_console_sem();
 
 	return 0;
 }
@@ -1553,23 +1588,29 @@
 static int i810fb_resume(struct pci_dev *dev) 
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
+	int cur_state = par->cur_state;
 
-	if (par->cur_state == 0)
+	par->cur_state = PM_EVENT_ON;
+
+	if (cur_state == PM_EVENT_FREEZE) {
+		pci_set_power_state(dev, PCI_D0);
 		return 0;
+	}
 
-	pci_restore_state(dev);
+	acquire_console_sem();
 	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
 	pci_enable_device(dev);
+	pci_set_master(dev);
 	agp_bind_memory(par->i810_gtt.i810_fb_memory,
 			par->fb.offset);
 	agp_bind_memory(par->i810_gtt.i810_cursor_memory,
 			par->cursor_heap.offset);
-
+	i810fb_set_par(info);
+	fb_set_suspend (info, 0);
 	info->fbops->fb_blank(VESA_NO_BLANKING, info);
-
-	par->cur_state = 0;
-
+	release_console_sem();
 	return 0;
 }
 /***********************************************************************
@@ -1610,7 +1651,7 @@
 
 static int __devinit i810_alloc_agp_mem(struct fb_info *info)
 {
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 	int size;
 	struct agp_bridge_data *bridge;
 	
@@ -2074,7 +2115,7 @@
 static void __exit i810fb_remove_pci(struct pci_dev *dev)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	struct i810fb_par *par = info->par;
 
 	unregister_framebuffer(info);  
 	i810fb_release_resource(info, par);
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 06072a6..51d4f3d 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -14,55 +14,6 @@
 #ifndef __I810_MAIN_H__
 #define __I810_MAIN_H__
 
-static int  __devinit i810fb_init_pci (struct pci_dev *dev, 
-				       const struct pci_device_id *entry);
-static void __exit i810fb_remove_pci(struct pci_dev *dev);
-static int i810fb_resume(struct pci_dev *dev);
-static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
-
-/*
- * voffset - framebuffer offset in MiB from aperture start address.  In order for
- * the driver to work with X, we must try to use memory holes left untouched by X. The 
- * following table lists where X's different surfaces start at.  
- * 
- * ---------------------------------------------
- * :                :  64 MiB     : 32 MiB      :
- * ----------------------------------------------
- * : FrontBuffer    :   0         :  0          :
- * : DepthBuffer    :   48        :  16         :
- * : BackBuffer     :   56        :  24         :
- * ----------------------------------------------
- *
- * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
- * 15 + 1 MiB of Framebuffer memory.  For 32 MiB Aperture sizes, a v_offset of 8 MiB should
- * work, allowing 7 + 1 MiB of Framebuffer memory.
- * Note, the size of the hole may change depending on how much memory you allocate to X,
- * and how the memory is split up between these surfaces.  
- *
- * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
- * DRI disabled.  But if the Frontbuffer is overlapped, X will fail to load.
- * 
- * Experiment with v_offset to find out which works best for you.
- */
-static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
-static u32 voffset          __initdata = 0;
-
-static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-
-/* Chipset Specific Functions */
-static int i810fb_set_par    (struct fb_info *info);
-static int i810fb_getcolreg  (u8 regno, u8 *red, u8 *green, u8 *blue,
-			      u8 *transp, struct fb_info *info);
-static int i810fb_setcolreg  (unsigned regno, unsigned red, unsigned green, unsigned blue,
-			      unsigned transp, struct fb_info *info);
-static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
-static int i810fb_blank      (int blank_mode, struct fb_info *info);
-
-/* Initialization */
-static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
-extern int __init agp_intel_init(void);
-
-
 /* Video Timings */
 extern void round_off_xres         (u32 *xres);
 extern void round_off_yres         (u32 *xres, u32 *yres);
@@ -101,7 +52,7 @@
 
 /* Conditionals */
 #ifdef CONFIG_X86
-inline void flush_cache(void)
+static inline void flush_cache(void)
 {
 	asm volatile ("wbinvd":::"memory");
 }
@@ -110,7 +61,9 @@
 #endif 
 
 #ifdef CONFIG_MTRR
-#define KERNEL_HAS_MTRR 1
+
+#include <asm/mtrr.h>
+
 static inline void __devinit set_mtrr(struct i810fb_par *par)
 {
 	par->mtrr_reg = mtrr_add((u32) par->aperture.physical, 
@@ -128,7 +81,6 @@
 			 par->aperture.size); 
 }
 #else
-#define KERNEL_HAS_MTRR 0
 #define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
 
 #define unset_mtrr(x) do { } while (0)
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7fbe242..a5d8130 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -323,6 +323,7 @@
 	unsigned long cmap_regs_phys;
 	__u8 *cmap_regs;
 	__u32 ramdac;
+	__u32 palette[16];
 };
  
 enum {
@@ -657,7 +658,7 @@
 static void
 set_imstt_regvals (struct fb_info *info, u_int bpp)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	struct imstt_regvals *init = &par->init;
 	__u32 ctl, pitch, byteswap, scr;
 
@@ -749,7 +750,7 @@
 static inline void
 set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	__u32 off = var->yoffset * (info->fix.line_length >> 3)
 		    + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
 	write_reg_le32(par->dc_regs, SSR, off);
@@ -863,7 +864,7 @@
 static int
 imsttfb_set_par(struct fb_info *info) 
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 		
 	if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
 		return -EINVAL;
@@ -881,7 +882,7 @@
 imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
 		   u_int transp, struct fb_info *info)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	u_int bpp = info->var.bits_per_pixel;
 
 	if (regno > 255)
@@ -905,14 +906,17 @@
 	if (regno < 16)
 		switch (bpp) {
 			case 16:
-				((u16 *)info->pseudo_palette)[regno] = (regno << (info->var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
+				par->palette[regno] =
+					(regno << (info->var.green.length ==
+					5 ? 10 : 11)) | (regno << 5) | regno;
 				break;
 			case 24:
-				((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno;
+				par->palette[regno] =
+					(regno << 16) | (regno << 8) | regno;
 				break;
 			case 32: {
 				int i = (regno << 8) | regno;
-				((u32 *)info->pseudo_palette)[regno] = (i << 16) | i;
+				par->palette[regno] = (i << 16) |i;
 				break;
 			}
 		}
@@ -935,7 +939,7 @@
 static int 
 imsttfb_blank(int blank, struct fb_info *info)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	__u32 ctrl;
 
 	ctrl = read_reg_le32(par->dc_regs, STGCTL);
@@ -989,7 +993,7 @@
 static void
 imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 { 
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
 
 	bgc = rect->color;
@@ -1033,7 +1037,7 @@
 static void
 imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
  	__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
 
@@ -1195,7 +1199,7 @@
 static int 
 imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
         u32 flags = cursor->set, fg, bg, xx, yy;
 
 	if (cursor->dest == NULL && cursor->rop == ROP_XOR)
@@ -1266,7 +1270,7 @@
 imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 	      u_long arg, struct fb_info *info)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	void __user *argp = (void __user *)arg;
 	__u32 reg[2];
 	__u8 idx[2];
@@ -1350,7 +1354,7 @@
 static void __devinit
 init_imstt(struct fb_info *info)
 {
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	__u32 i, tmp, *ip, *end;
 
 	tmp = read_reg_le32(par->dc_regs, PRC);
@@ -1413,7 +1417,7 @@
 	if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
 	    || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
 		printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
-		kfree(info);
+		framebuffer_release(info);
 		return;
 	}
 
@@ -1449,7 +1453,7 @@
 	fb_alloc_cmap(&info->cmap, 0, 0);
 
 	if (register_framebuffer(info) < 0) {
-		kfree(info);
+		framebuffer_release(info);
 		return;
 	}
 
@@ -1474,26 +1478,21 @@
 		printk(KERN_ERR "imsttfb: no OF node for pci device\n");
 #endif /* CONFIG_PPC_OF */
 
-	size = sizeof(struct fb_info) + sizeof(struct imstt_par) +
-		sizeof(u32) * 16;
-
-	info = kmalloc(size, GFP_KERNEL);
+	info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
 
 	if (!info) {
 		printk(KERN_ERR "imsttfb: Can't allocate memory\n");
 		return -ENOMEM;
 	}
 
-	memset(info, 0, size);
-
-	par = (struct imstt_par *) (info + 1);
+	par = info->par;
 
 	addr = pci_resource_start (pdev, 0);
 	size = pci_resource_len (pdev, 0);
 
 	if (!request_mem_region(addr, size, "imsttfb")) {
 		printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
-		kfree(info);
+		framebuffer_release(info);
 		return -ENODEV;
 	}
 
@@ -1516,14 +1515,13 @@
 	}
 
 	info->fix.smem_start = addr;
-	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000);
+	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
+					    0x400000 : 0x800000);
 	info->fix.mmio_start = addr + 0x800000;
 	par->dc_regs = ioremap(addr + 0x800000, 0x1000);
 	par->cmap_regs_phys = addr + 0x840000;
 	par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
-	info->par = par;
-	info->pseudo_palette = (void *) (par + 1);
-	info->device = &pdev->dev;
+	info->pseudo_palette = par->palette;
 	init_imstt(info);
 
 	pci_set_drvdata(pdev, info);
@@ -1534,7 +1532,7 @@
 imsttfb_remove(struct pci_dev *pdev)
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
-	struct imstt_par *par = (struct imstt_par *) info->par;
+	struct imstt_par *par = info->par;
 	int size = pci_resource_len(pdev, 0);
 
 	unregister_framebuffer(info);
@@ -1542,7 +1540,7 @@
 	iounmap(par->dc_regs);
 	iounmap(info->screen_base);
 	release_mem_region(info->fix.smem_start, size);
-	kfree(info);
+	framebuffer_release(info);
 }
 
 #ifndef MODULE
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index 7e33cd30..ab5285a 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/kyro/STG4000InitDevice.c
@@ -15,6 +15,7 @@
 #include <linux/pci.h>
 
 #include "STG4000Reg.h"
+#include "STG4000Interface.h"
 
 /* SDRAM fixed settings */
 #define SDRAM_CFG_0   0x49A1
diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/kyro/STG4000Interface.h
index e75b3b4..b7c83d5 100644
--- a/drivers/video/kyro/STG4000Interface.h
+++ b/drivers/video/kyro/STG4000Interface.h
@@ -11,7 +11,8 @@
 #ifndef _STG4000INTERFACE_H
 #define _STG4000INTERFACE_H
 
-struct pci_dev;
+#include <linux/pci.h>
+#include <video/kyro.h>
 
 /*
  * Ramdac Setup
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c
index 2ae9baf..a8c9713 100644
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ b/drivers/video/kyro/STG4000OverlayDevice.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 
 #include "STG4000Reg.h"
+#include "STG4000Interface.h"
 
 /* HW Defines */
 
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 5eb4d5c..bcd359b 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -73,8 +73,6 @@
 	.vmode		= FB_VMODE_NONINTERLACED,
 };
 
-static struct kyrofb_info *currentpar;
-
 typedef struct {
 	STG4000REG __iomem *pSTGReg;	/* Virtual address of PCI register region */
 	u32 ulNextFreeVidMem;	/* Offset from start of vid mem to next free region */
@@ -309,7 +307,7 @@
 /* Accessors */
 static int kyro_dev_video_mode_set(struct fb_info *info)
 {
-	struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+	struct kyrofb_info *par = info->par;
 
 	/* Turn off display */
 	StopVTG(deviceInfo.pSTGReg);
@@ -402,7 +400,7 @@
 
 static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+	struct kyrofb_info *par = info->par;
 
 	if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
 		printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
@@ -478,7 +476,7 @@
 
 static int kyrofb_set_par(struct fb_info *info)
 {
-	struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+	struct kyrofb_info *par = info->par;
 	unsigned long lineclock;
 	unsigned long frameclock;
 
@@ -536,20 +534,22 @@
 static int kyrofb_setcolreg(u_int regno, u_int red, u_int green,
 			    u_int blue, u_int transp, struct fb_info *info)
 {
+	struct kyrofb_info *par = info->par;
+
 	if (regno > 255)
 		return 1;	/* Invalid register */
 
 	if (regno < 16) {
 		switch (info->var.bits_per_pixel) {
 		case 16:
-			((u16*)(info->pseudo_palette))[regno] =
+			par->palette[regno] =
 			     (red   & 0xf800) |
 			    ((green & 0xfc00) >> 5) |
 			    ((blue  & 0xf800) >> 11);
 			break;
 		case 32:
 			red >>= 8; green >>= 8; blue >>= 8; transp >>= 8;
-			((u32*)(info->pseudo_palette))[regno] =
+			par->palette[regno] =
 			    (transp << 24) | (red << 16) | (green << 8) | blue;
 			break;
 		}
@@ -675,6 +675,7 @@
 				  const struct pci_device_id *ent)
 {
 	struct fb_info *info;
+	struct kyrofb_info *currentpar;
 	unsigned long size;
 	int err;
 
@@ -683,14 +684,11 @@
 		return err;
 	}
 
-	size = sizeof(struct fb_info) + sizeof(struct kyrofb_info) + 16 * sizeof(u32);
-	info = kmalloc(size, GFP_KERNEL);
+	info = framebuffer_alloc(sizeof(struct kyrofb_info), &pdev->dev);
 	if (!info)
 		return -ENOMEM;
 
-	memset(info, 0, size);
-
-	currentpar = (struct kyrofb_info *)(info + 1);
+	currentpar = info->par;
 
 	kyro_fix.smem_start = pci_resource_start(pdev, 0);
 	kyro_fix.smem_len   = pci_resource_len(pdev, 0);
@@ -716,8 +714,7 @@
 
 	info->fbops		= &kyrofb_ops;
 	info->fix		= kyro_fix;
-	info->par		= currentpar;
-	info->pseudo_palette	= (void *)(currentpar + 1);
+	info->pseudo_palette	= currentpar->palette;
 	info->flags		= FBINFO_DEFAULT;
 
 	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
@@ -741,7 +738,6 @@
 
 	fb_memset(info->screen_base, 0, size);
 
-	info->device = &pdev->dev;
 	if (register_framebuffer(info) < 0)
 		goto out_unmap;
 
@@ -757,7 +753,7 @@
 out_unmap:
 	iounmap(currentpar->regbase);
 	iounmap(info->screen_base);
-	kfree(info);
+	framebuffer_release(info);
 
 	return -EINVAL;
 }
@@ -765,7 +761,7 @@
 static void __devexit kyrofb_remove(struct pci_dev *pdev)
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
-	struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+	struct kyrofb_info *par = info->par;
 
 	/* Reset the board */
 	StopVTG(deviceInfo.pSTGReg);
@@ -789,7 +785,7 @@
 
 	unregister_framebuffer(info);
 	pci_set_drvdata(pdev, NULL);
-	kfree(info);
+	framebuffer_release(info);
 }
 
 static int __init kyrofb_init(void)
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index a8c47ad..3a3e180 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -50,8 +50,6 @@
 #include <asm/mtrr.h>
 #endif
 
-#include "../console/fbcon.h"
-
 #if defined(CONFIG_PPC_PMAC)
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -351,8 +349,6 @@
 		      } output;
 };
 
-extern struct display fb_display[];
-
 struct matrox_switch;
 struct matroxfb_driver;
 struct matroxfb_dh_fb_info;
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index 35008af..c122d87 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -20,6 +20,8 @@
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 
+#include "matroxfb_g450.h"
+
 /* Definition of the various controls */
 struct mctl {
 	struct v4l2_queryctrl desc;
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index d9d3e9f..455a46c 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -192,11 +192,8 @@
 	unsigned int wd;
 	unsigned int divider;
 	int i;
-	int fwidth;
 	struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
 
-	fwidth = 8;
-
 	DBG(__FUNCTION__)
 
 	hw->SEQ[0] = 0x00;
@@ -235,10 +232,7 @@
 	hw->ATTR[16] = 0x41;
 	hw->ATTR[17] = 0xFF;
 	hw->ATTR[18] = 0x0F;
-	if (fwidth == 9)
-		hw->ATTR[19] = 0x08;
-	else
-		hw->ATTR[19] = 0x00;
+	hw->ATTR[19] = 0x00;
 	hw->ATTR[20] = 0x00;
 
 	hd = m->HDisplay >> 3;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 8486e77..e18c9f9 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -485,7 +485,7 @@
  */
 static inline int neo2200_sync(struct fb_info *info)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	int waitcycles;
 
 	while (readl(&par->neo2200->bltStat) & 1)
@@ -525,7 +525,7 @@
 static inline void neo2200_accel_init(struct fb_info *info,
 				      struct fb_var_screeninfo *var)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	Neo2200 __iomem *neo2200 = par->neo2200;
 	u32 bltMod, pitch;
 
@@ -560,7 +560,7 @@
 static int
 neofb_open(struct fb_info *info, int user)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	int cnt = atomic_read(&par->ref_count);
 
 	if (!cnt) {
@@ -575,7 +575,7 @@
 static int
 neofb_release(struct fb_info *info, int user)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	int cnt = atomic_read(&par->ref_count);
 
 	if (!cnt)
@@ -590,7 +590,7 @@
 static int
 neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	unsigned int pixclock = var->pixclock;
 	struct xtimings timings;
 	int memlen, vramlen;
@@ -757,7 +757,7 @@
 
 static int neofb_set_par(struct fb_info *info)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	struct xtimings timings;
 	unsigned char temp;
 	int i, clock_hi = 0;
@@ -1216,7 +1216,7 @@
 static void neofb_update_start(struct fb_info *info,
 			       struct fb_var_screeninfo *var)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	struct vgastate *state = &par->state;
 	int oldExtCRTDispAddr;
 	int Base;
@@ -1331,7 +1331,7 @@
 	 *  wms...Enable VESA DPMS compatible powerdown mode
 	 *  run "setterm -powersave powerdown" to take advantage
 	 */
-	struct neofb_par *par = (struct neofb_par *)info->par;
+	struct neofb_par *par = info->par;
 	int seqflags, lcdflags, dpmsflags, reg;
 
 	switch (blank_mode) {
@@ -1404,7 +1404,7 @@
 static void
 neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	u_long dst, rop;
 
 	dst = rect->dx + rect->dy * info->var.xres_virtual;
@@ -1440,7 +1440,7 @@
 neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
 	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	u_long src, dst, bltCntl;
 
 	bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
@@ -1472,7 +1472,7 @@
 static void
 neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	int s_pitch = (image->width * image->depth + 7) >> 3;
 	int scan_align = info->pixmap.scan_align - 1;
 	int buf_align = info->pixmap.buf_align - 1;
@@ -1686,7 +1686,7 @@
 static int __devinit neo_map_mmio(struct fb_info *info,
 				  struct pci_dev *dev)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 
 	DBG("neo_map_mmio");
 
@@ -1733,7 +1733,7 @@
 
 static void neo_unmap_mmio(struct fb_info *info)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 
 	DBG("neo_unmap_mmio");
 
@@ -1796,7 +1796,7 @@
 
 #ifdef CONFIG_MTRR
 	{
-		struct neofb_par *par = (struct neofb_par *) info->par;
+		struct neofb_par *par = info->par;
 
 		mtrr_del(par->mtrr, info->fix.smem_start,
 			 info->fix.smem_len);
@@ -1811,7 +1811,7 @@
 
 static int __devinit neo_scan_monitor(struct fb_info *info)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	unsigned char type, display;
 	int w;
 
@@ -1890,7 +1890,7 @@
 
 static int __devinit neo_init_hw(struct fb_info *info)
 {
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	struct neofb_par *par = info->par;
 	int videoRam = 896;
 	int maxClock = 65000;
 	int CursorMem = 1024;
@@ -2014,7 +2014,7 @@
 	struct fb_info *info;
 	struct neofb_par *par;
 
-	info = framebuffer_alloc(sizeof(struct neofb_par) + sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
 
 	if (!info)
 		return NULL;
@@ -2081,7 +2081,7 @@
 	info->fix.accel = id->driver_data;
 
 	info->fbops = &neofb_ops;
-	info->pseudo_palette = (void *) (par + 1);
+	info->pseudo_palette = par->palette;
 	return info;
 }
 
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index b989358..99c3a8e 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -52,6 +52,7 @@
 #include <linux/pci.h>
 #include "nv_type.h"
 #include "nv_local.h"
+#include "nv_proto.h"
 
 void NVLockUnlock(struct nvidia_par *par, int Lock)
 {
@@ -848,7 +849,7 @@
 		    int width,
 		    int hDisplaySize, int height, int dotClock, int flags)
 {
-	int pixelDepth, VClk;
+	int pixelDepth, VClk = 0;
 	/*
 	 * Save mode parameters.
 	 */
@@ -938,15 +939,24 @@
 
 	if (par->Architecture == NV_ARCH_04) {
 		NV_WR32(par->PFB, 0x0200, state->config);
-	} else if ((par->Chipset & 0xfff0) == 0x0090) {
-		for (i = 0; i < 15; i++) {
-			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
-			NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1);
-		}
-	} else {
+	} else if ((par->Architecture < NV_ARCH_40) ||
+		   (par->Chipset & 0xfff0) == 0x0040) {
 		for (i = 0; i < 8; i++) {
 			NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
-			NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+			NV_WR32(par->PFB, 0x0244 + (i * 0x10),
+				par->FbMapSize - 1);
+		}
+	} else {
+		int regions = 12;
+
+		if (((par->Chipset & 0xfff0) == 0x0090) ||
+		    ((par->Chipset & 0xfff0) == 0x01D0) ||
+		    ((par->Chipset & 0xfff0) == 0x0290))
+			regions = 15;
+		for(i = 0; i < regions; i++) {
+			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0604 + (i * 0x10),
+				par->FbMapSize - 1);
 		}
 	}
 
@@ -1182,11 +1192,17 @@
 			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
 		} else {
 			if (par->Architecture >= NV_ARCH_40) {
+				u32 tmp;
+
 				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
 				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
 				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
 				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
 
+				tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
+				for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
+				NV_WR32(par->PGRAPH, 0x5000, i);
+
 				if ((par->Chipset & 0xfff0) == 0x0040) {
 					NV_WR32(par->PGRAPH, 0x09b0,
 						0x83280fff);
@@ -1211,6 +1227,7 @@
 						0xffff7fff);
 					break;
 				case 0x00C0:
+				case 0x0120:
 					NV_WR32(par->PGRAPH, 0x0828,
 						0x007596ff);
 					NV_WR32(par->PGRAPH, 0x082C,
@@ -1245,6 +1262,7 @@
 						0x00100000);
 					break;
 				case 0x0090:
+				case 0x0290:
 					NV_WR32(par->PRAMDAC, 0x0608,
 						NV_RD32(par->PRAMDAC, 0x0608) |
 						0x00100000);
@@ -1310,14 +1328,44 @@
 				}
 			}
 
-			if ((par->Chipset & 0xfff0) == 0x0090) {
-				for (i = 0; i < 60; i++)
-					NV_WR32(par->PGRAPH, 0x0D00 + i,
-						NV_RD32(par->PFB, 0x0600 + i));
+			if ((par->Architecture < NV_ARCH_40) ||
+			    ((par->Chipset & 0xfff0) == 0x0040)) {
+				for (i = 0; i < 32; i++) {
+					NV_WR32(par->PGRAPH, 0x0900 + i*4,
+						NV_RD32(par->PFB, 0x0240 +i*4));
+					NV_WR32(par->PGRAPH, 0x6900 + i*4,
+						NV_RD32(par->PFB, 0x0240 +i*4));
+				}
 			} else {
-				for (i = 0; i < 32; i++)
-					NV_WR32(par->PGRAPH, 0x0900 + i,
-						NV_RD32(par->PFB, 0x0240 + i));
+				if (((par->Chipset & 0xfff0) == 0x0090) ||
+				    ((par->Chipset & 0xfff0) == 0x01D0) ||
+				    ((par->Chipset & 0xfff0) == 0x0290)) {
+					for (i = 0; i < 60; i++) {
+						NV_WR32(par->PGRAPH,
+							0x0D00 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+						NV_WR32(par->PGRAPH,
+							0x6900 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+					}
+				} else {
+					for (i = 0; i < 48; i++) {
+						NV_WR32(par->PGRAPH,
+							0x0900 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+						if(((par->Chipset & 0xfff0)
+						    != 0x0160) &&
+						   ((par->Chipset & 0xfff0)
+						    != 0x0220))
+							NV_WR32(par->PGRAPH,
+								0x6900 + i*4,
+								NV_RD32(par->PFB,
+									0x0600 + i*4));
+					}
+				}
 			}
 
 			if (par->Architecture >= NV_ARCH_40) {
@@ -1338,7 +1386,9 @@
 					NV_WR32(par->PGRAPH, 0x0868,
 						par->FbMapSize - 1);
 				} else {
-					if((par->Chipset & 0xfff0) == 0x0090) {
+					if ((par->Chipset & 0xfff0) == 0x0090 ||
+					    (par->Chipset & 0xfff0) == 0x01D0 ||
+					    (par->Chipset & 0xfff0) == 0x0290) {
 						NV_WR32(par->PGRAPH, 0x0DF0,
 							NV_RD32(par->PFB, 0x0200));
 						NV_WR32(par->PGRAPH, 0x0DF4,
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 12f2884..bd9eca0 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -46,7 +46,7 @@
 
 static void nvidia_gpio_setsda(void *data, int state)
 {
-	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_i2c_chan *chan = data;
 	struct nvidia_par *par = chan->par;
 	u32 val;
 
@@ -64,7 +64,7 @@
 
 static int nvidia_gpio_getscl(void *data)
 {
-	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_i2c_chan *chan = data;
 	struct nvidia_par *par = chan->par;
 	u32 val = 0;
 
@@ -79,7 +79,7 @@
 
 static int nvidia_gpio_getsda(void *data)
 {
-	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_i2c_chan *chan = data;
 	struct nvidia_par *par = chan->par;
 	u32 val = 0;
 
@@ -136,13 +136,13 @@
 	par->chan[2].par = par;
 
 	par->chan[0].ddc_base = 0x3e;
-	nvidia_setup_i2c_bus(&par->chan[0], "BUS1");
+	nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0");
 
 	par->chan[1].ddc_base = 0x36;
-	nvidia_setup_i2c_bus(&par->chan[1], "BUS2");
+	nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1");
 
 	par->chan[2].ddc_base = 0x50;
-	nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
+	nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2");
 }
 
 void nvidia_delete_i2c_busses(struct nvidia_par *par)
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 3353103..b149a69 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -4,7 +4,7 @@
 #define __NV_PROTO_H__
 
 /* in nv_setup.c */
-void NVCommonSetup(struct fb_info *info);
+int NVCommonSetup(struct fb_info *info);
 void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
 u8 NVReadCrtc(struct nvidia_par *par, u8 index);
 void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 1f06a9f..a18a9ae 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -285,28 +285,34 @@
 			par->CrystalFreqKHz = 27000;
 	}
 
-	par->CursorStart = (par->RamAmountKBytes - 96) * 1024;
 	par->CURSOR = NULL;	/* can't set this here */
 	par->MinVClockFreqKHz = 12000;
 	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
 }
 
-void NVCommonSetup(struct fb_info *info)
+int NVCommonSetup(struct fb_info *info)
 {
 	struct nvidia_par *par = info->par;
-	struct fb_var_screeninfo var;
+	struct fb_var_screeninfo *var;
 	u16 implementation = par->Chipset & 0x0ff0;
 	u8 *edidA = NULL, *edidB = NULL;
-	struct fb_monspecs monitorA, monitorB;
+	struct fb_monspecs *monitorA, *monitorB;
 	struct fb_monspecs *monA = NULL, *monB = NULL;
 	int mobile = 0;
 	int tvA = 0;
 	int tvB = 0;
 	int FlatPanel = -1;	/* really means the CRTC is slaved */
 	int Television = 0;
+	int err = 0;
 
-	memset(&monitorA, 0, sizeof(struct fb_monspecs));
-	memset(&monitorB, 0, sizeof(struct fb_monspecs));
+	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+	monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+	monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+
+	if (!var || !monitorA || !monitorB) {
+		err = -ENOMEM;
+		goto done;
+	}
 
 	par->PRAMIN = par->REGS + (0x00710000 / 4);
 	par->PCRTC0 = par->REGS + (0x00600000 / 4);
@@ -382,6 +388,8 @@
 	case 0x0146:
 	case 0x0147:
 	case 0x0148:
+	case 0x0098:
+	case 0x0099:
 		mobile = 1;
 		break;
 	default:
@@ -406,9 +414,9 @@
 		par->CRTCnumber = 0;
 		if (nvidia_probe_i2c_connector(info, 1, &edidA))
 			nvidia_probe_of_connector(info, 1, &edidA);
-		if (edidA && !fb_parse_edid(edidA, &var)) {
+		if (edidA && !fb_parse_edid(edidA, var)) {
 			printk("nvidiafb: EDID found from BUS1\n");
-			monA = &monitorA;
+			monA = monitorA;
 			fb_edid_to_monspecs(edidA, monA);
 			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
 
@@ -494,17 +502,17 @@
 
 		if (nvidia_probe_i2c_connector(info, 1, &edidA))
 			nvidia_probe_of_connector(info, 1, &edidA);
-		if (edidA && !fb_parse_edid(edidA, &var)) {
+		if (edidA && !fb_parse_edid(edidA, var)) {
 			printk("nvidiafb: EDID found from BUS1\n");
-			monA = &monitorA;
+			monA = monitorA;
 			fb_edid_to_monspecs(edidA, monA);
 		}
 
 		if (nvidia_probe_i2c_connector(info, 2, &edidB))
 			nvidia_probe_of_connector(info, 2, &edidB);
-		if (edidB && !fb_parse_edid(edidB, &var)) {
+		if (edidB && !fb_parse_edid(edidB, var)) {
 			printk("nvidiafb: EDID found from BUS2\n");
-			monB = &monitorB;
+			monB = monitorB;
 			fb_edid_to_monspecs(edidB, monB);
 		}
 
@@ -639,4 +647,9 @@
 
 	kfree(edidA);
 	kfree(edidB);
+done:
+	kfree(var);
+	kfree(monitorA);
+	kfree(monitorB);
+	return err;
 }
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index bee09c6..dbcb896 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -284,6 +284,16 @@
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NVIDIA, 0x0252,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NVIDIA, 0x0313,
@@ -418,6 +428,7 @@
 static int noscale __devinitdata = 0;
 static int paneltweak __devinitdata = 0;
 static int vram __devinitdata = 0;
+static int bpp __devinitdata = 8;
 #ifdef CONFIG_MTRR
 static int nomtrr __devinitdata = 0;
 #endif
@@ -485,7 +496,7 @@
 
 static int nvidia_set_backlight_enable(int on, int level, void *data)
 {
-	struct nvidia_par *par = (struct nvidia_par *)data;
+	struct nvidia_par *par = data;
 	u32 tmp_pcrt, tmp_pmc, fpcontrol;
 
 	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
@@ -1382,24 +1393,36 @@
 				 info->monspecs.modedb_len, &info->modelist);
 	fb_var_to_videomode(&modedb, &nvidiafb_default_var);
 
+	switch (bpp) {
+	case 0 ... 8:
+		bpp = 8;
+		break;
+	case 9 ... 16:
+		bpp = 16;
+		break;
+	default:
+		bpp = 32;
+		break;
+	}
+
 	if (specs->modedb != NULL) {
 		struct fb_videomode *modedb;
 
 		modedb = fb_find_best_display(specs, &info->modelist);
 		fb_videomode_to_var(&nvidiafb_default_var, modedb);
-		nvidiafb_default_var.bits_per_pixel = 8;
+		nvidiafb_default_var.bits_per_pixel = bpp;
 	} else if (par->fpWidth && par->fpHeight) {
 		char buf[16];
 
 		memset(buf, 0, 16);
 		snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
 		fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
-			     specs->modedb_len, &modedb, 8);
+			     specs->modedb_len, &modedb, bpp);
 	}
 
 	if (mode_option)
 		fb_find_mode(&nvidiafb_default_var, info, mode_option,
-			     specs->modedb, specs->modedb_len, &modedb, 8);
+			     specs->modedb, specs->modedb_len, &modedb, bpp);
 
 	info->var = nvidiafb_default_var;
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
@@ -1448,11 +1471,34 @@
 	return nvidiafb_check_var(&info->var, info);
 }
 
-static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+static u32 __devinit nvidia_get_chipset(struct fb_info *info)
 {
+	struct nvidia_par *par = info->par;
+	u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
+
+	printk("nvidiafb: PCI id - %x\n", id);
+	if ((id & 0xfff0) == 0x00f0) {
+		/* pci-e */
+		printk("nvidiafb: PCI-E card\n");
+		id = NV_RD32(par->REGS, 0x1800);
+
+		if ((id & 0x0000ffff) == 0x000010DE)
+			id = 0x10DE0000 | (id >> 16);
+		else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
+			id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
+                            ((id >> 8) & 0x000000ff);
+	}
+
+	printk("nvidiafb: Actual id - %x\n", id);
+	return id;
+}
+
+static u32 __devinit nvidia_get_arch(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
 	u32 arch = 0;
 
-	switch (pd->device & 0x0ff0) {
+	switch (par->Chipset & 0x0ff0) {
 	case 0x0100:		/* GeForce 256 */
 	case 0x0110:		/* GeForce2 MX */
 	case 0x0150:		/* GeForce2 */
@@ -1485,6 +1531,8 @@
 	case 0x0210:
 	case 0x0220:
 	case 0x0230:
+	case 0x0290:
+	case 0x0390:
 		arch = NV_ARCH_40;
 		break;
 	case 0x0020:		/* TNT, TNT2 */
@@ -1513,7 +1561,7 @@
 	if (!info)
 		goto err_out;
 
-	par = (struct nvidia_par *)info->par;
+	par = info->par;
 	par->pci_dev = pd;
 
 	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -1533,18 +1581,6 @@
 		goto err_out_request;
 	}
 
-	par->Architecture = nvidia_get_arch(pd);
-
-	par->Chipset = (pd->vendor << 16) | pd->device;
-	printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
-
-	if (par->Architecture == 0) {
-		printk(KERN_ERR PFX "unknown NV_ARCH\n");
-		goto err_out_free_base0;
-	}
-
-	sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
-
 	par->FlatPanel = flatpanel;
 	if (flatpanel == 1)
 		printk(KERN_INFO PFX "flatpanel support enabled\n");
@@ -1570,7 +1606,19 @@
 		goto err_out_free_base0;
 	}
 
-	NVCommonSetup(info);
+	par->Chipset = nvidia_get_chipset(info);
+	printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
+	par->Architecture = nvidia_get_arch(info);
+
+	if (par->Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		goto err_out_arch;
+	}
+
+	sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+	if (NVCommonSetup(info))
+		goto err_out_arch;
 
 	par->FbAddress = nvidiafb_fix.smem_start;
 	par->FbMapSize = par->RamAmountKBytes * 1024;
@@ -1581,10 +1629,15 @@
 	if (par->FbMapSize > 64 * 1024 * 1024)
 		par->FbMapSize = 64 * 1024 * 1024;
 
-	par->FbUsableSize = par->FbMapSize - (128 * 1024);
+	if(par->Architecture >= NV_ARCH_40)
+  	        par->FbUsableSize = par->FbMapSize - (560 * 1024);
+	else
+		par->FbUsableSize = par->FbMapSize - (128 * 1024);
 	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
 	    16 * 1024;
 	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+	par->CursorStart = par->FbUsableSize + (32 * 1024);
+
 	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
 	info->screen_size = par->FbUsableSize;
 	nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
@@ -1640,21 +1693,22 @@
 	NVTRACE_LEAVE();
 	return 0;
 
-      err_out_iounmap_fb:
+err_out_iounmap_fb:
 	iounmap(info->screen_base);
-      err_out_free_base1:
+err_out_free_base1:
 	fb_destroy_modedb(info->monspecs.modedb);
 	nvidia_delete_i2c_busses(par);
+err_out_arch:
 	iounmap(par->REGS);
-      err_out_free_base0:
+err_out_free_base0:
 	pci_release_regions(pd);
-      err_out_request:
+err_out_request:
 	pci_disable_device(pd);
-      err_out_enable:
+err_out_enable:
 	kfree(info->pixmap.addr);
-      err_out_kfree:
+err_out_kfree:
 	framebuffer_release(info);
-      err_out:
+err_out:
 	return -ENODEV;
 }
 
@@ -1729,6 +1783,8 @@
 #endif
 		} else if (!strncmp(this_opt, "fpdither:", 9)) {
 			fpdither = simple_strtol(this_opt+9, NULL, 0);
+		} else if (!strncmp(this_opt, "bpp:", 4)) {
+			bpp = simple_strtoul(this_opt+4, NULL, 0);
 		} else
 			mode_option = this_opt;
 	}
@@ -1804,6 +1860,11 @@
 MODULE_PARM_DESC(vram,
 		 "amount of framebuffer memory to remap in MiB"
 		 "(default=0 - remap entire memory)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
+module_param(bpp, int, 0);
+MODULE_PARM_DESC(bpp, "pixel width in bits"
+		 "(default=8)");
 #ifdef CONFIG_MTRR
 module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 0277ce0..5fe1979 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -91,6 +91,7 @@
 	u32		mem_config;	/* MemConfig reg at probe */
 	u32		mem_control;	/* MemControl reg at probe */
 	u32		boot_address;	/* BootAddress reg at probe */
+	u32             palette[16];
 };
 
 /*
@@ -674,7 +675,7 @@
  */
 static int pm2fb_set_par(struct fb_info *info)
 {
-	struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+	struct pm2fb_par *par = info->par;
 	u32 pixclock;
 	u32 width, height, depth;
 	u32 hsstart, hsend, hbend, htotal;
@@ -854,7 +855,7 @@
 			   unsigned blue, unsigned transp,
 			   struct fb_info *info)
 {
-	struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+	struct pm2fb_par *par = info->par;
 
 	if (regno >= info->cmap.len)  /* no. of hw registers */
 		return 1;
@@ -929,7 +930,7 @@
    		case 16:
 		case 24:
 		case 32:	
-           		((u32*)(info->pseudo_palette))[regno] = v;
+           		par->palette[regno] = v;
 			break;
 		}
 		return 0;
@@ -955,7 +956,7 @@
 static int pm2fb_pan_display(struct fb_var_screeninfo *var,
 			     struct fb_info *info)
 {
-	struct pm2fb_par *p = (struct pm2fb_par *) info->par;
+	struct pm2fb_par *p = info->par;
 	u32 base;
 	u32 depth;
 	u32 xres;
@@ -987,7 +988,7 @@
  */
 static int pm2fb_blank(int blank_mode, struct fb_info *info)
 {
-	struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+	struct pm2fb_par *par = info->par;
 	u32 video = par->video;
 
 	DPRINTK("blank_mode %d\n", blank_mode);
@@ -1054,8 +1055,7 @@
 {
 	struct pm2fb_par *default_par;
 	struct fb_info *info;
-	int size, err;
-	int err_retval = -ENXIO;
+	int err, err_retval = -ENXIO;
 
 	err = pci_enable_device(pdev);
 	if ( err ) {
@@ -1063,11 +1063,10 @@
 		return err;
 	}
 
-	size = sizeof(struct pm2fb_par) + 256 * sizeof(u32);
-	info = framebuffer_alloc(size, &pdev->dev);
+	info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
 	if ( !info )
 		return -ENOMEM;
-	default_par = (struct pm2fb_par *) info->par;
+	default_par = info->par;
 
 	switch (pdev->device) {
 	case  PCI_DEVICE_ID_TI_TVP4020:
@@ -1171,7 +1170,7 @@
 
 	info->fbops		= &pm2fb_ops;
 	info->fix		= pm2fb_fix; 	
-	info->pseudo_palette	= (void *)(default_par + 1); 
+	info->pseudo_palette	= default_par->palette;
 	info->flags		= FBINFO_DEFAULT |
                                   FBINFO_HWACCEL_YPAN;
 
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9f96e..6c19ab6 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -630,7 +630,7 @@
 	int bpp, width, hDisplaySize, hDisplay, hStart,
 	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
 	int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	struct riva_regs newmode;
 	
 	NVTRACE_ENTER();
@@ -925,7 +925,7 @@
 
 static void riva_setup_accel(struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 
 	RIVA_FIFO_FREE(par->riva, Clip, 2);
 	NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
@@ -979,7 +979,7 @@
 #ifdef CONFIG_PMAC_BACKLIGHT
 static int riva_set_backlight_enable(int on, int level, void *data)
 {
-	struct riva_par *par = (struct riva_par *)data;
+	struct riva_par *par = data;
 	U032 tmp_pcrt, tmp_pmc;
 
 	tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
@@ -1008,7 +1008,7 @@
 
 static int rivafb_open(struct fb_info *info, int user)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	int cnt = atomic_read(&par->ref_count);
 
 	NVTRACE_ENTER();
@@ -1034,7 +1034,7 @@
 
 static int rivafb_release(struct fb_info *info, int user)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	int cnt = atomic_read(&par->ref_count);
 
 	NVTRACE_ENTER();
@@ -1057,7 +1057,7 @@
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct fb_videomode *mode;
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
 	
@@ -1166,7 +1166,7 @@
 
 static int rivafb_set_par(struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 
 	NVTRACE_ENTER();
 	/* vgaHWunlock() + riva unlock (0x7F) */
@@ -1205,43 +1205,19 @@
 static int rivafb_pan_display(struct fb_var_screeninfo *var,
 			      struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *)info->par;
+	struct riva_par *par = info->par;
 	unsigned int base;
 
 	NVTRACE_ENTER();
-	if (var->xoffset > (var->xres_virtual - var->xres))
-		return -EINVAL;
-	if (var->yoffset > (var->yres_virtual - var->yres))
-		return -EINVAL;
-
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0
-		    || var->yoffset >= info->var.yres_virtual
-		    || var->xoffset) return -EINVAL;
-	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
-	}
-
 	base = var->yoffset * info->fix.line_length + var->xoffset;
-
 	par->riva.SetStartAddress(&par->riva, base);
-
-	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;
 	NVTRACE_LEAVE();
 	return 0;
 }
 
 static int rivafb_blank(int blank, struct fb_info *info)
 {
-	struct riva_par *par= (struct riva_par *)info->par;
+	struct riva_par *par= info->par;
 	unsigned char tmp, vesa;
 
 	tmp = SEQin(par, 0x01) & ~0x20;	/* screen on/off */
@@ -1304,7 +1280,7 @@
 			  unsigned blue, unsigned transp,
 			  struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *)info->par;
+	struct riva_par *par = info->par;
 	RIVA_HW_INST *chip = &par->riva;
 	int i;
 
@@ -1393,7 +1369,7 @@
  */
 static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	u_int color, rop = 0;
 
 	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
@@ -1449,7 +1425,7 @@
  */
 static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 
 	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
 		cfb_copyarea(info, region);
@@ -1495,7 +1471,7 @@
 static void rivafb_imageblit(struct fb_info *info, 
 			     const struct fb_image *image)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	u32 fgx = 0, bgx = 0, width, tmp;
 	u8 *cdat = (u8 *) image->data;
 	volatile u32 __iomem *d;
@@ -1580,7 +1556,7 @@
  */
 static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	u8 data[MAX_CURS * MAX_CURS/8];
 	int i, set = cursor->set;
 	u16 fg, bg;
@@ -1664,7 +1640,7 @@
 
 static int rivafb_sync(struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *)info->par;
+	struct riva_par *par = info->par;
 
 	wait_for_idle(par);
 	return 0;
@@ -1696,7 +1672,7 @@
 static int __devinit riva_set_fbinfo(struct fb_info *info)
 {
 	unsigned int cmap_len;
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 
 	NVTRACE_ENTER();
 	info->flags = FBINFO_DEFAULT
@@ -1733,7 +1709,7 @@
 #ifdef CONFIG_PPC_OF
 static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	struct device_node *dp;
 	unsigned char *pedid = NULL;
 	unsigned char *disptype = NULL;
@@ -1767,7 +1743,7 @@
 #if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
 static int __devinit riva_get_EDID_i2c(struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	struct fb_var_screeninfo var;
 	int i;
 
@@ -1837,7 +1813,7 @@
 static void __devinit riva_get_edidinfo(struct fb_info *info)
 {
 	struct fb_var_screeninfo *var = &rivafb_default_var;
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 
 	fb_edid_to_monspecs(par->EDID, &info->monspecs);
 	fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
@@ -1909,7 +1885,7 @@
 		ret = -ENOMEM;
 		goto err_ret;
 	}
-	default_par = (struct riva_par *) info->par;
+	default_par = info->par;
 	default_par->pdev = pd;
 
 	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -2070,7 +2046,7 @@
 
 err_iounmap_screen_base:
 #ifdef CONFIG_FB_RIVA_I2C
-	riva_delete_i2c_busses((struct riva_par *) info->par);
+	riva_delete_i2c_busses(info->par);
 #endif
 	iounmap(info->screen_base);
 err_iounmap_pramin:
@@ -2093,7 +2069,7 @@
 static void __exit rivafb_remove(struct pci_dev *pd)
 {
 	struct fb_info *info = pci_get_drvdata(pd);
-	struct riva_par *par = (struct riva_par *) info->par;
+	struct riva_par *par = info->par;
 	
 	NVTRACE_ENTER();
 	if (!info)
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index 77151d8..8b1967f 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -30,7 +30,7 @@
 
 static void riva_gpio_setscl(void* data, int state)
 {
-	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_i2c_chan 	*chan = data;
 	struct riva_par 	*par = chan->par;
 	u32			val;
 
@@ -48,7 +48,7 @@
 
 static void riva_gpio_setsda(void* data, int state)
 {
-	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_i2c_chan 	*chan = data;
 	struct riva_par 	*par = chan->par;
 	u32			val;
 
@@ -66,7 +66,7 @@
 
 static int riva_gpio_getscl(void* data)
 {
-	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_i2c_chan 	*chan = data;
 	struct riva_par 	*par = chan->par;
 	u32			val = 0;
 
@@ -81,7 +81,7 @@
 
 static int riva_gpio_getsda(void* data)
 {
-	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_i2c_chan 	*chan = data;
 	struct riva_par 	*par = chan->par;
 	u32			val = 0;
 
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index fe99d17..d574dd3 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -552,7 +552,7 @@
  * s3c2410fb_init_registers - Initialise all LCD-related registers
  */
 
-int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
 {
 	unsigned long flags;
 
@@ -634,7 +634,7 @@
 
 static char driver_name[]="s3c2410fb";
 
-int __init s3c2410fb_probe(struct platform_device *pdev)
+static int __init s3c2410fb_probe(struct platform_device *pdev)
 {
 	struct s3c2410fb_info *info;
 	struct fb_info	   *fbinfo;
@@ -667,8 +667,6 @@
 	info->fb = fbinfo;
 	platform_set_drvdata(pdev, fbinfo);
 
-	s3c2410fb_init_registers(info);
-
 	dprintk("devinit\n");
 
 	strcpy(fbinfo->fix.id, driver_name);
@@ -701,8 +699,8 @@
 	fbinfo->var.yres_virtual    = mach_info->yres.defval;
 	fbinfo->var.bits_per_pixel  = mach_info->bpp.defval;
 
-	fbinfo->var.upper_margin    = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) +1;
-	fbinfo->var.lower_margin    = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) +1;
+	fbinfo->var.upper_margin    = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1;
+	fbinfo->var.lower_margin    = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) + 1;
 	fbinfo->var.vsync_len	    = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
 
 	fbinfo->var.left_margin	    = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 3c98457..00719a9 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -49,7 +49,7 @@
 
 static void savage4_gpio_setscl(void *data, int val)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 	unsigned int r;
 
 	r = readl(chan->ioaddr + chan->reg);
@@ -63,7 +63,7 @@
 
 static void savage4_gpio_setsda(void *data, int val)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 
 	unsigned int r;
 	r = readl(chan->ioaddr + chan->reg);
@@ -77,21 +77,21 @@
 
 static int savage4_gpio_getscl(void *data)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 
 	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
 }
 
 static int savage4_gpio_getsda(void *data)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 
 	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
 }
 
 static void prosavage_gpio_setscl(void* data, int val)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 	u32			  r;
 
 	SET_CR_IX(chan->ioaddr, chan->reg);
@@ -107,7 +107,7 @@
 
 static void prosavage_gpio_setsda(void* data, int val)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 	unsigned int r;
 
 	SET_CR_IX(chan->ioaddr, chan->reg);
@@ -123,7 +123,7 @@
 
 static int prosavage_gpio_getscl(void* data)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 
 	SET_CR_IX(chan->ioaddr, chan->reg);
 	return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN));
@@ -131,7 +131,7 @@
 
 static int prosavage_gpio_getsda(void* data)
 {
-	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	struct savagefb_i2c_chan *chan = data;
 
 	SET_CR_IX(chan->ioaddr, chan->reg);
 	return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
@@ -140,10 +140,9 @@
 static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
 				const char *name)
 {
-	int (*add_bus)(struct i2c_adapter *) = symbol_get(i2c_bit_add_bus);
 	int rc = 0;
 
-	if (add_bus && chan->par) {
+	if (chan->par) {
 		strcpy(chan->adapter.name, name);
 		chan->adapter.owner		= THIS_MODULE;
 		chan->adapter.id		= I2C_HW_B_SAVAGE;
@@ -161,7 +160,7 @@
 		chan->algo.setscl(chan, 1);
 		udelay(20);
 
-		rc = add_bus(&chan->adapter);
+		rc = i2c_bit_add_bus(&chan->adapter);
 
 		if (rc == 0)
 			dev_dbg(&chan->par->pcidev->dev,
@@ -169,8 +168,6 @@
 		else
 			dev_warn(&chan->par->pcidev->dev,
 				 "Failed to register I2C bus %s.\n", name);
-
-		symbol_put(i2c_bit_add_bus);
 	} else
 		chan->par = NULL;
 
@@ -179,7 +176,7 @@
 
 void savagefb_create_i2c_busses(struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	par->chan.par	= par;
 
 	switch(info->fix.accel) {
@@ -193,6 +190,7 @@
 		par->chan.algo.getscl = prosavage_gpio_getscl;
 		break;
 	case FB_ACCEL_SAVAGE4:
+	case FB_ACCEL_SAVAGE2000:
 		par->chan.reg         = 0xff20;
 		par->chan.ioaddr      = par->mmio.vbase;
 		par->chan.algo.setsda = savage4_gpio_setsda;
@@ -209,14 +207,10 @@
 
 void savagefb_delete_i2c_busses(struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	int (*del_bus)(struct i2c_adapter *) =
-		symbol_get(i2c_bit_del_bus);
+	struct savagefb_par *par = info->par;
 
-	if (del_bus && par->chan.par) {
-		del_bus(&par->chan.adapter);
-		symbol_put(i2c_bit_del_bus);
-	}
+	if (par->chan.par)
+		i2c_bit_del_bus(&par->chan.adapter);
 
 	par->chan.par = NULL;
 }
@@ -224,8 +218,6 @@
 static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
 {
 	u8 start = 0x0;
-	int (*transfer)(struct i2c_adapter *, struct i2c_msg *, int) =
-		symbol_get(i2c_transfer);
 	struct i2c_msg msgs[] = {
 		{
 			.addr	= SAVAGE_DDC,
@@ -239,21 +231,19 @@
 	};
 	u8 *buf = NULL;
 
-	if (transfer && chan->par) {
+	if (chan->par) {
 		buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
 
 		if (buf) {
 			msgs[1].buf = buf;
 
-			if (transfer(&chan->adapter, msgs, 2) != 2) {
+			if (i2c_transfer(&chan->adapter, msgs, 2) != 2) {
 				dev_dbg(&chan->par->pcidev->dev,
 					"Unable to read EDID block.\n");
 				kfree(buf);
 				buf = NULL;
 			}
 		}
-
-		symbol_put(i2c_transfer);
 	}
 
 	return buf;
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
index bac8ea3..bbcc055 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/savage/savagefb_accel.c
@@ -21,7 +21,7 @@
 
 int savagefb_sync(struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 
 	par->SavageWaitIdle(par);
 	return 0;
@@ -29,7 +29,7 @@
 
 void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	int sx = region->sx, dx = region->dx;
 	int sy = region->sy, dy = region->dy;
 	int cmd;
@@ -63,7 +63,7 @@
 
 void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	int cmd, color;
 
 	if (!rect->width || !rect->height)
@@ -90,7 +90,7 @@
 
 void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	int fg, bg, size, i, width;
 	int cmd;
 	u32 *src = (u32 *) image->data;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 09e2f28..ab727ea 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -686,7 +686,7 @@
 static int savagefb_check_var (struct fb_var_screeninfo   *var,
 			       struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	int memlen, vramlen, mode_valid = 0;
 
 	DBG("savagefb_check_var");
@@ -1025,7 +1025,7 @@
 			      unsigned        transp,
 			      struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 
 	if (regno >= NR_PALETTE)
 		return -EINVAL;
@@ -1328,7 +1328,7 @@
 #if defined(CONFIG_FB_SAVAGE_ACCEL)
 static void savagefb_set_clip(struct fb_info *info)
 {
-    struct savagefb_par *par = (struct savagefb_par *)info->par;
+    struct savagefb_par *par = info->par;
     int cmd;
 
     cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
@@ -1342,7 +1342,7 @@
 
 static int savagefb_set_par (struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	struct fb_var_screeninfo *var = &info->var;
 	int err;
 
@@ -1381,29 +1381,9 @@
 static int savagefb_pan_display (struct fb_var_screeninfo *var,
 				 struct fb_info           *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	u_int y_bottom;
-
-	y_bottom = var->yoffset;
-
-	if (!(var->vmode & FB_VMODE_YWRAP))
-		y_bottom += var->yres;
-
-	if (var->xoffset > (var->xres_virtual - var->xres))
-		return -EINVAL;
-	if (y_bottom > info->var.yres_virtual)
-		return -EINVAL;
+	struct savagefb_par *par = info->par;
 
 	savagefb_update_start (par, var);
-
-	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;
 }
 
@@ -1534,7 +1514,7 @@
 
 static int __devinit savage_map_mmio (struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	DBG ("savage_map_mmio");
 
 	if (S3_SAVAGE3D_SERIES (par->chip))
@@ -1567,7 +1547,7 @@
 
 static void __devinit savage_unmap_mmio (struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	DBG ("savage_unmap_mmio");
 
 	savage_disable_mmio(par);
@@ -1581,7 +1561,7 @@
 static int __devinit savage_map_video (struct fb_info *info,
 				       int video_len)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	int resource;
 
 	DBG("savage_map_video");
@@ -1619,7 +1599,7 @@
 
 static void __devinit savage_unmap_video (struct fb_info *info)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 
 	DBG("savage_unmap_video");
 
@@ -1869,7 +1849,7 @@
 					  struct pci_dev *dev,
 					  const struct pci_device_id *id)
 {
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct savagefb_par *par = info->par;
 	int err = 0;
 
 	par->pcidev  = dev;
@@ -2139,8 +2119,7 @@
 
 static void __devexit savagefb_remove (struct pci_dev *dev)
 {
-	struct fb_info *info =
-		(struct fb_info *)pci_get_drvdata(dev);
+	struct fb_info *info = pci_get_drvdata(dev);
 
 	DBG("savagefb_remove");
 
@@ -2174,9 +2153,8 @@
 
 static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
 {
-	struct fb_info *info =
-		(struct fb_info *)pci_get_drvdata(dev);
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct savagefb_par *par = info->par;
 
 	DBG("savagefb_suspend");
 
@@ -2210,9 +2188,8 @@
 
 static int savagefb_resume (struct pci_dev* dev)
 {
-	struct fb_info *info =
-		(struct fb_info *)pci_get_drvdata(dev);
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct savagefb_par *par = info->par;
 	int cur_state = par->pm_state;
 
 	DBG("savage_resume");
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a01e7ecc..9b70777 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -115,7 +115,8 @@
     /*
      *  If your driver supports multiple boards or it supports multiple 
      *  framebuffers, you should make these arrays, or allocate them 
-     *  dynamically (using kmalloc()). 
+     *  dynamically using framebuffer_alloc() and free them with
+     *  framebuffer_release().
      */ 
 static struct fb_info info;
 
@@ -179,18 +180,31 @@
  *	intent to only test a mode and not actually set it. The stuff in 
  *	modedb.c is a example of this. If the var passed in is slightly 
  *	off by what the hardware can support then we alter the var PASSED in
- *	to what we can do. If the hardware doesn't support mode change 
- * 	a -EINVAL will be returned by the upper layers. You don't need to 
- *	implement this function then. If you hardware doesn't support 
- *	changing the resolution then this function is not needed. In this
- *	case the driver woudl just provide a var that represents the static
- *	state the screen is in.
+ *	to what we can do.
+ *
+ *      For values that are off, this function must round them _up_ to the
+ *      next value that is supported by the hardware.  If the value is
+ *      greater than the highest value supported by the hardware, then this
+ *      function must return -EINVAL.
+ *
+ *      Exception to the above rule:  Some drivers have a fixed mode, ie,
+ *      the hardware is already set at boot up, and cannot be changed.  In
+ *      this case, it is more acceptable that this function just return
+ *      a copy of the currently working var (info->var). Better is to not
+ *      implement this function, as the upper layer will do the copying
+ *      of the current var for you.
+ *
+ *      Note:  This is the only function where the contents of var can be
+ *      freely adjusted after the driver has been registered. If you find
+ *      that you have code outside of this function that alters the content
+ *      of var, then you are doing something wrong.  Note also that the
+ *      contents of info->var must be left untouched at all times after
+ *      driver registration.
  *
  *	Returns negative errno on error, or zero on success.
  */
 static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-    const struct xxx_par *par = (const struct xxx_par *) info->par;
     /* ... */
     return 0;	   	
 }
@@ -204,14 +218,39 @@
  *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in 
  *	fb_info since we are using that data. This means we depend on the
  *	data in var inside fb_info to be supported by the hardware. 
- *	xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ *
+ *      This function is also used to recover/restore the hardware to a
+ *      known working state.
+ *
+ *	xxxfb_check_var is always called before xxxfb_set_par to ensure that
+ *      the contents of var is always valid.
+ *
  *	Again if you can't change the resolution you don't need this function.
  *
+ *      However, even if your hardware does not support mode changing,
+ *      a set_par might be needed to at least initialize the hardware to
+ *      a known working state, especially if it came back from another
+ *      process that also modifies the same hardware, such as X.
+ *
+ *      If this is the case, a combination such as the following should work:
+ *
+ *      static int xxxfb_check_var(struct fb_var_screeninfo *var,
+ *                                struct fb_info *info)
+ *      {
+ *              *var = info->var;
+ *              return 0;
+ *      }
+ *
+ *      static int xxxfb_set_par(struct fb_info *info)
+ *      {
+ *              init your hardware here
+ *      }
+ *
  *	Returns negative errno on error, or zero on success.
  */
 static int xxxfb_set_par(struct fb_info *info)
 {
-    struct xxx_par *par = (struct xxx_par *) info->par;
+    struct xxx_par *par = info->par;
     /* ... */
     return 0;	
 }
@@ -258,70 +297,110 @@
      *   var->{color}.offset contains start of bitfield
      *   var->{color}.length contains length of bitfield
      *   {hardwarespecific} contains width of DAC
-     *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+     *   pseudo_palette[X] is programmed to (X << red.offset) |
+     *                                      (X << green.offset) |
+     *                                      (X << blue.offset)
      *   RAMDAC[X] is programmed to (red, green, blue)
+     *   color depth = SUM(var->{color}.length)
      *
      * Pseudocolor:
-     *    uses offset = 0 && length = DAC register width.
      *    var->{color}.offset is 0
-     *    var->{color}.length contains widht of DAC
-     *    cmap is not used
-     *    DAC[X] is programmed to (red, green, blue)
+     *    var->{color}.length contains width of DAC or the number of unique
+     *                        colors available (color depth)
+     *    pseudo_palette is not used
+     *    RAMDAC[X] is programmed to (red, green, blue)
+     *    color depth = var->{color}.length
+     *
+     * Static pseudocolor:
+     *    same as Pseudocolor, but the RAMDAC is not programmed (read-only)
+     *
+     * Mono01/Mono10:
+     *    Has only 2 values, black on white or white on black (fg on bg),
+     *    var->{color}.offset is 0
+     *    white = (1 << var->{color}.length) - 1, black = 0
+     *    pseudo_palette is not used
+     *    RAMDAC does not exist
+     *    color depth is always 2
+     *
      * Truecolor:
      *    does not use RAMDAC (usually has 3 of them).
      *    var->{color}.offset contains start of bitfield
      *    var->{color}.length contains length of bitfield
-     *    cmap is programmed to (red << red.offset) | (green << green.offset) |
-     *                      (blue << blue.offset) | (transp << transp.offset)
+     *    pseudo_palette is programmed to (red << red.offset) |
+     *                                    (green << green.offset) |
+     *                                    (blue << blue.offset) |
+     *                                    (transp << transp.offset)
      *    RAMDAC does not exist
+     *    color depth = SUM(var->{color}.length})
+     *
+     *  The color depth is used by fbcon for choosing the logo and also
+     *  for color palette transformation if color depth < 4
+     *
+     *  As can be seen from the above, the field bits_per_pixel is _NOT_
+     *  a criteria for describing the color visual.
+     *
+     *  A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor,
+     *  and higher than that, true/directcolor.  This is incorrect, one needs
+     *  to look at the fix->visual.
+     *
+     *  Another common mistake is using bits_per_pixel to calculate the color
+     *  depth.  The bits_per_pixel field does not directly translate to color
+     *  depth. You have to compute for the color depth (using the color
+     *  bitfields) and fix->visual as seen above.
+     */
+
+    /*
+     * This is the point where the color is converted to something that
+     * is acceptable by the hardware.
      */
 #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:
-	       /* example here assumes 8 bit DAC. Might be different 
-		* for your hardware */	
-               red = CNVT_TOHW(red, 8);       
-               green = CNVT_TOHW(green, 8);
-               blue = CNVT_TOHW(blue, 8);
-               /* hey, there is bug in transp handling... */
-               transp = CNVT_TOHW(transp, 8);
-               break;
-    }
+    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);
 #undef CNVT_TOHW
-    /* Truecolor has hardware independent palette */
-    if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-       u32 v;
+    /*
+     * This is the point where the function feeds the color to the hardware
+     * palette after converting the colors to something acceptable by
+     * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and
+     * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette.
+     * If you have code that writes to the hardware CLUT, and it's not
+     * any of the above visuals, then you are doing something wrong.
+     */
+    if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
+	info->fix.visual == FB_VISUAL_TRUECOLOR)
+	    write_{red|green|blue|transp}_to_clut();
 
-       if (regno >= 16)
-           return -EINVAL;
+    /* This is the point were you need to fill up the contents of
+     * info->pseudo_palette. This structure is used _only_ by fbcon, thus
+     * it only contains 16 entries to match the number of colors supported
+     * by the console. The pseudo_palette is used only if the visual is
+     * in directcolor or truecolor mode.  With other visuals, the
+     * pseudo_palette is not used. (This might change in the future.)
+     *
+     * The contents of the pseudo_palette is in raw pixel format.  Ie, each
+     * entry can be written directly to the framebuffer without any conversion.
+     * The pseudo_palette is (void *).  However, if using the generic
+     * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette
+     * must be casted to (u32 *) _regardless_ of the bits per pixel. If the
+     * driver is using its own drawing functions, then it can use whatever
+     * size it wants.
+     */
+    if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+	    u32 v;
 
-       v = (red << info->var.red.offset) |
-           (green << info->var.green.offset) |
-           (blue << info->var.blue.offset) |
-           (transp << info->var.transp.offset);
+	    if (regno >= 16)
+		    return -EINVAL;
 
-       switch (info->var.bits_per_pixel) {
-		case 8:
-			/* Yes some hand held devices have this. */ 
-           		((u8*)(info->pseudo_palette))[regno] = v;
-			break;	
-   		case 16:
-           		((u16*)(info->pseudo_palette))[regno] = v;
-			break;
-		case 24:
-		case 32:	
-           		((u32*)(info->pseudo_palette))[regno] = v;
-			break;
-       }
-       return 0;
+	    v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+
+	    ((u32*)(info->pseudo_palette))[regno] = v;
     }
+
     /* ... */
     return 0;
 }
@@ -340,6 +419,17 @@
 static int xxxfb_pan_display(struct fb_var_screeninfo *var,
 			     const struct fb_info *info)
 {
+    /*
+     * If your hardware does not support panning, _do_ _not_ implement this
+     * function. Creating a dummy function will just confuse user apps.
+     */
+
+    /*
+     * Note that even if this function is fully functional, a setting of
+     * 0 in both xpanstep and ypanstep means that this function will never
+     * get called.
+     */
+
     /* ... */
     return 0;
 }
@@ -349,15 +439,20 @@
  *      @blank_mode: the blank mode we want. 
  *      @info: frame buffer structure that represents a single frame buffer
  *
- *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
- *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a 
- *      video mode which doesn't support it. Implements VESA suspend
- *      and powerdown modes on hardware that supports disabling hsync/vsync:
- *      blank_mode == 2: suspend vsync
- *      blank_mode == 3: suspend hsync
- *      blank_mode == 4: powerdown
+ *      Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
+ *      Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+ *      e.g. a video mode which doesn't support it.
  *
- *      Returns negative errno on error, or zero on success.
+ *      Implements VESA suspend and powerdown modes on hardware that supports
+ *      disabling hsync/vsync:
+ *
+ *      FB_BLANK_NORMAL = display is blanked, syncs are on.
+ *      FB_BLANK_HSYNC_SUSPEND = hsync off
+ *      FB_BLANK_VSYNC_SUSPEND = vsync off
+ *      FB_BLANK_POWERDOWN =  hsync and vsync off
+ *
+ *      If implementing this function, at least support FB_BLANK_UNBLANK.
+ *      Return !0 for any modes that are unimplemented.
  *
  */
 static int xxxfb_blank(int blank_mode, const struct fb_info *info)
@@ -454,6 +549,14 @@
  *	@data: The actual data used to construct the image on the display.
  *	@cmap: The colormap used for color images.   
  */
+
+/*
+ * The generic function, cfb_imageblit, expects that the bitmap scanlines are
+ * padded to the next byte.  Most hardware accelerators may require padding to
+ * the next u16 or the next u32.  If that is the case, the driver can specify
+ * this by setting info->pixmap.scan_align = 2 or 4.  See a more
+ * comprehensive description of the pixmap below.
+ */
 }
 
 /**
@@ -517,6 +620,7 @@
  */
 void xxxfb_rotate(struct fb_info *info, int angle)
 {
+/* Will be deprecated */
 }
 
 /**
@@ -540,6 +644,9 @@
  *		     so we can have consistent display output. 
  *
  *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      If the driver has implemented its own hardware-based drawing function,
+ *      implementing this function is highly recommended.
  */
 void xxxfb_sync(struct fb_info *info)
 {
@@ -549,20 +656,25 @@
      *  Initialization
      */
 
-int __init xxxfb_init(void)
+/* static int __init xxfb_probe (struct device *device) -- for platform devs */
+static int __init xxxfb_probe(struct pci_dev *dev,
+			      const_struct pci_device_id *ent)
 {
+    struct fb_info *info;
+    struct xxx_par *par;
+    struct device = &dev->dev; /* for pci drivers */
     int cmap_len, retval;	
    
     /*
-     *  For kernel boot options (in 'video=xxxfb:<options>' format)
+     * Dynamically allocate info and par
      */
-#ifndef MODULE
-    char *option = NULL;
+    info = framebuffer_alloc(sizeof(struct xxx_par), device);
 
-    if (fb_get_options("xxxfb", &option))
-	    return -ENODEV;
-    xxxfb_setup(option);
-#endif
+    if (!info) {
+	    /* goto error path */
+    }
+
+    par = info->par;
 
     /* 
      * Here we set the screen_base to the virtual memory address
@@ -570,18 +682,87 @@
      * from the bus layer and then translate it to virtual memory
      * space via ioremap. Consult ioport.h. 
      */
-    info.screen_base = framebuffer_virtual_memory;	
-    info.fbops = &xxxfb_ops;
-    info.fix = xxxfb_fix;
-    info.pseudo_palette = pseudo_palette;
-
+    info->screen_base = framebuffer_virtual_memory;
+    info->fbops = &xxxfb_ops;
+    info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be
+			    * used, so mark it as __initdata
+			    */
+    info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
+					    * 16-member array
+					    */
     /*
      * Set up flags to indicate what sort of acceleration your
      * driver can provide (pan/wrap/copyarea/etc.) and whether it
      * is a module -- see FBINFO_* in include/linux/fb.h
+     *
+     * If your hardware can support any of the hardware accelerated functions
+     * fbcon performance will improve if info->flags is set properly.
+     *
+     * FBINFO_HWACCEL_COPYAREA - hardware moves
+     * FBINFO_HWACCEL_FILLRECT - hardware fills
+     * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
+     * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
+     * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
+     * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
+     * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
+     * FBINFO_MISC_TILEBLITTING - hardware can do tile blits
+     *
+     * NOTE: These are for fbcon use only.
      */
-    info.flags = FBINFO_DEFAULT;
-    info.par = current_par;
+    info->flags = FBINFO_DEFAULT;
+
+/********************* This stage is optional ******************************/
+     /*
+     * The struct pixmap is a scratch pad for the drawing functions. This
+     * is where the monochrome bitmap is constructed by the higher layers
+     * and then passed to the accelerator.  For drivers that uses
+     * cfb_imageblit, you can skip this part.  For those that have a more
+     * rigorous requirement, this stage is needed
+     */
+
+    /* PIXMAP_SIZE should be small enough to optimize drawing, but not
+     * large enough that memory is wasted.  A safe size is
+     * (max_xres * max_font_height/8). max_xres is driver dependent,
+     * max_font_height is 32.
+     */
+    info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);
+    if (!info->pixmap.addr) {
+	    /* goto error */
+    }
+
+    info->pixmap.size = PIXMAP_SIZE;
+
+    /*
+     * FB_PIXMAP_SYSTEM - memory is in system ram
+     * FB_PIXMAP_IO     - memory is iomapped
+     * FB_PIXMAP_SYNC   - if set, will call fb_sync() per access to pixmap,
+     *                    usually if FB_PIXMAP_IO is set.
+     *
+     * Currently, FB_PIXMAP_IO is unimplemented.
+     */
+    info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+    /*
+     * scan_align is the number of padding for each scanline.  It is in bytes.
+     * Thus for accelerators that need padding to the next u32, put 4 here.
+     */
+    info->pixmap.scan_align = 4;
+
+    /*
+     * buf_align is the amount to be padded for the buffer. For example,
+     * the i810fb needs a scan_align of 2 but expects it to be fed with
+     * dwords, so a buf_align = 4 is required.
+     */
+    info->pixmap.buf_align = 4;
+
+    /* access_align is how many bits can be accessed from the framebuffer
+     * ie. some epson cards allow 16-bit access only.  Most drivers will
+     * be safe with u32 here.
+     *
+     * NOTE: This field is currently unused.
+     */
+    info->pixmap.scan_align = 32
+/***************************** End optional stage ***************************/
 
     /*
      * This should give a reasonable default video mode. The following is
@@ -590,43 +771,146 @@
     if (!mode_option)
 	mode_option = "640x480@60";	 	
 
-    retval = fb_find_mode(&info.var, &info, mode_option, NULL, 0, NULL, 8);
+    retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8);
   
     if (!retval || retval == 4)
 	return -EINVAL;			
 
     /* This has to been done !!! */	
-    fb_alloc_cmap(&info.cmap, cmap_len, 0);
+    fb_alloc_cmap(info->cmap, cmap_len, 0);
 	
     /* 
      * The following is done in the case of having hardware with a static 
      * mode. If we are setting the mode ourselves we don't call this. 
      */	
-    info.var = xxxfb_var;
-	
-    if (register_framebuffer(&info) < 0)
+    info->var = xxxfb_var;
+
+    /*
+     * For drivers that can...
+     */
+    xxxfb_check_var(&info->var, info);
+
+    /*
+     * Does a call to fb_set_par() before register_framebuffer needed?  This
+     * will depend on you and the hardware.  If you are sure that your driver
+     * is the only device in the system, a call to fb_set_par() is safe.
+     *
+     * Hardware in x86 systems has a VGA core.  Calling set_par() at this
+     * point will corrupt the VGA console, so it might be safer to skip a
+     * call to set_par here and just allow fbcon to do it for you.
+     */
+    /* xxxfb_set_par(info); */
+
+    if (register_framebuffer(info) < 0)
 	return -EINVAL;
-    printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
-	   info.fix.id);
+    printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+	   info->fix.id);
+    pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
     return 0;
 }
 
     /*
      *  Cleanup
      */
-
-static void __exit xxxfb_cleanup(void)
+/* static void __exit xxxfb_remove(struct device *device) */
+static void __exit xxxfb_remove(struct pci_dev *dev)
 {
-    /*
-     *  If your driver supports multiple boards, you should unregister and
-     *  clean up all instances.
-     */
+	struct fb_info *info = pci_get_drv_data(dev);
+	/* or dev_get_drv_data(device); */
 
-    unregister_framebuffer(info);
-    fb_dealloc_cmap(&info.cmap);
-    /* ... */
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info.cmap);
+		/* ... */
+		framebuffer_release(info);
+	}
+
+	return 0;
 }
 
+#if CONFIG_PCI
+/* For PCI drivers */
+static struct pci_driver xxxfb_driver = {
+	.name =		"xxxfb",
+	.id_table =	xxxfb_devices,
+	.probe =	xxxfb_probe,
+	.remove =	__devexit_p(xxxfb_remove),
+	.suspend =      xxxfb_suspend, /* optional */
+	.resume =       xxxfb_resume,  /* optional */
+};
+
+static int __init xxxfb_init(void)
+{
+	/*
+	 *  For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("xxxfb", &option))
+		return -ENODEV;
+	xxxfb_setup(option);
+#endif
+
+	return pci_register_driver(&xxxfb_driver);
+}
+
+static void __exit xxxfb_exit(void)
+{
+	pci_unregister_driver(&xxxfb_driver);
+}
+#else
+#include <linux/platform_device.h>
+/* for platform devices */
+static struct device_driver xxxfb_driver = {
+	.name = "xxxfb",
+	.bus  = &platform_bus_type,
+	.probe = xxxfb_probe,
+	.remove = xxxfb_remove,
+	.suspend = xxxfb_suspend, /* optional */
+	.resume = xxxfb_resume,   /* optional */
+};
+
+static struct platform_device xxxfb_device = {
+	.name = "xxxfb",
+};
+
+static int __init xxxfb_init(void)
+{
+	int ret;
+	/*
+	 *  For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("xxxfb", &option))
+		return -ENODEV;
+	xxxfb_setup(option);
+#endif
+	ret = driver_register(&xxxfb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&xxxfb_device);
+		if (ret)
+			driver_unregister(&xxxfb_driver);
+	}
+
+	return ret;
+}
+
+static void __exit xxxfb_exit(void)
+{
+	platform_device_unregister(&xxxfb_device);
+	driver_unregister(&xxxfb_driver);
+}
+#endif
+
+MODULE_LICENSE("GPL");
+module_init(xxxfb_init);
+module_exit(xxxfb_exit);
+
+
     /*
      *  Setup
      */
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index e0f14df..8a5ce21 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -382,7 +382,7 @@
 static int sstfb_check_var(struct fb_var_screeninfo *var,
 		struct fb_info *info)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	int hSyncOff   = var->xres + var->right_margin + var->left_margin;
 	int vSyncOff   = var->yres + var->lower_margin + var->upper_margin;
 	int vBackPorch = var->left_margin, yDim = var->yres;
@@ -542,7 +542,7 @@
  */
 static int sstfb_set_par(struct fb_info *info)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
 	struct pci_dev *sst_dev = par->dev;
 	unsigned int freq;
@@ -748,13 +748,14 @@
 static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                            u_int transp, struct fb_info *info)
 {
+	struct sstfb_par *par = info->par;
 	u32 col;
 
 	f_dddprintk("sstfb_setcolreg\n");
 	f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
 	            regno, red, green, blue, transp);
-	if (regno >= 16)
-		return -EINVAL;
+	if (regno > 15)
+		return 0;
 
 	red    >>= (16 - info->var.red.length);
 	green  >>= (16 - info->var.green.length);
@@ -765,7 +766,7 @@
 	    | (blue  << info->var.blue.offset)
 	    | (transp << info->var.transp.offset);
 	
-	((u32 *)info->pseudo_palette)[regno] = col;
+	par->palette[regno] = col;
 
 	return 0;
 }
@@ -773,7 +774,7 @@
 static int sstfb_ioctl(struct inode *inode, struct file *file,
                        u_int cmd, u_long arg, struct fb_info *info )
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	struct pci_dev *sst_dev = par->dev;
 	u32 fbiinit0, tmp, val;
 	u_long p;
@@ -830,7 +831,7 @@
 #if 0
 static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	u32 stride = info->fix.line_length;
    
 	if (!IS_VOODOO2(par))
@@ -855,7 +856,7 @@
  */
 static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	u32 stride = info->fix.line_length;
 
 	if (!IS_VOODOO2(par))
@@ -925,7 +926,7 @@
 
 static int __devinit sst_detect_att(struct fb_info *info)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	int i, mir, dir;
 
 	for (i=0; i<3; i++) {
@@ -950,7 +951,7 @@
 
 static int __devinit sst_detect_ti(struct fb_info *info)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	int i, mir, dir;
 
 	for (i = 0; i<3; i++) {
@@ -986,7 +987,7 @@
  */
 static int __devinit sst_detect_ics(struct fb_info *info)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	int m_clk0_1, m_clk0_7, m_clk1_b;
 	int n_clk0_1, n_clk0_7, n_clk1_b;
 	int i;
@@ -1023,7 +1024,7 @@
 static int sst_set_pll_att_ti(struct fb_info *info, 
 		const struct pll_timing *t, const int clock)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	u8 cr0, cc;
 
 	/* enable indexed mode */
@@ -1077,7 +1078,7 @@
 static int sst_set_pll_ics(struct fb_info *info,
 		const struct pll_timing *t, const int clock)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	u8 pll_ctrl;
 
 	sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
@@ -1114,7 +1115,7 @@
 
 static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	u8 cr0;
 
 	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
@@ -1149,7 +1150,7 @@
 
 static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 
 	switch(bpp) {
 	case 16:
@@ -1308,7 +1309,7 @@
 
 static void  __devexit sst_shutdown(struct fb_info *info)
 {
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	struct pci_dev *dev = par->dev;
 	struct pll_timing gfx_timings;
 	int Fout;
@@ -1394,12 +1395,6 @@
 	struct sst_spec *spec;
 	int err;
 
-	struct all_info {
-		struct fb_info info;
-		struct sstfb_par par;
-		u32 pseudo_palette[16];
-	} *all;
-	
 	/* Enable device in PCI config. */
 	if ((err=pci_enable_device(pdev))) {
 		eprintk("cannot enable device\n");
@@ -1407,14 +1402,13 @@
 	}
 
 	/* Allocate the fb and par structures.  */
-	all = kmalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
+	info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
+	if (!info)
 		return -ENOMEM;
-	memset(all, 0, sizeof(*all));
-	pci_set_drvdata(pdev, all);
+
+	pci_set_drvdata(pdev, info);
 	
-	info = &all->info;
-	par  = info->par = &all->par;
+	par  = info->par;
 	fix  = &info->fix;
 	
 	par->type = id->driver_data;
@@ -1471,7 +1465,7 @@
 
 	info->flags	= FBINFO_DEFAULT;
 	info->fbops	= &sstfb_ops;
-	info->pseudo_palette = &all->pseudo_palette;
+	info->pseudo_palette = par->palette;
 
 	fix->type	= FB_TYPE_PACKED_PIXELS;
 	fix->visual	= FB_VISUAL_TRUECOLOR;
@@ -1527,7 +1521,7 @@
 fail_fb_mem:
 	release_mem_region(fix->mmio_start, info->fix.mmio_len);
 fail_mmio_mem:
-	kfree(info);
+	framebuffer_release(info);
 	return -ENXIO; 	/* no voodoo detected */
 }
 
@@ -1537,7 +1531,7 @@
 	struct fb_info *info;
 
 	info = pci_get_drvdata(pdev);
-	par = (struct sstfb_par *) info->par;
+	par = info->par;
 	
 	sst_shutdown(info);
 	unregister_framebuffer(info);
@@ -1545,7 +1539,7 @@
 	iounmap(par->mmio_vbase);
 	release_mem_region(info->fix.smem_start, 0x400000);
 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-	kfree(info);
+	framebuffer_release(info);
 }
 
 
@@ -1613,7 +1607,7 @@
 
 	const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);
 	const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);
-	struct sstfb_par *par = (struct sstfb_par *) info->par;
+	struct sstfb_par *par = info->par;
 	struct pci_dev *dev = par->dev;
 	u32 pci_res[pci_s];
 	u32 sst_res[sst_s];
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 9d53387..3e7baf4 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -291,7 +291,7 @@
  
 static int banshee_wait_idle(struct fb_info *info)
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par; 
+	struct tdfx_par *par = info->par;
 	int i = 0;
 
 	banshee_make_room(par, 1);
@@ -364,7 +364,7 @@
 
 static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) 
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par; 
+	struct tdfx_par *par = info->par;
 	int i;
 
 	banshee_wait_idle(info);
@@ -469,7 +469,7 @@
 
 static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info) 
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par; 
+	struct tdfx_par *par = info->par;
 	u32 lpitch;
 
 	if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
@@ -558,7 +558,7 @@
 
 static int tdfxfb_set_par(struct fb_info *info)
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;	
+	struct tdfx_par *par = info->par;
 	u32 hdispend, hsyncsta, hsyncend, htotal;
 	u32 hd, hs, he, ht, hbs, hbe;
 	u32 vd, vs, ve, vt, vbs, vbe;
@@ -780,7 +780,7 @@
 static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,  
 			    unsigned blue,unsigned transp,struct fb_info *info) 
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 	u32 rgbcol;
    
 	if (regno >= info->cmap.len || regno > 255) return 1;
@@ -794,11 +794,15 @@
 			break;
 		/* Truecolor has no hardware color palettes. */
 		case FB_VISUAL_TRUECOLOR:
-			rgbcol = (CNVT_TOHW( red, info->var.red.length) << info->var.red.offset) |
-				 (CNVT_TOHW( green, info->var.green.length) << info->var.green.offset) |
-				 (CNVT_TOHW( blue, info->var.blue.length) << info->var.blue.offset) |
-				 (CNVT_TOHW( transp, info->var.transp.length) << info->var.transp.offset);
-				((u32*)(info->pseudo_palette))[regno] = rgbcol;
+			rgbcol = (CNVT_TOHW( red, info->var.red.length) <<
+				  info->var.red.offset) |
+				 (CNVT_TOHW( green, info->var.green.length) <<
+				  info->var.green.offset) |
+				 (CNVT_TOHW( blue, info->var.blue.length) <<
+				  info->var.blue.offset) |
+				 (CNVT_TOHW( transp, info->var.transp.length) <<
+				  info->var.transp.offset);
+				par->palette[regno] = rgbcol;
 			break;
 		default:
 			DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
@@ -810,7 +814,7 @@
 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
 static int tdfxfb_blank(int blank, struct fb_info *info)
 { 
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 	u32 dacmode, state = 0, vgablank = 0;
 
 	dacmode = tdfx_inl(par, DACMODE);
@@ -855,7 +859,7 @@
 static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
 			      struct fb_info *info) 
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 	u32 addr;  	
 
 	if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
@@ -878,7 +882,7 @@
  */
 static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 	u32 bpp = info->var.bits_per_pixel;
 	u32 stride = info->fix.line_length;
 	u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); 
@@ -894,7 +898,7 @@
 	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
 		tdfx_outl(par,	COLORFORE, rect->color);
 	} else { /* FB_VISUAL_TRUECOLOR */
-		tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]);
+		tdfx_outl(par, COLORFORE, par->palette[rect->color]);
 	}
 	tdfx_outl(par,	COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
 	tdfx_outl(par,	DSTSIZE,    rect->width | (rect->height << 16));
@@ -906,7 +910,7 @@
  */
 static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)  
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
    	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
 	u32 bpp = info->var.bits_per_pixel;
 	u32 stride = info->fix.line_length;
@@ -938,7 +942,7 @@
 
 static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) 
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 	int size = image->height * ((image->width * image->depth + 7)>>3);
 	int fifo_free;
 	int i, stride = info->fix.line_length;
@@ -961,8 +965,10 @@
 				break;
 			case FB_VISUAL_TRUECOLOR:
 			default:
-				tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[image->fg_color]);
-				tdfx_outl(par, COLORBACK, ((u32*)(info->pseudo_palette))[image->bg_color]);
+				tdfx_outl(par, COLORFORE,
+					  par->palette[image->fg_color]);
+				tdfx_outl(par, COLORBACK,
+					  par->palette[image->bg_color]);
 		}
 #ifdef __BIG_ENDIAN
 		srcfmt = 0x400000 | BIT(20);
@@ -1007,7 +1013,7 @@
 #ifdef TDFX_HARDWARE_CURSOR
 static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 	unsigned long flags;
 
 	/*
@@ -1157,18 +1163,17 @@
 {
 	struct tdfx_par *default_par;
 	struct fb_info *info;
-	int size, err, lpitch;
+	int err, lpitch;
 
 	if ((err = pci_enable_device(pdev))) {
 		printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
 		return err;
 	}
 
-	size = sizeof(struct tdfx_par)+256*sizeof(u32);
+	info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);
 
-	info = framebuffer_alloc(size, &pdev->dev);
-
-	if (!info)	return -ENOMEM;
+	if (!info)
+		return -ENOMEM;
 		
 	default_par = info->par;
  
@@ -1248,7 +1253,7 @@
    
 	info->fbops		= &tdfxfb_ops;
 	info->fix		= tdfx_fix; 	
-	info->pseudo_palette	= (void *)(default_par + 1); 
+	info->pseudo_palette	= default_par->palette;
 	info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 #ifdef CONFIG_FB_3DFX_ACCEL
 	info->flags             |= FBINFO_HWACCEL_FILLRECT |
@@ -1307,7 +1312,7 @@
 }
 
 #ifndef MODULE
-void tdfxfb_setup(char *options)
+static void tdfxfb_setup(char *options)
 {
 	char* this_opt;
 
@@ -1340,7 +1345,7 @@
 static void __devexit tdfxfb_remove(struct pci_dev *pdev)
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
-	struct tdfx_par *par = (struct tdfx_par *) info->par;
+	struct tdfx_par *par = info->par;
 
 	unregister_framebuffer(info);
 	iounmap(par->regbase_virt);
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 3e58ddc..8982e54 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -57,7 +57,6 @@
 static void            (*pmi_start)(void);
 static void            (*pmi_pal)(void);
 static int             depth;
-static int             vga_compat;
 
 /* --------------------------------------------------------------------- */
 
@@ -67,15 +66,6 @@
 #ifdef __i386__
 	int offset;
 
-	if (!ypan)
-		return -EINVAL;
-	if (var->xoffset)
-		return -EINVAL;
-	if (var->yoffset > var->yres_virtual)
-		return -EINVAL;
-	if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
-		return -EINVAL;
-
 	offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
 
         __asm__ __volatile__(
@@ -90,37 +80,6 @@
 	return 0;
 }
 
-static int vesafb_blank(int blank, struct fb_info *info)
-{
-	int err = 1;
-
-	if (vga_compat) {
-		int loop = 10000;
-		u8 seq = 0, crtc17 = 0;
-
-		if (blank == FB_BLANK_POWERDOWN) {
-			seq = 0x20;
-			crtc17 = 0x00;
-			err = 0;
-		} else {
-			seq = 0x00;
-			crtc17 = 0x80;
-			err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
-		}
-
-		vga_wseq(NULL, 0x00, 0x01);
-		seq |= vga_rseq(NULL, 0x01) & ~0x20;
-		vga_wseq(NULL, 0x00, seq);
-
-		crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
-		while (loop--);
-		vga_wcrt(NULL, 0x17, crtc17);
-		vga_wseq(NULL, 0x00, 0x03);
-	}
-
-	return err;
-}
-
 static void vesa_setpalette(int regno, unsigned red, unsigned green,
 			    unsigned blue)
 {
@@ -205,7 +164,6 @@
 	.owner		= THIS_MODULE,
 	.fb_setcolreg	= vesafb_setcolreg,
 	.fb_pan_display	= vesafb_pan_display,
-	.fb_blank       = vesafb_blank,
 	.fb_fillrect	= cfb_fillrect,
 	.fb_copyarea	= cfb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
@@ -459,9 +417,8 @@
 	info->flags = FBINFO_FLAG_DEFAULT |
 		(ypan) ? FBINFO_HWACCEL_YPAN : 0;
 
-	vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
-	printk("vesafb: Mode is %sVGA compatible\n",
-	       (vga_compat) ? "" : "not ");
+	if (!ypan)
+		info->fbops->fb_pan_display = NULL;
 
 	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 		err = -ENOMEM;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 226ae8a..f3f16fd 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -705,15 +705,7 @@
 static int vga16fb_pan_display(struct fb_var_screeninfo *var,
 			       struct fb_info *info) 
 {
-	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-	    var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
 	vga16fb_pan_var(info, var);
-
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	info->var.vmode &= ~FB_VMODE_YWRAP;
 	return 0;
 }
 
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index d9e01da..15179ec 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -356,10 +356,11 @@
 {
 	struct regstate *saved;
 
-	saved = kmalloc(sizeof(struct regstate), GFP_KERNEL);
+	saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
+
 	if (saved == NULL)
 		return 1;
-	memset (saved, 0, sizeof(struct regstate));
+
 	state->vidstate = (void *)saved;
 		
 	if (state->flags & VGA_SAVE_CMAP) {
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index ae0f06b..2c4fa75 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -91,7 +91,7 @@
 	sb->s_op = &v9fs_super_ops;
 
 	sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
-	    MS_NODIRATIME | MS_NOATIME;
+	    MS_NOATIME;
 }
 
 /**
diff --git a/fs/Kconfig b/fs/Kconfig
index 382e3b2..ef78e3a 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -798,7 +798,7 @@
 
 config PROC_VMCORE
         bool "/proc/vmcore support (EXPERIMENTAL)"
-        depends on PROC_FS && EMBEDDED && EXPERIMENTAL && CRASH_DUMP
+        depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP
         help
         Exports the dump image of crashed kernel in ELF format.
 
diff --git a/fs/Makefile b/fs/Makefile
index 35e9aec..1db7113 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -14,7 +14,7 @@
 
 obj-$(CONFIG_INOTIFY)		+= inotify.o
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
-obj-$(CONFIG_COMPAT)		+= compat.o
+obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 
 nfsd-$(CONFIG_NFSD)		:= nfsctl.o
 obj-y				+= $(nfsd-y) $(nfsd-m)
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 541b19e..14aa702 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -86,7 +86,7 @@
 
 /* Update usage from here to top of tree, so that scan of
    top-level directories will give a useful result */
-static void autofs4_update_usage(struct dentry *dentry)
+static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry)
 {
 	struct dentry *top = dentry->d_sb->s_root;
 
@@ -95,7 +95,7 @@
 		struct autofs_info *ino = autofs4_dentry_ino(dentry);
 
 		if (ino) {
-			update_atime(dentry->d_inode);
+			touch_atime(mnt, dentry);
 			ino->last_used = jiffies;
 		}
 	}
@@ -289,10 +289,10 @@
 	return autofs4_dcache_readdir(file, dirent, filldir);
 }
 
-static int try_to_fill_dentry(struct dentry *dentry, 
-			      struct super_block *sb,
-			      struct autofs_sb_info *sbi, int flags)
+static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)
 {
+	struct super_block *sb = mnt->mnt_sb;
+	struct autofs_sb_info *sbi = autofs4_sbi(sb);
 	struct autofs_info *de_info = autofs4_dentry_ino(dentry);
 	int status = 0;
 
@@ -367,7 +367,7 @@
 	/* We don't update the usages for the autofs daemon itself, this
 	   is necessary for recursive autofs mounts */
 	if (!autofs4_oz_mode(sbi))
-		autofs4_update_usage(dentry);
+		autofs4_update_usage(mnt, dentry);
 
 	spin_lock(&dentry->d_lock);
 	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
@@ -392,7 +392,7 @@
 	/* Pending dentry */
 	if (autofs4_ispending(dentry)) {
 		if (!oz_mode)
-			status = try_to_fill_dentry(dentry, dir->i_sb, sbi, flags);
+			status = try_to_fill_dentry(nd->mnt, dentry, flags);
 		return status;
 	}
 
@@ -409,14 +409,14 @@
 			 dentry, dentry->d_name.len, dentry->d_name.name);
 		spin_unlock(&dcache_lock);
 		if (!oz_mode)
-			status = try_to_fill_dentry(dentry, dir->i_sb, sbi, flags);
+			status = try_to_fill_dentry(nd->mnt, dentry, flags);
 		return status;
 	}
 	spin_unlock(&dcache_lock);
 
 	/* Update the usage list */
 	if (!oz_mode)
-		autofs4_update_usage(dentry);
+		autofs4_update_usage(nd->mnt, dentry);
 
 	return 1;
 }
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 7201182..f312103 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -33,8 +33,6 @@
 static int load_aout_library(struct file*);
 static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 static struct linux_binfmt aout_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_aout_binary,
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 80ca932..a4f6f57 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -622,7 +622,7 @@
 				goto out_free_file;
 
 			retval = -ENOMEM;
-			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
+			elf_interpreter = kmalloc(elf_ppnt->p_filesz,
 							   GFP_KERNEL);
 			if (!elf_interpreter)
 				goto out_free_file;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index e0344f6..5b3076e 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -187,7 +187,7 @@
 				goto error;
 
 			/* read the name of the interpreter into memory */
-			interpreter_name = (char *) kmalloc(phdr->p_filesz, GFP_KERNEL);
+			interpreter_name = kmalloc(phdr->p_filesz, GFP_KERNEL);
 			if (!interpreter_name)
 				goto error;
 
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 9d66258..b72dc31 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -77,8 +77,6 @@
 static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
 static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
 
-extern void dump_thread(struct pt_regs *, struct user *);
-
 static struct linux_binfmt flat_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_flat_binary,
diff --git a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h
index decd138..da2ad5b 100644
--- a/fs/cifs/cifs_uniupr.h
+++ b/fs/cifs/cifs_uniupr.h
@@ -242,7 +242,7 @@
 /*
  * Lower Case Range
  */
-const static struct UniCaseRange CifsUniLowerRange[] = {
+static const struct UniCaseRange CifsUniLowerRange[] = {
 	0x0380, 0x03ab, UniCaseRangeL0380,
 	0x0400, 0x042f, UniCaseRangeL0400,
 	0x0490, 0x04cb, UniCaseRangeL0490,
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 55d9a3a..890bc30f 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -10,7 +10,6 @@
  * ioctls.
  */
 
-#ifdef INCLUDES
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/compat.h>
@@ -81,13 +80,9 @@
 #include <linux/capi.h>
 
 #include <scsi/scsi.h>
-/* Ugly hack. */
-#undef __KERNEL__
 #include <scsi/scsi_ioctl.h>
-#define __KERNEL__
 #include <scsi/sg.h>
 
-#include <asm/types.h>
 #include <asm/uaccess.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -95,7 +90,6 @@
 #include <linux/watchdog.h>
 #include <linux/dm-ioctl.h>
 
-#include <asm/module.h>
 #include <linux/soundcard.h>
 #include <linux/lp.h>
 #include <linux/ppdev.h>
@@ -128,11 +122,6 @@
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/video.h>
 
-#undef INCLUDES
-#endif
-
-#ifdef CODE
-
 /* Aiee. Someone does not find a difference between int and long */
 #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
 #define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
@@ -148,6 +137,12 @@
 #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
 #define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
 
+static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
+			      unsigned long arg, struct file *f)
+{
+	return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
+}
+
 static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
@@ -2475,6 +2470,49 @@
 	return -EINVAL;
 }
 
+#define RTC_IRQP_READ32		_IOR('p', 0x0b, compat_ulong_t)
+#define RTC_IRQP_SET32		_IOW('p', 0x0c, compat_ulong_t)
+#define RTC_EPOCH_READ32	_IOR('p', 0x0d, compat_ulong_t)
+#define RTC_EPOCH_SET32		_IOW('p', 0x0e, compat_ulong_t)
+
+static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
+{
+	mm_segment_t oldfs = get_fs();
+	compat_ulong_t val32;
+	unsigned long kval;
+	int ret;
+
+	switch (cmd) {
+	case RTC_IRQP_READ32:
+	case RTC_EPOCH_READ32:
+		set_fs(KERNEL_DS);
+		ret = sys_ioctl(fd, (cmd == RTC_IRQP_READ32) ?
+					RTC_IRQP_READ : RTC_EPOCH_READ,
+					(unsigned long)&kval);
+		set_fs(oldfs);
+		if (ret)
+			return ret;
+		val32 = kval;
+		return put_user(val32, (unsigned int __user *)arg);
+	case RTC_IRQP_SET32:
+	case RTC_EPOCH_SET32:
+		ret = get_user(val32, (unsigned int __user *)arg);
+		if (ret)
+			return ret;
+		kval = val32;
+
+		set_fs(KERNEL_DS);
+		ret = sys_ioctl(fd, (cmd == RTC_IRQP_SET32) ?
+				RTC_IRQP_SET : RTC_EPOCH_SET,
+				(unsigned long)&kval);
+		set_fs(oldfs);
+		return ret;
+	default:
+		/* unreached */
+		return -ENOIOCTLCMD;
+	}
+}
+
 #if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
 struct ncp_ioctl_request_32 {
 	u32 function;
@@ -2662,10 +2700,20 @@
 }
 #endif
 
-#undef CODE
-#endif
+#define HANDLE_IOCTL(cmd,handler) \
+	{ (cmd), (ioctl_trans_handler_t)(handler) },
 
-#ifdef DECLARES
+/* pointer to compatible structure or no argument */
+#define COMPATIBLE_IOCTL(cmd) \
+	{ (cmd), do_ioctl32_pointer },
+
+/* argument is an unsigned long integer, not a pointer */
+#define ULONG_IOCTL(cmd) \
+	{ (cmd), (ioctl_trans_handler_t)sys_ioctl },
+
+
+struct ioctl_trans ioctl_start[] = {
+#include <linux/compat_ioctl.h>
 HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
 HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
 #ifdef CONFIG_NET
@@ -2858,6 +2906,10 @@
 HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl)
 HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
 HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
+HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl)
+HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl)
+HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl)
+HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl)
 
 #if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
 HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
@@ -2874,6 +2926,6 @@
 HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event)
 HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture)
 HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette)
+};
 
-#undef DECLARES
-#endif
+int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/fs/dcache.c b/fs/dcache.c
index 1536f15..134d677 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -808,10 +808,14 @@
  *
  * Fill in inode information in the entry. On success, it returns NULL.
  * If an unhashed alias of "entry" already exists, then we return the
- * aliased dentry instead.
+ * aliased dentry instead and drop one reference to inode.
  *
  * Note that in order to avoid conflicts with rename() etc, the caller
  * had better be holding the parent directory semaphore.
+ *
+ * This also assumes that the inode count has been incremented
+ * (or otherwise set) by the caller to indicate that it is now
+ * in use by the dcache.
  */
 struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 {
@@ -838,6 +842,7 @@
 		dget_locked(alias);
 		spin_unlock(&dcache_lock);
 		BUG_ON(!d_unhashed(alias));
+		iput(inode);
 		return alias;
 	}
 	list_add(&entry->d_alias, &inode->i_dentry);
diff --git a/fs/exec.c b/fs/exec.c
index fd02ea4a..b5bcf1a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -632,10 +632,10 @@
 		 * synchronize with any firing (by calling del_timer_sync)
 		 * before we can safely let the old group leader die.
 		 */
-		sig->real_timer.data = (unsigned long)current;
+		sig->real_timer.data = current;
 		spin_unlock_irq(lock);
-		if (del_timer_sync(&sig->real_timer))
-			add_timer(&sig->real_timer);
+		if (hrtimer_cancel(&sig->real_timer))
+			hrtimer_restart(&sig->real_timer);
 		spin_lock_irq(lock);
 	}
 	while (atomic_read(&sig->count) > count) {
diff --git a/fs/ext2/bitmap.c b/fs/ext2/bitmap.c
index 20145b7..e9983a0 100644
--- a/fs/ext2/bitmap.c
+++ b/fs/ext2/bitmap.c
@@ -7,8 +7,12 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
+#ifdef EXT2FS_DEBUG
+
 #include <linux/buffer_head.h>
 
+#include "ext2.h"
+
 static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
 
 unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
@@ -23,3 +27,6 @@
 			nibblemap[(map->b_data[i] >> 4) & 0xf];
 	return (sum);
 }
+
+#endif  /*  EXT2FS_DEBUG  */
+
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index f7a3b5f..a2ca310 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -389,10 +389,6 @@
 	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
 		  name_index, name, value, (long)value_len);
 
-	if (IS_RDONLY(inode))
-		return -EROFS;
-	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		return -EPERM;
 	if (value == NULL)
 		value_len = 0;
 	if (name == NULL)
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 52b30ee..2c072bf 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -38,8 +38,6 @@
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      buffer, size);
 }
@@ -50,8 +48,6 @@
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index 0c03ea1..f383e7c 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -35,16 +35,10 @@
 ext2_xattr_user_get(struct inode *inode, const char *name,
 		    void *buffer, size_t size)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	error = permission(inode, MAY_READ, NULL);
-	if (error)
-		return error;
-
 	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size);
 }
 
@@ -52,18 +46,10 @@
 ext2_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	if ( !S_ISREG(inode->i_mode) &&
-	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-		return -EPERM;
-	error = permission(inode, MAY_WRITE, NULL);
-	if (error)
-		return error;
 
 	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
 			      value, size, flags);
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index ae1148c..c6393fb 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -20,8 +20,6 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 
-#include "bitmap.h"
-
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c
index 5b4ba3e..cb16b4c 100644
--- a/fs/ext3/bitmap.c
+++ b/fs/ext3/bitmap.c
@@ -7,8 +7,11 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
+#ifdef EXT3FS_DEBUG
+
 #include <linux/buffer_head.h>
-#include "bitmap.h"
+
+#include "ext3_fs.h"
 
 static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
 
@@ -24,3 +27,6 @@
 			nibblemap[(map->b_data[i] >> 4) & 0xf];
 	return (sum);
 }
+
+#endif  /*  EXT3FS_DEBUG  */
+
diff --git a/fs/ext3/bitmap.h b/fs/ext3/bitmap.h
deleted file mode 100644
index 6ee503a..0000000
--- a/fs/ext3/bitmap.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*  linux/fs/ext3/bitmap.c
- *
- * Copyright (C) 2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
-*/
-
-extern unsigned long ext3_count_free (struct buffer_head *, unsigned int );
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 6907807..dc82646 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -26,7 +26,6 @@
 
 #include <asm/byteorder.h>
 
-#include "bitmap.h"
 #include "xattr.h"
 #include "acl.h"
 
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 238199d..e8d60bf 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -946,10 +946,6 @@
 	};
 	int error;
 
-	if (IS_RDONLY(inode))
-		return -EROFS;
-	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		return -EPERM;
 	if (!name)
 		return -EINVAL;
 	if (strlen(name) > 255)
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index f68bfd1..7c693c9 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -39,8 +39,6 @@
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
 			      buffer, size);
 }
@@ -51,8 +49,6 @@
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index e907cae..a85a0a1 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -37,16 +37,10 @@
 ext3_xattr_user_get(struct inode *inode, const char *name,
 		    void *buffer, size_t size)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	error = permission(inode, MAY_READ, NULL);
-	if (error)
-		return error;
-
 	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, buffer, size);
 }
 
@@ -54,19 +48,10 @@
 ext3_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	if ( !S_ISREG(inode->i_mode) &&
-	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-		return -EPERM;
-	error = permission(inode, MAY_WRITE, NULL);
-	if (error)
-		return error;
-
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
 			      value, size, flags);
 }
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index df16fcb..0fa1ab6 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -143,9 +143,6 @@
 
 	unsigned long flags;
 
-	atomic_t inode_cnt;
-	u32 last_inode_cnt;
-
 	struct hlist_head rsrc_inodes;
 };
 
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 983bcd0..7acff6c 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -182,11 +182,6 @@
 	igrab(dir);
 	hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes);
 	mark_inode_dirty(inode);
-	{
-	void hfsplus_inode_check(struct super_block *sb);
-	atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
-	hfsplus_inode_check(sb);
-	}
 out:
 	d_add(dentry, inode);
 	return NULL;
@@ -317,11 +312,6 @@
 	if (!inode)
 		return NULL;
 
-	{
-	void hfsplus_inode_check(struct super_block *sb);
-	atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
-	hfsplus_inode_check(sb);
-	}
 	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
 	inode->i_mode = mode;
 	inode->i_uid = current->fsuid;
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 6daaf7c..d791780 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -22,29 +22,12 @@
 
 #include "hfsplus_fs.h"
 
-void hfsplus_inode_check(struct super_block *sb)
-{
-#if 0
-	u32 cnt = atomic_read(&HFSPLUS_SB(sb).inode_cnt);
-	u32 last_cnt = HFSPLUS_SB(sb).last_inode_cnt;
-
-	if (cnt <= (last_cnt / 2) ||
-	    cnt >= (last_cnt * 2)) {
-		HFSPLUS_SB(sb).last_inode_cnt = cnt;
-		printk("inode_check: %u,%u,%u\n", cnt, last_cnt,
-			HFSPLUS_SB(sb).cat_tree ? HFSPLUS_SB(sb).cat_tree->node_hash_cnt : 0);
-	}
-#endif
-}
-
 static void hfsplus_read_inode(struct inode *inode)
 {
 	struct hfs_find_data fd;
 	struct hfsplus_vh *vhdr;
 	int err;
 
-	atomic_inc(&HFSPLUS_SB(inode->i_sb).inode_cnt);
-	hfsplus_inode_check(inode->i_sb);
 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
 	init_MUTEX(&HFSPLUS_I(inode).extents_lock);
 	HFSPLUS_I(inode).flags = 0;
@@ -155,12 +138,10 @@
 static void hfsplus_clear_inode(struct inode *inode)
 {
 	dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino);
-	atomic_dec(&HFSPLUS_SB(inode->i_sb).inode_cnt);
 	if (HFSPLUS_IS_RSRC(inode)) {
 		HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL;
 		iput(HFSPLUS_I(inode).rsrc_inode);
 	}
-	hfsplus_inode_check(inode->i_sb);
 }
 
 static void hfsplus_write_super(struct super_block *sb)
diff --git a/fs/inode.c b/fs/inode.c
index e08767f..108138d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -22,6 +22,7 @@
 #include <linux/cdev.h>
 #include <linux/bootmem.h>
 #include <linux/inotify.h>
+#include <linux/mount.h>
 
 /*
  * This is needed for the following functions:
@@ -1176,24 +1177,35 @@
 EXPORT_SYMBOL(bmap);
 
 /**
- *	update_atime	-	update the access time
+ *	touch_atime	-	update the access time
+ *	@mnt: mount the inode is accessed on
  *	@inode: inode accessed
  *
  *	Update the accessed time on an inode and mark it for writeback.
  *	This function automatically handles read only file systems and media,
  *	as well as the "noatime" flag and inode specific "noatime" markers.
  */
-void update_atime(struct inode *inode)
+void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
 {
+	struct inode *inode = dentry->d_inode;
 	struct timespec now;
 
-	if (IS_NOATIME(inode))
-		return;
-	if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
-		return;
 	if (IS_RDONLY(inode))
 		return;
 
+	if ((inode->i_flags & S_NOATIME) ||
+	    (inode->i_sb->s_flags & MS_NOATIME) ||
+	    ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
+		return;
+
+	/*
+	 * We may have a NULL vfsmount when coming from NFSD
+	 */
+	if (mnt &&
+	    ((mnt->mnt_flags & MNT_NOATIME) ||
+	     ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
+		return;
+
 	now = current_fs_time(inode->i_sb);
 	if (!timespec_equal(&inode->i_atime, &now)) {
 		inode->i_atime = now;
@@ -1201,19 +1213,23 @@
 	}
 }
 
-EXPORT_SYMBOL(update_atime);
+EXPORT_SYMBOL(touch_atime);
 
 /**
- *	inode_update_time	-	update mtime and ctime time
- *	@inode: inode accessed
- *	@ctime_too: update ctime too
+ *	file_update_time	-	update mtime and ctime time
+ *	@file: file accessed
  *
- *	Update the mtime time on an inode and mark it for writeback.
- *	When ctime_too is specified update the ctime too.
+ *	Update the mtime and ctime members of an inode and mark the inode
+ *	for writeback.  Note that this function is meant exclusively for
+ *	usage in the file write path of filesystems, and filesystems may
+ *	choose to explicitly ignore update via this function with the
+ *	S_NOCTIME inode flag, e.g. for network filesystem where these
+ *	timestamps are handled by the server.
  */
 
-void inode_update_time(struct inode *inode, int ctime_too)
+void file_update_time(struct file *file)
 {
+	struct inode *inode = file->f_dentry->d_inode;
 	struct timespec now;
 	int sync_it = 0;
 
@@ -1227,16 +1243,15 @@
 		sync_it = 1;
 	inode->i_mtime = now;
 
-	if (ctime_too) {
-		if (!timespec_equal(&inode->i_ctime, &now))
-			sync_it = 1;
-		inode->i_ctime = now;
-	}
+	if (!timespec_equal(&inode->i_ctime, &now))
+		sync_it = 1;
+	inode->i_ctime = now;
+
 	if (sync_it)
 		mark_inode_dirty_sync(inode);
 }
 
-EXPORT_SYMBOL(inode_update_time);
+EXPORT_SYMBOL(file_update_time);
 
 int inode_needs_sync(struct inode *inode)
 {
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 23aa506..952da5f 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -83,21 +83,6 @@
 #define EA_NEW		0x0004
 #define EA_MALLOC	0x0008
 
-/* Namespaces */
-#define XATTR_SYSTEM_PREFIX "system."
-#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
-
-#define XATTR_USER_PREFIX "user."
-#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
-
-#define XATTR_OS2_PREFIX "os2."
-#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
-
-/* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */
-#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
-
-#define XATTR_TRUSTED_PREFIX "trusted."
-#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
 
 /*
  * These three routines are used to recognize on-disk extended attributes
@@ -773,36 +758,23 @@
 static int can_set_xattr(struct inode *inode, const char *name,
 			 const void *value, size_t value_len)
 {
-	if (IS_RDONLY(inode))
-		return -EROFS;
-
-	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		return -EPERM;
-
-	if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
-		/*
-		 * "system.*"
-		 */
+	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 		return can_set_system_xattr(inode, name, value, value_len);
 
-	if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0)
-		return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
-
-#ifdef CONFIG_JFS_SECURITY
-	if (strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)
-	    == 0)
-		return 0;	/* Leave it to the security module */
-#endif
-		
-	if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) &&
-	   (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0))
+	/*
+	 * Don't allow setting an attribute in an unknown namespace.
+	 */
+	if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
+	    strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
+	    strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
+	    strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))
 		return -EOPNOTSUPP;
 
 	if (!S_ISREG(inode->i_mode) &&
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX))
 		return -EPERM;
 
-	return permission(inode, MAY_WRITE, NULL);
+	return 0;
 }
 
 int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
@@ -972,22 +944,6 @@
 	return rc;
 }
 
-static int can_get_xattr(struct inode *inode, const char *name)
-{
-#ifdef CONFIG_JFS_SECURITY
-	if(strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0)
-		return 0;
-#endif
-
-	if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0)
-		return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
-
-	if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
-		return 0;
-
-	return permission(inode, MAY_READ, NULL);
-}
-
 ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
 		       size_t buf_size)
 {
@@ -998,12 +954,8 @@
 	ssize_t size;
 	int namelen = strlen(name);
 	char *os2name = NULL;
-	int rc;
 	char *value;
 
-	if ((rc = can_get_xattr(inode, name)))
-		return rc;
-
 	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
 		os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
 				  GFP_KERNEL);
diff --git a/fs/namespace.c b/fs/namespace.c
index f0e353f..2ca6145 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -355,14 +355,14 @@
 		{ MS_SYNCHRONOUS, ",sync" },
 		{ MS_DIRSYNC, ",dirsync" },
 		{ MS_MANDLOCK, ",mand" },
-		{ MS_NOATIME, ",noatime" },
-		{ MS_NODIRATIME, ",nodiratime" },
 		{ 0, NULL }
 	};
 	static struct proc_fs_info mnt_info[] = {
 		{ MNT_NOSUID, ",nosuid" },
 		{ MNT_NODEV, ",nodev" },
 		{ MNT_NOEXEC, ",noexec" },
+		{ MNT_NOATIME, ",noatime" },
+		{ MNT_NODIRATIME, ",nodiratime" },
 		{ 0, NULL }
 	};
 	struct proc_fs_info *fs_infop;
@@ -1286,7 +1286,13 @@
 		mnt_flags |= MNT_NODEV;
 	if (flags & MS_NOEXEC)
 		mnt_flags |= MNT_NOEXEC;
-	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE);
+	if (flags & MS_NOATIME)
+		mnt_flags |= MNT_NOATIME;
+	if (flags & MS_NODIRATIME)
+		mnt_flags |= MNT_NODIRATIME;
+
+	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
+		   MS_NOATIME | MS_NODIRATIME);
 
 	/* ... and get the mountpoint */
 	retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 4947d9b..973b444 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -262,7 +262,7 @@
 	}
 	vfree(bouncebuffer);
 
-	inode_update_time(inode, 1);
+	file_update_time(file);
 
 	*ppos = pos;
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3e4ba9c..a77ee95 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -950,11 +950,20 @@
 
 	/* Flush out writes to the server in order to update c/mtime */
 	nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT);
-	if (__IS_FLG(inode, MS_NOATIME))
+
+	/*
+	 * We may force a getattr if the user cares about atime.
+	 *
+	 * Note that we only have to check the vfsmount flags here:
+	 *  - NFS always sets S_NOATIME by so checking it would give a
+	 *    bogus result
+	 *  - NFS never sets MS_NOATIME or MS_NODIRATIME so there is
+	 *    no point in checking those.
+	 */
+ 	if ((mnt->mnt_flags & MNT_NOATIME) ||
+ 	    ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
 		need_atime = 0;
-	else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode))
-		need_atime = 0;
-	/* We may force a getattr if the user cares about atime */
+
 	if (need_atime)
 		err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	else
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index bb36b43..eef0576 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -48,8 +48,8 @@
 #include <linux/fsnotify.h>
 #include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
-#ifdef CONFIG_NFSD_V4
 #include <linux/xattr.h>
+#ifdef CONFIG_NFSD_V4
 #include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
 #include <linux/nfsd_idmap.h>
@@ -365,8 +365,30 @@
 	goto out;
 }
 
-#if defined(CONFIG_NFSD_V4)
+#if defined(CONFIG_NFSD_V2_ACL) || \
+    defined(CONFIG_NFSD_V3_ACL) || \
+    defined(CONFIG_NFSD_V4)
+static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
+{
+	ssize_t buflen;
+	int error;
 
+	buflen = vfs_getxattr(dentry, key, NULL, 0);
+	if (buflen <= 0)
+		return buflen;
+
+	*buf = kmalloc(buflen, GFP_KERNEL);
+	if (!*buf)
+		return -ENOMEM;
+
+	error = vfs_getxattr(dentry, key, *buf, buflen);
+	if (error < 0)
+		return error;
+	return buflen;
+}
+#endif
+
+#if defined(CONFIG_NFSD_V4)
 static int
 set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
 {
@@ -374,7 +396,6 @@
 	size_t buflen;
 	char *buf = NULL;
 	int error = 0;
-	struct inode *inode = dentry->d_inode;
 
 	buflen = posix_acl_xattr_size(pacl->a_count);
 	buf = kmalloc(buflen, GFP_KERNEL);
@@ -388,15 +409,7 @@
 		goto out;
 	}
 
-	error = -EOPNOTSUPP;
-	if (inode->i_op && inode->i_op->setxattr) {
-		mutex_lock(&inode->i_mutex);
-		security_inode_setxattr(dentry, key, buf, len, 0);
-		error = inode->i_op->setxattr(dentry, key, buf, len, 0);
-		if (!error)
-			security_inode_post_setxattr(dentry, key, buf, len, 0);
-		mutex_unlock(&inode->i_mutex);
-	}
+	error = vfs_setxattr(dentry, key, buf, len, 0);
 out:
 	kfree(buf);
 	return error;
@@ -455,44 +468,19 @@
 static struct posix_acl *
 _get_posix_acl(struct dentry *dentry, char *key)
 {
-	struct inode *inode = dentry->d_inode;
-	char *buf = NULL;
-	int buflen, error = 0;
+	void *buf = NULL;
 	struct posix_acl *pacl = NULL;
+	int buflen;
 
-	error = -EOPNOTSUPP;
-	if (inode->i_op == NULL)
-		goto out_err;
-	if (inode->i_op->getxattr == NULL)
-		goto out_err;
-
-	error = security_inode_getxattr(dentry, key);
-	if (error)
-		goto out_err;
-
-	buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
-	if (buflen <= 0) {
-		error = buflen < 0 ? buflen : -ENODATA;
-		goto out_err;
-	}
-
-	buf = kmalloc(buflen, GFP_KERNEL);
-	if (buf == NULL) {
-		error = -ENOMEM;
-		goto out_err;
-	}
-
-	error = inode->i_op->getxattr(dentry, key, buf, buflen);
-	if (error < 0)
-		goto out_err;
+	buflen = nfsd_getxattr(dentry, key, &buf);
+	if (!buflen)
+		buflen = -ENODATA;
+	if (buflen <= 0)
+		return ERR_PTR(buflen);
 
 	pacl = posix_acl_from_xattr(buf, buflen);
- out:
 	kfree(buf);
 	return pacl;
- out_err:
-	pacl = ERR_PTR(error);
-	goto out;
 }
 
 int
@@ -1884,39 +1872,25 @@
 	ssize_t size;
 	struct posix_acl *acl;
 
-	if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
+	if (!IS_POSIXACL(inode))
 		return ERR_PTR(-EOPNOTSUPP);
-	switch(type) {
-		case ACL_TYPE_ACCESS:
-			name = POSIX_ACL_XATTR_ACCESS;
-			break;
-		case ACL_TYPE_DEFAULT:
-			name = POSIX_ACL_XATTR_DEFAULT;
-			break;
-		default:
-			return ERR_PTR(-EOPNOTSUPP);
+
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		name = POSIX_ACL_XATTR_ACCESS;
+		break;
+	case ACL_TYPE_DEFAULT:
+		name = POSIX_ACL_XATTR_DEFAULT;
+		break;
+	default:
+		return ERR_PTR(-EOPNOTSUPP);
 	}
 
-	size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
+	size = nfsd_getxattr(fhp->fh_dentry, name, &value);
+	if (size < 0)
+		return ERR_PTR(size);
 
-	if (size < 0) {
-		acl = ERR_PTR(size);
-		goto getout;
-	} else if (size > 0) {
-		value = kmalloc(size, GFP_KERNEL);
-		if (!value) {
-			acl = ERR_PTR(-ENOMEM);
-			goto getout;
-		}
-		size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
-		if (size < 0) {
-			acl = ERR_PTR(size);
-			goto getout;
-		}
-	}
 	acl = posix_acl_from_xattr(value, size);
-
-getout:
 	kfree(value);
 	return acl;
 }
@@ -1957,16 +1931,13 @@
 	} else
 		size = 0;
 
-	if (!fhp->fh_locked)
-		fh_lock(fhp);  /* unlocking is done automatically */
 	if (size)
-		error = inode->i_op->setxattr(fhp->fh_dentry, name,
-					      value, size, 0);
+		error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
 	else {
 		if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
 			error = 0;
 		else {
-			error = inode->i_op->removexattr(fhp->fh_dentry, name);
+			error = vfs_removexattr(fhp->fh_dentry, name);
 			if (error == -ENODATA)
 				error = 0;
 		}
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 30f71ac..fb413d3 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2173,7 +2173,7 @@
 	err = remove_suid(file->f_dentry);
 	if (err)
 		goto out;
-	inode_update_time(inode, 1);
+	file_update_time(file);
 	written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
 			count);
 out:
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index bda7a08..ea1bd3f 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2767,7 +2767,25 @@
 	up_write(&ni->runlist.lock);
 done:
 	/* Update the mtime and ctime on the base inode. */
-	inode_update_time(VFS_I(base_ni), 1);
+	/* normally ->truncate shouldn't update ctime or mtime,
+	 * but ntfs did before so it got a copy & paste version
+	 * of file_update_time.  one day someone should fix this
+	 * for real.
+	 */
+	if (!IS_NOCMTIME(VFS_I(base_ni)) && !IS_RDONLY(VFS_I(base_ni))) {
+		struct timespec now = current_fs_time(VFS_I(base_ni)->i_sb);
+		int sync_it = 0;
+
+		if (!timespec_equal(&VFS_I(base_ni)->i_mtime, &now) ||
+		    !timespec_equal(&VFS_I(base_ni)->i_ctime, &now))
+			sync_it = 1;
+		VFS_I(base_ni)->i_mtime = now;
+		VFS_I(base_ni)->i_ctime = now;
+
+		if (sync_it)
+			mark_inode_dirty_sync(VFS_I(base_ni));
+	}
+
 	if (likely(!err)) {
 		NInoClearTruncateFailed(ni);
 		ntfs_debug("Done.");
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 280e383..c3a3f1a 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -443,8 +443,8 @@
 
 	ntfs_debug("Entering with remount options string: %s", opt);
 #ifndef NTFS_RW
-	/* For read-only compiled driver, enforce all read-only flags. */
-	*flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+	/* For read-only compiled driver, enforce read-only flag. */
+	*flags |= MS_RDONLY;
 #else /* NTFS_RW */
 	/*
 	 * For the read-write compiled driver, if we are remounting read-write,
@@ -1721,7 +1721,7 @@
 						es3);
 				goto iput_mirr_err_out;
 			}
-			sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+			sb->s_flags |= MS_RDONLY;
 			ntfs_error(sb, "%s.  Mounting read-only%s",
 					!vol->mftmirr_ino ? es1 : es2, es3);
 		} else
@@ -1837,7 +1837,7 @@
 						es1, es2);
 				goto iput_vol_err_out;
 			}
-			sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+			sb->s_flags |= MS_RDONLY;
 			ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
 		} else
 			ntfs_warning(sb, "%s.  Will not be able to remount "
@@ -1874,7 +1874,7 @@
 				}
 				goto iput_logfile_err_out;
 			}
-			sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+			sb->s_flags |= MS_RDONLY;
 			ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
 		} else
 			ntfs_warning(sb, "%s.  Will not be able to remount "
@@ -1919,7 +1919,7 @@
 						es1, es2);
 				goto iput_root_err_out;
 			}
-			sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+			sb->s_flags |= MS_RDONLY;
 			ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
 		} else
 			ntfs_warning(sb, "%s.  Will not be able to remount "
@@ -1943,7 +1943,7 @@
 			goto iput_root_err_out;
 		}
 		ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
-		sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+		sb->s_flags |= MS_RDONLY;
 		/*
 		 * Do not set NVolErrors() because ntfs_remount() might manage
 		 * to set the dirty flag in which case all would be well.
@@ -1970,7 +1970,7 @@
 			goto iput_root_err_out;
 		}
 		ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
-		sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+		sb->s_flags |= MS_RDONLY;
 		NVolSetErrors(vol);
 	}
 #endif
@@ -1989,7 +1989,7 @@
 			goto iput_root_err_out;
 		}
 		ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
-		sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+		sb->s_flags |= MS_RDONLY;
 		NVolSetErrors(vol);
 	}
 #endif /* NTFS_RW */
@@ -2030,7 +2030,7 @@
 						es1, es2);
 				goto iput_quota_err_out;
 			}
-			sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+			sb->s_flags |= MS_RDONLY;
 			ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
 		} else
 			ntfs_warning(sb, "%s.  Will not be able to remount "
@@ -2053,7 +2053,7 @@
 			goto iput_quota_err_out;
 		}
 		ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
-		sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+		sb->s_flags |= MS_RDONLY;
 		NVolSetErrors(vol);
 	}
 	/*
@@ -2074,7 +2074,7 @@
 						es1, es2);
 				goto iput_usnjrnl_err_out;
 			}
-			sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+			sb->s_flags |= MS_RDONLY;
 			ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
 		} else
 			ntfs_warning(sb, "%s.  Will not be able to remount "
@@ -2097,7 +2097,7 @@
 			goto iput_usnjrnl_err_out;
 		}
 		ntfs_error(sb, "%s.  Mounting read-only%s", es1, es2);
-		sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+		sb->s_flags |= MS_RDONLY;
 		NVolSetErrors(vol);
 	}
 #endif /* NTFS_RW */
@@ -2689,7 +2689,7 @@
 
 	ntfs_debug("Entering.");
 #ifndef NTFS_RW
-	sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+	sb->s_flags |= MS_RDONLY;
 #endif /* ! NTFS_RW */
 	/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
 	sb->s_fs_info = kmalloc(sizeof(ntfs_volume), GFP_NOFS);
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index afdeec4..843cf9d 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -80,12 +80,8 @@
 	.nopage = ocfs2_nopage,
 };
 
-int ocfs2_mmap(struct file *file,
-	       struct vm_area_struct *vma)
+int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
-	struct inode *inode = mapping->host;
-
 	/* We don't want to support shared writable mappings yet. */
 	if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
 	    && ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
@@ -95,7 +91,7 @@
 		return -EINVAL;
 	}
 
-	update_atime(inode);
+	file_accessed(file);
 	vma->vm_ops = &ocfs2_file_vm_ops;
 	return 0;
 }
diff --git a/fs/pipe.c b/fs/pipe.c
index acb030b..eef0f29 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -347,7 +347,7 @@
 		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
 	}
 	if (ret > 0)
-		inode_update_time(inode, 1);	/* mtime and ctime */
+		file_update_time(filp);
 	return ret;
 }
 
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 5e9251f..7eb1bd7 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -330,7 +330,7 @@
 	unsigned long  min_flt = 0,  maj_flt = 0;
 	cputime_t cutime, cstime, utime, stime;
 	unsigned long rsslim = 0;
-	unsigned long it_real_value = 0;
+	DEFINE_KTIME(it_real_value);
 	struct task_struct *t;
 	char tcomm[sizeof(task->comm)];
 
@@ -386,7 +386,7 @@
 			utime = cputime_add(utime, task->signal->utime);
 			stime = cputime_add(stime, task->signal->stime);
 		}
-		it_real_value = task->signal->it_real_value;
+		it_real_value = task->signal->real_timer.expires;
 	}
 	ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
 	read_unlock(&tasklist_lock);
@@ -435,7 +435,7 @@
 		priority,
 		nice,
 		num_threads,
-		jiffies_to_clock_t(it_real_value),
+		(long) ktime_to_clock_t(it_real_value),
 		start_time,
 		vsize,
 		mm ? get_mm_rss(mm) : 0,
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 3b2e7b6..5378d7c7 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -35,6 +35,9 @@
 /* Total size of vmcore file. */
 static u64 vmcore_size;
 
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
 struct proc_dir_entry *proc_vmcore = NULL;
 
 /* Reads a page from the oldmem device from given offset. */
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 127e7d2..ad6fa96 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1360,7 +1360,7 @@
 	if (res)
 		goto out;
 
-	inode_update_time(inode, 1);	/* Both mtime and ctime */
+	file_update_time(file);
 
 	// Ok, we are done with all the checks.
 
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index f1895f0..6f99e01 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -497,12 +497,6 @@
 	struct iattr newattrs;
 	__u32 xahash = 0;
 
-	if (IS_RDONLY(inode))
-		return -EROFS;
-
-	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		return -EPERM;
-
 	if (get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
@@ -758,9 +752,6 @@
 	struct dentry *dir;
 	int err;
 
-	if (IS_RDONLY(inode))
-		return -EROFS;
-
 	dir = open_xa_dir(inode, FL_READONLY);
 	if (IS_ERR(dir)) {
 		err = PTR_ERR(dir);
@@ -984,12 +975,6 @@
 	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	if (IS_RDONLY(dentry->d_inode))
-		return -EROFS;
-
-	if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode))
-		return -EROFS;
-
 	reiserfs_write_lock_xattr_i(dentry->d_inode);
 	lock = !has_xattr_dir(dentry->d_inode);
 	if (lock)
@@ -1019,12 +1004,6 @@
 	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	if (IS_RDONLY(dentry->d_inode))
-		return -EROFS;
-
-	if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode))
-		return -EPERM;
-
 	reiserfs_write_lock_xattr_i(dentry->d_inode);
 	reiserfs_read_lock_xattrs(dentry->d_sb);
 
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 5145804..073f393 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -16,18 +16,10 @@
 user_get(struct inode *inode, const char *name, void *buffer, size_t size)
 {
 
-	int error;
-
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
-
 	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-
-	error = reiserfs_permission_locked(inode, MAY_READ, NULL);
-	if (error)
-		return error;
-
 	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
@@ -36,43 +28,21 @@
 	 size_t size, int flags)
 {
 
-	int error;
-
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
 
 	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-
-	if (!S_ISREG(inode->i_mode) &&
-	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-		return -EPERM;
-
-	error = reiserfs_permission_locked(inode, MAY_WRITE, NULL);
-	if (error)
-		return error;
-
 	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
 static int user_del(struct inode *inode, const char *name)
 {
-	int error;
-
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
 
 	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-
-	if (!S_ISREG(inode->i_mode) &&
-	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-		return -EPERM;
-
-	error = reiserfs_permission_locked(inode, MAY_WRITE, NULL);
-	if (error)
-		return error;
-
 	return 0;
 }
 
diff --git a/fs/xattr.c b/fs/xattr.c
index 386a532..80eca7d 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -19,6 +19,149 @@
 #include <linux/fsnotify.h>
 #include <asm/uaccess.h>
 
+
+/*
+ * Check permissions for extended attribute access.  This is a bit complicated
+ * because different namespaces have very different rules.
+ */
+static int
+xattr_permission(struct inode *inode, const char *name, int mask)
+{
+	/*
+	 * We can never set or remove an extended attribute on a read-only
+	 * filesystem  or on an immutable / append-only inode.
+	 */
+	if (mask & MAY_WRITE) {
+		if (IS_RDONLY(inode))
+			return -EROFS;
+		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+			return -EPERM;
+	}
+
+	/*
+	 * No restriction for security.* and system.* from the VFS.  Decision
+	 * on these is left to the underlying filesystem / security module.
+	 */
+	if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
+	    !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+		return 0;
+
+	/*
+	 * The trusted.* namespace can only accessed by a privilegued user.
+	 */
+	if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+		return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
+
+	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
+		if (!S_ISREG(inode->i_mode) &&
+		    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
+			return -EPERM;
+	}
+
+	return permission(inode, mask, NULL);
+}
+
+int
+vfs_setxattr(struct dentry *dentry, char *name, void *value,
+		size_t size, int flags)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	error = xattr_permission(inode, name, MAY_WRITE);
+	if (error)
+		return error;
+
+	mutex_lock(&inode->i_mutex);
+	error = security_inode_setxattr(dentry, name, value, size, flags);
+	if (error)
+		goto out;
+	error = -EOPNOTSUPP;
+	if (inode->i_op->setxattr) {
+		error = inode->i_op->setxattr(dentry, name, value, size, flags);
+		if (!error) {
+			fsnotify_xattr(dentry);
+			security_inode_post_setxattr(dentry, name, value,
+						     size, flags);
+		}
+	} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
+				XATTR_SECURITY_PREFIX_LEN)) {
+		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+		error = security_inode_setsecurity(inode, suffix, value,
+						   size, flags);
+		if (!error)
+			fsnotify_xattr(dentry);
+	}
+out:
+	mutex_unlock(&inode->i_mutex);
+	return error;
+}
+EXPORT_SYMBOL_GPL(vfs_setxattr);
+
+ssize_t
+vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	error = xattr_permission(inode, name, MAY_READ);
+	if (error)
+		return error;
+
+	error = security_inode_getxattr(dentry, name);
+	if (error)
+		return error;
+
+	if (inode->i_op->getxattr)
+		error = inode->i_op->getxattr(dentry, name, value, size);
+	else
+		error = -EOPNOTSUPP;
+
+	if (!strncmp(name, XATTR_SECURITY_PREFIX,
+				XATTR_SECURITY_PREFIX_LEN)) {
+		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+		int ret = security_inode_getsecurity(inode, suffix, value,
+						     size, error);
+		/*
+		 * Only overwrite the return value if a security module
+		 * is actually active.
+		 */
+		if (ret != -EOPNOTSUPP)
+			error = ret;
+	}
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(vfs_getxattr);
+
+int
+vfs_removexattr(struct dentry *dentry, char *name)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	if (!inode->i_op->removexattr)
+		return -EOPNOTSUPP;
+
+	error = xattr_permission(inode, name, MAY_WRITE);
+	if (error)
+		return error;
+
+	error = security_inode_removexattr(dentry, name);
+	if (error)
+		return error;
+
+	mutex_lock(&inode->i_mutex);
+	error = inode->i_op->removexattr(dentry, name);
+	mutex_unlock(&inode->i_mutex);
+
+	if (!error)
+		fsnotify_xattr(dentry);
+	return error;
+}
+EXPORT_SYMBOL_GPL(vfs_removexattr);
+
+
 /*
  * Extended attribute SET operations
  */
@@ -51,29 +194,7 @@
 		}
 	}
 
-	mutex_lock(&d->d_inode->i_mutex);
-	error = security_inode_setxattr(d, kname, kvalue, size, flags);
-	if (error)
-		goto out;
-	error = -EOPNOTSUPP;
-	if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
-		error = d->d_inode->i_op->setxattr(d, kname, kvalue,
-						   size, flags);
-		if (!error) {
-			fsnotify_xattr(d);
-			security_inode_post_setxattr(d, kname, kvalue,
-						     size, flags);
-		}
-	} else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
-			    sizeof XATTR_SECURITY_PREFIX - 1)) {
-		const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
-		error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
-						   size, flags);
-		if (!error)
-			fsnotify_xattr(d);
-	}
-out:
-	mutex_unlock(&d->d_inode->i_mutex);
+	error = vfs_setxattr(d, kname, kvalue, size, flags);
 	kfree(kvalue);
 	return error;
 }
@@ -147,22 +268,7 @@
 			return -ENOMEM;
 	}
 
-	error = security_inode_getxattr(d, kname);
-	if (error)
-		goto out;
-	error = -EOPNOTSUPP;
-	if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
-		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
-
-	if (!strncmp(kname, XATTR_SECURITY_PREFIX,
-		     sizeof XATTR_SECURITY_PREFIX - 1)) {
-		const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
-		int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue,
-						    size, error);
-		/* Security module active: overwrite error value */
-		if (rv != -EOPNOTSUPP)
-			error = rv;
-	}
+	error = vfs_getxattr(d, kname, kvalue, size);
 	if (error > 0) {
 		if (size && copy_to_user(value, kvalue, error))
 			error = -EFAULT;
@@ -171,7 +277,6 @@
 		   than XATTR_SIZE_MAX bytes. Not possible. */
 		error = -E2BIG;
 	}
-out:
 	kfree(kvalue);
 	return error;
 }
@@ -318,19 +423,7 @@
 	if (error < 0)
 		return error;
 
-	error = -EOPNOTSUPP;
-	if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
-		error = security_inode_removexattr(d, kname);
-		if (error)
-			goto out;
-		mutex_lock(&d->d_inode->i_mutex);
-		error = d->d_inode->i_op->removexattr(d, kname);
-		mutex_unlock(&d->d_inode->i_mutex);
-		if (!error)
-			fsnotify_xattr(d);
-	}
-out:
-	return error;
+	return vfs_removexattr(d, kname);
 }
 
 asmlinkage long
diff --git a/fs/xfs/Kbuild b/fs/xfs/Kbuild
new file mode 100644
index 0000000..2566e96
--- /dev/null
+++ b/fs/xfs/Kbuild
@@ -0,0 +1,6 @@
+#
+# The xfs people like to share Makefile with 2.6 and 2.4.
+# Utilise file named Kbuild file which has precedence over Makefile.
+#
+
+include $(srctree)/$(obj)/Makefile-linux-2.6
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index b78b5eb..f98c5be 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -530,6 +530,8 @@
 	char			*kbuf;
 	int			error = EFAULT;
 
+	if (IS_RDONLY(&vp->v_inode))
+		return -EROFS;
 	if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
 		return EPERM;
 	if (len > XATTR_SIZE_MAX)
@@ -557,6 +559,9 @@
 {
 	int			error;
 
+
+	if (IS_RDONLY(&vp->v_inode))
+		return -EROFS;
 	if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
 		return EPERM;
 
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index c83ae15..a7c9ba1 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -19,7 +19,6 @@
 #include <linux/compat.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
-#include <linux/ioctl32.h>
 #include <linux/syscalls.h>
 #include <linux/types.h>
 #include <linux/fs.h>
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 41c478b..97fb147 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -54,6 +54,9 @@
 #include <linux/xattr.h>
 #include <linux/namei.h>
 
+#define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) ||	\
+	(S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME))
+
 /*
  * Change the requested timestamp in the given inode.
  * We don't lock across timestamp updates, and we don't log them but
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 5675117..885dfaf 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -713,7 +713,7 @@
 	}
 
 	if (likely(!(ioflags & IO_INVIS))) {
-		inode_update_time(inode, 1);
+		file_update_time(file);
 		xfs_ichgtime_fast(xip, inode,
 				  XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	}
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 5484eeb..1a11c2b 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -117,11 +117,6 @@
 	     ip->i_d.di_anextents == 0))
 		return(ENOATTR);
 
-	if (!(flags & (ATTR_KERNACCESS|ATTR_SECURE))) {
-		if ((error = xfs_iaccess(ip, S_IRUSR, cred)))
-			return(XFS_ERROR(error));
-	}
-
 	/*
 	 * Fill in the arg structure for this request.
 	 */
@@ -425,7 +420,7 @@
 	     struct cred *cred)
 {
 	xfs_inode_t	*dp;
-	int             namelen, error;
+	int             namelen;
 
 	namelen = strlen(name);
 	if (namelen >= MAXNAMELEN)
@@ -437,14 +432,6 @@
 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 		return (EIO);
 
-	xfs_ilock(dp, XFS_ILOCK_SHARED);
-	if (!(flags & ATTR_SECURE) &&
-	     (error = xfs_iaccess(dp, S_IWUSR, cred))) {
-		xfs_iunlock(dp, XFS_ILOCK_SHARED);
-		return(XFS_ERROR(error));
-	}
-	xfs_iunlock(dp, XFS_ILOCK_SHARED);
-
 	return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags);
 }
 
@@ -579,7 +566,7 @@
 xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
 {
 	xfs_inode_t         *dp;
-	int                 namelen, error;
+	int                 namelen;
 
 	namelen = strlen(name);
 	if (namelen >= MAXNAMELEN)
@@ -592,11 +579,7 @@
 		return (EIO);
 
 	xfs_ilock(dp, XFS_ILOCK_SHARED);
-	if (!(flags & ATTR_SECURE) &&
-	     (error = xfs_iaccess(dp, S_IWUSR, cred))) {
-		xfs_iunlock(dp, XFS_ILOCK_SHARED);
-		return(XFS_ERROR(error));
-	} else if (XFS_IFORK_Q(dp) == 0 ||
+	if (XFS_IFORK_Q(dp) == 0 ||
 		   (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 		    dp->i_d.di_anextents == 0)) {
 		xfs_iunlock(dp, XFS_ILOCK_SHARED);
@@ -668,12 +651,6 @@
 		return (EIO);
 
 	xfs_ilock(dp, XFS_ILOCK_SHARED);
-	if (!(flags & ATTR_SECURE) &&
-	     (error = xfs_iaccess(dp, S_IRUSR, cred))) {
-		xfs_iunlock(dp, XFS_ILOCK_SHARED);
-		return(XFS_ERROR(error));
-	}
-
 	/*
 	 * Decide on what work routines to call based on the inode size.
 	 */
diff --git a/include/asm-arm/ioctl.h b/include/asm-arm/ioctl.h
index 2cbb7d0..b279fe0 100644
--- a/include/asm-arm/ioctl.h
+++ b/include/asm-arm/ioctl.h
@@ -1,74 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMARM_IOCTL_H
-#define _ASMARM_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASMARM_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-arm26/ioctl.h b/include/asm-arm26/ioctl.h
index 2cbb7d0..b279fe0 100644
--- a/include/asm-arm26/ioctl.h
+++ b/include/asm-arm26/ioctl.h
@@ -1,74 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMARM_IOCTL_H
-#define _ASMARM_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASMARM_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-cris/ioctl.h b/include/asm-cris/ioctl.h
index be2d8f6..b279fe0 100644
--- a/include/asm-cris/ioctl.h
+++ b/include/asm-cris/ioctl.h
@@ -1,83 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- *
- * This is the same as the i386 version.
- */
-
-#ifndef _ASMCRIS_IOCTL_H
-#define _ASMCRIS_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* provoke compile error for invalid uses of size argument */
-extern int __invalid_size_argument_for_IOC;
-#define _IOC_TYPECHECK(t) \
-	((sizeof(t) == sizeof(t[1]) && \
-	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
-	  sizeof(t) : __invalid_size_argument_for_IOC)
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASMCRIS_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-frv/ioctl.h b/include/asm-frv/ioctl.h
index 8aee769..b279fe0 100644
--- a/include/asm-frv/ioctl.h
+++ b/include/asm-frv/ioctl.h
@@ -1,80 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASM_IOCTL_H
-#define _ASM_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASM_IOCTL_H */
-
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-generic/ioctl.h b/include/asm-generic/ioctl.h
new file mode 100644
index 0000000..cd02729
--- /dev/null
+++ b/include/asm-generic/ioctl.h
@@ -0,0 +1,80 @@
+#ifndef _ASM_GENERIC_IOCTL_H
+#define _ASM_GENERIC_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The generic ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* provoke compile error for invalid uses of size argument */
+extern unsigned int __invalid_size_argument_for_IOC;
+#define _IOC_TYPECHECK(t) \
+	((sizeof(t) == sizeof(t[1]) && \
+	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
+	  sizeof(t) : __invalid_size_argument_for_IOC)
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* _ASM_GENERIC_IOCTL_H */
diff --git a/include/asm-h8300/ioctl.h b/include/asm-h8300/ioctl.h
index 031c623..b279fe0 100644
--- a/include/asm-h8300/ioctl.h
+++ b/include/asm-h8300/ioctl.h
@@ -1,80 +1 @@
-/* $Id: ioctl.h,v 1.1 2002/11/19 02:09:26 gerg Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _H8300_IOCTL_H
-#define _H8300_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _H8300_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-i386/ioctl.h b/include/asm-i386/ioctl.h
index 543f784..b279fe0 100644
--- a/include/asm-i386/ioctl.h
+++ b/include/asm-i386/ioctl.h
@@ -1,85 +1 @@
-/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMI386_IOCTL_H
-#define _ASMI386_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* provoke compile error for invalid uses of size argument */
-extern unsigned int __invalid_size_argument_for_IOC;
-#define _IOC_TYPECHECK(t) \
-	((sizeof(t) == sizeof(t[1]) && \
-	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
-	  sizeof(t) : __invalid_size_argument_for_IOC)
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASMI386_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-i386/kexec.h b/include/asm-i386/kexec.h
index 6ed2a03..53f0e06 100644
--- a/include/asm-i386/kexec.h
+++ b/include/asm-i386/kexec.h
@@ -2,6 +2,8 @@
 #define _I386_KEXEC_H
 
 #include <asm/fixmap.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
 
 /*
  * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
@@ -26,8 +28,49 @@
 #define KEXEC_ARCH KEXEC_ARCH_386
 
 #define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
 
-extern note_buf_t crash_notes[];
+/* CPU does not save ss and esp on stack if execution is already
+ * running in kernel mode at the time of NMI occurrence. This code
+ * fixes it.
+ */
+static inline void crash_fixup_ss_esp(struct pt_regs *newregs,
+					struct pt_regs *oldregs)
+{
+	memcpy(newregs, oldregs, sizeof(*newregs));
+	newregs->esp = (unsigned long)&(oldregs->esp);
+	__asm__ __volatile__(
+			"xorl %%eax, %%eax\n\t"
+			"movw %%ss, %%ax\n\t"
+			:"=a"(newregs->xss));
+}
+
+/*
+ * This function is responsible for capturing register states if coming
+ * via panic otherwise just fix up the ss and esp if coming via kernel
+ * mode exception.
+ */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                       struct pt_regs *oldregs)
+{
+       if (oldregs)
+               crash_fixup_ss_esp(newregs, oldregs);
+       else {
+               __asm__ __volatile__("movl %%ebx,%0" : "=m"(newregs->ebx));
+               __asm__ __volatile__("movl %%ecx,%0" : "=m"(newregs->ecx));
+               __asm__ __volatile__("movl %%edx,%0" : "=m"(newregs->edx));
+               __asm__ __volatile__("movl %%esi,%0" : "=m"(newregs->esi));
+               __asm__ __volatile__("movl %%edi,%0" : "=m"(newregs->edi));
+               __asm__ __volatile__("movl %%ebp,%0" : "=m"(newregs->ebp));
+               __asm__ __volatile__("movl %%eax,%0" : "=m"(newregs->eax));
+               __asm__ __volatile__("movl %%esp,%0" : "=m"(newregs->esp));
+               __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(newregs->xss));
+               __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(newregs->xcs));
+               __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(newregs->xds));
+               __asm__ __volatile__("movw %%es, %%ax;" :"=a"(newregs->xes));
+               __asm__ __volatile__("pushfl; popl %0" :"=m"(newregs->eflags));
+
+               newregs->eip = (unsigned long)current_text_addr();
+       }
+}
 
 #endif /* _I386_KEXEC_H */
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index ca916a8..27cac05 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -40,6 +40,7 @@
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define ARCH_SUPPORTS_KRETPROBES
+#define arch_remove_kprobe(p)	do {} while (0)
 
 void kretprobe_trampoline(void);
 
@@ -76,14 +77,6 @@
 		local_irq_enable();
 }
 
-#ifdef CONFIG_KPROBES
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
-#else				/* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
-					   unsigned long val, void *data)
-{
-	return 0;
-}
-#endif
 #endif				/* _ASM_KPROBES_H */
diff --git a/include/asm-ia64/ioctl.h b/include/asm-ia64/ioctl.h
index be9cc24..b279fe0 100644
--- a/include/asm-ia64/ioctl.h
+++ b/include/asm-ia64/ioctl.h
@@ -1,77 +1 @@
-#ifndef _ASM_IA64_IOCTL_H
-#define _ASM_IA64_IOCTL_H
-
-/*
- * Based on <asm-i386/ioctl.h>.
- *
- * Modified 1998, 1999
- *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The ia64 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASM_IA64_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 592abb0..a74b681 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -89,6 +89,7 @@
 #define IP_RELATIVE_PREDICT_OPCODE	(7)
 #define LONG_BRANCH_OPCODE		(0xC)
 #define LONG_CALL_OPCODE		(0xD)
+#define arch_remove_kprobe(p)		do {} while (0)
 
 typedef struct kprobe_opcode {
 	bundle_t bundle;
@@ -110,12 +111,6 @@
  	unsigned short target_br_reg;
 };
 
-/* ia64 does not need this */
-static inline void arch_copy_kprobe(struct kprobe *p)
-{
-}
-
-#ifdef CONFIG_KPROBES
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
@@ -124,11 +119,4 @@
 {
 }
 
-#else				/* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
-					   unsigned long val, void *data)
-{
-	return 0;
-}
-#endif
 #endif				/* _ASM_KPROBES_H */
diff --git a/include/asm-m32r/ioctl.h b/include/asm-m32r/ioctl.h
index 87d8f7d..b279fe0 100644
--- a/include/asm-m32r/ioctl.h
+++ b/include/asm-m32r/ioctl.h
@@ -1,78 +1 @@
-#ifndef _ASM_M32R_IOCTL_H
-#define _ASM_M32R_IOCTL_H
-
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASM_M32R_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-m68k/ioctl.h b/include/asm-m68k/ioctl.h
index fd68914..b279fe0 100644
--- a/include/asm-m68k/ioctl.h
+++ b/include/asm-m68k/ioctl.h
@@ -1,80 +1 @@
-/* $Id: ioctl.h,v 1.3 1997/04/16 15:10:07 jes Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _M68K_IOCTL_H
-#define _M68K_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _M68K_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-m68knommu/ioctl.h b/include/asm-m68knommu/ioctl.h
index cff72f3..b279fe0 100644
--- a/include/asm-m68knommu/ioctl.h
+++ b/include/asm-m68knommu/ioctl.h
@@ -1 +1 @@
-#include <asm-m68k/ioctl.h>
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h
index 4395b7b..b263fb2 100644
--- a/include/asm-powerpc/eeh.h
+++ b/include/asm-powerpc/eeh.h
@@ -34,9 +34,11 @@
 extern int eeh_subsystem_enabled;
 
 /* Values for eeh_mode bits in device_node */
-#define EEH_MODE_SUPPORTED	(1<<0)
-#define EEH_MODE_NOCHECK	(1<<1)
-#define EEH_MODE_ISOLATED	(1<<2)
+#define EEH_MODE_SUPPORTED     (1<<0)
+#define EEH_MODE_NOCHECK       (1<<1)
+#define EEH_MODE_ISOLATED      (1<<2)
+#define EEH_MODE_RECOVERING    (1<<3)
+#define EEH_MODE_IRQ_DISABLED  (1<<4)
 
 /* Max number of EEH freezes allowed before we consider the device
  * to be permanently disabled. */
diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h
index 5e11a00..93d55a2 100644
--- a/include/asm-powerpc/eeh_event.h
+++ b/include/asm-powerpc/eeh_event.h
@@ -30,7 +30,7 @@
 	struct list_head     list;
 	struct device_node 	*dn;   /* struct device node */
 	struct pci_dev       *dev;  /* affected device */
-	int                  state;
+	enum pci_channel_state state; /* PCI bus state for the affected device */
 	int time_unavail;    /* milliseconds until device might be available */
 };
 
@@ -47,8 +47,11 @@
  */
 int eeh_send_failure_event (struct device_node *dn,
                             struct pci_dev *dev,
-                            int reset_state,
+                            enum pci_channel_state state,
                             int time_unavail);
 
+/* Main recovery function */
+void handle_eeh_events (struct eeh_event *);
+
 #endif /* __KERNEL__ */
 #endif /* ASM_PPC64_EEH_EVENT_H */
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h
index 4263af3..fffdf69 100644
--- a/include/asm-powerpc/kexec.h
+++ b/include/asm-powerpc/kexec.h
@@ -38,9 +38,6 @@
 #ifdef CONFIG_KEXEC
 
 #define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES / sizeof(u32)];
-
-extern note_buf_t crash_notes[];
 
 #ifdef __powerpc64__
 extern void kexec_smp_wait(void);	/* get and clear naca physid, wait for
@@ -58,6 +55,12 @@
 
 #endif /* !CONFIG_KEXEC */
 
+/*
+ * Provide a dummy definition to avoid build failures. Will remain
+ * empty till crash dump support is enabled.
+ */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+					struct pt_regs *oldregs) { }
 #endif /* ! __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_KEXEC_H */
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index 0654f79..f466bc8 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -30,7 +30,10 @@
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
 
+#define  __ARCH_WANT_KPROBES_INSN_SLOT
+
 struct pt_regs;
+struct kprobe;
 
 typedef unsigned int kprobe_opcode_t;
 #define BREAKPOINT_INSTRUCTION	0x7fe00008	/* trap */
@@ -48,6 +51,7 @@
 
 #define ARCH_SUPPORTS_KRETPROBES
 void kretprobe_trampoline(void);
+extern void arch_remove_kprobe(struct kprobe *p);
 
 /* Architecture specific copy of original instruction */
 struct arch_specific_insn {
@@ -69,15 +73,7 @@
 	struct prev_kprobe prev_kprobe;
 };
 
-#ifdef CONFIG_KPROBES
 extern int kprobe_exceptions_notify(struct notifier_block *self,
-				    unsigned long val, void *data);
-#else				/* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
-					   unsigned long val, void *data)
-{
-	return 0;
-}
-#endif
+					unsigned long val, void *data);
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_KPROBES_H */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 1a08860..b0d816f 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -61,16 +61,17 @@
 struct iommu_table;
 
 struct pci_dn {
-	int	busno;			/* for pci devices */
-	int	bussubno;		/* for pci devices */
-	int	devfn;			/* for pci devices */
+	int	busno;			/* pci bus number */
+	int	bussubno;		/* pci subordinate bus number */
+	int	devfn;			/* pci device and function number */
+	int	class_code;		/* pci device class */
 
 #ifdef CONFIG_PPC_PSERIES
 	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
 	int	eeh_config_addr;
+	int	eeh_pe_config_addr; /* new-style partition endpoint address */
 	int 	eeh_check_count;	/* # times driver ignored error */
 	int 	eeh_freeze_count;	/* # times this device froze up. */
-	int	eeh_is_bridge;		/* device is pci-to-pci bridge */
 #endif
 	int	pci_ext_config_space;	/* for pci devices */
 	struct  pci_controller *phb;	/* for pci devices */
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index bdef312..f80482c 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -52,6 +52,21 @@
 
 /* ---- EEH internal-use-only related routines ---- */
 #ifdef CONFIG_EEH
+
+void pci_addr_cache_insert_device(struct pci_dev *dev);
+void pci_addr_cache_remove_device(struct pci_dev *dev);
+void pci_addr_cache_build(void);
+struct pci_dev *pci_get_device_by_addr(unsigned long addr);
+
+/**
+ * eeh_slot_error_detail -- record and EEH error condition to the log
+ * @severity: 1 if temporary, 2 if permanent failure.
+ *
+ * Obtains the the EEH error details from the RTAS subsystem,
+ * and then logs these details with the RTAS error log system.
+ */
+void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
+
 /**
  * rtas_set_slot_reset -- unfreeze a frozen slot
  *
@@ -59,8 +74,10 @@
  * does this by asserting the PCI #RST line for 1/8th of
  * a second; this routine will sleep while the adapter is
  * being reset.
+ *
+ * Returns a non-zero value if the reset failed.
  */
-void rtas_set_slot_reset (struct pci_dn *);
+int rtas_set_slot_reset (struct pci_dn *);
 
 /** 
  * eeh_restore_bars - Restore device configuration info.
@@ -84,6 +101,7 @@
 void rtas_configure_bridge(struct pci_dn *);
 
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
+int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 
 /**
  * mark and clear slots: find "partition endpoint" PE and set or 
@@ -92,6 +110,9 @@
 void eeh_mark_slot (struct device_node *dn, int mode_flag);
 void eeh_clear_slot (struct device_node *dn, int mode_flag);
 
+/* Find the associated "Partiationable Endpoint" PE */
+struct device_node * find_device_pe(struct device_node *dn);
+
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/serial.h b/include/asm-powerpc/serial.h
index 6dc9546..3e8589b 100644
--- a/include/asm-powerpc/serial.h
+++ b/include/asm-powerpc/serial.h
@@ -15,6 +15,10 @@
 /* Default baud base if not found in device-tree */
 #define BASE_BAUD ( 1843200 / 16 )
 
+#ifdef CONFIG_PPC_UDBG_16550
 extern void find_legacy_serial_ports(void);
+#else
+#define find_legacy_serial_ports()	do { } while (0)
+#endif
 
 #endif /* _PPC64_SERIAL_H */
diff --git a/include/asm-s390/ioctl.h b/include/asm-s390/ioctl.h
index df73943..b279fe0 100644
--- a/include/asm-s390/ioctl.h
+++ b/include/asm-s390/ioctl.h
@@ -1,88 +1 @@
-/*
- *  include/asm-s390/ioctl.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/ioctl.h"
- */
-
-#ifndef _S390_IOCTL_H
-#define _S390_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* provoke compile error for invalid uses of size argument */
-extern unsigned long __invalid_size_argument_for_IOC;
-#define _IOC_TYPECHECK(t) \
-	((sizeof(t) == sizeof(t[1]) && \
-	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
-	  sizeof(t) : __invalid_size_argument_for_IOC)
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
-#define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _S390_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-s390/kexec.h b/include/asm-s390/kexec.h
index 54cf7d9..ce28ddd 100644
--- a/include/asm-s390/kexec.h
+++ b/include/asm-s390/kexec.h
@@ -35,8 +35,9 @@
 #define KEXEC_ARCH KEXEC_ARCH_S390
 
 #define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
 
-extern note_buf_t crash_notes[];
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+					struct pt_regs *oldregs) { }
 
 #endif /*_S390_KEXEC_H */
diff --git a/include/asm-sh/ioctl.h b/include/asm-sh/ioctl.h
index 524700e..b279fe0 100644
--- a/include/asm-sh/ioctl.h
+++ b/include/asm-sh/ioctl.h
@@ -1,75 +1 @@
-/* $Id: ioctl.h,v 1.1.1.1 2001/10/15 20:45:09 mrbrown Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef __ASM_SH_IOCTL_H
-#define __ASM_SH_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* __ASM_SH_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-sh64/io.h b/include/asm-sh64/io.h
index cfafaa7..dee4f77 100644
--- a/include/asm-sh64/io.h
+++ b/include/asm-sh64/io.h
@@ -143,12 +143,12 @@
  * Change virtual addresses to physical addresses and vv.
  * These are trivial on the 1:1 Linux/SuperH mapping
  */
-extern __inline__ unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
 {
 	return __pa(address);
 }
 
-extern __inline__ void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
 {
 	return __va(address);
 }
@@ -156,12 +156,12 @@
 extern void * __ioremap(unsigned long phys_addr, unsigned long size,
 			unsigned long flags);
 
-extern __inline__ void * ioremap(unsigned long phys_addr, unsigned long size)
+static inline void * ioremap(unsigned long phys_addr, unsigned long size)
 {
 	return __ioremap(phys_addr, size, 1);
 }
 
-extern __inline__ void * ioremap_nocache (unsigned long phys_addr, unsigned long size)
+static inline void * ioremap_nocache (unsigned long phys_addr, unsigned long size)
 {
 	return __ioremap(phys_addr, size, 0);
 }
diff --git a/include/asm-sh64/ioctl.h b/include/asm-sh64/ioctl.h
index c089a6f..b279fe0 100644
--- a/include/asm-sh64/ioctl.h
+++ b/include/asm-sh64/ioctl.h
@@ -1,83 +1 @@
-#ifndef __ASM_SH64_IOCTL_H
-#define __ASM_SH64_IOCTL_H
-
-/*
- * 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.
- *
- * include/asm-sh64/ioctl.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- *
- */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* __ASM_SH64_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-sh64/mmu_context.h b/include/asm-sh64/mmu_context.h
index f062e15..991cfda 100644
--- a/include/asm-sh64/mmu_context.h
+++ b/include/asm-sh64/mmu_context.h
@@ -50,7 +50,7 @@
  */
 #define MMU_VPN_MASK	0xfffff000
 
-extern __inline__ void
+static inline void
 get_new_mmu_context(struct mm_struct *mm)
 {
 	extern void flush_tlb_all(void);
diff --git a/include/asm-sh64/pgalloc.h b/include/asm-sh64/pgalloc.h
index b25f5df..678251a 100644
--- a/include/asm-sh64/pgalloc.h
+++ b/include/asm-sh64/pgalloc.h
@@ -38,14 +38,14 @@
  * if any.
  */
 
-extern __inline__ pgd_t *get_pgd_slow(void)
+static inline pgd_t *get_pgd_slow(void)
 {
 	unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
 	pgd_t *ret = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
 	return ret;
 }
 
-extern __inline__ pgd_t *get_pgd_fast(void)
+static inline pgd_t *get_pgd_fast(void)
 {
 	unsigned long *ret;
 
@@ -62,14 +62,14 @@
 	return (pgd_t *)ret;
 }
 
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
+static inline void free_pgd_fast(pgd_t *pgd)
 {
 	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
 	pgd_quicklist = (unsigned long *) pgd;
 	pgtable_cache_size++;
 }
 
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
+static inline void free_pgd_slow(pgd_t *pgd)
 {
 	kfree((void *)pgd);
 }
@@ -77,7 +77,7 @@
 extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
 extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
 
-extern __inline__ pte_t *get_pte_fast(void)
+static inline pte_t *get_pte_fast(void)
 {
 	unsigned long *ret;
 
@@ -89,7 +89,7 @@
 	return (pte_t *)ret;
 }
 
-extern __inline__ void free_pte_fast(pte_t *pte)
+static inline void free_pte_fast(pte_t *pte)
 {
 	*(unsigned long *)pte = (unsigned long) pte_quicklist;
 	pte_quicklist = (unsigned long *) pte;
@@ -167,7 +167,7 @@
 
 extern int do_check_pgt_cache(int, int);
 
-extern inline void set_pgdir(unsigned long address, pgd_t entry)
+static inline void set_pgdir(unsigned long address, pgd_t entry)
 {
 	struct task_struct * p;
 	pgd_t *pgd;
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index a1906a7..57af6b3 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -421,18 +421,18 @@
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
 
-extern inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
-extern inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
-extern inline pte_t pte_mkold(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
+static inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
+static inline pte_t pte_wrprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
+static inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
+static inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
+static inline pte_t pte_mkold(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
 
-extern inline pte_t pte_mkread(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
-extern inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+static inline pte_t pte_mkread(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
+static inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
+static inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
+static inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
+static inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+static inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
 
 
 /*
@@ -456,7 +456,7 @@
 #define mk_pte_phys(physpage, pgprot) \
 ({ pte_t __pte; set_pte(&__pte, __pte(physpage | pgprot_val(pgprot))); __pte; })
 
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; }
 
 typedef pte_t *pte_addr_t;
diff --git a/include/asm-sh64/processor.h b/include/asm-sh64/processor.h
index a51bd41..1bf252d 100644
--- a/include/asm-sh64/processor.h
+++ b/include/asm-sh64/processor.h
@@ -228,7 +228,7 @@
  * FPU lazy state save handling.
  */
 
-extern __inline__ void release_fpu(void)
+static inline void release_fpu(void)
 {
 	unsigned long long __dummy;
 
@@ -240,7 +240,7 @@
 			     : "r" (SR_FD));
 }
 
-extern __inline__ void grab_fpu(void)
+static inline void grab_fpu(void)
 {
 	unsigned long long __dummy;
 
diff --git a/include/asm-sh64/system.h b/include/asm-sh64/system.h
index 42510e4..3002e988 100644
--- a/include/asm-sh64/system.h
+++ b/include/asm-sh64/system.h
@@ -132,7 +132,7 @@
 	(flags != 0);			\
 })
 
-extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
@@ -143,7 +143,7 @@
 	return retval;
 }
 
-extern __inline__ unsigned long xchg_u8(volatile unsigned char * m, unsigned long val)
+static inline unsigned long xchg_u8(volatile unsigned char * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
diff --git a/include/asm-sh64/tlbflush.h b/include/asm-sh64/tlbflush.h
index 15c0719..e45bead 100644
--- a/include/asm-sh64/tlbflush.h
+++ b/include/asm-sh64/tlbflush.h
@@ -20,7 +20,7 @@
 extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			    unsigned long end);
 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
 				      unsigned long start, unsigned long end)
 {
 }
diff --git a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
index 56aa3cf..f4936d8 100644
--- a/include/asm-sh64/uaccess.h
+++ b/include/asm-sh64/uaccess.h
@@ -287,7 +287,7 @@
  */
 extern long __strnlen_user(const char *__s, long __n);
 
-extern __inline__ long strnlen_user(const char *s, long n)
+static inline long strnlen_user(const char *s, long n)
 {
 	if (!__addr_ok(s))
 		return 0;
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 7ba8453..e4efe65 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -12,6 +12,7 @@
 #define MAX_INSN_SIZE 2
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
+#define arch_remove_kprobe(p)	do {} while (0)
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
@@ -38,15 +39,6 @@
 	struct prev_kprobe prev_kprobe;
 };
 
-#ifdef CONFIG_KPROBES
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
-#else				/* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
-					   unsigned long val, void *data)
-{
-	return 0;
-}
-#endif
-
 #endif /* _SPARC64_KPROBES_H */
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index 075771c..da07a69 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -89,7 +89,6 @@
 
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-extern void dump_thread(struct pt_regs *regs, struct user *u);
 
 static inline void prepare_to_copy(struct task_struct *tsk)
 {
diff --git a/include/asm-v850/ioctl.h b/include/asm-v850/ioctl.h
index 1765df6..b279fe0 100644
--- a/include/asm-v850/ioctl.h
+++ b/include/asm-v850/ioctl.h
@@ -1,80 +1 @@
-/* $Id: ioctl.h,v 1.1 2002/09/28 14:58:41 gerg Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _V850_IOCTL_H
-#define _V850_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* __V850_IOCTL_H__ */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index e682edc..8dcc326 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -55,6 +55,7 @@
 				    unsigned long end_pfn);
 
 extern void __init parse_memopt(char *p, char **end);
+extern void __init parse_memmapopt(char *p, char **end);
 
 extern struct e820map e820;
 #endif/*!__ASSEMBLY__*/
diff --git a/include/asm-x86_64/ioctl.h b/include/asm-x86_64/ioctl.h
index 609b663..b279fe0 100644
--- a/include/asm-x86_64/ioctl.h
+++ b/include/asm-x86_64/ioctl.h
@@ -1,75 +1 @@
-/* $Id: ioctl.h,v 1.2 2001/07/04 09:08:13 ak Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMX8664_IOCTL_H
-#define _ASMX8664_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif /* _ASMX8664_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-x86_64/kexec.h b/include/asm-x86_64/kexec.h
index 42d2ff1..ae28cd4 100644
--- a/include/asm-x86_64/kexec.h
+++ b/include/asm-x86_64/kexec.h
@@ -3,6 +3,7 @@
 
 #include <asm/page.h>
 #include <asm/proto.h>
+#include <asm/ptrace.h>
 
 /*
  * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
@@ -26,8 +27,40 @@
 #define KEXEC_ARCH KEXEC_ARCH_X86_64
 
 #define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
 
-extern note_buf_t crash_notes[];
+/*
+ * Saving the registers of the cpu on which panic occured in
+ * crash_kexec to save a valid sp. The registers of other cpus
+ * will be saved in machine_crash_shutdown while shooting down them.
+ */
 
+static inline void crash_setup_regs(struct pt_regs *newregs,
+						struct pt_regs *oldregs)
+{
+	if (oldregs)
+		memcpy(newregs, oldregs, sizeof(*newregs));
+	else {
+		__asm__ __volatile__("movq %%rbx,%0" : "=m"(newregs->rbx));
+		__asm__ __volatile__("movq %%rcx,%0" : "=m"(newregs->rcx));
+		__asm__ __volatile__("movq %%rdx,%0" : "=m"(newregs->rdx));
+		__asm__ __volatile__("movq %%rsi,%0" : "=m"(newregs->rsi));
+		__asm__ __volatile__("movq %%rdi,%0" : "=m"(newregs->rdi));
+		__asm__ __volatile__("movq %%rbp,%0" : "=m"(newregs->rbp));
+		__asm__ __volatile__("movq %%rax,%0" : "=m"(newregs->rax));
+		__asm__ __volatile__("movq %%rsp,%0" : "=m"(newregs->rsp));
+		__asm__ __volatile__("movq %%r8,%0" : "=m"(newregs->r8));
+		__asm__ __volatile__("movq %%r9,%0" : "=m"(newregs->r9));
+		__asm__ __volatile__("movq %%r10,%0" : "=m"(newregs->r10));
+		__asm__ __volatile__("movq %%r11,%0" : "=m"(newregs->r11));
+		__asm__ __volatile__("movq %%r12,%0" : "=m"(newregs->r12));
+		__asm__ __volatile__("movq %%r13,%0" : "=m"(newregs->r13));
+		__asm__ __volatile__("movq %%r14,%0" : "=m"(newregs->r14));
+		__asm__ __volatile__("movq %%r15,%0" : "=m"(newregs->r15));
+		__asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
+		__asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
+		__asm__ __volatile__("pushfq; popq %0" :"=m"(newregs->eflags));
+
+		newregs->rip = (unsigned long)current_text_addr();
+	}
+}
 #endif /* _X86_64_KEXEC_H */
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index 4dd7a7e..98a1e95d 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -27,7 +27,10 @@
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
 
+#define  __ARCH_WANT_KPROBES_INSN_SLOT
+
 struct pt_regs;
+struct kprobe;
 
 typedef u8 kprobe_opcode_t;
 #define BREAKPOINT_INSTRUCTION	0xcc
@@ -42,6 +45,7 @@
 #define ARCH_SUPPORTS_KRETPROBES
 
 void kretprobe_trampoline(void);
+extern void arch_remove_kprobe(struct kprobe *p);
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
diff --git a/include/asm-xtensa/ioctl.h b/include/asm-xtensa/ioctl.h
index 856c605..b279fe0 100644
--- a/include/asm-xtensa/ioctl.h
+++ b/include/asm-xtensa/ioctl.h
@@ -1,83 +1 @@
-/*
- * include/asm-xtensa/ioctl.h
- *
- * 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) 2003 - 2005 Tensilica Inc.
- *
- * Derived from "include/asm-i386/ioctl.h"
- */
-
-#ifndef _XTENSA_IOCTL_H
-#define _XTENSA_IOCTL_H
-
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms.  The i386 ioctl numbering scheme doesn't really enforce
- * a type field.  De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here.  Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
-#define _IOC_SIZEBITS	14
-#define _IOC_DIRBITS	2
-
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE	0U
-#define _IOC_WRITE	1U
-#define _IOC_READ	2U
-
-#define _IOC(dir,type,nr,size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
-
-#endif
+#include <asm-generic/ioctl.h>
diff --git a/include/linux/calc64.h b/include/linux/calc64.h
new file mode 100644
index 0000000..ebf4b8f
--- /dev/null
+++ b/include/linux/calc64.h
@@ -0,0 +1,49 @@
+#ifndef _LINUX_CALC64_H
+#define _LINUX_CALC64_H
+
+#include <linux/types.h>
+#include <asm/div64.h>
+
+/*
+ * This is a generic macro which is used when the architecture
+ * specific div64.h does not provide a optimized one.
+ *
+ * The 64bit dividend is divided by the divisor (data type long), the
+ * result is returned and the remainder stored in the variable
+ * referenced by remainder (data type long *). In contrast to the
+ * do_div macro the dividend is kept intact.
+ */
+#ifndef div_long_long_rem
+#define div_long_long_rem(dividend, divisor, remainder)	\
+	do_div_llr((dividend), divisor, remainder)
+
+static inline unsigned long do_div_llr(const long long dividend,
+				       const long divisor, long *remainder)
+{
+	u64 result = dividend;
+
+	*(remainder) = do_div(result, divisor);
+	return (unsigned long) result;
+}
+#endif
+
+/*
+ * Sign aware variation of the above. On some architectures a
+ * negative dividend leads to an divide overflow exception, which
+ * is avoided by the sign check.
+ */
+static inline long div_long_long_rem_signed(const long long dividend,
+					    const long divisor, long *remainder)
+{
+	long res;
+
+	if (unlikely(dividend < 0)) {
+		res = -div_long_long_rem(-dividend, divisor, remainder);
+		*remainder = -(*remainder);
+	} else
+		res = div_long_long_rem(dividend, divisor, remainder);
+
+	return res;
+}
+
+#endif
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 3398789..8fad50f 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -2,14 +2,6 @@
  * compatible types passed or none at all... Please include
  * only stuff that is compatible on *all architectures*.
  */
-#ifndef COMPATIBLE_IOCTL /* pointer to compatible structure or no argument */
-#define COMPATIBLE_IOCTL(cmd)  HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl)
-#endif
-
-#ifndef ULONG_IOCTL /* argument is an unsigned long integer, not a pointer */
-#define ULONG_IOCTL(cmd)  HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl)
-#endif
-
 
 COMPATIBLE_IOCTL(0x4B50)   /* KDGHWCLK - not in the kernel, but don't complain */
 COMPATIBLE_IOCTL(0x4B51)   /* KDSHWCLK - not in the kernel, but don't complain */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 92ae3e2..d1e370d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -114,8 +114,7 @@
 /*
  * Superblock flags that can be altered by MS_REMOUNT
  */
-#define MS_RMT_MASK	(MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|\
-			 MS_NODIRATIME)
+#define MS_RMT_MASK	(MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK)
 
 /*
  * Old magic mount flag and mask
@@ -161,8 +160,6 @@
 #define IS_NOQUOTA(inode)	((inode)->i_flags & S_NOQUOTA)
 #define IS_APPEND(inode)	((inode)->i_flags & S_APPEND)
 #define IS_IMMUTABLE(inode)	((inode)->i_flags & S_IMMUTABLE)
-#define IS_NOATIME(inode)	(__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
-#define IS_NODIRATIME(inode)	__IS_FLG(inode, MS_NODIRATIME)
 #define IS_POSIXACL(inode)	__IS_FLG(inode, MS_POSIXACL)
 
 #define IS_DEADDIR(inode)	((inode)->i_flags & S_DEAD)
@@ -235,9 +232,6 @@
 struct vm_area_struct;
 struct vfsmount;
 
-/* Used to be a macro which just called the function, now just a function */
-extern void update_atime (struct inode *);
-
 extern void __init inode_init(unsigned long);
 extern void __init inode_init_early(void);
 extern void __init mnt_init(unsigned long);
@@ -1118,12 +1112,7 @@
 	__mark_inode_dirty(inode, I_DIRTY_SYNC);
 }
 
-static inline void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
-{
-	/* per-mountpoint checks will go here */
-	update_atime(dentry->d_inode);
-}
-
+extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
 static inline void file_accessed(struct file *file)
 {
 	if (!(file->f_flags & O_NOATIME))
@@ -1716,7 +1705,7 @@
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern int __must_check inode_setattr(struct inode *, struct iattr *);
 
-extern void inode_update_time(struct inode *inode, int ctime_too);
+extern void file_update_time(struct file *file);
 
 static inline ino_t parent_ino(struct dentry *dentry)
 {
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
new file mode 100644
index 0000000..cf5cfdf
--- /dev/null
+++ b/include/linux/hrtimer.h
@@ -0,0 +1,143 @@
+/*
+ *  include/linux/hrtimer.h
+ *
+ *  hrtimers - High-resolution kernel timers
+ *
+ *   Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ *   Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ *  data type definitions, declarations, prototypes
+ *
+ *  Started by: Thomas Gleixner and Ingo Molnar
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+#ifndef _LINUX_HRTIMER_H
+#define _LINUX_HRTIMER_H
+
+#include <linux/rbtree.h>
+#include <linux/ktime.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+
+/*
+ * Mode arguments of xxx_hrtimer functions:
+ */
+enum hrtimer_mode {
+	HRTIMER_ABS,	/* Time value is absolute */
+	HRTIMER_REL,	/* Time value is relative to now */
+};
+
+enum hrtimer_restart {
+	HRTIMER_NORESTART,
+	HRTIMER_RESTART,
+};
+
+/*
+ * Timer states:
+ */
+enum hrtimer_state {
+	HRTIMER_INACTIVE,	/* Timer is inactive */
+	HRTIMER_EXPIRED,		/* Timer is expired */
+	HRTIMER_PENDING,		/* Timer is pending */
+};
+
+struct hrtimer_base;
+
+/**
+ * struct hrtimer - the basic hrtimer structure
+ *
+ * @node:	red black tree node for time ordered insertion
+ * @list:	list head for easier access to the time ordered list,
+ *		without walking the red black tree.
+ * @expires:	the absolute expiry time in the hrtimers internal
+ *		representation. The time is related to the clock on
+ *		which the timer is based.
+ * @state:	state of the timer
+ * @function:	timer expiry callback function
+ * @data:	argument for the callback function
+ * @base:	pointer to the timer base (per cpu and per clock)
+ *
+ * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
+ */
+struct hrtimer {
+	struct rb_node		node;
+	struct list_head	list;
+	ktime_t			expires;
+	enum hrtimer_state	state;
+	int			(*function)(void *);
+	void			*data;
+	struct hrtimer_base	*base;
+};
+
+/**
+ * struct hrtimer_base - the timer base for a specific clock
+ *
+ * @index:	clock type index for per_cpu support when moving a timer
+ *		to a base on another cpu.
+ * @lock:	lock protecting the base and associated timers
+ * @active:	red black tree root node for the active timers
+ * @pending:	list of pending timers for simple time ordered access
+ * @resolution:	the resolution of the clock, in nanoseconds
+ * @get_time:	function to retrieve the current time of the clock
+ * @curr_timer:	the timer which is executing a callback right now
+ */
+struct hrtimer_base {
+	clockid_t		index;
+	spinlock_t		lock;
+	struct rb_root		active;
+	struct list_head	pending;
+	unsigned long		resolution;
+	ktime_t			(*get_time)(void);
+	struct hrtimer		*curr_timer;
+};
+
+/*
+ * clock_was_set() is a NOP for non- high-resolution systems. The
+ * time-sorted order guarantees that a timer does not expire early and
+ * is expired in the next softirq when the clock was advanced.
+ */
+#define clock_was_set()		do { } while (0)
+
+/* Exported timer functions: */
+
+/* Initialize timers: */
+extern void hrtimer_init(struct hrtimer *timer, const clockid_t which_clock);
+extern void hrtimer_rebase(struct hrtimer *timer, const clockid_t which_clock);
+
+
+/* Basic timer operations: */
+extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
+			 const enum hrtimer_mode mode);
+extern int hrtimer_cancel(struct hrtimer *timer);
+extern int hrtimer_try_to_cancel(struct hrtimer *timer);
+
+#define hrtimer_restart(timer) hrtimer_start((timer), (timer)->expires, HRTIMER_ABS)
+
+/* Query timers: */
+extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
+extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
+
+static inline int hrtimer_active(const struct hrtimer *timer)
+{
+	return timer->state == HRTIMER_PENDING;
+}
+
+/* Forward a hrtimer so it expires after now: */
+extern unsigned long hrtimer_forward(struct hrtimer *timer,
+				     const ktime_t interval);
+
+/* Precise sleep: */
+extern long hrtimer_nanosleep(struct timespec *rqtp,
+			      struct timespec __user *rmtp,
+			      const enum hrtimer_mode mode,
+			      const clockid_t clockid);
+
+/* Soft interrupt function to run the hrtimer queues: */
+extern void hrtimer_run_queues(void);
+
+/* Bootup initialization: */
+extern void __init hrtimers_init(void);
+
+#endif
diff --git a/include/linux/isicom.h b/include/linux/isicom.h
index 7c6eae7..45b3d48 100644
--- a/include/linux/isicom.h
+++ b/include/linux/isicom.h
@@ -4,47 +4,12 @@
 /*#define		ISICOM_DEBUG*/
 /*#define		ISICOM_DEBUG_DTR_RTS*/
 
-
-/*
- *	Firmware Loader definitions ...
- */
- 
-#define		__MultiTech		('M'<<8)
-#define		MIOCTL_LOAD_FIRMWARE	(__MultiTech | 0x01)
-#define         MIOCTL_READ_FIRMWARE    (__MultiTech | 0x02)
-#define         MIOCTL_XFER_CTRL	(__MultiTech | 0x03)
-#define         MIOCTL_RESET_CARD	(__MultiTech | 0x04)
-
-#define		DATA_SIZE	16
-
-typedef	struct	{
-		unsigned short	exec_segment;
-		unsigned short	exec_addr;
-}	exec_record;
-
-typedef	struct	{
-		int		board;		/* Board to load */
-		unsigned short	addr;
-		unsigned short	count;
-}	bin_header;
-
-typedef	struct	{
-		int		board;		/* Board to load */
-		unsigned short	addr;
-		unsigned short	count;
-		unsigned short	segment;
-		unsigned char	bin_data[DATA_SIZE];
-}	bin_frame;
-
 #ifdef __KERNEL__
 
 #define		YES	1
 #define		NO	0
 
-#define		ISILOAD_MISC_MINOR	155	/* /dev/isctl */
-#define		ISILOAD_NAME		"ISILoad"
-
-/*	
+/*
  *  ISICOM Driver definitions ...
  *
  */
@@ -55,8 +20,8 @@
  *      PCI definitions
  */
 
- #define        DEVID_COUNT     9
- #define        VENDOR_ID       0x10b5
+#define		DEVID_COUNT	9
+#define		VENDOR_ID	0x10b5
 
 /*
  *	These are now officially allocated numbers
@@ -66,9 +31,9 @@
 #define		ISICOM_CMAJOR	113	/* callout */
 #define		ISICOM_MAGIC	(('M' << 8) | 'T')
 
-#define		WAKEUP_CHARS	256	/* hard coded for now	*/ 
-#define		TX_SIZE		254 
- 
+#define		WAKEUP_CHARS	256	/* hard coded for now	*/
+#define		TX_SIZE		254
+
 #define		BOARD_COUNT	4
 #define		PORT_COUNT	(BOARD_COUNT*16)
 
@@ -98,18 +63,15 @@
 #define		ISICOM_INITIATE_XONXOFF	0x04
 #define		ISICOM_RESPOND_XONXOFF	0x08
 
-#define InterruptTheCard(base) (outw(0,(base)+0xc)) 
-#define ClearInterrupt(base) (inw((base)+0x0a))	
-
 #define	BOARD(line)  (((line) >> 4) & 0x3)
 
 	/*	isi kill queue bitmap	*/
-	
+
 #define		ISICOM_KILLTX		0x01
 #define		ISICOM_KILLRX		0x02
 
 	/* isi_board status bitmap */
-	
+
 #define		FIRMWARE_LOADED		0x0001
 #define		BOARD_ACTIVE		0x0002
 
@@ -123,9 +85,8 @@
 #define		ISI_RTS			0x0200
 
 
-#define		ISI_TXOK		0x0001 
- 
+#define		ISI_TXOK		0x0001
+
 #endif	/*	__KERNEL__	*/
 
 #endif	/*	ISICOM_H	*/
-
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 6acfdbb..99905e1 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -1,21 +1,12 @@
 #ifndef _LINUX_JIFFIES_H
 #define _LINUX_JIFFIES_H
 
+#include <linux/calc64.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <asm/param.h>			/* for HZ */
-#include <asm/div64.h>
-
-#ifndef div_long_long_rem
-#define div_long_long_rem(dividend,divisor,remainder) \
-({							\
-	u64 result = dividend;				\
-	*remainder = do_div(result,divisor);		\
-	result;						\
-})
-#endif
 
 /*
  * The following defines establish the engineering parameters of the PLL
@@ -373,8 +364,11 @@
 	 * one divide.
 	 */
 	u64 nsec = (u64)jiffies * TICK_NSEC;
-	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
-	value->tv_usec /= NSEC_PER_USEC;
+	long tv_usec;
+
+	value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
+	tv_usec /= NSEC_PER_USEC;
+	value->tv_usec = tv_usec;
 }
 
 /*
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 7428198..45f625d 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -151,7 +151,7 @@
 
 static inline void con_schedule_flip(struct tty_struct *t)
 {
-	schedule_work(&t->flip.work);
+	schedule_work(&t->buf.work);
 }
 
 #endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index d0e6ca3..e6ee2d9 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -47,6 +47,8 @@
 #define default_console_loglevel (console_printk[3])
 
 struct completion;
+struct pt_regs;
+struct user;
 
 /**
  * might_sleep - annotation for functions that can sleep
@@ -123,6 +125,8 @@
 extern int kernel_text_address(unsigned long addr);
 extern int session_of_pgrp(int pgrp);
 
+extern void dump_thread(struct pt_regs *regs, struct user *dump);
+
 #ifdef CONFIG_PRINTK
 asmlinkage int vprintk(const char *fmt, va_list args)
 	__attribute__ ((format (printf, 1, 0)));
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index c846847..94abc07 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -41,7 +41,7 @@
 #define IND_DONE         0x4
 #define IND_SOURCE       0x8
 
-#define KEXEC_SEGMENT_MAX 8
+#define KEXEC_SEGMENT_MAX 16
 struct kexec_segment {
 	void __user *buf;
 	size_t bufsz;
@@ -125,6 +125,8 @@
 /* Location of a reserved region to hold the crash kernel.
  */
 extern struct resource crashk_res;
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+extern note_buf_t *crash_notes;
 
 #else /* !CONFIG_KEXEC */
 struct pt_regs;
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index c03f2dc..10005bc 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -149,11 +149,10 @@
 };
 
 extern spinlock_t kretprobe_lock;
+extern struct semaphore kprobe_mutex;
 extern int arch_prepare_kprobe(struct kprobe *p);
-extern void arch_copy_kprobe(struct kprobe *p);
 extern void arch_arm_kprobe(struct kprobe *p);
 extern void arch_disarm_kprobe(struct kprobe *p);
-extern void arch_remove_kprobe(struct kprobe *p);
 extern int arch_init_kprobes(void);
 extern void show_registers(struct pt_regs *regs);
 extern kprobe_opcode_t *get_insn_slot(void);
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
new file mode 100644
index 0000000..222a047
--- /dev/null
+++ b/include/linux/ktime.h
@@ -0,0 +1,284 @@
+/*
+ *  include/linux/ktime.h
+ *
+ *  ktime_t - nanosecond-resolution time format.
+ *
+ *   Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ *   Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ *  data type definitions, declarations, prototypes and macros.
+ *
+ *  Started by: Thomas Gleixner and Ingo Molnar
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+#ifndef _LINUX_KTIME_H
+#define _LINUX_KTIME_H
+
+#include <linux/time.h>
+#include <linux/jiffies.h>
+
+/*
+ * ktime_t:
+ *
+ * On 64-bit CPUs a single 64-bit variable is used to store the hrtimers
+ * internal representation of time values in scalar nanoseconds. The
+ * design plays out best on 64-bit CPUs, where most conversions are
+ * NOPs and most arithmetic ktime_t operations are plain arithmetic
+ * operations.
+ *
+ * On 32-bit CPUs an optimized representation of the timespec structure
+ * is used to avoid expensive conversions from and to timespecs. The
+ * endian-aware order of the tv struct members is choosen to allow
+ * mathematical operations on the tv64 member of the union too, which
+ * for certain operations produces better code.
+ *
+ * For architectures with efficient support for 64/32-bit conversions the
+ * plain scalar nanosecond based representation can be selected by the
+ * config switch CONFIG_KTIME_SCALAR.
+ */
+typedef union {
+	s64	tv64;
+#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
+	struct {
+# ifdef __BIG_ENDIAN
+	s32	sec, nsec;
+# else
+	s32	nsec, sec;
+# endif
+	} tv;
+#endif
+} ktime_t;
+
+#define KTIME_MAX			(~((u64)1 << 63))
+
+/*
+ * ktime_t definitions when using the 64-bit scalar representation:
+ */
+
+#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
+
+/* Define a ktime_t variable and initialize it to zero: */
+#define DEFINE_KTIME(kt)		ktime_t kt = { .tv64 = 0 }
+
+/**
+ * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
+ *
+ * @secs:	seconds to set
+ * @nsecs:	nanoseconds to set
+ *
+ * Return the ktime_t representation of the value
+ */
+static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
+{
+	return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
+}
+
+/* Subtract two ktime_t variables. rem = lhs -rhs: */
+#define ktime_sub(lhs, rhs) \
+		({ (ktime_t){ .tv64 = (lhs).tv64 - (rhs).tv64 }; })
+
+/* Add two ktime_t variables. res = lhs + rhs: */
+#define ktime_add(lhs, rhs) \
+		({ (ktime_t){ .tv64 = (lhs).tv64 + (rhs).tv64 }; })
+
+/*
+ * Add a ktime_t variable and a scalar nanosecond value.
+ * res = kt + nsval:
+ */
+#define ktime_add_ns(kt, nsval) \
+		({ (ktime_t){ .tv64 = (kt).tv64 + (nsval) }; })
+
+/* convert a timespec to ktime_t format: */
+#define timespec_to_ktime(ts)		ktime_set((ts).tv_sec, (ts).tv_nsec)
+
+/* convert a timeval to ktime_t format: */
+#define timeval_to_ktime(tv)		ktime_set((tv).tv_sec, (tv).tv_usec * 1000)
+
+/* Map the ktime_t to timespec conversion to ns_to_timespec function */
+#define ktime_to_timespec(kt)		ns_to_timespec((kt).tv64)
+
+/* Map the ktime_t to timeval conversion to ns_to_timeval function */
+#define ktime_to_timeval(kt)		ns_to_timeval((kt).tv64)
+
+/* Map the ktime_t to clock_t conversion to the inline in jiffies.h: */
+#define ktime_to_clock_t(kt)		nsec_to_clock_t((kt).tv64)
+
+/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */
+#define ktime_to_ns(kt)			((kt).tv64)
+
+#else
+
+/*
+ * Helper macros/inlines to get the ktime_t math right in the timespec
+ * representation. The macros are sometimes ugly - their actual use is
+ * pretty okay-ish, given the circumstances. We do all this for
+ * performance reasons. The pure scalar nsec_t based code was nice and
+ * simple, but created too many 64-bit / 32-bit conversions and divisions.
+ *
+ * Be especially aware that negative values are represented in a way
+ * that the tv.sec field is negative and the tv.nsec field is greater
+ * or equal to zero but less than nanoseconds per second. This is the
+ * same representation which is used by timespecs.
+ *
+ *   tv.sec < 0 and 0 >= tv.nsec < NSEC_PER_SEC
+ */
+
+/* Define a ktime_t variable and initialize it to zero: */
+#define DEFINE_KTIME(kt)		ktime_t kt = { .tv64 = 0 }
+
+/* Set a ktime_t variable to a value in sec/nsec representation: */
+static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
+{
+	return (ktime_t) { .tv = { .sec = secs, .nsec = nsecs } };
+}
+
+/**
+ * ktime_sub - subtract two ktime_t variables
+ *
+ * @lhs:	minuend
+ * @rhs:	subtrahend
+ *
+ * Returns the remainder of the substraction
+ */
+static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs)
+{
+	ktime_t res;
+
+	res.tv64 = lhs.tv64 - rhs.tv64;
+	if (res.tv.nsec < 0)
+		res.tv.nsec += NSEC_PER_SEC;
+
+	return res;
+}
+
+/**
+ * ktime_add - add two ktime_t variables
+ *
+ * @add1:	addend1
+ * @add2:	addend2
+ *
+ * Returns the sum of addend1 and addend2
+ */
+static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
+{
+	ktime_t res;
+
+	res.tv64 = add1.tv64 + add2.tv64;
+	/*
+	 * performance trick: the (u32) -NSEC gives 0x00000000Fxxxxxxx
+	 * so we subtract NSEC_PER_SEC and add 1 to the upper 32 bit.
+	 *
+	 * it's equivalent to:
+	 *   tv.nsec -= NSEC_PER_SEC
+	 *   tv.sec ++;
+	 */
+	if (res.tv.nsec >= NSEC_PER_SEC)
+		res.tv64 += (u32)-NSEC_PER_SEC;
+
+	return res;
+}
+
+/**
+ * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
+ *
+ * @kt:		addend
+ * @nsec:	the scalar nsec value to add
+ *
+ * Returns the sum of kt and nsec in ktime_t format
+ */
+extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
+
+/**
+ * timespec_to_ktime - convert a timespec to ktime_t format
+ *
+ * @ts:		the timespec variable to convert
+ *
+ * Returns a ktime_t variable with the converted timespec value
+ */
+static inline ktime_t timespec_to_ktime(const struct timespec ts)
+{
+	return (ktime_t) { .tv = { .sec = (s32)ts.tv_sec,
+			   	   .nsec = (s32)ts.tv_nsec } };
+}
+
+/**
+ * timeval_to_ktime - convert a timeval to ktime_t format
+ *
+ * @tv:		the timeval variable to convert
+ *
+ * Returns a ktime_t variable with the converted timeval value
+ */
+static inline ktime_t timeval_to_ktime(const struct timeval tv)
+{
+	return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec,
+				   .nsec = (s32)tv.tv_usec * 1000 } };
+}
+
+/**
+ * ktime_to_timespec - convert a ktime_t variable to timespec format
+ *
+ * @kt:		the ktime_t variable to convert
+ *
+ * Returns the timespec representation of the ktime value
+ */
+static inline struct timespec ktime_to_timespec(const ktime_t kt)
+{
+	return (struct timespec) { .tv_sec = (time_t) kt.tv.sec,
+				   .tv_nsec = (long) kt.tv.nsec };
+}
+
+/**
+ * ktime_to_timeval - convert a ktime_t variable to timeval format
+ *
+ * @kt:		the ktime_t variable to convert
+ *
+ * Returns the timeval representation of the ktime value
+ */
+static inline struct timeval ktime_to_timeval(const ktime_t kt)
+{
+	return (struct timeval) {
+		.tv_sec = (time_t) kt.tv.sec,
+		.tv_usec = (suseconds_t) (kt.tv.nsec / NSEC_PER_USEC) };
+}
+
+/**
+ * ktime_to_clock_t - convert a ktime_t variable to clock_t format
+ * @kt:		the ktime_t variable to convert
+ *
+ * Returns a clock_t variable with the converted value
+ */
+static inline clock_t ktime_to_clock_t(const ktime_t kt)
+{
+	return nsec_to_clock_t( (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec);
+}
+
+/**
+ * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
+ * @kt:		the ktime_t variable to convert
+ *
+ * Returns the scalar nanoseconds representation of kt
+ */
+static inline u64 ktime_to_ns(const ktime_t kt)
+{
+	return (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
+}
+
+#endif
+
+/*
+ * The resolution of the clocks. The resolution value is returned in
+ * the clock_getres() system call to give application programmers an
+ * idea of the (in)accuracy of timers. Timer values are rounded up to
+ * this resolution values.
+ */
+#define KTIME_REALTIME_RES	(NSEC_PER_SEC/HZ)
+#define KTIME_MONOTONIC_RES	(NSEC_PER_SEC/HZ)
+
+/* Get the monotonic time in timespec format: */
+extern void ktime_get_ts(struct timespec *ts);
+
+/* Get the real (wall-) time in timespec format: */
+#define ktime_get_real_ts(ts)	getnstimeofday(ts)
+
+#endif
diff --git a/include/linux/list.h b/include/linux/list.h
index 8e33882..945daa1 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -436,6 +436,20 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
+ * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
+ *				      removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
+	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
+		n = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/**
  * list_for_each_rcu	-	iterate over an rcu-protected list
  * @pos:	the &struct list_head to use as a loop counter.
  * @head:	the head for your list.
diff --git a/include/linux/mount.h b/include/linux/mount.h
index b98a709..b7472ae 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -20,10 +20,12 @@
 #define MNT_NOSUID	0x01
 #define MNT_NODEV	0x02
 #define MNT_NOEXEC	0x04
-#define MNT_SHARED	0x10	/* if the vfsmount is a shared mount */
-#define MNT_UNBINDABLE	0x20	/* if the vfsmount is a unbindable mount */
+#define MNT_NOATIME	0x08
+#define MNT_NODIRATIME	0x10
 
-#define MNT_PNODE_MASK	(MNT_SHARED | MNT_UNBINDABLE)
+#define MNT_SHARED	0x1000	/* if the vfsmount is a shared mount */
+#define MNT_UNBINDABLE	0x2000	/* if the vfsmount is a unbindable mount */
+#define MNT_PNODE_MASK	0x3000	/* propogation flag mask */
 
 struct vfsmount {
 	struct list_head mnt_hash;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 455660e..b699e42 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -74,7 +74,7 @@
 extern void release_open_intent(struct nameidata *);
 
 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-extern struct dentry * lookup_hash(struct nameidata *);
+extern __deprecated_for_modules struct dentry * lookup_hash(struct nameidata *);
 
 extern int follow_down(struct vfsmount **, struct dentry **);
 extern int follow_up(struct vfsmount **, struct dentry **);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index c3caa93..f55c98a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -377,6 +377,7 @@
 #define PCI_DEVICE_ID_NS_87560_USB	0x0012
 #define PCI_DEVICE_ID_NS_83815		0x0020
 #define PCI_DEVICE_ID_NS_83820		0x0022
+#define PCI_DEVICE_ID_NS_CS5535_ISA	0x002b
 #define PCI_DEVICE_ID_NS_CS5535_IDE	0x002d
 #define PCI_DEVICE_ID_NS_CS5535_AUDIO	0x002e
 #define PCI_DEVICE_ID_NS_CS5535_USB	0x002f
@@ -500,6 +501,14 @@
 #define PCI_DEVICE_ID_AMD_8111_AUDIO	0x746d
 #define PCI_DEVICE_ID_AMD_8151_0	0x7454
 #define PCI_DEVICE_ID_AMD_8131_APIC     0x7450
+#define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
+#define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
+#define PCI_DEVICE_ID_AMD_CS5536_AUDIO  0x2093
+#define PCI_DEVICE_ID_AMD_CS5536_OHC    0x2094
+#define PCI_DEVICE_ID_AMD_CS5536_EHC    0x2095
+#define PCI_DEVICE_ID_AMD_CS5536_UDC    0x2096
+#define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
+#define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
 
 #define PCI_DEVICE_ID_AMD_CS5536_IDE	0x209A
 
@@ -1041,6 +1050,11 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_6		0x00e6
 #define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO		0x00ea
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2	0x00ee
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT   0x00f9
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
 #define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index f942e2b..54faf52 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -42,7 +42,7 @@
 	timer_t it_id;			/* timer id */
 	int it_overrun;			/* overrun on pending signal  */
 	int it_overrun_last;		/* overrun on last delivered signal */
-	int it_requeue_pending;         /* waiting to requeue this timer */
+	int it_requeue_pending;		/* waiting to requeue this timer */
 #define REQUEUE_PENDING 1
 	int it_sigev_notify;		/* notify word of sigevent struct */
 	int it_sigev_signo;		/* signo word of sigevent struct */
@@ -51,10 +51,8 @@
 	struct sigqueue *sigq;		/* signal queue entry. */
 	union {
 		struct {
-			struct timer_list timer;
-			struct list_head abs_timer_entry; /* clock abs_timer_list */
-			struct timespec wall_to_prev;   /* wall_to_monotonic used when set */
-			unsigned long incr; /* interval in jiffies */
+			struct hrtimer timer;
+			ktime_t interval;
 		} real;
 		struct cpu_timer_list cpu;
 		struct {
@@ -66,18 +64,14 @@
 	} it;
 };
 
-struct k_clock_abs {
-	struct list_head list;
-	spinlock_t lock;
-};
 struct k_clock {
-	int res;		/* in nano seconds */
-	int (*clock_getres) (clockid_t which_clock, struct timespec *tp);
-	struct k_clock_abs *abs_struct;
-	int (*clock_set) (clockid_t which_clock, struct timespec * tp);
-	int (*clock_get) (clockid_t which_clock, struct timespec * tp);
+	int res;		/* in nanoseconds */
+	int (*clock_getres) (const clockid_t which_clock, struct timespec *tp);
+	int (*clock_set) (const clockid_t which_clock, struct timespec * tp);
+	int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
 	int (*timer_create) (struct k_itimer *timer);
-	int (*nsleep) (clockid_t which_clock, int flags, struct timespec *);
+	int (*nsleep) (const clockid_t which_clock, int flags,
+		       struct timespec *, struct timespec __user *);
 	int (*timer_set) (struct k_itimer * timr, int flags,
 			  struct itimerspec * new_setting,
 			  struct itimerspec * old_setting);
@@ -87,53 +81,35 @@
 			   struct itimerspec * cur_setting);
 };
 
-void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock);
+void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
 
-/* Error handlers for timer_create, nanosleep and settime */
+/* error handlers for timer_create, nanosleep and settime */
 int do_posix_clock_notimer_create(struct k_itimer *timer);
-int do_posix_clock_nonanosleep(clockid_t, int flags, struct timespec *);
-int do_posix_clock_nosettime(clockid_t, struct timespec *tp);
+int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
+			       struct timespec __user *);
+int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
 
 /* function to call to trigger timer event */
 int posix_timer_event(struct k_itimer *timr, int si_private);
 
-struct now_struct {
-	unsigned long jiffies;
-};
+int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *ts);
+int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *ts);
+int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
+int posix_cpu_timer_create(struct k_itimer *timer);
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+		     struct timespec *rqtp, struct timespec __user *rmtp);
+int posix_cpu_timer_set(struct k_itimer *timer, int flags,
+			struct itimerspec *new, struct itimerspec *old);
+int posix_cpu_timer_del(struct k_itimer *timer);
+void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp);
 
-#define posix_get_now(now) (now)->jiffies = jiffies;
-#define posix_time_before(timer, now) \
-                      time_before((timer)->expires, (now)->jiffies)
+void posix_cpu_timer_schedule(struct k_itimer *timer);
 
-#define posix_bump_timer(timr, now)					\
-         do {								\
-              long delta, orun;						\
-	      delta = now.jiffies - (timr)->it.real.timer.expires;	\
-              if (delta >= 0) {						\
-	           orun = 1 + (delta / (timr)->it.real.incr);		\
-	          (timr)->it.real.timer.expires +=			\
-			 orun * (timr)->it.real.incr;			\
-                  (timr)->it_overrun += orun;				\
-              }								\
-            }while (0)
+void run_posix_cpu_timers(struct task_struct *task);
+void posix_cpu_timers_exit(struct task_struct *task);
+void posix_cpu_timers_exit_group(struct task_struct *task);
 
-int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *);
-int posix_cpu_clock_get(clockid_t which_clock, struct timespec *);
-int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp);
-int posix_cpu_timer_create(struct k_itimer *);
-int posix_cpu_nsleep(clockid_t, int, struct timespec *);
-int posix_cpu_timer_set(struct k_itimer *, int,
-			struct itimerspec *, struct itimerspec *);
-int posix_cpu_timer_del(struct k_itimer *);
-void posix_cpu_timer_get(struct k_itimer *, struct itimerspec *);
-
-void posix_cpu_timer_schedule(struct k_itimer *);
-
-void run_posix_cpu_timers(struct task_struct *);
-void posix_cpu_timers_exit(struct task_struct *);
-void posix_cpu_timers_exit_group(struct task_struct *);
-
-void set_process_cpu_timer(struct task_struct *, unsigned int,
-			   cputime_t *, cputime_t *);
+void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
+			   cputime_t *newval, cputime_t *oldval);
 
 #endif
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
index 157d7e3..f54772d 100644
--- a/include/linux/rio_drv.h
+++ b/include/linux/rio_drv.h
@@ -337,8 +337,8 @@
 
 /**
  * RIO_DEVICE - macro used to describe a specific RIO device
- * @vid: the 16 bit RIO vendor ID
- * @did: the 16 bit RIO device ID
+ * @dev: the 16 bit RIO device ID
+ * @ven: the 16 bit RIO vendor ID
  *
  * This macro is used to create a struct rio_device_id that matches a
  * specific device.  The assembly vendor and assembly device fields
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 85b53f8..c4ee35d 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -105,6 +105,7 @@
 #include <linux/param.h>
 #include <linux/resource.h>
 #include <linux/timer.h>
+#include <linux/hrtimer.h>
 
 #include <asm/processor.h>
 
@@ -398,8 +399,8 @@
 	struct list_head posix_timers;
 
 	/* ITIMER_REAL timer for the process */
-	struct timer_list real_timer;
-	unsigned long it_real_value, it_real_incr;
+	struct hrtimer real_timer;
+	ktime_t it_real_incr;
 
 	/* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
 	cputime_t it_prof_expires, it_virt_expires;
@@ -1389,12 +1390,8 @@
 extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
 extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
 
-#ifdef CONFIG_MAGIC_SYSRQ
-
 extern void normalize_rt_tasks(void);
 
-#endif
-
 #ifdef CONFIG_PM
 /*
  * Check if a process has been frozen
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 76850b7..6336987 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -41,8 +41,7 @@
 	u16 vesapm_off;		/* 0x30 */
 	u16 pages;		/* 0x32 */
 	u16 vesa_attributes;	/* 0x34 */
-	u32  capabilities;      /* 0x36 */
-				/* 0x3a -- 0x3f reserved for future expansion */
+				/* 0x36 -- 0x3f reserved for future expansion */
 };
 
 extern struct screen_info screen_info;
diff --git a/include/linux/time.h b/include/linux/time.h
index 797ccd8..f2aca7e 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -4,7 +4,7 @@
 #include <linux/types.h>
 
 #ifdef __KERNEL__
-#include <linux/seqlock.h>
+# include <linux/seqlock.h>
 #endif
 
 #ifndef _STRUCT_TIMESPEC
@@ -13,7 +13,7 @@
 	time_t	tv_sec;		/* seconds */
 	long	tv_nsec;	/* nanoseconds */
 };
-#endif /* _STRUCT_TIMESPEC */
+#endif
 
 struct timeval {
 	time_t		tv_sec;		/* seconds */
@@ -27,93 +27,103 @@
 
 #ifdef __KERNEL__
 
-/* Parameters used to convert the timespec values */
-#define MSEC_PER_SEC (1000L)
-#define USEC_PER_SEC (1000000L)
-#define NSEC_PER_SEC (1000000000L)
-#define NSEC_PER_USEC (1000L)
+/* Parameters used to convert the timespec values: */
+#define MSEC_PER_SEC		1000L
+#define USEC_PER_SEC		1000000L
+#define NSEC_PER_SEC		1000000000L
+#define NSEC_PER_USEC		1000L
 
-static __inline__ int timespec_equal(struct timespec *a, struct timespec *b) 
-{ 
-	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
-} 
-
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static inline unsigned long
-mktime (unsigned int year, unsigned int mon,
-	unsigned int day, unsigned int hour,
-	unsigned int min, unsigned int sec)
+static __inline__ int timespec_equal(struct timespec *a, struct timespec *b)
 {
-	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
-		mon += 12;		/* Puts Feb last since it has leap day */
-		year -= 1;
-	}
-
-	return (((
-		(unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
-			year*365 - 719499
-	    )*24 + hour /* now have hours */
-	  )*60 + min /* now have minutes */
-	)*60 + sec; /* finally seconds */
+	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
 }
 
+extern unsigned long mktime(const unsigned int year, const unsigned int mon,
+			    const unsigned int day, const unsigned int hour,
+			    const unsigned int min, const unsigned int sec);
+
+extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec);
+
+/*
+ * Returns true if the timespec is norm, false if denorm:
+ */
+#define timespec_valid(ts) \
+	(((ts)->tv_sec >= 0) && (((unsigned) (ts)->tv_nsec) < NSEC_PER_SEC))
+
+/*
+ * 64-bit nanosec type. Large enough to span 292+ years in nanosecond
+ * resolution. Ought to be enough for a while.
+ */
+typedef s64 nsec_t;
+
 extern struct timespec xtime;
 extern struct timespec wall_to_monotonic;
 extern seqlock_t xtime_lock;
 
 static inline unsigned long get_seconds(void)
-{ 
+{
 	return xtime.tv_sec;
 }
 
 struct timespec current_kernel_time(void);
 
-#define CURRENT_TIME (current_kernel_time())
-#define CURRENT_TIME_SEC ((struct timespec) { xtime.tv_sec, 0 })
+#define CURRENT_TIME		(current_kernel_time())
+#define CURRENT_TIME_SEC	((struct timespec) { xtime.tv_sec, 0 })
 
 extern void do_gettimeofday(struct timeval *tv);
 extern int do_settimeofday(struct timespec *tv);
 extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
-extern void clock_was_set(void); // call when ever the clock is set
-extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
-extern long do_utimes(char __user * filename, struct timeval * times);
+#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
+extern long do_utimes(char __user *filename, struct timeval *times);
 struct itimerval;
-extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
+extern int do_setitimer(int which, struct itimerval *value,
+			struct itimerval *ovalue);
 extern int do_getitimer(int which, struct itimerval *value);
-extern void getnstimeofday (struct timespec *tv);
-extern void getnstimestamp(struct timespec *ts);
+extern void getnstimeofday(struct timespec *tv);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 
-static inline void
-set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
+/**
+ * timespec_to_ns - Convert timespec to nanoseconds
+ * @ts:		pointer to the timespec variable to be converted
+ *
+ * Returns the scalar nanosecond representation of the timespec
+ * parameter.
+ */
+static inline nsec_t timespec_to_ns(const struct timespec *ts)
 {
-	while (nsec >= NSEC_PER_SEC) {
-		nsec -= NSEC_PER_SEC;
-		++sec;
-	}
-	while (nsec < 0) {
-		nsec += NSEC_PER_SEC;
-		--sec;
-	}
-	ts->tv_sec = sec;
-	ts->tv_nsec = nsec;
+	return ((nsec_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
 }
 
+/**
+ * timeval_to_ns - Convert timeval to nanoseconds
+ * @ts:		pointer to the timeval variable to be converted
+ *
+ * Returns the scalar nanosecond representation of the timeval
+ * parameter.
+ */
+static inline nsec_t timeval_to_ns(const struct timeval *tv)
+{
+	return ((nsec_t) tv->tv_sec * NSEC_PER_SEC) +
+		tv->tv_usec * NSEC_PER_USEC;
+}
+
+/**
+ * ns_to_timespec - Convert nanoseconds to timespec
+ * @nsec:	the nanoseconds value to be converted
+ *
+ * Returns the timespec representation of the nsec parameter.
+ */
+extern struct timespec ns_to_timespec(const nsec_t nsec);
+
+/**
+ * ns_to_timeval - Convert nanoseconds to timeval
+ * @nsec:	the nanoseconds value to be converted
+ *
+ * Returns the timeval representation of the nsec parameter.
+ */
+extern struct timeval ns_to_timeval(const nsec_t nsec);
+
 #endif /* __KERNEL__ */
 
 #define NFDBITS			__NFDBITS
@@ -126,49 +136,41 @@
 
 /*
  * Names of the interval timers, and structure
- * defining a timer setting.
+ * defining a timer setting:
  */
-#define	ITIMER_REAL	0
-#define	ITIMER_VIRTUAL	1
-#define	ITIMER_PROF	2
+#define	ITIMER_REAL		0
+#define	ITIMER_VIRTUAL		1
+#define	ITIMER_PROF		2
 
-struct  itimerspec {
-        struct  timespec it_interval;    /* timer period */
-        struct  timespec it_value;       /* timer expiration */
+struct itimerspec {
+	struct timespec it_interval;	/* timer period */
+	struct timespec it_value;	/* timer expiration */
 };
 
-struct	itimerval {
-	struct	timeval it_interval;	/* timer interval */
-	struct	timeval it_value;	/* current value */
+struct itimerval {
+	struct timeval it_interval;	/* timer interval */
+	struct timeval it_value;	/* current value */
 };
 
+/*
+ * The IDs of the various system clocks (for POSIX.1b interval timers):
+ */
+#define CLOCK_REALTIME			0
+#define CLOCK_MONOTONIC			1
+#define CLOCK_PROCESS_CPUTIME_ID	2
+#define CLOCK_THREAD_CPUTIME_ID		3
 
 /*
- * The IDs of the various system clocks (for POSIX.1b interval timers).
+ * The IDs of various hardware clocks:
  */
-#define CLOCK_REALTIME		  0
-#define CLOCK_MONOTONIC	  1
-#define CLOCK_PROCESS_CPUTIME_ID 2
-#define CLOCK_THREAD_CPUTIME_ID	 3
-#define CLOCK_REALTIME_HR	 4
-#define CLOCK_MONOTONIC_HR	  5
+#define CLOCK_SGI_CYCLE			10
+#define MAX_CLOCKS			16
+#define CLOCKS_MASK			(CLOCK_REALTIME | CLOCK_MONOTONIC)
+#define CLOCKS_MONO			CLOCK_MONOTONIC
 
 /*
- * The IDs of various hardware clocks
+ * The various flags for setting POSIX.1b interval timers:
  */
-
-
-#define CLOCK_SGI_CYCLE 10
-#define MAX_CLOCKS 16
-#define CLOCKS_MASK  (CLOCK_REALTIME | CLOCK_MONOTONIC | \
-                     CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR)
-#define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR)
-
-/*
- * The various flags for setting POSIX.1b interval timers.
- */
-
-#define TIMER_ABSTIME 0x01
-
+#define TIMER_ABSTIME			0x01
 
 #endif
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 72f3a77..9b9877f 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -96,6 +96,6 @@
 
 extern void init_timers(void);
 extern void run_local_timers(void);
-extern void it_real_fn(unsigned long);
+extern int it_real_fn(void *);
 
 #endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 5744970..3787102 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -51,16 +51,22 @@
  */
 #define TTY_FLIPBUF_SIZE 512
 
-struct tty_flip_buffer {
+struct tty_buffer {
+	struct tty_buffer *next;
+	char *char_buf_ptr;
+	unsigned char *flag_buf_ptr;
+	int used;
+	int size;
+	/* Data points here */
+	unsigned long data[0];
+};
+
+struct tty_bufhead {
 	struct work_struct		work;
 	struct semaphore pty_sem;
-	char		*char_buf_ptr;
-	unsigned char	*flag_buf_ptr;
-	int		count;
-	int		buf_num;
-	unsigned char	char_buf[2*TTY_FLIPBUF_SIZE];
-	char		flag_buf[2*TTY_FLIPBUF_SIZE];
-	unsigned char	slop[4]; /* N.B. bug overwrites buffer by 1 */
+	struct tty_buffer *head;	/* Queue head */
+	struct tty_buffer *tail;	/* Active buffer */
+	struct tty_buffer *free;	/* Free queue head */
 };
 /*
  * The pty uses char_buf and flag_buf as a contiguous buffer
@@ -186,10 +192,11 @@
 	unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
 	unsigned char low_latency:1, warned:1;
 	unsigned char ctrl_status;
+	unsigned int receive_room;	/* Bytes free for queue */
 
 	struct tty_struct *link;
 	struct fasync_struct *fasync;
-	struct tty_flip_buffer flip;
+	struct tty_bufhead buf;
 	int max_flip_cnt;
 	int alt_speed;		/* For magic substitution of 38400 bps */
 	wait_queue_head_t write_wait;
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index abe9bfc..be1400e 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -1,25 +1,33 @@
 #ifndef _LINUX_TTY_FLIP_H
 #define _LINUX_TTY_FLIP_H
 
+extern int tty_buffer_request_room(struct tty_struct *tty, size_t size);
+extern int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size);
+extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size);
+extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
+extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
+
 #ifdef INCLUDE_INLINE_FUNCS
 #define _INLINE_ extern
 #else
 #define _INLINE_ static __inline__
 #endif
 
-_INLINE_ void tty_insert_flip_char(struct tty_struct *tty,
+_INLINE_ int tty_insert_flip_char(struct tty_struct *tty,
 				   unsigned char ch, char flag)
 {
-	if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = flag;
-		*tty->flip.char_buf_ptr++ = ch;
+	struct tty_buffer *tb = tty->buf.tail;
+	if (tb && tb->used < tb->size) {
+		tb->flag_buf_ptr[tb->used] = flag;
+		tb->char_buf_ptr[tb->used++] = ch;
+		return 1;
 	}
+	return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
 }
 
 _INLINE_ void tty_schedule_flip(struct tty_struct *tty)
 {
-	schedule_delayed_work(&tty->flip.work, 1);
+	schedule_delayed_work(&tty->buf.work, 1);
 }
 
 #undef _INLINE_
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 6066afd..83c6e6c 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -81,14 +81,6 @@
  * 	pointer of flag bytes which indicate whether a character was
  * 	received with a parity error, etc.
  * 
- * int	(*receive_room)(struct tty_struct *);
- *
- * 	This function is called by the low-level tty driver to
- * 	determine how many characters the line discpline can accept.
- * 	The low-level driver must not send more characters than was
- * 	indicated by receive_room, or the line discpline may drop
- * 	those characters.
- * 
  * void	(*write_wakeup)(struct tty_struct *);
  *
  * 	This function is called by the low-level tty driver to signal
@@ -136,7 +128,6 @@
 	 */
 	void	(*receive_buf)(struct tty_struct *, const unsigned char *cp,
 			       char *fp, int count);
-	int	(*receive_room)(struct tty_struct *);
 	void	(*write_wakeup)(struct tty_struct *);
 
 	struct  module *owner;
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 23f9c61..cda8a96 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -13,7 +13,22 @@
 #define XATTR_CREATE	0x1	/* set value, fail if attr already exists */
 #define XATTR_REPLACE	0x2	/* set value, fail if attr does not exist */
 
+/* Namespaces */
+#define XATTR_OS2_PREFIX "os2."
+#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
+
 #define XATTR_SECURITY_PREFIX	"security."
+#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
+
+#define XATTR_SYSTEM_PREFIX "system."
+#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
+
+#define XATTR_USER_PREFIX "user."
+#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
+
 
 struct xattr_handler {
 	char *prefix;
@@ -25,6 +40,10 @@
 		   size_t size, int flags);
 };
 
+ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
+int vfs_removexattr(struct dentry *, char *);
+
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
diff --git a/include/linux/zlib.h b/include/linux/zlib.h
index 74f7b78..4fa32f0 100644
--- a/include/linux/zlib.h
+++ b/include/linux/zlib.h
@@ -442,9 +442,11 @@
    not perform any compression: this will be done by deflate().
 */
                             
+#if 0
 extern int zlib_deflateSetDictionary (z_streamp strm,
 						     const Byte *dictionary,
 						     uInt  dictLength);
+#endif
 /*
      Initializes the compression dictionary from the given byte sequence
    without producing any compressed output. This function must be called
@@ -478,7 +480,10 @@
    perform any compression: this will be done by deflate().
 */
 
+#if 0
 extern int zlib_deflateCopy (z_streamp dest, z_streamp source);
+#endif
+
 /*
      Sets the destination stream as a complete copy of the source stream.
 
@@ -511,7 +516,9 @@
 	return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11;
 }
 
+#if 0
 extern int zlib_deflateParams (z_streamp strm, int level, int strategy);
+#endif
 /*
      Dynamically update the compression level and compression strategy.  The
    interpretation of level and strategy is as in deflateInit2.  This can be
@@ -571,7 +578,9 @@
    inflate().
 */
 
+#if 0
 extern int zlib_inflateSync (z_streamp strm);
+#endif
 /* 
     Skips invalid compressed data until a full flush point (see above the
   description of deflate with Z_FULL_FLUSH) can be found, or until all
@@ -636,7 +645,9 @@
 #endif
 
 extern const char  * zlib_zError           (int err);
+#if 0
 extern int           zlib_inflateSyncPoint (z_streamp z);
+#endif
 extern const uLong * zlib_get_crc_table    (void);
 
 #endif /* _ZLIB_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 90ac613..3093e3d 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -317,7 +317,7 @@
 #ifdef CONFIG_SND_VERBOSE_PRINTK
 /**
  * snd_printd - debug printk
- * @format: format string
+ * @fmt: format string
  *
  * Compiled only when Works like snd_printk() for debugging purpose.
  * Ignored when CONFIG_SND_DEBUG is not set.
@@ -331,7 +331,6 @@
 /**
  * snd_assert - run-time assertion macro
  * @expr: expression
- * @args...: the action
  *
  * This macro checks the expression in run-time and invokes the commands
  * given in the rest arguments if the assertion is failed.
diff --git a/include/video/kyro.h b/include/video/kyro.h
index 1bed37c..dba7de2 100644
--- a/include/video/kyro.h
+++ b/include/video/kyro.h
@@ -15,6 +15,7 @@
 struct kyrofb_info {
 	void __iomem *regbase;
 
+	u32 palette[16];
 	u32 HTot;	/* Hor Total Time    */
 	u32 HFP;	/* Hor Front Porch   */
 	u32 HST;	/* Hor Sync Time     */
diff --git a/include/video/neomagic.h b/include/video/neomagic.h
index bdaee70..1d69049 100644
--- a/include/video/neomagic.h
+++ b/include/video/neomagic.h
@@ -196,6 +196,7 @@
 	int internal_display;
 	int external_display;
 	int libretto;
+	u32 palette[16];
 };
 
 typedef struct {
diff --git a/include/video/newport.h b/include/video/newport.h
index 812dac5..1f5ebea 100644
--- a/include/video/newport.h
+++ b/include/video/newport.h
@@ -382,7 +382,8 @@
 #define VC2_IREG_CONTROL       0x10
 #define VC2_IREG_CONFIG        0x20
 
-extern __inline__ void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg,
+static inline void newport_vc2_set(struct newport_regs *regs,
+				   unsigned char vc2ireg,
 				   unsigned short val)
 {
 	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 |
@@ -390,7 +391,7 @@
 	regs->set.dcbdata0.byword = (vc2ireg << 24) | (val << 8);
 }
 
-extern __inline__ unsigned short newport_vc2_get(struct newport_regs *regs,
+static inline unsigned short newport_vc2_get(struct newport_regs *regs,
 					     unsigned char vc2ireg)
 {
 	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 |
diff --git a/include/video/sstfb.h b/include/video/sstfb.h
index 0d77b52..3570f9c 100644
--- a/include/video/sstfb.h
+++ b/include/video/sstfb.h
@@ -334,6 +334,7 @@
 };
 
 struct sstfb_par {
+	u32 palette[16];
 	unsigned int yDim;
 	unsigned int hSyncOn;	/* hsync_len */
 	unsigned int hSyncOff;	/* left_margin + xres + right_margin */
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index 0423767..c1cc94b 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -140,52 +140,52 @@
 #ifdef __KERNEL__
 
 struct banshee_reg {
-  /* VGA rubbish */
-  unsigned char att[21];
-  unsigned char crt[25];
-  unsigned char gra[ 9];
-  unsigned char misc[1];
-  unsigned char seq[ 5];
+	/* VGA rubbish */
+	unsigned char att[21];
+	unsigned char crt[25];
+	unsigned char gra[ 9];
+	unsigned char misc[1];
+	unsigned char seq[ 5];
 
-  /* Banshee extensions */
-  unsigned char ext[2];
-  unsigned long vidcfg;
-  unsigned long vidpll;
-  unsigned long mempll;
-  unsigned long gfxpll;
-  unsigned long dacmode;
-  unsigned long vgainit0;
-  unsigned long vgainit1;
-  unsigned long screensize;
-  unsigned long stride;
-  unsigned long cursloc;
-  unsigned long curspataddr;
-  unsigned long cursc0;
-  unsigned long cursc1;
-  unsigned long startaddr;
-  unsigned long clip0min;
-  unsigned long clip0max;
-  unsigned long clip1min;
-  unsigned long clip1max;
-  unsigned long srcbase;
-  unsigned long dstbase;
-  unsigned long miscinit0;	
+	/* Banshee extensions */
+	unsigned char ext[2];
+	unsigned long vidcfg;
+	unsigned long vidpll;
+	unsigned long mempll;
+	unsigned long gfxpll;
+	unsigned long dacmode;
+	unsigned long vgainit0;
+	unsigned long vgainit1;
+	unsigned long screensize;
+	unsigned long stride;
+	unsigned long cursloc;
+	unsigned long curspataddr;
+	unsigned long cursc0;
+	unsigned long cursc1;
+	unsigned long startaddr;
+	unsigned long clip0min;
+	unsigned long clip0max;
+	unsigned long clip1min;
+	unsigned long clip1max;
+	unsigned long srcbase;
+	unsigned long dstbase;
+	unsigned long miscinit0;
 };
 
 struct tdfx_par {
-  u32 max_pixclock;
+	u32 max_pixclock;
+	u32 palette[16];
+	void __iomem *regbase_virt;
+	unsigned long iobase;
+	u32 baseline;
 
-  void __iomem *regbase_virt;
-  unsigned long iobase;
-  u32 baseline;
+	struct {
+		int w,u,d;
+		unsigned long enable,disable;
+		struct timer_list timer;
+	} hwcursor;
 
-  struct {
-     int w,u,d;
-     unsigned long enable,disable;
-     struct timer_list timer;
-  } hwcursor; 
-
-  spinlock_t DAClock;
+	spinlock_t DAClock;
 };
 
 #endif /* __KERNEL__ */
diff --git a/init/Kconfig b/init/Kconfig
index f8f6929..9bdd549 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -230,9 +230,7 @@
 
 config UID16
 	bool "Enable 16-bit UID system calls" if EMBEDDED
-	depends !ALPHA && !PPC && !PPC64 && !PARISC && !V850 && !ARCH_S390X
-	depends !X86_64 || IA32_EMULATION
-	depends !SPARC64 || SPARC32_COMPAT
+	depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION)
 	default y
 	help
 	  This enables the legacy 16-bit UID syscall wrappers.
diff --git a/init/main.c b/init/main.c
index 8342c28..e092b19 100644
--- a/init/main.c
+++ b/init/main.c
@@ -485,6 +485,7 @@
 	init_IRQ();
 	pidhash_init();
 	init_timers();
+	hrtimers_init();
 	softirq_init();
 	time_init();
 
diff --git a/kernel/Makefile b/kernel/Makefile
index a940bac..3551266 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -7,7 +7,8 @@
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
-	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o
+	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
+	    hrtimer.o
 
 obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
 obj-$(CONFIG_FUTEX) += futex.o
@@ -30,7 +31,6 @@
 obj-$(CONFIG_SYSFS) += ksysfs.o
 obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_SECCOMP) += seccomp.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 
diff --git a/kernel/compat.c b/kernel/compat.c
index 102296e..256e5d9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -514,6 +514,24 @@
 	return 0;
 } 
 
+long compat_sys_timer_create(clockid_t which_clock,
+			struct compat_sigevent __user *timer_event_spec,
+			timer_t __user *created_timer_id)
+{
+	struct sigevent __user *event = NULL;
+
+	if (timer_event_spec) {
+		struct sigevent kevent;
+
+		event = compat_alloc_user_space(sizeof(*event));
+		if (get_compat_sigevent(&kevent, timer_event_spec) ||
+		    copy_to_user(event, &kevent, sizeof(*event)))
+			return -EFAULT;
+	}
+
+	return sys_timer_create(which_clock, event, created_timer_id);
+}
+
 long compat_sys_timer_settime(timer_t timer_id, int flags,
 			  struct compat_itimerspec __user *new, 
 			  struct compat_itimerspec __user *old)
@@ -649,8 +667,6 @@
 		? -EFAULT : 0;
 }
 
-/* timer_create is architecture specific because it needs sigevent conversion */
-
 long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
 		       unsigned long bitmap_size)
 {
diff --git a/kernel/exit.c b/kernel/exit.c
index 309a46f..8027228 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -842,7 +842,7 @@
 	}
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
 	if (group_dead) {
- 		del_timer_sync(&tsk->signal->real_timer);
+ 		hrtimer_cancel(&tsk->signal->real_timer);
 		exit_itimers(tsk->signal);
 		acct_process(code);
 	}
@@ -1071,6 +1071,9 @@
 	}
 
 	if (likely(p->real_parent == p->parent) && likely(p->signal)) {
+		struct signal_struct *psig;
+		struct signal_struct *sig;
+
 		/*
 		 * The resource counters for the group leader are in its
 		 * own task_struct.  Those for dead threads in the group
@@ -1087,24 +1090,26 @@
 		 * here reaping other children at the same time.
 		 */
 		spin_lock_irq(&p->parent->sighand->siglock);
-		p->parent->signal->cutime =
-			cputime_add(p->parent->signal->cutime,
+		psig = p->parent->signal;
+		sig = p->signal;
+		psig->cutime =
+			cputime_add(psig->cutime,
 			cputime_add(p->utime,
-			cputime_add(p->signal->utime,
-				    p->signal->cutime)));
-		p->parent->signal->cstime =
-			cputime_add(p->parent->signal->cstime,
+			cputime_add(sig->utime,
+				    sig->cutime)));
+		psig->cstime =
+			cputime_add(psig->cstime,
 			cputime_add(p->stime,
-			cputime_add(p->signal->stime,
-				    p->signal->cstime)));
-		p->parent->signal->cmin_flt +=
-			p->min_flt + p->signal->min_flt + p->signal->cmin_flt;
-		p->parent->signal->cmaj_flt +=
-			p->maj_flt + p->signal->maj_flt + p->signal->cmaj_flt;
-		p->parent->signal->cnvcsw +=
-			p->nvcsw + p->signal->nvcsw + p->signal->cnvcsw;
-		p->parent->signal->cnivcsw +=
-			p->nivcsw + p->signal->nivcsw + p->signal->cnivcsw;
+			cputime_add(sig->stime,
+				    sig->cstime)));
+		psig->cmin_flt +=
+			p->min_flt + sig->min_flt + sig->cmin_flt;
+		psig->cmaj_flt +=
+			p->maj_flt + sig->maj_flt + sig->cmaj_flt;
+		psig->cnvcsw +=
+			p->nvcsw + sig->nvcsw + sig->cnvcsw;
+		psig->cnivcsw +=
+			p->nivcsw + sig->nivcsw + sig->cnivcsw;
 		spin_unlock_irq(&p->parent->sighand->siglock);
 	}
 
diff --git a/kernel/fork.c b/kernel/fork.c
index b18d645..3bdcab4 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -801,10 +801,10 @@
 	init_sigpending(&sig->shared_pending);
 	INIT_LIST_HEAD(&sig->posix_timers);
 
-	sig->it_real_value = sig->it_real_incr = 0;
+	hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC);
+	sig->it_real_incr.tv64 = 0;
 	sig->real_timer.function = it_real_fn;
-	sig->real_timer.data = (unsigned long) tsk;
-	init_timer(&sig->real_timer);
+	sig->real_timer.data = tsk;
 
 	sig->it_virt_expires = cputime_zero;
 	sig->it_virt_incr = cputime_zero;
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
new file mode 100644
index 0000000..f073a24
--- /dev/null
+++ b/kernel/hrtimer.c
@@ -0,0 +1,821 @@
+/*
+ *  linux/kernel/hrtimer.c
+ *
+ *  Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ *  High-resolution kernel timers
+ *
+ *  In contrast to the low-resolution timeout API implemented in
+ *  kernel/timer.c, hrtimers provide finer resolution and accuracy
+ *  depending on system configuration and capabilities.
+ *
+ *  These timers are currently used for:
+ *   - itimers
+ *   - POSIX timers
+ *   - nanosleep
+ *   - precise in-kernel timing
+ *
+ *  Started by: Thomas Gleixner and Ingo Molnar
+ *
+ *  Credits:
+ *	based on kernel/timer.c
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/hrtimer.h>
+#include <linux/notifier.h>
+#include <linux/syscalls.h>
+#include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
+
+/**
+ * ktime_get - get the monotonic time in ktime_t format
+ *
+ * returns the time in ktime_t format
+ */
+static ktime_t ktime_get(void)
+{
+	struct timespec now;
+
+	ktime_get_ts(&now);
+
+	return timespec_to_ktime(now);
+}
+
+/**
+ * ktime_get_real - get the real (wall-) time in ktime_t format
+ *
+ * returns the time in ktime_t format
+ */
+static ktime_t ktime_get_real(void)
+{
+	struct timespec now;
+
+	getnstimeofday(&now);
+
+	return timespec_to_ktime(now);
+}
+
+EXPORT_SYMBOL_GPL(ktime_get_real);
+
+/*
+ * The timer bases:
+ */
+
+#define MAX_HRTIMER_BASES 2
+
+static DEFINE_PER_CPU(struct hrtimer_base, hrtimer_bases[MAX_HRTIMER_BASES]) =
+{
+	{
+		.index = CLOCK_REALTIME,
+		.get_time = &ktime_get_real,
+		.resolution = KTIME_REALTIME_RES,
+	},
+	{
+		.index = CLOCK_MONOTONIC,
+		.get_time = &ktime_get,
+		.resolution = KTIME_MONOTONIC_RES,
+	},
+};
+
+/**
+ * ktime_get_ts - get the monotonic clock in timespec format
+ *
+ * @ts:		pointer to timespec variable
+ *
+ * The function calculates the monotonic clock from the realtime
+ * clock and the wall_to_monotonic offset and stores the result
+ * in normalized timespec format in the variable pointed to by ts.
+ */
+void ktime_get_ts(struct timespec *ts)
+{
+	struct timespec tomono;
+	unsigned long seq;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		getnstimeofday(ts);
+		tomono = wall_to_monotonic;
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,
+				ts->tv_nsec + tomono.tv_nsec);
+}
+EXPORT_SYMBOL_GPL(ktime_get_ts);
+
+/*
+ * Functions and macros which are different for UP/SMP systems are kept in a
+ * single place
+ */
+#ifdef CONFIG_SMP
+
+#define set_curr_timer(b, t)		do { (b)->curr_timer = (t); } while (0)
+
+/*
+ * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock
+ * means that all timers which are tied to this base via timer->base are
+ * locked, and the base itself is locked too.
+ *
+ * So __run_timers/migrate_timers can safely modify all timers which could
+ * be found on the lists/queues.
+ *
+ * When the timer's base is locked, and the timer removed from list, it is
+ * possible to set timer->base = NULL and drop the lock: the timer remains
+ * locked.
+ */
+static struct hrtimer_base *lock_hrtimer_base(const struct hrtimer *timer,
+					      unsigned long *flags)
+{
+	struct hrtimer_base *base;
+
+	for (;;) {
+		base = timer->base;
+		if (likely(base != NULL)) {
+			spin_lock_irqsave(&base->lock, *flags);
+			if (likely(base == timer->base))
+				return base;
+			/* The timer has migrated to another CPU: */
+			spin_unlock_irqrestore(&base->lock, *flags);
+		}
+		cpu_relax();
+	}
+}
+
+/*
+ * Switch the timer base to the current CPU when possible.
+ */
+static inline struct hrtimer_base *
+switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
+{
+	struct hrtimer_base *new_base;
+
+	new_base = &__get_cpu_var(hrtimer_bases[base->index]);
+
+	if (base != new_base) {
+		/*
+		 * We are trying to schedule the timer on the local CPU.
+		 * However we can't change timer's base while it is running,
+		 * so we keep it on the same CPU. No hassle vs. reprogramming
+		 * the event source in the high resolution case. The softirq
+		 * code will take care of this when the timer function has
+		 * completed. There is no conflict as we hold the lock until
+		 * the timer is enqueued.
+		 */
+		if (unlikely(base->curr_timer == timer))
+			return base;
+
+		/* See the comment in lock_timer_base() */
+		timer->base = NULL;
+		spin_unlock(&base->lock);
+		spin_lock(&new_base->lock);
+		timer->base = new_base;
+	}
+	return new_base;
+}
+
+#else /* CONFIG_SMP */
+
+#define set_curr_timer(b, t)		do { } while (0)
+
+static inline struct hrtimer_base *
+lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
+{
+	struct hrtimer_base *base = timer->base;
+
+	spin_lock_irqsave(&base->lock, *flags);
+
+	return base;
+}
+
+#define switch_hrtimer_base(t, b)	(b)
+
+#endif	/* !CONFIG_SMP */
+
+/*
+ * Functions for the union type storage format of ktime_t which are
+ * too large for inlining:
+ */
+#if BITS_PER_LONG < 64
+# ifndef CONFIG_KTIME_SCALAR
+/**
+ * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
+ *
+ * @kt:		addend
+ * @nsec:	the scalar nsec value to add
+ *
+ * Returns the sum of kt and nsec in ktime_t format
+ */
+ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
+{
+	ktime_t tmp;
+
+	if (likely(nsec < NSEC_PER_SEC)) {
+		tmp.tv64 = nsec;
+	} else {
+		unsigned long rem = do_div(nsec, NSEC_PER_SEC);
+
+		tmp = ktime_set((long)nsec, rem);
+	}
+
+	return ktime_add(kt, tmp);
+}
+
+#else /* CONFIG_KTIME_SCALAR */
+
+# endif /* !CONFIG_KTIME_SCALAR */
+
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+static unsigned long ktime_divns(const ktime_t kt, nsec_t div)
+{
+	u64 dclc, inc, dns;
+	int sft = 0;
+
+	dclc = dns = ktime_to_ns(kt);
+	inc = div;
+	/* Make sure the divisor is less than 2^32: */
+	while (div >> 32) {
+		sft++;
+		div >>= 1;
+	}
+	dclc >>= sft;
+	do_div(dclc, (unsigned long) div);
+
+	return (unsigned long) dclc;
+}
+
+#else /* BITS_PER_LONG < 64 */
+# define ktime_divns(kt, div)		(unsigned long)((kt).tv64 / (div))
+#endif /* BITS_PER_LONG >= 64 */
+
+/*
+ * Counterpart to lock_timer_base above:
+ */
+static inline
+void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
+{
+	spin_unlock_irqrestore(&timer->base->lock, *flags);
+}
+
+/**
+ * hrtimer_forward - forward the timer expiry
+ *
+ * @timer:	hrtimer to forward
+ * @interval:	the interval to forward
+ *
+ * Forward the timer expiry so it will expire in the future.
+ * The number of overruns is added to the overrun field.
+ */
+unsigned long
+hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
+{
+	unsigned long orun = 1;
+	ktime_t delta, now;
+
+	now = timer->base->get_time();
+
+	delta = ktime_sub(now, timer->expires);
+
+	if (delta.tv64 < 0)
+		return 0;
+
+	if (unlikely(delta.tv64 >= interval.tv64)) {
+		nsec_t incr = ktime_to_ns(interval);
+
+		orun = ktime_divns(delta, incr);
+		timer->expires = ktime_add_ns(timer->expires, incr * orun);
+		if (timer->expires.tv64 > now.tv64)
+			return orun;
+		/*
+		 * This (and the ktime_add() below) is the
+		 * correction for exact:
+		 */
+		orun++;
+	}
+	timer->expires = ktime_add(timer->expires, interval);
+
+	return orun;
+}
+
+/*
+ * enqueue_hrtimer - internal function to (re)start a timer
+ *
+ * The timer is inserted in expiry order. Insertion into the
+ * red black tree is O(log(n)). Must hold the base lock.
+ */
+static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+{
+	struct rb_node **link = &base->active.rb_node;
+	struct list_head *prev = &base->pending;
+	struct rb_node *parent = NULL;
+	struct hrtimer *entry;
+
+	/*
+	 * Find the right place in the rbtree:
+	 */
+	while (*link) {
+		parent = *link;
+		entry = rb_entry(parent, struct hrtimer, node);
+		/*
+		 * We dont care about collisions. Nodes with
+		 * the same expiry time stay together.
+		 */
+		if (timer->expires.tv64 < entry->expires.tv64)
+			link = &(*link)->rb_left;
+		else {
+			link = &(*link)->rb_right;
+			prev = &entry->list;
+		}
+	}
+
+	/*
+	 * Insert the timer to the rbtree and to the sorted list:
+	 */
+	rb_link_node(&timer->node, parent, link);
+	rb_insert_color(&timer->node, &base->active);
+	list_add(&timer->list, prev);
+
+	timer->state = HRTIMER_PENDING;
+}
+
+
+/*
+ * __remove_hrtimer - internal function to remove a timer
+ *
+ * Caller must hold the base lock.
+ */
+static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+{
+	/*
+	 * Remove the timer from the sorted list and from the rbtree:
+	 */
+	list_del(&timer->list);
+	rb_erase(&timer->node, &base->active);
+}
+
+/*
+ * remove hrtimer, called with base lock held
+ */
+static inline int
+remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+{
+	if (hrtimer_active(timer)) {
+		__remove_hrtimer(timer, base);
+		timer->state = HRTIMER_INACTIVE;
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * hrtimer_start - (re)start an relative timer on the current CPU
+ *
+ * @timer:	the timer to be added
+ * @tim:	expiry time
+ * @mode:	expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
+ *
+ * Returns:
+ *  0 on success
+ *  1 when the timer was active
+ */
+int
+hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+{
+	struct hrtimer_base *base, *new_base;
+	unsigned long flags;
+	int ret;
+
+	base = lock_hrtimer_base(timer, &flags);
+
+	/* Remove an active timer from the queue: */
+	ret = remove_hrtimer(timer, base);
+
+	/* Switch the timer base, if necessary: */
+	new_base = switch_hrtimer_base(timer, base);
+
+	if (mode == HRTIMER_REL)
+		tim = ktime_add(tim, new_base->get_time());
+	timer->expires = tim;
+
+	enqueue_hrtimer(timer, new_base);
+
+	unlock_hrtimer_base(timer, &flags);
+
+	return ret;
+}
+
+/**
+ * hrtimer_try_to_cancel - try to deactivate a timer
+ *
+ * @timer:	hrtimer to stop
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ * -1 when the timer is currently excuting the callback function and
+ *    can not be stopped
+ */
+int hrtimer_try_to_cancel(struct hrtimer *timer)
+{
+	struct hrtimer_base *base;
+	unsigned long flags;
+	int ret = -1;
+
+	base = lock_hrtimer_base(timer, &flags);
+
+	if (base->curr_timer != timer)
+		ret = remove_hrtimer(timer, base);
+
+	unlock_hrtimer_base(timer, &flags);
+
+	return ret;
+
+}
+
+/**
+ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
+ *
+ * @timer:	the timer to be cancelled
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ */
+int hrtimer_cancel(struct hrtimer *timer)
+{
+	for (;;) {
+		int ret = hrtimer_try_to_cancel(timer);
+
+		if (ret >= 0)
+			return ret;
+	}
+}
+
+/**
+ * hrtimer_get_remaining - get remaining time for the timer
+ *
+ * @timer:	the timer to read
+ */
+ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
+{
+	struct hrtimer_base *base;
+	unsigned long flags;
+	ktime_t rem;
+
+	base = lock_hrtimer_base(timer, &flags);
+	rem = ktime_sub(timer->expires, timer->base->get_time());
+	unlock_hrtimer_base(timer, &flags);
+
+	return rem;
+}
+
+/**
+ * hrtimer_rebase - rebase an initialized hrtimer to a different base
+ *
+ * @timer:	the timer to be rebased
+ * @clock_id:	the clock to be used
+ */
+void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id)
+{
+	struct hrtimer_base *bases;
+
+	bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+	timer->base = &bases[clock_id];
+}
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ *
+ * @timer:	the timer to be initialized
+ * @clock_id:	the clock to be used
+ */
+void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id)
+{
+	memset(timer, 0, sizeof(struct hrtimer));
+	hrtimer_rebase(timer, clock_id);
+}
+
+/**
+ * hrtimer_get_res - get the timer resolution for a clock
+ *
+ * @which_clock: which clock to query
+ * @tp:		 pointer to timespec variable to store the resolution
+ *
+ * Store the resolution of the clock selected by which_clock in the
+ * variable pointed to by tp.
+ */
+int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+{
+	struct hrtimer_base *bases;
+
+	tp->tv_sec = 0;
+	bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+	tp->tv_nsec = bases[which_clock].resolution;
+
+	return 0;
+}
+
+/*
+ * Expire the per base hrtimer-queue:
+ */
+static inline void run_hrtimer_queue(struct hrtimer_base *base)
+{
+	ktime_t now = base->get_time();
+
+	spin_lock_irq(&base->lock);
+
+	while (!list_empty(&base->pending)) {
+		struct hrtimer *timer;
+		int (*fn)(void *);
+		int restart;
+		void *data;
+
+		timer = list_entry(base->pending.next, struct hrtimer, list);
+		if (now.tv64 <= timer->expires.tv64)
+			break;
+
+		fn = timer->function;
+		data = timer->data;
+		set_curr_timer(base, timer);
+		__remove_hrtimer(timer, base);
+		spin_unlock_irq(&base->lock);
+
+		/*
+		 * fn == NULL is special case for the simplest timer
+		 * variant - wake up process and do not restart:
+		 */
+		if (!fn) {
+			wake_up_process(data);
+			restart = HRTIMER_NORESTART;
+		} else
+			restart = fn(data);
+
+		spin_lock_irq(&base->lock);
+
+		if (restart == HRTIMER_RESTART)
+			enqueue_hrtimer(timer, base);
+		else
+			timer->state = HRTIMER_EXPIRED;
+	}
+	set_curr_timer(base, NULL);
+	spin_unlock_irq(&base->lock);
+}
+
+/*
+ * Called from timer softirq every jiffy, expire hrtimers:
+ */
+void hrtimer_run_queues(void)
+{
+	struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
+	int i;
+
+	for (i = 0; i < MAX_HRTIMER_BASES; i++)
+		run_hrtimer_queue(&base[i]);
+}
+
+/*
+ * Sleep related functions:
+ */
+
+/**
+ * schedule_hrtimer - sleep until timeout
+ *
+ * @timer:	hrtimer variable initialized with the correct clock base
+ * @mode:	timeout value is abs/rel
+ *
+ * Make the current task sleep until @timeout is
+ * elapsed.
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout is guaranteed to
+ * pass before the routine returns. The routine will return 0
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task. In this case the remaining time
+ * will be returned
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ */
+static ktime_t __sched
+schedule_hrtimer(struct hrtimer *timer, const enum hrtimer_mode mode)
+{
+	/* fn stays NULL, meaning single-shot wakeup: */
+	timer->data = current;
+
+	hrtimer_start(timer, timer->expires, mode);
+
+	schedule();
+	hrtimer_cancel(timer);
+
+	/* Return the remaining time: */
+	if (timer->state != HRTIMER_EXPIRED)
+		return ktime_sub(timer->expires, timer->base->get_time());
+	else
+		return (ktime_t) {.tv64 = 0 };
+}
+
+static inline ktime_t __sched
+schedule_hrtimer_interruptible(struct hrtimer *timer,
+			       const enum hrtimer_mode mode)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	return schedule_hrtimer(timer, mode);
+}
+
+static long __sched
+nanosleep_restart(struct restart_block *restart, clockid_t clockid)
+{
+	struct timespec __user *rmtp, tu;
+	void *rfn_save = restart->fn;
+	struct hrtimer timer;
+	ktime_t rem;
+
+	restart->fn = do_no_restart_syscall;
+
+	hrtimer_init(&timer, clockid);
+
+	timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
+
+	rem = schedule_hrtimer_interruptible(&timer, HRTIMER_ABS);
+
+	if (rem.tv64 <= 0)
+		return 0;
+
+	rmtp = (struct timespec __user *) restart->arg2;
+	tu = ktime_to_timespec(rem);
+	if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
+		return -EFAULT;
+
+	restart->fn = rfn_save;
+
+	/* The other values in restart are already filled in */
+	return -ERESTART_RESTARTBLOCK;
+}
+
+static long __sched nanosleep_restart_mono(struct restart_block *restart)
+{
+	return nanosleep_restart(restart, CLOCK_MONOTONIC);
+}
+
+static long __sched nanosleep_restart_real(struct restart_block *restart)
+{
+	return nanosleep_restart(restart, CLOCK_REALTIME);
+}
+
+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+		       const enum hrtimer_mode mode, const clockid_t clockid)
+{
+	struct restart_block *restart;
+	struct hrtimer timer;
+	struct timespec tu;
+	ktime_t rem;
+
+	hrtimer_init(&timer, clockid);
+
+	timer.expires = timespec_to_ktime(*rqtp);
+
+	rem = schedule_hrtimer_interruptible(&timer, mode);
+	if (rem.tv64 <= 0)
+		return 0;
+
+	/* Absolute timers do not update the rmtp value: */
+	if (mode == HRTIMER_ABS)
+		return -ERESTARTNOHAND;
+
+	tu = ktime_to_timespec(rem);
+
+	if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
+		return -EFAULT;
+
+	restart = &current_thread_info()->restart_block;
+	restart->fn = (clockid == CLOCK_MONOTONIC) ?
+		nanosleep_restart_mono : nanosleep_restart_real;
+	restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF;
+	restart->arg1 = timer.expires.tv64 >> 32;
+	restart->arg2 = (unsigned long) rmtp;
+
+	return -ERESTART_RESTARTBLOCK;
+}
+
+asmlinkage long
+sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
+{
+	struct timespec tu;
+
+	if (copy_from_user(&tu, rqtp, sizeof(tu)))
+		return -EFAULT;
+
+	if (!timespec_valid(&tu))
+		return -EINVAL;
+
+	return hrtimer_nanosleep(&tu, rmtp, HRTIMER_REL, CLOCK_MONOTONIC);
+}
+
+/*
+ * Functions related to boot-time initialization:
+ */
+static void __devinit init_hrtimers_cpu(int cpu)
+{
+	struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
+	int i;
+
+	for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+		spin_lock_init(&base->lock);
+		INIT_LIST_HEAD(&base->pending);
+		base++;
+	}
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void migrate_hrtimer_list(struct hrtimer_base *old_base,
+				struct hrtimer_base *new_base)
+{
+	struct hrtimer *timer;
+	struct rb_node *node;
+
+	while ((node = rb_first(&old_base->active))) {
+		timer = rb_entry(node, struct hrtimer, node);
+		__remove_hrtimer(timer, old_base);
+		timer->base = new_base;
+		enqueue_hrtimer(timer, new_base);
+	}
+}
+
+static void migrate_hrtimers(int cpu)
+{
+	struct hrtimer_base *old_base, *new_base;
+	int i;
+
+	BUG_ON(cpu_online(cpu));
+	old_base = per_cpu(hrtimer_bases, cpu);
+	new_base = get_cpu_var(hrtimer_bases);
+
+	local_irq_disable();
+
+	for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+
+		spin_lock(&new_base->lock);
+		spin_lock(&old_base->lock);
+
+		BUG_ON(old_base->curr_timer);
+
+		migrate_hrtimer_list(old_base, new_base);
+
+		spin_unlock(&old_base->lock);
+		spin_unlock(&new_base->lock);
+		old_base++;
+		new_base++;
+	}
+
+	local_irq_enable();
+	put_cpu_var(hrtimer_bases);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
+					unsigned long action, void *hcpu)
+{
+	long cpu = (long)hcpu;
+
+	switch (action) {
+
+	case CPU_UP_PREPARE:
+		init_hrtimers_cpu(cpu);
+		break;
+
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+		migrate_hrtimers(cpu);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata hrtimers_nb = {
+	.notifier_call = hrtimer_cpu_notify,
+};
+
+void __init hrtimers_init(void)
+{
+	hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
+			  (void *)(long)smp_processor_id());
+	register_cpu_notifier(&hrtimers_nb);
+}
+
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 7c1b25e..c2c05c4 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -12,36 +12,46 @@
 #include <linux/syscalls.h>
 #include <linux/time.h>
 #include <linux/posix-timers.h>
+#include <linux/hrtimer.h>
 
 #include <asm/uaccess.h>
 
-static unsigned long it_real_value(struct signal_struct *sig)
+/**
+ * itimer_get_remtime - get remaining time for the timer
+ *
+ * @timer: the timer to read
+ *
+ * Returns the delta between the expiry time and now, which can be
+ * less than zero or 1usec for an pending expired timer
+ */
+static struct timeval itimer_get_remtime(struct hrtimer *timer)
 {
-	unsigned long val = 0;
-	if (timer_pending(&sig->real_timer)) {
-		val = sig->real_timer.expires - jiffies;
+	ktime_t rem = hrtimer_get_remaining(timer);
 
-		/* look out for negative/zero itimer.. */
-		if ((long) val <= 0)
-			val = 1;
-	}
-	return val;
+	/*
+	 * Racy but safe: if the itimer expires after the above
+	 * hrtimer_get_remtime() call but before this condition
+	 * then we return 0 - which is correct.
+	 */
+	if (hrtimer_active(timer)) {
+		if (rem.tv64 <= 0)
+			rem.tv64 = NSEC_PER_USEC;
+	} else
+		rem.tv64 = 0;
+
+	return ktime_to_timeval(rem);
 }
 
 int do_getitimer(int which, struct itimerval *value)
 {
 	struct task_struct *tsk = current;
-	unsigned long interval, val;
 	cputime_t cinterval, cval;
 
 	switch (which) {
 	case ITIMER_REAL:
-		spin_lock_irq(&tsk->sighand->siglock);
-		interval = tsk->signal->it_real_incr;
-		val = it_real_value(tsk->signal);
-		spin_unlock_irq(&tsk->sighand->siglock);
-		jiffies_to_timeval(val, &value->it_value);
-		jiffies_to_timeval(interval, &value->it_interval);
+		value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
+		value->it_interval =
+			ktime_to_timeval(tsk->signal->it_real_incr);
 		break;
 	case ITIMER_VIRTUAL:
 		read_lock(&tasklist_lock);
@@ -113,59 +123,45 @@
 }
 
 
-void it_real_fn(unsigned long __data)
+/*
+ * The timer is automagically restarted, when interval != 0
+ */
+int it_real_fn(void *data)
 {
-	struct task_struct * p = (struct task_struct *) __data;
-	unsigned long inc = p->signal->it_real_incr;
+	struct task_struct *tsk = (struct task_struct *) data;
 
-	send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
+	send_group_sig_info(SIGALRM, SEND_SIG_PRIV, tsk);
 
-	/*
-	 * Now restart the timer if necessary.  We don't need any locking
-	 * here because do_setitimer makes sure we have finished running
-	 * before it touches anything.
-	 * Note, we KNOW we are (or should be) at a jiffie edge here so
-	 * we don't need the +1 stuff.  Also, we want to use the prior
-	 * expire value so as to not "slip" a jiffie if we are late.
-	 * Deal with requesting a time prior to "now" here rather than
-	 * in add_timer.
-	 */
-	if (!inc)
-		return;
-	while (time_before_eq(p->signal->real_timer.expires, jiffies))
-		p->signal->real_timer.expires += inc;
-	add_timer(&p->signal->real_timer);
+	if (tsk->signal->it_real_incr.tv64 != 0) {
+		hrtimer_forward(&tsk->signal->real_timer,
+			       tsk->signal->it_real_incr);
+
+		return HRTIMER_RESTART;
+	}
+	return HRTIMER_NORESTART;
 }
 
 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 {
 	struct task_struct *tsk = current;
- 	unsigned long val, interval, expires;
+	struct hrtimer *timer;
+	ktime_t expires;
 	cputime_t cval, cinterval, nval, ninterval;
 
 	switch (which) {
 	case ITIMER_REAL:
-again:
-		spin_lock_irq(&tsk->sighand->siglock);
-		interval = tsk->signal->it_real_incr;
-		val = it_real_value(tsk->signal);
-		/* We are sharing ->siglock with it_real_fn() */
-		if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) {
-			spin_unlock_irq(&tsk->sighand->siglock);
-			goto again;
+		timer = &tsk->signal->real_timer;
+		hrtimer_cancel(timer);
+		if (ovalue) {
+			ovalue->it_value = itimer_get_remtime(timer);
+			ovalue->it_interval
+				= ktime_to_timeval(tsk->signal->it_real_incr);
 		}
 		tsk->signal->it_real_incr =
-			timeval_to_jiffies(&value->it_interval);
-		expires = timeval_to_jiffies(&value->it_value);
-		if (expires)
-			mod_timer(&tsk->signal->real_timer,
-				  jiffies + 1 + expires);
-		spin_unlock_irq(&tsk->sighand->siglock);
-		if (ovalue) {
-			jiffies_to_timeval(val, &ovalue->it_value);
-			jiffies_to_timeval(interval,
-					   &ovalue->it_interval);
-		}
+			timeval_to_ktime(value->it_interval);
+		expires = timeval_to_ktime(value->it_value);
+		if (expires.tv64 != 0)
+			hrtimer_start(timer, expires, HRTIMER_REL);
 		break;
 	case ITIMER_VIRTUAL:
 		nval = timeval_to_cputime(&value->it_value);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 2c95848..de14416 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -26,6 +26,9 @@
 #include <asm/system.h>
 #include <asm/semaphore.h>
 
+/* Per cpu memory for storing cpu states in case of system crash. */
+note_buf_t* crash_notes;
+
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
 	.name  = "Crash kernel",
@@ -1054,9 +1057,24 @@
 	if (!locked) {
 		image = xchg(&kexec_crash_image, NULL);
 		if (image) {
-			machine_crash_shutdown(regs);
+			struct pt_regs fixed_regs;
+			crash_setup_regs(&fixed_regs, regs);
+			machine_crash_shutdown(&fixed_regs);
 			machine_kexec(image);
 		}
 		xchg(&kexec_lock, 0);
 	}
 }
+
+static int __init crash_notes_memory_init(void)
+{
+	/* Allocate memory for saving cpu registers. */
+	crash_notes = alloc_percpu(note_buf_t);
+	if (!crash_notes) {
+		printk("Kexec: Memory allocation for saving cpu register"
+		" states failed\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+module_init(crash_notes_memory_init)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 3bb71e6..34a885b 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -48,10 +48,11 @@
 static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 
-static DEFINE_SPINLOCK(kprobe_lock);	/* Protects kprobe_table */
+DECLARE_MUTEX(kprobe_mutex);		/* Protects kprobe_table */
 DEFINE_SPINLOCK(kretprobe_lock);	/* Protects kretprobe_inst_table */
 static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
 
+#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
 /*
  * kprobe->ainsn.insn points to the copy of the instruction to be
  * single-stepped. x86_64, POWER4 and above have no-exec support and
@@ -151,6 +152,7 @@
 		}
 	}
 }
+#endif
 
 /* We have preemption disabled.. so it is safe to use __ versions */
 static inline void set_kprobe_instance(struct kprobe *kp)
@@ -165,7 +167,7 @@
 
 /*
  * This routine is called either:
- * 	- under the kprobe_lock spinlock - during kprobe_[un]register()
+ * 	- under the kprobe_mutex - during kprobe_[un]register()
  * 				OR
  * 	- with preemption disabled - from arch/xxx/kernel/kprobes.c
  */
@@ -418,7 +420,6 @@
 /*
  * This is the second or subsequent kprobe at the address - handle
  * the intricacies
- * TODO: Move kcalloc outside the spin_lock
  */
 static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
 					  struct kprobe *p)
@@ -430,7 +431,7 @@
 		copy_kprobe(old_p, p);
 		ret = add_new_kprobe(old_p, p);
 	} else {
-		ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
+		ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
 		if (!ap)
 			return -ENOMEM;
 		add_aggr_kprobe(ap, old_p);
@@ -440,25 +441,6 @@
 	return ret;
 }
 
-/* kprobe removal house-keeping routines */
-static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
-{
-	arch_disarm_kprobe(p);
-	hlist_del_rcu(&p->hlist);
-	spin_unlock_irqrestore(&kprobe_lock, flags);
-	arch_remove_kprobe(p);
-}
-
-static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
-		struct kprobe *p, unsigned long flags)
-{
-	list_del_rcu(&p->list);
-	if (list_empty(&old_p->list))
-		cleanup_kprobe(old_p, flags);
-	else
-		spin_unlock_irqrestore(&kprobe_lock, flags);
-}
-
 static int __kprobes in_kprobes_functions(unsigned long addr)
 {
 	if (addr >= (unsigned long)__kprobes_text_start
@@ -470,7 +452,6 @@
 int __kprobes register_kprobe(struct kprobe *p)
 {
 	int ret = 0;
-	unsigned long flags = 0;
 	struct kprobe *old_p;
 	struct module *mod;
 
@@ -482,18 +463,17 @@
 			(unlikely(!try_module_get(mod))))
 		return -EINVAL;
 
-	if ((ret = arch_prepare_kprobe(p)) != 0)
-		goto rm_kprobe;
-
 	p->nmissed = 0;
-	spin_lock_irqsave(&kprobe_lock, flags);
+	down(&kprobe_mutex);
 	old_p = get_kprobe(p->addr);
 	if (old_p) {
 		ret = register_aggr_kprobe(old_p, p);
 		goto out;
 	}
 
-	arch_copy_kprobe(p);
+	if ((ret = arch_prepare_kprobe(p)) != 0)
+		goto out;
+
 	INIT_HLIST_NODE(&p->hlist);
 	hlist_add_head_rcu(&p->hlist,
 		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
@@ -501,10 +481,8 @@
   	arch_arm_kprobe(p);
 
 out:
-	spin_unlock_irqrestore(&kprobe_lock, flags);
-rm_kprobe:
-	if (ret == -EEXIST)
-		arch_remove_kprobe(p);
+	up(&kprobe_mutex);
+
 	if (ret && mod)
 		module_put(mod);
 	return ret;
@@ -512,29 +490,50 @@
 
 void __kprobes unregister_kprobe(struct kprobe *p)
 {
-	unsigned long flags;
-	struct kprobe *old_p;
 	struct module *mod;
+	struct kprobe *old_p, *list_p;
+	int cleanup_p;
 
-	spin_lock_irqsave(&kprobe_lock, flags);
+	down(&kprobe_mutex);
 	old_p = get_kprobe(p->addr);
-	if (old_p) {
-		/* cleanup_*_kprobe() does the spin_unlock_irqrestore */
-		if (old_p->pre_handler == aggr_pre_handler)
-			cleanup_aggr_kprobe(old_p, p, flags);
-		else
-			cleanup_kprobe(p, flags);
+	if (unlikely(!old_p)) {
+		up(&kprobe_mutex);
+		return;
+	}
+	if (p != old_p) {
+		list_for_each_entry_rcu(list_p, &old_p->list, list)
+			if (list_p == p)
+			/* kprobe p is a valid probe */
+				goto valid_p;
+		up(&kprobe_mutex);
+		return;
+	}
+valid_p:
+	if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
+		(p->list.next == &old_p->list) &&
+		(p->list.prev == &old_p->list))) {
+		/* Only probe on the hash list */
+		arch_disarm_kprobe(p);
+		hlist_del_rcu(&old_p->hlist);
+		cleanup_p = 1;
+	} else {
+		list_del_rcu(&p->list);
+		cleanup_p = 0;
+	}
 
-		synchronize_sched();
+	up(&kprobe_mutex);
 
-		if ((mod = module_text_address((unsigned long)p->addr)))
-			module_put(mod);
+	synchronize_sched();
+	if ((mod = module_text_address((unsigned long)p->addr)))
+		module_put(mod);
 
-		if (old_p->pre_handler == aggr_pre_handler &&
-				list_empty(&old_p->list))
+	if (cleanup_p) {
+		if (p != old_p) {
+			list_del_rcu(&p->list);
 			kfree(old_p);
-	} else
-		spin_unlock_irqrestore(&kprobe_lock, flags);
+		}
+		arch_remove_kprobe(p);
+	}
 }
 
 static struct notifier_block kprobe_exceptions_nb = {
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 99af8b0..d5eeae0 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -51,16 +51,6 @@
 KERNEL_ATTR_RW(uevent_helper);
 #endif
 
-#ifdef CONFIG_KEXEC
-#include <asm/kexec.h>
-
-static ssize_t crash_notes_show(struct subsystem *subsys, char *page)
-{
-	return sprintf(page, "%p\n", (void *)crash_notes);
-}
-KERNEL_ATTR_RO(crash_notes);
-#endif
-
 decl_subsys(kernel, NULL, NULL);
 EXPORT_SYMBOL_GPL(kernel_subsys);
 
@@ -69,9 +59,6 @@
 	&uevent_seqnum_attr.attr,
 	&uevent_helper_attr.attr,
 #endif
-#ifdef CONFIG_KEXEC
-	&crash_notes_attr.attr,
-#endif
 	NULL
 };
 
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 4c68edf..520f6c5 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -7,7 +7,7 @@
 #include <asm/uaccess.h>
 #include <linux/errno.h>
 
-static int check_clock(clockid_t which_clock)
+static int check_clock(const clockid_t which_clock)
 {
 	int error = 0;
 	struct task_struct *p;
@@ -31,7 +31,7 @@
 }
 
 static inline union cpu_time_count
-timespec_to_sample(clockid_t which_clock, const struct timespec *tp)
+timespec_to_sample(const clockid_t which_clock, const struct timespec *tp)
 {
 	union cpu_time_count ret;
 	ret.sched = 0;		/* high half always zero when .cpu used */
@@ -43,7 +43,7 @@
 	return ret;
 }
 
-static void sample_to_timespec(clockid_t which_clock,
+static void sample_to_timespec(const clockid_t which_clock,
 			       union cpu_time_count cpu,
 			       struct timespec *tp)
 {
@@ -55,7 +55,7 @@
 	}
 }
 
-static inline int cpu_time_before(clockid_t which_clock,
+static inline int cpu_time_before(const clockid_t which_clock,
 				  union cpu_time_count now,
 				  union cpu_time_count then)
 {
@@ -65,7 +65,7 @@
 		return cputime_lt(now.cpu, then.cpu);
 	}
 }
-static inline void cpu_time_add(clockid_t which_clock,
+static inline void cpu_time_add(const clockid_t which_clock,
 				union cpu_time_count *acc,
 			        union cpu_time_count val)
 {
@@ -75,7 +75,7 @@
 		acc->cpu = cputime_add(acc->cpu, val.cpu);
 	}
 }
-static inline union cpu_time_count cpu_time_sub(clockid_t which_clock,
+static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock,
 						union cpu_time_count a,
 						union cpu_time_count b)
 {
@@ -151,7 +151,7 @@
 	return (p == current) ? current_sched_time(p) : p->sched_time;
 }
 
-int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
 {
 	int error = check_clock(which_clock);
 	if (!error) {
@@ -169,7 +169,7 @@
 	return error;
 }
 
-int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp)
+int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
 {
 	/*
 	 * You can never reset a CPU clock, but we check for other errors
@@ -186,7 +186,7 @@
 /*
  * Sample a per-thread clock for the given task.
  */
-static int cpu_clock_sample(clockid_t which_clock, struct task_struct *p,
+static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
 			    union cpu_time_count *cpu)
 {
 	switch (CPUCLOCK_WHICH(which_clock)) {
@@ -248,7 +248,7 @@
  * Sample a process (thread group) clock for the given group_leader task.
  * Must be called with tasklist_lock held for reading.
  */
-static int cpu_clock_sample_group(clockid_t which_clock,
+static int cpu_clock_sample_group(const clockid_t which_clock,
 				  struct task_struct *p,
 				  union cpu_time_count *cpu)
 {
@@ -262,7 +262,7 @@
 }
 
 
-int posix_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
 {
 	const pid_t pid = CPUCLOCK_PID(which_clock);
 	int error = -EINVAL;
@@ -1399,8 +1399,8 @@
 
 static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
 
-int posix_cpu_nsleep(clockid_t which_clock, int flags,
-		     struct timespec *rqtp)
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+		     struct timespec *rqtp, struct timespec __user *rmtp)
 {
 	struct restart_block *restart_block =
 	    &current_thread_info()->restart_block;
@@ -1425,7 +1425,6 @@
 	error = posix_cpu_timer_create(&timer);
 	timer.it_process = current;
 	if (!error) {
-		struct timespec __user *rmtp;
 		static struct itimerspec zero_it;
 		struct itimerspec it = { .it_value = *rqtp,
 					 .it_interval = {} };
@@ -1472,7 +1471,6 @@
 		/*
 		 * Report back to the user the time still remaining.
 		 */
-		rmtp = (struct timespec __user *) restart_block->arg1;
 		if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
 		    copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
 			return -EFAULT;
@@ -1480,6 +1478,7 @@
 		restart_block->fn = posix_cpu_clock_nanosleep_restart;
 		/* Caller already set restart_block->arg1 */
 		restart_block->arg0 = which_clock;
+		restart_block->arg1 = (unsigned long) rmtp;
 		restart_block->arg2 = rqtp->tv_sec;
 		restart_block->arg3 = rqtp->tv_nsec;
 
@@ -1493,21 +1492,28 @@
 posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
 {
 	clockid_t which_clock = restart_block->arg0;
-	struct timespec t = { .tv_sec = restart_block->arg2,
-			      .tv_nsec = restart_block->arg3 };
+	struct timespec __user *rmtp;
+	struct timespec t;
+
+	rmtp = (struct timespec __user *) restart_block->arg1;
+	t.tv_sec = restart_block->arg2;
+	t.tv_nsec = restart_block->arg3;
+
 	restart_block->fn = do_no_restart_syscall;
-	return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t);
+	return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
 }
 
 
 #define PROCESS_CLOCK	MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)
 #define THREAD_CLOCK	MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)
 
-static int process_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+static int process_cpu_clock_getres(const clockid_t which_clock,
+				    struct timespec *tp)
 {
 	return posix_cpu_clock_getres(PROCESS_CLOCK, tp);
 }
-static int process_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+static int process_cpu_clock_get(const clockid_t which_clock,
+				 struct timespec *tp)
 {
 	return posix_cpu_clock_get(PROCESS_CLOCK, tp);
 }
@@ -1516,16 +1522,19 @@
 	timer->it_clock = PROCESS_CLOCK;
 	return posix_cpu_timer_create(timer);
 }
-static int process_cpu_nsleep(clockid_t which_clock, int flags,
-			      struct timespec *rqtp)
+static int process_cpu_nsleep(const clockid_t which_clock, int flags,
+			      struct timespec *rqtp,
+			      struct timespec __user *rmtp)
 {
-	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
+	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
 }
-static int thread_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+static int thread_cpu_clock_getres(const clockid_t which_clock,
+				   struct timespec *tp)
 {
 	return posix_cpu_clock_getres(THREAD_CLOCK, tp);
 }
-static int thread_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+static int thread_cpu_clock_get(const clockid_t which_clock,
+				struct timespec *tp)
 {
 	return posix_cpu_clock_get(THREAD_CLOCK, tp);
 }
@@ -1534,8 +1543,8 @@
 	timer->it_clock = THREAD_CLOCK;
 	return posix_cpu_timer_create(timer);
 }
-static int thread_cpu_nsleep(clockid_t which_clock, int flags,
-			      struct timespec *rqtp)
+static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
+			      struct timespec *rqtp, struct timespec __user *rmtp)
 {
 	return -EINVAL;
 }
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 5870efb..9e66e61 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -48,21 +48,6 @@
 #include <linux/workqueue.h>
 #include <linux/module.h>
 
-#ifndef div_long_long_rem
-#include <asm/div64.h>
-
-#define div_long_long_rem(dividend,divisor,remainder) ({ \
-		       u64 result = dividend;		\
-		       *remainder = do_div(result,divisor); \
-		       result; })
-
-#endif
-#define CLOCK_REALTIME_RES TICK_NSEC  /* In nano seconds. */
-
-static inline u64  mpy_l_X_l_ll(unsigned long mpy1,unsigned long mpy2)
-{
-	return (u64)mpy1 * mpy2;
-}
 /*
  * Management arrays for POSIX timers.	 Timers are kept in slab memory
  * Timer ids are allocated by an external routine that keeps track of the
@@ -148,18 +133,18 @@
  */
 
 static struct k_clock posix_clocks[MAX_CLOCKS];
-/*
- * We only have one real clock that can be set so we need only one abs list,
- * even if we should want to have several clocks with differing resolutions.
- */
-static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list),
-				      .lock = SPIN_LOCK_UNLOCKED};
 
-static void posix_timer_fn(unsigned long);
-static u64 do_posix_clock_monotonic_gettime_parts(
-	struct timespec *tp, struct timespec *mo);
-int do_posix_clock_monotonic_gettime(struct timespec *tp);
-static int do_posix_clock_monotonic_get(clockid_t, struct timespec *tp);
+/*
+ * These ones are defined below.
+ */
+static int common_nsleep(const clockid_t, int flags, struct timespec *t,
+			 struct timespec __user *rmtp);
+static void common_timer_get(struct k_itimer *, struct itimerspec *);
+static int common_timer_set(struct k_itimer *, int,
+			    struct itimerspec *, struct itimerspec *);
+static int common_timer_del(struct k_itimer *timer);
+
+static int posix_timer_fn(void *data);
 
 static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
 
@@ -184,7 +169,7 @@
  * the function pointer CALL in struct k_clock.
  */
 
-static inline int common_clock_getres(clockid_t which_clock,
+static inline int common_clock_getres(const clockid_t which_clock,
 				      struct timespec *tp)
 {
 	tp->tv_sec = 0;
@@ -192,39 +177,33 @@
 	return 0;
 }
 
-static inline int common_clock_get(clockid_t which_clock, struct timespec *tp)
+/*
+ * Get real time for posix timers
+ */
+static int common_clock_get(clockid_t which_clock, struct timespec *tp)
 {
-	getnstimeofday(tp);
+	ktime_get_real_ts(tp);
 	return 0;
 }
 
-static inline int common_clock_set(clockid_t which_clock, struct timespec *tp)
+static inline int common_clock_set(const clockid_t which_clock,
+				   struct timespec *tp)
 {
 	return do_sys_settimeofday(tp, NULL);
 }
 
 static inline int common_timer_create(struct k_itimer *new_timer)
 {
-	INIT_LIST_HEAD(&new_timer->it.real.abs_timer_entry);
-	init_timer(&new_timer->it.real.timer);
-	new_timer->it.real.timer.data = (unsigned long) new_timer;
+	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock);
+	new_timer->it.real.timer.data = new_timer;
 	new_timer->it.real.timer.function = posix_timer_fn;
 	return 0;
 }
 
 /*
- * These ones are defined below.
+ * Return nonzero if we know a priori this clockid_t value is bogus.
  */
-static int common_nsleep(clockid_t, int flags, struct timespec *t);
-static void common_timer_get(struct k_itimer *, struct itimerspec *);
-static int common_timer_set(struct k_itimer *, int,
-			    struct itimerspec *, struct itimerspec *);
-static int common_timer_del(struct k_itimer *timer);
-
-/*
- * Return nonzero iff we know a priori this clockid_t value is bogus.
- */
-static inline int invalid_clockid(clockid_t which_clock)
+static inline int invalid_clockid(const clockid_t which_clock)
 {
 	if (which_clock < 0)	/* CPU clock, posix_cpu_* will check it */
 		return 0;
@@ -232,26 +211,32 @@
 		return 1;
 	if (posix_clocks[which_clock].clock_getres != NULL)
 		return 0;
-#ifndef CLOCK_DISPATCH_DIRECT
 	if (posix_clocks[which_clock].res != 0)
 		return 0;
-#endif
 	return 1;
 }
 
+/*
+ * Get monotonic time for posix timers
+ */
+static int posix_ktime_get_ts(clockid_t which_clock, struct timespec *tp)
+{
+	ktime_get_ts(tp);
+	return 0;
+}
 
 /*
  * Initialize everything, well, just everything in Posix clocks/timers ;)
  */
 static __init int init_posix_timers(void)
 {
-	struct k_clock clock_realtime = {.res = CLOCK_REALTIME_RES,
-					 .abs_struct = &abs_list
+	struct k_clock clock_realtime = {
+		.clock_getres = hrtimer_get_res,
 	};
-	struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES,
-		.abs_struct = NULL,
-		.clock_get = do_posix_clock_monotonic_get,
-		.clock_set = do_posix_clock_nosettime
+	struct k_clock clock_monotonic = {
+		.clock_getres = hrtimer_get_res,
+		.clock_get = posix_ktime_get_ts,
+		.clock_set = do_posix_clock_nosettime,
 	};
 
 	register_posix_clock(CLOCK_REALTIME, &clock_realtime);
@@ -265,117 +250,17 @@
 
 __initcall(init_posix_timers);
 
-static void tstojiffie(struct timespec *tp, int res, u64 *jiff)
-{
-	long sec = tp->tv_sec;
-	long nsec = tp->tv_nsec + res - 1;
-
-	if (nsec >= NSEC_PER_SEC) {
-		sec++;
-		nsec -= NSEC_PER_SEC;
-	}
-
-	/*
-	 * The scaling constants are defined in <linux/time.h>
-	 * The difference between there and here is that we do the
-	 * res rounding and compute a 64-bit result (well so does that
-	 * but it then throws away the high bits).
-  	 */
-	*jiff =  (mpy_l_X_l_ll(sec, SEC_CONVERSION) +
-		  (mpy_l_X_l_ll(nsec, NSEC_CONVERSION) >> 
-		   (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
-}
-
-/*
- * This function adjusts the timer as needed as a result of the clock
- * being set.  It should only be called for absolute timers, and then
- * under the abs_list lock.  It computes the time difference and sets
- * the new jiffies value in the timer.  It also updates the timers
- * reference wall_to_monotonic value.  It is complicated by the fact
- * that tstojiffies() only handles positive times and it needs to work
- * with both positive and negative times.  Also, for negative offsets,
- * we need to defeat the res round up.
- *
- * Return is true if there is a new time, else false.
- */
-static long add_clockset_delta(struct k_itimer *timr,
-			       struct timespec *new_wall_to)
-{
-	struct timespec delta;
-	int sign = 0;
-	u64 exp;
-
-	set_normalized_timespec(&delta,
-				new_wall_to->tv_sec -
-				timr->it.real.wall_to_prev.tv_sec,
-				new_wall_to->tv_nsec -
-				timr->it.real.wall_to_prev.tv_nsec);
-	if (likely(!(delta.tv_sec | delta.tv_nsec)))
-		return 0;
-	if (delta.tv_sec < 0) {
-		set_normalized_timespec(&delta,
-					-delta.tv_sec,
-					1 - delta.tv_nsec -
-					posix_clocks[timr->it_clock].res);
-		sign++;
-	}
-	tstojiffie(&delta, posix_clocks[timr->it_clock].res, &exp);
-	timr->it.real.wall_to_prev = *new_wall_to;
-	timr->it.real.timer.expires += (sign ? -exp : exp);
-	return 1;
-}
-
-static void remove_from_abslist(struct k_itimer *timr)
-{
-	if (!list_empty(&timr->it.real.abs_timer_entry)) {
-		spin_lock(&abs_list.lock);
-		list_del_init(&timr->it.real.abs_timer_entry);
-		spin_unlock(&abs_list.lock);
-	}
-}
-
 static void schedule_next_timer(struct k_itimer *timr)
 {
-	struct timespec new_wall_to;
-	struct now_struct now;
-	unsigned long seq;
-
-	/*
-	 * Set up the timer for the next interval (if there is one).
-	 * Note: this code uses the abs_timer_lock to protect
-	 * it.real.wall_to_prev and must hold it until exp is set, not exactly
-	 * obvious...
-
-	 * This function is used for CLOCK_REALTIME* and
-	 * CLOCK_MONOTONIC* timers.  If we ever want to handle other
-	 * CLOCKs, the calling code (do_schedule_next_timer) would need
-	 * to pull the "clock" info from the timer and dispatch the
-	 * "other" CLOCKs "next timer" code (which, I suppose should
-	 * also be added to the k_clock structure).
-	 */
-	if (!timr->it.real.incr)
+	if (timr->it.real.interval.tv64 == 0)
 		return;
 
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		new_wall_to =	wall_to_monotonic;
-		posix_get_now(&now);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	if (!list_empty(&timr->it.real.abs_timer_entry)) {
-		spin_lock(&abs_list.lock);
-		add_clockset_delta(timr, &new_wall_to);
-
-		posix_bump_timer(timr, now);
-
-		spin_unlock(&abs_list.lock);
-	} else {
-		posix_bump_timer(timr, now);
-	}
+	timr->it_overrun += hrtimer_forward(&timr->it.real.timer,
+					    timr->it.real.interval);
 	timr->it_overrun_last = timr->it_overrun;
 	timr->it_overrun = -1;
 	++timr->it_requeue_pending;
-	add_timer(&timr->it.real.timer);
+	hrtimer_restart(&timr->it.real.timer);
 }
 
 /*
@@ -396,31 +281,23 @@
 
 	timr = lock_timer(info->si_tid, &flags);
 
-	if (!timr || timr->it_requeue_pending != info->si_sys_private)
-		goto exit;
+	if (timr && timr->it_requeue_pending == info->si_sys_private) {
+		if (timr->it_clock < 0)
+			posix_cpu_timer_schedule(timr);
+		else
+			schedule_next_timer(timr);
 
-	if (timr->it_clock < 0)	/* CPU clock */
-		posix_cpu_timer_schedule(timr);
-	else
-		schedule_next_timer(timr);
-	info->si_overrun = timr->it_overrun_last;
-exit:
-	if (timr)
-		unlock_timer(timr, flags);
+		info->si_overrun = timr->it_overrun_last;
+	}
+
+	unlock_timer(timr, flags);
 }
 
 int posix_timer_event(struct k_itimer *timr,int si_private)
 {
 	memset(&timr->sigq->info, 0, sizeof(siginfo_t));
 	timr->sigq->info.si_sys_private = si_private;
-	/*
-	 * Send signal to the process that owns this timer.
-
-	 * This code assumes that all the possible abs_lists share the
-	 * same lock (there is only one list at this time). If this is
-	 * not the case, the CLOCK info would need to be used to find
-	 * the proper abs list lock.
-	 */
+	/* Send signal to the process that owns this timer.*/
 
 	timr->sigq->info.si_signo = timr->it_sigev_signo;
 	timr->sigq->info.si_errno = 0;
@@ -454,65 +331,36 @@
 
  * This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
  */
-static void posix_timer_fn(unsigned long __data)
+static int posix_timer_fn(void *data)
 {
-	struct k_itimer *timr = (struct k_itimer *) __data;
+	struct k_itimer *timr = data;
 	unsigned long flags;
-	unsigned long seq;
-	struct timespec delta, new_wall_to;
-	u64 exp = 0;
-	int do_notify = 1;
+	int si_private = 0;
+	int ret = HRTIMER_NORESTART;
 
 	spin_lock_irqsave(&timr->it_lock, flags);
-	if (!list_empty(&timr->it.real.abs_timer_entry)) {
-		spin_lock(&abs_list.lock);
-		do {
-			seq = read_seqbegin(&xtime_lock);
-			new_wall_to =	wall_to_monotonic;
-		} while (read_seqretry(&xtime_lock, seq));
-		set_normalized_timespec(&delta,
-					new_wall_to.tv_sec -
-					timr->it.real.wall_to_prev.tv_sec,
-					new_wall_to.tv_nsec -
-					timr->it.real.wall_to_prev.tv_nsec);
-		if (likely((delta.tv_sec | delta.tv_nsec ) == 0)) {
-			/* do nothing, timer is on time */
-		} else if (delta.tv_sec < 0) {
-			/* do nothing, timer is already late */
-		} else {
-			/* timer is early due to a clock set */
-			tstojiffie(&delta,
-				   posix_clocks[timr->it_clock].res,
-				   &exp);
-			timr->it.real.wall_to_prev = new_wall_to;
-			timr->it.real.timer.expires += exp;
-			add_timer(&timr->it.real.timer);
-			do_notify = 0;
+
+	if (timr->it.real.interval.tv64 != 0)
+		si_private = ++timr->it_requeue_pending;
+
+	if (posix_timer_event(timr, si_private)) {
+		/*
+		 * signal was not sent because of sig_ignor
+		 * we will not get a call back to restart it AND
+		 * it should be restarted.
+		 */
+		if (timr->it.real.interval.tv64 != 0) {
+			timr->it_overrun +=
+				hrtimer_forward(&timr->it.real.timer,
+						timr->it.real.interval);
+			ret = HRTIMER_RESTART;
 		}
-		spin_unlock(&abs_list.lock);
-
 	}
-	if (do_notify)  {
-		int si_private=0;
 
-		if (timr->it.real.incr)
-			si_private = ++timr->it_requeue_pending;
-		else {
-			remove_from_abslist(timr);
-		}
-
-		if (posix_timer_event(timr, si_private))
-			/*
-			 * signal was not sent because of sig_ignor
-			 * we will not get a call back to restart it AND
-			 * it should be restarted.
-			 */
-			schedule_next_timer(timr);
-	}
-	unlock_timer(timr, flags); /* hold thru abs lock to keep irq off */
+	unlock_timer(timr, flags);
+	return ret;
 }
 
-
 static inline struct task_struct * good_sigevent(sigevent_t * event)
 {
 	struct task_struct *rtn = current->group_leader;
@@ -530,7 +378,7 @@
 	return rtn;
 }
 
-void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock)
+void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock)
 {
 	if ((unsigned) clock_id >= MAX_CLOCKS) {
 		printk("POSIX clock register failed for clock_id %d\n",
@@ -576,7 +424,7 @@
 /* Create a POSIX.1b interval timer. */
 
 asmlinkage long
-sys_timer_create(clockid_t which_clock,
+sys_timer_create(const clockid_t which_clock,
 		 struct sigevent __user *timer_event_spec,
 		 timer_t __user * created_timer_id)
 {
@@ -602,8 +450,7 @@
 		goto out;
 	}
 	spin_lock_irq(&idr_lock);
-	error = idr_get_new(&posix_timers_id,
-			    (void *) new_timer,
+	error = idr_get_new(&posix_timers_id, (void *) new_timer,
 			    &new_timer_id);
 	spin_unlock_irq(&idr_lock);
 	if (error == -EAGAIN)
@@ -704,27 +551,6 @@
 }
 
 /*
- * good_timespec
- *
- * This function checks the elements of a timespec structure.
- *
- * Arguments:
- * ts	     : Pointer to the timespec structure to check
- *
- * Return value:
- * If a NULL pointer was passed in, or the tv_nsec field was less than 0
- * or greater than NSEC_PER_SEC, or the tv_sec field was less than 0,
- * this function returns 0. Otherwise it returns 1.
- */
-static int good_timespec(const struct timespec *ts)
-{
-	if ((!ts) || (ts->tv_sec < 0) ||
-			((unsigned) ts->tv_nsec >= NSEC_PER_SEC))
-		return 0;
-	return 1;
-}
-
-/*
  * Locking issues: We need to protect the result of the id look up until
  * we get the timer locked down so it is not deleted under us.  The
  * removal is done under the idr spinlock so we use that here to bridge
@@ -776,39 +602,39 @@
 static void
 common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 {
-	unsigned long expires;
-	struct now_struct now;
+	ktime_t remaining;
+	struct hrtimer *timer = &timr->it.real.timer;
 
-	do
-		expires = timr->it.real.timer.expires;
-	while ((volatile long) (timr->it.real.timer.expires) != expires);
+	memset(cur_setting, 0, sizeof(struct itimerspec));
+	remaining = hrtimer_get_remaining(timer);
 
-	posix_get_now(&now);
-
-	if (expires &&
-	    ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) &&
-	    !timr->it.real.incr &&
-	    posix_time_before(&timr->it.real.timer, &now))
-		timr->it.real.timer.expires = expires = 0;
-	if (expires) {
-		if (timr->it_requeue_pending & REQUEUE_PENDING ||
-		    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
-			posix_bump_timer(timr, now);
-			expires = timr->it.real.timer.expires;
-		}
-		else
-			if (!timer_pending(&timr->it.real.timer))
-				expires = 0;
-		if (expires)
-			expires -= now.jiffies;
+	/* Time left ? or timer pending */
+	if (remaining.tv64 > 0 || hrtimer_active(timer))
+		goto calci;
+	/* interval timer ? */
+	if (timr->it.real.interval.tv64 == 0)
+		return;
+	/*
+	 * When a requeue is pending or this is a SIGEV_NONE timer
+	 * move the expiry time forward by intervals, so expiry is >
+	 * now.
+	 */
+	if (timr->it_requeue_pending & REQUEUE_PENDING ||
+	    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
+		timr->it_overrun +=
+			hrtimer_forward(timer, timr->it.real.interval);
+		remaining = hrtimer_get_remaining(timer);
 	}
-	jiffies_to_timespec(expires, &cur_setting->it_value);
-	jiffies_to_timespec(timr->it.real.incr, &cur_setting->it_interval);
-
-	if (cur_setting->it_value.tv_sec < 0) {
+ calci:
+	/* interval timer ? */
+	if (timr->it.real.interval.tv64 != 0)
+		cur_setting->it_interval =
+			ktime_to_timespec(timr->it.real.interval);
+	/* Return 0 only, when the timer is expired and not pending */
+	if (remaining.tv64 <= 0)
 		cur_setting->it_value.tv_nsec = 1;
-		cur_setting->it_value.tv_sec = 0;
-	}
+	else
+		cur_setting->it_value = ktime_to_timespec(remaining);
 }
 
 /* Get the time remaining on a POSIX.1b interval timer. */
@@ -832,6 +658,7 @@
 
 	return 0;
 }
+
 /*
  * Get the number of overruns of a POSIX.1b interval timer.  This is to
  * be the overrun of the timer last delivered.  At the same time we are
@@ -841,7 +668,6 @@
  * the call back to do_schedule_next_timer().  So all we need to do is
  * to pick up the frozen overrun.
  */
-
 asmlinkage long
 sys_timer_getoverrun(timer_t timer_id)
 {
@@ -858,84 +684,6 @@
 
 	return overrun;
 }
-/*
- * Adjust for absolute time
- *
- * If absolute time is given and it is not CLOCK_MONOTONIC, we need to
- * adjust for the offset between the timer clock (CLOCK_MONOTONIC) and
- * what ever clock he is using.
- *
- * If it is relative time, we need to add the current (CLOCK_MONOTONIC)
- * time to it to get the proper time for the timer.
- */
-static int adjust_abs_time(struct k_clock *clock, struct timespec *tp, 
-			   int abs, u64 *exp, struct timespec *wall_to)
-{
-	struct timespec now;
-	struct timespec oc = *tp;
-	u64 jiffies_64_f;
-	int rtn =0;
-
-	if (abs) {
-		/*
-		 * The mask pick up the 4 basic clocks 
-		 */
-		if (!((clock - &posix_clocks[0]) & ~CLOCKS_MASK)) {
-			jiffies_64_f = do_posix_clock_monotonic_gettime_parts(
-				&now,  wall_to);
-			/*
-			 * If we are doing a MONOTONIC clock
-			 */
-			if((clock - &posix_clocks[0]) & CLOCKS_MONO){
-				now.tv_sec += wall_to->tv_sec;
-				now.tv_nsec += wall_to->tv_nsec;
-			}
-		} else {
-			/*
-			 * Not one of the basic clocks
-			 */
-			clock->clock_get(clock - posix_clocks, &now);
-			jiffies_64_f = get_jiffies_64();
-		}
-		/*
-		 * Take away now to get delta and normalize
-		 */
-		set_normalized_timespec(&oc, oc.tv_sec - now.tv_sec,
-					oc.tv_nsec - now.tv_nsec);
-	}else{
-		jiffies_64_f = get_jiffies_64();
-	}
-	/*
-	 * Check if the requested time is prior to now (if so set now)
-	 */
-	if (oc.tv_sec < 0)
-		oc.tv_sec = oc.tv_nsec = 0;
-
-	if (oc.tv_sec | oc.tv_nsec)
-		set_normalized_timespec(&oc, oc.tv_sec,
-					oc.tv_nsec + clock->res);
-	tstojiffie(&oc, clock->res, exp);
-
-	/*
-	 * Check if the requested time is more than the timer code
-	 * can handle (if so we error out but return the value too).
-	 */
-	if (*exp > ((u64)MAX_JIFFY_OFFSET))
-			/*
-			 * This is a considered response, not exactly in
-			 * line with the standard (in fact it is silent on
-			 * possible overflows).  We assume such a large 
-			 * value is ALMOST always a programming error and
-			 * try not to compound it by setting a really dumb
-			 * value.
-			 */
-			rtn = -EINVAL;
-	/*
-	 * return the actual jiffies expire time, full 64 bits
-	 */
-	*exp += jiffies_64_f;
-	return rtn;
-}
 
 /* Set a POSIX.1b interval timer. */
 /* timr->it_lock is taken. */
@@ -943,68 +691,48 @@
 common_timer_set(struct k_itimer *timr, int flags,
 		 struct itimerspec *new_setting, struct itimerspec *old_setting)
 {
-	struct k_clock *clock = &posix_clocks[timr->it_clock];
-	u64 expire_64;
+	struct hrtimer *timer = &timr->it.real.timer;
 
 	if (old_setting)
 		common_timer_get(timr, old_setting);
 
 	/* disable the timer */
-	timr->it.real.incr = 0;
+	timr->it.real.interval.tv64 = 0;
 	/*
 	 * careful here.  If smp we could be in the "fire" routine which will
 	 * be spinning as we hold the lock.  But this is ONLY an SMP issue.
 	 */
-	if (try_to_del_timer_sync(&timr->it.real.timer) < 0) {
-#ifdef CONFIG_SMP
-		/*
-		 * It can only be active if on an other cpu.  Since
-		 * we have cleared the interval stuff above, it should
-		 * clear once we release the spin lock.  Of course once
-		 * we do that anything could happen, including the
-		 * complete melt down of the timer.  So return with
-		 * a "retry" exit status.
-		 */
+	if (hrtimer_try_to_cancel(timer) < 0)
 		return TIMER_RETRY;
-#endif
-	}
-
-	remove_from_abslist(timr);
 
 	timr->it_requeue_pending = (timr->it_requeue_pending + 2) & 
 		~REQUEUE_PENDING;
 	timr->it_overrun_last = 0;
-	timr->it_overrun = -1;
-	/*
-	 *switch off the timer when it_value is zero
-	 */
-	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) {
-		timr->it.real.timer.expires = 0;
+
+	/* switch off the timer when it_value is zero */
+	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
 		return 0;
-	}
 
-	if (adjust_abs_time(clock,
-			    &new_setting->it_value, flags & TIMER_ABSTIME, 
-			    &expire_64, &(timr->it.real.wall_to_prev))) {
-		return -EINVAL;
-	}
-	timr->it.real.timer.expires = (unsigned long)expire_64;
-	tstojiffie(&new_setting->it_interval, clock->res, &expire_64);
-	timr->it.real.incr = (unsigned long)expire_64;
-
-	/*
-	 * We do not even queue SIGEV_NONE timers!  But we do put them
-	 * in the abs list so we can do that right.
+	/* Posix madness. Only absolute CLOCK_REALTIME timers
+	 * are affected by clock sets. So we must reiniatilize
+	 * the timer.
 	 */
-	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE))
-		add_timer(&timr->it.real.timer);
+	if (timr->it_clock == CLOCK_REALTIME && (flags & TIMER_ABSTIME))
+		hrtimer_rebase(timer, CLOCK_REALTIME);
+	else
+		hrtimer_rebase(timer, CLOCK_MONOTONIC);
 
-	if (flags & TIMER_ABSTIME && clock->abs_struct) {
-		spin_lock(&clock->abs_struct->lock);
-		list_add_tail(&(timr->it.real.abs_timer_entry),
-			      &(clock->abs_struct->list));
-		spin_unlock(&clock->abs_struct->lock);
-	}
+	timer->expires = timespec_to_ktime(new_setting->it_value);
+
+	/* Convert interval */
+	timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
+
+	/* SIGEV_NONE timers are not queued ! See common_timer_get */
+	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+		return 0;
+
+	hrtimer_start(timer, timer->expires, (flags & TIMER_ABSTIME) ?
+		      HRTIMER_ABS : HRTIMER_REL);
 	return 0;
 }
 
@@ -1026,8 +754,8 @@
 	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
 		return -EFAULT;
 
-	if ((!good_timespec(&new_spec.it_interval)) ||
-	    (!good_timespec(&new_spec.it_value)))
+	if (!timespec_valid(&new_spec.it_interval) ||
+	    !timespec_valid(&new_spec.it_value))
 		return -EINVAL;
 retry:
 	timr = lock_timer(timer_id, &flag);
@@ -1043,8 +771,8 @@
 		goto retry;
 	}
 
-	if (old_setting && !error && copy_to_user(old_setting,
-						  &old_spec, sizeof (old_spec)))
+	if (old_setting && !error &&
+	    copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
 		error = -EFAULT;
 
 	return error;
@@ -1052,24 +780,10 @@
 
 static inline int common_timer_del(struct k_itimer *timer)
 {
-	timer->it.real.incr = 0;
+	timer->it.real.interval.tv64 = 0;
 
-	if (try_to_del_timer_sync(&timer->it.real.timer) < 0) {
-#ifdef CONFIG_SMP
-		/*
-		 * It can only be active if on an other cpu.  Since
-		 * we have cleared the interval stuff above, it should
-		 * clear once we release the spin lock.  Of course once
-		 * we do that anything could happen, including the
-		 * complete melt down of the timer.  So return with
-		 * a "retry" exit status.
-		 */
+	if (hrtimer_try_to_cancel(&timer->it.real.timer) < 0)
 		return TIMER_RETRY;
-#endif
-	}
-
-	remove_from_abslist(timer);
-
 	return 0;
 }
 
@@ -1085,24 +799,16 @@
 	struct k_itimer *timer;
 	long flags;
 
-#ifdef CONFIG_SMP
-	int error;
 retry_delete:
-#endif
 	timer = lock_timer(timer_id, &flags);
 	if (!timer)
 		return -EINVAL;
 
-#ifdef CONFIG_SMP
-	error = timer_delete_hook(timer);
-
-	if (error == TIMER_RETRY) {
+	if (timer_delete_hook(timer) == TIMER_RETRY) {
 		unlock_timer(timer, flags);
 		goto retry_delete;
 	}
-#else
-	timer_delete_hook(timer);
-#endif
+
 	spin_lock(&current->sighand->siglock);
 	list_del(&timer->list);
 	spin_unlock(&current->sighand->siglock);
@@ -1119,6 +825,7 @@
 	release_posix_timer(timer, IT_ID_SET);
 	return 0;
 }
+
 /*
  * return timer owned by the process, used by exit_itimers
  */
@@ -1126,22 +833,13 @@
 {
 	unsigned long flags;
 
-#ifdef CONFIG_SMP
-	int error;
 retry_delete:
-#endif
 	spin_lock_irqsave(&timer->it_lock, flags);
 
-#ifdef CONFIG_SMP
-	error = timer_delete_hook(timer);
-
-	if (error == TIMER_RETRY) {
+	if (timer_delete_hook(timer) == TIMER_RETRY) {
 		unlock_timer(timer, flags);
 		goto retry_delete;
 	}
-#else
-	timer_delete_hook(timer);
-#endif
 	list_del(&timer->list);
 	/*
 	 * This keeps any tasks waiting on the spin lock from thinking
@@ -1170,57 +868,8 @@
 	}
 }
 
-/*
- * And now for the "clock" calls
- *
- * These functions are called both from timer functions (with the timer
- * spin_lock_irq() held and from clock calls with no locking.	They must
- * use the save flags versions of locks.
- */
-
-/*
- * We do ticks here to avoid the irq lock ( they take sooo long).
- * The seqlock is great here.  Since we a reader, we don't really care
- * if we are interrupted since we don't take lock that will stall us or
- * any other cpu. Voila, no irq lock is needed.
- *
- */
-
-static u64 do_posix_clock_monotonic_gettime_parts(
-	struct timespec *tp, struct timespec *mo)
-{
-	u64 jiff;
-	unsigned int seq;
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		getnstimeofday(tp);
-		*mo = wall_to_monotonic;
-		jiff = jiffies_64;
-
-	} while(read_seqretry(&xtime_lock, seq));
-
-	return jiff;
-}
-
-static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp)
-{
-	struct timespec wall_to_mono;
-
-	do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono);
-
-	set_normalized_timespec(tp, tp->tv_sec + wall_to_mono.tv_sec,
-				tp->tv_nsec + wall_to_mono.tv_nsec);
-
-	return 0;
-}
-
-int do_posix_clock_monotonic_gettime(struct timespec *tp)
-{
-	return do_posix_clock_monotonic_get(CLOCK_MONOTONIC, tp);
-}
-
-int do_posix_clock_nosettime(clockid_t clockid, struct timespec *tp)
+/* Not available / possible... functions */
+int do_posix_clock_nosettime(const clockid_t clockid, struct timespec *tp)
 {
 	return -EINVAL;
 }
@@ -1232,7 +881,8 @@
 }
 EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
 
-int do_posix_clock_nonanosleep(clockid_t clock, int flags, struct timespec *t)
+int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
+			       struct timespec *t, struct timespec __user *r)
 {
 #ifndef ENOTSUP
 	return -EOPNOTSUPP;	/* aka ENOTSUP in userland for POSIX */
@@ -1242,8 +892,8 @@
 }
 EXPORT_SYMBOL_GPL(do_posix_clock_nonanosleep);
 
-asmlinkage long
-sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
+asmlinkage long sys_clock_settime(const clockid_t which_clock,
+				  const struct timespec __user *tp)
 {
 	struct timespec new_tp;
 
@@ -1256,7 +906,7 @@
 }
 
 asmlinkage long
-sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp)
+sys_clock_gettime(const clockid_t which_clock, struct timespec __user *tp)
 {
 	struct timespec kernel_tp;
 	int error;
@@ -1273,7 +923,7 @@
 }
 
 asmlinkage long
-sys_clock_getres(clockid_t which_clock, struct timespec __user *tp)
+sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)
 {
 	struct timespec rtn_tp;
 	int error;
@@ -1292,117 +942,34 @@
 }
 
 /*
- * The standard says that an absolute nanosleep call MUST wake up at
- * the requested time in spite of clock settings.  Here is what we do:
- * For each nanosleep call that needs it (only absolute and not on
- * CLOCK_MONOTONIC* (as it can not be set)) we thread a little structure
- * into the "nanosleep_abs_list".  All we need is the task_struct pointer.
- * When ever the clock is set we just wake up all those tasks.	 The rest
- * is done by the while loop in clock_nanosleep().
- *
- * On locking, clock_was_set() is called from update_wall_clock which
- * holds (or has held for it) a write_lock_irq( xtime_lock) and is
- * called from the timer bh code.  Thus we need the irq save locks.
- *
- * Also, on the call from update_wall_clock, that is done as part of a
- * softirq thing.  We don't want to delay the system that much (possibly
- * long list of timers to fix), so we defer that work to keventd.
+ * nanosleep for monotonic and realtime clocks
  */
-
-static DECLARE_WAIT_QUEUE_HEAD(nanosleep_abs_wqueue);
-static DECLARE_WORK(clock_was_set_work, (void(*)(void*))clock_was_set, NULL);
-
-static DECLARE_MUTEX(clock_was_set_lock);
-
-void clock_was_set(void)
+static int common_nsleep(const clockid_t which_clock, int flags,
+			 struct timespec *tsave, struct timespec __user *rmtp)
 {
-	struct k_itimer *timr;
-	struct timespec new_wall_to;
-	LIST_HEAD(cws_list);
-	unsigned long seq;
+	int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+	int clockid = which_clock;
 
-
-	if (unlikely(in_interrupt())) {
-		schedule_work(&clock_was_set_work);
-		return;
+	switch (which_clock) {
+	case CLOCK_REALTIME:
+		/* Posix madness. Only absolute timers on clock realtime
+		   are affected by clock set. */
+		if (mode != HRTIMER_ABS)
+			clockid = CLOCK_MONOTONIC;
+	case CLOCK_MONOTONIC:
+		break;
+	default:
+		return -EINVAL;
 	}
-	wake_up_all(&nanosleep_abs_wqueue);
-
-	/*
-	 * Check if there exist TIMER_ABSTIME timers to correct.
-	 *
-	 * Notes on locking: This code is run in task context with irq
-	 * on.  We CAN be interrupted!  All other usage of the abs list
-	 * lock is under the timer lock which holds the irq lock as
-	 * well.  We REALLY don't want to scan the whole list with the
-	 * interrupt system off, AND we would like a sequence lock on
-	 * this code as well.  Since we assume that the clock will not
-	 * be set often, it seems ok to take and release the irq lock
-	 * for each timer.  In fact add_timer will do this, so this is
-	 * not an issue.  So we know when we are done, we will move the
-	 * whole list to a new location.  Then as we process each entry,
-	 * we will move it to the actual list again.  This way, when our
-	 * copy is empty, we are done.  We are not all that concerned
-	 * about preemption so we will use a semaphore lock to protect
-	 * aginst reentry.  This way we will not stall another
-	 * processor.  It is possible that this may delay some timers
-	 * that should have expired, given the new clock, but even this
-	 * will be minimal as we will always update to the current time,
-	 * even if it was set by a task that is waiting for entry to
-	 * this code.  Timers that expire too early will be caught by
-	 * the expire code and restarted.
-
-	 * Absolute timers that repeat are left in the abs list while
-	 * waiting for the task to pick up the signal.  This means we
-	 * may find timers that are not in the "add_timer" list, but are
-	 * in the abs list.  We do the same thing for these, save
-	 * putting them back in the "add_timer" list.  (Note, these are
-	 * left in the abs list mainly to indicate that they are
-	 * ABSOLUTE timers, a fact that is used by the re-arm code, and
-	 * for which we have no other flag.)
-
-	 */
-
-	down(&clock_was_set_lock);
-	spin_lock_irq(&abs_list.lock);
-	list_splice_init(&abs_list.list, &cws_list);
-	spin_unlock_irq(&abs_list.lock);
-	do {
-		do {
-			seq = read_seqbegin(&xtime_lock);
-			new_wall_to =	wall_to_monotonic;
-		} while (read_seqretry(&xtime_lock, seq));
-
-		spin_lock_irq(&abs_list.lock);
-		if (list_empty(&cws_list)) {
-			spin_unlock_irq(&abs_list.lock);
-			break;
-		}
-		timr = list_entry(cws_list.next, struct k_itimer,
-				  it.real.abs_timer_entry);
-
-		list_del_init(&timr->it.real.abs_timer_entry);
-		if (add_clockset_delta(timr, &new_wall_to) &&
-		    del_timer(&timr->it.real.timer))  /* timer run yet? */
-			add_timer(&timr->it.real.timer);
-		list_add(&timr->it.real.abs_timer_entry, &abs_list.list);
-		spin_unlock_irq(&abs_list.lock);
-	} while (1);
-
-	up(&clock_was_set_lock);
+	return hrtimer_nanosleep(tsave, rmtp, mode, clockid);
 }
 
-long clock_nanosleep_restart(struct restart_block *restart_block);
-
 asmlinkage long
-sys_clock_nanosleep(clockid_t which_clock, int flags,
+sys_clock_nanosleep(const clockid_t which_clock, int flags,
 		    const struct timespec __user *rqtp,
 		    struct timespec __user *rmtp)
 {
 	struct timespec t;
-	struct restart_block *restart_block =
-	    &(current_thread_info()->restart_block);
-	int ret;
 
 	if (invalid_clockid(which_clock))
 		return -EINVAL;
@@ -1410,125 +977,9 @@
 	if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
 		return -EFAULT;
 
-	if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
+	if (!timespec_valid(&t))
 		return -EINVAL;
 
-	/*
-	 * Do this here as nsleep function does not have the real address.
-	 */
-	restart_block->arg1 = (unsigned long)rmtp;
-
-	ret = CLOCK_DISPATCH(which_clock, nsleep, (which_clock, flags, &t));
-
-	if ((ret == -ERESTART_RESTARTBLOCK) && rmtp &&
-					copy_to_user(rmtp, &t, sizeof (t)))
-		return -EFAULT;
-	return ret;
-}
-
-
-static int common_nsleep(clockid_t which_clock,
-			 int flags, struct timespec *tsave)
-{
-	struct timespec t, dum;
-	DECLARE_WAITQUEUE(abs_wqueue, current);
-	u64 rq_time = (u64)0;
-	s64 left;
-	int abs;
-	struct restart_block *restart_block =
-	    &current_thread_info()->restart_block;
-
-	abs_wqueue.flags = 0;
-	abs = flags & TIMER_ABSTIME;
-
-	if (restart_block->fn == clock_nanosleep_restart) {
-		/*
-		 * Interrupted by a non-delivered signal, pick up remaining
-		 * time and continue.  Remaining time is in arg2 & 3.
-		 */
-		restart_block->fn = do_no_restart_syscall;
-
-		rq_time = restart_block->arg3;
-		rq_time = (rq_time << 32) + restart_block->arg2;
-		if (!rq_time)
-			return -EINTR;
-		left = rq_time - get_jiffies_64();
-		if (left <= (s64)0)
-			return 0;	/* Already passed */
-	}
-
-	if (abs && (posix_clocks[which_clock].clock_get !=
-			    posix_clocks[CLOCK_MONOTONIC].clock_get))
-		add_wait_queue(&nanosleep_abs_wqueue, &abs_wqueue);
-
-	do {
-		t = *tsave;
-		if (abs || !rq_time) {
-			adjust_abs_time(&posix_clocks[which_clock], &t, abs,
-					&rq_time, &dum);
-		}
-
-		left = rq_time - get_jiffies_64();
-		if (left >= (s64)MAX_JIFFY_OFFSET)
-			left = (s64)MAX_JIFFY_OFFSET;
-		if (left < (s64)0)
-			break;
-
-		schedule_timeout_interruptible(left);
-
-		left = rq_time - get_jiffies_64();
-	} while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING));
-
-	if (abs_wqueue.task_list.next)
-		finish_wait(&nanosleep_abs_wqueue, &abs_wqueue);
-
-	if (left > (s64)0) {
-
-		/*
-		 * Always restart abs calls from scratch to pick up any
-		 * clock shifting that happened while we are away.
-		 */
-		if (abs)
-			return -ERESTARTNOHAND;
-
-		left *= TICK_NSEC;
-		tsave->tv_sec = div_long_long_rem(left, 
-						  NSEC_PER_SEC, 
-						  &tsave->tv_nsec);
-		/*
-		 * Restart works by saving the time remaing in 
-		 * arg2 & 3 (it is 64-bits of jiffies).  The other
-		 * info we need is the clock_id (saved in arg0). 
-		 * The sys_call interface needs the users 
-		 * timespec return address which _it_ saves in arg1.
-		 * Since we have cast the nanosleep call to a clock_nanosleep
-		 * both can be restarted with the same code.
-		 */
-		restart_block->fn = clock_nanosleep_restart;
-		restart_block->arg0 = which_clock;
-		/*
-		 * Caller sets arg1
-		 */
-		restart_block->arg2 = rq_time & 0xffffffffLL;
-		restart_block->arg3 = rq_time >> 32;
-
-		return -ERESTART_RESTARTBLOCK;
-	}
-
-	return 0;
-}
-/*
- * This will restart clock_nanosleep.
- */
-long
-clock_nanosleep_restart(struct restart_block *restart_block)
-{
-	struct timespec t;
-	int ret = common_nsleep(restart_block->arg0, 0, &t);
-
-	if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
-	    copy_to_user((struct timespec __user *)(restart_block->arg1), &t,
-			 sizeof (t)))
-		return -EFAULT;
-	return ret;
+	return CLOCK_DISPATCH(which_clock, nsleep,
+			      (which_clock, flags, &t, rmtp));
 }
diff --git a/kernel/resource.c b/kernel/resource.c
index 92285d8..e3080fc 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -464,7 +464,7 @@
 
 EXPORT_SYMBOL(__request_region);
 
-int __deprecated __check_region(struct resource *parent, unsigned long start, unsigned long n)
+int __check_region(struct resource *parent, unsigned long start, unsigned long n)
 {
 	struct resource * res;
 
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index b3d4dc8..dcfb5d7 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -87,13 +87,9 @@
 {
 	int i, ret = 0;
 	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
-	mm_segment_t old_fs = get_fs();
 
 	/* One high-prio thread per cpu.  We'll do this one. */
-	set_fs(KERNEL_DS);
-	sys_sched_setscheduler(current->pid, SCHED_FIFO,
-				(struct sched_param __user *)&param);
-	set_fs(old_fs);
+	sched_setscheduler(current, SCHED_FIFO, &param);
 
 	atomic_set(&stopmachine_thread_ack, 0);
 	stopmachine_num_threads = 0;
diff --git a/kernel/time.c b/kernel/time.c
index b94bfa8..169e832 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -154,6 +154,9 @@
 	static int firsttime = 1;
 	int error = 0;
 
+	if (!timespec_valid(tv))
+		return -EINVAL;
+
 	error = security_settime(tv, tz);
 	if (error)
 		return error;
@@ -561,27 +564,107 @@
 EXPORT_SYMBOL_GPL(getnstimeofday);
 #endif
 
-void getnstimestamp(struct timespec *ts)
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+unsigned long
+mktime(const unsigned int year0, const unsigned int mon0,
+       const unsigned int day, const unsigned int hour,
+       const unsigned int min, const unsigned int sec)
 {
-	unsigned int seq;
-	struct timespec wall2mono;
+	unsigned int mon = mon0, year = year0;
 
-	/* synchronize with settimeofday() changes */
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		getnstimeofday(ts);
-		wall2mono = wall_to_monotonic;
-	} while(unlikely(read_seqretry(&xtime_lock, seq)));
-
-	/* adjust to monotonicaly-increasing values */
-	ts->tv_sec += wall2mono.tv_sec;
-	ts->tv_nsec += wall2mono.tv_nsec;
-	while (unlikely(ts->tv_nsec >= NSEC_PER_SEC)) {
-		ts->tv_nsec -= NSEC_PER_SEC;
-		ts->tv_sec++;
+	/* 1..12 -> 11,12,1..10 */
+	if (0 >= (int) (mon -= 2)) {
+		mon += 12;	/* Puts Feb last since it has leap day */
+		year -= 1;
 	}
+
+	return ((((unsigned long)
+		  (year/4 - year/100 + year/400 + 367*mon/12 + day) +
+		  year*365 - 719499
+	    )*24 + hour /* now have hours */
+	  )*60 + min /* now have minutes */
+	)*60 + sec; /* finally seconds */
 }
-EXPORT_SYMBOL_GPL(getnstimestamp);
+
+EXPORT_SYMBOL(mktime);
+
+/**
+ * set_normalized_timespec - set timespec sec and nsec parts and normalize
+ *
+ * @ts:		pointer to timespec variable to be set
+ * @sec:	seconds to set
+ * @nsec:	nanoseconds to set
+ *
+ * Set seconds and nanoseconds field of a timespec variable and
+ * normalize to the timespec storage format
+ *
+ * Note: The tv_nsec part is always in the range of
+ * 	0 <= tv_nsec < NSEC_PER_SEC
+ * For negative values only the tv_sec field is negative !
+ */
+void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
+{
+	while (nsec >= NSEC_PER_SEC) {
+		nsec -= NSEC_PER_SEC;
+		++sec;
+	}
+	while (nsec < 0) {
+		nsec += NSEC_PER_SEC;
+		--sec;
+	}
+	ts->tv_sec = sec;
+	ts->tv_nsec = nsec;
+}
+
+/**
+ * ns_to_timespec - Convert nanoseconds to timespec
+ * @nsec:       the nanoseconds value to be converted
+ *
+ * Returns the timespec representation of the nsec parameter.
+ */
+inline struct timespec ns_to_timespec(const nsec_t nsec)
+{
+	struct timespec ts;
+
+	if (nsec)
+		ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC,
+						     &ts.tv_nsec);
+	else
+		ts.tv_sec = ts.tv_nsec = 0;
+
+	return ts;
+}
+
+/**
+ * ns_to_timeval - Convert nanoseconds to timeval
+ * @nsec:       the nanoseconds value to be converted
+ *
+ * Returns the timeval representation of the nsec parameter.
+ */
+struct timeval ns_to_timeval(const nsec_t nsec)
+{
+	struct timespec ts = ns_to_timespec(nsec);
+	struct timeval tv;
+
+	tv.tv_sec = ts.tv_sec;
+	tv.tv_usec = (suseconds_t) ts.tv_nsec / 1000;
+
+	return tv;
+}
 
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
diff --git a/kernel/timer.c b/kernel/timer.c
index 074b4bd..4f1cb0a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -858,6 +858,7 @@
 {
 	tvec_base_t *base = &__get_cpu_var(tvec_bases);
 
+ 	hrtimer_run_queues();
 	if (time_after_eq(jiffies, base->timer_jiffies))
 		__run_timers(base);
 }
@@ -1119,62 +1120,6 @@
 	return current->pid;
 }
 
-static long __sched nanosleep_restart(struct restart_block *restart)
-{
-	unsigned long expire = restart->arg0, now = jiffies;
-	struct timespec __user *rmtp = (struct timespec __user *) restart->arg1;
-	long ret;
-
-	/* Did it expire while we handled signals? */
-	if (!time_after(expire, now))
-		return 0;
-
-	expire = schedule_timeout_interruptible(expire - now);
-
-	ret = 0;
-	if (expire) {
-		struct timespec t;
-		jiffies_to_timespec(expire, &t);
-
-		ret = -ERESTART_RESTARTBLOCK;
-		if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
-			ret = -EFAULT;
-		/* The 'restart' block is already filled in */
-	}
-	return ret;
-}
-
-asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
-{
-	struct timespec t;
-	unsigned long expire;
-	long ret;
-
-	if (copy_from_user(&t, rqtp, sizeof(t)))
-		return -EFAULT;
-
-	if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
-		return -EINVAL;
-
-	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
-	expire = schedule_timeout_interruptible(expire);
-
-	ret = 0;
-	if (expire) {
-		struct restart_block *restart;
-		jiffies_to_timespec(expire, &t);
-		if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
-			return -EFAULT;
-
-		restart = &current_thread_info()->restart_block;
-		restart->fn = nanosleep_restart;
-		restart->arg0 = jiffies + expire;
-		restart->arg1 = (unsigned long) rmtp;
-		ret = -ERESTART_RESTARTBLOCK;
-	}
-	return ret;
-}
-
 /*
  * sys_sysinfo - fill in sysinfo struct
  */ 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1fcd856..a609235 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -9,15 +9,9 @@
 	  in kernel startup.
 
 
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
 config MAGIC_SYSRQ
 	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL && !UML
+	depends on !UML
 	help
 	  If you say Y here, you will have some control over the system even
 	  if the system crashes for example during kernel debugging (e.g., you
@@ -29,6 +23,12 @@
 	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
 	  unless you really know what this hack does.
 
+config DEBUG_KERNEL
+	bool "Kernel debugging"
+	help
+	  Say Y here if you are developing drivers or trying to debug and
+	  identify kernel problems.
+
 config LOG_BUF_SHIFT
 	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
 	range 12 21
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index dcd4be9..c8bb8cc 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -19,10 +19,11 @@
 	if (xchg(&print_once, 0)) {
 		if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
 			owner = lock->owner;
-		printk("BUG: spinlock %s on CPU#%d, %s/%d\n",
+		printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
 			msg, raw_smp_processor_id(),
 			current->comm, current->pid);
-		printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n",
+		printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
+				".owner_cpu: %d\n",
 			lock, lock->magic,
 			owner ? owner->comm : "<none>",
 			owner ? owner->pid : -1,
@@ -78,7 +79,8 @@
 		/* lockup suspected: */
 		if (print_once) {
 			print_once = 0;
-			printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n",
+			printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
+					"%s/%d, %p\n",
 				raw_smp_processor_id(), current->comm,
 				current->pid, lock);
 			dump_stack();
@@ -120,8 +122,8 @@
 	static long print_once = 1;
 
 	if (xchg(&print_once, 0)) {
-		printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg,
-			raw_smp_processor_id(), current->comm,
+		printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
+			msg, raw_smp_processor_id(), current->comm,
 			current->pid, lock);
 		dump_stack();
 #ifdef CONFIG_SMP
@@ -149,7 +151,8 @@
 		/* lockup suspected: */
 		if (print_once) {
 			print_once = 0;
-			printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n",
+			printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
+					"%s/%d, %p\n",
 				raw_smp_processor_id(), current->comm,
 				current->pid, lock);
 			dump_stack();
@@ -221,7 +224,8 @@
 		/* lockup suspected: */
 		if (print_once) {
 			print_once = 0;
-			printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n",
+			printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
+					"%s/%d, %p\n",
 				raw_smp_processor_id(), current->comm,
 				current->pid, lock);
 			dump_stack();
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
index ad9a1bf..1653dd9 100644
--- a/lib/zlib_deflate/deflate.c
+++ b/lib/zlib_deflate/deflate.c
@@ -255,6 +255,7 @@
 }
 
 /* ========================================================================= */
+#if 0
 int zlib_deflateSetDictionary(
 	z_streamp strm,
 	const Byte *dictionary,
@@ -297,6 +298,7 @@
     if (hash_head) hash_head = 0;  /* to make compiler happy */
     return Z_OK;
 }
+#endif  /*  0  */
 
 /* ========================================================================= */
 int zlib_deflateReset(
@@ -330,6 +332,7 @@
 }
 
 /* ========================================================================= */
+#if 0
 int zlib_deflateParams(
 	z_streamp strm,
 	int level,
@@ -365,6 +368,7 @@
     s->strategy = strategy;
     return err;
 }
+#endif  /*  0  */
 
 /* =========================================================================
  * Put a short in the pending buffer. The 16-bit value is put in MSB order.
@@ -572,6 +576,7 @@
 /* =========================================================================
  * Copy the source state to the destination state.
  */
+#if 0
 int zlib_deflateCopy (
 	z_streamp dest,
 	z_streamp source
@@ -624,6 +629,7 @@
     return Z_OK;
 #endif
 }
+#endif  /*  0  */
 
 /* ===========================================================================
  * Read a new buffer from the current input stream, update the adler32
diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c
index 5985b28..767b573 100644
--- a/lib/zlib_deflate/deflate_syms.c
+++ b/lib/zlib_deflate/deflate_syms.c
@@ -16,6 +16,4 @@
 EXPORT_SYMBOL(zlib_deflateInit2_);
 EXPORT_SYMBOL(zlib_deflateEnd);
 EXPORT_SYMBOL(zlib_deflateReset);
-EXPORT_SYMBOL(zlib_deflateCopy);
-EXPORT_SYMBOL(zlib_deflateParams);
 MODULE_LICENSE("GPL");
diff --git a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c
index 50f21ca4..c16cdef 100644
--- a/lib/zlib_inflate/infblock.c
+++ b/lib/zlib_inflate/infblock.c
@@ -338,6 +338,7 @@
 }
 
 
+#if 0
 void zlib_inflate_set_dictionary(
 	inflate_blocks_statef *s,
 	const Byte *d,
@@ -347,15 +348,18 @@
   memcpy(s->window, d, n);
   s->read = s->write = s->window + n;
 }
+#endif  /*  0  */
 
 
 /* Returns true if inflate is currently at the end of a block generated
  * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
  * IN assertion: s != NULL
  */
+#if 0
 int zlib_inflate_blocks_sync_point(
 	inflate_blocks_statef *s
 )
 {
   return s->mode == LENS;
 }
+#endif  /*  0  */
diff --git a/lib/zlib_inflate/infblock.h b/lib/zlib_inflate/infblock.h
index f5221dd..ceee60b 100644
--- a/lib/zlib_inflate/infblock.h
+++ b/lib/zlib_inflate/infblock.h
@@ -33,12 +33,16 @@
     inflate_blocks_statef *,
     z_streamp);
 
+#if 0
 extern void zlib_inflate_set_dictionary (
     inflate_blocks_statef *s,
     const Byte *d,  /* dictionary */
     uInt  n);       /* dictionary length */
+#endif  /*  0  */
 
+#if 0
 extern int zlib_inflate_blocks_sync_point (
     inflate_blocks_statef *s);
+#endif  /*  0  */
 
 #endif /* _INFBLOCK_H */
diff --git a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c
index aa1b081..ef49738 100644
--- a/lib/zlib_inflate/inflate_syms.c
+++ b/lib/zlib_inflate/inflate_syms.c
@@ -15,8 +15,6 @@
 EXPORT_SYMBOL(zlib_inflateInit_);
 EXPORT_SYMBOL(zlib_inflateInit2_);
 EXPORT_SYMBOL(zlib_inflateEnd);
-EXPORT_SYMBOL(zlib_inflateSync);
 EXPORT_SYMBOL(zlib_inflateReset);
-EXPORT_SYMBOL(zlib_inflateSyncPoint);
 EXPORT_SYMBOL(zlib_inflateIncomp); 
 MODULE_LICENSE("GPL");
diff --git a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c
index e07bdb2..61411ff 100644
--- a/lib/zlib_inflate/inflate_sync.c
+++ b/lib/zlib_inflate/inflate_sync.c
@@ -7,6 +7,7 @@
 #include "infblock.h"
 #include "infutil.h"
 
+#if 0
 int zlib_inflateSync(
 	z_streamp z
 )
@@ -57,6 +58,7 @@
   z->state->mode = BLOCKS;
   return Z_OK;
 }
+#endif  /*  0  */
 
 
 /* Returns true if inflate is currently at the end of a block generated
@@ -66,6 +68,7 @@
  * decompressing, PPP checks that at the end of input packet, inflate is
  * waiting for these length bytes.
  */
+#if 0
 int zlib_inflateSyncPoint(
 	z_streamp z
 )
@@ -74,6 +77,7 @@
     return Z_STREAM_ERROR;
   return zlib_inflate_blocks_sync_point(z->state->blocks);
 }
+#endif  /*  0  */
 
 /*
  * This subroutine adds the data at next_in/avail_in to the output history
diff --git a/mm/filemap.c b/mm/filemap.c
index 5fca273..96de772 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2108,7 +2108,7 @@
 	if (err)
 		goto out;
 
-	inode_update_time(inode, 1);
+	file_update_time(file);
 
 	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
 	if (unlikely(file->f_flags & O_DIRECT)) {
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index e2b34e9..b960ac8 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -383,7 +383,7 @@
 	if (ret)
 		goto out_backing;
 
-	inode_update_time(inode, 1);
+	file_update_time(filp);
 
 	ret = __xip_file_write (filp, buf, count, pos, ppos);
 
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 158a9c4..f57cde7 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -480,13 +480,8 @@
 	BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
 
 	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
-		register int i;
-		for (i = 0; i < skb->len; i++) {
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				tty_flip_buffer_push(tty);
-
-			tty_insert_flip_char(tty, skb->data[i], 0);
-		}
+		tty_buffer_request_room(tty, skb->len);
+		tty_insert_flip_string(tty, skb->data, skb->len);
 		tty_flip_buffer_push(tty);
 	} else
 		tty->ldisc.receive_buf(tty, skb->data, NULL, skb->len);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index e1da81d..58adaf2 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -16,6 +16,7 @@
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
 #include <linux/wireless.h>
+#include <net/iw_handler.h>
 
 #define to_class_dev(obj) container_of(obj,struct class_device,kobj)
 #define to_net_dev(class) container_of(class, struct net_device, class_dev)
@@ -294,13 +295,19 @@
 					       char *))
 {
 	struct net_device *dev = to_net_dev(cd);
-	const struct iw_statistics *iw;
+	const struct iw_statistics *iw = NULL;
 	ssize_t ret = -EINVAL;
 	
 	read_lock(&dev_base_lock);
-	if (dev_isalive(dev) && dev->get_wireless_stats 
-	    && (iw = dev->get_wireless_stats(dev)) != NULL) 
-		ret = (*format)(iw, buf);
+	if (dev_isalive(dev)) {
+		if(dev->wireless_handlers &&
+		   dev->wireless_handlers->get_wireless_stats)
+			iw = dev->wireless_handlers->get_wireless_stats(dev);
+		else if (dev->get_wireless_stats)
+			iw = dev->get_wireless_stats(dev);
+		if (iw != NULL)
+			ret = (*format)(iw, buf);
+	}
 	read_unlock(&dev_base_lock);
 
 	return ret;
@@ -402,7 +409,8 @@
 		sysfs_remove_group(&class_dev->kobj, &netstat_group);
 
 #ifdef WIRELESS_EXT
-	if (net->get_wireless_stats)
+	if (net->get_wireless_stats || (net->wireless_handlers &&
+			net->wireless_handlers->get_wireless_stats))
 		sysfs_remove_group(&class_dev->kobj, &wireless_group);
 #endif
 	class_device_del(class_dev);
@@ -427,10 +435,12 @@
 		goto out_unreg; 
 
 #ifdef WIRELESS_EXT
-	if (net->get_wireless_stats &&
-	    (ret = sysfs_create_group(&class_dev->kobj, &wireless_group)))
-		goto out_cleanup; 
-
+	if (net->get_wireless_stats || (net->wireless_handlers &&
+			net->wireless_handlers->get_wireless_stats)) {
+		ret = sysfs_create_group(&class_dev->kobj, &wireless_group);
+		if (ret)
+			goto out_cleanup;
+	}
 	return 0;
 out_cleanup:
 	if (net->get_stats)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5530ac8..a44da8b 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -268,7 +268,8 @@
 		clnt->cl_oneshot = 0;
 		clnt->cl_dead = 0;
 		rpc_killall_tasks(clnt);
-		sleep_on_timeout(&destroy_wait, 1*HZ);
+		wait_event_timeout(destroy_wait,
+			atomic_read(&clnt->cl_users) > 0, 1*HZ);
 	}
 
 	if (atomic_read(&clnt->cl_users) < 0) {
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index db3c708..0168d6c 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -3,6 +3,7 @@
 
 # Convinient variables
 comma   := ,
+squote  := '
 empty   :=
 space   := $(empty) $(empty)
 
@@ -12,6 +13,10 @@
 depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
 
 ###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+###
 # filechk is used to check if the content of a generated file is updated.
 # Sample usage:
 # define filechk_sample
@@ -47,7 +52,7 @@
 
 # If quiet is set, only print short version of command
 cmd = @$(if $($(quiet)cmd_$(1)),\
-      echo '  $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
+      echo '  $(call escsq,$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
 
 # Add $(obj)/ for paths that is not absolute
 objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
@@ -68,7 +73,7 @@
 
 # echo command. Short version is $(quiet) equals quiet, otherwise full command
 echo-cmd = $(if $($(quiet)cmd_$(1)), \
-	echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';)
+	echo '  $(call escsq,$($(quiet)cmd_$(1)))';)
 
 # function to only execute the passed command if necessary
 # >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
@@ -78,7 +83,7 @@
 	@set -e; \
 	$(echo-cmd) \
 	$(cmd_$(1)); \
-	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
+	echo 'cmd_$@ := $(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
 
 # execute the command and also postprocess generated .d dependencies
 # file
@@ -87,7 +92,7 @@
 	@set -e; \
 	$(echo-cmd) \
 	$(cmd_$(1)); \
-	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
 	rm -f $(depfile); \
 	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
 
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 506e3f3..c33e62b 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -179,10 +179,10 @@
 define rule_cc_o_c
 	$(if $($(quiet)cmd_checksrc),echo '  $($(quiet)cmd_checksrc)';)   \
 	$(cmd_checksrc)							  \
-	$(if $($(quiet)cmd_cc_o_c),echo '  $(subst ','\'',$($(quiet)cmd_cc_o_c))';)  \
+	$(if $($(quiet)cmd_cc_o_c),echo '  $(call escsq,$($(quiet)cmd_cc_o_c))';)  \
 	$(cmd_cc_o_c);							  \
 	$(cmd_modversions)						  \
-	scripts/basic/fixdep $(depfile) $@ '$(subst ','\'',$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp;  \
+	scripts/basic/fixdep $(depfile) $@ '$(call escsq,$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp;  \
 	rm -f $(depfile);						  \
 	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
 endef
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile
index a45a13f..8f41d9a 100644
--- a/scripts/kconfig/lxdialog/Makefile
+++ b/scripts/kconfig/lxdialog/Makefile
@@ -1,42 +1,18 @@
-HOST_EXTRACFLAGS := -DLOCALE 
-ifeq ($(shell uname),SunOS)
-HOST_LOADLIBES   := -lcurses
-else
-HOST_LOADLIBES   := -lncurses
-endif
+# Makefile to build lxdialog package
+#
 
-ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
-        HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
-else
-ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
-        HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
-else
-ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
-        HOST_EXTRACFLAGS += -DCURSES_LOC="<ncurses.h>"
-else
-	HOST_EXTRACFLAGS += -DCURSES_LOC="<curses.h>"
-endif
-endif
-endif
+check-lxdialog   := $(srctree)/$(src)/check-lxdialog.sh
+HOST_EXTRACFLAGS := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
+HOST_LOADLIBES   := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags)
+ 
+HOST_EXTRACFLAGS += -DLOCALE 
+
+.PHONY: dochecklxdialog
+$(obj)/dochecklxdialog:
+	$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
 
 hostprogs-y	:= lxdialog
-always		:= ncurses $(hostprogs-y)
+always		:= $(hostprogs-y) dochecklxdialog
 
 lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
 		 util.o lxdialog.o msgbox.o
-
-.PHONY: $(obj)/ncurses
-$(obj)/ncurses:
-	@echo "main() {}" > lxtemp.c
-	@if $(HOSTCC) lxtemp.c  $(HOST_LOADLIBES); then \
-		rm -f lxtemp.c a.out; \
-	else \
-		rm -f lxtemp.c; \
-		echo -e "\007" ;\
-		echo ">> Unable to find the Ncurses libraries." ;\
-		echo ">>" ;\
-		echo ">> You must install ncurses-devel in order" ;\
-		echo ">> to use 'make menuconfig'" ;\
-		echo ;\
-		exit 1 ;\
-	fi
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
new file mode 100644
index 0000000..a3c141b
--- /dev/null
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# Check ncurses compatibility
+
+# What library to link
+ldflags()
+{
+	if [ `uname` == SunOS ]; then
+		echo '-lcurses'
+	else
+		echo '-lncurses'
+	fi
+}
+
+# Where is ncurses.h?
+ccflags()
+{
+	if [ -f /usr/include/ncurses/ncurses.h ]; then
+		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
+	elif [ -f /usr/include/ncurses/curses.h ]; then
+		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+	elif [ -f /usr/include/ncurses.h ]; then
+		echo '-DCURSES_LOC="<ncurses.h>"'
+	else
+		echo '-DCURSES_LOC="<curses.h>"'
+	fi
+}
+
+compiler=""
+# Check if we can link to ncurses
+check() {
+	echo "main() {}" | $compiler -xc -
+	if [ $? != 0 ]; then
+		echo " *** Unable to find the ncurses libraries."          1>&2
+		echo " *** make menuconfig require the ncurses libraries"  1>&2
+		echo " *** "                                               1>&2
+		echo " *** Install ncurses (ncurses-devel) and try again"  1>&2
+		echo " *** "                                               1>&2
+		exit 1
+	fi
+}
+
+usage() {
+	printf "Usage: $0 [-check compiler options|-header|-library]\n"
+}
+
+if [ $# == 0 ]; then
+	usage
+	exit 1
+fi
+
+case "$1" in
+	"-check")
+		shift
+		compiler="$@"
+		check
+		;;
+	"-ccflags")
+		ccflags
+		;;
+	"-ldflags")
+		ldflags
+		;;
+	"*")
+		usage
+		exit 1
+		;;
+esac
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 2f45fd2..9fd5f5b 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1405,6 +1405,7 @@
     my $type;
     my $param;
 
+    # temporarily replace commas inside function pointer definition
     while ($args =~ /(\([^\),]+),/) {
         $args =~ s/(\([^\),]+),/$1#/g;
     }
@@ -1465,11 +1466,10 @@
 	my $param_name = $param;
 	$param_name =~ s/\[.*//;
 
-	if ($type eq "" && $param eq "...")
+	if ($type eq "" && $param =~ /\.\.\.$/)
 	{
 	    $type="";
-	    $param="...";
-	    $parameterdescs{"..."} = "variable arguments";
+	    $parameterdescs{$param} = "variable arguments";
 	}
 	elsif ($type eq "" && ($param eq "" or $param eq "void"))
 	{
@@ -1477,7 +1477,11 @@
 	    $param="void";
 	    $parameterdescs{void} = "no arguments";
 	}
-	if (defined $type && $type && !defined $parameterdescs{$param_name}) {
+	# warn if parameter has no description
+	# (but ignore ones starting with # as these are no parameters
+	# but inline preprocessor statements
+	if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
+
 	    $parameterdescs{$param_name} = $undescribed;
 
 	    if (($type eq 'function') || ($type eq 'enum')) {
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e0eedff..be97caf 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -417,7 +417,7 @@
 		do_input(alias, id->sndbit, 0, SND_MAX);
 	sprintf(alias + strlen(alias), "f*");
 	if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
-		do_input(alias, id->ffbit, 0, SND_MAX);
+		do_input(alias, id->ffbit, 0, FF_MAX);
 	sprintf(alias + strlen(alias), "w*");
 	if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
 		do_input(alias, id->swbit, 0, SW_MAX);
diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl
index c2d5414..4ee6ab2 100644
--- a/scripts/reference_discarded.pl
+++ b/scripts/reference_discarded.pl
@@ -71,6 +71,11 @@
 # printf("ignoring %d conglomerate(s)\n", $ignore);
 
 # printf("Scanning objects\n");
+
+# Keith Ownes <kaos@sgi.com> commented:
+# For our future {in}sanity, add a comment that this is the ppc .opd
+# section, not the ia64 .opd section.
+# ia64 .opd should not point to discarded sections.
 $errorcount = 0;
 foreach $object (keys(%object)) {
 	my $from;
@@ -88,6 +93,7 @@
 		    ($from !~ /\.text\.exit$/ &&
 		     $from !~ /\.exit\.text$/ &&
 		     $from !~ /\.data\.exit$/ &&
+		     $from !~ /\.opd$/ &&
 		     $from !~ /\.exit\.data$/ &&
 		     $from !~ /\.altinstructions$/ &&
 		     $from !~ /\.pdr$/ &&
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index f54dac8..9a23825 100644
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -17,6 +17,6 @@
 
 	# Are there uncommitted changes?
 	if git diff-files | read dummy; then
-		printf '%s' -git_dirty
+		printf '%s' -dirty
 	fi
 fi
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 44eb4d7..8a76492 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1712,11 +1712,11 @@
 		goto out;
 	}
 
-	*names = (char**)kcalloc(*len, sizeof(char*), GFP_ATOMIC);
+       *names = kcalloc(*len, sizeof(char*), GFP_ATOMIC);
 	if (!*names)
 		goto err;
 
-	*values = (int*)kcalloc(*len, sizeof(int), GFP_ATOMIC);
+       *values = kcalloc(*len, sizeof(int), GFP_ATOMIC);
 	if (!*values)
 		goto err;
 
@@ -1724,7 +1724,7 @@
 		size_t name_len;
 		(*values)[i] = policydb.bool_val_to_struct[i]->state;
 		name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
-		(*names)[i] = (char*)kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
+               (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
 		if (!(*names)[i])
 			goto err;
 		strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 202c7cf..f36ede8 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -385,7 +385,7 @@
 
 static int __init alsa_card_cs5535audio_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cs5535audio_exit(void)