Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6:
  JFS: Remove incorrect kgdb define
  JFS: call io_schedule() instead of schedule() to avoid deadlock
  JFS: Add lockdep annotations
  JFS: Avoid BUG() on a damaged file system
diff --git a/CREDITS b/CREDITS
index 75c5ce8..ae08e4c 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3279,7 +3279,7 @@
 S: Spain
 
 N: Linus Torvalds
-E: torvalds@osdl.org
+E: torvalds@linux-foundation.org
 D: Original kernel hacker
 S: 12725 SW Millikan Way, Suite 400
 S: Beaverton, Oregon 97005
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 07a6355..e2e24b4 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -883,7 +883,7 @@
   </chapter>
 
   <chapter id="ataExceptions">
-     <title>ATA errors &amp; exceptions</title>
+     <title>ATA errors and exceptions</title>
 
   <para>
   This chapter tries to identify what error/exception conditions exist
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 2270efa..bfbb271 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -72,3 +72,7 @@
 
     If the new code is substantial, addition of subsystem-specific fault
     injection might be appropriate.
+
+22: Newly-added code has been compiled with `gcc -W'.  This will generate
+    lots of noise, but is good for finding bugs like "warning: comparison
+    between signed and unsigned".
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 302d148..b0d0043 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -134,9 +134,9 @@
 
 
 Linus Torvalds is the final arbiter of all changes accepted into the
-Linux kernel.  His e-mail address is <torvalds@osdl.org>.  He gets
-a lot of e-mail, so typically you should do your best to -avoid- sending
-him e-mail.
+Linux kernel.  His e-mail address is <torvalds@linux-foundation.org>. 
+He gets a lot of e-mail, so typically you should do your best to -avoid-
+sending him e-mail. 
 
 Patches which are bug fixes, are "obvious" changes, or similarly
 require little discussion should be sent or CC'd to Linus.  Patches
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index f2024df..0ba6af0 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -273,3 +273,55 @@
 Who:	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
 
 ---------------------------
+
+What:	ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
+When:	2.6.21
+Why:	hotkey.c was an attempt to consolidate multiple drivers that use
+	ACPI to implement hotkeys.  However, hotkeys are not documented
+	in the ACPI specification, so the drivers used undocumented
+	vendor-specific hooks and turned out to be more different than
+	the same.
+
+	Further, the keys and the features supplied by each platform
+	are different, so there will always be a need for
+	platform-specific drivers.
+
+	So the new plan is to delete hotkey.c and instead, work on the
+	platform specific drivers to try to make them look the same
+	to the user when they supply the same features.
+
+	hotkey.c has always depended on CONFIG_EXPERIMENTAL
+
+Who:	Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What:	/sys/firmware/acpi/namespace
+When:	2.6.21
+Why:	The ACPI namespace is effectively the symbol list for
+	the BIOS.  The device names are completely arbitrary
+	and have no place being exposed to user-space.
+
+	For those interested in the BIOS ACPI namespace,
+	the BIOS can be extracted and disassembled with acpidump
+	and iasl as documented in the pmtools package here:
+	http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils
+
+Who:	Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What:	/proc/acpi/button
+When:	August 2007
+Why:	/proc/acpi/button has been replaced by events to the input layer
+	since 2.6.20.
+Who:	Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What:	JFFS (version 1)
+When:	2.6.21
+Why:	Unmaintained for years, superceded by JFFS2 for years.
+Who:	Jeff Garzik <jeff@garzik.org>
+
+---------------------------
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index 43b89c2..4d075a4 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -73,8 +73,22 @@
 RESOURCES
 =========
 
-The Linux version of the 9p server is now maintained under the npfs project
-on sourceforge (http://sourceforge.net/projects/npfs).
+Our current recommendation is to use Inferno (http://www.vitanuova.com/inferno)
+as the 9p server.  You can start a 9p server under Inferno by issuing the
+following command:
+   ; styxlisten -A tcp!*!564 export '#U*'
+
+The -A specifies an unauthenticated export.  The 564 is the port # (you may
+have to choose a higher port number if running as a normal user).  The '#U*'
+specifies exporting the root of the Linux name space.  You may specify a
+subset of the namespace by extending the path: '#U*'/tmp would just export
+/tmp.  For more information, see the Inferno manual pages covering styxlisten
+and export.
+
+A Linux version of the 9p server is now maintained under the npfs project
+on sourceforge (http://sourceforge.net/projects/npfs).  There is also a
+more stable single-threaded version of the server (named spfs) available from
+the same CVS repository.
 
 There are user and developer mailing lists available through the v9fs project
 on sourceforge (http://sourceforge.net/projects/v9fs).
@@ -96,5 +110,5 @@
 
 The 2.6 kernel support is working on PPC and x86.
 
-PLEASE USE THE SOURCEFORGE BUG-TRACKER TO REPORT PROBLEMS.
+PLEASE USE THE KERNEL BUGZILLA TO REPORT PROBLEMS. (http://bugzilla.kernel.org)
 
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 790ef6f..28bfea7 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -171,6 +171,7 @@
 	int (*releasepage) (struct page *, int);
 	int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs);
+	int (*launder_page) (struct page *);
 
 locking rules:
 	All except set_page_dirty may block
@@ -188,6 +189,7 @@
 invalidatepage:		no	yes
 releasepage:		no	yes
 direct_IO:		no
+launder_page:		no	yes
 
 	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
@@ -281,6 +283,12 @@
 indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
 the kernel assumes that the fs has no private interest in the buffers.
 
+	->launder_page() may be called prior to releasing a page if
+it is still found to be dirty. It returns zero if the page was successfully
+cleaned, or an error value if not. Note that in order to prevent the page
+getting mapped back in and redirtied, it needs to be kept locked
+across the entire operation.
+
 	Note: currently almost all instances of address_space methods are
 using BKL for internal serialization and that's one of the worst sources
 of contention. Normally they are calling library functions (in fs/buffer.c)
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index 13ba649..8177906 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -457,6 +457,8 @@
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.1.28:
+	- Fix a deadlock.
 2.1.27:
 	- Implement page migration support so the kernel can move memory used
 	  by NTFS files and directories around for management purposes.
diff --git a/Documentation/hwmon/w83793 b/Documentation/hwmon/w83793
index 45e5408..51171a8 100644
--- a/Documentation/hwmon/w83793
+++ b/Documentation/hwmon/w83793
@@ -45,18 +45,14 @@
   temp5-6 have a 1 degree Celsiis resolution.
 
 * Temperature sensor types
-  Temp1-4 have 3 possible types. It can be read from (and written to)
+  Temp1-4 have 2 possible types. It can be read from (and written to)
   temp[1-4]_type.
-  - If the value of 0, the related temperature channel stops
-    monitoring.
   - If the value is 3, it starts monitoring using a remote termal diode
     (default).
-  - If the value is 5, it starts monitoring using the temperature sensor
-    in AMD CPU and get result by AMDSI.
   - If the value is 6, it starts monitoring using the temperature sensor
     in Intel CPU and get result by PECI.
   Temp5-6 can be connected to external thermistors (value of
-  temp[5-6]_type is 4). They can also be disabled (value is 0).
+  temp[5-6]_type is 4).
 
 * Alarm mechanism
   For voltage sensors, an alarm triggers if the measured value is below
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
index 9575de3..38fe1f0 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
@@ -2,7 +2,7 @@
 		     ----------------------------
 
 		    H. Peter Anvin <hpa@zytor.com>
-			Last update 2006-11-17
+			Last update 2007-01-26
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -186,6 +186,7 @@
 	7  GRuB
 	8  U-BOOT
 	9  Xen
+	A  Gujin
 
 	Please contact <hpa@zytor.com> if you need a bootloader ID
 	value assigned.
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 99f2d4d..0733068 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -17,7 +17,7 @@
 memory image to a dump file on the local disk, or across the network to
 a remote system.
 
-Kdump and kexec are currently supported on the x86, x86_64, and ppc64
+Kdump and kexec are currently supported on the x86, x86_64, ppc64 and ia64
 architectures.
 
 When the system kernel boots, it reserves a small section of memory for
@@ -54,59 +54,69 @@
 Setup and Installation
 ======================
 
-Install kexec-tools and the Kdump patch
----------------------------------------
+Install kexec-tools
+-------------------
 
 1) Login as the root user.
 
 2) Download the kexec-tools user-space package from the following URL:
 
-   http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
+http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools-testing.tar.gz
+
+This is a symlink to the latest version, which at the time of writing is
+20061214, the only release of kexec-tools-testing so far. As other versions
+are made released, the older onese will remain available at
+http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
+
+Note: Latest kexec-tools-testing git tree is available at
+
+git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools-testing.git
+or
+http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools-testing.git;a=summary
 
 3) Unpack the tarball with the tar command, as follows:
 
-   tar xvpzf kexec-tools-1.101.tar.gz
+   tar xvpzf kexec-tools-testing.tar.gz
 
-4) Download the latest consolidated Kdump patch from the following URL:
+4) Change to the kexec-tools directory, as follows:
 
-   http://lse.sourceforge.net/kdump/
+   cd kexec-tools-testing-VERSION
 
-   (This location is being used until all the user-space Kdump patches
-   are integrated with the kexec-tools package.)
-
-5) Change to the kexec-tools-1.101 directory, as follows:
-
-   cd kexec-tools-1.101
-
-6) Apply the consolidated patch to the kexec-tools-1.101 source tree
-   with the patch command, as follows. (Modify the path to the downloaded
-   patch as necessary.)
-
-   patch -p1 < /path-to-kdump-patch/kexec-tools-1.101-kdump.patch
-
-7) Configure the package, as follows:
+5) Configure the package, as follows:
 
    ./configure
 
-8) Compile the package, as follows:
+6) Compile the package, as follows:
 
    make
 
-9) Install the package, as follows:
+7) Install the package, as follows:
 
    make install
 
 
-Download and build the system and dump-capture kernels
-------------------------------------------------------
+Build the system and dump-capture kernels
+-----------------------------------------
+There are two possible methods of using Kdump.
 
-Download the mainline (vanilla) kernel source code (2.6.13-rc1 or newer)
-from http://www.kernel.org. Two kernels must be built: a system kernel
-and a dump-capture kernel. Use the following steps to configure these
-kernels with the necessary kexec and Kdump features:
+1) Build a separate custom dump-capture kernel for capturing the
+   kernel core dump.
 
-System kernel
--------------
+2) Or use the system kernel binary itself as dump-capture kernel and there is
+   no need to build a separate dump-capture kernel. This is possible
+   only with the architecutres which support a relocatable kernel. As
+   of today i386 and ia64 architectures support relocatable kernel.
+
+Building a relocatable kernel is advantageous from the point of view that
+one does not have to build a second kernel for capturing the dump. But
+at the same time one might want to build a custom dump capture kernel
+suitable to his needs.
+
+Following are the configuration setting required for system and
+dump-capture kernels for enabling kdump support.
+
+System kernel config options
+----------------------------
 
 1) Enable "kexec system call" in "Processor type and features."
 
@@ -132,89 +142,183 @@
    analysis tools require a vmlinux with debug symbols in order to read
    and analyze a dump file.
 
-4) Make and install the kernel and its modules. Update the boot loader
-   (such as grub, yaboot, or lilo) configuration files as necessary.
+Dump-capture kernel config options (Arch Independent)
+-----------------------------------------------------
 
-5) Boot the system kernel with the boot parameter "crashkernel=Y@X",
-   where Y specifies how much memory to reserve for the dump-capture kernel
-   and X specifies the beginning of this reserved memory. For example,
-   "crashkernel=64M@16M" tells the system kernel to reserve 64 MB of memory
-   starting at physical address 0x01000000 for the dump-capture kernel.
+1) Enable "kernel crash dumps" support under "Processor type and
+   features":
 
-   On x86 and x86_64, use "crashkernel=64M@16M".
+   CONFIG_CRASH_DUMP=y
 
-   On ppc64, use "crashkernel=128M@32M".
+2) Enable "/proc/vmcore support" under "Filesystems" -> "Pseudo filesystems".
 
+   CONFIG_PROC_VMCORE=y
+   (CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.)
 
-The dump-capture kernel
------------------------
-
-1) Under "General setup," append "-kdump" to the current string in
-   "Local version."
-
-2) On x86, enable high memory support under "Processor type and
+Dump-capture kernel config options (Arch Dependent, i386)
+--------------------------------------------------------
+1) On x86, enable high memory support under "Processor type and
    features":
 
    CONFIG_HIGHMEM64G=y
    or
    CONFIG_HIGHMEM4G
 
-3) On x86 and x86_64, disable symmetric multi-processing support
+2) On x86 and x86_64, disable symmetric multi-processing support
    under "Processor type and features":
 
    CONFIG_SMP=n
+
    (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
    when loading the dump-capture kernel, see section "Load the Dump-capture
    Kernel".)
 
-4) On ppc64, disable NUMA support and enable EMBEDDED support:
+3) If one wants to build and use a relocatable kernel,
+   Enable "Build a relocatable kernel" support under "Processor type and
+   features"
 
-   CONFIG_NUMA=n
-   CONFIG_EMBEDDED=y
-   CONFIG_EEH=N for the dump-capture kernel
+   CONFIG_RELOCATABLE=y
 
-5) Enable "kernel crash dumps" support under "Processor type and
-   features":
+4) Use a suitable value for "Physical address where the kernel is
+   loaded" (under "Processor type and features"). This only appears when
+   "kernel crash dumps" is enabled. A suitable value depends upon
+   whether kernel is relocatable or not.
 
-   CONFIG_CRASH_DUMP=y
+   If you are using a relocatable kernel use CONFIG_PHYSICAL_START=0x100000
+   This will compile the kernel for physical address 1MB, but given the fact
+   kernel is relocatable, it can be run from any physical address hence
+   kexec boot loader will load it in memory region reserved for dump-capture
+   kernel.
 
-6) Use a suitable value for "Physical address where the kernel is
+   Otherwise it should be the start of memory region reserved for
+   second kernel using boot parameter "crashkernel=Y@X". Here X is
+   start of memory region reserved for dump-capture kernel.
+   Generally X is 16MB (0x1000000). So you can set
+   CONFIG_PHYSICAL_START=0x1000000
+
+5) Make and install the kernel and its modules. DO NOT add this kernel
+   to the boot loader configuration files.
+
+Dump-capture kernel config options (Arch Dependent, x86_64)
+----------------------------------------------------------
+1) On x86 and x86_64, disable symmetric multi-processing support
+   under "Processor type and features":
+
+   CONFIG_SMP=n
+
+   (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
+   when loading the dump-capture kernel, see section "Load the Dump-capture
+   Kernel".)
+
+2) Use a suitable value for "Physical address where the kernel is
    loaded" (under "Processor type and features"). This only appears when
    "kernel crash dumps" is enabled. By default this value is 0x1000000
    (16MB). It should be the same as X in the "crashkernel=Y@X" boot
-   parameter discussed above.
+   parameter.
 
-   On x86 and x86_64, use "CONFIG_PHYSICAL_START=0x1000000".
+   For x86_64, normally "CONFIG_PHYSICAL_START=0x1000000".
 
-   On ppc64 the value is automatically set at 32MB when
-   CONFIG_CRASH_DUMP is set.
-
-6) Optionally enable "/proc/vmcore support" under "Filesystems" ->
-   "Pseudo filesystems".
-
-   CONFIG_PROC_VMCORE=y
-   (CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.)
-
-7) Make and install the kernel and its modules. DO NOT add this kernel
+3) Make and install the kernel and its modules. DO NOT add this kernel
    to the boot loader configuration files.
 
+Dump-capture kernel config options (Arch Dependent, ppc64)
+----------------------------------------------------------
+
+-  Make and install the kernel and its modules. DO NOT add this kernel
+   to the boot loader configuration files.
+
+Dump-capture kernel config options (Arch Dependent, ia64)
+----------------------------------------------------------
+
+- No specific options are required to create a dump-capture kernel
+  for ia64, other than those specified in the arch idependent section
+  above. This means that it is possible to use the system kernel
+  as a dump-capture kernel if desired.
+
+  The crashkernel region can be automatically placed by the system
+  kernel at run time. This is done by specifying the base address as 0,
+  or omitting it all together.
+
+  crashkernel=256M@0
+  or
+  crashkernel=256M
+
+  If the start address is specified, note that the start address of the
+  kernel will be aligned to 64Mb, so if the start address is not then
+  any space below the alignment point will be wasted.
+
+
+Boot into System Kernel
+=======================
+
+1) Make and install the kernel and its modules. Update the boot loader
+   (such as grub, yaboot, or lilo) configuration files as necessary.
+
+2) Boot the system kernel with the boot parameter "crashkernel=Y@X",
+   where Y specifies how much memory to reserve for the dump-capture kernel
+   and X specifies the beginning of this reserved memory. For example,
+   "crashkernel=64M@16M" tells the system kernel to reserve 64 MB of memory
+   starting at physical address 0x01000000 (16MB) for the dump-capture kernel.
+
+   On x86 and x86_64, use "crashkernel=64M@16M".
+
+   On ppc64, use "crashkernel=128M@32M".
+
+   On ia64, 256M@256M is a generous value that typically works.
+   The region may be automatically placed on ia64, see the
+   dump-capture kernel config option notes above.
 
 Load the Dump-capture Kernel
 ============================
 
-After booting to the system kernel, load the dump-capture kernel using
-the following command:
+After booting to the system kernel, dump-capture kernel needs to be
+loaded.
 
-   kexec -p <dump-capture-kernel> \
+Based on the architecture and type of image (relocatable or not), one
+can choose to load the uncompressed vmlinux or compressed bzImage/vmlinuz
+of dump-capture kernel. Following is the summary.
+
+For i386:
+	- Use vmlinux if kernel is not relocatable.
+	- Use bzImage/vmlinuz if kernel is relocatable.
+For x86_64:
+	- Use vmlinux
+For ppc64:
+	- Use vmlinux
+For ia64:
+	- Use vmlinux or vmlinuz.gz
+
+
+If you are using a uncompressed vmlinux image then use following command
+to load dump-capture kernel.
+
+   kexec -p <dump-capture-kernel-vmlinux-image> \
    --initrd=<initrd-for-dump-capture-kernel> --args-linux \
-   --append="root=<root-dev> init 1 irqpoll"
+   --append="root=<root-dev> <arch-specific-options>"
+
+If you are using a compressed bzImage/vmlinuz, then use following command
+to load dump-capture kernel.
+
+   kexec -p <dump-capture-kernel-bzImage> \
+   --initrd=<initrd-for-dump-capture-kernel> \
+   --append="root=<root-dev> <arch-specific-options>"
+
+Please note, that --args-linux does not need to be specified for ia64.
+It is planned to make this a no-op on that architecture, but for now
+it should be omitted
+
+Following are the arch specific command line options to be used while
+loading dump-capture kernel.
+
+For i386, x86_64 and ia64:
+	"init 1 irqpoll maxcpus=1"
+
+For ppc64:
+	"init 1 maxcpus=1 noirqdistrib"
 
 
 Notes on loading the dump-capture kernel:
 
-* <dump-capture-kernel> must be a vmlinux image (that is, an
-  uncompressed ELF image). bzImage does not work at this time.
-
 * By default, the ELF headers are stored in ELF64 format to support
   systems with more than 4GB memory. The --elf32-core-headers option can
   be used to force the generation of ELF32 headers. This is necessary
@@ -231,6 +335,9 @@
 * "init 1" boots the dump-capture kernel into single-user mode without
   networking. If you want networking, use "init 3."
 
+* We generally don' have to bring up a SMP kernel just to capture the
+  dump. Hence generally it is useful either to build a UP dump-capture
+  kernel or specify maxcpus=1 option while loading dump-capture kernel.
 
 Kernel Panic
 ============
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 2b395e4..fd5028e 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -1,142 +1,231 @@
-			 How To Write Linux PCI Drivers
 
-		   by Martin Mares <mj@ucw.cz> on 07-Feb-2000
+			How To Write Linux PCI Drivers
+
+		by Martin Mares <mj@ucw.cz> on 07-Feb-2000
+	updated by Grant Grundler <grundler@parisc-linux.org> on 23-Dec-2006
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The world of PCI is vast and it's full of (mostly unpleasant) surprises.
-Different PCI devices have different requirements and different bugs --
-because of this, the PCI support layer in Linux kernel is not as trivial
-as one would wish. This short pamphlet tries to help all potential driver
-authors find their way through the deep forests of PCI handling.
+The world of PCI is vast and full of (mostly unpleasant) surprises.
+Since each CPU architecture implements different chip-sets and PCI devices
+have different requirements (erm, "features"), the result is the PCI support
+in the Linux kernel is not as trivial as one would wish. This short paper
+tries to introduce all potential driver authors to Linux APIs for
+PCI device drivers.
+
+A more complete resource is the third edition of "Linux Device Drivers"
+by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
+LDD3 is available for free (under Creative Commons License) from:
+
+	http://lwn.net/Kernel/LDD3/
+
+However, keep in mind that all documents are subject to "bit rot".
+Refer to the source code if things are not working as described here.
+
+Please send questions/comments/patches about Linux PCI API to the
+"Linux PCI" <linux-pci@atrey.karlin.mff.cuni.cz> mailing list.
+
 
 
 0. Structure of PCI drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There exist two kinds of PCI drivers: new-style ones (which leave most of
-probing for devices to the PCI layer and support online insertion and removal
-of devices [thus supporting PCI, hot-pluggable PCI and CardBus in a single
-driver]) and old-style ones which just do all the probing themselves. Unless
-you have a very good reason to do so, please don't use the old way of probing
-in any new code. After the driver finds the devices it wishes to operate
-on (either the old or the new way), it needs to perform the following steps:
+PCI drivers "discover" PCI devices in a system via pci_register_driver().
+Actually, it's the other way around. When the PCI generic code discovers
+a new device, the driver with a matching "description" will be notified.
+Details on this below.
+
+pci_register_driver() leaves most of the probing for devices to
+the PCI layer and supports online insertion/removal of devices [thus
+supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
+pci_register_driver() call requires passing in a table of function
+pointers and thus dictates the high level structure of a driver.
+
+Once the driver knows about a PCI device and takes ownership, the
+driver generally needs to perform the following initialization:
 
 	Enable the device
-	Access device configuration space
-	Discover resources (addresses and IRQ numbers) provided by the device
-	Allocate these resources
-	Communicate with the device
+	Request MMIO/IOP resources
+	Set the DMA mask size (for both coherent and streaming DMA)
+	Allocate and initialize shared control data (pci_allocate_coherent())
+	Access device configuration space (if needed)
+	Register IRQ handler (request_irq())
+	Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+	Enable DMA/processing engines
+
+When done using the device, and perhaps the module needs to be unloaded,
+the driver needs to take the follow steps:
+	Disable the device from generating IRQs
+	Release the IRQ (free_irq())
+	Stop all DMA activity
+	Release DMA buffers (both streaming and coherent)
+	Unregister from other subsystems (e.g. scsi or netdev)
+	Release MMIO/IOP resources
 	Disable the device
 
-Most of these topics are covered by the following sections, for the rest
-look at <linux/pci.h>, it's hopefully well commented.
+Most of these topics are covered in the following sections.
+For the rest look at LDD3 or <linux/pci.h> .
 
 If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
-the functions described below are defined as inline functions either completely
-empty or just returning an appropriate error codes to avoid lots of ifdefs
-in the drivers.
+the PCI functions described below are defined as inline functions either
+completely empty or just returning an appropriate error codes to avoid
+lots of ifdefs in the drivers.
 
 
-1. New-style drivers
-~~~~~~~~~~~~~~~~~~~~
-The new-style drivers just call pci_register_driver during their initialization
-with a pointer to a structure describing the driver (struct pci_driver) which
-contains:
 
-	name		Name of the driver
+1. pci_register_driver() call
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+PCI device drivers call pci_register_driver() during their
+initialization with a pointer to a structure describing the driver
+(struct pci_driver):
+
+	field name	Description
+	----------	------------------------------------------------------
 	id_table	Pointer to table of device ID's the driver is
 			interested in.  Most drivers should export this
 			table using MODULE_DEVICE_TABLE(pci,...).
-	probe		Pointer to a probing function which gets called (during
-			execution of pci_register_driver for already existing
-			devices or later if a new device gets inserted) for all
-			PCI devices which match the ID table and are not handled
-			by the other drivers yet. This function gets passed a
-			pointer to the pci_dev structure representing the device
-			and also which entry in the ID table did the device
-			match. It returns zero when the driver has accepted the
-			device or an error code (negative number) otherwise.
-			This function always gets called from process context,
-			so it can sleep.
-	remove		Pointer to a function which gets called whenever a
-			device being handled by this driver is removed (either
-			during deregistration of the driver or when it's
-			manually pulled out of a hot-pluggable slot). This
-			function always gets called from process context, so it
-			can sleep.
-	save_state	Save a device's state before it's suspend.
+
+	probe		This probing function gets called (during execution
+			of pci_register_driver() for already existing
+			devices or later if a new device gets inserted) for
+			all PCI devices which match the ID table and are not
+			"owned" by the other drivers yet. This function gets
+			passed a "struct pci_dev *" for each device whose
+			entry in the ID table matches the device. The probe
+			function returns zero when the driver chooses to
+			take "ownership" of the device or an error code
+			(negative number) otherwise.
+			The probe function always gets called from process
+			context, so it can sleep.
+
+	remove		The remove() function gets called whenever a device
+			being handled by this driver is removed (either during
+			deregistration of the driver or when it's manually
+			pulled out of a hot-pluggable slot).
+			The remove function always gets called from process
+			context, so it can sleep.
+
 	suspend		Put device into low power state.
+	suspend_late	Put device into low power state.
+
+	resume_early	Wake device from low power state.
 	resume		Wake device from low power state.
+
+		(Please see Documentation/power/pci.txt for descriptions
+		of PCI Power Management and the related functions.)
+
 	enable_wake	Enable device to generate wake events from a low power
 			state.
 
-			(Please see Documentation/power/pci.txt for descriptions
-			of PCI Power Management and the related functions)
+	shutdown	Hook into reboot_notifier_list (kernel/sys.c).
+			Intended to stop any idling DMA operations.
+			Useful for enabling wake-on-lan (NIC) or changing
+			the power state of a device before reboot.
+			e.g. drivers/net/e100.c.
 
-The ID table is an array of struct pci_device_id ending with a all-zero entry.
-Each entry consists of:
+	err_handler	See Documentation/pci-error-recovery.txt
 
-	vendor, device	Vendor and device ID to match (or PCI_ANY_ID)
+	multithread_probe	Enable multi-threaded probe/scan. Driver must
+			provide its own locking/syncronization for init
+			operations if this is enabled.
+
+
+The ID table is an array of struct pci_device_id entries ending with an
+all-zero entry.  Each entry consists of:
+
+	vendor,device	Vendor and device ID to match (or PCI_ANY_ID)
+
 	subvendor,	Subsystem vendor and device ID to match (or PCI_ANY_ID)
-	subdevice
-	class,		Device class to match. The class_mask tells which bits
-	class_mask	of the class are honored during the comparison.
+	subdevice,
+
+	class		Device class, subclass, and "interface" to match.
+			See Appendix D of the PCI Local Bus Spec or
+			include/linux/pci_ids.h for a full list of classes.
+			Most drivers do not need to specify class/class_mask
+			as vendor/device is normally sufficient.
+
+	class_mask	limit which sub-fields of the class field are compared.
+			See drivers/scsi/sym53c8xx_2/ for example of usage.
+
 	driver_data	Data private to the driver.
+			Most drivers don't need to use driver_data field.
+			Best practice is to use driver_data as an index
+			into a static list of equivalent device types,
+			instead of using it as a pointer.
 
-Most drivers don't need to use the driver_data field.  Best practice
-for use of driver_data is to use it as an index into a static list of
-equivalent device types, not to use it as a pointer.
 
-Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}
-to have probe() called for every PCI device known to the system.
+Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
+a pci_device_id table.
 
-New PCI IDs may be added to a device driver at runtime by writing
-to the file /sys/bus/pci/drivers/{driver}/new_id.  When added, the
-driver will probe for all devices it can support.
+New PCI IDs may be added to a device driver pci_ids table at runtime
+as shown below:
 
 echo "vendor device subvendor subdevice class class_mask driver_data" > \
- /sys/bus/pci/drivers/{driver}/new_id
-where all fields are passed in as hexadecimal values (no leading 0x).
-Users need pass only as many fields as necessary; vendor, device,
-subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF),
-class and classmask fields default to 0, and driver_data defaults to
-0UL.  Device drivers must initialize use_driver_data in the dynids struct
-in their pci_driver struct prior to calling pci_register_driver in order
-for the driver_data field to get passed to the driver. Otherwise, only a
-0 is passed in that field.
+/sys/bus/pci/drivers/{driver}/new_id
+
+All fields are passed in as hexadecimal values (no leading 0x).
+Users need pass only as many fields as necessary:
+	o vendor, device, subvendor, and subdevice fields default
+	  to PCI_ANY_ID (FFFFFFFF),
+	o class and classmask fields default to 0
+	o driver_data defaults to 0UL.
+
+Once added, the driver probe routine will be invoked for any unclaimed
+PCI devices listed in its (newly updated) pci_ids list.
 
 When the driver exits, it just calls pci_unregister_driver() and the PCI layer
 automatically calls the remove hook for all devices handled by the driver.
 
+
+1.1 "Attributes" for driver functions/data
+
 Please mark the initialization and cleanup functions where appropriate
 (the corresponding macros are defined in <linux/init.h>):
 
 	__init		Initialization code. Thrown away after the driver
 			initializes.
 	__exit		Exit code. Ignored for non-modular drivers.
-	__devinit	Device initialization code. Identical to __init if
-			the kernel is not compiled with CONFIG_HOTPLUG, normal
-			function otherwise.
+
+
+	__devinit	Device initialization code.
+			Identical to __init if the kernel is not compiled
+			with CONFIG_HOTPLUG, normal function otherwise.
 	__devexit	The same for __exit.
 
-Tips:
-	The module_init()/module_exit() functions (and all initialization
-        functions called only from these) should be marked __init/exit.
-	The struct pci_driver shouldn't be marked with any of these tags.
-	The ID table array should be marked __devinitdata.
-	The probe() and remove() functions (and all initialization
-	functions called only from these) should be marked __devinit/exit.
-	If you are sure the driver is not a hotplug driver then use only 
-	__init/exit __initdata/exitdata.
+Tips on when/where to use the above attributes:
+	o The module_init()/module_exit() functions (and all
+	  initialization functions called _only_ from these)
+	  should be marked __init/__exit.
 
-        Pointers to functions marked as __devexit must be created using
-        __devexit_p(function_name).  That will generate the function
-        name or NULL if the __devexit function will be discarded.
+	o Do not mark the struct pci_driver.
+
+	o The ID table array should be marked __devinitdata.
+
+	o The probe() and remove() functions should be marked __devinit
+	  and __devexit respectively.  All initialization functions
+	  exclusively called by the probe() routine, can be marked __devinit.
+	  Ditto for remove() and __devexit.
+
+	o If mydriver_probe() is marked with __devinit(), then all address
+	  references to mydriver_probe must use __devexit_p(mydriver_probe)
+	  (in the struct pci_driver declaration for example).
+	  __devexit_p() will generate the function name _or_ NULL if the
+	  function will be discarded.  For an example, see drivers/net/tg3.c.
+
+	o Do NOT mark a function if you are not sure which mark to use.
+	  Better to not mark the function than mark the function wrong.
 
 
-2. How to find PCI devices manually (the old style)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-PCI drivers not using the pci_register_driver() interface search
-for PCI devices manually using the following constructs:
+
+2. How to find PCI devices manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+PCI drivers should have a really good reason for not using the
+pci_register_driver() interface to search for PCI devices.
+The main reason PCI devices are controlled by multiple drivers
+is because one PCI device implements several different HW services.
+E.g. combined serial/parallel port/floppy controller.
+
+A manual search may be performed using the following constructs:
 
 Searching by vendor and device ID:
 
@@ -150,87 +239,311 @@
 
 Searching by both vendor/device and subsystem vendor/device ID:
 
-	pci_get_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+	pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
 
-   You can use the constant PCI_ANY_ID as a wildcard replacement for
+You can use the constant PCI_ANY_ID as a wildcard replacement for
 VENDOR_ID or DEVICE_ID.  This allows searching for any device from a
 specific vendor, for example.
 
-   These functions are hotplug-safe. They increment the reference count on
+These functions are hotplug-safe. They increment the reference count on
 the pci_dev that they return. You must eventually (possibly at module unload)
 decrement the reference count on these devices by calling pci_dev_put().
 
 
-3. Enabling and disabling devices
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   Before you do anything with the device you've found, you need to enable
-it by calling pci_enable_device() which enables I/O and memory regions of
-the device, allocates an IRQ if necessary, assigns missing resources if
-needed and wakes up the device if it was in suspended state. Please note
-that this function can fail.
 
-   If you want to use the device in bus mastering mode, call pci_set_master()
-which enables the bus master bit in PCI_COMMAND register and also fixes
-the latency timer value if it's set to something bogus by the BIOS.
+3. Device Initialization Steps
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-   If you want to use the PCI Memory-Write-Invalidate transaction,
+As noted in the introduction, most PCI drivers need the following steps
+for device initialization:
+
+	Enable the device
+	Request MMIO/IOP resources
+	Set the DMA mask size (for both coherent and streaming DMA)
+	Allocate and initialize shared control data (pci_allocate_coherent())
+	Access device configuration space (if needed)
+	Register IRQ handler (request_irq())
+	Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+	Enable DMA/processing engines.
+
+The driver can access PCI config space registers at any time.
+(Well, almost. When running BIST, config space can go away...but
+that will just result in a PCI Bus Master Abort and config reads
+will return garbage).
+
+
+3.1 Enable the PCI device
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Before touching any device registers, the driver needs to enable
+the PCI device by calling pci_enable_device(). This will:
+	o wake up the device if it was in suspended state,
+	o allocate I/O and memory regions of the device (if BIOS did not),
+	o allocate an IRQ (if BIOS did not).
+
+NOTE: pci_enable_device() can fail! Check the return value.
+NOTE2: Also see pci_enable_device_bars() below. Drivers can
+    attempt to enable only a subset of BARs they need.
+
+[ OS BUG: we don't check resource allocations before enabling those
+  resources. The sequence would make more sense if we called
+  pci_request_resources() before calling pci_enable_device().
+  Currently, the device drivers can't detect the bug when when two
+  devices have been allocated the same range. This is not a common
+  problem and unlikely to get fixed soon.
+
+  This has been discussed before but not changed as of 2.6.19:
+	http://lkml.org/lkml/2006/3/2/194
+]
+
+pci_set_master() will enable DMA by setting the bus master bit
+in the PCI_COMMAND register. It also fixes the latency timer value if
+it's set to something bogus by the BIOS.
+
+If the PCI device can use the PCI Memory-Write-Invalidate transaction,
 call pci_set_mwi().  This enables the PCI_COMMAND bit for Mem-Wr-Inval
 and also ensures that the cache line size register is set correctly.
-Make sure to check the return value of pci_set_mwi(), not all architectures
-may support Memory-Write-Invalidate.
+Check the return value of pci_set_mwi() as not all architectures
+or chip-sets may support Memory-Write-Invalidate.
 
-   If your driver decides to stop using the device (e.g., there was an
-error while setting it up or the driver module is being unloaded), it
-should call pci_disable_device() to deallocate any IRQ resources, disable
-PCI bus-mastering, etc.  You should not do anything with the device after
+
+3.2 Request MMIO/IOP resources
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Memory (MMIO), and I/O port addresses should NOT be read directly
+from the PCI device config space. Use the values in the pci_dev structure
+as the PCI "bus address" might have been remapped to a "host physical"
+address by the arch/chip-set specific kernel support.
+
+See Documentation/IO-mapping.txt for how to access device registers
+or device memory.
+
+The device driver needs to call pci_request_region() to verify
+no other device is already using the same address resource.
+Conversely, drivers should call pci_release_region() AFTER
 calling pci_disable_device().
+The idea is to prevent two devices colliding on the same address range.
 
-4. How to access PCI config space
+[ See OS BUG comment above. Currently (2.6.19), The driver can only
+  determine MMIO and IO Port resource availability _after_ calling
+  pci_enable_device(). ]
+
+Generic flavors of pci_request_region() are request_mem_region()
+(for MMIO ranges) and request_region() (for IO Port ranges).
+Use these for address resources that are not described by "normal" PCI
+BARs.
+
+Also see pci_request_selected_regions() below.
+
+
+3.3 Set the DMA mask size
+~~~~~~~~~~~~~~~~~~~~~~~~~
+[ If anything below doesn't make sense, please refer to
+  Documentation/DMA-API.txt. This section is just a reminder that
+  drivers need to indicate DMA capabilities of the device and is not
+  an authoritative source for DMA interfaces. ]
+
+While all drivers should explicitly indicate the DMA capability
+(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
+32-bit bus master capability for streaming data need the driver
+to "register" this capability by calling pci_set_dma_mask() with
+appropriate parameters.  In general this allows more efficient DMA
+on systems where System RAM exists above 4G _physical_ address.
+
+Drivers for all PCI-X and PCIe compliant devices must call
+pci_set_dma_mask() as they are 64-bit DMA devices.
+
+Similarly, drivers must also "register" this capability if the device
+can directly address "consistent memory" in System RAM above 4G physical
+address by calling pci_set_consistent_dma_mask().
+Again, this includes drivers for all PCI-X and PCIe compliant devices.
+Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
+64-bit DMA capable for payload ("streaming") data but not control
+("consistent") data.
+
+
+3.4 Setup shared control data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
+memory.  See Documentation/DMA-API.txt for a full description of
+the DMA APIs. This section is just a reminder that it needs to be done
+before enabling DMA on the device.
+
+
+3.5 Initialize device registers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some drivers will need specific "capability" fields programmed
+or other "vendor specific" register initialized or reset.
+E.g. clearing pending interrupts.
+
+
+3.6 Register IRQ handler
+~~~~~~~~~~~~~~~~~~~~~~~~
+While calling request_irq() is the the last step described here,
+this is often just another intermediate step to initialize a device.
+This step can often be deferred until the device is opened for use.
+
+All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
+and use the devid to map IRQs to devices (remember that all PCI IRQ lines
+can be shared).
+
+request_irq() will associate an interrupt handler and device handle
+with an interrupt number. Historically interrupt numbers represent
+IRQ lines which run from the PCI device to the Interrupt controller.
+With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
+
+request_irq() also enables the interrupt. Make sure the device is
+quiesced and does not have any interrupts pending before registering
+the interrupt handler.
+
+MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
+which deliver interrupts to the CPU via a DMA write to a Local APIC.
+The fundamental difference between MSI and MSI-X is how multiple
+"vectors" get allocated. MSI requires contiguous blocks of vectors
+while MSI-X can allocate several individual ones.
+
+MSI capability can be enabled by calling pci_enable_msi() or
+pci_enable_msix() before calling request_irq(). This causes
+the PCI support to program CPU vector data into the PCI device
+capability registers.
+
+If your PCI device supports both, try to enable MSI-X first.
+Only one can be enabled at a time.  Many architectures, chip-sets,
+or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
+will fail. This is important to note since many drivers have
+two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
+They choose which handler to register with request_irq() based on the
+return value from pci_enable_msi/msix().
+
+There are (at least) two really good reasons for using MSI:
+1) MSI is an exclusive interrupt vector by definition.
+   This means the interrupt handler doesn't have to verify
+   its device caused the interrupt.
+
+2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
+   to be visible to the host CPU(s) when the MSI is delivered. This
+   is important for both data coherency and avoiding stale control data.
+   This guarantee allows the driver to omit MMIO reads to flush
+   the DMA stream.
+
+See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
+of MSI/MSI-X usage.
+
+
+
+4. PCI device shutdown
+~~~~~~~~~~~~~~~~~~~~~~~
+
+When a PCI device driver is being unloaded, most of the following
+steps need to be performed:
+
+	Disable the device from generating IRQs
+	Release the IRQ (free_irq())
+	Stop all DMA activity
+	Release DMA buffers (both streaming and consistent)
+	Unregister from other subsystems (e.g. scsi or netdev)
+	Disable device from responding to MMIO/IO Port addresses
+	Release MMIO/IO Port resource(s)
+
+
+4.1 Stop IRQs on the device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+How to do this is chip/device specific. If it's not done, it opens
+the possibility of a "screaming interrupt" if (and only if)
+the IRQ is shared with another device.
+
+When the shared IRQ handler is "unhooked", the remaining devices
+using the same IRQ line will still need the IRQ enabled. Thus if the
+"unhooked" device asserts IRQ line, the system will respond assuming
+it was one of the remaining devices asserted the IRQ line. Since none
+of the other devices will handle the IRQ, the system will "hang" until
+it decides the IRQ isn't going to get handled and masks the IRQ (100,000
+iterations later). Once the shared IRQ is masked, the remaining devices
+will stop functioning properly. Not a nice situation.
+
+This is another reason to use MSI or MSI-X if it's available.
+MSI and MSI-X are defined to be exclusive interrupts and thus
+are not susceptible to the "screaming interrupt" problem.
+
+
+4.2 Release the IRQ
+~~~~~~~~~~~~~~~~~~~
+Once the device is quiesced (no more IRQs), one can call free_irq().
+This function will return control once any pending IRQs are handled,
+"unhook" the drivers IRQ handler from that IRQ, and finally release
+the IRQ if no one else is using it.
+
+
+4.3 Stop all DMA activity
+~~~~~~~~~~~~~~~~~~~~~~~~~
+It's extremely important to stop all DMA operations BEFORE attempting
+to deallocate DMA control data. Failure to do so can result in memory
+corruption, hangs, and on some chip-sets a hard crash.
+
+Stopping DMA after stopping the IRQs can avoid races where the
+IRQ handler might restart DMA engines.
+
+While this step sounds obvious and trivial, several "mature" drivers
+didn't get this step right in the past.
+
+
+4.4 Release DMA buffers
+~~~~~~~~~~~~~~~~~~~~~~~
+Once DMA is stopped, clean up streaming DMA first.
+I.e. unmap data buffers and return buffers to "upstream"
+owners if there is one.
+
+Then clean up "consistent" buffers which contain the control data.
+
+See Documentation/DMA-API.txt for details on unmapping interfaces.
+
+
+4.5 Unregister from other subsystems
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Most low level PCI device drivers support some other subsystem
+like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
+driver isn't losing resources from that other subsystem.
+If this happens, typically the symptom is an Oops (panic) when
+the subsystem attempts to call into a driver that has been unloaded.
+
+
+4.6 Disable Device from responding to MMIO/IO Port addresses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+io_unmap() MMIO or IO Port resources and then call pci_disable_device().
+This is the symmetric opposite of pci_enable_device().
+Do not access device registers after calling pci_disable_device().
+
+
+4.7 Release MMIO/IO Port Resource(s)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Call pci_release_region() to mark the MMIO or IO Port range as available.
+Failure to do so usually results in the inability to reload the driver.
+
+
+
+5. How to access PCI config space
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   You can use pci_(read|write)_config_(byte|word|dword) to access the config
+
+You can use pci_(read|write)_config_(byte|word|dword) to access the config
 space of a device represented by struct pci_dev *. All these functions return 0
 when successful or an error code (PCIBIOS_...) which can be translated to a text
 string by pcibios_strerror. Most drivers expect that accesses to valid PCI
 devices don't fail.
 
-   If you don't have a struct pci_dev available, you can call
+If you don't have a struct pci_dev available, you can call
 pci_bus_(read|write)_config_(byte|word|dword) to access a given device
 and function on that bus.
 
-   If you access fields in the standard portion of the config header, please
+If you access fields in the standard portion of the config header, please
 use symbolic names of locations and bits declared in <linux/pci.h>.
 
-   If you need to access Extended PCI Capability registers, just call
+If you need to access Extended PCI Capability registers, just call
 pci_find_capability() for the particular capability and it will find the
 corresponding register block for you.
 
 
-5. Addresses and interrupts
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   Memory and port addresses and interrupt numbers should NOT be read from the
-config space. You should use the values in the pci_dev structure as they might
-have been remapped by the kernel.
-
-   See Documentation/IO-mapping.txt for how to access device memory.
-
-   The device driver needs to call pci_request_region() to make sure
-no other device is already using the same resource. The driver is expected
-to determine MMIO and IO Port resource availability _before_ calling
-pci_enable_device().  Conversely, drivers should call pci_release_region()
-_after_ calling pci_disable_device(). The idea is to prevent two devices
-colliding on the same address range.
-
-Generic flavors of pci_request_region() are request_mem_region()
-(for MMIO ranges) and request_region() (for IO Port ranges).
-Use these for address resources that are not described by "normal" PCI
-interfaces (e.g. BAR).
-
-   All interrupt handlers should be registered with IRQF_SHARED and use the devid
-to map IRQs to devices (remember that all PCI interrupts are shared).
-
 
 6. Other interesting functions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 pci_find_slot()			Find pci_dev corresponding to given bus and
 				slot numbers.
 pci_set_power_state()		Set PCI Power Management state (0=D0 ... 3=D3)
@@ -247,11 +560,12 @@
 pci_clear_mwi()			Disable Memory-Write-Invalidate transactions.
 
 
+
 7. Miscellaneous hints
 ~~~~~~~~~~~~~~~~~~~~~~
-When displaying PCI slot names to the user (for example when a driver wants
-to tell the user what card has it found), please use pci_name(pci_dev)
-for this purpose.
+
+When displaying PCI device names to the user (for example when a driver wants
+to tell the user what card has it found), please use pci_name(pci_dev).
 
 Always refer to the PCI devices by a pointer to the pci_dev structure.
 All PCI layer functions use this identification and it's the only
@@ -259,31 +573,113 @@
 special purposes -- on systems with multiple primary buses their semantics
 can be pretty complex.
 
-If you're going to use PCI bus mastering DMA, take a look at
-Documentation/DMA-mapping.txt.
-
 Don't try to turn on Fast Back to Back writes in your driver.  All devices
 on the bus need to be capable of doing it, so this is something which needs
 to be handled by platform and generic code, not individual drivers.
 
 
+
 8. Vendor and device identifications
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-For the future, let's avoid adding device ids to include/linux/pci_ids.h.
 
-PCI_VENDOR_ID_xxx for vendors, and a hex constant for device ids.
+One is not not required to add new device ids to include/linux/pci_ids.h.
+Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
 
-Rationale:  PCI_VENDOR_ID_xxx constants are re-used, but device ids are not.
-    Further, device ids are arbitrary hex numbers, normally used only in a
-    single location, the pci_device_id table.
+PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
+hex numbers (vendor controlled) and normally used only in a single
+location, the pci_device_id table.
+
+Please DO submit new vendor/device ids to pciids.sourceforge.net project.
+
+
 
 9. Obsolete functions
 ~~~~~~~~~~~~~~~~~~~~~
+
 There are several functions which you might come across when trying to
 port an old driver to the new PCI interface.  They are no longer present
 in the kernel as they aren't compatible with hotplug or PCI domains or
 having sane locking.
 
-pci_find_device()		Superseded by pci_get_device()
-pci_find_subsys()		Superseded by pci_get_subsys()
-pci_find_slot()			Superseded by pci_get_slot()
+pci_find_device()	Superseded by pci_get_device()
+pci_find_subsys()	Superseded by pci_get_subsys()
+pci_find_slot()		Superseded by pci_get_slot()
+
+
+The alternative is the traditional PCI device driver that walks PCI
+device lists. This is still possible but discouraged.
+
+
+
+10. pci_enable_device_bars() and Legacy I/O Port space
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Large servers may not be able to provide I/O port resources to all PCI
+devices. I/O Port space is only 64KB on Intel Architecture[1] and is
+likely also fragmented since the I/O base register of PCI-to-PCI
+bridge will usually be aligned to a 4KB boundary[2]. On such systems,
+pci_enable_device() and pci_request_region() will fail when
+attempting to enable I/O Port regions that don't have I/O Port
+resources assigned.
+
+Fortunately, many PCI devices which request I/O Port resources also
+provide access to the same registers via MMIO BARs. These devices can
+be handled without using I/O port space and the drivers typically
+offer a CONFIG_ option to only use MMIO regions
+(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port
+interface for legacy OSes and will work when I/O port resources are not
+assigned. The "PCI Local Bus Specification Revision 3.0" discusses
+this on p.44, "IMPLEMENTATION NOTE".
+
+If your PCI device driver doesn't need I/O port resources assigned to
+I/O Port BARs, you should use pci_enable_device_bars() instead of
+pci_enable_device() in order not to enable I/O port regions for the
+corresponding devices. In addition, you should use
+pci_request_selected_regions() and pci_release_selected_regions()
+instead of pci_request_regions()/pci_release_regions() in order not to
+request/release I/O port regions for the corresponding devices.
+
+[1] Some systems support 64KB I/O port space per PCI segment.
+[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base.
+
+
+
+11. MMIO Space and "Write Posting"
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Converting a driver from using I/O Port space to using MMIO space
+often requires some additional changes. Specifically, "write posting"
+needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
+already do this. I/O Port space guarantees write transactions reach the PCI
+device before the CPU can continue. Writes to MMIO space allow the CPU
+to continue before the transaction reaches the PCI device. HW weenies
+call this "Write Posting" because the write completion is "posted" to
+the CPU before the transaction has reached its destination.
+
+Thus, timing sensitive code should add readl() where the CPU is
+expected to wait before doing other work.  The classic "bit banging"
+sequence works fine for I/O Port space:
+
+       for (i = 8; --i; val >>= 1) {
+               outb(val & 1, ioport_reg);      /* write bit */
+               udelay(10);
+       }
+
+The same sequence for MMIO space should be:
+
+       for (i = 8; --i; val >>= 1) {
+               writeb(val & 1, mmio_reg);      /* write bit */
+               readb(safe_mmio_reg);           /* flush posted write */
+               udelay(10);
+       }
+
+It is important that "safe_mmio_reg" not have any side effects that
+interferes with the correct operation of the device.
+
+Another case to watch out for is when resetting a PCI device. Use PCI
+Configuration space reads to flush the writel(). This will gracefully
+handle the PCI master abort on all platforms if the PCI device is
+expected to not respond to a readl().  Most x86 platforms will allow
+MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
+(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
+
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
index d077d76..69f016f 100644
--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
@@ -4,6 +4,12 @@
 (c) 2006 Secret Lab Technologies Ltd
 Grant Likely <grant.likely at secretlab.ca>
 
+********** DRAFT ***********
+* WARNING: Do not depend on the stability of these bindings just yet.
+* The MPC5200 device tree conventions are still in flux
+* Keep an eye on the linuxppc-dev mailing list for more details
+********** DRAFT ***********
+
 I - Introduction
 ================
 Boards supported by the arch/powerpc architecture require device tree be
@@ -157,8 +163,8 @@
 mscan@<addr>	mscan		*-mscan		CAN bus controller
 pci@<addr>	pci		*-pci		PCI bridge
 serial@<addr>	serial		*-psc-uart	PSC in serial mode
-i2s@<addr>	i2s		*-psc-i2s	PSC in i2s mode
-ac97@<addr>	ac97		*-psc-ac97	PSC in ac97 mode
+i2s@<addr>	sound		*-psc-i2s	PSC in i2s mode
+ac97@<addr>	sound		*-psc-ac97	PSC in ac97 mode
 spi@<addr>	spi		*-psc-spi	PSC in spi mode
 irda@<addr>	irda		*-psc-irda	PSC in IrDA mode
 spi@<addr>	spi		*-spi		MPC52xx spi device
diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
index 3f9ddbc..09939696 100644
--- a/Documentation/s390/Debugging390.txt
+++ b/Documentation/s390/Debugging390.txt
@@ -480,7 +480,7 @@
 r3       argument 1 / return value 1 (if long long) call-clobbered
 r4       argument 2                                 call-clobbered
 r5       argument 3                                 call-clobbered
-r6	 argument 5                                 saved
+r6	 argument 4				    saved
 r7       pointer-to arguments 5 to ...              saved      
 r8       this & that                                saved
 r9       this & that                                saved
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
index 3367130..dc8e44f 100644
--- a/Documentation/scsi/aacraid.txt
+++ b/Documentation/scsi/aacraid.txt
@@ -11,43 +11,42 @@
 Supported Cards/Chipsets
 -------------------------
 	PCI ID (pci.ids)	OEM	Product
-	9005:0283:9005:0283	Adaptec	Catapult (3210S with arc firmware)
-	9005:0284:9005:0284	Adaptec	Tomcat (3410S with arc firmware)
 	9005:0285:9005:0285	Adaptec	2200S (Vulcan)
 	9005:0285:9005:0286	Adaptec	2120S (Crusader)
 	9005:0285:9005:0287	Adaptec	2200S (Vulcan-2m)
 	9005:0285:9005:0288	Adaptec	3230S (Harrier)
 	9005:0285:9005:0289	Adaptec	3240S (Tornado)
 	9005:0285:9005:028a	Adaptec	2020ZCR (Skyhawk)
-	9005:0285:9005:028b	Adaptec 2025ZCR (Terminator)
+	9005:0285:9005:028b	Adaptec	2025ZCR (Terminator)
 	9005:0286:9005:028c	Adaptec	2230S (Lancer)
 	9005:0286:9005:028c	Adaptec	2230SLP (Lancer)
 	9005:0286:9005:028d	Adaptec	2130S (Lancer)
 	9005:0285:9005:028e	Adaptec	2020SA (Skyhawk)
-	9005:0285:9005:028f	Adaptec 2025SA (Terminator)
+	9005:0285:9005:028f	Adaptec	2025SA (Terminator)
 	9005:0285:9005:0290	Adaptec	2410SA (Jaguar)
-	9005:0285:103c:3227	Adaptec 2610SA (Bearcat HP release)
-	9005:0285:9005:0293	Adaptec 21610SA (Corsair-16)
+	9005:0285:103c:3227	Adaptec	2610SA (Bearcat HP release)
+	9005:0285:9005:0293	Adaptec	21610SA (Corsair-16)
 	9005:0285:9005:0296	Adaptec	2240S (SabreExpress)
 	9005:0285:9005:0292	Adaptec	2810SA (Corsair-8)
-	9005:0285:9005:0294	Adaptec	Prowler
-	9005:0285:9005:0297	Adaptec	4005SAS (AvonPark)
-	9005:0285:9005:0298	Adaptec	4000SAS (BlackBird)
+	9005:0285:9005:0297	Adaptec	4005 (AvonPark)
+	9005:0285:9005:0298	Adaptec	4000 (BlackBird)
 	9005:0285:9005:0299	Adaptec	4800SAS (Marauder-X)
 	9005:0285:9005:029a	Adaptec	4805SAS (Marauder-E)
 	9005:0286:9005:029b	Adaptec	2820SA (Intruder)
 	9005:0286:9005:029c	Adaptec	2620SA (Intruder)
 	9005:0286:9005:029d	Adaptec	2420SA (Intruder HP release)
-	9005:0286:9005:02a2	Adaptec	3800SAS (Hurricane44)
-	9005:0286:9005:02a7	Adaptec	3805SAS (Hurricane80)
-	9005:0286:9005:02a8	Adaptec	3400SAS (Hurricane40)
-	9005:0286:9005:02ac	Adaptec	1800SAS (Typhoon44)
-	9005:0286:9005:02b3	Adaptec	2400SAS (Hurricane40lm)
-	9005:0285:9005:02b5	Adaptec ASR5800 (Voodoo44)
-	9005:0285:9005:02b6	Adaptec ASR5805 (Voodoo80)
-	9005:0285:9005:02b7	Adaptec ASR5808 (Voodoo08)
+	9005:0286:9005:02ac	Adaptec	1800 (Typhoon44)
+	9005:0285:9005:02b5	Adaptec	5445 (Voodoo44)
+	9005:0285:9005:02b6	Adaptec	5805 (Voodoo80)
+	9005:0285:9005:02b7	Adaptec	5085 (Voodoo08)
+	9005:0285:9005:02bb	Adaptec	3405 (Marauder40LP)
+	9005:0285:9005:02bc	Adaptec	3805 (Marauder80LP)
+	9005:0285:9005:02c7	Adaptec	3085 (Marauder08ELP)
+	9005:0285:9005:02bd	Adaptec	31205 (Marauder120)
+	9005:0285:9005:02be	Adaptec	31605 (Marauder160)
+	9005:0285:9005:02c3	Adaptec	51205 (Voodoo120)
+	9005:0285:9005:02c4	Adaptec	51605 (Voodoo160)
 	1011:0046:9005:0364	Adaptec	5400S (Mustang)
-	1011:0046:9005:0365	Adaptec	5400S (Mustang)
 	9005:0287:9005:0800	Adaptec	Themisto (Jupiter)
 	9005:0200:9005:0200	Adaptec	Themisto (Jupiter)
 	9005:0286:9005:0800	Adaptec	Callisto (Jupiter)
@@ -68,21 +67,32 @@
 	9005:0285:17aa:0287	Legend	S230 (Vulcan)
 	9005:0285:9005:0290	IBM	ServeRAID 7t (Jaguar)
 	9005:0285:1014:02F2	IBM	ServeRAID 8i (AvonPark)
-	9005:0285:1014:0312	IBM	ServeRAID 8i (AvonParkLite)
 	9005:0286:1014:9540	IBM	ServeRAID 8k/8k-l4 (AuroraLite)
 	9005:0286:1014:9580	IBM	ServeRAID 8k/8k-l8 (Aurora)
-	9005:0286:1014:034d	IBM	ServeRAID 8s (Hurricane)
-	9005:0286:9005:029e	ICP	ICP9024R0 (Lancer)
-	9005:0286:9005:029f	ICP	ICP9014R0 (Lancer)
+	9005:0285:1014:034d	IBM	ServeRAID 8s (Marauder-E)
+	9005:0286:9005:029e	ICP	ICP9024RO (Lancer)
+	9005:0286:9005:029f	ICP	ICP9014RO (Lancer)
 	9005:0286:9005:02a0	ICP	ICP9047MA (Lancer)
 	9005:0286:9005:02a1	ICP	ICP9087MA (Lancer)
-	9005:0286:9005:02a3	ICP	ICP5445AU (Hurricane44)
-	9005:0286:9005:02a4	ICP	ICP9085LI (Marauder-X)
-	9005:0286:9005:02a5	ICP	ICP5085BR (Marauder-E)
+	9005:0285:9005:02a4	ICP	ICP9085LI (Marauder-X)
+	9005:0285:9005:02a5	ICP	ICP5085BR (Marauder-E)
 	9005:0286:9005:02a6	ICP	ICP9067MA (Intruder-6)
-	9005:0286:9005:02a9	ICP	ICP5085AU (Hurricane80)
-	9005:0286:9005:02aa	ICP	ICP5045AU (Hurricane40)
-	9005:0286:9005:02b4	ICP	ICP5045AL (Hurricane40lm)
+	9005:0285:9005:02b2	ICP	(Voodoo 8 internal 8 external)
+	9005:0285:9005:02b8	ICP	ICP5445SL (Voodoo44)
+	9005:0285:9005:02b9	ICP	ICP5085SL (Voodoo80)
+	9005:0285:9005:02ba	ICP	ICP5805SL (Voodoo08)
+	9005:0285:9005:02bf	ICP	ICP5045BL (Marauder40LP)
+	9005:0285:9005:02c0	ICP	ICP5085BL (Marauder80LP)
+	9005:0285:9005:02c8	ICP	ICP5805BL (Marauder08ELP)
+	9005:0285:9005:02c1	ICP	ICP5125BR (Marauder120)
+	9005:0285:9005:02c2	ICP	ICP5165BR (Marauder160)
+	9005:0285:9005:02c5	ICP	ICP5125SL (Voodoo120)
+	9005:0285:9005:02c6	ICP	ICP5165SL (Voodoo160)
+	9005:0286:9005:02ab		(Typhoon40)
+	9005:0286:9005:02ad		(Aurora ARK)
+	9005:0286:9005:02ae		(Aurora Lite ARK)
+	9005:0285:9005:02b0		(Sunrise Lake ARK)
+	9005:0285:9005:02b1	Adaptec	(Voodoo 8 internal 8 external)
 
 People
 -------------------------
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index e0188a2..6161316 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -1,6 +1,6 @@
 Linux Magic System Request Key Hacks
-Documentation for sysrq.c version 1.15
-Last update: $Date: 2001/01/28 10:15:59 $
+Documentation for sysrq.c
+Last update: 2007-JAN-06
 
 *  What is the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -35,7 +35,7 @@
 
 Note that the value of /proc/sys/kernel/sysrq influences only the invocation
 via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
-allowed.
+allowed (by a user with admin privileges).
 
 *  How do I use the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -58,7 +58,7 @@
 On other - If you know of the key combos for other architectures, please
            let me know so I can add them to this section.
 
-On all -  write a character to /proc/sysrq-trigger.  eg:
+On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
 		echo t > /proc/sysrq-trigger
 
@@ -74,6 +74,8 @@
 
 'c'	- Will perform a kexec reboot in order to take a crashdump.
 
+'d'	- Shows all locks that are held.
+
 'o'     - Will shut your system off (if configured and supported).
 
 's'     - Will attempt to sync all mounted filesystems.
@@ -87,38 +89,43 @@
 
 'm'     - Will dump current memory info to your console.
 
+'n'	- Used to make RT tasks nice-able
+
 'v'	- Dumps Voyager SMP processor info to your console.
 
+'w'	- Dumps tasks that are in uninterruptable (blocked) state.
+
+'x'	- Used by xmon interface on ppc/powerpc platforms.
+
 '0'-'9' - Sets the console log level, controlling which kernel messages
           will be printed to your console. ('0', for example would make
           it so that only emergency messages like PANICs or OOPSes would
           make it to your console.)
 
-'f'	- Will call oom_kill to kill a memory hog process
+'f'	- Will call oom_kill to kill a memory hog process.
 
 'e'     - Send a SIGTERM to all processes, except for init.
 
+'g'	- Used by kgdb on ppc platforms.
+
 'i'     - Send a SIGKILL to all processes, except for init.
 
-'l'     - Send a SIGKILL to all processes, INCLUDING init. (Your system
-          will be non-functional after this.)
-
-'h'     - Will display help ( actually any other key than those listed
+'h'     - Will display help (actually any other key than those listed
           above will display help. but 'h' is easy to remember :-)
 
 *  Okay, so what can I use them for?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Well, un'R'aw is very handy when your X server or a svgalib program crashes.
 
-sa'K' (Secure Access Key) is useful when you want to be sure there are no
-trojan program is running at console and which could grab your password
-when you would try to login. It will kill all programs on given console
-and thus letting you make sure that the login prompt you see is actually
+sa'K' (Secure Access Key) is useful when you want to be sure there is no
+trojan program running at console which could grab your password
+when you would try to login. It will kill all programs on given console,
+thus letting you make sure that the login prompt you see is actually
 the one from init, not some trojan program.
 IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
 IMPORTANT: c2 compliant system, and it should not be mistaken as   :IMPORTANT
 IMPORTANT: such.                                                   :IMPORTANT
-       It seems other find it useful as (System Attention Key) which is
+       It seems others find it useful as (System Attention Key) which is
 useful when you want to exit a program that will not let you switch consoles.
 (For example, X or a svgalib program.)
 
@@ -139,8 +146,8 @@
 Again, the unmount (remount read-only) hasn't taken place until you see the
 "OK" and "Done" message appear on the screen.
 
-The loglevel'0'-'9' is useful when your console is being flooded with
-kernel messages you do not want to see. Setting '0' will prevent all but
+The loglevels '0'-'9' are useful when your console is being flooded with
+kernel messages you do not want to see. Selecting '0' will prevent all but
 the most urgent kernel messages from reaching your console. (They will
 still be logged if syslogd/klogd are alive, though.)
 
@@ -152,7 +159,7 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 That happens to me, also. I've found that tapping shift, alt, and control
 on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (ie, something like alt-sysrq-z). Switching to another
+will fix the problem. (i.e., something like alt-sysrq-z). Switching to another
 virtual console (ALT+Fn) and then back again should also help.
 
 *  I hit SysRq, but nothing seems to happen, what's wrong?
@@ -174,11 +181,11 @@
 prints help, and C) an action_msg string, that will print right before your
 handler is called. Your handler must conform to the prototype in 'sysrq.h'.
 
-After the sysrq_key_op is created, you can call the macro 
-register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
-sysrq.h, this will register the operation pointed to by 'op_p' at table
-key 'key', if that slot in the table is blank. At module unload time, you must
-call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
+After the sysrq_key_op is created, you can call the kernel function
+register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
+register the operation pointed to by 'op_p' at table key 'key',
+if that slot in the table is blank. At module unload time, you must call
+the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
 will remove the key op pointed to by 'op_p' from the key 'key', if and only if
 it is currently registered in that slot. This is in case the slot has been
 overwritten since you registered it.
@@ -186,15 +193,12 @@
 The Magic SysRQ system works by registering key operations against a key op
 lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
 a number of operations registered into it at compile time, but is mutable,
-and 4 functions are exported for interface to it: __sysrq_lock_table,
-__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The
-functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined
-in the header itself, and the REGISTER and UNREGISTER macros are built from
-these. More complex (and dangerous!) manipulations of the table are possible
-using these functions, but you must be careful to always lock the table before
-you read or write from it, and to unlock it again when you are done. (And of
-course, to never ever leave an invalid pointer in the table). Null pointers in
-the table are always safe :)
+and 2 functions are exported for interface to it:
+	register_sysrq_key and unregister_sysrq_key.
+Of course, never ever leave an invalid pointer in the table. I.e., when
+your module that called register_sysrq_key() exits, it must call
+unregister_sysrq_key() to clean up the sysrq key table entry that it used.
+Null pointers in the table are always safe. :)
 
 If for some reason you feel the need to call the handle_sysrq function from
 within a function called by handle_sysrq, you must be aware that you are in
diff --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS
index 01e7f85..27a7216 100644
--- a/Documentation/usb/CREDITS
+++ b/Documentation/usb/CREDITS
@@ -21,7 +21,7 @@
   Bill Ryder <bryder@sgi.com>
   Thomas Sailer <sailer@ife.ee.ethz.ch>
   Gregory P. Smith <greg@electricrain.com>
-  Linus Torvalds <torvalds@osdl.org>
+  Linus Torvalds <torvalds@linux-foundation.org>
   Roman Weissgaerber <weissg@vienna.at>
   <Kazuki.Yasumatsu@fujixerox.co.jp>
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 4ccc5fa..16c0e15 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -207,16 +207,45 @@
 ACPI
 P:	Len Brown
 M:	len.brown@intel.com
+M:	lenb@kernel.org
 L:	linux-acpi@vger.kernel.org
 W:	http://acpi.sourceforge.net/
 T:	git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
-S:	Maintained
+S:	Supported
+
+ACPI BATTERY DRIVERS
+P:	Vladimir P. Lebedev
+M:	vladimir.p.lebedev@intel.com
+L:	linux-acpi@vger.kernel.org
+W:	http://acpi.sourceforge.net/
+S:	Supported
+
+ACPI EC DRIVER
+P:	Alexey Starikovskiy
+M:	alexey.y.starikovskiy@linux.intel.com
+L:	linux-acpi@vger.kernel.org
+W:	http://acpi.sourceforge.net/
+S:	Supported
+
+ACPI FAN DRIVER
+P:	Konstantin A. Karasyov
+M:	konstantin.a.karasyov@intel.com
+L:	linux-acpi@vger.kernel.org
+W:	http://acpi.sourceforge.net/
+S:	Supported
 
 ACPI PCI HOTPLUG DRIVER
 P:	Kristen Carlson Accardi
 M:	kristen.c.accardi@intel.com
 L:	pcihpd-discuss@lists.sourceforge.net
-S:	Maintained
+S:	Supported
+
+ACPI THERMAL DRIVER
+P:	Konstantin A. Karasyov
+M:	konstantin.a.karasyov@intel.com
+L:	linux-acpi@vger.kernel.org
+W:	http://acpi.sourceforge.net/
+S:	Supported
 
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
@@ -569,8 +598,6 @@
 S:	Maintained
 
 ATMEL MACB ETHERNET DRIVER
-P:	Atmel AVR32 Support Team
-M:	avr32@atmel.com
 P:	Haavard Skinnemoen
 M:	hskinnemoen@atmel.com
 S:	Supported
@@ -591,8 +618,6 @@
 S:	Maintained
 
 AVR32 ARCHITECTURE
-P:	Atmel AVR32 Support Team
-M:	avr32@atmel.com
 P:	Haavard Skinnemoen
 M:	hskinnemoen@atmel.com
 W:	http://www.atmel.com/products/AVR32/
@@ -601,8 +626,6 @@
 S:	Supported
 
 AVR32/AT32AP MACHINE SUPPORT
-P:	Atmel AVR32 Support Team
-M:	avr32@atmel.com
 P:	Haavard Skinnemoen
 M:	hskinnemoen@atmel.com
 S:	Supported
@@ -1085,7 +1108,7 @@
 P:	Kristen Carlson Accardi
 M:	kristen.c.accardi@intel.com
 L:	linux-acpi@vger.kernel.org
-S:	Maintained
+S:	Supported
 
 DOUBLETALK DRIVER
 P:	James R. Van Zandt
@@ -1108,9 +1131,9 @@
 S:	Maintained
 
 DSCC4 DRIVER
-P:	François Romieu
-M:	romieu@cogenit.fr
-M:	romieu@ensta.fr
+P:	Francois Romieu
+M:	romieu@fr.zoreil.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 DVB SUBSYSTEM AND DRIVERS
@@ -1225,7 +1248,7 @@
 
 ETHERNET BRIDGE
 P:	Stephen Hemminger
-M:	shemminger@osdl.org
+M:	shemminger@linux-foundation.org
 L:	bridge@osdl.org
 W:	http://bridge.sourceforge.net/
 S:	Maintained
@@ -1569,12 +1592,11 @@
 W:	http://www.developer.ibm.com/welcome/netfinity/serveraid.html
 S:	Supported 
 
-IDE DRIVER [GENERAL]
+IDE SUBSYSTEM
 P:	Bartlomiej Zolnierkiewicz
-M:	B.Zolnierkiewicz@elka.pw.edu.pl
-L:	linux-kernel@vger.kernel.org
+M:	bzolnier@gmail.com
 L:	linux-ide@vger.kernel.org
-T:	git kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git
+T:	quilt kernel.org/pub/linux/kernel/people/bart/pata-2.6/
 S:	Maintained
 
 IDE/ATAPI CDROM DRIVER
@@ -1899,11 +1921,10 @@
 
 KERNEL NFSD
 P:	Neil Brown
-M:	neilb@cse.unsw.edu.au
+M:	neilb@suse.de
 L:	nfs@lists.sourceforge.net
 W:	http://nfs.sourceforge.net/
-W:	http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
-S:	Maintained
+S:	Supported
 
 KERNEL VIRTUAL MACHINE (KVM)
 P:	Avi Kivity
@@ -2248,7 +2269,7 @@
 
 NETEM NETWORK EMULATOR
 P:	Stephen Hemminger
-M:	shemminger@osdl.org
+M:	shemminger@linux-foundation.org
 L:	netem@osdl.org
 S:	Maintained
 
@@ -2261,7 +2282,7 @@
 P:	Patrick McHardy
 M:	kaber@trash.net
 L:	netfilter-devel@lists.netfilter.org
-L:	netfilter@lists.netfilter.org
+L:	netfilter@lists.netfilter.org (subscribers-only)
 L:	coreteam@netfilter.org
 W:	http://www.netfilter.org/
 W:	http://www.iptables.org/
@@ -2535,7 +2556,7 @@
 P:	Kristen Carlson Accardi
 M:	kristen.c.accardi@intel.com
 L:	pcihpd-discuss@lists.sourceforge.net
-S:	Maintained
+S:	Supported
 
 PCMCIA SUBSYSTEM
 P:	Linux PCMCIA Team
@@ -2636,6 +2657,12 @@
 W:	http://www.pnd-pc.demon.co.uk/promise/
 S:	Maintained
 
+PROMISE SATA TX2/TX4 CONTROLLER LIBATA DRIVER
+P:	Mikael Pettersson
+M:	mikpe@it.uu.se
+L:	linux-ide@vger.kernel.org
+S:	Maintained
+
 PS3 PLATFORM SUPPORT
 P:	Geoff Levand
 M:	geoffrey.levand@am.sony.com
@@ -2764,7 +2791,7 @@
 P:	Heiko Carstens
 M:	heiko.carstens@de.ibm.com
 M:	linux390@de.ibm.com
-L:	linux-390@vm.marist.edu
+L:	linux-s390@vger.kernel.org
 W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 
@@ -2772,7 +2799,7 @@
 P:	Frank Pavlic
 M:	fpavlic@de.ibm.com
 M:	linux390@de.ibm.com
-L:	linux-390@vm.marist.edu
+L:	linux-s390@vger.kernel.org
 W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 
@@ -2780,7 +2807,7 @@
 P:	Swen Schillig
 M:	swen@vnet.ibm.com
 M:	linux390@de.ibm.com
-L:	linux-390@vm.marist.edu
+L:	linux-s390@vger.kernel.org
 W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 
@@ -2958,9 +2985,9 @@
 P:	Ingo Molnar
 M:	mingo@redhat.com
 P:	Neil Brown
-M:	neilb@cse.unsw.edu.au
+M:	neilb@suse.de
 L:	linux-raid@vger.kernel.org
-S:	Maintained
+S:	Supported
 
 SOFTWARE SUSPEND:
 P:	Pavel Machek
@@ -3035,7 +3062,7 @@
 P:	Kristen Carlson Accardi
 M:	kristen.c.accardi@intel.com
 L:	pcihpd-discuss@lists.sourceforge.net
-S:	Maintained
+S:	Supported
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
 P:	Pierre Ossman
@@ -3046,7 +3073,7 @@
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
 P:	Stephen Hemminger
-M:	shemminger@osdl.org
+M:	shemminger@linux-foundation.org
 L:	netdev@vger.kernel.org
 S:	Maintained
 
@@ -3299,9 +3326,8 @@
 S:	Maintained
 
 USB HID/HIDBP DRIVERS
-P:	Vojtech Pavlik
-M:	vojtech@suse.cz
-L:	linux-usb-users@lists.sourceforge.net
+P:	Jiri Kosina
+M:	jkosina@suse.cz
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
@@ -3541,6 +3567,12 @@
 L:	i2c@lm-sensors.org
 S:	Maintained
 
+VIA VELOCITY NETWORK DRIVER
+P:	Francois Romieu
+M:	romieu@fr.zoreil.com
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 UCLINUX (AND M68KNOMMU)
 P:	Greg Ungerer
 M:	gerg@uclinux.org
@@ -3561,6 +3593,12 @@
 W:	http://uclinux-h8.sourceforge.jp/
 S:	Supported
 
+UFS FILESYSTEM
+P: Evgeniy Dushistov
+M: dushistov@mail.ru
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
 USB DIAMOND RIO500 DRIVER
 P:	Cesar Miquel
 M:	miquel@df.uba.ar
@@ -3609,7 +3647,7 @@
 W83L51xD SD/MMC CARD INTERFACE DRIVER
 P:	Pierre Ossman
 M:	drzeus-wbsd@drzeus.cx
-L:	wbsd-devel@list.drzeus.cx
+L:	linux-kernel@vger.kernel.org
 W:	http://projects.drzeus.cx/wbsd
 S:	Maintained
 
diff --git a/Makefile b/Makefile
index fb5b3ef..cdeda68 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 20
-EXTRAVERSION =-rc4
+EXTRAVERSION =
 NAME = Homicidal Dwarf Hamster
 
 # *DOCUMENTATION*
@@ -368,14 +368,10 @@
 # Detect when mixed targets is specified, and make a second invocation
 # of make so .config is not included in this case either (for *config).
 
-PHONY += generated_headers
-
-generated_headers: include/linux/version.h include/linux/compile.h \
-		include/linux/utsrelease.h
-
-no-dot-config-targets := generated_headers clean mrproper distclean \
+no-dot-config-targets := clean mrproper distclean \
 			 cscope TAGS tags help %docs check% \
-			 headers_% kernelrelease kernelversion
+			 include/linux/version.h headers_% \
+			 kernelrelease kernelversion
 
 config-targets := 0
 mixed-targets  := 0
@@ -738,16 +734,6 @@
 
 endif # ifdef CONFIG_KALLSYMS
 
-# compile.h changes depending on hostname, generation number, etc,
-# so we regenerate it always.
-# mkcompile_h will make sure to only update the
-# actual file if its content has changed.
-
-include/linux/compile.h: FORCE
-	@echo '  CHK     $@'
-	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
-	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(CFLAGS)"
-
 # vmlinux image - including updated kernel symbols
 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
 ifdef CONFIG_HEADERS_CHECK
@@ -790,7 +776,7 @@
 #	  $(EXTRAVERSION)		eg, -rc6
 #	$(localver-full)
 #	  $(localver)
-#	    localversion*		(all localversion* files)
+#	    localversion*		(files without backups, containing '~')
 #	    $(CONFIG_LOCALVERSION)	(from kernel config setting)
 #	  $(localver-auto)		(only if CONFIG_LOCALVERSION_AUTO is set)
 #	    ./scripts/setlocalversion	(SCM tag, if one exists)
@@ -801,17 +787,12 @@
 # moment, only git is supported but other SCMs can edit the script
 # scripts/setlocalversion and add the appropriate checks as needed.
 
-nullstring :=
-space      := $(nullstring) # end of line
+pattern = ".*/localversion[^~]*"
+string  = $(shell cat /dev/null \
+	   `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`)
 
-___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)))
+localver = $(subst $(space),, $(string) \
+			      $(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.
@@ -866,8 +847,8 @@
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile
 
-prepare1: prepare2 generated_headers include/asm include/config/auto.conf
-
+prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
+                   include/asm include/config/auto.conf
 ifneq ($(KBUILD_MODULES),)
 	$(Q)mkdir -p $(MODVERDIR)
 	$(Q)rm -f $(MODVERDIR)/*
@@ -936,14 +917,14 @@
 HDRARCHES=$(filter-out generic,$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
 
 PHONY += headers_install_all
-headers_install_all: generated_headers scripts_basic FORCE
+headers_install_all: include/linux/version.h scripts_basic FORCE
 	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
 	$(Q)for arch in $(HDRARCHES); do \
 	 $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
 	 done
 
 PHONY += headers_install
-headers_install: generated_headers scripts_basic FORCE
+headers_install: include/linux/version.h scripts_basic FORCE
 	@if [ ! -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
 	  echo '*** Error: Headers not exportable for this architecture ($(ARCH))'; \
 	  exit 1 ; fi
@@ -1040,7 +1021,8 @@
 # Directories & files removed with 'make mrproper'
 MRPROPER_DIRS  += include/config include2 usr/include
 MRPROPER_FILES += .config .config.old include/asm .version .old_version \
-                  include/linux/autoconf.h include/linux/utsrelease.h include/linux/version.h \
+                  include/linux/autoconf.h include/linux/version.h      \
+                  include/linux/utsrelease.h                            \
 		  Module.symvers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
@@ -1129,15 +1111,15 @@
 	@echo  '  cscope	  - Generate cscope index'
 	@echo  '  kernelrelease	  - Output the release version string'
 	@echo  '  kernelversion	  - Output the version stored in Makefile'
-	@if [ -r include/asm-$(ARCH)/Kbuild ]; then \
+	@if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
 	 echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
+	 echo  '                    (default: $(INSTALL_HDR_PATH))'; \
 	 fi
-	@echo  '                    (default: $(INSTALL_HDR_PATH))'
 	@echo  ''
 	@echo  'Static analysers'
 	@echo  '  checkstack      - Generate a list of stack hogs'
 	@echo  '  namespacecheck  - Name space analysis on compiled kernel'
-	@if [ -r include/asm-$(ARCH)/Kbuild ]; then \
+	@if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
 	 echo  '  headers_check   - Sanity check on exported headers'; \
 	 fi
 	@echo  ''
diff --git a/README b/README
index c055615..46a66c6 100644
--- a/README
+++ b/README
@@ -278,8 +278,8 @@
    the file MAINTAINERS to see if there is a particular person associated
    with the part of the kernel that you are having trouble with. If there
    isn't anyone listed there, then the second best thing is to mail
-   them to me (torvalds@osdl.org), and possibly to any other relevant
-   mailing-list or to the newsgroup.
+   them to me (torvalds@linux-foundation.org), and possibly to any other
+   relevant mailing-list or to the newsgroup.
 
  - In all bug-reports, *please* tell what kernel you are talking about,
    how to duplicate the problem, and what your setup is (use your common
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 3370e6f..c151863 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -47,6 +47,7 @@
  * Power off function, if any
  */
 void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
 
 void
 cpu_idle(void)
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
index 7904920..46b0c73 100644
--- a/arch/arm/configs/at91sam9260ek_defconfig
+++ b/arch/arm/configs/at91sam9260ek_defconfig
@@ -923,7 +923,6 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
index 784ad7c..fcd8fa0 100644
--- a/arch/arm/configs/at91sam9261ek_defconfig
+++ b/arch/arm/configs/at91sam9261ek_defconfig
@@ -1079,7 +1079,6 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index d994561..cf495a30 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -22,6 +22,10 @@
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
+#if (PHYS_OFFSET & 0x001fffff)
+#error "PHYS_OFFSET must be at an even 2MiB boundary!"
+#endif
+
 #define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
 #define KERNEL_RAM_PADDR	(PHYS_OFFSET + TEXT_OFFSET)
 
@@ -251,7 +255,8 @@
 	 * Then map first 1MB of ram in case it contains our boot params.
 	 */
 	add	r0, r4, #PAGE_OFFSET >> 18
-	orr	r6, r7, #PHYS_OFFSET
+	orr	r6, r7, #(PHYS_OFFSET & 0xff000000)
+	orr	r6, r6, #(PHYS_OFFSET & 0x00e00000)
 	str	r6, [r0]
 
 #ifdef CONFIG_XIP_KERNEL
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c
index 4641b99..57fac72 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c
+++ b/arch/arm/mach-at91rm9200/at91rm9200_devices.c
@@ -272,7 +272,7 @@
 	at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
 
 	/* nWAIT is _not_ a default setting */
-	at91_set_A_periph(AT91_PIN_PC6, 1);	/*  nWAIT */
+	at91_set_A_periph(AT91_PIN_PC6, 1);	/* nWAIT */
 
 	cf_data = *data;
 	platform_device_register(&at91rm9200_cf_device);
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c
index 203f073..b14871a 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260.c
+++ b/arch/arm/mach-at91rm9200/at91sam9260.c
@@ -16,6 +16,7 @@
 #include <asm/mach/map.h>
 #include <asm/arch/at91sam9260.h>
 #include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
 
 #include "generic.h"
 #include "clock.h"
@@ -212,7 +213,7 @@
 
 static void at91sam9260_reset(void)
 {
-#warning "Implement CPU reset"
+	at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
 }
 
 
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c
index 5a82f35..d242bb8 100644
--- a/arch/arm/mach-at91rm9200/at91sam9261.c
+++ b/arch/arm/mach-at91rm9200/at91sam9261.c
@@ -16,6 +16,7 @@
 #include <asm/mach/map.h>
 #include <asm/arch/at91sam9261.h>
 #include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
 
 #include "generic.h"
 #include "clock.h"
@@ -207,7 +208,7 @@
 
 static void at91sam9261_reset(void)
 {
-#warning "Implement CPU reset"
+	at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
 }
 
 
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 3f18850..af22659 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/at91_pio.h>
-#include <asm/arch/at91_pmc.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
@@ -224,17 +223,17 @@
 static int gpio_irq_set_wake(unsigned pin, unsigned state)
 {
 	unsigned	mask = pin_to_mask(pin);
+	unsigned	bank = (pin - PIN_BASE) / 32;
 
-	pin -= PIN_BASE;
-	pin /= 32;
-
-	if (unlikely(pin >= MAX_GPIO_BANKS))
+	if (unlikely(bank >= MAX_GPIO_BANKS))
 		return -EINVAL;
 
 	if (state)
-		wakeups[pin] |= mask;
+		wakeups[bank] |= mask;
 	else
-		wakeups[pin] &= ~mask;
+		wakeups[bank] &= ~mask;
+
+	set_irq_wake(gpio[bank].id, state);
 
 	return 0;
 }
@@ -246,29 +245,15 @@
 	for (i = 0; i < gpio_banks; i++) {
 		u32 pio = gpio[i].offset;
 
-		/*
-		 * Note: drivers should have disabled GPIO interrupts that
-		 * aren't supposed to be wakeup sources.
-		 * But that is not much good on ARM.....  disable_irq() does
-		 * not update the hardware immediately, so the hardware mask
-		 * (IMR) has the wrong value (not current, too much is
-		 * permitted).
-		 *
-		 * Our workaround is to disable all non-wakeup IRQs ...
-		 * which is exactly what correct drivers asked for in the
-		 * first place!
-		 */
 		backups[i] = at91_sys_read(pio + PIO_IMR);
 		at91_sys_write(pio + PIO_IDR, backups[i]);
 		at91_sys_write(pio + PIO_IER, wakeups[i]);
 
-		if (!wakeups[i]) {
-			disable_irq_wake(gpio[i].id);
-			at91_sys_write(AT91_PMC_PCDR, 1 << gpio[i].id);
-		} else {
-			enable_irq_wake(gpio[i].id);
+		if (!wakeups[i])
+			clk_disable(gpio[i].clock);
+		else {
 #ifdef CONFIG_PM_DEBUG
-			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]);
+			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
 #endif
 		}
 	}
@@ -281,9 +266,11 @@
 	for (i = 0; i < gpio_banks; i++) {
 		u32 pio = gpio[i].offset;
 
+		if (!wakeups[i])
+			clk_enable(gpio[i].clock);
+
 		at91_sys_write(pio + PIO_IDR, wakeups[i]);
 		at91_sys_write(pio + PIO_IER, backups[i]);
-		at91_sys_write(AT91_PMC_PCER, 1 << gpio[i].id);
 	}
 }
 
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c
index ac5f998..4f66e90 100644
--- a/arch/arm/mach-imx/cpufreq.c
+++ b/arch/arm/mach-imx/cpufreq.c
@@ -184,6 +184,17 @@
 	long sysclk;
 	unsigned int bclk_div = 1;
 
+	/*
+	 * Some governors do not respects CPU and policy lower limits
+	 * which leads to bad things (division by zero etc), ensure
+	 * that such things do not happen.
+	 */
+	if(target_freq < policy->cpuinfo.min_freq)
+		target_freq = policy->cpuinfo.min_freq;
+
+	if(target_freq < policy->min)
+		target_freq = policy->min;
+
 	freq = target_freq * 1000;
 
 	pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n",
@@ -258,7 +269,8 @@
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	policy->cpuinfo.min_freq = 8000;
 	policy->cpuinfo.max_freq = 200000;
-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	 /* Manual states, that PLL stabilizes in two CLK32 periods */
+	policy->cpuinfo.transition_latency = 4 * 1000000000LL / CLK32;
 	return 0;
 }
 
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index ba34654..f6fb215 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -57,6 +57,7 @@
 	case S3C2410_GPIO_SFN2:
 	case S3C2410_GPIO_SFN3:
 		if (pin < S3C2410_GPIO_BANKB) {
+			function -= 1;
 			function &= 1;
 			function <<= S3C2410_GPIO_OFFSET(pin);
 		} else {
@@ -83,15 +84,18 @@
 unsigned int s3c2410_gpio_getcfg(unsigned int pin)
 {
 	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long mask;
+	unsigned long val = __raw_readl(base);
 
 	if (pin < S3C2410_GPIO_BANKB) {
-		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+		val >>= S3C2410_GPIO_OFFSET(pin);
+		val &= 1;
+		val += 1;
 	} else {
-		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+		val >>= S3C2410_GPIO_OFFSET(pin)*2;
+		val &= 3;
 	}
 
-	return __raw_readl(base) & mask;
+	return val | S3C2410_GPIO_INPUT;
 }
 
 EXPORT_SYMBOL(s3c2410_gpio_getcfg);
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index 0083409..ebf294d 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -451,15 +451,14 @@
 		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
 
 	pinstate = s3c2410_gpio_getcfg(pin);
-	pinstate >>= S3C2410_GPIO_OFFSET(pin)*2;
 
 	if (!irqstate) {
-		if (pinstate == 0x02)
+		if (pinstate == S3C2410_GPIO_IRQ)
 			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
 	} else {
-		if (pinstate == 0x02) {
+		if (pinstate == S3C2410_GPIO_IRQ) {
 			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
-			s3c2410_gpio_cfgpin(pin, 0x00);
+			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
 		}
 	}
 }
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2410/s3c2412-dma.c
index fe71a8f..138f726 100644
--- a/arch/arm/mach-s3c2410/s3c2412-dma.c
+++ b/arch/arm/mach-s3c2410/s3c2412-dma.c
@@ -133,8 +133,8 @@
 static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
 			       struct s3c24xx_dma_map *map)
 {
-	writel(chan->regs + S3C2412_DMA_DMAREQSEL,
-	       map->channels[0] | S3C2412_DMAREQSEL_HW);
+	writel(map->channels[0] | S3C2412_DMAREQSEL_HW,
+	       chan->regs + S3C2412_DMA_DMAREQSEL);
 }
 
 static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b5814b4..7760193 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -52,15 +52,18 @@
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 
 	for_each_online_node(node) {
+		pg_data_t *n = NODE_DATA(node);
+		struct page *map = n->node_mem_map - n->node_start_pfn;
+
 		for_each_nodebank (i,mi,node) {
 			unsigned int pfn1, pfn2;
 			struct page *page, *end;
 
-			pfn1 = mi->bank[i].start >> PAGE_SHIFT;
-			pfn2 = (mi->bank[i].size + mi->bank[i].start) >> PAGE_SHIFT;
+			pfn1 = __phys_to_pfn(mi->bank[i].start);
+			pfn2 = __phys_to_pfn(mi->bank[i].size + mi->bank[i].start);
 
-			page = NODE_MEM_MAP(node) + pfn1;
-			end  = NODE_MEM_MAP(node) + pfn2;
+			page = map + pfn1;
+			end  = map + pfn2;
 
 			do {
 				total++;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 251685f..0ac615c 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -300,7 +300,8 @@
  	addr = (unsigned long)area->addr;
 
 #ifndef CONFIG_SMP
-	if ((((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
+	if (DOMAIN_IO == 0 &&
+	    (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
 	       cpu_is_xsc3()) &&
 	       !((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) {
 		area->flags |= VM_ARM_SECTION_MAPPING;
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 490e11b..d29fe92 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -708,7 +708,7 @@
 	.type	__8033x_proc_info,#object
 __8033x_proc_info:
 	.long	0x69054010
-	.long	0xffffff30
+	.long	0xfffffd30
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_BUFFERABLE | \
 		PMD_SECT_CACHEABLE | \
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8bcb838..bd78058 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Thu Dec 7 17:19:20 2006
+# Last update: Tue Jan 16 16:52:56 2007
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1219,3 +1219,26 @@
 hitrack			MACH_HITRACK		HITRACK			1208
 syme1			MACH_SYME1		SYME1			1209
 syhl1			MACH_SYHL1		SYHL1			1210
+empca400		MACH_EMPCA400		EMPCA400		1211
+em7210			MACH_EM7210		EM7210			1212
+htchermes		MACH_HTCHERMES		HTCHERMES		1213
+eti_c1			MACH_ETI_C1		ETI_C1			1214
+mach_dep2410		MACH_MACH_DEP2410	MACH_DEP2410		1215
+ac100			MACH_AC100		AC100			1216
+sneetch			MACH_SNEETCH		SNEETCH			1217
+studentmate		MACH_STUDENTMATE	STUDENTMATE		1218
+zir2410			MACH_ZIR2410		ZIR2410			1219
+zir2413			MACH_ZIR2413		ZIR2413			1220
+dlonip3			MACH_DLONIP3		DLONIP3			1221
+instream		MACH_INSTREAM		INSTREAM		1222
+ambarella		MACH_AMBARELLA		AMBARELLA		1223
+nevis			MACH_NEVIS		NEVIS			1224
+htc_trinity		MACH_HTC_TRINITY	HTC_TRINITY		1225
+ql202b			MACH_QL202B		QL202B			1226
+vpac270			MACH_VPAC270		VPAC270			1227
+rd129			MACH_RD129		RD129			1228
+htcwizard		MACH_HTCWIZARD		HTCWIZARD		1229
+xscale_treo680		MACH_XSCALE_TREO680	XSCALE_TREO680		1230
+tecon_tmezon		MACH_TECON_TMEZON	TECON_TMEZON		1231
+zylonite		MACH_ZYLONITE		ZYLONITE		1233
+gene1270		MACH_GENE1270		GENE1270		1234
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index 7b59554..ca2a5ad 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -25,6 +25,7 @@
 do_vfp:
 	enable_irq
  	ldr	r4, .LCvfp
+	ldr	r11, [r10, #TI_CPU]	@ CPU number
 	add	r10, r10, #TI_VFPSTATE	@ r10 = workspace
 	ldr	pc, [r4]		@ call VFP entry point
 
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index f279789..54a2ad6 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -370,3 +370,7 @@
 	u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
 	u32 flags;
 };
+
+#ifdef CONFIG_SMP
+extern void vfp_save_state(void *location, u32 fpexc);
+#endif
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index e51e667..d4b7b22 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -65,6 +65,7 @@
 @  r2  = faulted PC+4
 @  r9  = successful return
 @  r10 = vfp_state union
+@  r11 = CPU number
 @  lr  = failure return
 
 	.globl	vfp_support_entry
@@ -79,7 +80,7 @@
 	DBGSTR1 "enable %x", r10
 	ldr	r3, last_VFP_context_address
 	orr	r1, r1, #FPEXC_ENABLE	@ user FPEXC has the enable bit set
-	ldr	r4, [r3]		@ last_VFP_context pointer
+	ldr	r4, [r3, r11, lsl #2]	@ last_VFP_context pointer
 	bic	r5, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled
 	cmp	r4, r10
 	beq	check_for_exception	@ we are returning to the same
@@ -91,7 +92,9 @@
 					@ exceptions, so we can get at the
 					@ rest of it
 
+#ifndef CONFIG_SMP
 	@ Save out the current registers to the old thread state
+	@ No need for SMP since this is not done lazily
 
 	DBGSTR1	"save old state %p", r4
 	cmp	r4, #0
@@ -105,10 +108,11 @@
 	stmia	r4, {r1, r5, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2
 					@ and point r4 at the word at the
 					@ start of the register dump
+#endif
 
 no_old_VFP_process:
 	DBGSTR1	"load state %p", r10
-	str	r10, [r3]		@ update the last_VFP_context pointer
+	str	r10, [r3, r11, lsl #2]	@ update the last_VFP_context pointer
 					@ Load the saved state back into the VFP
 	VFPFLDMIA r10	 		@ reload the working registers while
 					@ FPEXC is in a safe state
@@ -162,6 +166,24 @@
 					@ required. If not, the user code will
 					@ retry the faulted instruction
 
+#ifdef CONFIG_SMP
+	.globl	vfp_save_state
+	.type	vfp_save_state, %function
+vfp_save_state:
+	@ Save the current VFP state
+	@ r0 - save location
+	@ r1 - FPEXC
+	DBGSTR1	"save VFP state %p", r0
+	VFPFMRX	r2, FPSCR		@ current status
+	VFPFMRX	r3, FPINST		@ FPINST (always there, rev0 onwards)
+	tst	r1, #FPEXC_FPV2		@ is there an FPINST2 to read?
+	VFPFMRX	r12, FPINST2, NE	@ FPINST2 if needed - avoids reading
+					@ nonexistant reg on rev0
+	VFPFSTMIA r0 			@ save the working registers
+	stmia	r0, {r1, r2, r3, r12}	@ save FPEXC, FPSCR, FPINST, FPINST2
+	mov	pc, lr
+#endif
+
 last_VFP_context_address:
 	.word	last_VFP_context
 
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 490d9d1..f1e5951 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -28,7 +28,7 @@
 void vfp_support_entry(void);
 
 void (*vfp_vector)(void) = vfp_testing_entry;
-union vfp_state *last_VFP_context;
+union vfp_state *last_VFP_context[NR_CPUS];
 
 /*
  * Dual-use variable.
@@ -41,13 +41,35 @@
 {
 	struct thread_info *thread = v;
 	union vfp_state *vfp;
+	__u32 cpu = thread->cpu;
 
 	if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
+		u32 fpexc = fmrx(FPEXC);
+
+#ifdef CONFIG_SMP
+		/*
+		 * On SMP, if VFP is enabled, save the old state in
+		 * case the thread migrates to a different CPU. The
+		 * restoring is done lazily.
+		 */
+		if ((fpexc & FPEXC_ENABLE) && last_VFP_context[cpu]) {
+			vfp_save_state(last_VFP_context[cpu], fpexc);
+			last_VFP_context[cpu]->hard.cpu = cpu;
+		}
+		/*
+		 * Thread migration, just force the reloading of the
+		 * state on the new CPU in case the VFP registers
+		 * contain stale data.
+		 */
+		if (thread->vfpstate.hard.cpu != cpu)
+			last_VFP_context[cpu] = NULL;
+#endif
+
 		/*
 		 * Always disable VFP so we can lazily save/restore the
 		 * old state.
 		 */
-		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+		fmxr(FPEXC, fpexc & ~FPEXC_ENABLE);
 		return NOTIFY_DONE;
 	}
 
@@ -68,8 +90,8 @@
 	}
 
 	/* flush and release case: Per-thread VFP cleanup. */
-	if (last_VFP_context == vfp)
-		last_VFP_context = NULL;
+	if (last_VFP_context[cpu] == vfp)
+		last_VFP_context[cpu] = NULL;
 
 	return NOTIFY_DONE;
 }
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index ae92a14..77dace9 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Fri Oct 20 11:52:37 2006
+# Linux kernel version: 2.6.20-rc6
+# Fri Jan 26 13:12:59 2007
 #
 CONFIG_AVR32=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -9,6 +9,8 @@
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -36,6 +38,7 @@
 # CONFIG_UTS_NS is not set
 CONFIG_AUDIT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -75,7 +78,9 @@
 # Block layer
 #
 CONFIG_BLOCK=y
+# CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -125,6 +130,7 @@
 # CONFIG_OWNERSHIP_TRACE is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_CMDLINE=""
@@ -182,6 +188,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -260,6 +267,7 @@
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
@@ -355,7 +363,6 @@
 #
 # Misc devices
 #
-# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 
 #
@@ -405,11 +412,14 @@
 #
 # PHY device support
 #
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACB=y
 
 #
 # Ethernet (1000 Mbit)
@@ -505,10 +515,6 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -621,6 +627,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -683,7 +693,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -763,6 +772,11 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
@@ -770,6 +784,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -785,13 +801,10 @@
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_KPROBES is not set
 
@@ -809,6 +822,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -817,3 +831,4 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
index 7c4c761..80f55f8 100644
--- a/arch/avr32/kernel/avr32_ksyms.c
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -29,6 +29,7 @@
  */
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(clear_page);
 
 /*
  * Userspace access stuff.
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 2d0023f..77e655f 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -195,7 +195,7 @@
  */
 unsigned long cache_decay_ticks = 1;
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	smp_boot_one_cpu(cpu);
 	return cpu_online(cpu) ? 0 : -ENOSYS;
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c
index 468da89..881951c 100644
--- a/arch/i386/boot/compressed/relocs.c
+++ b/arch/i386/boot/compressed/relocs.c
@@ -43,6 +43,8 @@
 			/* Match found */
 			return 1;
 	}
+	if (strncmp(sym_name, "__crc_", 6) == 0)
+		return 1;
 	return 0;
 }
 
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 88b7c1c..5d80edf 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-git14
-# Sat Dec  9 21:23:14 2006
+# Linux kernel version: 2.6.20-rc3
+# Fri Jan  5 11:54:46 2007
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -1287,6 +1287,11 @@
 #
 
 #
+# Virtualization
+#
+# CONFIG_KVM is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1471,6 +1476,8 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1489,12 +1496,10 @@
 # CONFIG_DEBUG_HIGHMEM is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_FORCED_INLINING is not set
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 CONFIG_EARLY_PRINTK=y
@@ -1527,6 +1532,7 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 12e937c..2d39f55 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -47,13 +47,13 @@
 
 /* The code below handles cstate entry with monitor-mwait pair on Intel*/
 
-struct cstate_entry_s {
+struct cstate_entry {
 	struct {
 		unsigned int eax;
 		unsigned int ecx;
 	} states[ACPI_PROCESSOR_MAX_POWER];
 };
-static struct cstate_entry_s *cpu_cstate_entry;	/* per CPU ptr */
+static struct cstate_entry *cpu_cstate_entry;	/* per CPU ptr */
 
 static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
 
@@ -71,7 +71,7 @@
 int acpi_processor_ffh_cstate_probe(unsigned int cpu,
 		struct acpi_processor_cx *cx, struct acpi_power_register *reg)
 {
-	struct cstate_entry_s *percpu_entry;
+	struct cstate_entry *percpu_entry;
 	struct cpuinfo_x86 *c = cpu_data + cpu;
 
 	cpumask_t saved_mask;
@@ -136,7 +136,7 @@
 void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
 {
 	unsigned int cpu = smp_processor_id();
-	struct cstate_entry_s *percpu_entry;
+	struct cstate_entry *percpu_entry;
 
 	percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
 	mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
@@ -150,7 +150,7 @@
 	if (c->x86_vendor != X86_VENDOR_INTEL)
 		return -1;
 
-	cpu_cstate_entry = alloc_percpu(struct cstate_entry_s);
+	cpu_cstate_entry = alloc_percpu(struct cstate_entry);
 	return 0;
 }
 
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 8689d62..8a8bbda 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -710,11 +710,8 @@
 	return 1;
 }
 
-/* Common CPU init for both boot and secondary CPUs */
-static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+void __cpuinit cpu_set_gdt(int cpu)
 {
-	struct tss_struct * t = &per_cpu(init_tss, cpu);
-	struct thread_struct *thread = &curr->thread;
 	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
 
 	/* Reinit these anyway, even if they've already been done (on
@@ -722,6 +719,13 @@
 	   the real ones). */
 	load_gdt(cpu_gdt_descr);
 	set_kernel_gs();
+}
+
+/* Common CPU init for both boot and secondary CPUs */
+static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+{
+	struct tss_struct * t = &per_cpu(init_tss, cpu);
+	struct thread_struct *thread = &curr->thread;
 
 	if (cpu_test_and_set(cpu, cpu_initialized)) {
 		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -807,6 +811,7 @@
 			local_irq_enable();
 	}
 
+	cpu_set_gdt(cpu);
 	_cpu_init(cpu, curr);
 }
 
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index bec5017..4786fed 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -51,7 +51,6 @@
 
 
 static int has_N44_O17_errata[NR_CPUS];
-static int has_N60_errata[NR_CPUS];
 static unsigned int stock_freq;
 static struct cpufreq_driver p4clockmod_driver;
 static unsigned int cpufreq_p4_get(unsigned int cpu);
@@ -224,12 +223,6 @@
 	case 0x0f12:
 		has_N44_O17_errata[policy->cpu] = 1;
 		dprintk("has errata -- disabling low frequencies\n");
-		break;
-
-	case 0x0f29:
-		has_N60_errata[policy->cpu] = 1;
-		dprintk("has errata -- disabling frequencies lower than 2ghz\n");
-		break;
 	}
 
 	/* get max frequency */
@@ -241,8 +234,6 @@
 	for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		if ((i<2) && (has_N44_O17_errata[policy->cpu]))
 			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
-		else if (has_N60_errata[policy->cpu] && ((stock_freq * i)/8) < 2000000)
-			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
 		else
 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
 	}
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index b92c7f0..8f9c624 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -473,6 +473,70 @@
 }
 
 /*
+ * Wrap all the virtual calls in a way that forces the parameters on the stack.
+ */
+
+#define efi_call_virt(f, args...) \
+     ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
+
+static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+	return efi_call_virt(get_time, tm, tc);
+}
+
+static efi_status_t virt_efi_set_time (efi_time_t *tm)
+{
+	return efi_call_virt(set_time, tm);
+}
+
+static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled,
+					      efi_bool_t *pending,
+					      efi_time_t *tm)
+{
+	return efi_call_virt(get_wakeup_time, enabled, pending, tm);
+}
+
+static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled,
+					      efi_time_t *tm)
+{
+	return efi_call_virt(set_wakeup_time, enabled, tm);
+}
+
+static efi_status_t virt_efi_get_variable (efi_char16_t *name,
+					   efi_guid_t *vendor, u32 *attr,
+					   unsigned long *data_size, void *data)
+{
+	return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_variable (unsigned long *name_size,
+						efi_char16_t *name,
+						efi_guid_t *vendor)
+{
+	return efi_call_virt(get_next_variable, name_size, name, vendor);
+}
+
+static efi_status_t virt_efi_set_variable (efi_char16_t *name,
+					   efi_guid_t *vendor,
+					   unsigned long attr,
+					   unsigned long data_size, void *data)
+{
+	return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_high_mono_count (u32 *count)
+{
+	return efi_call_virt(get_next_high_mono_count, count);
+}
+
+static void virt_efi_reset_system (int reset_type, efi_status_t status,
+				   unsigned long data_size,
+				   efi_char16_t *data)
+{
+	efi_call_virt(reset_system, reset_type, status, data_size, data);
+}
+
+/*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
  * has the runtime attribute bit set in its memory descriptor and update
@@ -525,22 +589,15 @@
 	 * pointers in the runtime service table to the new virtual addresses.
 	 */
 
-	efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time;
-	efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time;
-	efi.get_wakeup_time = (efi_get_wakeup_time_t *)
-					efi.systab->runtime->get_wakeup_time;
-	efi.set_wakeup_time = (efi_set_wakeup_time_t *)
-					efi.systab->runtime->set_wakeup_time;
-	efi.get_variable = (efi_get_variable_t *)
-					efi.systab->runtime->get_variable;
-	efi.get_next_variable = (efi_get_next_variable_t *)
-					efi.systab->runtime->get_next_variable;
-	efi.set_variable = (efi_set_variable_t *)
-					efi.systab->runtime->set_variable;
-	efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *)
-					efi.systab->runtime->get_next_high_mono_count;
-	efi.reset_system = (efi_reset_system_t *)
-					efi.systab->runtime->reset_system;
+	efi.get_time = virt_efi_get_time;
+	efi.set_time = virt_efi_set_time;
+	efi.get_wakeup_time = virt_efi_get_wakeup_time;
+	efi.set_wakeup_time = virt_efi_set_wakeup_time;
+	efi.get_variable = virt_efi_get_variable;
+	efi.get_next_variable = virt_efi_get_next_variable;
+	efi.set_variable = virt_efi_set_variable;
+	efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
+	efi.reset_system = virt_efi_reset_system;
 }
 
 void __init
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 06461b8..5e47683 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -302,12 +302,16 @@
 	pushl $(__USER_CS)
 	CFI_ADJUST_CFA_OFFSET 4
 	/*CFI_REL_OFFSET cs, 0*/
+#ifndef CONFIG_COMPAT_VDSO
 	/*
 	 * Push current_thread_info()->sysenter_return to the stack.
 	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
 	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
 	 */
 	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
+#else
+	pushl $SYSENTER_RETURN
+#endif
 	CFI_ADJUST_CFA_OFFSET 4
 	CFI_REL_OFFSET eip, 0
 
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 2424cc9..6a3875f 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1227,26 +1227,32 @@
 
 static int __assign_irq_vector(int irq)
 {
-	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
-	int vector;
+	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	int vector, offset, i;
 
 	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
 
 	if (irq_vector[irq] > 0)
 		return irq_vector[irq];
 
-	current_vector += 8;
-	if (current_vector == SYSCALL_VECTOR)
-		current_vector += 8;
-
-	if (current_vector >= FIRST_SYSTEM_VECTOR) {
-		offset++;
-		if (!(offset % 8))
-			return -ENOSPC;
-		current_vector = FIRST_DEVICE_VECTOR + offset;
-	}
-
 	vector = current_vector;
+	offset = current_offset;
+next:
+	vector += 8;
+	if (vector >= FIRST_SYSTEM_VECTOR) {
+		offset = (offset + 1) % 8;
+		vector = FIRST_DEVICE_VECTOR + offset;
+	}
+	if (vector == current_vector)
+		return -ENOSPC;
+	if (vector == SYSCALL_VECTOR)
+		goto next;
+	for (i = 0; i < NR_IRQ_VECTORS; i++)
+		if (irq_vector[i] == vector)
+			goto next;
+
+	current_vector = vector;
+	current_offset = offset;
 	irq_vector[irq] = vector;
 
 	return vector;
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 2ce6722..49bff35 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -36,7 +36,7 @@
 
 /* Have we found an MP table */
 int smp_found_config;
-unsigned int __initdata maxcpus = NR_CPUS;
+unsigned int __cpuinitdata maxcpus = NR_CPUS;
 
 /*
  * Various Linux-internal data structures created from the
@@ -102,9 +102,9 @@
  */
 
 static int mpc_record; 
-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
+static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
 
-static void __devinit MP_processor_info (struct mpc_config_processor *m)
+static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
 {
  	int ver, apicid;
 	physid_mask_t phys_cpu;
@@ -822,7 +822,7 @@
 	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
 }
 
-void __devinit mp_register_lapic (u8 id, u8 enabled)
+void __cpuinit mp_register_lapic (u8 id, u8 enabled)
 {
 	struct mpc_config_processor processor;
 	int boot_cpu = 0;
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index a5e34d6..1a6f8bb 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -310,13 +310,7 @@
 
 	if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
 		return 0;
-	/*
-	 * If any other x86 CPU has a local APIC, then
-	 * please test the NMI stuff there and send me the
-	 * missing bits. Right now Intel P6/P4 and AMD K7 only.
-	 */
-	if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
-		return 0;  /* no lapic support */
+
 	nmi_watchdog = nmi;
 	return 1;
 }
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
index 3dceab5..e55fd05 100644
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -566,4 +566,11 @@
 	.irq_enable_sysexit = native_irq_enable_sysexit,
 	.iret = native_iret,
 };
-EXPORT_SYMBOL(paravirt_ops);
+
+/*
+ * NOTE: CONFIG_PARAVIRT is experimental and the paravirt_ops
+ * semantics are subject to change. Hence we only do this
+ * internal-only export of this, until it gets sorted out and
+ * all lowlevel CPU ops used by modules are separately exported.
+ */
+EXPORT_SYMBOL_GPL(paravirt_ops);
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 6f6cb7b..4b31ad7 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -77,7 +77,7 @@
 extern struct resource data_resource;
 
 /* cpu data as detected by the assembly code in head.S */
-struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 /* common cpu data for all cpus */
 struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 EXPORT_SYMBOL(boot_cpu_data);
@@ -495,7 +495,7 @@
 #endif
 
 /* Overridden in paravirt.c if CONFIG_PARAVIRT */
-char * __attribute__((weak)) memory_setup(void)
+char * __init __attribute__((weak)) memory_setup(void)
 {
 	return machine_specific_memory_setup();
 }
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 300d9b3..8c6c8c5 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -159,7 +159,7 @@
  * a given CPU
  */
 
-static void __devinit smp_store_cpu_info(int id)
+static void __cpuinit smp_store_cpu_info(int id)
 {
 	struct cpuinfo_x86 *c = cpu_data + id;
 
@@ -364,7 +364,7 @@
 
 static atomic_t init_deasserted;
 
-static void __devinit smp_callin(void)
+static void __cpuinit smp_callin(void)
 {
 	int cpuid, phys_id;
 	unsigned long timeout;
@@ -538,7 +538,7 @@
 /*
  * Activate a secondary processor.
  */
-static void __devinit start_secondary(void *unused)
+static void __cpuinit start_secondary(void *unused)
 {
 	/*
 	 * Don't put *anything* before secondary_cpu_init(), SMP
@@ -596,6 +596,12 @@
 void __devinit initialize_secondary(void)
 {
 	/*
+	 * switch to the per CPU GDT we already set up
+	 * in do_boot_cpu()
+	 */
+	cpu_set_gdt(current_thread_info()->cpu);
+
+	/*
 	 * We don't actually need to load the full TSS,
 	 * basically just the stack pointer and the eip.
 	 */
@@ -931,7 +937,7 @@
 #define alloc_idle_task(cpu) fork_idle(cpu)
 #endif
 
-static int __devinit do_boot_cpu(int apicid, int cpu)
+static int __cpuinit do_boot_cpu(int apicid, int cpu)
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
  * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -972,9 +978,6 @@
 	/* Stack for startup_32 can be just as for start_secondary onwards */
 	stack_start.esp = (void *) idle->thread.esp;
 
-	start_pda = cpu_pda(cpu);
-	cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu);
-
 	irq_ctx_init(cpu);
 
 	x86_cpu_to_apicid[cpu] = apicid;
@@ -1432,7 +1435,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 #ifdef CONFIG_HOTPLUG_CPU
 	int ret=0;
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 7de9117..5da7442 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -79,11 +79,6 @@
 #ifdef CONFIG_COMPAT_VDSO
 	__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
 	printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
-#else
-	/*
-	 * In the non-compat case the ELF coredumping code needs the fixmap:
-	 */
-	__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_KERNEL_RO);
 #endif
 
 	if (!boot_cpu_has(X86_FEATURE_SEP)) {
@@ -100,6 +95,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_COMPAT_VDSO
 static struct page *syscall_nopage(struct vm_area_struct *vma,
 				unsigned long adr, int *type)
 {
@@ -146,6 +142,13 @@
 	vma->vm_end = addr + PAGE_SIZE;
 	/* MAYWRITE to allow gdb to COW and set breakpoints */
 	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	vma->vm_flags |= VM_ALWAYSDUMP;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
 	vma->vm_ops = &syscall_vm_ops;
@@ -187,3 +190,4 @@
 {
 	return 0;
 }
+#endif
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index 1bbe45d..2cfc7b0 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -24,7 +24,7 @@
  */
 unsigned int tsc_khz;
 
-int tsc_disable __cpuinitdata = 0;
+int tsc_disable;
 
 #ifdef CONFIG_X86_TSC
 static int __init tsc_setup(char *str)
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c
index c511705..cc2f519 100644
--- a/arch/i386/mach-default/setup.c
+++ b/arch/i386/mach-default/setup.c
@@ -102,7 +102,7 @@
  *	along the MCA bus.  Use this to hook into that chain if you will need
  *	it.
  **/
-void __init mca_nmi_hook(void)
+void mca_nmi_hook(void)
 {
 	/* If I recall correctly, there's a whole bunch of other things that
 	 * we can do to check for NMI problems, but that's all I know about
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
index 33d9f93..8a210fa 100644
--- a/arch/i386/mach-generic/bigsmp.c
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -45,7 +45,7 @@
 };
 
 
-static __init int probe_bigsmp(void)
+static int probe_bigsmp(void)
 { 
 	if (def_to_bigsmp)
         	dmi_bigsmp = 1;
diff --git a/arch/i386/mach-generic/default.c b/arch/i386/mach-generic/default.c
index 96c1982..8685208 100644
--- a/arch/i386/mach-generic/default.c
+++ b/arch/i386/mach-generic/default.c
@@ -18,7 +18,7 @@
 #include <asm/mach-default/mach_mpparse.h>
 
 /* should be called last. */
-static __init int probe_default(void)
+static int probe_default(void)
 { 
 	return 1;
 } 
diff --git a/arch/i386/mach-generic/es7000.c b/arch/i386/mach-generic/es7000.c
index aa144d8..b8963a5 100644
--- a/arch/i386/mach-generic/es7000.c
+++ b/arch/i386/mach-generic/es7000.c
@@ -19,7 +19,7 @@
 #include <asm/mach-es7000/mach_mpparse.h>
 #include <asm/mach-es7000/mach_wakecpu.h>
 
-static __init int probe_es7000(void)
+static int probe_es7000(void)
 {
 	/* probed later in mptable/ACPI hooks */
 	return 0;
diff --git a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c
index f7e5d66..74883cc 100644
--- a/arch/i386/mach-generic/summit.c
+++ b/arch/i386/mach-generic/summit.c
@@ -18,7 +18,7 @@
 #include <asm/mach-summit/mach_ipi.h>
 #include <asm/mach-summit/mach_mpparse.h>
 
-static __init int probe_summit(void)
+static int probe_summit(void)
 { 
 	/* probed later in mptable/ACPI hooks */
 	return 0;
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 55428e6..74aeedf 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -773,6 +773,12 @@
 #endif
 
 	/*
+	 * switch to the per CPU GDT we already set up
+	 * in do_boot_cpu()
+	 */
+	cpu_set_gdt(current_thread_info()->cpu);
+
+	/*
 	 * We don't actually need to load the full TSS,
 	 * basically just the stack pointer and the eip.
 	 */
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 60a7e57..c5c5ea7 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -283,7 +283,7 @@
 		SetPageReserved(page);
 }
 
-static int add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long pfn)
 {
 	free_new_highpage(page);
 	totalram_pages++;
@@ -300,7 +300,7 @@
  * has been added dynamically that would be
  * onlined here is in HIGHMEM
  */
-void online_page(struct page *page)
+void __meminit online_page(struct page *page)
 {
 	ClearPageReserved(page);
 	add_one_highpage_hotplug(page, page_to_pfn(page));
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index fcacfe2..f1d2899 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -11,6 +11,8 @@
 
 config IA64
 	bool
+	select PCI if (!IA64_HP_SIM)
+	select ACPI if (!IA64_HP_SIM)
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
@@ -28,7 +30,6 @@
 
 config SWIOTLB
        bool
-       default y
 
 config RWSEM_XCHGADD_ALGORITHM
 	bool
@@ -84,10 +85,9 @@
 
 config IA64_GENERIC
 	bool "generic"
-	select ACPI
-	select PCI
 	select NUMA
 	select ACPI_NUMA
+	select SWIOTLB
 	help
 	  This selects the system type of your hardware.  A "generic" kernel
 	  will run on any supported IA-64 system.  However, if you configure
@@ -104,6 +104,7 @@
 
 config IA64_DIG
 	bool "DIG-compliant"
+	select SWIOTLB
 
 config IA64_HP_ZX1
 	bool "HP-zx1/sx1000"
@@ -113,6 +114,7 @@
 
 config IA64_HP_ZX1_SWIOTLB
 	bool "HP-zx1/sx1000 with software I/O TLB"
+	select SWIOTLB
 	help
 	  Build a kernel that runs on HP zx1 and sx1000 systems even when they
 	  have broken PCI devices which cannot DMA to full 32 bits.  Apart
@@ -131,6 +133,7 @@
 
 config IA64_HP_SIM
 	bool "Ski-simulator"
+	select SWIOTLB
 
 endchoice
 
diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index a5a5637..2153bca 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -192,3 +192,7 @@
 EXPORT_SYMBOL(hwsw_dma_supported);
 EXPORT_SYMBOL(hwsw_alloc_coherent);
 EXPORT_SYMBOL(hwsw_free_coherent);
+EXPORT_SYMBOL(hwsw_sync_single_for_cpu);
+EXPORT_SYMBOL(hwsw_sync_single_for_device);
+EXPORT_SYMBOL(hwsw_sync_sg_for_cpu);
+EXPORT_SYMBOL(hwsw_sync_sg_for_device);
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 73ef4a85..29f05d4 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -590,6 +590,9 @@
  */
 int acpi_register_gsi(u32 gsi, int triggering, int polarity)
 {
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+		return gsi;
+
 	if (has_8259 && gsi < 16)
 		return isa_irq_to_vector(gsi);
 
@@ -606,6 +609,9 @@
 
 void acpi_unregister_gsi(u32 gsi)
 {
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+		return;
+
 	iosapic_unregister_intr(gsi);
 }
 
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
index bc2f64d..9d92097 100644
--- a/arch/ia64/kernel/crash.c
+++ b/arch/ia64/kernel/crash.c
@@ -79,6 +79,7 @@
 	final_note(buf);
 }
 
+#ifdef CONFIG_SMP
 static int
 kdump_wait_cpu_freeze(void)
 {
@@ -91,6 +92,7 @@
 	}
 	return 1;
 }
+#endif
 
 void
 machine_crash_shutdown(struct pt_regs *pt)
@@ -116,6 +118,11 @@
 static void
 machine_kdump_on_init(void)
 {
+	if (!ia64_kimage) {
+		printk(KERN_NOTICE "machine_kdump_on_init(): "
+				"kdump not configured\n");
+		return;
+	}
 	local_irq_disable();
 	kexec_disable_iosapic();
 	machine_kexec(ia64_kimage);
@@ -132,11 +139,12 @@
 	atomic_inc(&kdump_cpu_freezed);
 	kdump_status[cpuid] = 1;
 	mb();
-	if (cpuid == 0) {
-		for (;;)
-			cpu_relax();
-	} else
+#ifdef CONFIG_HOTPLUG_CPU
+	if (cpuid != 0)
 		ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]);
+#endif
+	for (;;)
+		cpu_relax();
 }
 
 static int
diff --git a/arch/ia64/kernel/crash_dump.c b/arch/ia64/kernel/crash_dump.c
index 83b8c91..da60e90 100644
--- a/arch/ia64/kernel/crash_dump.c
+++ b/arch/ia64/kernel/crash_dump.c
@@ -9,7 +9,8 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 
-#include <linux/uaccess.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
 
 /**
  * copy_oldmem_page - copy one page from "oldmem"
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 0b25a7d..6c03928 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -380,7 +380,7 @@
 #endif
 		return __va(md->phys_addr);
 	}
-	printk(KERN_WARNING "%s: no PAL-code memory-descriptor found",
+	printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n",
 	       __FUNCTION__);
 	return NULL;
 }
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 15234ed..e7873ee 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1610,5 +1610,7 @@
 	data8 sys_sync_file_range		// 1300
 	data8 sys_tee
 	data8 sys_vmsplice
+	data8 sys_ni_syscall			// reserved for move_pages
+	data8 sys_getcpu
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 0fc5fb7..d6aab40 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -925,6 +925,11 @@
 			/* Clear the interrupt controller descriptor */
 			idesc->chip = &no_irq_type;
 
+#ifdef CONFIG_SMP
+			/* Clear affinity */
+			cpus_setall(idesc->affinity);
+#endif
+
 			/* Clear the interrupt information */
 			memset(&iosapic_intr_info[vector], 0,
 			       sizeof(struct iosapic_intr_info));
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 54d55e4..ce49c85 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -122,6 +122,9 @@
 	for (irq=0; irq < NR_IRQS; irq++) {
 		desc = irq_desc + irq;
 
+		if (desc->status == IRQ_DISABLED)
+			continue;
+
 		/*
 		 * No handling for now.
 		 * TBD: Implement a disable function so we can now
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index e2ccc9f..4f0f3b8 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -14,6 +14,7 @@
 #include <linux/kexec.h>
 #include <linux/cpu.h>
 #include <linux/irq.h>
+#include <linux/efi.h>
 #include <asm/mmu_context.h>
 #include <asm/setup.h>
 #include <asm/delay.h>
@@ -68,22 +69,10 @@
 {
 }
 
-void machine_shutdown(void)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		if (cpu != smp_processor_id())
-			cpu_down(cpu);
-	}
-	kexec_disable_iosapic();
-}
-
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-extern void *efi_get_pal_addr(void);
 static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
 {
 	struct kimage *image = arg;
@@ -93,6 +82,7 @@
 	unsigned long vector;
 	int ii;
 
+	BUG_ON(!image);
 	if (image->type == KEXEC_TYPE_CRASH) {
 		crash_save_this_cpu();
 		current->thread.ksp = (__u64)info->sw - 16;
@@ -131,6 +121,7 @@
 
 void machine_kexec(struct kimage *image)
 {
+	BUG_ON(!image);
 	unw_init_running(ia64_machine_kexec, image);
 	for(;;);
 }
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 17685ab..ae96d41 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -34,6 +34,7 @@
 #include <asm/ia32.h>
 #include <asm/irq.h>
 #include <asm/kdebug.h>
+#include <asm/kexec.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sal.h>
@@ -803,6 +804,21 @@
 		ia64_pal_halt(min_power_state);
 }
 
+void machine_shutdown(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		if (cpu != smp_processor_id())
+			cpu_down(cpu);
+	}
+#endif
+#ifdef CONFIG_KEXEC
+	kexec_disable_iosapic();
+#endif
+}
+
 void
 machine_restart (char *restart_cmd)
 {
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index aa705e4..3f89187 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -607,7 +607,7 @@
 	 */
  	list_for_each_safe(this, next, &current->children) {
 		p = list_entry(this, struct task_struct, sibling);
-		if (p->mm != mm)
+		if (p->tgid != child->tgid)
 			continue;
 		if (thread_matches(p, addr)) {
 			child = p;
@@ -1405,6 +1405,7 @@
 	struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
 
 	/* make sure the single step/taken-branch trap bits are not set: */
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	child_psr->ss = 0;
 	child_psr->tb = 0;
 }
@@ -1525,6 +1526,7 @@
 		 * Make sure the single step/taken-branch trap bits
 		 * are not set:
 		 */
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		ia64_psr(pt)->ss = 0;
 		ia64_psr(pt)->tb = 0;
 
@@ -1556,6 +1558,7 @@
 			goto out_tsk;
 
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		set_tsk_thread_flag(child, TIF_SINGLESTEP);
 		if (request == PTRACE_SINGLESTEP) {
 			ia64_psr(pt)->ss = 1;
 		} else {
@@ -1595,13 +1598,9 @@
 }
 
 
-void
+static void
 syscall_trace (void)
 {
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
-	if (!(current->ptrace & PT_PTRACED))
-		return;
 	/*
 	 * The 0x80 provides a way for the tracing parent to
 	 * distinguish between a syscall stop and SIGTRAP delivery.
@@ -1664,7 +1663,8 @@
 		audit_syscall_exit(success, result);
 	}
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	if ((test_thread_flag(TIF_SYSCALL_TRACE)
+	    || test_thread_flag(TIF_SINGLESTEP))
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace();
 }
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index ad567b8d..83c2629 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -569,34 +569,31 @@
 		{ 1UL << 1, "spontaneous deferral"},
 		{ 1UL << 2, "16-byte atomic ops" }
 	};
-	char features[128], *cp, sep;
+	char features[128], *cp, *sep;
 	struct cpuinfo_ia64 *c = v;
 	unsigned long mask;
 	unsigned long proc_freq;
-	int i;
+	int i, size;
 
 	mask = c->features;
 
 	/* build the feature string: */
-	memcpy(features, " standard", 10);
+	memcpy(features, "standard", 9);
 	cp = features;
-	sep = 0;
-	for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) {
+	size = sizeof(features);
+	sep = "";
+	for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) {
 		if (mask & feature_bits[i].mask) {
-			if (sep)
-				*cp++ = sep;
-			sep = ',';
-			*cp++ = ' ';
-			strcpy(cp, feature_bits[i].feature_name);
-			cp += strlen(feature_bits[i].feature_name);
+			cp += snprintf(cp, size, "%s%s", sep,
+				       feature_bits[i].feature_name),
+			sep = ", ";
 			mask &= ~feature_bits[i].mask;
+			size = sizeof(features) - (cp - features);
 		}
 	}
-	if (mask) {
-		/* print unknown features as a hex value: */
-		if (sep)
-			*cp++ = sep;
-		sprintf(cp, " 0x%lx", mask);
+	if (mask && size > 1) {
+		/* print unknown features as a hex value */
+		snprintf(cp, size, "%s0x%lx", sep, mask);
 	}
 
 	proc_freq = cpufreq_quick_get(cpunum);
@@ -612,7 +609,7 @@
 		   "model name : %s\n"
 		   "revision   : %u\n"
 		   "archrev    : %u\n"
-		   "features   :%s\n"	/* don't change this---it _is_ right! */
+		   "features   : %s\n"
 		   "cpu number : %lu\n"
 		   "cpu regs   : %u\n"
 		   "cpu MHz    : %lu.%06lu\n"
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index d6083a0..8f3d006 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -157,6 +157,7 @@
 	}
 #endif
 
+  . = ALIGN(8);
    __con_initcall_start = .;
   .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET)
 	{ *(.con_initcall.init) }
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 1e79551..63e6d49 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -30,47 +30,69 @@
 #endif
 
 /**
- * show_mem - display a memory statistics summary
+ * show_mem - give short summary of memory stats
  *
- * Just walks the pages in the system and describes where they're allocated.
+ * Shows a simple page count of reserved and used pages in the system.
+ * For discontig machines, it does this on a per-pgdat basis.
  */
-void
-show_mem (void)
+void show_mem(void)
 {
-	int i, total = 0, reserved = 0;
-	int shared = 0, cached = 0;
+	int i, total_reserved = 0;
+	int total_shared = 0, total_cached = 0;
+	unsigned long total_present = 0;
+	pg_data_t *pgdat;
 
 	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas();
-
 	printk(KERN_INFO "Free swap:       %6ldkB\n",
 	       nr_swap_pages<<(PAGE_SHIFT-10));
-	i = max_mapnr;
-	for (i = 0; i < max_mapnr; i++) {
-		if (!pfn_valid(i)) {
+	printk(KERN_INFO "Node memory in pages:\n");
+	for_each_online_pgdat(pgdat) {
+		unsigned long present;
+		unsigned long flags;
+		int shared = 0, cached = 0, reserved = 0;
+
+		pgdat_resize_lock(pgdat, &flags);
+		present = pgdat->node_present_pages;
+		for(i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page;
+			if (pfn_valid(pgdat->node_start_pfn + i))
+				page = pfn_to_page(pgdat->node_start_pfn + i);
+			else {
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-			if (max_gap < LARGE_GAP)
-				continue;
-			i = vmemmap_find_next_valid_pfn(0, i) - 1;
+				if (max_gap < LARGE_GAP)
+					continue;
 #endif
-			continue;
+				i = vmemmap_find_next_valid_pfn(pgdat->node_id,
+					 i) - 1;
+				continue;
+			}
+			if (PageReserved(page))
+				reserved++;
+			else if (PageSwapCache(page))
+				cached++;
+			else if (page_count(page))
+				shared += page_count(page)-1;
 		}
-		total++;
-		if (PageReserved(mem_map+i))
-			reserved++;
-		else if (PageSwapCache(mem_map+i))
-			cached++;
-		else if (page_count(mem_map + i))
-			shared += page_count(mem_map + i) - 1;
+		pgdat_resize_unlock(pgdat, &flags);
+		total_present += present;
+		total_reserved += reserved;
+		total_cached += cached;
+		total_shared += shared;
+		printk(KERN_INFO "Node %4d:  RAM: %11ld, rsvd: %8d, "
+		       "shrd: %10d, swpd: %10d\n", pgdat->node_id,
+		       present, reserved, shared, cached);
 	}
-	printk(KERN_INFO "%d pages of RAM\n", total);
-	printk(KERN_INFO "%d reserved pages\n", reserved);
-	printk(KERN_INFO "%d pages shared\n", shared);
-	printk(KERN_INFO "%d pages swap cached\n", cached);
-	printk(KERN_INFO "%ld pages in page table cache\n",
+	printk(KERN_INFO "%ld pages of RAM\n", total_present);
+	printk(KERN_INFO "%d reserved pages\n", total_reserved);
+	printk(KERN_INFO "%d pages shared\n", total_shared);
+	printk(KERN_INFO "%d pages swap cached\n", total_cached);
+	printk(KERN_INFO "Total of %ld pages in page table cache\n",
 	       pgtable_quicklist_total_size());
+	printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
 }
 
+
 /* physical address where the bootmem map is located */
 unsigned long bootmap_start;
 
@@ -177,7 +199,7 @@
 
 #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. */
+	 * size before original memory map is reset. */
 	saved_max_pfn = max_pfn;
 #endif
 }
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 96722cb..6eae596 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -412,37 +412,6 @@
 	return;
 }
 
-#ifdef CONFIG_SPARSEMEM
-/**
- * register_sparse_mem - notify SPARSEMEM that this memory range exists.
- * @start: physical start of range
- * @end: physical end of range
- * @arg: unused
- *
- * Simply calls SPARSEMEM to register memory section(s).
- */
-static int __init register_sparse_mem(unsigned long start, unsigned long end,
-	void *arg)
-{
-	int nid;
-
-	start = __pa(start) >> PAGE_SHIFT;
-	end = __pa(end) >> PAGE_SHIFT;
-	nid = early_pfn_to_nid(start);
-	memory_present(nid, start, end);
-
-	return 0;
-}
-
-static void __init arch_sparse_init(void)
-{
-	efi_memmap_walk(register_sparse_mem, NULL);
-	sparse_init();
-}
-#else
-#define arch_sparse_init() do {} while (0)
-#endif
-
 /**
  * find_memory - walk the EFI memory map and setup the bootmem allocator
  *
@@ -473,6 +442,9 @@
 			node_clear(node, memory_less_mask);
 			mem_data[node].min_pfn = ~0UL;
 		}
+
+	efi_memmap_walk(register_active_ranges, NULL);
+
 	/*
 	 * Initialize the boot memory maps in reverse order since that's
 	 * what the bootmem allocator expects
@@ -506,6 +478,12 @@
 	max_pfn = max_low_pfn;
 
 	find_initrd();
+
+#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 = max_pfn;
+#endif
 }
 
 #ifdef CONFIG_SMP
@@ -654,7 +632,6 @@
 {
 	unsigned long end = start + len;
 
-	add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT);
 	mem_data[node].num_physpages += len >> PAGE_SHIFT;
 	if (start <= __pa(MAX_DMA_ADDRESS))
 		mem_data[node].num_dma_physpages +=
@@ -686,10 +663,11 @@
 
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
-	arch_sparse_init();
-
 	efi_memmap_walk(filter_rsvd_memory, count_node_pages);
 
+	sparse_memory_present_with_active_regions(MAX_NUMNODES);
+	sparse_init();
+
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 	vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
 		sizeof(struct page));
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 1a3d8a2..faaca21 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -19,6 +19,7 @@
 #include <linux/swap.h>
 #include <linux/proc_fs.h>
 #include <linux/bitops.h>
+#include <linux/kexec.h>
 
 #include <asm/a.out.h>
 #include <asm/dma.h>
@@ -128,6 +129,25 @@
 	set_bit(PG_arch_1, &page->flags);	/* mark page as clean */
 }
 
+/*
+ * Since DMA is i-cache coherent, any (complete) pages that were written via
+ * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
+ * flush them when they get mapped into an executable vm-area.
+ */
+void
+dma_mark_clean(void *addr, size_t size)
+{
+	unsigned long pg_addr, end;
+
+	pg_addr = PAGE_ALIGN((unsigned long) addr);
+	end = (unsigned long) addr + size;
+	while (pg_addr + PAGE_SIZE <= end) {
+		struct page *page = virt_to_page(pg_addr);
+		set_bit(PG_arch_1, &page->flags);
+		pg_addr += PAGE_SIZE;
+	}
+}
+
 inline void
 ia64_set_rbs_bot (void)
 {
@@ -543,7 +563,8 @@
 
 	if (map_start < map_end)
 		memmap_init_zone((unsigned long)(map_end - map_start),
-				 args->nid, args->zone, page_to_pfn(map_start));
+				 args->nid, args->zone, page_to_pfn(map_start),
+				 MEMMAP_EARLY);
 	return 0;
 }
 
@@ -552,7 +573,7 @@
 	     unsigned long start_pfn)
 {
 	if (!vmem_map)
-		memmap_init_zone(size, nid, zone, start_pfn);
+		memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY);
 	else {
 		struct page *start;
 		struct memmap_init_callback_data args;
@@ -594,13 +615,27 @@
 	return 0;
 }
 
+#endif /* CONFIG_VIRTUAL_MEM_MAP */
+
 int __init
 register_active_ranges(u64 start, u64 end, void *arg)
 {
-	add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT);
+	int nid = paddr_to_nid(__pa(start));
+
+	if (nid < 0)
+		nid = 0;
+#ifdef CONFIG_KEXEC
+	if (start > crashk_res.start && start < crashk_res.end)
+		start = crashk_res.end;
+	if (end > crashk_res.start && end < crashk_res.end)
+		end = crashk_res.start;
+#endif
+
+	if (start < end)
+		add_active_range(nid, __pa(start) >> PAGE_SHIFT,
+			__pa(end) >> PAGE_SHIFT);
 	return 0;
 }
-#endif /* CONFIG_VIRTUAL_MEM_MAP */
 
 static int __init
 count_reserved_pages (u64 start, u64 end, void *arg)
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index abca6bd..fcf7f93 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/types.h>
@@ -38,12 +38,20 @@
 			(u64) nasid, 0, 0, 0, 0, 0, 0);
 
 		if ((int)ret_stuff.v0)
-			panic("hubii_eint_handler(): Fatal TIO Error");
+			panic("%s: Fatal %s Error", __FUNCTION__,
+				((nasid & 1) ? "TIO" : "HUBII"));
 
 		if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
 			(void)hubiio_crb_error_handler(hubdev_info);
-	} else 
-		bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
+	} else
+		if (nasid & 1) {	/* TIO errors */
+			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
+				(u64) nasid, 0, 0, 0, 0, 0, 0);
+
+			if ((int)ret_stuff.v0)
+				panic("%s: Fatal TIO Error", __FUNCTION__);
+		} else
+			bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
index 99d7f27..cb96b4e 100644
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -223,6 +223,9 @@
 	u64 result;
 	s64 status;
 
+	/* SN Altix does not follow the IOSAPIC IRQ routing model */
+	acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
+
 	acpi_bus_register_driver(&acpi_sn_hubdev_driver);
 	status = sal_ioif_init(&result);
 	if (status || result)
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index fa78656..48d376f 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -351,7 +351,7 @@
 	}
 }
 
-int __devinit __cpu_up(unsigned int cpu_id)
+int __cpuinit __cpu_up(unsigned int cpu_id)
 {
 	int timeout;
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fd2ff06..44a0224 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -575,6 +575,7 @@
 	select DMA_IP27
 	select EARLY_PRINTK
 	select HW_HAS_PCI
+	select NR_CPUS_DEFAULT_64
 	select PCI_DOMAINS
 	select SYS_HAS_CPU_R10000
 	select SYS_SUPPORTS_64BIT_KERNEL
@@ -612,6 +613,7 @@
 	bool "Sibyte BCM91480B-BigSur"
 	select BOOT_ELF32
 	select DMA_COHERENT
+	select NR_CPUS_DEFAULT_4
 	select PCI_DOMAINS
 	select SIBYTE_BCM1x80
 	select SWAP_IO_SPACE
@@ -623,6 +625,7 @@
 	bool "Sibyte BCM91250A-SWARM"
 	select BOOT_ELF32
 	select DMA_COHERENT
+	select NR_CPUS_DEFAULT_2
 	select SIBYTE_SB1250
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_SB1
@@ -635,6 +638,7 @@
 	depends on EXPERIMENTAL
 	select BOOT_ELF32
 	select DMA_COHERENT
+	select NR_CPUS_DEFAULT_2
 	select SIBYTE_SB1250
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_SB1
@@ -668,6 +672,7 @@
 	depends on EXPERIMENTAL
 	select BOOT_ELF32
 	select DMA_COHERENT
+	select NR_CPUS_DEFAULT_2
 	select SIBYTE_SB1250
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_SB1
@@ -680,6 +685,7 @@
 	depends on EXPERIMENTAL
 	select BOOT_ELF32
 	select DMA_COHERENT
+	select NR_CPUS_DEFAULT_2
 	select SIBYTE_SB1250
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_SB1
@@ -790,23 +796,6 @@
 
 endchoice
 
-config KEXEC
- 	bool "Kexec system call (EXPERIMENTAL)"
- 	depends on EXPERIMENTAL
- 	help
- 	  kexec is a system call that implements the ability to shutdown your
- 	  current kernel, and to start another kernel.  It is like a reboot
- 	  but it is indepedent of the system firmware.   And like a reboot
- 	  you can start any kernel with it, not just Linux.
-
- 	  The name comes from the similiarity to the exec system call.
-
- 	  It is an ongoing process to be certain the hardware in a machine
- 	  is properly shutdown, so do not be surprised if this code does not
- 	  initially work for you.  It may help to enable device hotplugging
- 	  support.  As of this writing the exact hardware interface is
- 	  strongly in flux, so no good recommendation can be made.
-
 source "arch/mips/ddb5xxx/Kconfig"
 source "arch/mips/gt64120/ev64120/Kconfig"
 source "arch/mips/jazz/Kconfig"
@@ -1541,6 +1530,8 @@
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_SRS
 	select MIPS_MT
+	select NR_CPUS_DEFAULT_2
+	select NR_CPUS_DEFAULT_8
 	select SMP
 	select SYS_SUPPORTS_SMP
 	help
@@ -1568,6 +1559,20 @@
 	depends on MIPS_MT
 	default y
 
+config MIPS_MT_SMTC_INSTANT_REPLAY
+	bool "Low-latency Dispatch of Deferred SMTC IPIs"
+	depends on MIPS_MT_SMTC
+	default y
+	help
+	  SMTC pseudo-interrupts between TCs are deferred and queued
+	  if the target TC is interrupt-inhibited (IXMT). In the first
+	  SMTC prototypes, these queued IPIs were serviced on return
+	  to user mode, or on entry into the kernel idle loop. The
+	  INSTANT_REPLAY option dispatches them as part of local_irq_restore()
+	  processing, which adds runtime overhead (hence the option to turn
+	  it off), but ensures that IPIs are handled promptly even under
+	  heavy I/O interrupt load.
+
 config MIPS_VPE_LOADER_TOM
 	bool "Load VPE program into memory hidden from linux"
 	depends on MIPS_VPE_LOADER
@@ -1742,13 +1747,34 @@
 config SYS_SUPPORTS_SMP
 	bool
 
+config NR_CPUS_DEFAULT_2
+	bool
+
+config NR_CPUS_DEFAULT_4
+	bool
+
+config NR_CPUS_DEFAULT_8
+	bool
+
+config NR_CPUS_DEFAULT_16
+	bool
+
+config NR_CPUS_DEFAULT_32
+	bool
+
+config NR_CPUS_DEFAULT_64
+	bool
+
 config NR_CPUS
 	int "Maximum number of CPUs (2-64)"
 	range 2 64
 	depends on SMP
-	default "64" if SGI_IP27
-	default "2"
-	default "8" if MIPS_MT_SMTC
+	default "2" if NR_CPUS_DEFAULT_2
+	default "4" if NR_CPUS_DEFAULT_4
+	default "8" if NR_CPUS_DEFAULT_8
+	default "16" if NR_CPUS_DEFAULT_16
+	default "32" if NR_CPUS_DEFAULT_32
+	default "64" if NR_CPUS_DEFAULT_64
 	help
 	  This allows you to specify the maximum number of CPUs which this
 	  kernel will support.  The maximum supported value is 32 for 32-bit
@@ -1845,6 +1871,40 @@
 	  This will result in additional memory usage, so it is not
 	  recommended for normal users.
 
+config KEXEC
+	bool "Kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  kexec is a system call that implements the ability to shutdown your
+	  current kernel, and to start another kernel.  It is like a reboot
+	  but it is indepedent of the system firmware.   And like a reboot
+	  you can start any kernel with it, not just Linux.
+
+	  The name comes from the similiarity to the exec system call.
+
+	  It is an ongoing process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS && BROKEN
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 config RWSEM_GENERIC_SPINLOCK
@@ -2011,23 +2071,6 @@
 	bool
 	default y if MIPS32_O32 || MIPS32_N32
 
-config SECCOMP
-	bool "Enable seccomp to safely compute untrusted bytecode"
-	depends on PROC_FS && BROKEN
-	default y
-	help
-	  This kernel feature is useful for number crunching applications
-	  that may need to compute untrusted bytecode during their
-	  execution. By using pipes or other transports made available to
-	  the process as file descriptors supporting the read/write
-	  syscalls, it's possible to isolate those applications in
-	  their own address space using seccomp. Once seccomp is
-	  enabled via /proc/<pid>/seccomp, it cannot be disabled
-	  and the task is only allowed to execute a few safe syscalls
-	  defined by each seccomp mode.
-
-	  If unsure, say Y. Only embedded should say N here.
-
 config PM
 	bool "Power Management support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && SOC_AU1X00
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 5d6afb5..9351f1c 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -22,10 +22,10 @@
 	string "Default kernel command string"
 	default ""
 	help
-          On some platforms, there is currently no way for the boot loader to
-          pass arguments to the kernel. For these platforms, you can supply
-          some command-line options at build time by entering them here.  In
-          other cases you can specify kernel args so that you don't have
+	  On some platforms, there is currently no way for the boot loader to
+	  pass arguments to the kernel. For these platforms, you can supply
+	  some command-line options at build time by entering them here.  In
+	  other cases you can specify kernel args so that you don't have
 	  to set them up in board prom initialization routines.
 
 config DEBUG_STACK_USAGE
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index d1b026a..c68b5d3 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -623,7 +623,7 @@
 
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \
-	egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \
+	egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
 	sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
 ifdef CONFIG_64BIT
 CHECKFLAGS		+= -m64
diff --git a/arch/mips/arc/identify.c b/arch/mips/arc/identify.c
index 3ba7c47..4b90736 100644
--- a/arch/mips/arc/identify.c
+++ b/arch/mips/arc/identify.c
@@ -77,7 +77,7 @@
 {
 	int i;
 
-	for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) {
+	for (i = 0; i < ARRAY_SIZE(mach_table); i++) {
 		if (!strcmp(s, mach_table[i].arcname))
 			return &mach_table[i];
 	}
diff --git a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c
index 8a9ef58..456cb81a 100644
--- a/arch/mips/arc/memory.c
+++ b/arch/mips/arc/memory.c
@@ -141,30 +141,20 @@
 	}
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	unsigned long freed = 0;
 	unsigned long addr;
 	int i;
 
 	if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
-		return 0;
+		return;
 
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
 
 		addr = boot_mem_map.map[i].addr;
-		while (addr < boot_mem_map.map[i].addr
-			      + boot_mem_map.map[i].size) {
-			ClearPageReserved(virt_to_page(__va(addr)));
-			init_page_count(virt_to_page(__va(addr)));
-			free_page((unsigned long)__va(addr));
-			addr += PAGE_SIZE;
-			freed += PAGE_SIZE;
-		}
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
 	}
-	printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10);
-
-	return freed;
 }
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 9cf7b671..ea6e99f 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -233,7 +233,7 @@
 
 
 static struct irq_chip rise_edge_irq_type = {
-	.typename = "Au1000 Rise Edge",
+	.name = "Au1000 Rise Edge",
 	.ack = mask_and_ack_rise_edge_irq,
 	.mask = local_disable_irq,
 	.mask_ack = mask_and_ack_rise_edge_irq,
@@ -242,7 +242,7 @@
 };
 
 static struct irq_chip fall_edge_irq_type = {
-	.typename = "Au1000 Fall Edge",
+	.name = "Au1000 Fall Edge",
 	.ack = mask_and_ack_fall_edge_irq,
 	.mask = local_disable_irq,
 	.mask_ack = mask_and_ack_fall_edge_irq,
@@ -251,7 +251,7 @@
 };
 
 static struct irq_chip either_edge_irq_type = {
-	.typename = "Au1000 Rise or Fall Edge",
+	.name = "Au1000 Rise or Fall Edge",
 	.ack = mask_and_ack_either_edge_irq,
 	.mask = local_disable_irq,
 	.mask_ack = mask_and_ack_either_edge_irq,
@@ -260,7 +260,7 @@
 };
 
 static struct irq_chip level_irq_type = {
-	.typename = "Au1000 Level",
+	.name = "Au1000 Level",
 	.ack = mask_and_ack_level_irq,
 	.mask = local_disable_irq,
 	.mask_ack = mask_and_ack_level_irq,
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
index da591f6..6c25e6c 100644
--- a/arch/mips/au1000/common/pci.c
+++ b/arch/mips/au1000/common/pci.c
@@ -39,15 +39,15 @@
 
 /* TBD */
 static struct resource pci_io_resource = {
-	.start	= PCI_IO_START,
-	.end	= PCI_IO_END,
+	.start	= (resource_size_t)PCI_IO_START,
+	.end	= (resource_size_t)PCI_IO_END,
 	.name	= "PCI IO space",
 	.flags	= IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource = {
-	.start	= PCI_MEM_START,
-	.end	= PCI_MEM_END,
+	.start	= (resource_size_t)PCI_MEM_START,
+	.end	= (resource_size_t)PCI_MEM_END,
 	.name	= "PCI memory space",
 	.flags	= IORESOURCE_MEM
 };
@@ -76,13 +76,17 @@
 	}
 
 #ifdef CONFIG_DMA_NONCOHERENT
-	/*
-         *  Set the NC bit in controller for Au1500 pre-AC silicon
-	 */
-	u32 prid = read_c0_prid();
-	if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
-	       au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
-	       printk("Non-coherent PCI accesses enabled\n");
+	{
+		/*
+		 *  Set the NC bit in controller for Au1500 pre-AC silicon
+		 */
+		u32 prid = read_c0_prid();
+
+		if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
+		       au_writel((1 << 16) | au_readl(Au1500_PCI_CFG),
+			         Au1500_PCI_CFG);
+		       printk("Non-coherent PCI accesses enabled\n");
+		}
 	}
 #endif
 
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
index 6fce60a..a8637cd 100644
--- a/arch/mips/au1000/common/prom.c
+++ b/arch/mips/au1000/common/prom.c
@@ -149,9 +149,8 @@
 	return 0;
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 EXPORT_SYMBOL(prom_getcmdline);
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 919172db..13fe187 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -141,17 +141,20 @@
 /* This routine should be valid for all Au1x based boards */
 phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
 {
-	u32 start, end;
-
 	/* Don't fixup 36 bit addresses */
-	if ((phys_addr >> 32) != 0) return phys_addr;
+	if ((phys_addr >> 32) != 0)
+		return phys_addr;
 
 #ifdef CONFIG_PCI
-	start = (u32)Au1500_PCI_MEM_START;
-	end = (u32)Au1500_PCI_MEM_END;
-	/* check for pci memory window */
-	if ((phys_addr >= start) && ((phys_addr + size) < end)) {
-		return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START);
+	{
+		u32 start, end;
+
+		start = (u32)Au1500_PCI_MEM_START;
+		end = (u32)Au1500_PCI_MEM_END;
+		/* check for pci memory window */
+		if ((phys_addr >= start) && ((phys_addr + size) < end))
+			return (phys_t)
+			       ((phys_addr - start) + Au1500_PCI_MEM_START);
 	}
 #endif
 
diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c
index 2d1533f..6bc1f8e 100644
--- a/arch/mips/au1000/pb1100/board_setup.c
+++ b/arch/mips/au1000/pb1100/board_setup.c
@@ -47,8 +47,7 @@
 
 void __init board_setup(void)
 {
-	u32 pin_func;
-	u32 sys_freqctrl, sys_clksrc;
+	volatile void __iomem * base = (volatile void __iomem *) 0xac000000UL;
 
 	// set AUX clock to 12MHz * 8 = 96 MHz
 	au_writel(8, SYS_AUXPLL);
@@ -56,58 +55,62 @@
 	udelay(100);
 
 #ifdef CONFIG_USB_OHCI
-	// configure pins GPIO[14:9] as GPIO
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
+	{
+		u32 pin_func, sys_freqctrl, sys_clksrc;
 
-	/* zero and disable FREQ2 */
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+		// configure pins GPIO[14:9] as GPIO
+		pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
 
-	/* zero and disable USBH/USBD/IrDA clock */
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x0000001F;
-	au_writel(sys_clksrc, SYS_CLKSRC);
+		/* zero and disable FREQ2 */
+		sys_freqctrl = au_readl(SYS_FREQCTRL0);
+		sys_freqctrl &= ~0xFFF00000;
+		au_writel(sys_freqctrl, SYS_FREQCTRL0);
 
-	sys_freqctrl = au_readl(SYS_FREQCTRL0);
-	sys_freqctrl &= ~0xFFF00000;
+		/* zero and disable USBH/USBD/IrDA clock */
+		sys_clksrc = au_readl(SYS_CLKSRC);
+		sys_clksrc &= ~0x0000001F;
+		au_writel(sys_clksrc, SYS_CLKSRC);
 
-	sys_clksrc = au_readl(SYS_CLKSRC);
-	sys_clksrc &= ~0x0000001F;
+		sys_freqctrl = au_readl(SYS_FREQCTRL0);
+		sys_freqctrl &= ~0xFFF00000;
 
-	// FREQ2 = aux/2 = 48 MHz
-	sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
-	au_writel(sys_freqctrl, SYS_FREQCTRL0);
+		sys_clksrc = au_readl(SYS_CLKSRC);
+		sys_clksrc &= ~0x0000001F;
 
-	/*
-	 * Route 48MHz FREQ2 into USBH/USBD/IrDA
-	 */
-	sys_clksrc |= ((4<<2) | (0<<1) | 0 );
-	au_writel(sys_clksrc, SYS_CLKSRC);
+		// FREQ2 = aux/2 = 48 MHz
+		sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+		au_writel(sys_freqctrl, SYS_FREQCTRL0);
 
-	/* setup the static bus controller */
-	au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
-	au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
-	au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+		/*
+		 * Route 48MHz FREQ2 into USBH/USBD/IrDA
+		 */
+		sys_clksrc |= ((4<<2) | (0<<1) | 0 );
+		au_writel(sys_clksrc, SYS_CLKSRC);
 
-	// get USB Functionality pin state (device vs host drive pins)
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-	// 2nd USB port is USB host
-	pin_func |= 0x8000;
-	au_writel(pin_func, SYS_PINFUNC);
+		/* setup the static bus controller */
+		au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
+		au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
+		au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+
+		// get USB Functionality pin state (device vs host drive pins)
+		pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+		// 2nd USB port is USB host
+		pin_func |= 0x8000;
+		au_writel(pin_func, SYS_PINFUNC);
+	}
 #endif // defined (CONFIG_USB_OHCI)
 
 	/* Enable sys bus clock divider when IDLE state or no bus activity. */
 	au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
 
 	// Enable the RTC if not already enabled
-	if (!(readb(0xac000028) & 0x20)) {
-		writeb(readb(0xac000028) | 0x20, 0xac000028);
+	if (!(readb(base + 0x28) & 0x20)) {
+		writeb(readb(base + 0x28) | 0x20, base + 0x28);
 		au_sync();
 	}
 	// Put the clock in BCD mode
-	if (readb(0xac00002C) & 0x4) { /* reg B */
-		writeb(readb(0xac00002c) & ~0x4, 0xac00002c);
+	if (readb(base + 0x2C) & 0x4) { /* reg B */
+		writeb(readb(base + 0x2c) & ~0x4, base + 0x2c);
 		au_sync();
 	}
 }
diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
index 91983ba..b73b2d1 100644
--- a/arch/mips/au1000/pb1200/irqmap.c
+++ b/arch/mips/au1000/pb1200/irqmap.c
@@ -137,33 +137,20 @@
 	return;
 }
 
-static inline void pb1200_mask_and_ack_irq(unsigned int irq_nr)
-{
-	pb1200_disable_irq( irq_nr );
-}
-
-static void pb1200_end_irq(unsigned int irq_nr)
-{
-	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-		pb1200_enable_irq(irq_nr);
-	}
-}
-
 static struct irq_chip external_irq_type =
 {
 #ifdef CONFIG_MIPS_PB1200
-	"Pb1200 Ext",
+	.name = "Pb1200 Ext",
 #endif
 #ifdef CONFIG_MIPS_DB1200
-	"Db1200 Ext",
+	.name = "Db1200 Ext",
 #endif
-	pb1200_startup_irq,
-	pb1200_shutdown_irq,
-	pb1200_enable_irq,
-	pb1200_disable_irq,
-	pb1200_mask_and_ack_irq,
-	pb1200_end_irq,
-	NULL
+	.startup  = pb1200_startup_irq,
+	.shutdown = pb1200_shutdown_irq,
+	.ack      = pb1200_disable_irq,
+	.mask     = pb1200_disable_irq,
+	.mask_ack = pb1200_disable_irq,
+	.unmask   = pb1200_enable_irq,
 };
 
 void _board_init_irq(void)
@@ -172,7 +159,8 @@
 
 	for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
 	{
-		irq_desc[irq_nr].chip = &external_irq_type;
+		set_irq_chip_and_handler(irq_nr, &external_irq_type,
+					 handle_level_irq);
 		pb1200_disable_irq(irq_nr);
 	}
 
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
index 2e2061a..1ecab63 100644
--- a/arch/mips/basler/excite/excite_irq.c
+++ b/arch/mips/basler/excite/excite_irq.c
@@ -47,9 +47,9 @@
  */
 void __init arch_init_irq(void)
 {
-	mips_cpu_irq_init(0);
-	rm7k_cpu_irq_init(8);
-	rm9k_cpu_irq_init(12);
+	mips_cpu_irq_init();
+	rm7k_cpu_irq_init();
+	rm9k_cpu_irq_init();
 
 #ifdef CONFIG_KGDB
 	excite_kgdb_init();
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index 4c46f0e..fe93b84 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -104,7 +104,7 @@
 	GT_WRITE(GT_INTRMASK_OFS, 0);
 
 	init_i8259_irqs();				/*  0 ... 15 */
-	mips_cpu_irq_init(COBALT_CPU_IRQ);		/* 16 ... 23 */
+	mips_cpu_irq_init();		/* 16 ... 23 */
 
 	/*
 	 * Mask all cpu interrupts
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index e8f0f20..a4b69b5 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -204,8 +204,7 @@
 	add_memory_region(0x0, memsz, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
 	/* Nothing to do! */
-	return 0;
 }
diff --git a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c
index efef0f5..54a857b 100644
--- a/arch/mips/ddb5xxx/common/prom.c
+++ b/arch/mips/ddb5xxx/common/prom.c
@@ -59,9 +59,8 @@
 #endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 #if defined(CONFIG_DDB5477)
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index a8bd2e6..2b23234 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -17,6 +17,7 @@
 #include <linux/ptrace.h>
 
 #include <asm/i8259.h>
+#include <asm/irq_cpu.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/debug.h>
@@ -73,7 +74,6 @@
 }
 
 extern void vrc5477_irq_init(u32 base);
-extern void mips_cpu_irq_init(u32 base);
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
 void __init arch_init_irq(void)
@@ -125,7 +125,7 @@
 
 	/* init all controllers */
 	init_i8259_irqs();
-	mips_cpu_irq_init(CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 	vrc5477_irq_init(VRC5477_IRQ_BASE);
 
 
@@ -146,8 +146,7 @@
 	irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
 	ddb_out32(DDB_PCIINIT10, reg);
 
-	/* i8259.c set the base vector to be 0x0 */
-	return irq + I8259_IRQ_BASE;
+	return irq;
 }
 /*
  * the first level int-handler will jump here if it is a vrc5477 irq
@@ -177,7 +176,7 @@
 		/* check for i8259 interrupts */
 		if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
 			int i8259_irq = i8259_interrupt_ack();
-			do_IRQ(I8259_IRQ_BASE + i8259_irq);
+			do_IRQ(i8259_irq);
 			return;
 		}
 	}
diff --git a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
index 96249aa..98c3b15 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq_5477.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
@@ -82,7 +82,7 @@
 }
 
 struct irq_chip vrc5477_irq_controller = {
-	.typename = "vrc5477_irq",
+	.name = "vrc5477_irq",
 	.ack = vrc5477_irq_ack,
 	.mask = vrc5477_irq_disable,
 	.mask_ack = vrc5477_irq_ack,
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 4c7cb40..3acb133 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -62,7 +62,7 @@
 }
 
 static struct irq_chip ioasic_irq_type = {
-	.typename = "IO-ASIC",
+	.name = "IO-ASIC",
 	.ack = ack_ioasic_irq,
 	.mask = mask_ioasic_irq,
 	.mask_ack = ack_ioasic_irq,
@@ -84,7 +84,7 @@
 }
 
 static struct irq_chip ioasic_dma_irq_type = {
-	.typename = "IO-ASIC-DMA",
+	.name = "IO-ASIC-DMA",
 	.ack = ack_ioasic_dma_irq,
 	.mask = mask_ioasic_dma_irq,
 	.mask_ack = ack_ioasic_dma_irq,
diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c
index 916e46b..02439dc 100644
--- a/arch/mips/dec/kn02-irq.c
+++ b/arch/mips/dec/kn02-irq.c
@@ -58,7 +58,7 @@
 }
 
 static struct irq_chip kn02_irq_type = {
-	.typename = "KN02-CSR",
+	.name = "KN02-CSR",
 	.ack = ack_kn02_irq,
 	.mask = mask_kn02_irq,
 	.mask_ack = ack_kn02_irq,
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
index 3027ce7..5a557e2 100644
--- a/arch/mips/dec/prom/memory.c
+++ b/arch/mips/dec/prom/memory.c
@@ -92,9 +92,9 @@
 		rex_setup_memory_region();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	unsigned long addr, end;
+	unsigned long end;
 
 	/*
 	 * Free everything below the kernel itself but leave
@@ -114,16 +114,5 @@
 #endif
 		end = __pa(&_text);
 
-	addr = PAGE_SIZE;
-	while (addr < end) {
-		ClearPageReserved(virt_to_page(__va(addr)));
-		init_page_count(virt_to_page(__va(addr)));
-		free_page((unsigned long)__va(addr));
-		addr += PAGE_SIZE;
-	}
-
-	printk("Freeing unused PROM memory: %ldk freed\n",
-	       (end - PAGE_SIZE) >> 10);
-
-	return end - PAGE_SIZE;
+	free_init_pages("unused PROM memory", PAGE_SIZE, end);
 }
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index d34032a..1058e2f 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -234,7 +234,7 @@
 	memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl,
 		sizeof(kn01_cpu_mask_nr_tbl));
 
-	mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 
 }				/* dec_init_kn01 */
 
@@ -309,7 +309,7 @@
 	memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl,
 		sizeof(kn230_cpu_mask_nr_tbl));
 
-	mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 
 }				/* dec_init_kn230 */
 
@@ -403,7 +403,7 @@
 	memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl,
 		sizeof(kn02_asic_mask_nr_tbl));
 
-	mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 	init_kn02_irqs(KN02_IRQ_BASE);
 
 }				/* dec_init_kn02 */
@@ -504,7 +504,7 @@
 	memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl,
 		sizeof(kn02ba_asic_mask_nr_tbl));
 
-	mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 	init_ioasic_irqs(IO_IRQ_BASE);
 
 }				/* dec_init_kn02ba */
@@ -601,7 +601,7 @@
 	memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl,
 		sizeof(kn02ca_asic_mask_nr_tbl));
 
-	mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 	init_ioasic_irqs(IO_IRQ_BASE);
 
 }				/* dec_init_kn02ca */
@@ -702,7 +702,7 @@
 	memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl,
 		sizeof(kn03_asic_mask_nr_tbl));
 
-	mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 	init_ioasic_irqs(IO_IRQ_BASE);
 
 }				/* dec_init_kn03 */
diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c
index 8d880f0..96df37b 100644
--- a/arch/mips/emma2rh/common/irq_emma2rh.c
+++ b/arch/mips/emma2rh/common/irq_emma2rh.c
@@ -57,7 +57,7 @@
 }
 
 struct irq_chip emma2rh_irq_controller = {
-	.typename = "emma2rh_irq",
+	.name = "emma2rh_irq",
 	.ack = emma2rh_irq_disable,
 	.mask = emma2rh_irq_disable,
 	.mask_ack = emma2rh_irq_disable,
diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c
index c93369c..3299b6d 100644
--- a/arch/mips/emma2rh/markeins/irq.c
+++ b/arch/mips/emma2rh/markeins/irq.c
@@ -106,7 +106,7 @@
 	emma2rh_irq_init(EMMA2RH_IRQ_BASE);
 	emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE);
 	emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE);
-	mips_cpu_irq_init(CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 
 	/* setup cascade interrupts */
 	setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c
index 2116d9b..fba5c15 100644
--- a/arch/mips/emma2rh/markeins/irq_markeins.c
+++ b/arch/mips/emma2rh/markeins/irq_markeins.c
@@ -49,7 +49,7 @@
 }
 
 struct irq_chip emma2rh_sw_irq_controller = {
-	.typename = "emma2rh_sw_irq",
+	.name = "emma2rh_sw_irq",
 	.ack = emma2rh_sw_irq_disable,
 	.mask = emma2rh_sw_irq_disable,
 	.mask_ack = emma2rh_sw_irq_disable,
@@ -115,7 +115,7 @@
 }
 
 struct irq_chip emma2rh_gpio_irq_controller = {
-	.typename = "emma2rh_gpio_irq",
+	.name = "emma2rh_gpio_irq",
 	.ack = emma2rh_gpio_irq_ack,
 	.mask = emma2rh_gpio_irq_disable,
 	.mask_ack = emma2rh_gpio_irq_ack,
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index b3e5796..04572b9 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -88,7 +88,7 @@
 }
 
 static struct irq_chip ev64120_irq_type = {
-	.typename	= "EV64120",
+	.name		= "EV64120",
 	.ack		= disable_ev64120_irq,
 	.mask		= disable_ev64120_irq,
 	.mask_ack	= disable_ev64120_irq,
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
index 99c8d42..477848c 100644
--- a/arch/mips/gt64120/ev64120/setup.c
+++ b/arch/mips/gt64120/ev64120/setup.c
@@ -59,9 +59,8 @@
  */
 extern struct pci_ops galileo_pci_ops;
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 /*
diff --git a/arch/mips/gt64120/momenco_ocelot/dbg_io.c b/arch/mips/gt64120/momenco_ocelot/dbg_io.c
index 2128684..32d6fb4 100644
--- a/arch/mips/gt64120/momenco_ocelot/dbg_io.c
+++ b/arch/mips/gt64120/momenco_ocelot/dbg_io.c
@@ -1,6 +1,4 @@
 
-#ifdef CONFIG_KGDB
-
 #include <asm/serial.h> /* For the serial port location and base baud */
 
 /* --- CONFIG --- */
@@ -121,5 +119,3 @@
 	UART16550_WRITE(OFS_SEND_BUFFER, byte);
 	return 1;
 }
-
-#endif
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index d929440..2585d9d 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -90,6 +90,6 @@
 	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
-	mips_cpu_irq_init(0);
-	rm7k_cpu_irq_init(8);
+	mips_cpu_irq_init();
+	rm7k_cpu_irq_init();
 }
diff --git a/arch/mips/gt64120/momenco_ocelot/prom.c b/arch/mips/gt64120/momenco_ocelot/prom.c
index 8677b6d..78f393b 100644
--- a/arch/mips/gt64120/momenco_ocelot/prom.c
+++ b/arch/mips/gt64120/momenco_ocelot/prom.c
@@ -67,7 +67,6 @@
 	add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c
index eedfc24..d3d9659 100644
--- a/arch/mips/gt64120/wrppmc/irq.c
+++ b/arch/mips/gt64120/wrppmc/irq.c
@@ -63,7 +63,7 @@
 void __init arch_init_irq(void)
 {
 	/* IRQ 0 - 7 are for MIPS common irq_cpu controller */
-	mips_cpu_irq_init(0);
+	mips_cpu_irq_init();
 
 	gt64120_init_pic();
 }
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
index 429afc4..121188d 100644
--- a/arch/mips/gt64120/wrppmc/setup.c
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -93,9 +93,8 @@
 }
 #endif /* WRPPMC_EARLY_DEBUG */
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 #ifdef CONFIG_SERIAL_8250
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index f8d417b..295892e 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -40,7 +40,7 @@
 }
 
 static struct irq_chip r4030_irq_type = {
-	.typename = "R4030",
+	.name = "R4030",
 	.ack = disable_r4030_irq,
 	.mask = disable_r4030_irq,
 	.mask_ack = disable_r4030_irq,
diff --git a/arch/mips/jmr3927/common/prom.c b/arch/mips/jmr3927/common/prom.c
index 5d5838f..aa481b7 100644
--- a/arch/mips/jmr3927/common/prom.c
+++ b/arch/mips/jmr3927/common/prom.c
@@ -75,7 +75,6 @@
 	*cp = '\0';
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 3da49c5..7d2c203 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -439,7 +439,7 @@
 }
 
 static struct irq_chip jmr3927_irq_controller = {
-	.typename = "jmr3927_irq",
+	.name = "jmr3927_irq",
 	.ack = jmr3927_irq_ack,
 	.mask = jmr3927_irq_disable,
 	.mask_ack = jmr3927_irq_ack,
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 138f25e..7ca3d6d 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -434,7 +434,7 @@
 
 	/* DMA */
 	tx3927_dmaptr->mcr = 0;
-	for (i = 0; i < sizeof(tx3927_dmaptr->ch) / sizeof(tx3927_dmaptr->ch[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(tx3927_dmaptr->ch); i++) {
 		/* reset channel */
 		tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST;
 		tx3927_dmaptr->ch[i].ccr = 0;
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ff88b06..ea7df4b 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -234,10 +234,6 @@
 	constant("#define _PMD_SHIFT     ", PMD_SHIFT);
 	constant("#define _PGDIR_SHIFT   ", PGDIR_SHIFT);
 	linefeed;
-	constant("#define _PGD_ORDER     ", PGD_ORDER);
-	constant("#define _PMD_ORDER     ", PMD_ORDER);
-	constant("#define _PTE_ORDER     ", PTE_ORDER);
-	linefeed;
 	constant("#define _PTRS_PER_PGD  ", PTRS_PER_PGD);
 	constant("#define _PTRS_PER_PMD  ", PTRS_PER_PMD);
 	constant("#define _PTRS_PER_PTE  ", PTRS_PER_PTE);
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 442839e..f59ef27 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -565,7 +565,7 @@
 	if (config3 & MIPS_CONF3_VEIC)
 		c->options |= MIPS_CPU_VEIC;
 	if (config3 & MIPS_CONF3_MT)
-                c->ases |= MIPS_ASE_MIPSMT;
+	        c->ases |= MIPS_ASE_MIPSMT;
 
 	return config3 & MIPS_CONF_M;
 }
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index 719d269..7bc8820 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -505,13 +505,13 @@
 	 */
 	printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
 	       regs->reg0, regs->reg1, regs->reg2, regs->reg3,
-               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+	       regs->reg4, regs->reg5, regs->reg6, regs->reg7);
 	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
 	       regs->reg8, regs->reg9, regs->reg10, regs->reg11,
-               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+	       regs->reg12, regs->reg13, regs->reg14, regs->reg15);
 	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
 	       regs->reg16, regs->reg17, regs->reg18, regs->reg19,
-               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+	       regs->reg20, regs->reg21, regs->reg22, regs->reg23);
 	printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
 	       regs->reg24, regs->reg25, regs->reg26, regs->reg27,
 	       regs->reg28, regs->reg29, regs->reg30, regs->reg31);
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 9a7811d..6f57ca4 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -231,28 +231,3 @@
 #endif /* CONFIG_SMP */
 
 	__FINIT
-
-	.comm	kernelsp,    NR_CPUS * 8, 8
-	.comm	pgd_current, NR_CPUS * 8, 8
-
-	.comm	fw_arg0, SZREG, SZREG		# firmware arguments
-	.comm	fw_arg1, SZREG, SZREG
-	.comm	fw_arg2, SZREG, SZREG
-	.comm	fw_arg3, SZREG, SZREG
-
-	.macro page name, order
-	.comm	\name, (_PAGE_SIZE << \order), (_PAGE_SIZE << \order)
-	.endm
-
-	/*
-	 * On 64-bit we've got three-level pagetables with a slightly
-	 * different layout ...
-	 */
-	page	swapper_pg_dir, _PGD_ORDER
-#ifdef CONFIG_64BIT
-#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64)
-	page	module_pg_dir, _PGD_ORDER
-#endif
-	page	invalid_pmd_table, _PMD_ORDER
-#endif
-	page	invalid_pte_table, _PTE_ORDER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index b59a676..b33ba6c 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -54,9 +54,11 @@
 
 void disable_8259A_irq(unsigned int irq)
 {
-	unsigned int mask = 1 << irq;
+	unsigned int mask;
 	unsigned long flags;
 
+	irq -= I8259A_IRQ_BASE;
+	mask = 1 << irq;
 	spin_lock_irqsave(&i8259A_lock, flags);
 	cached_irq_mask |= mask;
 	if (irq & 8)
@@ -68,9 +70,11 @@
 
 void enable_8259A_irq(unsigned int irq)
 {
-	unsigned int mask = ~(1 << irq);
+	unsigned int mask;
 	unsigned long flags;
 
+	irq -= I8259A_IRQ_BASE;
+	mask = ~(1 << irq);
 	spin_lock_irqsave(&i8259A_lock, flags);
 	cached_irq_mask &= mask;
 	if (irq & 8)
@@ -82,10 +86,12 @@
 
 int i8259A_irq_pending(unsigned int irq)
 {
-	unsigned int mask = 1 << irq;
+	unsigned int mask;
 	unsigned long flags;
 	int ret;
 
+	irq -= I8259A_IRQ_BASE;
+	mask = 1 << irq;
 	spin_lock_irqsave(&i8259A_lock, flags);
 	if (irq < 8)
 		ret = inb(PIC_MASTER_CMD) & mask;
@@ -134,9 +140,11 @@
  */
 void mask_and_ack_8259A(unsigned int irq)
 {
-	unsigned int irqmask = 1 << irq;
+	unsigned int irqmask;
 	unsigned long flags;
 
+	irq -= I8259A_IRQ_BASE;
+	irqmask = 1 << irq;
 	spin_lock_irqsave(&i8259A_lock, flags);
 	/*
 	 * Lightweight spurious IRQ detection. We do not want
@@ -169,8 +177,8 @@
 		outb(0x60+irq,PIC_MASTER_CMD);	/* 'Specific EOI to master */
 	}
 #ifdef CONFIG_MIPS_MT_SMTC
-        if (irq_hwmask[irq] & ST0_IM)
-        	set_c0_status(irq_hwmask[irq] & ST0_IM);
+	if (irq_hwmask[irq] & ST0_IM)
+		set_c0_status(irq_hwmask[irq] & ST0_IM);
 #endif /* CONFIG_MIPS_MT_SMTC */
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 	return;
@@ -322,8 +330,8 @@
 
 	init_8259A(0);
 
-	for (i = 0; i < 16; i++)
+	for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++)
 		set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
 
-	setup_irq(PIC_CASCADE_IR, &irq2);
+	setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
 }
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 37cad5d..3cc25c0 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -10,6 +10,8 @@
  * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com>
  * Copyright (C) 2004 - 2005 Steven J. Hill <sjhill@realitydiluted.com>
  */
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
@@ -40,8 +42,6 @@
 
 #include <linux/elf.h>
 
-#undef DEBUG
-
 static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_irix_library(struct file *);
 static int irix_core_dump(long signr, struct pt_regs * regs,
@@ -52,72 +52,102 @@
 	irix_core_dump, PAGE_SIZE
 };
 
-#ifdef DEBUG
 /* Debugging routines. */
 static char *get_elf_p_type(Elf32_Word p_type)
 {
-	int i = (int) p_type;
+#ifdef DEBUG
+	switch (p_type) {
+	case PT_NULL:
+		return "PT_NULL";
+		break;
 
-	switch(i) {
-	case PT_NULL: return("PT_NULL"); break;
-	case PT_LOAD: return("PT_LOAD"); break;
-	case PT_DYNAMIC: return("PT_DYNAMIC"); break;
-	case PT_INTERP: return("PT_INTERP"); break;
-	case PT_NOTE: return("PT_NOTE"); break;
-	case PT_SHLIB: return("PT_SHLIB"); break;
-	case PT_PHDR: return("PT_PHDR"); break;
-	case PT_LOPROC: return("PT_LOPROC/REGINFO"); break;
-	case PT_HIPROC: return("PT_HIPROC"); break;
-	default: return("PT_BOGUS"); break;
+	case PT_LOAD:
+		return "PT_LOAD";
+		break;
+
+	case PT_DYNAMIC:
+		return "PT_DYNAMIC";
+		break;
+
+	case PT_INTERP:
+		return "PT_INTERP";
+		break;
+
+	case PT_NOTE:
+		return "PT_NOTE";
+		break;
+
+	case PT_SHLIB:
+		return "PT_SHLIB";
+		break;
+
+	case PT_PHDR:
+		return "PT_PHDR";
+		break;
+
+	case PT_LOPROC:
+		return "PT_LOPROC/REGINFO";
+		break;
+
+	case PT_HIPROC:
+		return "PT_HIPROC";
+		break;
+
+	default:
+		return "PT_BOGUS";
+		break;
 	}
+#endif
 }
 
 static void print_elfhdr(struct elfhdr *ehp)
 {
 	int i;
 
-	printk("ELFHDR: e_ident<");
-	for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]);
-	printk("%x>\n", ehp->e_ident[i]);
-	printk("        e_type[%04x] e_machine[%04x] e_version[%08lx]\n",
-	       (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,
-	       (unsigned long) ehp->e_version);
-	printk("        e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "
-	       "e_flags[%08lx]\n",
-	       (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,
-	       (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);
-	printk("        e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",
-	       (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize,
-	       (unsigned short) ehp->e_phnum);
-	printk("        e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",
-	       (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum,
-	       (unsigned short) ehp->e_shstrndx);
+	pr_debug("ELFHDR: e_ident<");
+	for (i = 0; i < (EI_NIDENT - 1); i++)
+		pr_debug("%x ", ehp->e_ident[i]);
+	pr_debug("%x>\n", ehp->e_ident[i]);
+	pr_debug("        e_type[%04x] e_machine[%04x] e_version[%08lx]\n",
+	         (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,
+	         (unsigned long) ehp->e_version);
+	pr_debug("        e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "
+	         "e_flags[%08lx]\n",
+	         (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,
+	         (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);
+	pr_debug("        e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",
+	         (unsigned short) ehp->e_ehsize,
+	         (unsigned short) ehp->e_phentsize,
+	         (unsigned short) ehp->e_phnum);
+	pr_debug("        e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",
+	         (unsigned short) ehp->e_shentsize,
+	         (unsigned short) ehp->e_shnum,
+	         (unsigned short) ehp->e_shstrndx);
 }
 
 static void print_phdr(int i, struct elf_phdr *ep)
 {
-	printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "
-	       "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),
-	       (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,
-	       (unsigned long) ep->p_paddr);
-	printk("         p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "
-	       "p_align[%08lx]\n", (unsigned long) ep->p_filesz,
-	       (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,
-	       (unsigned long) ep->p_align);
+	pr_debug("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "
+	         "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),
+	         (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,
+	         (unsigned long) ep->p_paddr);
+	pr_debug("         p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "
+	         "p_align[%08lx]\n", (unsigned long) ep->p_filesz,
+	         (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,
+	         (unsigned long) ep->p_align);
 }
 
 static void dump_phdrs(struct elf_phdr *ep, int pnum)
 {
 	int i;
 
-	for(i = 0; i < pnum; i++, ep++) {
-		if((ep->p_type == PT_LOAD) ||
-		   (ep->p_type == PT_INTERP) ||
-		   (ep->p_type == PT_PHDR))
+	for (i = 0; i < pnum; i++, ep++) {
+		if ((ep->p_type == PT_LOAD) ||
+		    (ep->p_type == PT_INTERP) ||
+		    (ep->p_type == PT_PHDR))
 			print_phdr(i, ep);
 	}
 }
-#endif /* DEBUG */
 
 static void set_brk(unsigned long start, unsigned long end)
 {
@@ -156,11 +186,10 @@
 	elf_addr_t *envp;
 	elf_addr_t *sp, *csp;
 
-#ifdef DEBUG
-	printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
-	       "load_addr[%08x] interp_load_addr[%08x]\n",
-	       p, argc, envc, load_addr, interp_load_addr);
-#endif
+	pr_debug("create_irix_tables: p[%p] argc[%d] envc[%d] "
+	         "load_addr[%08x] interp_load_addr[%08x]\n",
+	         p, argc, envc, load_addr, interp_load_addr);
+
 	sp = (elf_addr_t *) (~15UL & (unsigned long) p);
 	csp = sp;
 	csp -= exec ? DLINFO_ITEMS*2 : 2;
@@ -181,7 +210,7 @@
 	sp -= 2;
 	NEW_AUX_ENT(0, AT_NULL, 0);
 
-	if(exec) {
+	if (exec) {
 		sp -= 11*2;
 
 		NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
@@ -245,9 +274,7 @@
 	last_bss = 0;
 	error = load_addr = 0;
 
-#ifdef DEBUG
 	print_elfhdr(interp_elf_ex);
-#endif
 
 	/* First of all, some simple consistency checks */
 	if ((interp_elf_ex->e_type != ET_EXEC &&
@@ -258,7 +285,7 @@
 	}
 
 	/* Now read in all of the header information */
-	if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
+	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
 	    printk("IRIX interp header bigger than a page (%d)\n",
 		   (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));
 	    return 0xffffffff;
@@ -267,15 +294,15 @@
 	elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
 			     GFP_KERNEL);
 
-	if(!elf_phdata) {
-          printk("Cannot kmalloc phdata for IRIX interp.\n");
-	  return 0xffffffff;
+	if (!elf_phdata) {
+		printk("Cannot kmalloc phdata for IRIX interp.\n");
+		return 0xffffffff;
 	}
 
 	/* If the size of this structure has changed, then punt, since
 	 * we will be doing the wrong thing.
 	 */
-	if(interp_elf_ex->e_phentsize != 32) {
+	if (interp_elf_ex->e_phentsize != 32) {
 		printk("IRIX interp e_phentsize == %d != 32 ",
 		       interp_elf_ex->e_phentsize);
 		kfree(elf_phdata);
@@ -286,61 +313,71 @@
 			   (char *) elf_phdata,
 			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
-#ifdef DEBUG
 	dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);
-#endif
 
 	eppnt = elf_phdata;
-	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-	  if(eppnt->p_type == PT_LOAD) {
-	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
-	    int elf_prot = 0;
-	    unsigned long vaddr = 0;
-	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
-	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-	    elf_type |= MAP_FIXED;
-	    vaddr = eppnt->p_vaddr;
+	for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
+		if (eppnt->p_type == PT_LOAD) {
+			int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+			int elf_prot = 0;
+			unsigned long vaddr = 0;
+			if (eppnt->p_flags & PF_R)
+				elf_prot =  PROT_READ;
+			if (eppnt->p_flags & PF_W)
+				elf_prot |= PROT_WRITE;
+			if (eppnt->p_flags & PF_X)
+				elf_prot |= PROT_EXEC;
+			elf_type |= MAP_FIXED;
+			vaddr = eppnt->p_vaddr;
 
-	    pr_debug("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
-		   interpreter, vaddr,
-		   (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
-		   (unsigned long) elf_prot, (unsigned long) elf_type,
-		   (unsigned long) (eppnt->p_offset & 0xfffff000));
-	    down_write(&current->mm->mmap_sem);
-	    error = do_mmap(interpreter, vaddr,
-			    eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
-			    elf_prot, elf_type,
-			    eppnt->p_offset & 0xfffff000);
-	    up_write(&current->mm->mmap_sem);
+			pr_debug("INTERP do_mmap"
+			         "(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
+			         interpreter, vaddr,
+			         (unsigned long)
+			         (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
+			         (unsigned long)
+			         elf_prot, (unsigned long) elf_type,
+			         (unsigned long)
+			         (eppnt->p_offset & 0xfffff000));
 
-	    if(error < 0 && error > -1024) {
-		    printk("Aieee IRIX interp mmap error=%d\n", error);
-		    break;  /* Real error */
-	    }
-	    pr_debug("error=%08lx ", (unsigned long) error);
-	    if(!load_addr && interp_elf_ex->e_type == ET_DYN) {
-	      load_addr = error;
-              pr_debug("load_addr = error ");
-	    }
+			down_write(&current->mm->mmap_sem);
+			error = do_mmap(interpreter, vaddr,
+			eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+			elf_prot, elf_type,
+			eppnt->p_offset & 0xfffff000);
+			up_write(&current->mm->mmap_sem);
 
-	    /* Find the end of the file  mapping for this phdr, and keep
-	     * track of the largest address we see for this.
-	     */
-	    k = eppnt->p_vaddr + eppnt->p_filesz;
-	    if(k > elf_bss) elf_bss = k;
+			if (error < 0 && error > -1024) {
+				printk("Aieee IRIX interp mmap error=%d\n",
+				       error);
+				break;  /* Real error */
+			}
+			pr_debug("error=%08lx ", (unsigned long) error);
+			if (!load_addr && interp_elf_ex->e_type == ET_DYN) {
+				load_addr = error;
+				pr_debug("load_addr = error ");
+			}
 
-	    /* Do the same thing for the memory mapping - between
-	     * elf_bss and last_bss is the bss section.
-	     */
-	    k = eppnt->p_memsz + eppnt->p_vaddr;
-	    if(k > last_bss) last_bss = k;
-	    pr_debug("\n");
-	  }
+			/*
+			 * Find the end of the file  mapping for this phdr, and
+			 * keep track of the largest address we see for this.
+			 */
+			k = eppnt->p_vaddr + eppnt->p_filesz;
+			if (k > elf_bss)
+				elf_bss = k;
+
+			/* Do the same thing for the memory mapping - between
+			 * elf_bss and last_bss is the bss section.
+			 */
+			k = eppnt->p_memsz + eppnt->p_vaddr;
+			if (k > last_bss)
+				last_bss = k;
+			pr_debug("\n");
+		}
 	}
 
 	/* Now use mmap to map the library into memory. */
-	if(error < 0 && error > -1024) {
+	if (error < 0 && error > -1024) {
 		pr_debug("got error %d\n", error);
 		kfree(elf_phdata);
 		return 0xffffffff;
@@ -377,7 +414,7 @@
 		return -ENOEXEC;
 
 	/* First of all, some simple consistency checks */
-	if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
+	if ((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
 	    !bprm->file->f_op->mmap) {
 		return -ENOEXEC;
 	}
@@ -388,7 +425,7 @@
 	 * XXX all registers as 64bits on cpu's capable of this at
 	 * XXX exception time plus frob the XTLB exception vector.
 	 */
-	if((ehp->e_flags & EF_MIPS_ABI2))
+	if ((ehp->e_flags & EF_MIPS_ABI2))
 		return -ENOEXEC;
 
 	return 0;
@@ -410,7 +447,7 @@
 	struct file *file = NULL;
 
 	*name = NULL;
-	for(i = 0; i < pnum; i++, epp++) {
+	for (i = 0; i < pnum; i++, epp++) {
 		if (epp->p_type != PT_INTERP)
 			continue;
 
@@ -467,8 +504,8 @@
 	unsigned int tmp;
 	int i, prot;
 
-	for(i = 0; i < pnum; i++, epp++) {
-		if(epp->p_type != PT_LOAD)
+	for (i = 0; i < pnum; i++, epp++) {
+		if (epp->p_type != PT_LOAD)
 			continue;
 
 		/* Map it. */
@@ -483,23 +520,23 @@
 	        up_write(&current->mm->mmap_sem);
 
 		/* Fixup location tracking vars. */
-		if((epp->p_vaddr & 0xfffff000) < *estack)
+		if ((epp->p_vaddr & 0xfffff000) < *estack)
 			*estack = (epp->p_vaddr & 0xfffff000);
-		if(!*laddr)
+		if (!*laddr)
 			*laddr = epp->p_vaddr - epp->p_offset;
-		if(epp->p_vaddr < *scode)
+		if (epp->p_vaddr < *scode)
 			*scode = epp->p_vaddr;
 
 		tmp = epp->p_vaddr + epp->p_filesz;
-		if(tmp > *ebss)
+		if (tmp > *ebss)
 			*ebss = tmp;
-		if((epp->p_flags & PF_X) && *ecode < tmp)
+		if ((epp->p_flags & PF_X) && *ecode < tmp)
 			*ecode = tmp;
-		if(*edata < tmp)
+		if (*edata < tmp)
 			*edata = tmp;
 
 		tmp = epp->p_vaddr + epp->p_memsz;
-		if(tmp > *ebrk)
+		if (tmp > *ebrk)
 			*ebrk = tmp;
 	}
 
@@ -513,12 +550,12 @@
 	int i;
 
 	*eentry = 0xffffffff;
-	for(i = 0; i < pnum; i++, epp++) {
-		if(epp->p_type != PT_INTERP)
+	for (i = 0; i < pnum; i++, epp++) {
+		if (epp->p_type != PT_INTERP)
 			continue;
 
 		/* We should have fielded this error elsewhere... */
-		if(*eentry != 0xffffffff)
+		if (*eentry != 0xffffffff)
 			return -1;
 
 		set_fs(old_fs);
@@ -604,9 +641,7 @@
 	if (elf_ex.e_shnum > 20)
 		goto out;
 
-#ifdef DEBUG
 	print_elfhdr(&elf_ex);
-#endif
 
 	/* Now read in all of the header information */
 	size = elf_ex.e_phentsize * elf_ex.e_phnum;
@@ -622,13 +657,11 @@
 	if (retval < 0)
 		goto out_free_ph;
 
-#ifdef DEBUG
 	dump_phdrs(elf_phdata, elf_ex.e_phnum);
-#endif
 
 	/* Set some things for later. */
-	for(i = 0; i < elf_ex.e_phnum; i++) {
-		switch(elf_phdata[i].p_type) {
+	for (i = 0; i < elf_ex.e_phnum; i++) {
+		switch (elf_phdata[i].p_type) {
 		case PT_INTERP:
 			has_interp = 1;
 			elf_ihdr = &elf_phdata[i];
@@ -667,7 +700,7 @@
 
 	if (elf_interpreter) {
 		retval = verify_irix_interpreter(&interp_elf_ex);
-		if(retval)
+		if (retval)
 			goto out_free_interp;
 	}
 
@@ -706,12 +739,12 @@
 	               &load_addr, &start_code, &elf_bss, &end_code,
 	               &end_data, &elf_brk);
 
-	if(elf_interpreter) {
+	if (elf_interpreter) {
 		retval = map_interpreter(elf_phdata, &interp_elf_ex,
 					 interpreter, &interp_load_addr,
 					 elf_ex.e_phnum, old_fs, &elf_entry);
 		kfree(elf_interpreter);
-		if(retval) {
+		if (retval) {
 			set_fs(old_fs);
 			printk("Unable to load IRIX ELF interpreter\n");
 			send_sig(SIGSEGV, current, 0);
@@ -809,12 +842,12 @@
 		return -ENOEXEC;
 
 	/* First of all, some simple consistency checks. */
-	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
+	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 	   !file->f_op->mmap)
 		return -ENOEXEC;
 
 	/* Now read in all of the header information. */
-	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
+	if (sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
 		return -ENOEXEC;
 
 	elf_phdata = kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
@@ -825,15 +858,15 @@
 			   sizeof(struct elf_phdr) * elf_ex.e_phnum);
 
 	j = 0;
-	for(i=0; i<elf_ex.e_phnum; i++)
-		if((elf_phdata + i)->p_type == PT_LOAD) j++;
+	for (i=0; i<elf_ex.e_phnum; i++)
+		if ((elf_phdata + i)->p_type == PT_LOAD) j++;
 
-	if(j != 1)  {
+	if (j != 1)  {
 		kfree(elf_phdata);
 		return -ENOEXEC;
 	}
 
-	while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
+	while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
 
 	/* Now use mmap to map the library into memory. */
 	down_write(&current->mm->mmap_sem);
@@ -889,9 +922,7 @@
 		return -EFAULT;
 	}
 
-#ifdef DEBUG
 	dump_phdrs(user_phdrp, cnt);
-#endif
 
 	for (i = 0; i < cnt; i++, hp++) {
 		if (__get_user(type, &hp->p_type))
@@ -905,14 +936,14 @@
 	filp = fget(fd);
 	if (!filp)
 		return -EACCES;
-	if(!filp->f_op) {
+	if (!filp->f_op) {
 		printk("irix_mapelf: Bogon filp!\n");
 		fput(filp);
 		return -EACCES;
 	}
 
 	hp = user_phdrp;
-	for(i = 0; i < cnt; i++, hp++) {
+	for (i = 0; i < cnt; i++, hp++) {
 		int prot;
 
 		retval = __get_user(vaddr, &hp->p_vaddr);
@@ -1015,8 +1046,6 @@
 	return sz;
 }
 
-/* #define DEBUG */
-
 #define DUMP_WRITE(addr, nr)	\
 	if (!dump_write(file, (addr), (nr))) \
 		goto end_coredump;
@@ -1093,9 +1122,7 @@
 
 		segs++;
 	}
-#ifdef DEBUG
-	printk("irix_core_dump: %d segs taking %d bytes\n", segs, size);
-#endif
+	pr_debug("irix_core_dump: %d segs taking %d bytes\n", segs, size);
 
 	/* Set up header. */
 	memcpy(elf.e_ident, ELFMAG, SELFMAG);
@@ -1221,7 +1248,7 @@
 		struct elf_phdr phdr;
 		int sz = 0;
 
-		for(i = 0; i < numnote; i++)
+		for (i = 0; i < numnote; i++)
 			sz += notesize(&notes[i]);
 
 		phdr.p_type = PT_NOTE;
@@ -1241,7 +1268,7 @@
 	dataoff = offset = roundup(offset, PAGE_SIZE);
 
 	/* Write program headers for segments dump. */
-	for(vma = current->mm->mmap, i = 0;
+	for (vma = current->mm->mmap, i = 0;
 		i < segs && vma != NULL; vma = vma->vm_next) {
 		struct elf_phdr phdr;
 		size_t sz;
@@ -1267,7 +1294,7 @@
 		DUMP_WRITE(&phdr, sizeof(phdr));
 	}
 
-	for(i = 0; i < numnote; i++)
+	for (i = 0; i < numnote; i++)
 		if (!writenote(&notes[i], file))
 			goto end_coredump;
 
@@ -1275,7 +1302,7 @@
 
 	DUMP_SEEK(dataoff);
 
-	for(i = 0, vma = current->mm->mmap;
+	for (i = 0, vma = current->mm->mmap;
 	    i < segs && vma != NULL;
 	    vma = vma->vm_next) {
 		unsigned long addr = vma->vm_start;
@@ -1284,9 +1311,7 @@
 		if (!maydump(vma))
 			continue;
 		i++;
-#ifdef DEBUG
-		printk("elf_core_dump: writing %08lx %lx\n", addr, len);
-#endif
+		pr_debug("elf_core_dump: writing %08lx %lx\n", addr, len);
 		DUMP_WRITE((void __user *)addr, len);
 	}
 
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index bcaad66..2967537 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -112,7 +112,7 @@
 }
 
 struct irq_chip msc_levelirq_type = {
-	.typename = "SOC-it-Level",
+	.name = "SOC-it-Level",
 	.ack = level_mask_and_ack_msc_irq,
 	.mask = mask_msc_irq,
 	.mask_ack = level_mask_and_ack_msc_irq,
@@ -122,7 +122,7 @@
 };
 
 struct irq_chip msc_edgeirq_type = {
-	.typename = "SOC-it-Edge",
+	.name = "SOC-it-Edge",
 	.ack = edge_mask_and_ack_msc_irq,
 	.mask = mask_msc_irq,
 	.mask_ack = edge_mask_and_ack_msc_irq,
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
index efbd219..3dd5618 100644
--- a/arch/mips/kernel/irq-mv6434x.c
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -23,13 +23,13 @@
 
 static inline int ls1bit32(unsigned int x)
 {
-        int b = 31, s;
+	int b = 31, s;
 
-        s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
-        s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
-        s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
-        s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
-        s =  1; if (x <<  1 == 0) s = 0; b -= s;
+	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
+	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
+	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
+	s =  1; if (x <<  1 == 0) s = 0; b -= s;
 
         return b;
 }
@@ -92,7 +92,7 @@
 }
 
 struct irq_chip mv64340_irq_type = {
-	.typename = "MV-64340",
+	.name = "MV-64340",
 	.ack = mask_mv64340_irq,
 	.mask = mask_mv64340_irq,
 	.mask_ack = mask_mv64340_irq,
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index 123324b..2507328 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -17,28 +17,27 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static int irq_base;
-
 static inline void unmask_rm7k_irq(unsigned int irq)
 {
-	set_c0_intcontrol(0x100 << (irq - irq_base));
+	set_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE));
 }
 
 static inline void mask_rm7k_irq(unsigned int irq)
 {
-	clear_c0_intcontrol(0x100 << (irq - irq_base));
+	clear_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE));
 }
 
 static struct irq_chip rm7k_irq_controller = {
-	.typename = "RM7000",
+	.name = "RM7000",
 	.ack = mask_rm7k_irq,
 	.mask = mask_rm7k_irq,
 	.mask_ack = mask_rm7k_irq,
 	.unmask = unmask_rm7k_irq,
 };
 
-void __init rm7k_cpu_irq_init(int base)
+void __init rm7k_cpu_irq_init(void)
 {
+	int base = RM7K_CPU_IRQ_BASE;
 	int i;
 
 	clear_c0_intcontrol(0x00000f00);		/* Mask all */
@@ -46,6 +45,4 @@
 	for (i = base; i < base + 4; i++)
 		set_irq_chip_and_handler(i, &rm7k_irq_controller,
 					 handle_level_irq);
-
-	irq_base = base;
 }
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index 0e6f4c5..ae83d2d 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -18,16 +18,14 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static int irq_base;
-
 static inline void unmask_rm9k_irq(unsigned int irq)
 {
-	set_c0_intcontrol(0x1000 << (irq - irq_base));
+	set_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
 }
 
 static inline void mask_rm9k_irq(unsigned int irq)
 {
-	clear_c0_intcontrol(0x1000 << (irq - irq_base));
+	clear_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
 }
 
 static inline void rm9k_cpu_irq_enable(unsigned int irq)
@@ -39,15 +37,6 @@
 	local_irq_restore(flags);
 }
 
-static void rm9k_cpu_irq_disable(unsigned int irq)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	mask_rm9k_irq(irq);
-	local_irq_restore(flags);
-}
-
 /*
  * Performance counter interrupts are global on all processors.
  */
@@ -81,7 +70,7 @@
 }
 
 static struct irq_chip rm9k_irq_controller = {
-	.typename = "RM9000",
+	.name = "RM9000",
 	.ack = mask_rm9k_irq,
 	.mask = mask_rm9k_irq,
 	.mask_ack = mask_rm9k_irq,
@@ -89,7 +78,7 @@
 };
 
 static struct irq_chip rm9k_perfcounter_irq = {
-	.typename = "RM9000",
+	.name = "RM9000",
 	.startup = rm9k_perfcounter_irq_startup,
 	.shutdown = rm9k_perfcounter_irq_shutdown,
 	.ack = mask_rm9k_irq,
@@ -102,8 +91,9 @@
 
 EXPORT_SYMBOL(rm9000_perfcount_irq);
 
-void __init rm9k_cpu_irq_init(int base)
+void __init rm9k_cpu_irq_init(void)
 {
+	int base = RM9K_CPU_IRQ_BASE;
 	int i;
 
 	clear_c0_intcontrol(0x0000f000);		/* Mask all */
@@ -115,6 +105,4 @@
 	rm9000_perfcount_irq = base + 1;
 	set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
 				 handle_level_irq);
-
-	irq_base = base;
 }
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index fcc86b9..7b66e03 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -25,7 +25,7 @@
  * Don't even think about using this on SMP.  You have been warned.
  *
  * This file exports one global function:
- *	void mips_cpu_irq_init(int irq_base);
+ *	void mips_cpu_irq_init(void);
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -36,22 +36,20 @@
 #include <asm/mipsmtregs.h>
 #include <asm/system.h>
 
-static int mips_cpu_irq_base;
-
 static inline void unmask_mips_irq(unsigned int irq)
 {
-	set_c0_status(0x100 << (irq - mips_cpu_irq_base));
+	set_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE));
 	irq_enable_hazard();
 }
 
 static inline void mask_mips_irq(unsigned int irq)
 {
-	clear_c0_status(0x100 << (irq - mips_cpu_irq_base));
+	clear_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE));
 	irq_disable_hazard();
 }
 
 static struct irq_chip mips_cpu_irq_controller = {
-	.typename	= "MIPS",
+	.name		= "MIPS",
 	.ack		= mask_mips_irq,
 	.mask		= mask_mips_irq,
 	.mask_ack	= mask_mips_irq,
@@ -70,7 +68,7 @@
 {
 	unsigned int vpflags = dvpe();
 
-	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+	clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE));
 	evpe(vpflags);
 	unmask_mips_mt_irq(irq);
 
@@ -84,13 +82,13 @@
 static void mips_mt_cpu_irq_ack(unsigned int irq)
 {
 	unsigned int vpflags = dvpe();
-	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+	clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE));
 	evpe(vpflags);
 	mask_mips_mt_irq(irq);
 }
 
 static struct irq_chip mips_mt_cpu_irq_controller = {
-	.typename	= "MIPS",
+	.name		= "MIPS",
 	.startup	= mips_mt_cpu_irq_startup,
 	.ack		= mips_mt_cpu_irq_ack,
 	.mask		= mask_mips_mt_irq,
@@ -99,8 +97,9 @@
 	.eoi		= unmask_mips_mt_irq,
 };
 
-void __init mips_cpu_irq_init(int irq_base)
+void __init mips_cpu_irq_init(void)
 {
+	int irq_base = MIPS_CPU_IRQ_BASE;
 	int i;
 
 	/* Mask interrupts. */
@@ -118,6 +117,4 @@
 	for (i = irq_base + 2; i < irq_base + 8; i++)
 		set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
 					 handle_level_irq);
-
-	mips_cpu_irq_base = irq_base;
 }
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index b061c9a..0b8ce59 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -194,15 +194,15 @@
 }
 
 struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        u16 procs;
+	s32 uptime;
+	u32 loads[3];
+	u32 totalram;
+	u32 freeram;
+	u32 sharedram;
+	u32 bufferram;
+	u32 totalswap;
+	u32 freeswap;
+	u16 procs;
 	u32 totalhigh;
 	u32 freehigh;
 	u32 mem_unit;
@@ -440,14 +440,26 @@
 }
 
 #ifdef CONFIG_MIPS32_N32
-asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, union semun arg)
+asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
 {
 	/* compat_sys_semctl expects a pointer to union semun */
 	u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
-	if (put_user(ptr_to_compat(arg.__pad), uptr))
+	if (put_user(arg, uptr))
 		return -EFAULT;
 	return compat_sys_semctl(semid, semnum, cmd, uptr);
 }
+
+asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
+{
+	return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
+}
+
+asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
+			      int msgflg)
+{
+	return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
+				 compat_ptr(msgp));
+}
 #endif
 
 struct sysctl_args32
@@ -546,7 +558,7 @@
 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
 {
 	int err;
-        struct ustat tmp;
+	struct ustat tmp;
 	struct ustat32 tmp32;
 	mm_segment_t old_fs = get_fs();
 
@@ -557,11 +569,11 @@
 	if (err)
 		goto out;
 
-        memset(&tmp32,0,sizeof(struct ustat32));
-        tmp32.f_tfree = tmp.f_tfree;
-        tmp32.f_tinode = tmp.f_tinode;
+	memset(&tmp32,0,sizeof(struct ustat32));
+	tmp32.f_tfree = tmp.f_tfree;
+	tmp32.f_tinode = tmp.f_tinode;
 
-        err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
+	err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
 
 out:
 	return err;
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index c1373a6..a32f679 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -96,6 +96,10 @@
 		goto out_unlock;
 	}
 
+	retval = security_task_setscheduler(p, 0, NULL);
+	if (retval)
+		goto out_unlock;
+
 	/* Record new user-specified CPU set for future reference */
 	p->thread.user_cpus_allowed = new_mask;
 
@@ -141,8 +145,9 @@
 	p = find_process_by_pid(pid);
 	if (!p)
 		goto out_unlock;
-
-	retval = 0;
+	retval = security_task_getscheduler(p);
+	if (retval)
+		goto out_unlock;
 
 	cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
 
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 4ed37ba..5ddc2e9 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -31,13 +31,13 @@
 	[CPU_R4000PC]	= "R4000PC",
 	[CPU_R4000SC]	= "R4000SC",
 	[CPU_R4000MC]	= "R4000MC",
-        [CPU_R4200]	= "R4200",
+	[CPU_R4200]	= "R4200",
 	[CPU_R4400PC]	= "R4400PC",
 	[CPU_R4400SC]	= "R4400SC",
 	[CPU_R4400MC]	= "R4400MC",
 	[CPU_R4600]	= "R4600",
 	[CPU_R6000]	= "R6000",
-        [CPU_R6000A]	= "R6000A",
+	[CPU_R6000A]	= "R6000A",
 	[CPU_R8000]	= "R8000",
 	[CPU_R10000]	= "R10000",
 	[CPU_R12000]	= "R12000",
@@ -46,14 +46,14 @@
 	[CPU_R4650]	= "R4650",
 	[CPU_R4700]	= "R4700",
 	[CPU_R5000]	= "R5000",
-        [CPU_R5000A]	= "R5000A",
+	[CPU_R5000A]	= "R5000A",
 	[CPU_R4640]	= "R4640",
 	[CPU_NEVADA]	= "Nevada",
 	[CPU_RM7000]	= "RM7000",
 	[CPU_RM9000]	= "RM9000",
 	[CPU_R5432]	= "R5432",
 	[CPU_4KC]	= "MIPS 4Kc",
-        [CPU_5KC]	= "MIPS 5Kc",
+	[CPU_5KC]	= "MIPS 5Kc",
 	[CPU_R4310]	= "R4310",
 	[CPU_SB1]	= "SiByte SB1",
 	[CPU_SB1A]	= "SiByte SB1A",
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index ec8209f..04e5b38 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -41,10 +41,6 @@
 #include <asm/isadep.h>
 #include <asm/inst.h>
 #include <asm/stacktrace.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-extern void smtc_idle_loop_hook(void);
-#endif /* CONFIG_MIPS_MT_SMTC */
 
 /*
  * The idle thread. There's no useful work to be done, so just try to conserve
@@ -57,6 +53,8 @@
 	while (1) {
 		while (!need_resched()) {
 #ifdef CONFIG_MIPS_MT_SMTC
+			extern void smtc_idle_loop_hook(void);
+
 			smtc_idle_loop_hook();
 #endif /* CONFIG_MIPS_MT_SMTC */
 			if (cpu_wait)
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 880fa6e..59c1577 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -114,6 +114,14 @@
  */
 LEAF(_restore_fp_context)
 	EX	lw t0, SC_FPC_CSR(a0)
+
+	/* Fail if the CSR has exceptions pending */
+	srl	t1, t0, 5
+	and	t1, t0
+	andi	t1, 0x1f << 7
+	bnez	t1, fault
+	 nop
+
 #ifdef CONFIG_64BIT
 	EX	ldc1 $f1, SC_FPREGS+8(a0)
 	EX	ldc1 $f3, SC_FPREGS+24(a0)
@@ -157,6 +165,14 @@
 LEAF(_restore_fp_context32)
 	/* Restore an o32 sigcontext.  */
 	EX	lw t0, SC32_FPC_CSR(a0)
+
+	/* Fail if the CSR has exceptions pending */
+	srl	t1, t0, 5
+	and	t1, t0
+	andi	t1, 0x1f << 7
+	bnez	t1, fault
+	 nop
+
 	EX	ldc1 $f0, SC32_FPREGS+0(a0)
 	EX	ldc1 $f2, SC32_FPREGS+16(a0)
 	EX	ldc1 $f4, SC32_FPREGS+32(a0)
@@ -177,9 +193,10 @@
 	jr	ra
 	 li	v0, 0					# success
 	END(_restore_fp_context32)
-	.set	reorder
 #endif
 
+	.set	reorder
+
 	.type	fault@function
 	.ent	fault
 fault:	li	v0, -EFAULT				# failure
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 5a99e3e..8610f4a 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -63,7 +63,7 @@
 
 static void rtlx_dispatch(void)
 {
-	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ);
+	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
 }
 
 
@@ -491,7 +491,7 @@
 	.name		= "RTLX",
 };
 
-static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
 
 static char register_chrdev_failed[] __initdata =
 	KERN_ERR "rtlx_module_init: unable to register device\n";
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 34567d8..39add23 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -187,8 +187,8 @@
 	PTR	sysn32_semctl
 	PTR	sys_shmdt			/* 6065 */
 	PTR	sys_msgget
-	PTR	compat_sys_msgsnd
-	PTR	compat_sys_msgrcv
+	PTR	sysn32_msgsnd
+	PTR	sysn32_msgrcv
 	PTR	compat_sys_msgctl
 	PTR	compat_sys_fcntl		/* 6070 */
 	PTR	sys_flock
@@ -384,7 +384,7 @@
 	PTR	sys_readlinkat
 	PTR	sys_fchmodat
 	PTR	sys_faccessat
-	PTR	sys_pselect6
+	PTR	compat_sys_pselect6
 	PTR	sys_ppoll			/* 6265 */
 	PTR	sys_unshare
 	PTR	sys_splice
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index e91379c..c58b8e0 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -506,7 +506,7 @@
 	PTR	sys_readlinkat
 	PTR	sys_fchmodat
 	PTR	sys_faccessat			/* 4300 */
-	PTR	sys_pselect6
+	PTR	compat_sys_pselect6
 	PTR	sys_ppoll
 	PTR	sys_unshare
 	PTR	sys_splice
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 89440a0..d2e01e7 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -271,8 +271,7 @@
 static void __init bootmem_init(void)
 {
 	unsigned long reserved_end;
-	unsigned long highest = 0;
-	unsigned long mapstart = -1UL;
+	unsigned long mapstart = ~0UL;
 	unsigned long bootmap_size;
 	int i;
 
@@ -284,6 +283,13 @@
 	reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
 
 	/*
+	 * max_low_pfn is not a number of pages. The number of pages
+	 * of the system is given by 'max_low_pfn - min_low_pfn'.
+	 */
+	min_low_pfn = ~0UL;
+	max_low_pfn = 0;
+
+	/*
 	 * Find the highest page frame number we have available.
 	 */
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
@@ -296,8 +302,10 @@
 		end = PFN_DOWN(boot_mem_map.map[i].addr
 				+ boot_mem_map.map[i].size);
 
-		if (end > highest)
-			highest = end;
+		if (end > max_low_pfn)
+			max_low_pfn = end;
+		if (start < min_low_pfn)
+			min_low_pfn = start;
 		if (end <= reserved_end)
 			continue;
 		if (start >= mapstart)
@@ -305,22 +313,36 @@
 		mapstart = max(reserved_end, start);
 	}
 
+	if (min_low_pfn >= max_low_pfn)
+		panic("Incorrect memory mapping !!!");
+	if (min_low_pfn > ARCH_PFN_OFFSET) {
+		printk(KERN_INFO
+		       "Wasting %lu bytes for tracking %lu unused pages\n",
+		       (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page),
+		       min_low_pfn - ARCH_PFN_OFFSET);
+	} else if (min_low_pfn < ARCH_PFN_OFFSET) {
+		printk(KERN_INFO
+		       "%lu free pages won't be used\n",
+		       ARCH_PFN_OFFSET - min_low_pfn);
+	}
+	min_low_pfn = ARCH_PFN_OFFSET;
+
 	/*
 	 * Determine low and high memory ranges
 	 */
-	if (highest > PFN_DOWN(HIGHMEM_START)) {
+	if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) {
 #ifdef CONFIG_HIGHMEM
 		highstart_pfn = PFN_DOWN(HIGHMEM_START);
-		highend_pfn = highest;
+		highend_pfn = max_low_pfn;
 #endif
-		highest = PFN_DOWN(HIGHMEM_START);
+		max_low_pfn = PFN_DOWN(HIGHMEM_START);
 	}
 
 	/*
 	 * Initialize the boot-time allocator with low memory only.
 	 */
-	bootmap_size = init_bootmem(mapstart, highest);
-
+	bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart,
+					 min_low_pfn, max_low_pfn);
 	/*
 	 * Register fully available low RAM pages with the bootmem allocator.
 	 */
@@ -507,9 +529,9 @@
 
 #if defined(CONFIG_VT)
 #if defined(CONFIG_VGA_CONSOLE)
-        conswitchp = &vga_con;
+	conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
-        conswitchp = &dummy_con;
+	conswitchp = &dummy_con;
 #endif
 #endif
 
@@ -541,3 +563,6 @@
 }
 
 __setup("nodsp", dsp_disable);
+
+unsigned long kernelsp[NR_CPUS];
+unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index b9d358e..9a44053 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -89,7 +89,7 @@
 	spin_lock_irq(&current->sighand->siglock);
 	current->saved_sigmask = current->blocked;
 	current->blocked = newset;
-        recalc_sigpending();
+	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
 	current->state = TASK_INTERRUPTIBLE;
@@ -124,7 +124,7 @@
 
 	if (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
-                        return -EFAULT;
+			return -EFAULT;
 		err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 		err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
 		err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
@@ -304,7 +304,7 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->regs[31]);
 #endif
-        return 0;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index a67c185..b28646b 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -105,7 +105,7 @@
 	spin_lock_irq(&current->sighand->siglock);
 	current->saved_sigmask = current->blocked;
 	current->blocked = newset;
-        recalc_sigpending();
+	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
 	current->state = TASK_INTERRUPTIBLE;
@@ -184,7 +184,7 @@
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
 	err |= __put_user(0, &frame->rs_uc.uc_link);
-        sp = (int) (long) current->sas_ss_sp;
+	sp = (int) (long) current->sas_ss_sp;
 	err |= __put_user(sp,
 	                  &frame->rs_uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->regs[29]),
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 1ee689c..64b62bd 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -35,7 +35,6 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
-#include <asm/mips-boards/maltaint.h>  /* This is f*cking wrong */
 
 #define MIPS_CPU_IPI_RESCHED_IRQ 0
 #define MIPS_CPU_IPI_CALL_IRQ 1
@@ -108,12 +107,12 @@
 
 static void ipi_resched_dispatch(void)
 {
-	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
+	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
 }
 
 static void ipi_call_dispatch(void)
 {
-	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ);
+	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
 }
 
 static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
@@ -270,8 +269,8 @@
 		set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
 	}
 
-	cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
-	cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
+	cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
+	cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
 
 	setup_irq(cpu_ipi_resched_irq, &irq_resched);
 	setup_irq(cpu_ipi_call_irq, &irq_call);
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index f2a8701..0555fc5 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -271,7 +271,7 @@
  * and keep control until "cpu_online(cpu)" is set.  Note: cpu is
  * physical, not logical.
  */
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	struct task_struct *idle;
 
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 802febe..9251ea8 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -4,6 +4,7 @@
 #include <linux/sched.h>
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
@@ -25,16 +26,6 @@
  * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
  */
 
-/*
- * MIPSCPU_INT_BASE is identically defined in both
- * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h,
- * but as yet there's no properly organized include structure that
- * will ensure that the right *int.h file will be included for a
- * given platform build.
- */
-
-#define MIPSCPU_INT_BASE	16
-
 #define MIPS_CPU_IPI_IRQ	1
 
 #define LOCK_MT_PRA() \
@@ -76,15 +67,15 @@
 
 #define IPIBUF_PER_CPU 4
 
-struct smtc_ipi_q IPIQ[NR_CPUS];
-struct smtc_ipi_q freeIPIq;
+static struct smtc_ipi_q IPIQ[NR_CPUS];
+static struct smtc_ipi_q freeIPIq;
 
 
 /* Forward declarations */
 
 void ipi_decode(struct smtc_ipi *);
-void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
-void setup_cross_vpe_interrupts(void);
+static void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
+static void setup_cross_vpe_interrupts(void);
 void init_smtc_stats(void);
 
 /* Global SMTC Status */
@@ -199,7 +190,7 @@
  * Configure shared TLB - VPC configuration bit must be set by caller
  */
 
-void smtc_configure_tlb(void)
+static void smtc_configure_tlb(void)
 {
 	int i,tlbsiz,vpes;
 	unsigned long mvpconf0;
@@ -261,6 +252,7 @@
 		    }
 		}
 		write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
+		ehb();
 
 		/*
 		 * Setup kernel data structures to use software total,
@@ -269,9 +261,12 @@
 		 * of their initialization in smtc_cpu_setup().
 		 */
 
-		tlbsiz = tlbsiz & 0x3f;	/* MIPS32 limits TLB indices to 64 */
-		cpu_data[0].tlbsize = tlbsiz;
+		/* MIPS32 limits TLB indices to 64 */
+		if (tlbsiz > 64)
+			tlbsiz = 64;
+		cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz;
 		smtc_status |= SMTC_TLB_SHARED;
+		local_flush_tlb_all();
 
 		printk("TLB of %d entry pairs shared by %d VPEs\n",
 			tlbsiz, vpes);
@@ -643,7 +638,7 @@
  * the VPE.
  */
 
-void smtc_ipi_qdump(void)
+static void smtc_ipi_qdump(void)
 {
 	int i;
 
@@ -681,28 +676,6 @@
 	return result;
 }
 
-/* No longer used in IPI dispatch, but retained for future recycling */
-
-static __inline__ int atomic_postclear(unsigned int *pv)
-{
-	unsigned long result;
-
-	unsigned long temp;
-
-	__asm__ __volatile__(
-	"1:	ll	%0, %2					\n"
-	"	or	%1, $0, $0				\n"
-	"	sc	%1, %2					\n"
-	"	beqz	%1, 1b					\n"
-	"	sync						\n"
-	: "=&r" (result), "=&r" (temp), "=m" (*pv)
-	: "m" (*pv)
-	: "memory");
-
-	return result;
-}
-
-
 void smtc_send_ipi(int cpu, int type, unsigned int action)
 {
 	int tcstatus;
@@ -776,7 +749,7 @@
 /*
  * Send IPI message to Halted TC, TargTC/TargVPE already having been set
  */
-void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
+static void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
 {
 	struct pt_regs *kstack;
 	unsigned long tcstatus;
@@ -916,7 +889,7 @@
  * interrupts.
  */
 
-static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
+static int cpu_ipi_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_IRQ;
 
 static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
 {
@@ -995,7 +968,7 @@
 
 static struct irqaction irq_ipi;
 
-void setup_cross_vpe_interrupts(void)
+static void setup_cross_vpe_interrupts(void)
 {
 	if (!cpu_has_vint)
 		panic("SMTC Kernel requires Vectored Interupt support");
@@ -1016,6 +989,35 @@
  * SMTC-specific hacks invoked from elsewhere in the kernel.
  */
 
+void smtc_ipi_replay(void)
+{
+	/*
+	 * To the extent that we've ever turned interrupts off,
+	 * we may have accumulated deferred IPIs.  This is subtle.
+	 * If we use the smtc_ipi_qdepth() macro, we'll get an
+	 * exact number - but we'll also disable interrupts
+	 * and create a window of failure where a new IPI gets
+	 * queued after we test the depth but before we re-enable
+	 * interrupts. So long as IXMT never gets set, however,
+	 * we should be OK:  If we pick up something and dispatch
+	 * it here, that's great. If we see nothing, but concurrent
+	 * with this operation, another TC sends us an IPI, IXMT
+	 * is clear, and we'll handle it as a real pseudo-interrupt
+	 * and not a pseudo-pseudo interrupt.
+	 */
+	if (IPIQ[smp_processor_id()].depth > 0) {
+		struct smtc_ipi *pipi;
+		extern void self_ipi(struct smtc_ipi *);
+
+		while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) {
+			self_ipi(pipi);
+			smtc_cpu_stats[smp_processor_id()].selfipis++;
+		}
+	}
+}
+
+EXPORT_SYMBOL(smtc_ipi_replay);
+
 void smtc_idle_loop_hook(void)
 {
 #ifdef SMTC_IDLE_HOOK_DEBUG
@@ -1112,29 +1114,14 @@
 	if (pdb_msg != &id_ho_db_msg[0])
 		printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
 #endif /* SMTC_IDLE_HOOK_DEBUG */
-	/*
-	 * To the extent that we've ever turned interrupts off,
-	 * we may have accumulated deferred IPIs.  This is subtle.
-	 * If we use the smtc_ipi_qdepth() macro, we'll get an
-	 * exact number - but we'll also disable interrupts
-	 * and create a window of failure where a new IPI gets
-	 * queued after we test the depth but before we re-enable
-	 * interrupts. So long as IXMT never gets set, however,
-	 * we should be OK:  If we pick up something and dispatch
-	 * it here, that's great. If we see nothing, but concurrent
-	 * with this operation, another TC sends us an IPI, IXMT
-	 * is clear, and we'll handle it as a real pseudo-interrupt
-	 * and not a pseudo-pseudo interrupt.
-	 */
-	if (IPIQ[smp_processor_id()].depth > 0) {
-		struct smtc_ipi *pipi;
-		extern void self_ipi(struct smtc_ipi *);
 
-		if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
-			self_ipi(pipi);
-			smtc_cpu_stats[smp_processor_id()].selfipis++;
-		}
-	}
+	/*
+	 * Replay any accumulated deferred IPIs. If "Instant Replay"
+	 * is in use, there should never be any.
+	 */
+#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
+	smtc_ipi_replay();
+#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
 }
 
 void smtc_soft_dump(void)
@@ -1172,7 +1159,7 @@
 	 * It would be nice to be able to use a spinlock here,
 	 * but this is invoked from within TLB flush routines
 	 * that protect themselves with DVPE, so if a lock is
-         * held by another TC, it'll never be freed.
+	 * held by another TC, it'll never be freed.
 	 *
 	 * DVPE/DMT must not be done with interrupts enabled,
 	 * so even so most callers will already have disabled
@@ -1277,7 +1264,7 @@
  * Support for single-threading cache flush operations.
  */
 
-int halt_state_save[NR_CPUS];
+static int halt_state_save[NR_CPUS];
 
 /*
  * To really, really be sure that nothing is being done
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 6c2406a..93a1484 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -669,7 +669,7 @@
 
 struct irix_statfs {
 	short f_type;
-        long  f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree;
+	long  f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree;
 	char  f_fname[6], f_fpack[6];
 };
 
@@ -959,7 +959,7 @@
 
 	fn = default_llseek;
 	if (file->f_op && file->f_op->llseek)
-        fn = file->f_op->llseek;
+	fn = file->f_op->llseek;
 	lock_kernel();
 	retval = fn(file, offset, origin);
 	unlock_kernel();
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 666bef4..4596249 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -139,13 +139,16 @@
 	struct list_head list;
 };
 
-struct vpecontrol_ {
+struct {
 	/* Virtual processing elements */
 	struct list_head vpe_list;
 
 	/* Thread contexts */
 	struct list_head tc_list;
-} vpecontrol;
+} vpecontrol = {
+	.vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list),
+	.tc_list = LIST_HEAD_INIT(vpecontrol.tc_list)
+};
 
 static void release_progmem(void *ptr);
 /* static __attribute_used__ void dump_vpe(struct vpe * v); */
@@ -519,7 +522,7 @@
 };
 
 static char *rstrs[] = {
-    	[R_MIPS_NONE]	= "MIPS_NONE",
+	[R_MIPS_NONE]	= "MIPS_NONE",
 	[R_MIPS_32]	= "MIPS_32",
 	[R_MIPS_26]	= "MIPS_26",
 	[R_MIPS_HI16]	= "MIPS_HI16",
@@ -692,7 +695,7 @@
 }
 
 /* We are prepared so configure and start the VPE... */
-int vpe_run(struct vpe * v)
+static int vpe_run(struct vpe * v)
 {
 	struct vpe_notifications *n;
 	unsigned long val, dmt_flag;
@@ -710,16 +713,16 @@
 	dvpe();
 
 	if (!list_empty(&v->tc)) {
-                if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
-                        printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
-                               t->index);
-                        return -ENOEXEC;
-                }
-        } else {
-                printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
-                       v->minor);
-                return -ENOEXEC;
-        }
+		if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+			printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
+			       t->index);
+			return -ENOEXEC;
+		}
+	} else {
+		printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
+		       v->minor);
+		return -ENOEXEC;
+	}
 
 	/* Put MVPE's into 'configuration state' */
 	set_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -772,14 +775,14 @@
 
 	back_to_back_c0_hazard();
 
-        /* Set up the XTC bit in vpeconf0 to point at our tc */
-        write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
-                               | (t->index << VPECONF0_XTC_SHIFT));
+	/* Set up the XTC bit in vpeconf0 to point at our tc */
+	write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+	                      | (t->index << VPECONF0_XTC_SHIFT));
 
 	back_to_back_c0_hazard();
 
-        /* enable this VPE */
-        write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+	/* enable this VPE */
+	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
 
 	/* clear out any left overs from a previous program */
 	write_vpe_c0_status(0);
@@ -829,7 +832,7 @@
  * contents of the program (p)buffer performing relocatations/etc, free's it
  * when finished.
  */
-int vpe_elfload(struct vpe * v)
+static int vpe_elfload(struct vpe * v)
 {
 	Elf_Ehdr *hdr;
 	Elf_Shdr *sechdrs;
@@ -1388,8 +1391,6 @@
 
 	/* dump_mtregs(); */
 
-	INIT_LIST_HEAD(&vpecontrol.vpe_list);
-	INIT_LIST_HEAD(&vpecontrol.tc_list);
 
 	val = read_c0_mvpconf0();
 	for (i = 0; i < ((val & MVPCONF0_PTC) + 1); i++) {
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 2affa5f..9a622b9 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -45,7 +45,7 @@
 }
 
 static struct irq_chip lasat_irq_type = {
-	.typename = "Lasat",
+	.name = "Lasat",
 	.ack = disable_lasat_irq,
 	.mask = disable_lasat_irq,
 	.mask_ack = disable_lasat_irq,
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
index 88c7ab8..d47692f 100644
--- a/arch/mips/lasat/prom.c
+++ b/arch/mips/lasat/prom.c
@@ -132,9 +132,8 @@
 	add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 const char *get_system_type(void)
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
index dcd4d2e..2036cf5 100644
--- a/arch/mips/lib-32/Makefile
+++ b/arch/mips/lib-32/Makefile
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= memset.o watch.o
+lib-y	+= watch.o
 
 obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
index dcd4d2e..2036cf5 100644
--- a/arch/mips/lib-64/Makefile
+++ b/arch/mips/lib-64/Makefile
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= memset.o watch.o
+lib-y	+= watch.o
 
 obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
diff --git a/arch/mips/lib-64/memset.S b/arch/mips/lib-64/memset.S
deleted file mode 100644
index e2c42c8..0000000
--- a/arch/mips/lib-64/memset.S
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/regdef.h>
-
-#define EX(insn,reg,addr,handler)			\
-9:	insn	reg, addr;				\
-	.section __ex_table,"a"; 			\
-	PTR	9b, handler; 				\
-	.previous
-
-	.macro	f_fill64 dst, offset, val, fixup
-	EX(LONG_S, \val, (\offset +  0 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  1 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  2 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  3 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  4 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
-	EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
-	.endm
-
-/*
- * memset(void *s, int c, size_t n)
- *
- * a0: start of area to clear
- * a1: char to fill with
- * a2: size of area to clear
- */
-	.set	noreorder
-	.align	5
-LEAF(memset)
-	beqz		a1, 1f
-	 move		v0, a0			/* result */
-
-	andi		a1, 0xff		/* spread fillword */
-	dsll		t1, a1, 8
-	or		a1, t1
-	dsll		t1, a1, 16
-	or		a1, t1
-	dsll		t1, a1, 32
-	or		a1, t1
-1:
-
-FEXPORT(__bzero)
-	sltiu		t0, a2, LONGSIZE	/* very small region? */
-	bnez		t0, small_memset
-	 andi		t0, a0, LONGMASK	/* aligned? */
-
-	beqz		t0, 1f
-	 PTR_SUBU	t0, LONGSIZE		/* alignment in bytes */
-
-#ifdef __MIPSEB__
-	EX(sdl, a1, (a0), first_fixup)		/* make dword aligned */
-#endif
-#ifdef __MIPSEL__
-	EX(sdr, a1, (a0), first_fixup)		/* make dword aligned */
-#endif
-	PTR_SUBU	a0, t0			/* long align ptr */
-	PTR_ADDU	a2, t0			/* correct size */
-
-1:	ori		t1, a2, 0x3f		/* # of full blocks */
-	xori		t1, 0x3f
-	beqz		t1, memset_partial	/* no block to fill */
-	 andi		t0, a2, 0x38
-
-	PTR_ADDU	t1, a0			/* end address */
-	.set		reorder
-1:	PTR_ADDIU	a0, 64
-	f_fill64 a0, -64, a1, fwd_fixup
-	bne		t1, a0, 1b
-	.set		noreorder
-
-memset_partial:
-	PTR_LA		t1, 2f			/* where to start */
-	.set		noat
-	dsrl		AT, t0, 1
-	PTR_SUBU	t1, AT
-	.set		noat
-	jr		t1
-	 PTR_ADDU	a0, t0			/* dest ptr */
-
-	.set		push
-	.set		noreorder
-	.set		nomacro
-	f_fill64 a0, -64, a1, partial_fixup	/* ... but first do longs ... */
-2:	.set		pop
-	andi		a2, LONGMASK		/* At most one long to go */
-
-	beqz		a2, 1f
-	 PTR_ADDU	a0, a2			/* What's left */
-#ifdef __MIPSEB__
-	EX(sdr, a1, -1(a0), last_fixup)
-#endif
-#ifdef __MIPSEL__
-	EX(sdl, a1, -1(a0), last_fixup)
-#endif
-1:	jr		ra
-	 move		a2, zero
-
-small_memset:
-	beqz		a2, 2f
-	 PTR_ADDU	t1, a0, a2
-
-1:	PTR_ADDIU	a0, 1			/* fill bytewise */
-	bne		t1, a0, 1b
-	 sb		a1, -1(a0)
-
-2:	jr		ra			/* done */
-	 move		a2, zero
-	END(memset)
-
-first_fixup:
-	jr	ra
-	 nop
-
-fwd_fixup:
-	PTR_L		t0, TI_TASK($28)
-	LONG_L		t0, THREAD_BUADDR(t0)
-	andi		a2, 0x3f
-	LONG_ADDU	a2, t1
-	jr		ra
-	 LONG_SUBU	a2, t0
-
-partial_fixup:
-	PTR_L		t0, TI_TASK($28)
-	LONG_L		t0, THREAD_BUADDR(t0)
-	andi		a2, LONGMASK
-	LONG_ADDU	a2, t1
-	jr		ra
-	 LONG_SUBU	a2, t0
-
-last_fixup:
-	jr		ra
-	 andi		v1, a2, LONGMASK
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 989c900..5ad501b 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial.o memcpy.o promlib.o \
+lib-y	+= csum_partial.o memcpy.o memset.o promlib.o \
 	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o
 
 obj-y	+= iomap.o
diff --git a/arch/mips/lib-32/memset.S b/arch/mips/lib/memset.S
similarity index 84%
rename from arch/mips/lib-32/memset.S
rename to arch/mips/lib/memset.S
index 1981485..3f8b8b3 100644
--- a/arch/mips/lib-32/memset.S
+++ b/arch/mips/lib/memset.S
@@ -10,6 +10,14 @@
 #include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
+#if LONGSIZE == 4
+#define LONG_S_L swl
+#define LONG_S_R swr
+#else
+#define LONG_S_L sdl
+#define LONG_S_R sdr
+#endif
+
 #define EX(insn,reg,addr,handler)			\
 9:	insn	reg, addr;				\
 	.section __ex_table,"a"; 			\
@@ -25,6 +33,7 @@
 	EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
+#if LONGSIZE == 4
 	EX(LONG_S, \val, (\offset +  8 * LONGSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset +  9 * LONGSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup)
@@ -33,6 +42,7 @@
 	EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup)
 	EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup)
+#endif
 	.endm
 
 /*
@@ -49,9 +59,13 @@
 	 move		v0, a0			/* result */
 
 	andi		a1, 0xff		/* spread fillword */
-	sll		t1, a1, 8
+	LONG_SLL		t1, a1, 8
 	or		a1, t1
-	sll		t1, a1, 16
+	LONG_SLL		t1, a1, 16
+#if LONGSIZE == 8
+	or		a1, t1
+	LONG_SLL		t1, a1, 32
+#endif
 	or		a1, t1
 1:
 
@@ -64,10 +78,10 @@
 	 PTR_SUBU	t0, LONGSIZE		/* alignment in bytes */
 
 #ifdef __MIPSEB__
-	EX(swl, a1, (a0), first_fixup)		/* make word aligned */
+	EX(LONG_S_L, a1, (a0), first_fixup)	/* make word/dword aligned */
 #endif
 #ifdef __MIPSEL__
-	EX(swr, a1, (a0), first_fixup)		/* make word aligned */
+	EX(LONG_S_R, a1, (a0), first_fixup)	/* make word/dword aligned */
 #endif
 	PTR_SUBU	a0, t0			/* long align ptr */
 	PTR_ADDU	a2, t0			/* correct size */
@@ -75,7 +89,7 @@
 1:	ori		t1, a2, 0x3f		/* # of full blocks */
 	xori		t1, 0x3f
 	beqz		t1, memset_partial	/* no block to fill */
-	 andi		t0, a2, 0x3c
+	 andi		t0, a2, 0x40-LONGSIZE
 
 	PTR_ADDU	t1, a0			/* end address */
 	.set		reorder
@@ -86,7 +100,14 @@
 
 memset_partial:
 	PTR_LA		t1, 2f			/* where to start */
+#if LONGSIZE == 4
 	PTR_SUBU	t1, t0
+#else
+	.set		noat
+	LONG_SRL		AT, t0, 1
+	PTR_SUBU	t1, AT
+	.set		noat
+#endif
 	jr		t1
 	 PTR_ADDU	a0, t0			/* dest ptr */
 
@@ -100,10 +121,10 @@
 	beqz		a2, 1f
 	 PTR_ADDU	a0, a2			/* What's left */
 #ifdef __MIPSEB__
-	EX(swr, a1, -1(a0), last_fixup)
+	EX(LONG_S_R, a1, -1(a0), last_fixup)
 #endif
 #ifdef __MIPSEL__
-	EX(swl, a1, -1(a0), last_fixup)
+	EX(LONG_S_L, a1, -1(a0), last_fixup)
 #endif
 1:	jr		ra
 	 move		a2, zero
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c
index 98ce89f..2388f7f 100644
--- a/arch/mips/lib/uncached.c
+++ b/arch/mips/lib/uncached.c
@@ -44,20 +44,24 @@
 
 	if (sp >= (long)CKSEG0 && sp < (long)CKSEG2)
 		usp = CKSEG1ADDR(sp);
+#ifdef CONFIG_64BIT
 	else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
 		 (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0))
 		usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
 				     XKPHYS_TO_PHYS((long long)sp));
+#endif
 	else {
 		BUG();
 		usp = sp;
 	}
 	if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2)
 		ufunc = CKSEG1ADDR(lfunc);
+#ifdef CONFIG_64BIT
 	else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
 		 (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0))
 		ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
 				       XKPHYS_TO_PHYS((long long)lfunc));
+#endif
 	else {
 		BUG();
 		ufunc = lfunc;
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index 43dba6c..dfa0acb 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/kernel.h>
 
 #include <asm/gdb-stub.h>
 #include <asm/io.h>
@@ -69,7 +70,7 @@
 }
 
 static struct irq_chip atlas_irq_type = {
-	.typename = "Atlas",
+	.name = "Atlas",
 	.ack = disable_atlas_irq,
 	.mask = disable_atlas_irq,
 	.mask_ack = disable_atlas_irq,
@@ -220,7 +221,7 @@
 	{MSC01C_INT_TMR,		MSC01_IRQ_EDGE, 0},
 	{MSC01C_INT_PCI,		MSC01_IRQ_LEVEL, 0},
 };
-int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap);
+int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
 
 msc_irqmap_t __initdata msc_eicirqmap[] = {
 	{MSC01E_INT_SW0,		MSC01_IRQ_LEVEL, 0},
@@ -231,14 +232,14 @@
 	{MSC01E_INT_PERFCTR,		MSC01_IRQ_LEVEL, 0},
 	{MSC01E_INT_CPUCTR,		MSC01_IRQ_LEVEL, 0}
 };
-int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap);
+int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 
 void __init arch_init_irq(void)
 {
 	init_atlas_irqs(ATLAS_INT_BASE);
 
 	if (!cpu_has_veic)
-		mips_cpu_irq_init(MIPSCPU_INT_BASE);
+		mips_cpu_irq_init();
 
 	switch(mips_revision_corid) {
 	case MIPS_REVISION_CORID_CORE_MSC:
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index eeed944..ebf0e16 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -166,9 +166,8 @@
 	}
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	unsigned long freed = 0;
 	unsigned long addr;
 	int i;
 
@@ -176,17 +175,8 @@
 		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
 
-		addr = PAGE_ALIGN(boot_mem_map.map[i].addr);
-		while (addr < boot_mem_map.map[i].addr
-			      + boot_mem_map.map[i].size) {
-			ClearPageReserved(virt_to_page(__va(addr)));
-			init_page_count(virt_to_page(__va(addr)));
-			free_page((unsigned long)__va(addr));
-			addr += PAGE_SIZE;
-			freed += PAGE_SIZE;
-		}
+		addr = boot_mem_map.map[i].addr;
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
 	}
-	printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
-
-	return freed;
 }
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index b662c75..cb7f349 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,5 +19,6 @@
 # under Linux.
 #
 
-obj-y := malta_int.o malta_mtd.o malta_setup.o
+obj-y := malta_int.o malta_setup.o
+obj-$(CONFIG_MTD) += malta_mtd.o
 obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 90ad5bf..3c206bb 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/kernel.h>
 #include <linux/random.h>
 
 #include <asm/i8259.h>
@@ -289,7 +290,7 @@
 	{MSC01C_INT_TMR,		MSC01_IRQ_EDGE, 0},
 	{MSC01C_INT_PCI,		MSC01_IRQ_LEVEL, 0},
 };
-int __initdata msc_nr_irqs = sizeof(msc_irqmap)/sizeof(msc_irqmap_t);
+int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
 
 msc_irqmap_t __initdata msc_eicirqmap[] = {
 	{MSC01E_INT_SW0,		MSC01_IRQ_LEVEL, 0},
@@ -303,14 +304,14 @@
 	{MSC01E_INT_PERFCTR,		MSC01_IRQ_LEVEL, 0},
 	{MSC01E_INT_CPUCTR,		MSC01_IRQ_LEVEL, 0}
 };
-int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t);
+int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 
 void __init arch_init_irq(void)
 {
 	init_i8259_irqs();
 
 	if (!cpu_has_veic)
-		mips_cpu_irq_init (MIPSCPU_INT_BASE);
+		mips_cpu_irq_init();
 
         switch(mips_revision_corid) {
         case MIPS_REVISION_CORID_CORE_MSC:
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index 874ccb0..c4b9de3 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -113,5 +113,5 @@
 
 void __init arch_init_irq(void)
 {
-	mips_cpu_irq_init(MIPSCPU_INT_BASE);
+	mips_cpu_irq_init();
 }
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index 2ce449d..15ac065 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -21,9 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <asm/mips-boards/simint.h>
-
-
-extern void mips_cpu_irq_init(int);
+#include <asm/irq_cpu.h>
 
 static inline int clz(unsigned long x)
 {
@@ -86,5 +84,5 @@
 
 void __init arch_init_irq(void)
 {
-	mips_cpu_irq_init(MIPSCPU_INT_BASE);
+	mips_cpu_irq_init();
 }
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
index f7ce769..46bc16f 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -99,10 +99,9 @@
 	}
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
 	int i;
-	unsigned long freed = 0;
 	unsigned long addr;
 
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
@@ -110,16 +109,7 @@
 			continue;
 
 		addr = boot_mem_map.map[i].addr;
-		while (addr < boot_mem_map.map[i].addr
-			      + boot_mem_map.map[i].size) {
-			ClearPageReserved(virt_to_page(__va(addr)));
-			init_page_count(virt_to_page(__va(addr)));
-			free_page((unsigned long)__va(addr));
-			addr += PAGE_SIZE;
-			freed += PAGE_SIZE;
-		}
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
 	}
-	printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
-
-	return freed;
 }
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
index 2659c1c..ea2066c 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mips-boards/sim/sim_setup.c
@@ -57,7 +57,7 @@
 	board_time_init = sim_time_init;
 	prom_printf("Linux started...\n");
 
-#ifdef CONFIG_MT_SMP
+#ifdef CONFIG_MIPS_MT_SMP
 	sanitize_tlb_entries();
 #endif
 }
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 30245c0..125a4a8 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -341,7 +341,6 @@
 void __init paging_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-	unsigned long max_dma, low;
 #ifndef CONFIG_FLATMEM
 	unsigned long zholes_size[MAX_NR_ZONES] = { 0, };
 	unsigned long i, j, pfn;
@@ -354,19 +353,19 @@
 #endif
 	kmap_coherent_init();
 
-	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	low = max_low_pfn;
-
 #ifdef CONFIG_ISA
-	if (low < max_dma)
-		zones_size[ZONE_DMA] = low;
-	else {
-		zones_size[ZONE_DMA] = max_dma;
-		zones_size[ZONE_NORMAL] = low - max_dma;
-	}
-#else
-	zones_size[ZONE_DMA] = low;
+	if (max_low_pfn >= MAX_DMA_PFN)
+		if (min_low_pfn >= MAX_DMA_PFN) {
+			zones_size[ZONE_DMA] = 0;
+			zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
+		} else {
+			zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn;
+			zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN;
+		}
+	else
 #endif
+	zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn;
+
 #ifdef CONFIG_HIGHMEM
 	zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn;
 
@@ -467,7 +466,7 @@
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
-static void free_init_pages(char *what, unsigned long begin, unsigned long end)
+void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
 	unsigned long pfn;
 
@@ -493,17 +492,25 @@
 }
 #endif
 
-extern unsigned long prom_free_prom_memory(void);
-
 void free_initmem(void)
 {
-	unsigned long freed;
-
-	freed = prom_free_prom_memory();
-	if (freed)
-		printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
-
+	prom_free_prom_memory();
 	free_init_pages("unused kernel memory",
 			__pa_symbol(&__init_begin),
 			__pa_symbol(&__init_end));
 }
+
+unsigned long pgd_current[NR_CPUS];
+/*
+ * On 64-bit we've got three-level pagetables with a slightly
+ * different layout ...
+ */
+#define __page_aligned(order) __attribute__((__aligned__(PAGE_SIZE<<order)))
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
+#ifdef CONFIG_64BIT
+#ifdef MODULE_START
+pgd_t module_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
+#endif
+pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned(PMD_ORDER);
+#endif
+pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER);
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 2e0e21e..65160d4 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -106,7 +106,6 @@
 		ENTER_CRITICAL(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		size = (size + 1) >> 1;
-		local_irq_save(flags);
 		if (size <= current_cpu_data.tlbsize/2) {
 			int oldpid = read_c0_entryhi();
 			int newpid = cpu_asid(cpu, mm);
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
index 67372f3..2e8cebd 100644
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ b/arch/mips/momentum/jaguar_atx/Makefile
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y += irq.o prom.o reset.o setup.o
+obj-y += irq.o platform.o prom.o reset.o setup.o
 
 obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
 obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
index 2efb25a..f2b4325 100644
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -82,8 +82,8 @@
 	 */
 	clear_c0_status(ST0_IM);
 
-	mips_cpu_irq_init(0);
-	rm7k_cpu_irq_init(8);
+	mips_cpu_irq_init();
+	rm7k_cpu_irq_init();
 
 	/* set up the cascading interrupts */
 	setup_irq(8, &cascade_mv64340);
diff --git a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
index 6978654..022f697 100644
--- a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
+++ b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
@@ -46,7 +46,9 @@
 
 extern unsigned long ja_fpga_base;
 
-#define JAGUAR_FPGA_WRITE(x,y) writeb(x, ja_fpga_base + JAGUAR_ATX_REG_##y)
-#define JAGUAR_FPGA_READ(x) readb(ja_fpga_base + JAGUAR_ATX_REG_##x)
+#define __FPGA_REG_TO_ADDR(reg)						\
+	((void *) ja_fpga_base + JAGUAR_ATX_REG_##reg)
+#define JAGUAR_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
+#define JAGUAR_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
 
 #endif
diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c
new file mode 100644
index 0000000..035ea51
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/platform.c
@@ -0,0 +1,235 @@
+#include <linux/delay.h>
+#include <linux/if_ether.h>
+#include <linux/ioport.h>
+#include <linux/mv643xx.h>
+#include <linux/platform_device.h>
+
+#include "jaguar_atx_fpga.h"
+
+#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
+
+static struct resource mv643xx_eth_shared_resources[] = {
+	[0] = {
+		.name   = "ethernet shared base",
+		.start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
+		.end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
+		                       MV643XX_ETH_SHARED_REGS_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device mv643xx_eth_shared_device = {
+	.name		= MV643XX_ETH_SHARED_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
+	.resource	= mv643xx_eth_shared_resources,
+};
+
+#define MV_SRAM_BASE			0xfe000000UL
+#define MV_SRAM_SIZE			(256 * 1024)
+
+#define MV_SRAM_RXRING_SIZE		(MV_SRAM_SIZE / 4)
+#define MV_SRAM_TXRING_SIZE		(MV_SRAM_SIZE / 4)
+
+#define MV_SRAM_BASE_ETH0		MV_SRAM_BASE
+#define MV_SRAM_BASE_ETH1		(MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
+
+#define MV64x60_IRQ_ETH_0 48
+#define MV64x60_IRQ_ETH_1 49
+#define MV64x60_IRQ_ETH_2 50
+
+#ifdef CONFIG_MV643XX_ETH_0
+
+static struct resource mv64x60_eth0_resources[] = {
+	[0] = {
+		.name	= "eth0 irq",
+		.start	= MV64x60_IRQ_ETH_0,
+		.end	= MV64x60_IRQ_ETH_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static char eth0_mac_addr[ETH_ALEN];
+
+static struct mv643xx_eth_platform_data eth0_pd = {
+	.mac_addr	= eth0_mac_addr,
+
+	.tx_sram_addr	= MV_SRAM_BASE_ETH0,
+	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
+	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
+
+	.rx_sram_addr	= MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
+	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
+	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
+};
+
+static struct platform_device eth0_device = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
+	.resource	= mv64x60_eth0_resources,
+	.dev = {
+		.platform_data = &eth0_pd,
+	},
+};
+#endif /* CONFIG_MV643XX_ETH_0 */
+
+#ifdef CONFIG_MV643XX_ETH_1
+
+static struct resource mv64x60_eth1_resources[] = {
+	[0] = {
+		.name	= "eth1 irq",
+		.start	= MV64x60_IRQ_ETH_1,
+		.end	= MV64x60_IRQ_ETH_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static char eth1_mac_addr[ETH_ALEN];
+
+static struct mv643xx_eth_platform_data eth1_pd = {
+	.mac_addr	= eth1_mac_addr,
+
+	.tx_sram_addr	= MV_SRAM_BASE_ETH1,
+	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
+	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
+
+	.rx_sram_addr	= MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
+	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
+	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
+};
+
+static struct platform_device eth1_device = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
+	.resource	= mv64x60_eth1_resources,
+	.dev = {
+		.platform_data = &eth1_pd,
+	},
+};
+#endif /* CONFIG_MV643XX_ETH_1 */
+
+#ifdef CONFIG_MV643XX_ETH_2
+
+static struct resource mv64x60_eth2_resources[] = {
+	[0] = {
+		.name	= "eth2 irq",
+		.start	= MV64x60_IRQ_ETH_2,
+		.end	= MV64x60_IRQ_ETH_2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static char eth2_mac_addr[ETH_ALEN];
+
+static struct mv643xx_eth_platform_data eth2_pd = {
+	.mac_addr	= eth2_mac_addr,
+};
+
+static struct platform_device eth2_device = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
+	.resource	= mv64x60_eth2_resources,
+	.dev = {
+		.platform_data = &eth2_pd,
+	},
+};
+#endif /* CONFIG_MV643XX_ETH_2 */
+
+static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
+	&mv643xx_eth_shared_device,
+#ifdef CONFIG_MV643XX_ETH_0
+	&eth0_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+	&eth1_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+	&eth2_device,
+#endif
+};
+
+static u8 __init exchange_bit(u8 val, u8 cs)
+{
+	/* place the data */
+	JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
+	udelay(1);
+
+	/* turn the clock on */
+	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
+	udelay(1);
+
+	/* turn the clock off and read-strobe */
+	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
+
+	/* return the data */
+	return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
+}
+
+static void __init get_mac(char dest[6])
+{
+	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	int i,j;
+
+	for (i = 0; i < 12; i++)
+		exchange_bit(read_opcode[i], 1);
+
+	for (j = 0; j < 6; j++) {
+		dest[j] = 0;
+		for (i = 0; i < 8; i++) {
+			dest[j] <<= 1;
+			dest[j] |= exchange_bit(0, 1);
+		}
+	}
+
+	/* turn off CS */
+	exchange_bit(0,0);
+}
+
+/*
+ * Copy and increment ethernet MAC address by a small value.
+ *
+ * This is useful for systems where the only one MAC address is stored in
+ * non-volatile memory for multiple ports.
+ */
+static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
+	unsigned int add)
+{
+	int i;
+
+	BUG_ON(add >= 256);
+
+	for (i = ETH_ALEN; i >= 0; i--) {
+		dst[i] = src[i] + add;
+		add = dst[i] < src[i];		/* compute carry */
+	}
+
+	WARN_ON(add);
+}
+
+static int __init mv643xx_eth_add_pds(void)
+{
+	unsigned char mac[ETH_ALEN];
+	int ret;
+
+	get_mac(mac);
+#ifdef CONFIG_MV643XX_ETH_0
+	eth_mac_add(eth1_mac_addr, mac, 0);
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+	eth_mac_add(eth1_mac_addr, mac, 1);
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+	eth_mac_add(eth2_mac_addr, mac, 2);
+#endif
+	ret = platform_add_devices(mv643xx_eth_pd_devs,
+			ARRAY_SIZE(mv643xx_eth_pd_devs));
+
+	return ret;
+}
+
+device_initcall(mv643xx_eth_add_pds);
+
+#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
index 3d27129..5dd154e 100644
--- a/arch/mips/momentum/jaguar_atx/prom.c
+++ b/arch/mips/momentum/jaguar_atx/prom.c
@@ -39,56 +39,6 @@
 	return "Momentum Jaguar-ATX";
 }
 
-#ifdef CONFIG_MV643XX_ETH
-extern unsigned char prom_mac_addr_base[6];
-
-static void burn_clocks(void)
-{
-	int i;
-
-	/* this loop should burn at least 1us -- this should be plenty */
-	for (i = 0; i < 0x10000; i++)
-		;
-}
-
-static u8 exchange_bit(u8 val, u8 cs)
-{
-	/* place the data */
-	JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-	burn_clocks();
-
-	/* turn the clock on */
-	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-	burn_clocks();
-
-	/* turn the clock off and read-strobe */
-	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-	/* return the data */
-	return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
-}
-
-void get_mac(char dest[6])
-{
-	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	int i,j;
-
-	for (i = 0; i < 12; i++)
-		exchange_bit(read_opcode[i], 1);
-
-	for (j = 0; j < 6; j++) {
-		dest[j] = 0;
-		for (i = 0; i < 8; i++) {
-			dest[j] <<= 1;
-			dest[j] |= exchange_bit(0, 1);
-		}
-	}
-
-	/* turn off CS */
-	exchange_bit(0,0);
-}
-#endif
-
 #ifdef CONFIG_64BIT
 
 unsigned long signext(unsigned long addr)
@@ -228,16 +178,10 @@
 #endif /* CONFIG_64BIT */
 	mips_machgroup = MACH_GROUP_MOMENCO;
 	mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
-
-#ifdef CONFIG_MV643XX_ETH
-	/* get the base MAC address for on-board ethernet ports */
-	get_mac(prom_mac_addr_base);
-#endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
index cea0e5d..3862d1d 100644
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -65,7 +65,7 @@
 	 */
 	clear_c0_status(ST0_IM | ST0_BEV);
 
-	rm7k_cpu_irq_init(8);
+	rm7k_cpu_irq_init();
 
 	/* set up the cascading interrupts */
 	setup_irq(8, &cascade_mv64340);		/* unmask intControl IM8, IRQ 9 */
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
index 6ce9b7f..8e02df6 100644
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ b/arch/mips/momentum/ocelot_3/prom.c
@@ -180,9 +180,8 @@
 #endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
index bb11fef..186a140 100644
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ b/arch/mips/momentum/ocelot_c/cpci-irq.c
@@ -84,7 +84,7 @@
 }
 
 struct irq_chip cpci_irq_type = {
-	.typename = "CPCI/FPGA",
+	.name = "CPCI/FPGA",
 	.ack = mask_cpci_irq,
 	.mask = mask_cpci_irq,
 	.mask_ack = mask_cpci_irq,
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
index 2128684..32d6fb4 100644
--- a/arch/mips/momentum/ocelot_c/dbg_io.c
+++ b/arch/mips/momentum/ocelot_c/dbg_io.c
@@ -1,6 +1,4 @@
 
-#ifdef CONFIG_KGDB
-
 #include <asm/serial.h> /* For the serial port location and base baud */
 
 /* --- CONFIG --- */
@@ -121,5 +119,3 @@
 	UART16550_WRITE(OFS_SEND_BUFFER, byte);
 	return 1;
 }
-
-#endif
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
index ea65223..40472f7 100644
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -94,7 +94,7 @@
 	 */
 	clear_c0_status(ST0_IM);
 
-	mips_cpu_irq_init(0);
+	mips_cpu_irq_init();
 
 	/* set up the cascading interrupts */
 	setup_irq(3, &cascade_fpga);
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
index d0b77e1..b689cee 100644
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ b/arch/mips/momentum/ocelot_c/prom.c
@@ -178,7 +178,6 @@
 #endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
index a7a80c0..de1a31e 100644
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ b/arch/mips/momentum/ocelot_c/uart-irq.c
@@ -77,7 +77,7 @@
 }
 
 struct irq_chip uart_irq_type = {
-	.typename = "UART/FPGA",
+	.name = "UART/FPGA",
 	.ack = mask_uart_irq,
 	.mask = mask_uart_irq,
 	.mask_ack = mask_uart_irq,
diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c
index 2128684..32d6fb4 100644
--- a/arch/mips/momentum/ocelot_g/dbg_io.c
+++ b/arch/mips/momentum/ocelot_g/dbg_io.c
@@ -1,6 +1,4 @@
 
-#ifdef CONFIG_KGDB
-
 #include <asm/serial.h> /* For the serial port location and base baud */
 
 /* --- CONFIG --- */
@@ -121,5 +119,3 @@
 	UART16550_WRITE(OFS_SEND_BUFFER, byte);
 	return 1;
 }
-
-#endif
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
index da46524..273541f 100644
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -94,8 +94,8 @@
 	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
-	mips_cpu_irq_init(0);
-	rm7k_cpu_irq_init(8);
+	mips_cpu_irq_init();
+	rm7k_cpu_irq_init();
 
 	gt64240_irq_init();
 }
diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c
index 6509a9c..836d083 100644
--- a/arch/mips/momentum/ocelot_g/prom.c
+++ b/arch/mips/momentum/ocelot_g/prom.c
@@ -28,7 +28,7 @@
 extern unsigned long marvell_base;
 extern unsigned long bus_clock;
 
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
 extern unsigned char prom_mac_addr_base[6];
 #endif
 
@@ -61,7 +61,7 @@
 	mips_machgroup = MACH_GROUP_MOMENCO;
 	mips_machtype = MACH_MOMENCO_OCELOT_G;
 
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
 	/* get the base MAC address for on-board ethernet ports */
 	memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
 #endif
@@ -79,7 +79,6 @@
 	}
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
index d288f7b..9db638a 100644
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -64,7 +64,7 @@
 
 #include "ocelot_pld.h"
 
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
 extern unsigned char prom_mac_addr_base[6];
 #endif
 
@@ -185,7 +185,7 @@
 	/* do handoff reconfiguration */
 	PMON_v2_setup();
 
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
 	/* get the mac addr */
 	memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
 #endif
diff --git a/arch/mips/oprofile/Kconfig b/arch/mips/oprofile/Kconfig
index 55feaf7..ca395ef 100644
--- a/arch/mips/oprofile/Kconfig
+++ b/arch/mips/oprofile/Kconfig
@@ -11,7 +11,7 @@
 
 config OPROFILE
 	tristate "OProfile system profiling (EXPERIMENTAL)"
-	depends on PROFILING && EXPERIMENTAL
+	depends on PROFILING && !!MIPS_MT_SMTC && EXPERIMENTAL
 	help
 	  OProfile is a profiling system capable of profiling the
 	  whole system, include the kernel, kernel modules, libraries,
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c
index 597b897..a8d9d22 100644
--- a/arch/mips/pci/fixup-vr4133.c
+++ b/arch/mips/pci/fixup-vr4133.c
@@ -17,8 +17,10 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/kernel.h>
 
 #include <asm/io.h>
+#include <asm/i8259.h>
 #include <asm/vr41xx/cmbvr4133.h>
 
 extern int vr4133_rockhopper;
@@ -142,7 +144,7 @@
 	if (bus == NULL)
 		return -1;
 
-	for (i = 0; i < sizeof (int_map) / sizeof (int_map[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(int_map); i++) {
 		if (int_map[i].bus == bus->number && int_map[i].slot == slot) {
 			int line;
 			for (line = 0; line < 4; line++)
@@ -160,17 +162,7 @@
 #ifdef CONFIG_ROCKHOPPER
 void i8259_init(void)
 {
-	outb(0x11, 0x20);		/* Master ICW1 */
-	outb(I8259_IRQ_BASE, 0x21);	/* Master ICW2 */
-	outb(0x04, 0x21);		/* Master ICW3 */
-	outb(0x01, 0x21);		/* Master ICW4 */
-	outb(0xff, 0x21);		/* Master IMW */
-
-	outb(0x11, 0xa0);		/* Slave ICW1 */
-	outb(I8259_IRQ_BASE + 8, 0xa1);	/* Slave ICW2 */
-	outb(0x02, 0xa1);		/* Slave ICW3 */
-	outb(0x01, 0xa1);		/* Slave ICW4 */
-	outb(0xff, 0xa1);		/* Slave IMW */
+	init_i8259_irqs();
 
 	outb(0x00, 0x4d0);
 	outb(0x02, 0x4d1);	/* USB IRQ9 is level */
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index 2c36c10..d48665e 100644
--- a/arch/mips/philips/pnx8550/common/int.c
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -159,7 +159,7 @@
 }
 
 static struct irq_chip level_irq_type = {
-	.typename =	"PNX Level IRQ",
+	.name =		"PNX Level IRQ",
 	.ack =		mask_irq,
 	.mask =		mask_irq,
 	.mask_ack =	mask_irq,
diff --git a/arch/mips/philips/pnx8550/common/prom.c b/arch/mips/philips/pnx8550/common/prom.c
index eb6ec11..8aeed6c 100644
--- a/arch/mips/philips/pnx8550/common/prom.c
+++ b/arch/mips/philips/pnx8550/common/prom.c
@@ -106,9 +106,8 @@
 	return 0;
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 extern int pnx8550_console_port;
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
index f80acae..68def38 100644
--- a/arch/mips/philips/pnx8550/common/time.c
+++ b/arch/mips/philips/pnx8550/common/time.c
@@ -79,6 +79,7 @@
 	 */
 	mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
 	cpj = (mips_hpt_frequency + HZ / 2) / HZ;
+	write_c0_count(0);
 	timer_ack();
 
 	/* Setup Timer 2 */
diff --git a/arch/mips/pmc-sierra/yosemite/dbg_io.c b/arch/mips/pmc-sierra/yosemite/dbg_io.c
index 0f659c9..6362c70 100644
--- a/arch/mips/pmc-sierra/yosemite/dbg_io.c
+++ b/arch/mips/pmc-sierra/yosemite/dbg_io.c
@@ -93,7 +93,7 @@
  * Functions to READ and WRITE to serial port 1
  */
 #define	SERIAL_READ_1(ofs)		(*((volatile unsigned char*)	\
-					(TITAN_SERIAL_BASE_1 + ofs)
+					(TITAN_SERIAL_BASE_1 + ofs)))
 
 #define	SERIAL_WRITE_1(ofs, val)	((*((volatile unsigned char*)	\
 					(TITAN_SERIAL_BASE_1 + ofs))) = val)
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
index adb0485..428d1f4 100644
--- a/arch/mips/pmc-sierra/yosemite/irq.c
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -148,9 +148,9 @@
 {
 	clear_c0_status(ST0_IM);
 
-	mips_cpu_irq_init(0);
-	rm7k_cpu_irq_init(8);
-	rm9k_cpu_irq_init(12);
+	mips_cpu_irq_init();
+	rm7k_cpu_irq_init();
+	rm9k_cpu_irq_init();
 
 #ifdef CONFIG_KGDB
 	/* At this point, initialize the second serial port */
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
index 9fe4973..1e1685e 100644
--- a/arch/mips/pmc-sierra/yosemite/prom.c
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -132,9 +132,8 @@
 	prom_grab_secondary();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 1b9b0d3..6a6e15e 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -171,6 +171,7 @@
 
 static void __init py_uart_setup(void)
 {
+#ifdef CONFIG_SERIAL_8250
 	struct uart_port up;
 
 	/*
@@ -188,6 +189,7 @@
 
 	if (early_serial_setup(&up))
 		printk(KERN_ERR "Early serial init of port 0 failed\n");
+#endif /* CONFIG_SERIAL_8250 */
 }
 
 static void __init py_rtc_setup(void)
diff --git a/arch/mips/qemu/q-mem.c b/arch/mips/qemu/q-mem.c
index d174fac..dae39b5 100644
--- a/arch/mips/qemu/q-mem.c
+++ b/arch/mips/qemu/q-mem.c
@@ -1,6 +1,5 @@
 #include <linux/init.h>
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0UL;
 }
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index a1a9af6..6b6e97b 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -139,7 +139,7 @@
 }
 
 static struct irq_chip ip22_eisa1_irq_type = {
-	.typename	= "IP22 EISA",
+	.name		= "IP22 EISA",
 	.startup	= startup_eisa1_irq,
 	.ack		= mask_and_ack_eisa1_irq,
 	.mask		= disable_eisa1_irq,
@@ -194,7 +194,7 @@
 }
 
 static struct irq_chip ip22_eisa2_irq_type = {
-	.typename	= "IP22 EISA",
+	.name		= "IP22 EISA",
 	.startup	= startup_eisa2_irq,
 	.ack		= mask_and_ack_eisa2_irq,
 	.mask		= disable_eisa2_irq,
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index c44f8be..b454924 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -19,6 +19,7 @@
 
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
+#include <asm/irq_cpu.h>
 
 #include <asm/sgi/ioc.h>
 #include <asm/sgi/hpc3.h>
@@ -52,7 +53,7 @@
 }
 
 static struct irq_chip ip22_local0_irq_type = {
-	.typename	= "IP22 local 0",
+	.name		= "IP22 local 0",
 	.ack		= disable_local0_irq,
 	.mask		= disable_local0_irq,
 	.mask_ack	= disable_local0_irq,
@@ -73,7 +74,7 @@
 }
 
 static struct irq_chip ip22_local1_irq_type = {
-	.typename	= "IP22 local 1",
+	.name		= "IP22 local 1",
 	.ack		= disable_local1_irq,
 	.mask		= disable_local1_irq,
 	.mask_ack	= disable_local1_irq,
@@ -94,7 +95,7 @@
 }
 
 static struct irq_chip ip22_local2_irq_type = {
-	.typename	= "IP22 local 2",
+	.name		= "IP22 local 2",
 	.ack		= disable_local2_irq,
 	.mask		= disable_local2_irq,
 	.mask_ack	= disable_local2_irq,
@@ -115,7 +116,7 @@
 }
 
 static struct irq_chip ip22_local3_irq_type = {
-	.typename	= "IP22 local 3",
+	.name		= "IP22 local 3",
 	.ack		= disable_local3_irq,
 	.mask		= disable_local3_irq,
 	.mask_ack	= disable_local3_irq,
@@ -253,8 +254,6 @@
 		indy_8254timer_irq();
 }
 
-extern void mips_cpu_irq_init(unsigned int irq_base);
-
 void __init arch_init_irq(void)
 {
 	int i;
@@ -316,7 +315,7 @@
 	sgint->cmeimask1 = 0;
 
 	/* init CPU irqs */
-	mips_cpu_irq_init(SGINT_CPU);
+	mips_cpu_irq_init();
 
 	for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
 		struct irq_chip *handler;
diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
index b58bd52..ddb6506 100644
--- a/arch/mips/sgi-ip22/ip22-mc.c
+++ b/arch/mips/sgi-ip22/ip22-mc.c
@@ -202,7 +202,6 @@
 }
 
 void __init prom_meminit(void) {}
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 319f880..60ade76 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -333,7 +333,7 @@
 }
 
 static struct irq_chip bridge_irq_type = {
-	.typename	= "bridge",
+	.name		= "bridge",
 	.startup	= startup_bridge_irq,
 	.shutdown	= shutdown_bridge_irq,
 	.ack		= disable_bridge_irq,
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 16e5682..0e3d535 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -498,10 +498,9 @@
 	}
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
 	/* We got nothing to free here ...  */
-	return 0;
 }
 
 extern void pagetable_init(void);
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index c20e989..9ce5136 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -181,7 +181,7 @@
 }
 
 static struct irq_chip rt_irq_type = {
-	.typename	= "SN HUB RT timer",
+	.name		= "SN HUB RT timer",
 	.ack		= disable_rt_irq,
 	.mask		= disable_rt_irq,
 	.mask_ack	= disable_rt_irq,
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index ae06386..8c450d9 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -144,7 +144,7 @@
 }
 
 static struct irq_chip ip32_cpu_interrupt = {
-	.typename = "IP32 CPU",
+	.name = "IP32 CPU",
 	.ack = disable_cpu_irq,
 	.mask = disable_cpu_irq,
 	.mask_ack = disable_cpu_irq,
@@ -193,7 +193,7 @@
 }
 
 static struct irq_chip ip32_crime_interrupt = {
-	.typename = "IP32 CRIME",
+	.name = "IP32 CRIME",
 	.ack = mask_and_ack_crime_irq,
 	.mask = disable_crime_irq,
 	.mask_ack = mask_and_ack_crime_irq,
@@ -234,7 +234,7 @@
 }
 
 static struct irq_chip ip32_macepci_interrupt = {
-	.typename = "IP32 MACE PCI",
+	.name = "IP32 MACE PCI",
 	.ack = disable_macepci_irq,
 	.mask = disable_macepci_irq,
 	.mask_ack = disable_macepci_irq,
@@ -347,7 +347,7 @@
 }
 
 static struct irq_chip ip32_maceisa_interrupt = {
-	.typename = "IP32 MACE ISA",
+	.name = "IP32 MACE ISA",
 	.ack = mask_and_ack_maceisa_irq,
 	.mask = disable_maceisa_irq,
 	.mask_ack = mask_and_ack_maceisa_irq,
@@ -379,7 +379,7 @@
 }
 
 static struct irq_chip ip32_mace_interrupt = {
-	.typename = "IP32 MACE",
+	.name = "IP32 MACE",
 	.ack = disable_mace_irq,
 	.mask = disable_mace_irq,
 	.mask_ack = disable_mace_irq,
diff --git a/arch/mips/sgi-ip32/ip32-memory.c b/arch/mips/sgi-ip32/ip32-memory.c
index d37d40a..849d392 100644
--- a/arch/mips/sgi-ip32/ip32-memory.c
+++ b/arch/mips/sgi-ip32/ip32-memory.c
@@ -43,7 +43,6 @@
 }
 
 
-unsigned long __init prom_free_prom_memory (void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 2e8f6b2..1dc5d05 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -82,7 +82,7 @@
 #endif
 
 static struct irq_chip bcm1480_irq_type = {
-	.typename = "BCM1480-IMR",
+	.name = "BCM1480-IMR",
 	.ack = ack_bcm1480_irq,
 	.mask = disable_bcm1480_irq,
 	.mask_ack = ack_bcm1480_irq,
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index 6e8952d..9e6099e 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -343,10 +343,9 @@
 	prom_meminit();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
 	/* Not sure what I'm supposed to do here.  Nothing, I think */
-	return 0;
 }
 
 void prom_putchar(char c)
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 82ce753..1482394 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -67,7 +67,7 @@
 #endif
 
 static struct irq_chip sb1250_irq_type = {
-	.typename = "SB1250-IMR",
+	.name = "SB1250-IMR",
 	.ack = ack_sb1250_irq,
 	.mask = disable_sb1250_irq,
 	.mask_ack = ack_sb1250_irq,
diff --git a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c
index 3c33a45..257c4e6 100644
--- a/arch/mips/sibyte/sb1250/prom.c
+++ b/arch/mips/sibyte/sb1250/prom.c
@@ -87,10 +87,9 @@
 	prom_meminit();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
 	/* Not sure what I'm supposed to do here.  Nothing, I think */
-	return 0;
 }
 
 void prom_putchar(char c)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 8511bcc..039e8e5 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -37,7 +37,7 @@
 }
 
 static struct irq_chip pciasic_irq_type = {
-	.typename = "ASIC-PCI",
+	.name = "ASIC-PCI",
 	.ack = disable_pciasic_irq,
 	.mask = disable_pciasic_irq,
 	.mask_ack = disable_pciasic_irq,
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
index d1d0f1f..1213d16 100644
--- a/arch/mips/sni/sniprom.c
+++ b/arch/mips/sni/sniprom.c
@@ -67,9 +67,8 @@
 	va_end(args);
 }
 
-unsigned long prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 /*
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index ed4a19a..e7f3e5b 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -120,7 +120,7 @@
 
 #define TX4927_CP0_NAME "TX4927-CP0"
 static struct irq_chip tx4927_irq_cp0_type = {
-	.typename	= TX4927_CP0_NAME,
+	.name		= TX4927_CP0_NAME,
 	.ack		= tx4927_irq_cp0_disable,
 	.mask		= tx4927_irq_cp0_disable,
 	.mask_ack	= tx4927_irq_cp0_disable,
@@ -129,7 +129,7 @@
 
 #define TX4927_PIC_NAME "TX4927-PIC"
 static struct irq_chip tx4927_irq_pic_type = {
-	.typename	= TX4927_PIC_NAME,
+	.name		= TX4927_PIC_NAME,
 	.ack		= tx4927_irq_pic_disable,
 	.mask		= tx4927_irq_pic_disable,
 	.mask_ack	= tx4927_irq_pic_disable,
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
index b54b529..dcce88f 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
@@ -228,7 +228,7 @@
 
 #define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
 static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
-	.typename = TOSHIBA_RBTX4927_IOC_NAME,
+	.name = TOSHIBA_RBTX4927_IOC_NAME,
 	.ack = toshiba_rbtx4927_irq_ioc_disable,
 	.mask = toshiba_rbtx4927_irq_ioc_disable,
 	.mask_ack = toshiba_rbtx4927_irq_ioc_disable,
@@ -241,7 +241,7 @@
 #ifdef CONFIG_TOSHIBA_FPCIB0
 #define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA"
 static struct irq_chip toshiba_rbtx4927_irq_isa_type = {
-	.typename = TOSHIBA_RBTX4927_ISA_NAME,
+	.name = TOSHIBA_RBTX4927_ISA_NAME,
 	.ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
 	.mask = toshiba_rbtx4927_irq_isa_disable,
 	.mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
@@ -490,13 +490,13 @@
 	{
 		u32 i, j = 0;
 		for (i = 0; i < NR_IRQS; i++) {
-			if (strcmp(irq_desc[i].chip->typename, "none")
+			if (strcmp(irq_desc[i].chip->name, "none")
 			    == 0)
 				continue;
 
 			if ((i >= 1)
-			    && (irq_desc[i - 1].chip->typename ==
-				irq_desc[i].chip->typename)) {
+			    && (irq_desc[i - 1].chip->name ==
+				irq_desc[i].chip->name)) {
 				j++;
 			} else {
 				j = 0;
@@ -510,7 +510,7 @@
 			     (u32) (irq_desc[i].action ? irq_desc[i].
 				    action->handler : 0),
 			     irq_desc[i].depth,
-			     irq_desc[i].chip->typename, j);
+			     irq_desc[i].chip->name, j);
 		}
 	}
 #endif
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
index efe5056..9a3a5ba 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
@@ -80,9 +80,8 @@
 	add_memory_region(0, msize << 20, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 const char *get_system_type(void)
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index a347b42..3a2dbfc 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -49,7 +49,7 @@
 
 #define TX4938_CP0_NAME "TX4938-CP0"
 static struct irq_chip tx4938_irq_cp0_type = {
-	.typename = TX4938_CP0_NAME,
+	.name = TX4938_CP0_NAME,
 	.ack = tx4938_irq_cp0_disable,
 	.mask = tx4938_irq_cp0_disable,
 	.mask_ack = tx4938_irq_cp0_disable,
@@ -58,7 +58,7 @@
 
 #define TX4938_PIC_NAME "TX4938-PIC"
 static struct irq_chip tx4938_irq_pic_type = {
-	.typename = TX4938_PIC_NAME,
+	.name = TX4938_PIC_NAME,
 	.ack = tx4938_irq_pic_disable,
 	.mask = tx4938_irq_pic_disable,
 	.mask_ack = tx4938_irq_pic_disable,
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index b6f363d..2e96dbb 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -92,7 +92,7 @@
 
 #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
 static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
-	.typename = TOSHIBA_RBTX4938_IOC_NAME,
+	.name = TOSHIBA_RBTX4938_IOC_NAME,
 	.ack = toshiba_rbtx4938_irq_ioc_disable,
 	.mask = toshiba_rbtx4938_irq_ioc_disable,
 	.mask_ack = toshiba_rbtx4938_irq_ioc_disable,
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/prom.c b/arch/mips/tx4938/toshiba_rbtx4938/prom.c
index e44daf3..7dc6a0a 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/prom.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/prom.c
@@ -56,9 +56,8 @@
 	return;
 }
 
-unsigned long  __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index c075261..adabc6b 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
  *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  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
@@ -68,6 +68,7 @@
 #define MPIUINTREG	0x0e
 #define MAIUINTREG	0x10
 #define MKIUINTREG	0x12
+#define MMACINTREG	0x12
 #define MGIUINTLREG	0x14
 #define MDSIUINTREG	0x16
 #define NMIREG		0x18
@@ -241,6 +242,30 @@
 
 EXPORT_SYMBOL(vr41xx_disable_kiuint);
 
+void vr41xx_enable_macint(uint16_t mask)
+{
+	struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	icu1_set(MMACINTREG, mask);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_enable_macint);
+
+void vr41xx_disable_macint(uint16_t mask)
+{
+	struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	icu1_clear(MMACINTREG, mask);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_disable_macint);
+
 void vr41xx_enable_dsiuint(uint16_t mask)
 {
 	struct irq_desc *desc = irq_desc + DSIU_IRQ;
@@ -428,7 +453,7 @@
 }
 
 static struct irq_chip sysint1_irq_type = {
-	.typename	= "SYSINT1",
+	.name		= "SYSINT1",
 	.ack		= disable_sysint1_irq,
 	.mask		= disable_sysint1_irq,
 	.mask_ack	= disable_sysint1_irq,
@@ -446,7 +471,7 @@
 }
 
 static struct irq_chip sysint2_irq_type = {
-	.typename	= "SYSINT2",
+	.name		= "SYSINT2",
 	.ack		= disable_sysint2_irq,
 	.mask		= disable_sysint2_irq,
 	.mask_ack	= disable_sysint2_irq,
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index a2e285c..4f97e0b 100644
--- a/arch/mips/vr41xx/common/init.c
+++ b/arch/mips/vr41xx/common/init.c
@@ -81,7 +81,6 @@
 	}
 }
 
-unsigned long __init prom_free_prom_memory (void)
+void __init prom_free_prom_memory(void)
 {
-	return 0UL;
 }
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 397ba94..cba36a2 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -1,7 +1,7 @@
 /*
  *  Interrupt handing routines for NEC VR4100 series.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  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
@@ -73,13 +73,19 @@
 	if (cascade->get_irq != NULL) {
 		unsigned int source_irq = irq;
 		desc = irq_desc + source_irq;
-		desc->chip->ack(source_irq);
+		if (desc->chip->mask_ack)
+			desc->chip->mask_ack(source_irq);
+		else {
+			desc->chip->mask(source_irq);
+			desc->chip->ack(source_irq);
+		}
 		irq = cascade->get_irq(irq);
 		if (irq < 0)
 			atomic_inc(&irq_err_count);
 		else
 			irq_dispatch(irq);
-		desc->chip->end(source_irq);
+		if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+			desc->chip->unmask(source_irq);
 	} else
 		do_IRQ(irq);
 }
@@ -89,27 +95,27 @@
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 
 	if (pending & CAUSEF_IP7)
-		do_IRQ(7);
+		do_IRQ(TIMER_IRQ);
 	else if (pending & 0x7800) {
 		if (pending & CAUSEF_IP3)
-			irq_dispatch(3);
+			irq_dispatch(INT1_IRQ);
 		else if (pending & CAUSEF_IP4)
-			irq_dispatch(4);
+			irq_dispatch(INT2_IRQ);
 		else if (pending & CAUSEF_IP5)
-			irq_dispatch(5);
+			irq_dispatch(INT3_IRQ);
 		else if (pending & CAUSEF_IP6)
-			irq_dispatch(6);
+			irq_dispatch(INT4_IRQ);
 	} else if (pending & CAUSEF_IP2)
-		irq_dispatch(2);
+		irq_dispatch(INT0_IRQ);
 	else if (pending & CAUSEF_IP0)
-		do_IRQ(0);
+		do_IRQ(MIPS_SOFTINT0_IRQ);
 	else if (pending & CAUSEF_IP1)
-		do_IRQ(1);
+		do_IRQ(MIPS_SOFTINT1_IRQ);
 	else
 		spurious_interrupt();
 }
 
 void __init arch_init_irq(void)
 {
-	mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
+	mips_cpu_irq_init();
 }
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
index 128ed8d..7d2d076 100644
--- a/arch/mips/vr41xx/nec-cmbvr4133/irq.c
+++ b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
@@ -21,60 +21,16 @@
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
+#include <asm/i8259.h>
 #include <asm/vr41xx/cmbvr4133.h>
 
-extern void enable_8259A_irq(unsigned int irq);
-extern void disable_8259A_irq(unsigned int irq);
-extern void mask_and_ack_8259A(unsigned int irq);
-extern void init_8259A(int hoge);
-
 extern int vr4133_rockhopper;
 
-static void enable_i8259_irq(unsigned int irq)
-{
-	enable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
-static void disable_i8259_irq(unsigned int irq)
-{
-	disable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
-static void ack_i8259_irq(unsigned int irq)
-{
-	mask_and_ack_8259A(irq - I8259_IRQ_BASE);
-}
-
-static struct irq_chip i8259_irq_type = {
-	.typename       = "XT-PIC",
-	.ack            = ack_i8259_irq,
-	.mask		= disable_i8259_irq,
-	.mask_ack	= ack_i8259_irq,
-	.unmask		= enable_i8259_irq,
-};
-
 static int i8259_get_irq_number(int irq)
 {
-	unsigned long isr;
-
-	isr = inb(0x20);
-	irq = ffz(~isr);
-	if (irq == 2) {
-		isr = inb(0xa0);
-		irq = 8 + ffz(~isr);
-	}
-
-	if (irq < 0 || irq > 15)
-		return -EINVAL;
-
-	return I8259_IRQ_BASE + irq;
+	return i8259_irq();
 }
 
-static struct irqaction i8259_slave_cascade = {
-	.handler        = &no_action,
-	.name           = "cascade",
-};
-
 void __init rockhopper_init_irq(void)
 {
 	int i;
@@ -84,11 +40,6 @@
 		return;
 	}
 
-	for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
-		set_irq_chip_and_handler(i, &i8259_irq_type, handle_level_irq);
-
-	setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
-
 	vr41xx_set_irq_trigger(CMBVR41XX_INTC_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
 	vr41xx_set_irq_level(CMBVR41XX_INTC_PIN, LEVEL_HIGH);
 	vr41xx_cascade_irq(CMBVR41XX_INTC_IRQ, i8259_get_irq_number);
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 4a23a97..12cc0193 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -608,7 +608,7 @@
 }
 
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	if (cpu != 0 && cpu < parisc_max_cpus)
 		smp_boot_one_cpu(cpu);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8699dad..d6abe49 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -436,7 +436,7 @@
 	select RTAS_PROC
 	select PPC_MPC52xx
 	select PPC_NATIVE
-	default y
+	default n
 
 config PPC_LITE5200
 	bool "Freescale Lite5200 Eval Board"
@@ -471,7 +471,7 @@
 	select PPC_INDIRECT_PCI
 	select PPC_UDBG_16550
 	select PPC_NATIVE
-	default y
+	default n
 
 config PPC_MAPLE
 	depends on PPC_MULTIPLATFORM && PPC64
@@ -484,6 +484,7 @@
 	select PPC_970_NAP
 	select PPC_NATIVE
 	select PPC_RTAS
+	select ATA_NONSTANDARD if ATA
 	default n
 	help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -525,12 +526,15 @@
 	select UDBG_RTAS_CONSOLE
 
 config PPC_PS3
-	bool "Sony PS3"
+	bool "Sony PS3 (incomplete)"
 	depends on PPC_MULTIPLATFORM && PPC64
 	select PPC_CELL
 	help
 	  This option enables support for the Sony PS3 game console
 	  and other platforms using the PS3 hypervisor.
+	  Support for this platform is not yet complete, so
+	  enabling this will not result in a bootable kernel on a
+	  PS3 system.
 
 config PPC_NATIVE
 	bool
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 8bc0d25..1868707 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -10,6 +10,12 @@
  * option) any later version.
  */
 
+/*
+ * WARNING: Do not depend on this tree layout remaining static just yet.
+ * The MPC5200 device tree conventions are still in flux
+ * Keep an eye on the linuxppc-dev mailing list for more details
+ */
+
 / {
 	model = "Lite5200";
 	compatible = "lite5200\0lite52xx\0mpc5200\0mpc52xx";
@@ -238,7 +244,7 @@
 
 		// PSC3 in CODEC mode example
 		i2s@2400 {		// PSC3
-			device_type = "i2s";
+			device_type = "sound";
 			compatible = "mpc5200-psc-i2s\0mpc52xx-psc-i2s";
 			reg = <2400 100>;
 			interrupts = <2 3 0>;
@@ -265,7 +271,7 @@
 
 		// PSC6 in AC97 mode example
 		ac97@2c00 {		// PSC6
-			device_type = "ac97";
+			device_type = "sound";
 			compatible = "mpc5200-psc-ac97\0mpc52xx-psc-ac97";
 			reg = <2c00 100>;
 			interrupts = <2 4 0>;
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 81cb764..5bb2760 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -10,6 +10,12 @@
  * option) any later version.
  */
 
+/*
+ * WARNING: Do not depend on this tree layout remaining static just yet.
+ * The MPC5200 device tree conventions are still in flux
+ * Keep an eye on the linuxppc-dev mailing list for more details
+ */
+
 / {
 	model = "Lite5200b";
 	compatible = "lite5200b\0lite52xx\0mpc5200b\0mpc52xx";
@@ -243,7 +249,7 @@
 
 		// PSC3 in CODEC mode example
 		i2s@2400 {		// PSC3
-			device_type = "i2s";
+			device_type = "sound";
 			compatible = "mpc5200b-psc-i2s\0mpc52xx-psc-i2s";
 			reg = <2400 100>;
 			interrupts = <2 3 0>;
@@ -270,7 +276,7 @@
 
 		// PSC6 in AC97 mode example
 		ac97@2c00 {		// PSC6
-			device_type = "ac97";
+			device_type = "sound";
 			compatible = "mpc5200b-psc-ac97\0mpc52xx-psc-ac97";
 			reg = <2c00 100>;
 			interrupts = <2 4 0>;
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index d1d2515..e956548 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc1
-# Tue Dec 19 14:59:53 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:12:56 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -245,7 +245,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCIEPORTBUS=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -854,7 +853,6 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
-CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_HVC_DRIVER=y
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index fee72f8..029c9a0 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:22:54 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:12:58 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
 #
 CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
@@ -59,18 +63,22 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -79,12 +87,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -103,6 +111,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -124,13 +133,16 @@
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 CONFIG_PPC_CHRP=y
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_EFIKA is not set
+# CONFIG_PPC_LITE5200 is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_NATIVE=y
 # CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
@@ -138,6 +150,8 @@
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_PPC_MPC106=y
 # CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_TAU is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
@@ -149,6 +163,7 @@
 CONFIG_HIGHMEM=y
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -161,6 +176,7 @@
 # CONFIG_KEXEC is not set
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -243,10 +259,13 @@
 # CONFIG_INET_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -263,24 +282,29 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 
 #
@@ -306,7 +330,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -381,6 +404,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -407,7 +436,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
@@ -422,6 +450,7 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -430,6 +459,7 @@
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+CONFIG_BLK_DEV_SL82C105=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 CONFIG_BLK_DEV_VIA82CXXX=y
@@ -445,6 +475,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -464,14 +496,16 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -487,12 +521,13 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_ATA is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -506,17 +541,18 @@
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 CONFIG_SCSI_SYM53C8XX_MMIO=y
-# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC395x is not set
@@ -525,6 +561,12 @@
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -557,6 +599,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -607,6 +650,7 @@
 # CONFIG_NET_ISA is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
@@ -655,6 +699,7 @@
 # CONFIG_MV643XX_ETH_0 is not set
 # CONFIG_MV643XX_ETH_1 is not set
 # CONFIG_MV643XX_ETH_2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -663,6 +708,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -690,6 +736,7 @@
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
@@ -710,6 +757,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -732,6 +780,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -778,12 +827,14 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_BRIQ_PANEL=m
 # CONFIG_HVC_RTAS is not set
 
 #
@@ -802,10 +853,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -814,7 +861,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -881,6 +927,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -889,14 +936,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -909,6 +951,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
+CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -949,6 +992,7 @@
 # CONFIG_FB_3DFX_ACCEL is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -979,6 +1023,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -993,6 +1042,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1034,13 +1084,13 @@
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
@@ -1070,6 +1120,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1087,6 +1138,7 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -1094,12 +1146,13 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1157,6 +1210,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1166,6 +1223,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1173,6 +1231,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1207,8 +1266,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -1308,17 +1369,22 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1329,8 +1395,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1345,14 +1414,16 @@
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
 # CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1367,7 +1438,11 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
@@ -1376,6 +1451,10 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 92d0a9d..7724847 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:22:55 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:15:04 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -10,6 +10,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,6 +24,8 @@
 CONFIG_PPC_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -30,6 +34,9 @@
 CONFIG_POWER4_ONLY=y
 CONFIG_POWER4=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -51,18 +58,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -71,12 +82,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -95,6 +106,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -114,23 +126,28 @@
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 # CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PMAC64=y
 # CONFIG_PPC_MAPLE is not set
+# CONFIG_PPC_PASEMI is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
 CONFIG_U3_DART=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_MPIC_BROKEN_U3=y
 # CONFIG_PPC_MPC106 is not set
 CONFIG_PPC_970_NAP=y
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -152,6 +169,7 @@
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -171,6 +189,7 @@
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -225,6 +244,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -243,10 +263,13 @@
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -263,24 +286,29 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -307,7 +335,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -382,6 +409,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -408,7 +441,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
@@ -423,6 +455,7 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -431,6 +464,7 @@
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -448,6 +482,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -467,14 +503,16 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -487,17 +525,42 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 CONFIG_ATA=y
 # CONFIG_SATA_AHCI is not set
 CONFIG_SATA_SVW=y
-# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_ATA_PIIX is not set
 # CONFIG_SATA_MV is not set
 # CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
-# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_PDC_ADMA is not set
 # CONFIG_SATA_QSTOR is not set
 # CONFIG_SATA_PROMISE is not set
 # CONFIG_SATA_SX4 is not set
@@ -507,22 +570,40 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -537,6 +618,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -591,11 +673,13 @@
 CONFIG_ADB_PMU=y
 # CONFIG_ADB_PMU_LED is not set
 CONFIG_PMAC_SMU=y
+CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_THERM_PM72=y
 CONFIG_WINDFARM=y
 CONFIG_WINDFARM_PM81=y
 CONFIG_WINDFARM_PM91=y
 CONFIG_WINDFARM_PM112=y
+# CONFIG_PMAC_RACKMETER is not set
 
 #
 # Network device support
@@ -652,7 +736,7 @@
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -661,6 +745,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -691,6 +776,7 @@
 # CONFIG_PPP_MPPE is not set
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
@@ -711,6 +797,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
 
 #
 # Userland interfaces
@@ -733,6 +820,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
@@ -789,13 +877,7 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=m
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
@@ -806,7 +888,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -871,6 +952,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -879,14 +961,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -899,6 +976,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
+CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -930,6 +1008,7 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -1080,6 +1159,11 @@
 # CONFIG_SOUND_PRIME is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1094,6 +1178,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1135,18 +1220,19 @@
 CONFIG_USB_STORAGE_JUMPSHOT=y
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 CONFIG_HID_FF=y
 CONFIG_HID_PID=y
 CONFIG_LOGITECH_FF=y
 CONFIG_THRUSTMASTER_FF=y
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
@@ -1174,12 +1260,14 @@
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET_MII is not set
 CONFIG_USB_USBNET=m
 # CONFIG_USB_NET_AX8817X is not set
 CONFIG_USB_NET_CDCETHER=m
 # CONFIG_USB_NET_GL620A is not set
 # CONFIG_USB_NET_NET1080 is not set
 # CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
@@ -1194,6 +1282,7 @@
 #
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ARK3116 is not set
 CONFIG_USB_SERIAL_BELKIN=m
@@ -1228,6 +1317,8 @@
 CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=m
 # CONFIG_USB_SERIAL_HP4X is not set
@@ -1239,6 +1330,7 @@
 CONFIG_USB_SERIAL_XIRCOM=m
 # CONFIG_USB_SERIAL_OPTION is not set
 CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
 CONFIG_USB_EZUSB=y
 
 #
@@ -1246,6 +1338,7 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -1253,12 +1346,13 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1316,6 +1410,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1328,6 +1426,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1344,6 +1443,7 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1380,8 +1480,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1505,17 +1607,22 @@
 CONFIG_NLS_UTF8=y
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1528,8 +1635,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1543,9 +1653,10 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -1565,7 +1676,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1574,9 +1690,14 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index b500550..5fc8744 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc1
-# Fri Oct  6 13:25:04 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:16:44 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -10,6 +10,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -32,6 +35,9 @@
 CONFIG_POWER3=y
 CONFIG_POWER4=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -63,12 +69,13 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -125,18 +132,22 @@
 # CONFIG_APUS is not set
 # CONFIG_PPC_PSERIES is not set
 CONFIG_PPC_ISERIES=y
+# CONFIG_PPC_MPC52xx is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_PPC_PS3 is not set
 # CONFIG_U3_DART is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
+CONFIG_PPC_INDIRECT_IO=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 # CONFIG_MPIC is not set
@@ -146,6 +157,7 @@
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -178,6 +190,7 @@
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
@@ -192,7 +205,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -245,6 +257,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -261,21 +274,37 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 # CONFIG_NETFILTER_XT_MATCH_DCCP is not set
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 # CONFIG_NETFILTER_XT_MATCH_ESP is not set
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
@@ -286,27 +315,17 @@
 # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
 # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -317,23 +336,25 @@
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -440,6 +461,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -449,6 +476,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -469,6 +497,7 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -515,6 +544,7 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -562,6 +592,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -647,6 +678,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -765,10 +797,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
@@ -779,7 +807,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -795,6 +822,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -803,11 +831,6 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -822,6 +845,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -830,6 +854,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -892,6 +921,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -904,6 +937,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -937,6 +971,7 @@
 CONFIG_AUTOFS_FS=m
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1024,7 +1059,6 @@
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 # CONFIG_9P_FS is not set
-CONFIG_GENERIC_ACL=y
 
 #
 # Partition Types
@@ -1080,6 +1114,8 @@
 # Distributed Lock Manager
 #
 CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
 # CONFIG_DLM_DEBUG is not set
 
 #
@@ -1094,6 +1130,7 @@
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1105,6 +1142,7 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1119,6 +1157,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1132,8 +1172,8 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
@@ -1142,6 +1182,7 @@
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
+# CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1155,10 +1196,11 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER=y
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1167,8 +1209,10 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index 23fd210..405c1c9 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Wed Nov 15 20:36:30 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:17:58 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
 #
 CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -69,12 +70,13 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -130,6 +132,7 @@
 # CONFIG_PPC_MULTIPLATFORM is not set
 CONFIG_EMBEDDED6xx=y
 # CONFIG_APUS is not set
+# CONFIG_PPC_MPC52xx is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_RTAS is not set
@@ -166,7 +169,6 @@
 # CONFIG_TQM8260 is not set
 # CONFIG_ADS8272 is not set
 # CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
 # CONFIG_EV64360 is not set
 CONFIG_PPC_GEN550=y
 CONFIG_MPC10X_BRIDGE=y
@@ -181,6 +183,7 @@
 # CONFIG_HIGHMEM is not set
 CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
 CONFIG_PREEMPT_NONE=y
@@ -217,7 +220,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -286,6 +288,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -302,18 +305,35 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 # CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
 # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 # CONFIG_NETFILTER_XT_MATCH_DCCP is not set
 # CONFIG_NETFILTER_XT_MATCH_DSCP is not set
 CONFIG_NETFILTER_XT_MATCH_ESP=m
-# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
@@ -324,27 +344,17 @@
 # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 # CONFIG_NETFILTER_XT_MATCH_REALM is not set
 # CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
 # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 # CONFIG_NETFILTER_XT_MATCH_STRING is not set
 # CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -355,22 +365,25 @@
 # CONFIG_IP_NF_MATCH_TTL is not set
 # CONFIG_IP_NF_MATCH_OWNER is not set
 # CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 # CONFIG_IP_NF_TARGET_LOG is not set
 # CONFIG_IP_NF_TARGET_ULOG is not set
 # CONFIG_IP_NF_TARGET_TCPMSS is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -580,6 +593,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -599,6 +613,7 @@
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -646,6 +661,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -683,6 +699,7 @@
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -726,6 +743,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -777,6 +795,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -899,6 +918,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -921,10 +941,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -1032,6 +1048,7 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -1042,6 +1059,7 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
@@ -1063,6 +1081,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 
 #
 # Console display driver support
@@ -1077,6 +1096,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1091,6 +1115,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1170,6 +1195,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1218,6 +1244,7 @@
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OPTION is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
 
 #
 # USB Miscellaneous drivers
@@ -1324,6 +1351,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1398,7 +1429,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1488,8 +1518,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1497,6 +1533,7 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1511,6 +1548,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1524,12 +1563,11 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
@@ -1551,6 +1589,7 @@
 CONFIG_CRYPTO_BLKCIPHER=y
 CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1559,8 +1598,10 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig
index ee76557..8cbd87d 100644
--- a/arch/powerpc/configs/lite5200_defconfig
+++ b/arch/powerpc/configs/lite5200_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Mon Nov 27 11:08:20 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:18:18 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
 #
 CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -68,6 +69,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -151,6 +153,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -259,6 +262,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -374,6 +378,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -393,6 +398,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -440,6 +446,7 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -477,7 +484,7 @@
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
 # CONFIG_PATA_TRIFLEX is not set
-CONFIG_PATA_MPC52xx=y
+# CONFIG_PATA_MARVELL is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
 # CONFIG_PATA_NETCELL is not set
@@ -494,6 +501,7 @@
 # CONFIG_PATA_SIS is not set
 # CONFIG_PATA_VIA is not set
 # CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -521,6 +529,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -572,6 +581,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -632,6 +642,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_MPC52xx=y
@@ -657,10 +668,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -707,6 +714,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -777,6 +785,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -873,6 +885,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
@@ -880,6 +897,7 @@
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -893,6 +911,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -906,12 +926,11 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index ae96a5b..de97f2f 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Mon Oct  9 11:59:34 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:19:02 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -10,6 +10,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@
 CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -31,6 +34,9 @@
 CONFIG_POWER4_ONLY=y
 CONFIG_POWER4=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -61,12 +67,13 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -123,18 +130,27 @@
 # CONFIG_APUS is not set
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_MAPLE=y
 # CONFIG_PPC_PASEMI is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
 CONFIG_U3_DART=y
-# CONFIG_PPC_RTAS is not set
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_RTAS_FLASH is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_MPIC_BROKEN_U3=y
 # CONFIG_PPC_MPC106 is not set
 CONFIG_PPC_970_NAP=y
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 CONFIG_MPIC=y
@@ -144,6 +160,7 @@
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -190,7 +207,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -246,6 +262,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -346,6 +363,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -371,7 +394,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
@@ -395,6 +417,7 @@
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -439,6 +462,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -523,6 +547,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -618,6 +643,8 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
 
 #
 # IPMI
@@ -634,10 +661,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -647,7 +670,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -711,6 +733,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -719,15 +742,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -740,6 +757,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 
 #
 # Console display driver support
@@ -754,6 +772,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -768,6 +791,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -803,7 +827,6 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
@@ -819,7 +842,6 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
 
 #
 # USB Imaging devices
@@ -833,6 +855,7 @@
 # CONFIG_USB_KAWETH is not set
 CONFIG_USB_PEGASUS=y
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -881,6 +904,7 @@
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
 # CONFIG_USB_SERIAL_MOS7840 is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
@@ -892,6 +916,7 @@
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OPTION is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
 CONFIG_USB_EZUSB=y
 
 #
@@ -913,6 +938,7 @@
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -970,6 +996,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -978,12 +1008,14 @@
 CONFIG_FS_XIP=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1133,14 +1165,21 @@
 CONFIG_NLS_UTF8=y
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1155,6 +1194,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1169,8 +1210,8 @@
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
@@ -1180,6 +1221,7 @@
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
 # CONFIG_IRQSTACKS is not set
 CONFIG_BOOTX_TEXT=y
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1195,9 +1237,10 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1206,8 +1249,10 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index d1811e7..fdf09ea 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:26:55 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:20:53 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
@@ -58,16 +62,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -75,12 +83,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -93,6 +101,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -114,19 +123,19 @@
 # Platform support
 #
 # CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_PPC_ISERIES is not set
 CONFIG_EMBEDDED6xx=y
 # CONFIG_APUS is not set
+# CONFIG_PPC_MPC52xx is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_UDBG_RTAS_CONSOLE is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_TAU is not set
-# CONFIG_PPC_TODC is not set
 # CONFIG_KATANA is not set
 # CONFIG_WILLOW is not set
 # CONFIG_CPCI690 is not set
@@ -141,6 +150,7 @@
 # CONFIG_PRPMC750 is not set
 # CONFIG_PRPMC800 is not set
 # CONFIG_SANDPOINT is not set
+# CONFIG_LINKSTATION is not set
 CONFIG_MPC7448HPC2=y
 # CONFIG_RADSTONE_PPC7D is not set
 # CONFIG_PAL4 is not set
@@ -152,7 +162,6 @@
 # CONFIG_TQM8260 is not set
 # CONFIG_ADS8272 is not set
 # CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
 # CONFIG_EV64360 is not set
 CONFIG_TSI108_BRIDGE=y
 # CONFIG_WANT_EARLY_SERIAL is not set
@@ -164,6 +173,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -173,6 +183,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -237,6 +248,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -258,10 +270,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -291,7 +306,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -362,6 +376,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -371,6 +391,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -389,14 +411,16 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -409,18 +433,44 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 CONFIG_ATA=y
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
-# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_ATA_PIIX is not set
 CONFIG_SATA_MV=y
 # CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
-# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_PDC_ADMA is not set
 # CONFIG_SATA_QSTOR is not set
 # CONFIG_SATA_PROMISE is not set
 # CONFIG_SATA_SX4 is not set
@@ -430,23 +480,41 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -474,6 +542,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -505,6 +574,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -563,6 +633,8 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+CONFIG_TSI108_ETH=y
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -571,6 +643,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -610,6 +683,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -654,6 +728,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -677,10 +752,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -689,7 +760,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -705,6 +775,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -713,17 +784,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -735,6 +803,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -743,6 +812,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -805,6 +879,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -814,6 +892,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -821,6 +900,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -850,8 +930,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -921,13 +1003,20 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -938,12 +1027,14 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
@@ -957,7 +1048,3 @@
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index 0561b73..45757b6 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Mon Sep 25 19:41:14 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:23:43 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
@@ -40,6 +41,8 @@
 CONFIG_6xx=y
 CONFIG_83xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_SMP is not set
@@ -59,16 +62,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
 CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
@@ -98,6 +105,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -120,8 +128,10 @@
 #
 # Platform support
 #
+# CONFIG_MPC832x_MDS is not set
 # CONFIG_MPC834x_SYS is not set
 CONFIG_MPC834x_ITX=y
+# CONFIG_MPC8360E_PB is not set
 CONFIG_MPC834x=y
 # CONFIG_MPIC is not set
 
@@ -131,6 +141,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -138,8 +149,10 @@
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -206,6 +219,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -227,10 +241,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -411,9 +428,16 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 # CONFIG_BLK_DEV_IDE is not set
 # CONFIG_BLK_DEV_HD_ONLY is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -423,6 +447,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -441,14 +467,16 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -461,18 +489,44 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
 CONFIG_ATA=y
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SVW is not set
-# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_ATA_PIIX is not set
 # CONFIG_SATA_MV is not set
 # CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
-# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_PDC_ADMA is not set
 # CONFIG_SATA_QSTOR is not set
 # CONFIG_SATA_PROMISE is not set
 # CONFIG_SATA_SX4 is not set
@@ -482,23 +536,41 @@
 # CONFIG_SATA_ULI is not set
 # CONFIG_SATA_VIA is not set
 # CONFIG_SATA_VITESSE is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -535,6 +607,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -566,6 +639,7 @@
 CONFIG_CICADA_PHY=y
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -622,6 +696,7 @@
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -630,6 +705,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -669,6 +745,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -713,6 +790,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -753,10 +831,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -765,7 +839,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -842,6 +915,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -876,29 +950,27 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -911,6 +983,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -919,6 +992,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -933,6 +1011,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -972,6 +1051,7 @@
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -1010,6 +1090,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1027,6 +1108,7 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -1034,12 +1116,13 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1067,6 +1150,7 @@
 # CONFIG_USB_GADGETFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
 
 #
 # MMC/SD Card support
@@ -1102,6 +1186,7 @@
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
 CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
 
 #
 # RTC interfaces
@@ -1145,6 +1230,10 @@
 CONFIG_INTEL_IOATDMA=y
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1154,6 +1243,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1161,6 +1251,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1190,8 +1281,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -1206,7 +1299,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1249,6 +1341,10 @@
 # CONFIG_ATARI_PARTITION is not set
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
@@ -1262,13 +1358,20 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1279,8 +1382,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1294,9 +1400,10 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
@@ -1316,8 +1423,10 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
-# CONFIG_CRYPTO_MANAGER is not set
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -1326,8 +1435,10 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 9eefab9..c24db58 100644
--- a/arch/powerpc/configs/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:28:54 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:24:10 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
@@ -39,6 +41,8 @@
 CONFIG_6xx=y
 CONFIG_83xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_SMP is not set
@@ -58,28 +62,32 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -97,6 +105,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -119,8 +128,10 @@
 #
 # Platform support
 #
+# CONFIG_MPC832x_MDS is not set
 CONFIG_MPC834x_SYS=y
 # CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC8360E_PB is not set
 CONFIG_MPC834x=y
 # CONFIG_MPIC is not set
 
@@ -130,6 +141,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -137,8 +149,10 @@
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -204,6 +218,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -225,10 +240,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -258,7 +276,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -329,6 +346,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -338,6 +361,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -362,6 +391,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -393,6 +423,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -449,6 +480,7 @@
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 # CONFIG_GFAR_NAPI is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -457,6 +489,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -495,6 +528,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -539,6 +573,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -575,10 +610,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -587,7 +618,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -653,6 +683,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -686,29 +717,27 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -720,6 +749,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -728,6 +758,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -790,6 +825,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -799,6 +838,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -806,6 +846,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -835,8 +876,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -905,13 +948,20 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -922,11 +972,14 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -941,7 +994,11 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -950,6 +1007,10 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc8360emds_defconfig b/arch/powerpc/configs/mpc8360emds_defconfig
index c070341..58e6795 100644
--- a/arch/powerpc/configs/mpc8360emds_defconfig
+++ b/arch/powerpc/configs/mpc8360emds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Thu Sep 21 18:14:27 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:24:40 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 CONFIG_PPC_83xx=y
 # CONFIG_PPC_85xx is not set
@@ -40,6 +41,8 @@
 CONFIG_6xx=y
 CONFIG_83xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_SMP is not set
@@ -59,16 +62,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
 CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
@@ -98,6 +105,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -121,6 +129,7 @@
 #
 # Platform support
 #
+# CONFIG_MPC832x_MDS is not set
 # CONFIG_MPC834x_SYS is not set
 # CONFIG_MPC834x_ITX is not set
 CONFIG_MPC8360E_PB=y
@@ -133,6 +142,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -140,8 +150,10 @@
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -207,6 +219,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -228,10 +241,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -331,6 +347,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -340,6 +362,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -358,14 +382,16 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -378,11 +404,12 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -392,15 +419,22 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -428,6 +462,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -488,6 +523,7 @@
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_FILTERING is not set
 # CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -496,6 +532,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -535,6 +572,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -579,6 +617,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -615,10 +654,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -627,7 +662,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -693,6 +727,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -726,29 +761,27 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -760,6 +793,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -768,6 +802,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -830,6 +869,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -839,6 +882,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -846,6 +890,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -875,8 +920,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -945,20 +992,27 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # QE Options
 #
-# CONFIG_UCC_SLOW is not set
+CONFIG_UCC_SLOW=y
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -969,11 +1023,14 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_SERIAL_TEXT_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -988,7 +1045,11 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
 # CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
@@ -997,6 +1058,10 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 67e7d0b..17120c4 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:29:23 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:25:24 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_BOOKE=y
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
@@ -58,16 +62,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,12 +84,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -94,6 +102,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -116,6 +125,7 @@
 # Platform support
 #
 CONFIG_MPC8540_ADS=y
+# CONFIG_MPC8560_ADS is not set
 # CONFIG_MPC85xx_CDS is not set
 CONFIG_MPC8540=y
 CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -127,6 +137,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -137,6 +148,7 @@
 CONFIG_MATH_EMULATION=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -199,6 +211,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -220,10 +233,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -253,7 +269,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -320,6 +335,11 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -329,6 +349,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -351,6 +377,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -377,6 +404,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -429,6 +457,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -472,6 +501,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
@@ -493,17 +523,12 @@
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -519,6 +544,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -527,17 +553,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -549,6 +572,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -557,6 +581,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -617,6 +646,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -626,6 +659,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -633,6 +667,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -662,8 +697,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -729,13 +766,20 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -746,8 +790,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -761,10 +808,10 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
@@ -782,7 +829,3 @@
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
index ddc2a7b..ecaa267 100644
--- a/arch/powerpc/configs/mpc8560_ads_defconfig
+++ b/arch/powerpc/configs/mpc8560_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc4
-# Fri Aug 11 16:45:05 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:25:53 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_BOOKE=y
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
@@ -58,16 +62,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,12 +84,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -94,6 +102,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -110,7 +119,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_MPIC=y
 CONFIG_CPM2=y
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -122,6 +130,7 @@
 # CONFIG_MPC85xx_CDS is not set
 CONFIG_MPC8560=y
 CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPIC=y
 
 #
 # Kernel options
@@ -129,6 +138,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -140,6 +150,7 @@
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_PC_KEYBOARD is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -152,13 +163,13 @@
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
-# CONFIG_SOFTWARE_SUSPEND is not set
 # CONFIG_SECCOMP is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+# CONFIG_MPIC_WEIRD is not set
 # CONFIG_PPC_I8259 is not set
 CONFIG_PPC_INDIRECT_PCI=y
 CONFIG_FSL_SOC=y
@@ -205,6 +216,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -226,10 +238,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -259,7 +274,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -331,6 +345,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -340,6 +360,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -364,6 +390,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -395,6 +422,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -437,6 +465,7 @@
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -445,6 +474,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -483,6 +513,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -522,6 +553,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_CPM=y
@@ -536,7 +568,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_BRIQ_PANEL is not set
 
 #
 # IPMI
@@ -554,10 +585,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -566,7 +593,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -582,6 +608,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -590,17 +617,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -612,6 +636,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -620,6 +645,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -682,6 +712,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -691,6 +725,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -698,6 +733,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -727,8 +763,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -794,13 +832,20 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -811,8 +856,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -826,10 +874,10 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
@@ -848,7 +896,3 @@
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
index 72edf9f..1f61bce 100644
--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:29:49 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:26:46 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_85xx=y
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_85xx=y
 CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_BOOKE=y
 CONFIG_FSL_BOOKE=y
 # CONFIG_PHYS_64BIT is not set
@@ -58,16 +62,20 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,12 +84,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -94,6 +102,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -116,6 +125,7 @@
 # Platform support
 #
 # CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8560_ADS is not set
 CONFIG_MPC85xx_CDS=y
 CONFIG_MPC8540=y
 CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -127,6 +137,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -137,6 +148,7 @@
 CONFIG_MATH_EMULATION=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -202,6 +214,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -223,10 +236,13 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -256,7 +272,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -328,9 +343,16 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -353,7 +375,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 # CONFIG_IDEDMA_PCI_AUTO is not set
@@ -367,6 +388,7 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -375,6 +397,7 @@
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 CONFIG_BLK_DEV_VIA82CXXX=y
@@ -389,6 +412,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -413,6 +442,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -444,6 +474,7 @@
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -483,6 +514,7 @@
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -491,6 +523,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -529,6 +562,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -573,6 +607,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -596,10 +631,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -608,7 +639,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -624,6 +654,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -632,17 +663,14 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -654,6 +682,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -662,6 +691,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -724,6 +758,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -733,6 +771,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -740,6 +779,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -769,8 +809,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -836,13 +878,20 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -853,8 +902,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -868,10 +920,10 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
@@ -889,7 +941,3 @@
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index 92a527f..53fcd69 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:30:15 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:27:14 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
 #
 # CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
@@ -62,15 +66,18 @@
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -79,15 +86,15 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-# CONFIG_SLAB is not set
+CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-CONFIG_SLOB=y
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -97,6 +104,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -129,6 +137,7 @@
 CONFIG_HIGHMEM=y
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 CONFIG_HZ_1000=y
 CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
@@ -140,6 +149,7 @@
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_IRQ_ALL_CPUS is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -206,6 +216,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -226,21 +237,29 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 CONFIG_INET6_XFRM_MODE_TRANSPORT=y
 CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
 # CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
@@ -267,7 +286,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -339,6 +357,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
@@ -348,6 +372,12 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -372,6 +402,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -403,6 +434,7 @@
 # CONFIG_CICADA_PHY is not set
 CONFIG_VITESSE_PHY=y
 # CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
 # CONFIG_FIXED_PHY is not set
 
 #
@@ -440,6 +472,7 @@
 # CONFIG_BNX2 is not set
 CONFIG_GIANFAR=y
 # CONFIG_GFAR_NAPI is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -448,6 +481,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -486,6 +520,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -542,6 +577,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
@@ -563,10 +599,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -575,7 +607,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -640,6 +671,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -648,14 +680,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -667,6 +694,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 
 #
 # Console display driver support
@@ -682,6 +710,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -744,6 +777,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -753,6 +790,7 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -760,6 +798,7 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -788,8 +827,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -904,13 +945,20 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -921,12 +969,16 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -936,10 +988,10 @@
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
@@ -957,7 +1009,3 @@
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index 765c8bb..f611df4 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:30:23 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:28:56 2007
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@
 CONFIG_PPC_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
 # Processor support
 #
 CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@
 # CONFIG_E200 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
@@ -58,17 +62,21 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -77,12 +85,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -100,6 +108,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 CONFIG_LSF=y
@@ -121,18 +130,22 @@
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 # CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_EFIKA is not set
+# CONFIG_PPC_LITE5200 is not set
 CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_PPC_NATIVE=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_PPC_MPC106=y
 # CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -157,6 +170,7 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -167,6 +181,7 @@
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_KEXEC is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -181,6 +196,8 @@
 CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 CONFIG_PM_DEBUG=y
+# CONFIG_DISABLE_CONSOLE_SUSPEND is not set
+CONFIG_PM_SYSFS_DEPRECATED=y
 CONFIG_SOFTWARE_SUSPEND=y
 CONFIG_PM_STD_PARTITION=""
 CONFIG_SECCOMP=y
@@ -254,6 +271,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -272,10 +290,13 @@
 # CONFIG_INET_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -292,14 +313,33 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -312,61 +352,49 @@
 # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
 # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_NETBIOS_NS=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_PPTP=m
-CONFIG_IP_NF_NAT_H323=m
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
 CONFIG_IP_NF_ARPTABLES=m
@@ -384,8 +412,11 @@
 # DCCP CCIDs Configuration (EXPERIMENTAL)
 #
 CONFIG_IP_DCCP_CCID2=m
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
 CONFIG_IP_DCCP_CCID3=m
 CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
 
 #
 # DCCP Kernel Hacking
@@ -410,7 +441,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -567,6 +597,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -594,7 +630,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
@@ -609,6 +644,7 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -617,6 +653,7 @@
 CONFIG_BLK_DEV_PDC202XX_NEW=y
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+CONFIG_BLK_DEV_SL82C105=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -634,6 +671,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -653,14 +692,16 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -678,11 +719,12 @@
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 CONFIG_SCSI_AIC7XXX_OLD=m
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_ATA is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -692,14 +734,15 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 CONFIG_SCSI_SYM53C8XX_MMIO=y
-# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -709,6 +752,7 @@
 CONFIG_SCSI_MESH_SYNC_RATE=5
 CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
 CONFIG_SCSI_MAC53C94=y
+# CONFIG_SCSI_SRP is not set
 
 #
 # PCMCIA SCSI adapter support
@@ -720,6 +764,11 @@
 # CONFIG_PCMCIA_SYM53C500 is not set
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 CONFIG_MD=y
@@ -732,6 +781,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -798,6 +848,7 @@
 CONFIG_THERM_ADT746X=m
 # CONFIG_WINDFARM is not set
 # CONFIG_ANSLCD is not set
+CONFIG_PMAC_RACKMETER=m
 
 #
 # Network device support
@@ -838,6 +889,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -874,6 +926,7 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -882,6 +935,7 @@
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -957,6 +1011,7 @@
 # CONFIG_PPP_MPPE is not set
 # CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
+CONFIG_SLHC=y
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
@@ -977,6 +1032,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -999,6 +1055,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
@@ -1039,6 +1096,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=m
 CONFIG_SERIAL_PMACZILOG=m
 # CONFIG_SERIAL_JSM is not set
@@ -1062,13 +1120,7 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 CONFIG_AGP=m
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 CONFIG_DRM=m
 # CONFIG_DRM_TDFX is not set
@@ -1091,7 +1143,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -1167,14 +1218,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1187,6 +1233,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB=y
+CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1235,6 +1282,7 @@
 # CONFIG_FB_3DFX_ACCEL is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -1393,6 +1441,11 @@
 # CONFIG_SOUND_PRIME is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1408,6 +1461,7 @@
 # CONFIG_USB_BANDWIDTH is not set
 CONFIG_USB_DYNAMIC_MINORS=y
 # CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1448,13 +1502,13 @@
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 CONFIG_USB_HIDINPUT_POWERBOOK=y
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
@@ -1484,12 +1538,14 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET_MII=m
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_AX8817X=m
 CONFIG_USB_NET_CDCETHER=m
 # CONFIG_USB_NET_GL620A is not set
 CONFIG_USB_NET_NET1080=m
 # CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 CONFIG_USB_NET_ZAURUS=m
@@ -1504,6 +1560,7 @@
 #
 CONFIG_USB_SERIAL=m
 # CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ARK3116 is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
@@ -1538,6 +1595,8 @@
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_HP4X is not set
@@ -1548,6 +1607,7 @@
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OPTION is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
 CONFIG_USB_EZUSB=y
 
 #
@@ -1555,6 +1615,7 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -1562,12 +1623,13 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1630,6 +1692,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1639,6 +1705,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1646,6 +1713,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1682,8 +1750,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
@@ -1802,8 +1872,14 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 CONFIG_CRC32=y
@@ -1815,6 +1891,7 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1826,8 +1903,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1841,14 +1921,16 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
 # CONFIG_BDI_SWITCH is not set
 CONFIG_BOOTX_TEXT=y
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1863,7 +1945,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1872,9 +1959,14 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 1c00965..debac66 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:45:11 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:28:58 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -10,6 +10,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,6 +24,8 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -31,6 +35,10 @@
 CONFIG_POWER3=y
 CONFIG_POWER4=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+CONFIG_PPC_DCR_MMIO=y
+CONFIG_PPC_DCR=y
+CONFIG_PPC_OF_PLATFORM_PCI=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -52,19 +60,24 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_TASK_XACCT is not set
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -73,12 +86,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -97,6 +110,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 
 #
@@ -116,16 +130,20 @@
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 CONFIG_PPC_PSERIES=y
+CONFIG_PPC_ISERIES=y
+# CONFIG_PPC_MPC52xx is not set
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PMAC64=y
 CONFIG_PPC_MAPLE=y
+# CONFIG_PPC_PASEMI is not set
 CONFIG_PPC_CELL=y
 CONFIG_PPC_CELL_NATIVE=y
 CONFIG_PPC_IBM_CELL_BLADE=y
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
 CONFIG_UDBG_RTAS_CONSOLE=y
 CONFIG_XICS=y
 CONFIG_U3_DART=y
@@ -139,6 +157,8 @@
 # CONFIG_IBMEBUS is not set
 # CONFIG_PPC_MPC106 is not set
 CONFIG_PPC_970_NAP=y
+CONFIG_PPC_INDIRECT_IO=y
+CONFIG_GENERIC_IOMAP=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -160,14 +180,16 @@
 #
 CONFIG_SPU_FS=m
 CONFIG_SPU_BASE=y
-CONFIG_SPUFS_MMAP=y
 CONFIG_CBE_RAS=y
+CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
 
 #
 # Kernel options
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -192,6 +214,7 @@
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -201,6 +224,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPARSEMEM_EXTREME=y
 CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
 CONFIG_ARCH_MEMORY_PROBE=y
@@ -254,6 +278,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -272,10 +297,13 @@
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -294,25 +322,31 @@
 CONFIG_NETFILTER_NETLINK=y
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -339,7 +373,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -412,6 +445,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -438,7 +477,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
@@ -453,6 +491,7 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -461,6 +500,7 @@
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+CONFIG_BLK_DEV_SL82C105=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -478,6 +518,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -497,14 +539,16 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -517,26 +561,12 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
-# CONFIG_SATA_AHCI is not set
-CONFIG_SATA_SVW=y
-# CONFIG_SCSI_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
 # CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -546,6 +576,7 @@
 CONFIG_SCSI_IBMVSCSI=y
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
@@ -556,10 +587,66 @@
 CONFIG_SCSI_IPR_DUMP=y
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SVW=y
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -575,6 +662,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -630,11 +718,13 @@
 CONFIG_ADB_PMU=y
 # CONFIG_ADB_PMU_LED is not set
 CONFIG_PMAC_SMU=y
+# CONFIG_MAC_EMUMOUSEBTN is not set
 CONFIG_THERM_PM72=y
 CONFIG_WINDFARM=y
 CONFIG_WINDFARM_PM81=y
 CONFIG_WINDFARM_PM91=y
 CONFIG_WINDFARM_PM112=y
+# CONFIG_PMAC_RACKMETER is not set
 
 #
 # Network device support
@@ -675,6 +765,7 @@
 CONFIG_IBMVETH=m
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -713,7 +804,7 @@
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=m
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -723,6 +814,7 @@
 # CONFIG_IXGB_NAPI is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -741,6 +833,7 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+CONFIG_ISERIES_VETH=m
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 CONFIG_PPP=m
@@ -753,6 +846,7 @@
 # CONFIG_PPP_MPPE is not set
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
@@ -775,6 +869,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -797,6 +892,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -850,6 +946,7 @@
 CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_HVC_DRIVER=y
 CONFIG_HVC_CONSOLE=y
+CONFIG_HVC_ISERIES=y
 CONFIG_HVC_RTAS=y
 CONFIG_HVCS=m
 
@@ -868,10 +965,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
@@ -882,7 +975,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -947,6 +1039,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -955,14 +1048,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -975,6 +1063,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
+CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1011,6 +1100,7 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+CONFIG_FB_IBM_GXT4500=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -1159,6 +1249,11 @@
 # CONFIG_SOUND_PRIME is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1173,6 +1268,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1214,13 +1310,13 @@
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
@@ -1250,6 +1346,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
@@ -1267,6 +1364,7 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -1274,12 +1372,13 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1318,6 +1417,7 @@
 CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_AMSO1100 is not set
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
@@ -1347,6 +1447,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1359,6 +1463,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1379,6 +1484,7 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1414,8 +1520,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1540,8 +1648,23 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# iSeries device drivers
+#
+# CONFIG_VIOCONS is not set
+CONFIG_VIODASD=y
+CONFIG_VIOCD=m
+CONFIG_VIOTAPE=m
+CONFIG_VIOPATH=y
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
@@ -1551,6 +1674,7 @@
 CONFIG_TEXTSEARCH=y
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1563,8 +1687,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1578,16 +1705,19 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_HCALL_STATS is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 # CONFIG_XMON_DEFAULT is not set
+CONFIG_XMON_DISASSEMBLY=y
 CONFIG_IRQSTACKS=y
 CONFIG_BOOTX_TEXT=y
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1602,7 +1732,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1611,9 +1746,14 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 70ed613..3256087 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Tue Nov 21 19:38:53 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:29:11 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -10,6 +10,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -64,6 +67,7 @@
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -126,6 +130,7 @@
 # CONFIG_APUS is not set
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
@@ -164,6 +169,7 @@
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -261,6 +267,7 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -366,6 +373,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -385,6 +393,7 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -427,6 +436,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -549,10 +559,6 @@
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HANGCHECK_TIMER is not set
 
@@ -598,6 +604,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
 
 #
 # Console display driver support
@@ -612,6 +619,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
@@ -672,6 +684,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
@@ -772,6 +788,11 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
@@ -779,6 +800,7 @@
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -793,6 +815,8 @@
 CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -806,12 +830,11 @@
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_DEBUG_LIST=y
 CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index d2833c1..1c794fe 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:45:12 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:31:27 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -10,6 +10,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,6 +24,8 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -31,6 +35,9 @@
 CONFIG_POWER3=y
 CONFIG_POWER4=y
 CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -52,19 +59,22 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -73,12 +83,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -97,6 +107,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -116,15 +127,19 @@
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 CONFIG_PPC_PSERIES=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
+# CONFIG_PPC_PASEMI is not set
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
 # CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_XICS=y
 # CONFIG_U3_DART is not set
@@ -137,6 +152,8 @@
 CONFIG_IBMEBUS=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 CONFIG_MPIC=y
@@ -146,6 +163,7 @@
 #
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
@@ -170,6 +188,7 @@
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -183,7 +202,6 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
-CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_NODES_SPAN_OTHER_NODES=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
@@ -235,6 +253,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -253,10 +272,13 @@
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 
 #
 # IP: Virtual Server Configuration
@@ -275,25 +297,30 @@
 CONFIG_NETFILTER_NETLINK=y
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -320,7 +347,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -402,6 +428,12 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -428,7 +460,6 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
@@ -443,6 +474,7 @@
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -451,6 +483,7 @@
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
+CONFIG_BLK_DEV_SL82C105=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -465,6 +498,8 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -484,14 +519,16 @@
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -504,10 +541,11 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -520,6 +558,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
@@ -530,10 +569,66 @@
 CONFIG_SCSI_IPR_DUMP=y
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA_FC=m
+# CONFIG_SCSI_QLA_ISCSI is not set
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -548,6 +643,7 @@
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -576,6 +672,7 @@
 #
 # Macintosh device drivers
 #
+# CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 
 #
@@ -617,6 +714,7 @@
 CONFIG_IBMVETH=y
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -655,17 +753,19 @@
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+CONFIG_EHEA=m
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -697,6 +797,7 @@
 # CONFIG_PPP_MPPE is not set
 CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
@@ -719,6 +820,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -741,6 +843,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
@@ -815,10 +918,6 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
@@ -829,7 +928,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -894,6 +992,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -902,14 +1001,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -922,6 +1016,7 @@
 #
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
+CONFIG_FB_DDC=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -957,6 +1052,7 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+CONFIG_FB_IBM_GXT4500=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -989,6 +1085,11 @@
 # CONFIG_SOUND is not set
 
 #
+# HID Devices
+#
+CONFIG_HID=y
+
+#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1003,6 +1104,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1043,13 +1145,13 @@
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
@@ -1079,6 +1181,7 @@
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 CONFIG_USB_MON=y
 
@@ -1097,6 +1200,7 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -1104,12 +1208,13 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1148,6 +1253,9 @@
 CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_EHCA=m
+CONFIG_INFINIBAND_EHCA_SCALING=y
+# CONFIG_INFINIBAND_AMSO1100 is not set
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
@@ -1177,6 +1285,10 @@
 #
 
 #
+# Virtualization
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1189,6 +1301,7 @@
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -1209,6 +1322,7 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
 CONFIG_OCFS2_FS=m
 CONFIG_OCFS2_DEBUG_MASKLOG=y
 # CONFIG_MINIX_FS is not set
@@ -1246,8 +1360,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1357,17 +1473,22 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
 
 #
 # Instrumentation Support
@@ -1380,8 +1501,11 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1395,16 +1519,20 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_LKDTM is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_HCALL_STATS=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
@@ -1419,7 +1547,12 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
@@ -1428,9 +1561,14 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index e965215..030d300 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -303,5 +303,8 @@
 	DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
 	DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
 
+#ifdef CONFIG_BUG
+	DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
+#endif
 	return 0;
 }
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 1a3d4de..2551c08 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -28,6 +28,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
+#include <asm/bug.h>
 
 /*
  * System calls.
@@ -634,19 +635,15 @@
 	li	r0,0
 	mtcr	r0
 
+#ifdef CONFIG_BUG	
 	/* There is no way it is acceptable to get here with interrupts enabled,
 	 * check it with the asm equivalent of WARN_ON
 	 */
 	lbz	r0,PACASOFTIRQEN(r13)
 1:	tdnei	r0,0
-.section __bug_table,"a"
-	.llong	1b,__LINE__ + 0x1000000, 1f, 2f
-.previous
-.section .rodata,"a"
-1:	.asciz	__FILE__
-2:	.asciz "enter_rtas"
-.previous
-
+	EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING
+#endif
+	
 	/* Hard-disable interrupts */
 	mfmsr	r6
 	rldicl	r7,r6,48,1
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 2847cd5..c54f363 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -775,11 +775,6 @@
 	np = scan_OF_for_pci_dev(parent, bus->self->devfn);
 	of_node_put(parent);
 
-	/* sanity check */
-	if (strcmp(np->type, "pci") != 0)
-		printk(KERN_WARNING "pci: wrong type \"%s\" for bridge %s\n",
-		       np->type, np->full_name);
-
 	return np;
 }
 
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 73c59ec..01f18c6 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1430,7 +1430,7 @@
 
 	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
 		bus = pci_bus_b(ln);
-		if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
+		if (in_bus >= bus->number && in_bus <= bus->subordinate)
 			break;
 		bus = NULL;
 	}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9b28c23..0e8beca 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -468,7 +468,7 @@
 	return -ENOSYS;
 }
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	int c;
 
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index a4b28c7..ae0ede1 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -284,6 +284,13 @@
 	 * pages though
 	 */
 	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	vma->vm_flags |= VM_ALWAYSDUMP;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
 	vma->vm_ops = &vdso_vmops;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 89c836d..1bb20d8 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -744,7 +744,8 @@
 	struct vm_area_struct *vma;
 
 	vma = find_vma(current->mm, addr);
-	if (!vma || ((addr + len) <= vma->vm_start))
+	if (TASK_SIZE - len >= addr &&
+	    (!vma || ((addr + len) <= vma->vm_start)))
 		return 0;
 
 	return -ENOMEM;
@@ -815,6 +816,8 @@
 		return -EINVAL;
 	if (len & ~HPAGE_MASK)
 		return -EINVAL;
+	if (len > TASK_SIZE)
+		return -ENOMEM;
 
 	if (!cpu_has_feature(CPU_FTR_16M_PAGE))
 		return -EINVAL;
@@ -823,9 +826,6 @@
 	BUG_ON((addr + len)  < addr);
 
 	if (test_thread_flag(TIF_32BIT)) {
-		/* Paranoia, caller should have dealt with this */
-		BUG_ON((addr + len) > 0x100000000UL);
-
 		curareas = current->mm->context.low_htlb_areas;
 
 		/* First see if we can use the hint address */
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index eaff71e..0f21bab 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -153,6 +153,7 @@
 	.name 		= "lite52xx",
 	.probe 		= lite52xx_probe,
 	.setup_arch 	= lite52xx_setup_arch,
+	.init		= mpc52xx_declare_of_platform_devices,
 	.init_IRQ 	= mpc52xx_init_irq,
 	.get_irq 	= mpc52xx_get_irq,
 	.show_cpuinfo	= lite52xx_show_cpuinfo,
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 8331ff4..cc40889 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -116,11 +116,12 @@
 	if (xlb) iounmap(xlb);
 }
 
-static int __init
+void __init
 mpc52xx_declare_of_platform_devices(void)
 {
 	/* Find every child of the SOC node and add it to of_platform */
-	return of_platform_bus_probe(NULL, NULL, NULL);
+	if (of_platform_bus_probe(NULL, NULL, NULL))
+		printk(KERN_ERR __FILE__ ": "
+			"Error while probing of_platform bus\n");
 }
 
-device_initcall(mpc52xx_declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index f58c978..4d47119 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -103,7 +103,7 @@
 #ifdef CONFIG_QUICC_ENGINE
 	qe_reset();
 
-	if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+	if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
 		par_io_init(np);
 		of_node_put(np);
 
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
index 7bfd47a..53b92a9 100644
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
@@ -108,7 +108,7 @@
 #ifdef CONFIG_QUICC_ENGINE
 	qe_reset();
 
-	if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+	if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
 		par_io_init(np);
 		of_node_put(np);
 
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index e3e929e..c1f4502 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -17,6 +17,7 @@
 
 #include <asm/system.h>
 #include <asm/paca.h>
+#include <asm/firmware.h>
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/hv_call_event.h>
@@ -318,6 +319,9 @@
 {
 	struct proc_dir_entry *e;
 
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+
 	e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
 	if (e)
 		e->proc_fops = &proc_lpevents_operations;
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index cff15ae..1ad0e4a 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -38,6 +38,7 @@
 #include <asm/uaccess.h>
 #include <asm/paca.h>
 #include <asm/abs_addr.h>
+#include <asm/firmware.h>
 #include <asm/iseries/vio.h>
 #include <asm/iseries/mf.h>
 #include <asm/iseries/hv_lp_config.h>
@@ -1235,6 +1236,9 @@
 	char name[2];
 	int i;
 
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+
 	mf_proc_root = proc_mkdir("iSeries/mf", NULL);
 	if (!mf_proc_root)
 		return 1;
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
index c241413..b54e371 100644
--- a/arch/powerpc/platforms/iseries/proc.c
+++ b/arch/powerpc/platforms/iseries/proc.c
@@ -24,6 +24,7 @@
 #include <asm/processor.h>
 #include <asm/time.h>
 #include <asm/lppaca.h>
+#include <asm/firmware.h>
 #include <asm/iseries/hv_call_xm.h>
 
 #include "processor_vpd.h"
@@ -31,7 +32,12 @@
 
 static int __init iseries_proc_create(void)
 {
-	struct proc_dir_entry *e = proc_mkdir("iSeries", 0);
+	struct proc_dir_entry *e;
+
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+
+	e = proc_mkdir("iSeries", 0);
 	if (!e)
 		return 1;
 
@@ -106,6 +112,9 @@
 {
 	struct proc_dir_entry *e;
 
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+
 	e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
 	if (e)
 		e->proc_fops = &proc_titantod_operations;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index bdf2afb..cce7e30 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -527,7 +527,8 @@
 static int __init iSeries_src_init(void)
 {
         /* clear the progress line */
-        ppc_md.progress(" ", 0xffff);
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		ppc_md.progress(" ", 0xffff);
         return 0;
 }
 
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 84e7ee2..a6799ed 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -42,6 +42,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/prom.h>
+#include <asm/firmware.h>
 #include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/hv_lp_config.h>
@@ -183,6 +184,9 @@
 {
 	struct proc_dir_entry *e;
 
+	if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		return 0;
+
 	e = create_proc_entry("iSeries/config", 0, NULL);
 	if (e)
 		e->proc_fops = &proc_viopath_operations;
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index f12d5c6..50855d4 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -254,7 +254,6 @@
 		printk(KERN_DEBUG "OpenPIC addr: %lx, has ISUs: %d\n",
 		       openpic_addr, has_isus);
 	}
-	of_node_put(root);
 
 	BUG_ON(openpic_addr == 0);
 
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 89d6e29..bea7d1b 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -129,7 +129,6 @@
 	}
 	openpic_addr = of_read_number(opprop, naddr);
 	printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
-	of_node_put(root);
 
 	mpic = mpic_alloc(mpic_node, openpic_addr, MPIC_PRIMARY, 0, 0,
 			  " PAS-OPIC  ");
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile
index 3757cfa..1994904 100644
--- a/arch/powerpc/platforms/ps3/Makefile
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -1,4 +1,5 @@
-obj-y += setup.o mm.o smp.o time.o hvcall.o htab.o repository.o
+obj-y += setup.o mm.o time.o hvcall.o htab.o repository.o
 obj-y += interrupt.o exports.o os-area.o
 
+obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 056c1e4..6f5de43 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -71,7 +71,7 @@
 
 	result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
 
-	if (!result)
+	if (result)
 		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index c00cfed..5c7e387 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -26,7 +26,7 @@
 BEGIN_FTR_SECTION;						\
 	mfspr	r0,SPRN_PURR;		/* get PURR and */	\
 	std	r0,STK_PARM(r6)(r1);	/* save for later */	\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);
 	
 /*
  * postcall is performed immediately before function return which
@@ -43,7 +43,7 @@
 	mfspr	r8,SPRN_PURR;		/* PURR after */	\
 	ld	r6,STK_PARM(r6)(r1);	/* PURR before */	\
 	subf	r6,r6,r8;		/* delta */		\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);				\
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
 	ld	r5,STK_PARM(r5)(r1);	/* timebase before */	\
 	subf	r5,r5,r7;		/* time delta */	\
 								\
@@ -66,7 +66,7 @@
 	ld	r7,HCALL_STAT_PURR(r4);	/* PURR */		\
 	add	r7,r7,r6;					\
 	std	r7,HCALL_STAT_PURR(r4);				\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);				\
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
 1:
 #else
 #define HCALL_INST_PRECALL
@@ -145,6 +145,7 @@
 
 	HVSC				/* invoke the hypervisor */
 
+	mr	r0,r12
 	ld	r12,STK_PARM(r4)(r1)
 	std	r4,  0(r12)
 	std	r5,  8(r12)
@@ -154,7 +155,7 @@
 	std	r9, 40(r12)
 	std	r10,48(r12)
 	std	r11,56(r12)
-	std	r12,64(r12)
+	std	r0, 64(r12)
 
 	HCALL_INST_POSTCALL
 
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index 80181c4..3ddc049 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -34,7 +34,7 @@
  */
 static void *hc_start(struct seq_file *m, loff_t *pos)
 {
-	if ((int)*pos < HCALL_STAT_ARRAY_SIZE)
+	if ((int)*pos < (HCALL_STAT_ARRAY_SIZE-1))
 		return (void *)(unsigned long)(*pos + 1);
 
 	return NULL;
@@ -57,7 +57,7 @@
 	struct hcall_stats *hs = (struct hcall_stats *)m->private;
 
 	if (hs[h_num].num_calls) {
-		if (!cpu_has_feature(CPU_FTR_PURR))
+		if (cpu_has_feature(CPU_FTR_PURR))
 			seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2,
 				   hs[h_num].num_calls,
 				   hs[h_num].tb_total,
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 3c95392..e6653a8 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -459,7 +459,8 @@
 		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
 				   phb->node);
 		iommu_table_setparms(phb, dn, tbl);
-		dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node);
+		PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);
+		dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;
 		return;
 	}
 
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index b5b2b11..81d172d 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -224,7 +224,6 @@
 static void xics_mask_real_irq(unsigned int irq)
 {
 	int call_status;
-	unsigned int server;
 
 	if (irq == XICS_IPI)
 		return;
@@ -236,9 +235,9 @@
 		return;
 	}
 
-	server = get_irq_server(irq);
 	/* Have to set XIVE to 0xff to be able to remove a slot */
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
+				default_server, 0xff);
 	if (call_status != 0) {
 		printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
 		       " returned %d\n", irq, call_status);
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 04d4917..2621a7e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,7 +12,6 @@
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
-obj-$(CONFIG_MTD)		+= rom.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
@@ -21,5 +20,6 @@
 
 # Temporary hack until we have migrated to asm-powerpc
 ifeq ($(ARCH),powerpc)
+obj-$(CONFIG_MTD)		+= rom.o
 obj-$(CONFIG_CPM2)		+= cpm2_common.o cpm2_pic.o
 endif
diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c
index ff23f5a..e073e24 100644
--- a/arch/powerpc/sysdev/mmio_nvram.c
+++ b/arch/powerpc/sysdev/mmio_nvram.c
@@ -80,33 +80,39 @@
 int __init mmio_nvram_init(void)
 {
 	struct device_node *nvram_node;
-	const unsigned long *buffer;
-	int proplen;
 	unsigned long nvram_addr;
+	struct resource r;
 	int ret;
 
-	ret = -ENODEV;
 	nvram_node = of_find_node_by_type(NULL, "nvram");
-	if (!nvram_node)
-		goto out;
+	if (!nvram_node) {
+		printk(KERN_WARNING "nvram: no node found in device-tree\n");
+		return -ENODEV;
+	}
 
-	ret = -EIO;
-	buffer = get_property(nvram_node, "reg", &proplen);
-	if (proplen != 2*sizeof(unsigned long))
+	ret = of_address_to_resource(nvram_node, 0, &r);
+	if (ret) {
+		printk(KERN_WARNING "nvram: failed to get address (err %d)\n",
+		       ret);
 		goto out;
-
-	ret = -ENODEV;
-	nvram_addr = buffer[0];
-	mmio_nvram_len = buffer[1];
-	if ( (!mmio_nvram_len) || (!nvram_addr) )
+	}
+	nvram_addr = r.start;
+	mmio_nvram_len = r.end - r.start + 1;
+	if ( (!mmio_nvram_len) || (!nvram_addr) ) {
+		printk(KERN_WARNING "nvram: address or lenght is 0\n");
+		ret = -EIO;
 		goto out;
+	}
 
 	mmio_nvram_start = ioremap(nvram_addr, mmio_nvram_len);
-	if (!mmio_nvram_start)
+	if (!mmio_nvram_start) {
+		printk(KERN_WARNING "nvram: failed to ioremap\n");
+		ret = -ENOMEM;
 		goto out;
+	}
 
-	printk(KERN_INFO "mmio NVRAM, %luk mapped to %p\n",
-	       mmio_nvram_len >> 10, mmio_nvram_start);
+	printk(KERN_INFO "mmio NVRAM, %luk at 0x%lx mapped to %p\n",
+	       mmio_nvram_len >> 10, nvram_addr, mmio_nvram_start);
 
 	ppc_md.nvram_read	= mmio_nvram_read;
 	ppc_md.nvram_write	= mmio_nvram_write;
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
index 90ed375..f87e06f 100644
--- a/arch/ppc/platforms/ev64360.c
+++ b/arch/ppc/platforms/ev64360.c
@@ -358,13 +358,12 @@
 
 	ptbl_entries = 3;
 
-	if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+	if ((ptbl = kzalloc(ptbl_entries * sizeof(struct mtd_partition),
 		GFP_KERNEL)) == NULL) {
 
 		printk(KERN_WARNING "Can't alloc MTD partition table\n");
 		return -ENOMEM;
 	}
-	memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
 
 	ptbl[0].name = "reserved";
 	ptbl[0].offset = 0;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 1227236..eaed402 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -34,10 +34,6 @@
 	bool
 	default y
 
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
 config GENERIC_TIME
 	def_bool y
 
@@ -134,6 +130,31 @@
 	bool
 	default y
 
+config S390_SWITCH_AMODE
+	bool "Switch kernel/user addressing modes"
+	help
+	  This option allows to switch the addressing modes of kernel and user
+	  space. The kernel parameter switch_amode=on will enable this feature,
+	  default is disabled. Enabling this (via kernel parameter) on machines
+	  earlier than IBM System z9-109 EC/BC will reduce system performance.
+
+	  Note that this option will also be selected by selecting the execute
+	  protection option below. Enabling the execute protection via the
+	  noexec kernel parameter will also switch the addressing modes,
+	  independent of the switch_amode kernel parameter.
+
+
+config S390_EXEC_PROTECT
+	bool "Data execute protection"
+	select S390_SWITCH_AMODE
+	help
+	  This option allows to enable a buffer overflow protection for user
+	  space programs and it also selects the addressing mode option above.
+	  The kernel parameter noexec=on will enable this feature and also
+	  switch the addressing modes, default is disabled. Enabling this (via
+	  kernel parameter) on machines earlier than IBM System z9-109 EC/BC
+	  will reduce system performance.
+
 comment "Code generation options"
 
 choice
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index b8c2372..c9da7d1 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -81,7 +81,7 @@
 /*
  * Timer
  */
-DEFINE_PER_CPU(struct vtimer_list, appldata_timer);
+static DEFINE_PER_CPU(struct vtimer_list, appldata_timer);
 static atomic_t appldata_expire_count = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(appldata_timer_lock);
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index 8aea369..4ca6157 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -36,7 +36,7 @@
  * book:
  * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
-struct appldata_mem_data {
+static struct appldata_mem_data {
 	u64 timestamp;
 	u32 sync_count_1;       /* after VM collected the record data, */
 	u32 sync_count_2;	/* sync_count_1 and sync_count_2 should be the
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
index 075e619..f64b8c8 100644
--- a/arch/s390/appldata/appldata_net_sum.c
+++ b/arch/s390/appldata/appldata_net_sum.c
@@ -34,7 +34,7 @@
  * book:
  * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
-struct appldata_net_sum_data {
+static struct appldata_net_sum_data {
 	u64 timestamp;
 	u32 sync_count_1;	/* after VM collected the record data, */
 	u32 sync_count_2;	/* sync_count_1 and sync_count_2 should be the
diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig
new file mode 100644
index 0000000..99ff9f0
--- /dev/null
+++ b/arch/s390/crypto/Kconfig
@@ -0,0 +1,60 @@
+config CRYPTO_SHA1_S390
+	tristate "SHA1 digest algorithm"
+	depends on S390
+	select CRYPTO_ALGAPI
+	help
+	  This is the s390 hardware accelerated implementation of the
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+
+config CRYPTO_SHA256_S390
+	tristate "SHA256 digest algorithm"
+	depends on S390
+	select CRYPTO_ALGAPI
+	help
+	  This is the s390 hardware accelerated implementation of the
+	  SHA256 secure hash standard (DFIPS 180-2).
+
+	  This version of SHA implements a 256 bit hash with 128 bits of
+	  security against collision attacks.
+
+config CRYPTO_DES_S390
+	tristate "DES and Triple DES cipher algorithms"
+	depends on S390
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
+	help
+	  This us the s390 hardware accelerated implementation of the
+	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+
+config CRYPTO_AES_S390
+	tristate "AES cipher algorithms"
+	depends on S390
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
+	help
+	  This is the s390 hardware accelerated implementation of the
+	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
+	  algorithm.
+
+	  Rijndael appears to be consistently a very good performer in
+	  both hardware and software across a wide range of computing
+	  environments regardless of its use in feedback or non-feedback
+	  modes. Its key setup time is excellent, and its key agility is
+	  good. Rijndael's very low memory requirements make it very well
+	  suited for restricted-space environments, in which it also
+	  demonstrates excellent performance. Rijndael's operations are
+	  among the easiest to defend against power and timing attacks.
+
+	  On s390 the System z9-109 currently only supports the key size
+	  of 128 bit.
+
+config S390_PRNG
+	tristate "Pseudo random number generator device driver"
+	depends on S390
+	default "m"
+	help
+	  Select this option if you want to use the s390 pseudo random number
+	  generator. The PRNG is part of the cryptograhic processor functions
+	  and uses triple-DES to generate secure random numbers like the
+	  ANSI X9.17 standard. The PRNG is usable via the char device
+	  /dev/prandom.
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index bfe2541..14e552c 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -6,5 +6,4 @@
 obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
 obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
 obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
-
-obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o
+obj-$(CONFIG_S390_PRNG) += prng.o
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 15c9eec..9163635 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -4,7 +4,7 @@
  * s390 implementation of the AES Cipher Algorithm.
  *
  * s390 Version:
- *   Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
+ *   Copyright IBM Corp. 2005,2007
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *
  * Derived from "crypto/aes.c"
@@ -27,9 +27,11 @@
 /* data block size for all key lengths */
 #define AES_BLOCK_SIZE		16
 
-int has_aes_128 = 0;
-int has_aes_192 = 0;
-int has_aes_256 = 0;
+#define AES_KEYLEN_128		1
+#define AES_KEYLEN_192		2
+#define AES_KEYLEN_256		4
+
+static char keylen_flag = 0;
 
 struct s390_aes_ctx {
 	u8 iv[AES_BLOCK_SIZE];
@@ -47,20 +49,19 @@
 
 	switch (key_len) {
 	case 16:
-		if (!has_aes_128)
+		if (!(keylen_flag & AES_KEYLEN_128))
 			goto fail;
 		break;
 	case 24:
-		if (!has_aes_192)
+		if (!(keylen_flag & AES_KEYLEN_192))
 			goto fail;
 
 		break;
 	case 32:
-		if (!has_aes_256)
+		if (!(keylen_flag & AES_KEYLEN_256))
 			goto fail;
 		break;
 	default:
-		/* invalid key length */
 		goto fail;
 		break;
 	}
@@ -322,34 +323,32 @@
 	int ret;
 
 	if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
-		has_aes_128 = 1;
+		keylen_flag |= AES_KEYLEN_128;
 	if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
-		has_aes_192 = 1;
+		keylen_flag |= AES_KEYLEN_192;
 	if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
-		has_aes_256 = 1;
+		keylen_flag |= AES_KEYLEN_256;
 
-	if (!has_aes_128 && !has_aes_192 && !has_aes_256)
-		return -ENOSYS;
+	if (!keylen_flag)
+		return -EOPNOTSUPP;
+
+	/* z9 109 and z9 BC/EC only support 128 bit key length */
+	if (keylen_flag == AES_KEYLEN_128)
+		printk(KERN_INFO
+		       "aes_s390: hardware acceleration only available for"
+		       "128 bit keys\n");
 
 	ret = crypto_register_alg(&aes_alg);
-	if (ret != 0) {
-		printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n");
+	if (ret)
 		goto aes_err;
-	}
 
 	ret = crypto_register_alg(&ecb_aes_alg);
-	if (ret != 0) {
-		printk(KERN_INFO
-		       "crypt_s390: ecb-aes-s390 couldn't be loaded.\n");
+	if (ret)
 		goto ecb_aes_err;
-	}
 
 	ret = crypto_register_alg(&cbc_aes_alg);
-	if (ret != 0) {
-		printk(KERN_INFO
-		       "crypt_s390: cbc-aes-s390 couldn't be loaded.\n");
+	if (ret)
 		goto cbc_aes_err;
-	}
 
 out:
 	return ret;
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index 2b13708..2775d26 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -3,8 +3,9 @@
  *
  * Support for s390 cryptographic instructions.
  *
- *   Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
- *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Copyright IBM Corp. 2003,2007
+ *   Author(s): Thomas Spatzier
+ *		Jan Glauber (jan.glauber@de.ibm.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
@@ -32,7 +33,8 @@
 	CRYPT_S390_KMAC = 0x0500
 };
 
-/* function codes for KM (CIPHER MESSAGE) instruction
+/*
+ * function codes for KM (CIPHER MESSAGE) instruction
  * 0x80 is the decipher modifier bit
  */
 enum crypt_s390_km_func {
@@ -51,7 +53,8 @@
 	KM_AES_256_DECRYPT  = CRYPT_S390_KM | 0x14 | 0x80,
 };
 
-/* function codes for KMC (CIPHER MESSAGE WITH CHAINING)
+/*
+ * function codes for KMC (CIPHER MESSAGE WITH CHAINING)
  * instruction
  */
 enum crypt_s390_kmc_func {
@@ -68,9 +71,11 @@
 	KMC_AES_192_DECRYPT  = CRYPT_S390_KMC | 0x13 | 0x80,
 	KMC_AES_256_ENCRYPT  = CRYPT_S390_KMC | 0x14,
 	KMC_AES_256_DECRYPT  = CRYPT_S390_KMC | 0x14 | 0x80,
+	KMC_PRNG	     = CRYPT_S390_KMC | 0x43,
 };
 
-/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+/*
+ * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
  * instruction
  */
 enum crypt_s390_kimd_func {
@@ -79,7 +84,8 @@
 	KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
 };
 
-/* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
+/*
+ * function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
  * instruction
  */
 enum crypt_s390_klmd_func {
@@ -88,7 +94,8 @@
 	KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
 };
 
-/* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+/*
+ * function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
  * instruction
  */
 enum crypt_s390_kmac_func {
@@ -98,229 +105,219 @@
 	KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
 };
 
-/* status word for s390 crypto instructions' QUERY functions */
-struct crypt_s390_query_status {
-	u64 high;
-	u64 low;
-};
-
-/*
+/**
+ * crypt_s390_km:
+ * @func: the function code passed to KM; see crypt_s390_km_func
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
  * Executes the KM (CIPHER MESSAGE) operation of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_km_func
- * @param param: address of parameter block; see POP for details on each func
- * @param dest: address of destination memory area
- * @param src: address of source memory area
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- * 	for encryption/decryption funcs
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for encryption/decryption funcs
  */
-static inline int
-crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len)
+static inline int crypt_s390_km(long func, void *param,
+				u8 *dest, const u8 *src, long src_len)
 {
 	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void* __param asm("1") = param;
-	register const u8* __src asm("2") = src;
+	register void *__param asm("1") = param;
+	register const u8 *__src asm("2") = src;
 	register long __src_len asm("3") = src_len;
-	register u8* __dest asm("4") = dest;
+	register u8 *__dest asm("4") = dest;
 	int ret;
 
 	asm volatile(
 		"0:	.insn	rre,0xb92e0000,%3,%1 \n" /* KM opcode */
 		"1:	brc	1,0b \n" /* handle partial completion */
-		"	ahi	%0,%h7\n"
-		"2:	ahi	%0,%h8\n"
-		"3:\n"
-		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+		"	la	%0,0\n"
+		"2:\n"
+		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
-		: "d" (__func), "a" (__param), "0" (-EFAULT),
-		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/*
- * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_kmc_func
- * @param param: address of parameter block; see POP for details on each func
- * @param dest: address of destination memory area
- * @param src: address of source memory area
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- * 	for encryption/decryption funcs
- */
-static inline int
-crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void* __param asm("1") = param;
-	register const u8* __src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	register u8* __dest asm("4") = dest;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
-		"1:	brc	1,0b \n" /* handle partial completion */
-		"	ahi	%0,%h7\n"
-		"2:	ahi	%0,%h8\n"
-		"3:\n"
-		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
-		: "d" (__func), "a" (__param), "0" (-EFAULT),
-		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/*
- * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation
- * of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_kimd_func
- * @param param: address of parameter block; see POP for details on each func
- * @param src: address of source memory area
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- * 	for digest funcs
- */
-static inline int
-crypt_s390_kimd(long func, void* param, const u8* src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void* __param asm("1") = param;
-	register const u8* __src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
-		"1:	brc	1,0b \n" /* handle partial completion */
-		"	ahi	%0,%h6\n"
-		"2:	ahi	%0,%h7\n"
-		"3:\n"
-		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len)
-		: "d" (__func), "a" (__param), "0" (-EFAULT),
-		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/*
- * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_klmd_func
- * @param param: address of parameter block; see POP for details on each func
- * @param src: address of source memory area
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- * 	for digest funcs
- */
-static inline int
-crypt_s390_klmd(long func, void* param, const u8* src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void* __param asm("1") = param;
-	register const u8* __src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
-		"1:	brc	1,0b \n" /* handle partial completion */
-		"	ahi	%0,%h6\n"
-		"2:	ahi	%0,%h7\n"
-		"3:\n"
-		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len)
-		: "d" (__func), "a" (__param), "0" (-EFAULT),
-		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/*
- * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation
- * of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_klmd_func
- * @param param: address of parameter block; see POP for details on each func
- * @param src: address of source memory area
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- * 	for digest funcs
- */
-static inline int
-crypt_s390_kmac(long func, void* param, const u8* src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void* __param asm("1") = param;
-	register const u8* __src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
-		"1:	brc	1,0b \n" /* handle partial completion */
-		"	ahi	%0,%h6\n"
-		"2:	ahi	%0,%h7\n"
-		"3:\n"
-		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len)
-		: "d" (__func), "a" (__param), "0" (-EFAULT),
-		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
 	if (ret < 0)
 		return ret;
 	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /**
- * Tests if a specific crypto function is implemented on the machine.
- * @param func:	the function code of the specific function; 0 if op in general
- * @return	1 if func available; 0 if func or op in general not available
+ * crypt_s390_kmc:
+ * @func: the function code passed to KM; see crypt_s390_kmc_func
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU.
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for encryption/decryption funcs
  */
-static inline int
-crypt_s390_func_available(int func)
+static inline int crypt_s390_kmc(long func, void *param,
+				 u8 *dest, const u8 *src, long src_len)
 {
+	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
+	register void *__param asm("1") = param;
+	register const u8 *__src asm("2") = src;
+	register long __src_len asm("3") = src_len;
+	register u8 *__dest asm("4") = dest;
 	int ret;
 
-	struct crypt_s390_query_status status = {
-		.high = 0,
-		.low = 0
-	};
-	switch (func & CRYPT_S390_OP_MASK){
-		case CRYPT_S390_KM:
-			ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
-			break;
-		case CRYPT_S390_KMC:
-			ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
-			break;
-		case CRYPT_S390_KIMD:
-			ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
-			break;
-		case CRYPT_S390_KLMD:
-			ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
-			break;
-		case CRYPT_S390_KMAC:
-			ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
-			break;
-		default:
-			ret = 0;
-			return ret;
-	}
-	if (ret >= 0){
-		func &= CRYPT_S390_FUNC_MASK;
-		func &= 0x7f; //mask modifier bit
-		if (func < 64){
-			ret = (status.high >> (64 - func - 1)) & 0x1;
-		} else {
-			ret = (status.low >> (128 - func - 1)) & 0x1;
-		}
-	} else {
-		ret = 0;
-	}
-	return ret;
+	asm volatile(
+		"0:	.insn	rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	la	%0,0\n"
+		"2:\n"
+		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
-#endif // _CRYPTO_ARCH_S390_CRYPT_S390_H
+/**
+ * crypt_s390_kimd:
+ * @func: the function code passed to KM; see crypt_s390_kimd_func
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation
+ * of the CPU.
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for digest funcs
+ */
+static inline int crypt_s390_kimd(long func, void *param,
+				  const u8 *src, long src_len)
+{
+	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
+	register void *__param asm("1") = param;
+	register const u8 *__src asm("2") = src;
+	register long __src_len asm("3") = src_len;
+	int ret;
+
+	asm volatile(
+		"0:	.insn	rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	la	%0,0\n"
+		"2:\n"
+		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len)
+		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
+}
+
+/**
+ * crypt_s390_klmd:
+ * @func: the function code passed to KM; see crypt_s390_klmd_func
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU.
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for digest funcs
+ */
+static inline int crypt_s390_klmd(long func, void *param,
+				  const u8 *src, long src_len)
+{
+	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
+	register void *__param asm("1") = param;
+	register const u8 *__src asm("2") = src;
+	register long __src_len asm("3") = src_len;
+	int ret;
+
+	asm volatile(
+		"0:	.insn	rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	la	%0,0\n"
+		"2:\n"
+		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len)
+		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
+}
+
+/**
+ * crypt_s390_kmac:
+ * @func: the function code passed to KM; see crypt_s390_klmd_func
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation
+ * of the CPU.
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for digest funcs
+ */
+static inline int crypt_s390_kmac(long func, void *param,
+				  const u8 *src, long src_len)
+{
+	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
+	register void *__param asm("1") = param;
+	register const u8 *__src asm("2") = src;
+	register long __src_len asm("3") = src_len;
+	int ret;
+
+	asm volatile(
+		"0:	.insn	rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	la	%0,0\n"
+		"2:\n"
+		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len)
+		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
+}
+
+/**
+ * crypt_s390_func_available:
+ * @func: the function code of the specific function; 0 if op in general
+ *
+ * Tests if a specific crypto function is implemented on the machine.
+ *
+ * Returns 1 if func available; 0 if func or op in general not available
+ */
+static inline int crypt_s390_func_available(int func)
+{
+	unsigned char status[16];
+	int ret;
+
+	switch (func & CRYPT_S390_OP_MASK) {
+	case CRYPT_S390_KM:
+		ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
+		break;
+	case CRYPT_S390_KMC:
+		ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
+		break;
+	case CRYPT_S390_KIMD:
+		ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
+		break;
+	case CRYPT_S390_KLMD:
+		ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
+		break;
+	case CRYPT_S390_KMAC:
+		ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
+		break;
+	default:
+		return 0;
+	}
+	if (ret < 0)
+		return 0;
+	func &= CRYPT_S390_FUNC_MASK;
+	func &= 0x7f;		/* mask modifier bit */
+	return (status[func >> 3] & (0x80 >> (func & 7))) != 0;
+}
+
+#endif	/* _CRYPTO_ARCH_S390_CRYPT_S390_H */
diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c
deleted file mode 100644
index 54fb11d..0000000
--- a/arch/s390/crypto/crypt_s390_query.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Support for s390 cryptographic instructions.
- * Testing module for querying processor crypto capabilities.
- *
- * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@de.ibm.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.
- *
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/errno.h>
-#include "crypt_s390.h"
-
-static void query_available_functions(void)
-{
-	printk(KERN_INFO "#####################\n");
-
-	/* query available KM functions */
-	printk(KERN_INFO "KM_QUERY: %d\n",
-		crypt_s390_func_available(KM_QUERY));
-	printk(KERN_INFO "KM_DEA: %d\n",
-		crypt_s390_func_available(KM_DEA_ENCRYPT));
-	printk(KERN_INFO "KM_TDEA_128: %d\n",
-		crypt_s390_func_available(KM_TDEA_128_ENCRYPT));
-	printk(KERN_INFO "KM_TDEA_192: %d\n",
-		crypt_s390_func_available(KM_TDEA_192_ENCRYPT));
-	printk(KERN_INFO "KM_AES_128: %d\n",
-		crypt_s390_func_available(KM_AES_128_ENCRYPT));
-	printk(KERN_INFO "KM_AES_192: %d\n",
-		crypt_s390_func_available(KM_AES_192_ENCRYPT));
-	printk(KERN_INFO "KM_AES_256: %d\n",
-		crypt_s390_func_available(KM_AES_256_ENCRYPT));
-
-	/* query available KMC functions */
-	printk(KERN_INFO "KMC_QUERY: %d\n",
-		crypt_s390_func_available(KMC_QUERY));
-	printk(KERN_INFO "KMC_DEA: %d\n",
-		crypt_s390_func_available(KMC_DEA_ENCRYPT));
-	printk(KERN_INFO "KMC_TDEA_128: %d\n",
-		crypt_s390_func_available(KMC_TDEA_128_ENCRYPT));
-	printk(KERN_INFO "KMC_TDEA_192: %d\n",
-		crypt_s390_func_available(KMC_TDEA_192_ENCRYPT));
-	printk(KERN_INFO "KMC_AES_128: %d\n",
-		crypt_s390_func_available(KMC_AES_128_ENCRYPT));
-	printk(KERN_INFO "KMC_AES_192: %d\n",
-		crypt_s390_func_available(KMC_AES_192_ENCRYPT));
-	printk(KERN_INFO "KMC_AES_256: %d\n",
-		crypt_s390_func_available(KMC_AES_256_ENCRYPT));
-
-	/* query available KIMD functions */
-	printk(KERN_INFO "KIMD_QUERY: %d\n",
-		crypt_s390_func_available(KIMD_QUERY));
-	printk(KERN_INFO "KIMD_SHA_1: %d\n",
-		crypt_s390_func_available(KIMD_SHA_1));
-	printk(KERN_INFO "KIMD_SHA_256: %d\n",
-		crypt_s390_func_available(KIMD_SHA_256));
-
-	/* query available KLMD functions */
-	printk(KERN_INFO "KLMD_QUERY: %d\n",
-		crypt_s390_func_available(KLMD_QUERY));
-	printk(KERN_INFO "KLMD_SHA_1: %d\n",
-		crypt_s390_func_available(KLMD_SHA_1));
-	printk(KERN_INFO "KLMD_SHA_256: %d\n",
-		crypt_s390_func_available(KLMD_SHA_256));
-
-	/* query available KMAC functions */
-	printk(KERN_INFO "KMAC_QUERY: %d\n",
-		crypt_s390_func_available(KMAC_QUERY));
-	printk(KERN_INFO "KMAC_DEA: %d\n",
-		crypt_s390_func_available(KMAC_DEA));
-	printk(KERN_INFO "KMAC_TDEA_128: %d\n",
-		crypt_s390_func_available(KMAC_TDEA_128));
-	printk(KERN_INFO "KMAC_TDEA_192: %d\n",
-		crypt_s390_func_available(KMAC_TDEA_192));
-}
-
-static int init(void)
-{
-	struct crypt_s390_query_status status = {
-		.high = 0,
-		.low = 0
-	};
-
-	printk(KERN_INFO "crypt_s390: querying available crypto functions\n");
-	crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
-	printk(KERN_INFO "KM:\t%016llx %016llx\n",
-			(unsigned long long) status.high,
-			(unsigned long long) status.low);
-	status.high = status.low = 0;
-	crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
-	printk(KERN_INFO "KMC:\t%016llx %016llx\n",
-			(unsigned long long) status.high,
-			(unsigned long long) status.low);
-	status.high = status.low = 0;
-	crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
-	printk(KERN_INFO "KIMD:\t%016llx %016llx\n",
-			(unsigned long long) status.high,
-			(unsigned long long) status.low);
-	status.high = status.low = 0;
-	crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
-	printk(KERN_INFO "KLMD:\t%016llx %016llx\n",
-			(unsigned long long) status.high,
-			(unsigned long long) status.low);
-	status.high = status.low = 0;
-	crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
-	printk(KERN_INFO "KMAC:\t%016llx %016llx\n",
-			(unsigned long long) status.high,
-			(unsigned long long) status.low);
-
-	query_available_functions();
-	return -ECANCELED;
-}
-
-static void __exit cleanup(void)
-{
-}
-
-module_init(init);
-module_exit(cleanup);
-
-MODULE_LICENSE("GPL");
diff --git a/arch/s390/crypto/des_check_key.c b/arch/s390/crypto/des_check_key.c
index e3f5c5f..5706af2 100644
--- a/arch/s390/crypto/des_check_key.c
+++ b/arch/s390/crypto/des_check_key.c
@@ -10,8 +10,9 @@
  * scatterlist interface.  Changed LGPL to GPL per section 3 of the LGPL.
  *
  * s390 Version:
- *   Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
- *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Copyright IBM Corp. 2003
+ *   Author(s): Thomas Spatzier
+ *		Jan Glauber (jan.glauber@de.ibm.com)
  *
  * Derived from "crypto/des.c"
  *   Copyright (c) 1992 Dana L. How.
@@ -30,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/crypto.h>
+#include "crypto_des.h"
 
 #define ROR(d,c,o)	((d) = (d) >> (c) | (d) << (o))
 
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index 2aba048..ea22707 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -3,9 +3,9 @@
  *
  * s390 implementation of the DES Cipher Algorithm.
  *
- * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@de.ibm.com)
- *
+ * Copyright IBM Corp. 2003,2007
+ * Author(s): Thomas Spatzier
+ *	      Jan Glauber (jan.glauber@de.ibm.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
@@ -557,7 +557,7 @@
 	if (!crypt_s390_func_available(KM_DEA_ENCRYPT) ||
 	    !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) ||
 	    !crypt_s390_func_available(KM_TDEA_192_ENCRYPT))
-		return -ENOSYS;
+		return -EOPNOTSUPP;
 
 	ret = crypto_register_alg(&des_alg);
 	if (ret)
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
new file mode 100644
index 0000000..8eb3a1a
--- /dev/null
+++ b/arch/s390/crypto/prng.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright IBM Corp. 2006,2007
+ * Author(s): Jan Glauber <jan.glauber@de.ibm.com>
+ * Driver for the s390 pseudo random number generator
+ */
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/random.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+
+#include "crypt_s390.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jan Glauber <jan.glauber@de.ibm.com>");
+MODULE_DESCRIPTION("s390 PRNG interface");
+
+static int prng_chunk_size = 256;
+module_param(prng_chunk_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes");
+
+static int prng_entropy_limit = 4096;
+module_param(prng_entropy_limit, int, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
+MODULE_PARM_DESC(prng_entropy_limit,
+	"PRNG add entropy after that much bytes were produced");
+
+/*
+ * Any one who considers arithmetical methods of producing random digits is,
+ * of course, in a state of sin. -- John von Neumann
+ */
+
+struct s390_prng_data {
+	unsigned long count; /* how many bytes were produced */
+	char *buf;
+};
+
+static struct s390_prng_data *p;
+
+/* copied from libica, use a non-zero initial parameter block */
+static unsigned char parm_block[32] = {
+0x0F,0x2B,0x8E,0x63,0x8C,0x8E,0xD2,0x52,0x64,0xB7,0xA0,0x7B,0x75,0x28,0xB8,0xF4,
+0x75,0x5F,0xD2,0xA6,0x8D,0x97,0x11,0xFF,0x49,0xD8,0x23,0xF3,0x7E,0x21,0xEC,0xA0,
+};
+
+static int prng_open(struct inode *inode, struct file *file)
+{
+	return nonseekable_open(inode, file);
+}
+
+static void prng_add_entropy(void)
+{
+	__u64 entropy[4];
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < 16; i++) {
+		ret = crypt_s390_kmc(KMC_PRNG, parm_block, (char *)entropy,
+				     (char *)entropy, sizeof(entropy));
+		BUG_ON(ret < 0 || ret != sizeof(entropy));
+		memcpy(parm_block, entropy, sizeof(entropy));
+	}
+}
+
+static void prng_seed(int nbytes)
+{
+	char buf[16];
+	int i = 0;
+
+	BUG_ON(nbytes > 16);
+	get_random_bytes(buf, nbytes);
+
+	/* Add the entropy */
+	while (nbytes >= 8) {
+		*((__u64 *)parm_block) ^= *((__u64 *)buf+i*8);
+		prng_add_entropy();
+		i += 8;
+		nbytes -= 8;
+	}
+	prng_add_entropy();
+}
+
+static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
+			 loff_t *ppos)
+{
+	int chunk, n;
+	int ret = 0;
+	int tmp;
+
+	/* nbytes can be arbitrary long, we spilt it into chunks */
+	while (nbytes) {
+		/* same as in extract_entropy_user in random.c */
+		if (need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		/*
+		 * we lose some random bytes if an attacker issues
+		 * reads < 8 bytes, but we don't care
+		 */
+		chunk = min_t(int, nbytes, prng_chunk_size);
+
+		/* PRNG only likes multiples of 8 bytes */
+		n = (chunk + 7) & -8;
+
+		if (p->count > prng_entropy_limit)
+			prng_seed(8);
+
+		/* if the CPU supports PRNG stckf is present too */
+		asm volatile(".insn     s,0xb27c0000,%0"
+			     : "=m" (*((unsigned long long *)p->buf)) : : "cc");
+
+		/*
+		 * Beside the STCKF the input for the TDES-EDE is the output
+		 * of the last operation. We differ here from X9.17 since we
+		 * only store one timestamp into the buffer. Padding the whole
+		 * buffer with timestamps does not improve security, since
+		 * successive stckf have nearly constant offsets.
+		 * If an attacker knows the first timestamp it would be
+		 * trivial to guess the additional values. One timestamp
+		 * is therefore enough and still guarantees unique input values.
+		 *
+		 * Note: you can still get strict X9.17 conformity by setting
+		 * prng_chunk_size to 8 bytes.
+		*/
+		tmp = crypt_s390_kmc(KMC_PRNG, parm_block, p->buf, p->buf, n);
+		BUG_ON((tmp < 0) || (tmp != n));
+
+		p->count += n;
+
+		if (copy_to_user(ubuf, p->buf, chunk))
+			return -EFAULT;
+
+		nbytes -= chunk;
+		ret += chunk;
+		ubuf += chunk;
+	}
+	return ret;
+}
+
+static struct file_operations prng_fops = {
+	.owner		= THIS_MODULE,
+	.open		= &prng_open,
+	.release	= NULL,
+	.read		= &prng_read,
+};
+
+static struct miscdevice prng_dev = {
+	.name	= "prandom",
+	.minor	= MISC_DYNAMIC_MINOR,
+	.fops	= &prng_fops,
+};
+
+static int __init prng_init(void)
+{
+	int ret;
+
+	/* check if the CPU has a PRNG */
+	if (!crypt_s390_func_available(KMC_PRNG))
+		return -EOPNOTSUPP;
+
+	if (prng_chunk_size < 8)
+		return -EINVAL;
+
+	p = kmalloc(sizeof(struct s390_prng_data), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	p->count = 0;
+
+	p->buf = kmalloc(prng_chunk_size, GFP_KERNEL);
+	if (!p->buf) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	/* initialize the PRNG, add 128 bits of entropy */
+	prng_seed(16);
+
+	ret = misc_register(&prng_dev);
+	if (ret) {
+		printk(KERN_WARNING
+		       "Could not register misc device for PRNG.\n");
+		goto out_buf;
+	}
+	return 0;
+
+out_buf:
+	kfree(p->buf);
+out_free:
+	kfree(p);
+	return ret;
+}
+
+static void __exit prng_exit(void)
+{
+	/* wipe me */
+	memset(p->buf, 0, prng_chunk_size);
+	kfree(p->buf);
+	kfree(p);
+
+	misc_deregister(&prng_dev);
+}
+
+module_init(prng_init);
+module_exit(prng_exit);
diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
index 49ca869..969639f 100644
--- a/arch/s390/crypto/sha1_s390.c
+++ b/arch/s390/crypto/sha1_s390.c
@@ -8,8 +8,9 @@
  * implementation written by Steve Reid.
  *
  * s390 Version:
- *   Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
- *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Copyright IBM Corp. 2003,2007
+ *   Author(s): Thomas Spatzier
+ *		Jan Glauber (jan.glauber@de.ibm.com)
  *
  * Derived from "crypto/sha1.c"
  *   Copyright (c) Alan Smithee.
@@ -43,16 +44,14 @@
 static void sha1_init(struct crypto_tfm *tfm)
 {
 	struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm);
-	static const u32 initstate[5] = {
-		0x67452301,
-		0xEFCDAB89,
-		0x98BADCFE,
-		0x10325476,
-		0xC3D2E1F0
-	};
+
+	ctx->state[0] = 0x67452301;
+	ctx->state[1] =	0xEFCDAB89;
+	ctx->state[2] =	0x98BADCFE;
+	ctx->state[3] = 0x10325476;
+	ctx->state[4] =	0xC3D2E1F0;
 
 	ctx->count = 0;
-	memcpy(ctx->state, &initstate, sizeof(initstate));
 	ctx->buf_len = 0;
 }
 
@@ -63,13 +62,13 @@
 	long imd_len;
 
 	sctx = crypto_tfm_ctx(tfm);
-	sctx->count += len * 8; //message bit length
+	sctx->count += len * 8; /* message bit length */
 
-	//anything in buffer yet? -> must be completed
+	/* anything in buffer yet? -> must be completed */
 	if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) {
-		//complete full block and hash
+		/* complete full block and hash */
 		memcpy(sctx->buffer + sctx->buf_len, data,
-				SHA1_BLOCK_SIZE - sctx->buf_len);
+		       SHA1_BLOCK_SIZE - sctx->buf_len);
 		crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer,
 				SHA1_BLOCK_SIZE);
 		data += SHA1_BLOCK_SIZE - sctx->buf_len;
@@ -77,37 +76,36 @@
 		sctx->buf_len = 0;
 	}
 
-	//rest of data contains full blocks?
+	/* rest of data contains full blocks? */
 	imd_len = len & ~0x3ful;
-	if (imd_len){
+	if (imd_len) {
 		crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len);
 		data += imd_len;
 		len -= imd_len;
 	}
-	//anything left? store in buffer
-	if (len){
+	/* anything left? store in buffer */
+	if (len) {
 		memcpy(sctx->buffer + sctx->buf_len , data, len);
 		sctx->buf_len += len;
 	}
 }
 
 
-static void
-pad_message(struct crypt_s390_sha1_ctx* sctx)
+static void pad_message(struct crypt_s390_sha1_ctx* sctx)
 {
 	int index;
 
 	index = sctx->buf_len;
-	sctx->buf_len = (sctx->buf_len < 56)?
-		SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE;
-	//start pad with 1
+	sctx->buf_len = (sctx->buf_len < 56) ?
+			 SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE;
+	/* start pad with 1 */
 	sctx->buffer[index] = 0x80;
-	//pad with zeros
+	/* pad with zeros */
 	index++;
 	memset(sctx->buffer + index, 0x00, sctx->buf_len - index);
-	//append length
+	/* append length */
 	memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count,
-			sizeof sctx->count);
+	       sizeof sctx->count);
 }
 
 /* Add padding and return the message digest. */
@@ -115,47 +113,40 @@
 {
 	struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
 
-	//must perform manual padding
+	/* must perform manual padding */
 	pad_message(sctx);
 	crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len);
-	//copy digest to out
+	/* copy digest to out */
 	memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
-	/* Wipe context */
+	/* wipe context */
 	memset(sctx, 0, sizeof *sctx);
 }
 
 static struct crypto_alg alg = {
 	.cra_name	=	"sha1",
-	.cra_driver_name =	"sha1-s390",
+	.cra_driver_name=	"sha1-s390",
 	.cra_priority	=	CRYPT_S390_PRIORITY,
 	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
 	.cra_blocksize	=	SHA1_BLOCK_SIZE,
 	.cra_ctxsize	=	sizeof(struct crypt_s390_sha1_ctx),
 	.cra_module	=	THIS_MODULE,
-	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),
+	.cra_list	=	LIST_HEAD_INIT(alg.cra_list),
 	.cra_u		=	{ .digest = {
 	.dia_digestsize	=	SHA1_DIGEST_SIZE,
-	.dia_init   	= 	sha1_init,
-	.dia_update 	=	sha1_update,
-	.dia_final  	=	sha1_final } }
+	.dia_init	=	sha1_init,
+	.dia_update	=	sha1_update,
+	.dia_final	=	sha1_final } }
 };
 
-static int
-init(void)
+static int __init init(void)
 {
-	int ret = -ENOSYS;
+	if (!crypt_s390_func_available(KIMD_SHA_1))
+		return -EOPNOTSUPP;
 
-	if (crypt_s390_func_available(KIMD_SHA_1)){
-		ret = crypto_register_alg(&alg);
-		if (ret == 0){
-			printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n");
-		}
-	}
-	return ret;
+	return crypto_register_alg(&alg);
 }
 
-static void __exit
-fini(void)
+static void __exit fini(void)
 {
 	crypto_unregister_alg(&alg);
 }
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index 8e4e675..78436c6 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -4,7 +4,7 @@
  * s390 implementation of the SHA256 Secure Hash Algorithm.
  *
  * s390 Version:
- *   Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
+ *   Copyright IBM Corp. 2005,2007
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *
  * Derived from "crypto/sha256.c"
@@ -143,15 +143,10 @@
 
 static int init(void)
 {
-	int ret;
-
 	if (!crypt_s390_func_available(KIMD_SHA_256))
-		return -ENOSYS;
+		return -EOPNOTSUPP;
 
-	ret = crypto_register_alg(&alg);
-	if (ret != 0)
-		printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded.");
-	return ret;
+	return crypto_register_alg(&alg);
 }
 
 static void __exit fini(void)
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 5368cf4..7c621b8 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -108,6 +108,8 @@
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_AUDIT_ARCH=y
+CONFIG_S390_SWITCH_AMODE=y
+CONFIG_S390_EXEC_PROTECT=y
 
 #
 # Code generation options
@@ -431,7 +433,6 @@
 CONFIG_TN3215=y
 CONFIG_TN3215_CONSOLE=y
 CONFIG_CCW_CONSOLE=y
-CONFIG_SCLP=y
 CONFIG_SCLP_TTY=y
 CONFIG_SCLP_CONSOLE=y
 CONFIG_SCLP_VT220_TTY=y
@@ -724,9 +725,7 @@
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
 # CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA1_S390 is not set
 # CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA256_S390 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
@@ -735,12 +734,10 @@
 CONFIG_CRYPTO_CBC=y
 # CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_DES_S390 is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
 # CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_AES_S390 is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
 # CONFIG_CRYPTO_TEA is not set
@@ -755,6 +752,11 @@
 #
 # Hardware crypto devices
 #
+# CONFIG_CRYPTO_SHA1_S390 is not set
+# CONFIG_CRYPTO_SHA256_S390 is not set
+# CONFIG_CRYPTO_DES_S390 is not set
+# CONFIG_CRYPTO_AES_S390 is not set
+CONFIG_S390_PRNG=m
 
 #
 # Library routines
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile
index f4b00cd..b08d2ab 100644
--- a/arch/s390/hypfs/Makefile
+++ b/arch/s390/hypfs/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
 
-s390_hypfs-objs := inode.o hypfs_diag.o
+s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
index f3dbd91..aea5720 100644
--- a/arch/s390/hypfs/hypfs.h
+++ b/arch/s390/hypfs/hypfs.h
@@ -27,4 +27,13 @@
 				       struct dentry *dir, const char *name,
 				       char *string);
 
+/* LPAR Hypervisor */
+extern int hypfs_diag_init(void);
+extern void hypfs_diag_exit(void);
+extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
+
+/* VM Hypervisor */
+extern int hypfs_vm_init(void);
+extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root);
+
 #endif /* _HYPFS_H_ */
diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h
deleted file mode 100644
index 256b384..0000000
--- a/arch/s390/hypfs/hypfs_diag.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  arch/s390/hypfs_diag.h
- *    Hypervisor filesystem for Linux on s390.
- *
- *    Copyright (C) IBM Corp. 2006
- *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
- */
-
-#ifndef _HYPFS_DIAG_H_
-#define _HYPFS_DIAG_H_
-
-extern int hypfs_diag_init(void);
-extern void hypfs_diag_exit(void);
-extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
-
-#endif /* _HYPFS_DIAG_H_ */
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
new file mode 100644
index 0000000..d01fc8f
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -0,0 +1,231 @@
+/*
+ *    Hypervisor filesystem for Linux on s390. z/VM implementation.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+
+#define NAME_LEN 8
+
+static char local_guest[] = "        ";
+static char all_guests[] = "*       ";
+static char *guest_query;
+
+struct diag2fc_data {
+	__u32 version;
+	__u32 flags;
+	__u64 used_cpu;
+	__u64 el_time;
+	__u64 mem_min_kb;
+	__u64 mem_max_kb;
+	__u64 mem_share_kb;
+	__u64 mem_used_kb;
+	__u32 pcpus;
+	__u32 lcpus;
+	__u32 vcpus;
+	__u32 cpu_min;
+	__u32 cpu_max;
+	__u32 cpu_shares;
+	__u32 cpu_use_samp;
+	__u32 cpu_delay_samp;
+	__u32 page_wait_samp;
+	__u32 idle_samp;
+	__u32 other_samp;
+	__u32 total_samp;
+	char  guest_name[NAME_LEN];
+};
+
+struct diag2fc_parm_list {
+	char userid[NAME_LEN];
+	char aci_grp[NAME_LEN];
+	__u64 addr;
+	__u32 size;
+	__u32 fmt;
+};
+
+static int diag2fc(int size, char* query, void *addr)
+{
+	unsigned long residual_cnt;
+	unsigned long rc;
+	struct diag2fc_parm_list parm_list;
+
+	memcpy(parm_list.userid, query, NAME_LEN);
+	ASCEBC(parm_list.userid, NAME_LEN);
+	parm_list.addr = (unsigned long) addr ;
+	parm_list.size = size;
+	parm_list.fmt = 0x02;
+	memset(parm_list.aci_grp, 0x40, NAME_LEN);
+	rc = -1;
+
+	asm volatile(
+		"	diag    %0,%1,0x2fc\n"
+		"0:\n"
+		EX_TABLE(0b,0b)
+		: "=d" (residual_cnt), "+d" (rc) : "0" (&parm_list) : "memory");
+
+	if ((rc != 0 ) && (rc != -2))
+		return rc;
+	else
+		return -residual_cnt;
+}
+
+static struct diag2fc_data *diag2fc_store(char *query, int *count)
+{
+	int size;
+	struct diag2fc_data *data;
+
+	do {
+		size = diag2fc(0, query, NULL);
+		if (size < 0)
+			return ERR_PTR(-EACCES);
+		data = vmalloc(size);
+		if (!data)
+			return ERR_PTR(-ENOMEM);
+		if (diag2fc(size, query, data) == 0)
+			break;
+		vfree(data);
+	} while (1);
+	*count = (size / sizeof(*data));
+
+	return data;
+}
+
+static void diag2fc_free(void *data)
+{
+	vfree(data);
+}
+
+#define ATTRIBUTE(sb, dir, name, member) \
+do { \
+	void *rc; \
+	rc = hypfs_create_u64(sb, dir, name, member); \
+	if (IS_ERR(rc)) \
+		return PTR_ERR(rc); \
+} while(0)
+
+static int hpyfs_vm_create_guest(struct super_block *sb,
+				 struct dentry *systems_dir,
+				 struct diag2fc_data *data)
+{
+	char guest_name[NAME_LEN + 1] = {};
+	struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir;
+	int dedicated_flag, capped_value;
+
+	capped_value = (data->flags & 0x00000006) >> 1;
+	dedicated_flag = (data->flags & 0x00000008) >> 3;
+
+	/* guest dir */
+	memcpy(guest_name, data->guest_name, NAME_LEN);
+	EBCASC(guest_name, NAME_LEN);
+	strstrip(guest_name);
+	guest_dir = hypfs_mkdir(sb, systems_dir, guest_name);
+	if (IS_ERR(guest_dir))
+		return PTR_ERR(guest_dir);
+	ATTRIBUTE(sb, guest_dir, "onlinetime_us", data->el_time);
+
+	/* logical cpu information */
+	cpus_dir = hypfs_mkdir(sb, guest_dir, "cpus");
+	if (IS_ERR(cpus_dir))
+		return PTR_ERR(cpus_dir);
+	ATTRIBUTE(sb, cpus_dir, "cputime_us", data->used_cpu);
+	ATTRIBUTE(sb, cpus_dir, "capped", capped_value);
+	ATTRIBUTE(sb, cpus_dir, "dedicated", dedicated_flag);
+	ATTRIBUTE(sb, cpus_dir, "count", data->vcpus);
+	ATTRIBUTE(sb, cpus_dir, "weight_min", data->cpu_min);
+	ATTRIBUTE(sb, cpus_dir, "weight_max", data->cpu_max);
+	ATTRIBUTE(sb, cpus_dir, "weight_cur", data->cpu_shares);
+
+	/* memory information */
+	mem_dir = hypfs_mkdir(sb, guest_dir, "mem");
+	if (IS_ERR(mem_dir))
+		return PTR_ERR(mem_dir);
+	ATTRIBUTE(sb, mem_dir, "min_KiB", data->mem_min_kb);
+	ATTRIBUTE(sb, mem_dir, "max_KiB", data->mem_max_kb);
+	ATTRIBUTE(sb, mem_dir, "used_KiB", data->mem_used_kb);
+	ATTRIBUTE(sb, mem_dir, "share_KiB", data->mem_share_kb);
+
+	/* samples */
+	samples_dir = hypfs_mkdir(sb, guest_dir, "samples");
+	if (IS_ERR(samples_dir))
+		return PTR_ERR(samples_dir);
+	ATTRIBUTE(sb, samples_dir, "cpu_using", data->cpu_use_samp);
+	ATTRIBUTE(sb, samples_dir, "cpu_delay", data->cpu_delay_samp);
+	ATTRIBUTE(sb, samples_dir, "mem_delay", data->page_wait_samp);
+	ATTRIBUTE(sb, samples_dir, "idle", data->idle_samp);
+	ATTRIBUTE(sb, samples_dir, "other", data->other_samp);
+	ATTRIBUTE(sb, samples_dir, "total", data->total_samp);
+	return 0;
+}
+
+int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
+{
+	struct dentry *dir, *file;
+	struct diag2fc_data *data;
+	int rc, i, count = 0;
+
+	data = diag2fc_store(guest_query, &count);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	/* Hpervisor Info */
+	dir = hypfs_mkdir(sb, root, "hyp");
+	if (IS_ERR(dir)) {
+		rc = PTR_ERR(dir);
+		goto failed;
+	}
+	file = hypfs_create_str(sb, dir, "type", "z/VM Hypervisor");
+	if (IS_ERR(file)) {
+		rc = PTR_ERR(file);
+		goto failed;
+	}
+
+	/* physical cpus */
+	dir = hypfs_mkdir(sb, root, "cpus");
+	if (IS_ERR(dir)) {
+		rc = PTR_ERR(dir);
+		goto failed;
+	}
+	file = hypfs_create_u64(sb, dir, "count", data->lcpus);
+	if (IS_ERR(file)) {
+		rc = PTR_ERR(file);
+		goto failed;
+	}
+
+	/* guests */
+	dir = hypfs_mkdir(sb, root, "systems");
+	if (IS_ERR(dir)) {
+		rc = PTR_ERR(dir);
+		goto failed;
+	}
+
+	for (i = 0; i < count; i++) {
+		rc = hpyfs_vm_create_guest(sb, dir, &(data[i]));
+		if (rc)
+			goto failed;
+	}
+	diag2fc_free(data);
+	return 0;
+
+failed:
+	diag2fc_free(data);
+	return rc;
+}
+
+int hypfs_vm_init(void)
+{
+	if (diag2fc(0, all_guests, NULL) > 0)
+		guest_query = all_guests;
+	else if (diag2fc(0, local_guest, NULL) > 0)
+		guest_query = local_guest;
+	else
+		return -EACCES;
+
+	return 0;
+}
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index b6716c4..a4fda7b 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <asm/ebcdic.h>
 #include "hypfs.h"
-#include "hypfs_diag.h"
 
 #define HYPFS_MAGIC 0x687970	/* ASCII 'hyp' */
 #define TMP_SIZE 64		/* size of temporary buffers */
@@ -192,7 +191,10 @@
 		goto out;
 	}
 	hypfs_delete_tree(sb->s_root);
-	rc = hypfs_diag_create_files(sb, sb->s_root);
+	if (MACHINE_IS_VM)
+		rc = hypfs_vm_create_files(sb, sb->s_root);
+	else
+		rc = hypfs_diag_create_files(sb, sb->s_root);
 	if (rc) {
 		printk(KERN_ERR "hypfs: Update failed\n");
 		hypfs_delete_tree(sb->s_root);
@@ -289,7 +291,10 @@
 		rc = -ENOMEM;
 		goto err_alloc;
 	}
-	rc = hypfs_diag_create_files(sb, root_dentry);
+	if (MACHINE_IS_VM)
+		rc = hypfs_vm_create_files(sb, root_dentry);
+	else
+		rc = hypfs_diag_create_files(sb, root_dentry);
 	if (rc)
 		goto err_tree;
 	sbi->update_file = hypfs_create_update_file(sb, root_dentry);
@@ -462,11 +467,15 @@
 {
 	int rc;
 
-	if (MACHINE_IS_VM)
-		return -ENODATA;
-	if (hypfs_diag_init()) {
-		rc = -ENODATA;
-		goto fail_diag;
+	if (MACHINE_IS_VM) {
+		if (hypfs_vm_init())
+			/* no diag 2fc, just exit */
+			return -ENODATA;
+	} else {
+		if (hypfs_diag_init()) {
+			rc = -ENODATA;
+			goto fail_diag;
+		}
 	}
 	kset_set_kset_s(&s390_subsys, hypervisor_subsys);
 	rc = subsystem_register(&s390_subsys);
@@ -480,7 +489,8 @@
 fail_filesystem:
 	subsystem_unregister(&s390_subsys);
 fail_sysfs:
-	hypfs_diag_exit();
+	if (!MACHINE_IS_VM)
+		hypfs_diag_exit();
 fail_diag:
 	printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc);
 	return rc;
@@ -488,7 +498,8 @@
 
 static void __exit hypfs_exit(void)
 {
-	hypfs_diag_exit();
+	if (!MACHINE_IS_VM)
+		hypfs_diag_exit();
 	unregister_filesystem(&hypfs_type);
 	subsystem_unregister(&s390_subsys);
 }
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index a81881c..5492d25 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -4,9 +4,9 @@
 
 EXTRA_AFLAGS	:= -traditional
 
-obj-y	:=  bitmap.o traps.o time.o process.o reset.o \
+obj-y	:=  bitmap.o traps.o time.o process.o base.o early.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-	    semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o
+	    semaphore.o s390_ext.o debug.o irq.o ipl.o
 
 obj-y	+= $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
new file mode 100644
index 0000000..dc7e525
--- /dev/null
+++ b/arch/s390/kernel/base.S
@@ -0,0 +1,150 @@
+/*
+ *  arch/s390/kernel/base.S
+ *
+ *    Copyright IBM Corp. 2006,2007
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ *		 Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <asm/ptrace.h>
+#include <asm/lowcore.h>
+
+#ifdef CONFIG_64BIT
+
+	.globl	s390_base_mcck_handler
+s390_base_mcck_handler:
+	basr	%r13,0
+0:	lg	%r15,__LC_PANIC_STACK	# load panic stack
+	aghi	%r15,-STACK_FRAME_OVERHEAD
+	larl	%r1,s390_base_mcck_handler_fn
+	lg	%r1,0(%r1)
+	ltgr	%r1,%r1
+	jz	1f
+	basr	%r14,%r1
+1:	la	%r1,4095
+	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
+	lpswe	__LC_MCK_OLD_PSW
+
+	.section .bss
+	.globl	s390_base_mcck_handler_fn
+s390_base_mcck_handler_fn:
+	.quad	0
+	.previous
+
+	.globl	s390_base_ext_handler
+s390_base_ext_handler:
+	stmg	%r0,%r15,__LC_SAVE_AREA
+	basr	%r13,0
+0:	aghi	%r15,-STACK_FRAME_OVERHEAD
+	larl	%r1,s390_base_ext_handler_fn
+	lg	%r1,0(%r1)
+	ltgr	%r1,%r1
+	jz	1f
+	basr	%r14,%r1
+1:	lmg	%r0,%r15,__LC_SAVE_AREA
+	ni	__LC_EXT_OLD_PSW+1,0xfd	# clear wait state bit
+	lpswe	__LC_EXT_OLD_PSW
+
+	.section .bss
+	.globl s390_base_ext_handler_fn
+s390_base_ext_handler_fn:
+	.quad	0
+	.previous
+
+	.globl	s390_base_pgm_handler
+s390_base_pgm_handler:
+	stmg	%r0,%r15,__LC_SAVE_AREA
+	basr	%r13,0
+0:	aghi	%r15,-STACK_FRAME_OVERHEAD
+	larl	%r1,s390_base_pgm_handler_fn
+	lg	%r1,0(%r1)
+	ltgr	%r1,%r1
+	jz	1f
+	basr	%r14,%r1
+	lmg	%r0,%r15,__LC_SAVE_AREA
+	lpswe	__LC_PGM_OLD_PSW
+1:	lpswe	disabled_wait_psw-0b(%r13)
+
+	.align	8
+disabled_wait_psw:
+	.quad	0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
+
+	.section .bss
+	.globl s390_base_pgm_handler_fn
+s390_base_pgm_handler_fn:
+	.quad	0
+	.previous
+
+#else /* CONFIG_64BIT */
+
+	.globl	s390_base_mcck_handler
+s390_base_mcck_handler:
+	basr	%r13,0
+0:	l	%r15,__LC_PANIC_STACK	# load panic stack
+	ahi	%r15,-STACK_FRAME_OVERHEAD
+	l	%r1,2f-0b(%r13)
+	l	%r1,0(%r1)
+	ltr	%r1,%r1
+	jz	1f
+	basr	%r14,%r1
+1:	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA
+	lpsw	__LC_MCK_OLD_PSW
+
+2:	.long	s390_base_mcck_handler_fn
+
+	.section .bss
+	.globl	s390_base_mcck_handler_fn
+s390_base_mcck_handler_fn:
+	.long	0
+	.previous
+
+	.globl	s390_base_ext_handler
+s390_base_ext_handler:
+	stm	%r0,%r15,__LC_SAVE_AREA
+	basr	%r13,0
+0:	ahi	%r15,-STACK_FRAME_OVERHEAD
+	l	%r1,2f-0b(%r13)
+	l	%r1,0(%r1)
+	ltr	%r1,%r1
+	jz	1f
+	basr	%r14,%r1
+1:	lm	%r0,%r15,__LC_SAVE_AREA
+	ni	__LC_EXT_OLD_PSW+1,0xfd	# clear wait state bit
+	lpsw	__LC_EXT_OLD_PSW
+
+2:	.long	s390_base_ext_handler_fn
+
+	.section .bss
+	.globl	s390_base_ext_handler_fn
+s390_base_ext_handler_fn:
+	.long	0
+	.previous
+
+	.globl	s390_base_pgm_handler
+s390_base_pgm_handler:
+	stm	%r0,%r15,__LC_SAVE_AREA
+	basr	%r13,0
+0:	ahi	%r15,-STACK_FRAME_OVERHEAD
+	l	%r1,2f-0b(%r13)
+	l	%r1,0(%r1)
+	ltr	%r1,%r1
+	jz	1f
+	basr	%r14,%r1
+	lm	%r0,%r15,__LC_SAVE_AREA
+	lpsw	__LC_PGM_OLD_PSW
+
+1:	lpsw	disabled_wait_psw-0b(%r13)
+
+2:	.long	s390_base_pgm_handler_fn
+
+disabled_wait_psw:
+	.align	8
+	.long	0x000a0000,0x00000000 + s390_base_pgm_handler
+
+	.section .bss
+	.globl	s390_base_pgm_handler_fn
+s390_base_pgm_handler_fn:
+	.long	0
+	.previous
+
+#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
index 5c46054..f1e40ca 100644
--- a/arch/s390/kernel/binfmt_elf32.c
+++ b/arch/s390/kernel/binfmt_elf32.c
@@ -192,7 +192,7 @@
 
 #undef cputime_to_timeval
 #define cputime_to_timeval cputime_to_compat_timeval
-static __inline__ void
+static inline void
 cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
 {
 	value->tv_usec = cputime % 1000000;
diff --git a/arch/s390/kernel/compat_exec_domain.c b/arch/s390/kernel/compat_exec_domain.c
index 71d27c4..914d494 100644
--- a/arch/s390/kernel/compat_exec_domain.c
+++ b/arch/s390/kernel/compat_exec_domain.c
@@ -12,10 +12,9 @@
 #include <linux/personality.h>
 #include <linux/sched.h>
 
-struct exec_domain s390_exec_domain;
+static struct exec_domain s390_exec_domain;
 
-static int __init
-s390_init (void)
+static int __init s390_init (void)
 {
 	s390_exec_domain.name = "Linux/s390";
 	s390_exec_domain.handler = NULL;
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 5b33f82..666bb6d 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -69,6 +69,12 @@
 
 #include "compat_linux.h"
 
+long psw_user32_bits	= (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+			   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+			   PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
+long psw32_user_bits	= (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
+			   PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
+			   PSW32_MASK_PSTATE);
  
 /* For this source file, we want overflow handling. */
 
@@ -416,7 +422,7 @@
 	mm_segment_t old_fs = get_fs ();
 	
 	set_fs (KERNEL_DS);
-	ret = sys_sysinfo((struct sysinfo __user *) &s);
+	ret = sys_sysinfo((struct sysinfo __force __user *) &s);
 	set_fs (old_fs);
 	err = put_user (s.uptime, &info->uptime);
 	err |= __put_user (s.loads[0], &info->loads[0]);
@@ -445,7 +451,8 @@
 	mm_segment_t old_fs = get_fs ();
 	
 	set_fs (KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
+	ret = sys_sched_rr_get_interval(pid,
+					(struct timespec __force __user *) &t);
 	set_fs (old_fs);
 	if (put_compat_timespec(&t, interval))
 		return -EFAULT;
@@ -472,8 +479,8 @@
 	}
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigprocmask(how,
-				 set ? (sigset_t __user *) &s : NULL,
-				 oset ? (sigset_t __user *) &s : NULL,
+				 set ? (sigset_t __force __user *) &s : NULL,
+				 oset ? (sigset_t __force __user *) &s : NULL,
 				 sigsetsize);
 	set_fs (old_fs);
 	if (ret) return ret;
@@ -499,7 +506,7 @@
 	mm_segment_t old_fs = get_fs();
 		
 	set_fs (KERNEL_DS);
-	ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
+	ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize);
 	set_fs (old_fs);
 	if (!ret) {
 		switch (_NSIG_WORDS) {
@@ -524,7 +531,7 @@
 	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *) &info);
 	set_fs (old_fs);
 	return ret;
 }
@@ -682,7 +689,7 @@
 		
 	set_fs(KERNEL_DS);
 	ret = sys_sendfile(out_fd, in_fd,
-			   offset ? (off_t __user *) &of : NULL, count);
+			   offset ? (off_t __force __user *) &of : NULL, count);
 	set_fs(old_fs);
 	
 	if (offset && put_user(of, offset))
@@ -703,7 +710,8 @@
 		
 	set_fs(KERNEL_DS);
 	ret = sys_sendfile64(out_fd, in_fd,
-			     offset ? (loff_t __user *) &lof : NULL, count);
+			     offset ? (loff_t __force __user *) &lof : NULL,
+			     count);
 	set_fs(old_fs);
 	
 	if (offset && put_user(lof, offset))
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 1a18e29..e89f8c0 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -115,37 +115,6 @@
         __u32	addr;
 } _psw_t32 __attribute__ ((aligned(8)));
 
-#define PSW32_MASK_PER		0x40000000UL
-#define PSW32_MASK_DAT		0x04000000UL
-#define PSW32_MASK_IO		0x02000000UL
-#define PSW32_MASK_EXT		0x01000000UL
-#define PSW32_MASK_KEY		0x00F00000UL
-#define PSW32_MASK_MCHECK	0x00040000UL
-#define PSW32_MASK_WAIT		0x00020000UL
-#define PSW32_MASK_PSTATE	0x00010000UL
-#define PSW32_MASK_ASC		0x0000C000UL
-#define PSW32_MASK_CC		0x00003000UL
-#define PSW32_MASK_PM		0x00000f00UL
-
-#define PSW32_ADDR_AMODE31	0x80000000UL
-#define PSW32_ADDR_INSN		0x7FFFFFFFUL
-
-#define PSW32_BASE_BITS		0x00080000UL
-
-#define PSW32_ASC_PRIMARY	0x00000000UL
-#define PSW32_ASC_ACCREG	0x00004000UL
-#define PSW32_ASC_SECONDARY	0x00008000UL
-#define PSW32_ASC_HOME		0x0000C000UL
-
-#define PSW32_USER_BITS	(PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME | \
-			 PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | \
-			 PSW32_MASK_PSTATE)
-
-#define PSW32_MASK_MERGE(CURRENT,NEW) \
-        (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
-         ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
-
-
 typedef struct
 {
 	_psw_t32	psw;
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 861888a..887a988 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -275,8 +275,8 @@
 	}
 
 	set_fs (KERNEL_DS);
-	ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL),
-			     (stack_t __user *) (uoss ? &koss : NULL),
+	ret = do_sigaltstack((stack_t __force __user *) (uss ? &kss : NULL),
+			     (stack_t __force __user *) (uoss ? &koss : NULL),
 			     regs->gprs[15]);
 	set_fs (old_fs);
 
@@ -298,7 +298,7 @@
 	_s390_regs_common32 regs32;
 	int err, i;
 
-	regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS,
+	regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
 					   (__u32)(regs->psw.mask >> 32));
 	regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
 	for (i = 0; i < NUM_GPRS; i++)
@@ -401,7 +401,7 @@
 		goto badframe; 
 
 	set_fs (KERNEL_DS);
-	do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
+	do_sigaltstack((stack_t __force __user *)&st, NULL, regs->gprs[15]);
 	set_fs (old_fs);
 
 	return regs->gprs[2];
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index a5972f1..6c89f30 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -16,6 +16,7 @@
 #include <asm/ebcdic.h>
 #include <asm/cpcmd.h>
 #include <asm/system.h>
+#include <asm/io.h>
 
 static DEFINE_SPINLOCK(cpcmd_lock);
 static char cpcmd_buf[241];
@@ -88,13 +89,8 @@
 	int len;
 	unsigned long flags;
 
-	if ((rlen == 0) || (response == NULL)
-	    || !((unsigned long)response >> 31)) {
-		spin_lock_irqsave(&cpcmd_lock, flags);
-		len = __cpcmd(cmd, response, rlen, response_code);
-		spin_unlock_irqrestore(&cpcmd_lock, flags);
-	}
-	else {
+	if ((virt_to_phys(response) != (unsigned long) response) ||
+			(((unsigned long)response + rlen) >> 31)) {
 		lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
 		if (!lowbuf) {
 			printk(KERN_WARNING
@@ -106,6 +102,10 @@
 		spin_unlock_irqrestore(&cpcmd_lock, flags);
 		memcpy(response, lowbuf, rlen);
 		kfree(lowbuf);
+	} else {
+		spin_lock_irqsave(&cpcmd_lock, flags);
+		len = __cpcmd(cmd, response, rlen, response_code);
+		spin_unlock_irqrestore(&cpcmd_lock, flags);
 	}
 	return len;
 }
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
index 926ccee..8cc7c9f 100644
--- a/arch/s390/kernel/crash.c
+++ b/arch/s390/kernel/crash.c
@@ -9,6 +9,7 @@
 
 #include <linux/threads.h>
 #include <linux/kexec.h>
+#include <linux/reboot.h>
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index bb57bc0..f4b62df 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -120,7 +120,7 @@
 	NULL
 };
 
-struct debug_view debug_level_view = {
+static struct debug_view debug_level_view = {
 	"level",
 	&debug_prolog_level_fn,
 	NULL,
@@ -129,7 +129,7 @@
 	NULL
 };
 
-struct debug_view debug_pages_view = {
+static struct debug_view debug_pages_view = {
 	"pages",
 	&debug_prolog_pages_fn,
 	NULL,
@@ -138,7 +138,7 @@
 	NULL
 };
 
-struct debug_view debug_flush_view = {
+static struct debug_view debug_flush_view = {
         "flush",
         NULL,
         NULL,
@@ -156,14 +156,14 @@
 	NULL
 };
 
-
+/* used by dump analysis tools to determine version of debug feature */
 unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
 
 /* static globals */
 
 static debug_info_t *debug_area_first = NULL;
 static debug_info_t *debug_area_last = NULL;
-DECLARE_MUTEX(debug_lock);
+static DECLARE_MUTEX(debug_lock);
 
 static int initialized;
 
@@ -905,7 +905,7 @@
 	{ .ctl_name = 0 }
 };
 
-struct ctl_table_header *s390dbf_sysctl_header;
+static struct ctl_table_header *s390dbf_sysctl_header;
 
 void
 debug_stop_all(void)
@@ -1300,8 +1300,7 @@
  * flushes debug areas
  */
  
-void
-debug_flush(debug_info_t* id, int area)
+static void debug_flush(debug_info_t* id, int area)
 {
         unsigned long flags;
         int i,j;
@@ -1511,8 +1510,7 @@
 /*
  * clean up module
  */
-void
-__exit debug_exit(void)
+static void __exit debug_exit(void)
 {
 	debugfs_remove(debug_debugfs_root_entry);
 	unregister_sysctl_table(s390dbf_sysctl_header);
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
new file mode 100644
index 0000000..e518dd5
--- /dev/null
+++ b/arch/s390/kernel/early.c
@@ -0,0 +1,306 @@
+/*
+ *  arch/s390/kernel/early.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Hongjie Yang <hongjie@us.ibm.com>,
+ *		 Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/uaccess.h>
+#include <asm/lowcore.h>
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/cpcmd.h>
+#include <asm/sclp.h>
+
+/*
+ * Create a Kernel NSS if the SAVESYS= parameter is defined
+ */
+#define DEFSYS_CMD_SIZE		96
+#define SAVESYS_CMD_SIZE	32
+
+char kernel_nss_name[NSS_NAME_SIZE + 1];
+
+#ifdef CONFIG_SHARED_KERNEL
+static noinline __init void create_kernel_nss(void)
+{
+	unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
+#ifdef CONFIG_BLK_DEV_INITRD
+	unsigned int sinitrd_pfn, einitrd_pfn;
+#endif
+	int response;
+	char *savesys_ptr;
+	char upper_command_line[COMMAND_LINE_SIZE];
+	char defsys_cmd[DEFSYS_CMD_SIZE];
+	char savesys_cmd[SAVESYS_CMD_SIZE];
+
+	/* Do nothing if we are not running under VM */
+	if (!MACHINE_IS_VM)
+		return;
+
+	/* Convert COMMAND_LINE to upper case */
+	for (i = 0; i < strlen(COMMAND_LINE); i++)
+		upper_command_line[i] = toupper(COMMAND_LINE[i]);
+
+	savesys_ptr = strstr(upper_command_line, "SAVESYS=");
+
+	if (!savesys_ptr)
+		return;
+
+	savesys_ptr += 8;    /* Point to the beginning of the NSS name */
+	for (i = 0; i < NSS_NAME_SIZE; i++) {
+		if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
+			break;
+		kernel_nss_name[i] = savesys_ptr[i];
+	}
+
+	stext_pfn = PFN_DOWN(__pa(&_stext));
+	eshared_pfn = PFN_DOWN(__pa(&_eshared));
+	end_pfn = PFN_UP(__pa(&_end));
+	min_size = end_pfn << 2;
+
+	sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
+		kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
+		eshared_pfn, end_pfn);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (INITRD_START && INITRD_SIZE) {
+		sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
+		einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
+		min_size = einitrd_pfn << 2;
+		sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
+		sinitrd_pfn, einitrd_pfn);
+	}
+#endif
+
+	sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
+	sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
+		kernel_nss_name, kernel_nss_name);
+
+	__cpcmd(defsys_cmd, NULL, 0, &response);
+
+	if (response != 0)
+		return;
+
+	__cpcmd(savesys_cmd, NULL, 0, &response);
+
+	if (response != strlen(savesys_cmd))
+		return;
+
+	ipl_flags = IPL_NSS_VALID;
+}
+
+#else /* CONFIG_SHARED_KERNEL */
+
+static inline void create_kernel_nss(void) { }
+
+#endif /* CONFIG_SHARED_KERNEL */
+
+/*
+ * Clear bss memory
+ */
+static noinline __init void clear_bss_section(void)
+{
+	memset(__bss_start, 0, _end - __bss_start);
+}
+
+/*
+ * Initialize storage key for kernel pages
+ */
+static noinline __init void init_kernel_storage_key(void)
+{
+	unsigned long end_pfn, init_pfn;
+
+	end_pfn = PFN_UP(__pa(&_end));
+
+	for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
+		page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+}
+
+static noinline __init void detect_machine_type(void)
+{
+	struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
+
+	asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
+
+	/* Running under z/VM ? */
+	if (cpuinfo->cpu_id.version == 0xff)
+		machine_flags |= 1;
+
+	/* Running on a P/390 ? */
+	if (cpuinfo->cpu_id.machine == 0x7490)
+		machine_flags |= 4;
+}
+
+static noinline __init int memory_fast_detect(void)
+{
+
+	unsigned long val0 = 0;
+	unsigned long val1 = 0xc;
+	int ret = -ENOSYS;
+
+	if (ipl_flags & IPL_NSS_VALID)
+		return -ENOSYS;
+
+	asm volatile(
+		"	diag	%1,%2,0x260\n"
+		"0:	lhi	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (ret), "+d" (val0), "+d" (val1) : : "cc");
+
+	if (ret || val0 != val1)
+		return -ENOSYS;
+
+	memory_chunk[0].size = val0;
+	return 0;
+}
+
+#define ADDR2G	(1UL << 31)
+
+static noinline __init unsigned long sclp_memory_detect(void)
+{
+	struct sclp_readinfo_sccb *sccb;
+	unsigned long long memsize;
+
+	sccb = &s390_readinfo_sccb;
+
+	if (sccb->header.response_code != 0x10)
+		return 0;
+
+	if (sccb->rnsize)
+		memsize = sccb->rnsize << 20;
+	else
+		memsize = sccb->rnsize2 << 20;
+	if (sccb->rnmax)
+		memsize *= sccb->rnmax;
+	else
+		memsize *= sccb->rnmax2;
+#ifndef CONFIG_64BIT
+	/*
+	 * Can't deal with more than 2G in 31 bit addressing mode, so
+	 * limit the value in order to avoid strange side effects.
+	 */
+	if (memsize > ADDR2G)
+		memsize = ADDR2G;
+#endif
+	return (unsigned long) memsize;
+}
+
+static inline __init unsigned long __tprot(unsigned long addr)
+{
+	int cc = -1;
+
+	asm volatile(
+		"	tprot	0(%1),0\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (cc) : "a" (addr) : "cc");
+	return (unsigned long)cc;
+}
+
+/* Checking memory in 128KB increments. */
+#define CHUNK_INCR	(1UL << 17)
+
+static noinline __init void find_memory_chunks(unsigned long memsize)
+{
+	unsigned long addr = 0, old_addr = 0;
+	unsigned long old_cc = CHUNK_READ_WRITE;
+	unsigned long cc;
+	int chunk = 0;
+
+	while (chunk < MEMORY_CHUNKS) {
+		cc = __tprot(addr);
+		while (cc == old_cc) {
+			addr += CHUNK_INCR;
+			cc = __tprot(addr);
+#ifndef CONFIG_64BIT
+			if (addr == ADDR2G)
+				break;
+#endif
+		}
+
+		if (old_addr != addr &&
+		    (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) {
+			memory_chunk[chunk].addr = old_addr;
+			memory_chunk[chunk].size = addr - old_addr;
+			memory_chunk[chunk].type = old_cc;
+			chunk++;
+		}
+
+		old_addr = addr;
+		old_cc = cc;
+
+#ifndef CONFIG_64BIT
+		if (addr == ADDR2G)
+			break;
+#endif
+		/*
+		 * Finish memory detection at the first hole, unless
+		 * - we reached the hsa -> skip it.
+		 * - we know there must be more.
+		 */
+		if (cc == -1UL && !memsize && old_addr != ADDR2G)
+			break;
+		if (memsize && addr >= memsize)
+			break;
+	}
+}
+
+static __init void early_pgm_check_handler(void)
+{
+	unsigned long addr;
+	const struct exception_table_entry *fixup;
+
+	addr = S390_lowcore.program_old_psw.addr;
+	fixup = search_exception_tables(addr & PSW_ADDR_INSN);
+	if (!fixup)
+		disabled_wait(0);
+	S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
+}
+
+static noinline __init void setup_lowcore_early(void)
+{
+	psw_t psw;
+
+	psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
+	S390_lowcore.external_new_psw = psw;
+	psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
+	S390_lowcore.program_new_psw = psw;
+	s390_base_pgm_handler_fn = early_pgm_check_handler;
+}
+
+/*
+ * Save ipl parameters, clear bss memory, initialize storage keys
+ * and create a kernel NSS at startup if the SAVESYS= parm is defined
+ */
+void __init startup_init(void)
+{
+	unsigned long memsize;
+
+	ipl_save_parameters();
+	clear_bss_section();
+	init_kernel_storage_key();
+	lockdep_init();
+	lockdep_off();
+	detect_machine_type();
+	create_kernel_nss();
+	sort_main_extable();
+	setup_lowcore_early();
+	sclp_readinfo_early();
+	memsize = sclp_memory_detect();
+	if (memory_fast_detect() < 0)
+		find_memory_chunks(memsize);
+	lockdep_on();
+}
diff --git a/arch/s390/kernel/ebcdic.c b/arch/s390/kernel/ebcdic.c
index bb0f973..cc0dc60 100644
--- a/arch/s390/kernel/ebcdic.c
+++ b/arch/s390/kernel/ebcdic.c
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <asm/types.h>
+#include <asm/ebcdic.h>
 
 /*
  * ASCII (IBM PC 437)  -> EBCDIC 037
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 4388b33..453fd3b 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -51,166 +51,15 @@
 	st	%r15,__LC_KERNEL_STACK	# set end of kernel stack
 	ahi	%r15,-96
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
-	l	%r14,.Lipl_save_parameters-.LPG1(%r13)
+#
+# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
+# and create a kernel NSS if the SAVESYS= parm is defined
+#
+	l	%r14,.Lstartup_init-.LPG1(%r13)
 	basr	%r14,%r14
-#
-# clear bss memory
-#
-	l	%r2,.Lbss_bgn-.LPG1(%r13) # start of bss
-	l	%r3,.Lbss_end-.LPG1(%r13) # end of bss
-	sr	%r3,%r2			# length of bss
-	sr	%r4,%r4
-	sr	%r5,%r5			# set src,length and pad to zero
-	sr	%r0,%r0
-	mvcle	%r2,%r4,0		# clear mem
-	jo	.-4			# branch back, if not finish
 
-	l	%r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
-.Lservicecall:
-	stosm	.Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
-
-	stctl	%r0, %r0,.Lcr-.LPG1(%r13)	# get cr0
-	la	%r1,0x200		# set bit 22
-	o	%r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
-	st	%r1,.Lcr-.LPG1(%r13)
-	lctl	%r0, %r0,.Lcr-.LPG1(%r13)	# load modified cr0
-
-	mvc	__LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
-	la	%r1, .Lsclph-.LPG1(%r13)
-	a	%r1,__LC_EXT_NEW_PSW+4	# set handler
-	st	%r1,__LC_EXT_NEW_PSW+4
-
-	l	%r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff
-	lr	%r1,%r4			# our sccb
-	.insn	rre,0xb2200000,%r2,%r1	# service call
-	ipm	%r1
-	srl	%r1,28			# get cc code
-	xr	%r3, %r3
-	chi	%r1,3
-	be	.Lfchunk-.LPG1(%r13)	# leave
-	chi	%r1,2
-	be	.Lservicecall-.LPG1(%r13)
-	lpsw	.Lwaitsclp-.LPG1(%r13)
-.Lsclph:
-	lh	%r1,.Lsccbr-.Lsccb(%r4)
-	chi	%r1,0x10		# 0x0010 is the sucess code
-	je	.Lprocsccb		# let's process the sccb
-	chi	%r1,0x1f0
-	bne	.Lfchunk-.LPG1(%r13)	# unhandled error code
-	c	%r2, .Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
-	bne	.Lfchunk-.LPG1(%r13)	# if no, give up
-	l	%r2, .Lrcp2-.LPG1(%r13)	# try with Read SCP
-	b	.Lservicecall-.LPG1(%r13)
-.Lprocsccb:
-	lhi	%r1,0
-	icm	%r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
-	jnz	.Lscnd
-	lhi	%r1,0x800		# otherwise report 2GB
-.Lscnd:
-	lhi	%r3,0x800		# limit reported memory size to 2GB
-	cr	%r1,%r3
-	jl	.Lno2gb
-	lr	%r1,%r3
-.Lno2gb:
-	xr	%r3,%r3			# same logic
-	ic	%r3,.Lscpa1-.Lsccb(%r4)
-	chi	%r3,0x00
-	jne	.Lcompmem
-	l	%r3,.Lscpa2-.Lsccb(%r4)
-.Lcompmem:
-	mr	%r2,%r1			# mem in MB on 128-bit
-	l	%r1,.Lonemb-.LPG1(%r13)
-	mr	%r2,%r1			# mem size in bytes in %r3
-	b	.Lfchunk-.LPG1(%r13)
-
-	.align 4
-.Lipl_save_parameters:
-	.long	ipl_save_parameters
-.Linittu:
-	.long	init_thread_union
-.Lpmask:
-	.byte	0
-	.align	8
-.Lpcext:.long	0x00080000,0x80000000
-.Lcr:
-	.long	0x00			# place holder for cr0
-	.align	8
-.Lwaitsclp:
-	.long 0x010a0000,0x80000000 + .Lsclph
-.Lrcp:
-	.int	0x00120001		# Read SCP forced code
-.Lrcp2:
-	.int	0x00020001		# Read SCP code
-.Lonemb:
-	.int	0x100000
-.Lfchunk:
-
-#
-# find memory chunks.
-#
-	lr	%r9,%r3			# end of mem
-	mvc	__LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
-	la	%r1,1			# test in increments of 128KB
-	sll	%r1,17
-	l	%r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
-	slr	%r4,%r4			# set start of chunk to zero
-	slr	%r5,%r5			# set end of chunk to zero
-	slr	%r6,%r6			# set access code to zero
-	la	%r10,MEMORY_CHUNKS	# number of chunks
-.Lloop:
-	tprot	0(%r5),0		# test protection of first byte
-	ipm	%r7
-	srl	%r7,28
-	clr	%r6,%r7			# compare cc with last access code
-	be	.Lsame-.LPG1(%r13)
-	b	.Lchkmem-.LPG1(%r13)
-.Lsame:
-	ar	%r5,%r1			# add 128KB to end of chunk
-	bno	.Lloop-.LPG1(%r13)	# r1 < 0x80000000 -> loop
-.Lchkmem:				# > 2GB or tprot got a program check
-	clr	%r4,%r5			# chunk size > 0?
-	be	.Lchkloop-.LPG1(%r13)
-	st	%r4,0(%r3)		# store start address of chunk
-	lr	%r0,%r5
-	slr	%r0,%r4
-	st	%r0,4(%r3)		# store size of chunk
-	st	%r6,8(%r3)		# store type of chunk
-	la	%r3,12(%r3)
-	ahi	%r10,-1			# update chunk number
-.Lchkloop:
-	lr	%r6,%r7			# set access code to last cc
-	# we got an exception or we're starting a new
-	# chunk , we must check if we should
-	# still try to find valid memory (if we detected
-	# the amount of available storage), and if we
-	# have chunks left
-	xr	%r0,%r0
-	clr	%r0,%r9			# did we detect memory?
-	je	.Ldonemem		# if not, leave
-	chi	%r10,0			# do we have chunks left?
-	je	.Ldonemem
-	alr	%r5,%r1			# add 128KB to end of chunk
-	lr	%r4,%r5			# potential new chunk
-	clr	%r5,%r9			# should we go on?
-	jl	.Lloop
-.Ldonemem:
 	l	%r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
 #
-# find out if we are running under VM
-#
-	stidp	__LC_CPUID		# store cpuid
-	tm	__LC_CPUID,0xff		# running under VM ?
-	bno	.Lnovm-.LPG1(%r13)
-	oi	3(%r12),1		# set VM flag
-.Lnovm:
-	lh	%r0,__LC_CPUID+4	# get cpu version
-	chi	%r0,0x7490		# running on a P/390 ?
-	bne	.Lnop390-.LPG1(%r13)
-	oi	3(%r12),4		# set P/390 flag
-.Lnop390:
-
-#
 # find out if we have an IEEE fpu
 #
 	mvc	__LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
@@ -285,7 +134,6 @@
 	.long	0			# cr15: linkage stack operations
 .Lduct:	.long	0,0,0,0,0,0,0,0
 	.long	0,0,0,0,0,0,0,0
-.Lpcmem:.long	0x00080000,0x80000000 + .Lchkmem
 .Lpcfpu:.long	0x00080000,0x80000000 + .Lchkfpu
 .Lpccsp:.long	0x00080000,0x80000000 + .Lchkcsp
 .Lpcmvpg:.long	0x00080000,0x80000000 + .Lchkmvpg
@@ -296,7 +144,9 @@
 .Lbss_bgn:  .long __bss_start
 .Lbss_end:  .long _end
 .Lparmaddr: .long PARMAREA
-.Lsccbaddr: .long .Lsccb
+.Linittu:   .long init_thread_union
+.Lstartup_init:
+	    .long startup_init
 
 	.globl ipl_schib
 ipl_schib:
@@ -312,26 +162,6 @@
 	.word 0
 
 	.org	0x12000
-.globl s390_readinfo_sccb
-s390_readinfo_sccb:
-.Lsccb:
-	.hword	0x1000			# length, one page
-	.byte	0x00,0x00,0x00
-	.byte	0x80			# variable response bit set
-.Lsccbr:
-	.hword	0x00			# response code
-.Lscpincr1:
-	.hword	0x00
-.Lscpa1:
-	.byte	0x00
-	.fill	89,1,0
-.Lscpa2:
-	.int	0x00
-.Lscpincr2:
-	.quad	0x00
-	.fill	3984,1,0
-	.org	0x13000
-
 #ifdef CONFIG_SHARED_KERNEL
 	.org	0x100000
 #endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index c526279e1..b8fec4e 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -58,173 +58,15 @@
 	stg	%r15,__LC_KERNEL_STACK	# set end of kernel stack
 	aghi	%r15,-160
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
-	brasl	%r14,ipl_save_parameters
 #
-# clear bss memory
+# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
+# and create a kernel NSS if the SAVESYS= parm is defined
 #
-	larl	%r2,__bss_start 	# start of bss segment
-	larl	%r3,_end		# end of bss segment
-	sgr	%r3,%r2 		# length of bss
-	sgr	%r4,%r4 		#
-	sgr	%r5,%r5 		# set src,length and pad to zero
-	mvcle	%r2,%r4,0		# clear mem
-	jo	.-4			# branch back, if not finish
+	brasl	%r14,startup_init
 					# set program check new psw mask
 	mvc	__LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
-	larl	%r1,.Lslowmemdetect	# set program check address
-	stg	%r1,__LC_PGM_NEW_PSW+8
-	lghi	%r1,0xc
-	diag	%r0,%r1,0x260		# get memory size of virtual machine
-	cgr	%r0,%r1			# different? -> old detection routine
-	jne	.Lslowmemdetect
-	aghi	%r1,1			# size is one more than end
-	larl	%r2,memory_chunk
-	stg	%r1,8(%r2)		# store size of chunk
-	j	.Ldonemem
-
-.Lslowmemdetect:
-	l	%r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
-.Lservicecall:
-	stosm	.Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
-
-	stctg	%r0,%r0,.Lcr-.LPG1(%r13)	# get cr0
-	la	%r1,0x200		# set bit 22
-	og	%r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
-	stg	%r1,.Lcr-.LPG1(%r13)
-	lctlg	%r0,%r0,.Lcr-.LPG1(%r13)	# load modified cr0
-
-	mvc	__LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
-	larl	%r1,.Lsclph
-	stg	%r1,__LC_EXT_NEW_PSW+8	# set handler
-
-	larl	%r4,.Lsccb		# %r4 is our index for sccb stuff
-	lgr	%r1,%r4			# our sccb
-	.insn	rre,0xb2200000,%r2,%r1	# service call
-	ipm	%r1
-	srl	%r1,28			# get cc code
-	xr	%r3,%r3
-	chi	%r1,3
-	be	.Lfchunk-.LPG1(%r13)	# leave
-	chi	%r1,2
-	be	.Lservicecall-.LPG1(%r13)
-	lpswe	.Lwaitsclp-.LPG1(%r13)
-.Lsclph:
-	lh	%r1,.Lsccbr-.Lsccb(%r4)
-	chi	%r1,0x10		# 0x0010 is the sucess code
-	je	.Lprocsccb		# let's process the sccb
-	chi	%r1,0x1f0
-	bne	.Lfchunk-.LPG1(%r13)	# unhandled error code
-	c	%r2,.Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
-	bne	.Lfchunk-.LPG1(%r13)	# if no, give up
-	l	%r2,.Lrcp2-.LPG1(%r13)	# try with Read SCP
-	b	.Lservicecall-.LPG1(%r13)
-.Lprocsccb:
-	lghi	%r1,0
-	icm	%r1,3,.Lscpincr1-.Lsccb(%r4)	# use this one if != 0
-	jnz	.Lscnd
-	lg	%r1,.Lscpincr2-.Lsccb(%r4)	# otherwise use this one
-.Lscnd:
-	xr	%r3,%r3			# same logic
-	ic	%r3,.Lscpa1-.Lsccb(%r4)
-	chi	%r3,0x00
-	jne	.Lcompmem
-	l	%r3,.Lscpa2-.Lsccb(%r4)
-.Lcompmem:
-	mlgr	%r2,%r1			# mem in MB on 128-bit
-	l	%r1,.Lonemb-.LPG1(%r13)
-	mlgr	%r2,%r1			# mem size in bytes in %r3
-	b	.Lfchunk-.LPG1(%r13)
-
-	.align	4
-.Lpmask:
-	.byte	0
-	.align	8
-.Lcr:
-	.quad	0x00  # place holder for cr0
-.Lwaitsclp:
-	.quad	0x0102000180000000,.Lsclph
-.Lrcp:
-	.int	0x00120001 # Read SCP forced code
-.Lrcp2:
-	.int	0x00020001 # Read SCP code
-.Lonemb:
-	.int	0x100000
-
-.Lfchunk:
-
-#
-# find memory chunks.
-#
-	lgr	%r9,%r3			# end of mem
-	larl	%r1,.Lchkmem		# set program check address
-	stg	%r1,__LC_PGM_NEW_PSW+8
-	la	%r1,1			# test in increments of 128KB
-	sllg	%r1,%r1,17
-	larl	%r3,memory_chunk
-	slgr	%r4,%r4 		# set start of chunk to zero
-	slgr	%r5,%r5 		# set end of chunk to zero
-	slr	%r6,%r6			# set access code to zero
-	la	%r10,MEMORY_CHUNKS	# number of chunks
-.Lloop:
-	tprot	0(%r5),0		# test protection of first byte
-	ipm	%r7
-	srl	%r7,28
-	clr	%r6,%r7			# compare cc with last access code
-	je	.Lsame
-	j	.Lchkmem
-.Lsame:
-	algr	%r5,%r1			# add 128KB to end of chunk
-					# no need to check here,
-	brc	12,.Lloop		# this is the same chunk
-.Lchkmem:				# > 16EB or tprot got a program check
-	clgr	%r4,%r5			# chunk size > 0?
-	je	.Lchkloop
-	stg	%r4,0(%r3)		# store start address of chunk
-	lgr	%r0,%r5
-	slgr	%r0,%r4
-	stg	%r0,8(%r3)		# store size of chunk
-	st	%r6,20(%r3)		# store type of chunk
-	la	%r3,24(%r3)
-	ahi	%r10,-1			# update chunk number
-.Lchkloop:
-	lr	%r6,%r7			# set access code to last cc
-	# we got an exception or we're starting a new
-	# chunk , we must check if we should
-	# still try to find valid memory (if we detected
-	# the amount of available storage), and if we
-	# have chunks left
-	lghi	%r4,1
-	sllg	%r4,%r4,31
-	clgr	%r5,%r4
-	je	.Lhsaskip
-	xr	%r0, %r0
-	clgr	%r0, %r9		# did we detect memory?
-	je	.Ldonemem		# if not, leave
-	chi	%r10, 0			# do we have chunks left?
-	je	.Ldonemem
-.Lhsaskip:
-	algr	%r5,%r1			# add 128KB to end of chunk
-	lgr	%r4,%r5			# potential new chunk
-	clgr	%r5,%r9			# should we go on?
-	jl	.Lloop
-.Ldonemem:
-
 	larl	%r12,machine_flags
 #
-# find out if we are running under VM
-#
-	stidp	__LC_CPUID		# store cpuid
-	tm	__LC_CPUID,0xff 	# running under VM ?
-	bno	0f-.LPG1(%r13)
-	oi	7(%r12),1		# set VM flag
-0:	lh	%r0,__LC_CPUID+4	# get cpu version
-	chi	%r0,0x7490		# running on a P/390 ?
-	bne	1f-.LPG1(%r13)
-	oi	7(%r12),4		# set P/390 flag
-1:
-
-#
 # find out if we have the MVPG instruction
 #
 	la	%r1,0f-.LPG1(%r13)	# set program check address
@@ -326,25 +168,6 @@
 	.word 0
 
 	.org	0x12000
-.globl s390_readinfo_sccb
-s390_readinfo_sccb:
-.Lsccb:
-	.hword	0x1000			# length, one page
-	.byte	0x00,0x00,0x00
-	.byte	0x80			# variable response bit set
-.Lsccbr:
-	.hword	0x00			# response code
-.Lscpincr1:
-	.hword	0x00
-.Lscpa1:
-	.byte	0x00
-	.fill	89,1,0
-.Lscpa2:
-	.int	0x00
-.Lscpincr2:
-	.quad	0x00
-	.fill	3984,1,0
-	.org	0x13000
 
 #ifdef CONFIG_SHARED_KERNEL
 	.org	0x100000
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 9e9972e..0522595 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -20,26 +20,27 @@
 #include <asm/cio.h>
 #include <asm/ebcdic.h>
 #include <asm/reset.h>
+#include <asm/sclp.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
-#define LOADPARM_LEN 8
 
-extern char s390_readinfo_sccb[];
-#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010)
-#define SCCB_LOADPARM (&s390_readinfo_sccb[24])
-#define SCCB_FLAG (s390_readinfo_sccb[91])
+#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
+#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
+#define SCCB_FLAG (s390_readinfo_sccb.flags)
 
 enum ipl_type {
 	IPL_TYPE_NONE	 = 1,
 	IPL_TYPE_UNKNOWN = 2,
 	IPL_TYPE_CCW	 = 4,
 	IPL_TYPE_FCP	 = 8,
+	IPL_TYPE_NSS	 = 16,
 };
 
 #define IPL_NONE_STR	 "none"
 #define IPL_UNKNOWN_STR  "unknown"
 #define IPL_CCW_STR	 "ccw"
 #define IPL_FCP_STR	 "fcp"
+#define IPL_NSS_STR	 "nss"
 
 static char *ipl_type_str(enum ipl_type type)
 {
@@ -50,6 +51,8 @@
 		return IPL_CCW_STR;
 	case IPL_TYPE_FCP:
 		return IPL_FCP_STR;
+	case IPL_TYPE_NSS:
+		return IPL_NSS_STR;
 	case IPL_TYPE_UNKNOWN:
 	default:
 		return IPL_UNKNOWN_STR;
@@ -64,6 +67,7 @@
 	IPL_METHOD_FCP_RO_DIAG,
 	IPL_METHOD_FCP_RW_DIAG,
 	IPL_METHOD_FCP_RO_VM,
+	IPL_METHOD_NSS,
 };
 
 enum shutdown_action {
@@ -114,11 +118,14 @@
 static int diag308_set_works = 0;
 
 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
+
 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
 static enum ipl_method reipl_method = IPL_METHOD_NONE;
 static struct ipl_parameter_block *reipl_block_fcp;
 static struct ipl_parameter_block *reipl_block_ccw;
 
+static char reipl_nss_name[NSS_NAME_SIZE + 1];
+
 static int dump_capabilities = IPL_TYPE_NONE;
 static enum ipl_type dump_type = IPL_TYPE_NONE;
 static enum ipl_method dump_method = IPL_METHOD_NONE;
@@ -173,6 +180,24 @@
 			sys_##_prefix##_##_name##_show,			\
 			sys_##_prefix##_##_name##_store);
 
+#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
+static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,	\
+		char *page)						\
+{									\
+	return sprintf(page, _fmt_out, _value);				\
+}									\
+static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+		const char *buf, size_t len)				\
+{									\
+	if (sscanf(buf, _fmt_in, _value) != 1)				\
+		return -EINVAL;						\
+	return len;							\
+}									\
+static struct subsys_attribute sys_##_prefix##_##_name##_attr =		\
+	__ATTR(_name,(S_IRUGO | S_IWUSR),				\
+			sys_##_prefix##_##_name##_show,			\
+			sys_##_prefix##_##_name##_store);
+
 static void make_attrs_ro(struct attribute **attrs)
 {
 	while (*attrs) {
@@ -189,6 +214,8 @@
 {
 	struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
 
+	if (ipl_flags & IPL_NSS_VALID)
+		return IPL_TYPE_NSS;
 	if (!(ipl_flags & IPL_DEVNO_VALID))
 		return IPL_TYPE_UNKNOWN;
 	if (!(ipl_flags & IPL_PARMBLOCK_VALID))
@@ -324,6 +351,20 @@
 	.attrs = ipl_ccw_attrs,
 };
 
+/* NSS ipl device attributes */
+
+DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
+
+static struct attribute *ipl_nss_attrs[] = {
+	&sys_ipl_type_attr.attr,
+	&sys_ipl_nss_name_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ipl_nss_attr_group = {
+	.attrs = ipl_nss_attrs,
+};
+
 /* UNKNOWN ipl device attributes */
 
 static struct attribute *ipl_unknown_attrs[] = {
@@ -432,6 +473,21 @@
 	.attrs = reipl_ccw_attrs,
 };
 
+
+/* NSS reipl device attributes */
+
+DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
+
+static struct attribute *reipl_nss_attrs[] = {
+	&sys_reipl_nss_name_attr.attr,
+	NULL,
+};
+
+static struct attribute_group reipl_nss_attr_group = {
+	.name  = IPL_NSS_STR,
+	.attrs = reipl_nss_attrs,
+};
+
 /* reipl type */
 
 static int reipl_set_type(enum ipl_type type)
@@ -454,6 +510,9 @@
 		else
 			reipl_method = IPL_METHOD_FCP_RO_DIAG;
 		break;
+	case IPL_TYPE_NSS:
+		reipl_method = IPL_METHOD_NSS;
+		break;
 	default:
 		reipl_method = IPL_METHOD_NONE;
 	}
@@ -475,6 +534,8 @@
 		rc = reipl_set_type(IPL_TYPE_CCW);
 	else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
 		rc = reipl_set_type(IPL_TYPE_FCP);
+	else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
+		rc = reipl_set_type(IPL_TYPE_NSS);
 	return (rc != 0) ? rc : len;
 }
 
@@ -647,6 +708,10 @@
 	case IPL_METHOD_FCP_RO_VM:
 		__cpcmd("IPL", NULL, 0, NULL);
 		break;
+	case IPL_METHOD_NSS:
+		sprintf(buf, "IPL %s", reipl_nss_name);
+		__cpcmd(buf, NULL, 0, NULL);
+		break;
 	case IPL_METHOD_NONE:
 	default:
 		if (MACHINE_IS_VM)
@@ -733,6 +798,10 @@
 	case IPL_TYPE_FCP:
 		rc = ipl_register_fcp_files();
 		break;
+	case IPL_TYPE_NSS:
+		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+					&ipl_nss_attr_group);
+		break;
 	default:
 		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
 					&ipl_unknown_attr_group);
@@ -755,6 +824,20 @@
 	free_page((unsigned long)buffer);
 }
 
+static int __init reipl_nss_init(void)
+{
+	int rc;
+
+	if (!MACHINE_IS_VM)
+		return 0;
+	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group);
+	if (rc)
+		return rc;
+	strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
+	reipl_capabilities |= IPL_TYPE_NSS;
+	return 0;
+}
+
 static int __init reipl_ccw_init(void)
 {
 	int rc;
@@ -837,6 +920,9 @@
 	rc = reipl_fcp_init();
 	if (rc)
 		return rc;
+	rc = reipl_nss_init();
+	if (rc)
+		return rc;
 	rc = reipl_set_type(ipl_get_type());
 	if (rc)
 		return rc;
@@ -993,8 +1079,6 @@
 		reset->fn();
 }
 
-extern void reset_mcck_handler(void);
-extern void reset_pgm_handler(void);
 extern __u32 dump_prefix_page;
 
 void s390_reset_system(void)
@@ -1016,14 +1100,14 @@
 	__ctl_clear_bit(0,28);
 
 	/* Set new machine check handler */
-	S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
+	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
 	S390_lowcore.mcck_new_psw.addr =
-		PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
+		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
 
 	/* Set new program check handler */
-	S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
 	S390_lowcore.program_new_psw.addr =
-		PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler;
+		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
 	do_reset_calls();
 }
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 1eef509..8f0cbca 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -1,9 +1,9 @@
 /*
  *  arch/s390/kernel/irq.c
  *
- *  S390 version
- *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2004,2007
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *		 Thomas Spatzier (tspat@de.ibm.com)
  *
  * This file contains interrupt related functions.
  */
@@ -14,6 +14,8 @@
 #include <linux/interrupt.h>
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
+#include <linux/proc_fs.h>
+#include <linux/profile.h>
 
 /*
  * show_interrupts is needed by /proc/interrupts.
@@ -93,5 +95,12 @@
 
 	local_irq_restore(flags);
 }
-
 EXPORT_SYMBOL(do_softirq);
+
+void init_irq_proc(void)
+{
+	struct proc_dir_entry *root_irq_dir;
+
+	root_irq_dir = proc_mkdir("irq", NULL);
+	create_prof_cpu_mask(root_irq_dir);
+}
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 576368c..a466bab 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -155,15 +155,34 @@
 static int __kprobes swap_instruction(void *aref)
 {
 	struct ins_replace_args *args = aref;
+	u32 *addr;
+	u32 instr;
 	int err = -EFAULT;
 
+	/*
+	 * Text segment is read-only, hence we use stura to bypass dynamic
+	 * address translation to exchange the instruction. Since stura
+	 * always operates on four bytes, but we only want to exchange two
+	 * bytes do some calculations to get things right. In addition we
+	 * shall not cross any page boundaries (vmalloc area!) when writing
+	 * the new instruction.
+	 */
+	addr = (u32 *)ALIGN((unsigned long)args->ptr, 4);
+	if ((unsigned long)args->ptr & 2)
+		instr = ((*addr) & 0xffff0000) | args->new;
+	else
+		instr = ((*addr) & 0x0000ffff) | args->new << 16;
+
 	asm volatile(
-		"0: mvc  0(2,%2),0(%3)\n"
-		"1: la   %0,0\n"
+		"	lra	%1,0(%1)\n"
+		"0:	stura	%2,%1\n"
+		"1:	la	%0,0\n"
 		"2:\n"
 		EX_TABLE(0b,2b)
-		: "+d" (err), "=m" (*args->ptr)
-		: "a" (args->ptr), "a" (&args->new), "m" (args->new));
+		: "+d" (err)
+		: "a" (addr), "d" (instr)
+		: "memory", "cc");
+
 	return err;
 }
 
@@ -356,7 +375,7 @@
  *	- When the probed function returns, this probe
  *		causes the handlers to fire
  */
-void __kprobes kretprobe_trampoline_holder(void)
+void kretprobe_trampoline_holder(void)
 {
 	asm volatile(".global kretprobe_trampoline\n"
 		     "kretprobe_trampoline: bcr 0,0\n");
@@ -365,7 +384,8 @@
 /*
  * Called when the probe at kretprobe trampoline is hit
  */
-int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes trampoline_probe_handler(struct kprobe *p,
+					      struct pt_regs *regs)
 {
 	struct kretprobe_instance *ri = NULL;
 	struct hlist_head *head, empty_rp;
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index f6d9bcc..52f57af 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/kexec.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index d989ed4..39d1dd7 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -30,6 +30,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/moduleloader.h>
 
 #if 0
 #define DEBUGP printk
@@ -58,7 +59,7 @@
            table entries. */
 }
 
-static inline void
+static void
 check_rela(Elf_Rela *rela, struct module *me)
 {
 	struct mod_arch_syminfo *info;
@@ -181,7 +182,7 @@
 	return -ENOEXEC;
 }
 
-static inline int
+static int
 apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, 
 	   struct module *me)
 {
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 6603fbb..5acfac6 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -144,7 +144,7 @@
 
 	trace_hardirqs_on();
 	/* Wait for external, I/O or machine check interrupt. */
-	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT |
+	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
 			PSW_MASK_IO | PSW_MASK_EXT);
 }
 
@@ -190,7 +190,7 @@
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
+	regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
 	regs.gprs[9] = (unsigned long) fn;
 	regs.gprs[10] = (unsigned long) arg;
diff --git a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c
deleted file mode 100644
index b81aa1f..0000000
--- a/arch/s390/kernel/profile.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/s390/kernel/profile.c
- *
- * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@de.ibm.com)
- *
- */
-#include <linux/proc_fs.h>
-#include <linux/profile.h>
-
-static struct proc_dir_entry * root_irq_dir;
-
-void init_irq_proc(void)
-{
-	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", NULL);
-
-	/* create /proc/irq/prof_cpu_mask */
-	create_prof_cpu_mask(root_irq_dir);
-}
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 8f36504..2a8f087 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -86,15 +86,13 @@
 		per_info->control_regs.bits.storage_alt_space_ctl = 0;
 }
 
-void
-set_single_step(struct task_struct *task)
+static void set_single_step(struct task_struct *task)
 {
 	task->thread.per_info.single_step = 1;
 	FixPerRegisters(task);
 }
 
-void
-clear_single_step(struct task_struct *task)
+static void clear_single_step(struct task_struct *task)
 {
 	task->thread.per_info.single_step = 0;
 	FixPerRegisters(task);
@@ -232,9 +230,9 @@
 		 */
 		if (addr == (addr_t) &dummy->regs.psw.mask &&
 #ifdef CONFIG_COMPAT
-		    data != PSW_MASK_MERGE(PSW_USER32_BITS, data) &&
+		    data != PSW_MASK_MERGE(psw_user32_bits, data) &&
 #endif
-		    data != PSW_MASK_MERGE(PSW_USER_BITS, data))
+		    data != PSW_MASK_MERGE(psw_user_bits, data))
 			/* Invalid psw mask. */
 			return -EINVAL;
 #ifndef CONFIG_64BIT
@@ -309,7 +307,7 @@
 		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
 		if (copied != sizeof(tmp))
 			return -EIO;
-		return put_user(tmp, (unsigned long __user *) data);
+		return put_user(tmp, (unsigned long __force __user *) data);
 
 	case PTRACE_PEEKUSR:
 		/* read the word at location addr in the USER area. */
@@ -331,7 +329,7 @@
 
 	case PTRACE_PEEKUSR_AREA:
 	case PTRACE_POKEUSR_AREA:
-		if (copy_from_user(&parea, (void __user *) addr,
+		if (copy_from_user(&parea, (void __force __user *) addr,
 							sizeof(parea)))
 			return -EFAULT;
 		addr = parea.kernel_addr;
@@ -341,10 +339,11 @@
 			if (request == PTRACE_PEEKUSR_AREA)
 				ret = peek_user(child, addr, data);
 			else {
-				addr_t tmp;
-				if (get_user (tmp, (addr_t __user *) data))
+				addr_t utmp;
+				if (get_user(utmp,
+					     (addr_t __force __user *) data))
 					return -EFAULT;
-				ret = poke_user(child, addr, tmp);
+				ret = poke_user(child, addr, utmp);
 			}
 			if (ret)
 				return ret;
@@ -394,7 +393,7 @@
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Fake a 31 bit psw mask. */
 			tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
-			tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp);
+			tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp);
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Fake a 31 bit psw address. */
 			tmp = (__u32) task_pt_regs(child)->psw.addr |
@@ -469,11 +468,11 @@
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Build a 64 bit psw mask from 31 bit mask. */
-			if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp))
+			if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp))
 				/* Invalid psw mask. */
 				return -EINVAL;
 			task_pt_regs(child)->psw.mask =
-				PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32);
+				PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32);
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Build a 64 bit psw address from 31 bit address. */
 			task_pt_regs(child)->psw.addr =
@@ -550,7 +549,7 @@
 		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
 		if (copied != sizeof(tmp))
 			return -EIO;
-		return put_user(tmp, (unsigned int __user *) data);
+		return put_user(tmp, (unsigned int __force __user *) data);
 
 	case PTRACE_PEEKUSR:
 		/* read the word at location addr in the USER area. */
@@ -571,7 +570,7 @@
 
 	case PTRACE_PEEKUSR_AREA:
 	case PTRACE_POKEUSR_AREA:
-		if (copy_from_user(&parea, (void __user *) addr,
+		if (copy_from_user(&parea, (void __force __user *) addr,
 							sizeof(parea)))
 			return -EFAULT;
 		addr = parea.kernel_addr;
@@ -581,10 +580,11 @@
 			if (request == PTRACE_PEEKUSR_AREA)
 				ret = peek_user_emu31(child, addr, data);
 			else {
-				__u32 tmp;
-				if (get_user (tmp, (__u32 __user *) data))
+				__u32 utmp;
+				if (get_user(utmp,
+					     (__u32 __force __user *) data))
 					return -EFAULT;
-				ret = poke_user_emu31(child, addr, tmp);
+				ret = poke_user_emu31(child, addr, utmp);
 			}
 			if (ret)
 				return ret;
@@ -595,17 +595,19 @@
 		return 0;
 	case PTRACE_GETEVENTMSG:
 		return put_user((__u32) child->ptrace_message,
-				(unsigned int __user *) data);
+				(unsigned int __force __user *) data);
 	case PTRACE_GETSIGINFO:
 		if (child->last_siginfo == NULL)
 			return -EINVAL;
-		return copy_siginfo_to_user32((compat_siginfo_t __user *) data,
+		return copy_siginfo_to_user32((compat_siginfo_t
+					       __force __user *) data,
 					      child->last_siginfo);
 	case PTRACE_SETSIGINFO:
 		if (child->last_siginfo == NULL)
 			return -EINVAL;
 		return copy_siginfo_from_user32(child->last_siginfo,
-						(compat_siginfo_t __user *) data);
+						(compat_siginfo_t
+						 __force __user *) data);
 	}
 	return ptrace_request(child, request, addr, data);
 }
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
deleted file mode 100644
index 8a87355..0000000
--- a/arch/s390/kernel/reset.S
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *  arch/s390/kernel/reset.S
- *
- *    Copyright (C) IBM Corp. 2006
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- *		 Michael Holzheu <holzheu@de.ibm.com>
- */
-
-#include <asm/ptrace.h>
-#include <asm/lowcore.h>
-
-#ifdef CONFIG_64BIT
-
-	.globl	reset_mcck_handler
-reset_mcck_handler:
-	basr	%r13,0
-0:	lg	%r15,__LC_PANIC_STACK	# load panic stack
-	aghi	%r15,-STACK_FRAME_OVERHEAD
-	lg	%r1,s390_reset_mcck_handler-0b(%r13)
-	ltgr	%r1,%r1
-	jz	1f
-	basr	%r14,%r1
-1:	la	%r1,4095
-	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
-	lpswe	__LC_MCK_OLD_PSW
-
-	.globl	s390_reset_mcck_handler
-s390_reset_mcck_handler:
-	.quad	0
-
-	.globl	reset_pgm_handler
-reset_pgm_handler:
-	stmg	%r0,%r15,__LC_SAVE_AREA
-	basr	%r13,0
-0:	lg	%r15,__LC_PANIC_STACK	# load panic stack
-	aghi	%r15,-STACK_FRAME_OVERHEAD
-	lg	%r1,s390_reset_pgm_handler-0b(%r13)
-	ltgr	%r1,%r1
-	jz	1f
-	basr	%r14,%r1
-	lmg	%r0,%r15,__LC_SAVE_AREA
-	lpswe	__LC_PGM_OLD_PSW
-1:	lpswe	disabled_wait_psw-0b(%r13)
-	.globl s390_reset_pgm_handler
-s390_reset_pgm_handler:
-	.quad	0
-	.align	8
-disabled_wait_psw:
-	.quad	0x0002000180000000,0x0000000000000000 + reset_pgm_handler
-
-#else /* CONFIG_64BIT */
-
-	.globl	reset_mcck_handler
-reset_mcck_handler:
-	basr	%r13,0
-0:	l	%r15,__LC_PANIC_STACK	# load panic stack
-	ahi	%r15,-STACK_FRAME_OVERHEAD
-	l	%r1,s390_reset_mcck_handler-0b(%r13)
-	ltr	%r1,%r1
-	jz	1f
-	basr	%r14,%r1
-1:	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA
-	lpsw	__LC_MCK_OLD_PSW
-
-	.globl	s390_reset_mcck_handler
-s390_reset_mcck_handler:
-	.long	0
-
-	.globl	reset_pgm_handler
-reset_pgm_handler:
-	stm	%r0,%r15,__LC_SAVE_AREA
-	basr	%r13,0
-0:	l	%r15,__LC_PANIC_STACK	# load panic stack
-	ahi	%r15,-STACK_FRAME_OVERHEAD
-	l	%r1,s390_reset_pgm_handler-0b(%r13)
-	ltr	%r1,%r1
-	jz	1f
-	basr	%r14,%r1
-	lm	%r0,%r15,__LC_SAVE_AREA
-	lpsw	__LC_PGM_OLD_PSW
-
-1:	lpsw	disabled_wait_psw-0b(%r13)
-	.globl	s390_reset_pgm_handler
-s390_reset_pgm_handler:
-	.long	0
-disabled_wait_psw:
-	.align 8
-	.long	0x000a0000,0x00000000 + reset_pgm_handler
-
-#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index bc5beaa..acf93db 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -125,14 +125,12 @@
 		 * Make sure that the i/o interrupt did not "overtake"
 		 * the last HZ timer interrupt.
 		 */
-		account_ticks();
+		account_ticks(S390_lowcore.int_clock);
 	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
         index = ext_hash(code);
 	for (p = ext_int_hash[index]; p; p = p->next) {
-		if (likely(p->code == code)) {
-			if (likely(p->handler))
-				p->handler(code);
-		}
+		if (likely(p->code == code))
+			p->handler(code);
 	}
 	irq_exit();
 	set_irq_regs(old_regs);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 49ef206..0373981 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -38,6 +38,8 @@
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/pfn.h>
+#include <linux/ctype.h>
+#include <linux/reboot.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -49,6 +51,14 @@
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
+#include <asm/ebcdic.h>
+#include <asm/compat.h>
+
+long psw_kernel_bits	= (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
+			   PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
+long psw_user_bits	= (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+			   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+			   PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
 
 /*
  * User copy operations.
@@ -117,9 +127,9 @@
  */
 char vmhalt_cmd[128] = "";
 char vmpoff_cmd[128] = "";
-char vmpanic_cmd[128] = "";
+static char vmpanic_cmd[128] = "";
 
-static inline void strncpy_skip_quote(char *dst, char *src, int n)
+static void strncpy_skip_quote(char *dst, char *src, int n)
 {
         int sx, dx;
 
@@ -275,10 +285,6 @@
 }
 
 #ifdef CONFIG_SMP
-extern void machine_restart_smp(char *);
-extern void machine_halt_smp(void);
-extern void machine_power_off_smp(void);
-
 void (*_machine_restart)(char *command) = machine_restart_smp;
 void (*_machine_halt)(void) = machine_halt_smp;
 void (*_machine_power_off)(void) = machine_power_off_smp;
@@ -386,6 +392,84 @@
 }
 early_param("ipldelay", early_parse_ipldelay);
 
+#ifdef CONFIG_S390_SWITCH_AMODE
+unsigned int switch_amode = 0;
+EXPORT_SYMBOL_GPL(switch_amode);
+
+static void set_amode_and_uaccess(unsigned long user_amode,
+				  unsigned long user32_amode)
+{
+	psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode |
+			PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+			PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+#ifdef CONFIG_COMPAT
+	psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode |
+			  PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+			  PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+	psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
+			  PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
+			  PSW32_MASK_PSTATE;
+#endif
+	psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+			  PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
+
+	if (MACHINE_HAS_MVCOS) {
+		printk("mvcos available.\n");
+		memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
+	} else {
+		printk("mvcos not available.\n");
+		memcpy(&uaccess, &uaccess_pt, sizeof(uaccess));
+	}
+}
+
+/*
+ * Switch kernel/user addressing modes?
+ */
+static int __init early_parse_switch_amode(char *p)
+{
+	switch_amode = 1;
+	return 0;
+}
+early_param("switch_amode", early_parse_switch_amode);
+
+#else /* CONFIG_S390_SWITCH_AMODE */
+static inline void set_amode_and_uaccess(unsigned long user_amode,
+					 unsigned long user32_amode)
+{
+}
+#endif /* CONFIG_S390_SWITCH_AMODE */
+
+#ifdef CONFIG_S390_EXEC_PROTECT
+unsigned int s390_noexec = 0;
+EXPORT_SYMBOL_GPL(s390_noexec);
+
+/*
+ * Enable execute protection?
+ */
+static int __init early_parse_noexec(char *p)
+{
+	if (!strncmp(p, "off", 3))
+		return 0;
+	switch_amode = 1;
+	s390_noexec = 1;
+	return 0;
+}
+early_param("noexec", early_parse_noexec);
+#endif /* CONFIG_S390_EXEC_PROTECT */
+
+static void setup_addressing_mode(void)
+{
+	if (s390_noexec) {
+		printk("S390 execute protection active, ");
+		set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY);
+		return;
+	}
+	if (switch_amode) {
+		printk("S390 address spaces switched, ");
+		set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY);
+	}
+}
+
 static void __init
 setup_lowcore(void)
 {
@@ -402,19 +486,21 @@
 	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
 	lc->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
-	lc->external_new_psw.mask = PSW_KERNEL_BITS;
+	if (switch_amode)
+		lc->restart_psw.mask |= PSW_ASC_HOME;
+	lc->external_new_psw.mask = psw_kernel_bits;
 	lc->external_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
-	lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
+	lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
 	lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
-	lc->program_new_psw.mask = PSW_KERNEL_BITS;
+	lc->program_new_psw.mask = psw_kernel_bits;
 	lc->program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
 	lc->mcck_new_psw.mask =
-		PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
+		psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
 	lc->mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
-	lc->io_new_psw.mask = PSW_KERNEL_BITS;
+	lc->io_new_psw.mask = psw_kernel_bits;
 	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
 	lc->ipl_device = S390_lowcore.ipl_device;
 	lc->jiffy_timer = -1LL;
@@ -439,7 +525,7 @@
 static void __init
 setup_resources(void)
 {
-	struct resource *res;
+	struct resource *res, *sub_res;
 	int i;
 
 	code_resource.start = (unsigned long) &_text;
@@ -464,8 +550,38 @@
 		res->start = memory_chunk[i].addr;
 		res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
 		request_resource(&iomem_resource, res);
-		request_resource(res, &code_resource);
-		request_resource(res, &data_resource);
+
+		if (code_resource.start >= res->start  &&
+			code_resource.start <= res->end &&
+			code_resource.end > res->end) {
+			sub_res = alloc_bootmem_low(sizeof(struct resource));
+			memcpy(sub_res, &code_resource,
+				sizeof(struct resource));
+			sub_res->end = res->end;
+			code_resource.start = res->end + 1;
+			request_resource(res, sub_res);
+		}
+
+		if (code_resource.start >= res->start &&
+			code_resource.start <= res->end &&
+			code_resource.end <= res->end)
+			request_resource(res, &code_resource);
+
+		if (data_resource.start >= res->start &&
+			data_resource.start <= res->end &&
+			data_resource.end > res->end) {
+			sub_res = alloc_bootmem_low(sizeof(struct resource));
+			memcpy(sub_res, &data_resource,
+				sizeof(struct resource));
+			sub_res->end = res->end;
+			data_resource.start = res->end + 1;
+			request_resource(res, sub_res);
+		}
+
+		if (data_resource.start >= res->start &&
+			data_resource.start <= res->end &&
+			data_resource.end <= res->end)
+			request_resource(res, &data_resource);
 	}
 }
 
@@ -476,7 +592,7 @@
 	int i;
 
 	memory_size = real_size = 0;
-	max_phys = VMALLOC_END - VMALLOC_MIN_SIZE;
+	max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE;
 	memory_end &= PAGE_MASK;
 
 	max_mem = memory_end ? min(max_phys, memory_end) : max_phys;
@@ -495,16 +611,13 @@
 	}
 	if (!memory_end)
 		memory_end = memory_size;
-	if (real_size > memory_end)
-		printk("More memory detected than supported. Unused: %luk\n",
-		       (real_size - memory_end) >> 10);
 }
 
 static void __init
 setup_memory(void)
 {
         unsigned long bootmap_size;
-	unsigned long start_pfn, end_pfn, init_pfn;
+	unsigned long start_pfn, end_pfn;
 	int i;
 
 	/*
@@ -514,10 +627,6 @@
 	start_pfn = PFN_UP(__pa(&_end));
 	end_pfn = max_pfn = PFN_DOWN(memory_end);
 
-	/* Initialize storage key for kernel pages */
-	for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
-		page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
-
 #ifdef CONFIG_BLK_DEV_INITRD
 	/*
 	 * Move the initrd in case the bitmap of the bootmem allocater
@@ -651,6 +760,7 @@
 	parse_early_param();
 
 	setup_memory_end();
+	setup_addressing_mode();
 	setup_memory();
 	setup_resources();
 	setup_lowcore();
@@ -694,6 +804,7 @@
         struct cpuinfo_S390 *cpuinfo;
 	unsigned long n = (unsigned long) v - 1;
 
+	s390_adjust_jiffies();
 	preempt_disable();
 	if (!n) {
 		seq_printf(m, "vendor_id       : IBM/S390\n"
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 4c8a795..554f9cf 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -119,7 +119,7 @@
 
 	/* Copy a 'clean' PSW mask to the user to avoid leaking
 	   information about whether PER is currently on.  */
-	user_sregs.regs.psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask);
+	user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask);
 	user_sregs.regs.psw.addr = regs->psw.addr;
 	memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
 	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 19090f7..65b5232 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -22,23 +22,23 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
-
 #include <linux/delay.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
-
+#include <linux/timex.h>
+#include <asm/setup.h>
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
 #include <asm/irq.h>
 #include <asm/s390_ext.h>
 #include <asm/cpcmd.h>
 #include <asm/tlbflush.h>
+#include <asm/timer.h>
 
 extern volatile int __cpu_logical_map[];
 
@@ -53,12 +53,6 @@
 
 static struct task_struct *current_set[NR_CPUS];
 
-/*
- * Reboot, halt and power_off routines for SMP.
- */
-extern char vmhalt_cmd[];
-extern char vmpoff_cmd[];
-
 static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
 
@@ -200,7 +194,7 @@
 }
 EXPORT_SYMBOL(smp_call_function_on);
 
-static inline void do_send_stop(void)
+static void do_send_stop(void)
 {
         int cpu, rc;
 
@@ -214,7 +208,7 @@
 	}
 }
 
-static inline void do_store_status(void)
+static void do_store_status(void)
 {
         int cpu, rc;
 
@@ -230,7 +224,7 @@
         }
 }
 
-static inline void do_wait_for_stop(void)
+static void do_wait_for_stop(void)
 {
 	int cpu;
 
@@ -250,7 +244,7 @@
 void smp_send_stop(void)
 {
 	/* Disable all interrupts/machine checks */
-	__load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
+	__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
 
         /* write magic number to zero page (absolute 0) */
 	lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
@@ -298,7 +292,7 @@
  * cpus are handled.
  */
 
-void do_ext_call_interrupt(__u16 code)
+static void do_ext_call_interrupt(__u16 code)
 {
         unsigned long bits;
 
@@ -385,7 +379,7 @@
 /*
  * callback for setting/clearing control bits
  */
-void smp_ctl_bit_callback(void *info) {
+static void smp_ctl_bit_callback(void *info) {
 	struct ec_creg_mask_parms *pp = info;
 	unsigned long cregs[16];
 	int i;
@@ -458,17 +452,15 @@
 /*
  *      Activate a secondary processor.
  */
-extern void init_cpu_timer(void);
-extern void init_cpu_vtimer(void);
-
 int __devinit start_secondary(void *cpuvoid)
 {
         /* Setup the cpu */
         cpu_init();
 	preempt_disable();
-        /* init per CPU timer */
+	/* Enable TOD clock interrupts on the secondary cpu. */
         init_cpu_timer();
 #ifdef CONFIG_VIRT_TIMER
+	/* Enable cpu timer interrupts on the secondary cpu. */
         init_cpu_vtimer();
 #endif
 	/* Enable pfault pseudo page faults on this cpu. */
@@ -542,7 +534,7 @@
 	spin_unlock_irqrestore(&smp_reserve_lock, flags);
 }
 
-static inline int
+static int
 cpu_stopped(int cpu)
 {
 	__u32 status;
@@ -794,7 +786,10 @@
 	int ret;
 
 	for_each_possible_cpu(cpu) {
-		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu);
+		struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+		c->hotpluggable = 1;
+		ret = register_cpu(c, cpu);
 		if (ret)
 			printk(KERN_WARNING "topology_init: register_cpu %d "
 			       "failed (%d)\n", cpu, ret);
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 0d14a47..2e5c65a 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -11,11 +11,11 @@
 #include <linux/stacktrace.h>
 #include <linux/kallsyms.h>
 
-static inline unsigned long save_context_stack(struct stack_trace *trace,
-					       unsigned int *skip,
-					       unsigned long sp,
-					       unsigned long low,
-					       unsigned long high)
+static unsigned long save_context_stack(struct stack_trace *trace,
+					unsigned int *skip,
+					unsigned long sp,
+					unsigned long low,
+					unsigned long high)
 {
 	struct stack_frame *sf;
 	struct pt_regs *regs;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 6cceed4..3b91f27 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -37,11 +37,15 @@
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/timer.h>
+#include <asm/etr.h>
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
 #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
 
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
 /*
  * Create a small time difference between the timer interrupts
  * on the different cpus to avoid lock contention.
@@ -51,6 +55,7 @@
 #define TICK_SIZE tick
 
 static ext_int_info_t ext_int_info_cc;
+static ext_int_info_t ext_int_etr_cc;
 static u64 init_timer_cc;
 static u64 jiffies_timer_cc;
 static u64 xtime_cc;
@@ -89,29 +94,21 @@
 #define s390_do_profile()	do { ; } while(0)
 #endif /* CONFIG_PROFILING */
 
-
 /*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * Advance the per cpu tick counter up to the time given with the
+ * "time" argument. The per cpu update consists of accounting
+ * the virtual cpu time, calling update_process_times and calling
+ * the profiling hook. If xtime is before time it is advanced as well.
  */
-void account_ticks(void)
+void account_ticks(u64 time)
 {
-	__u64 tmp;
 	__u32 ticks;
+	__u64 tmp;
 
 	/* Calculate how many ticks have passed. */
-	if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
-		/*
-		 * We have to program the clock comparator even if
-		 * no tick has passed. That happens if e.g. an i/o
-		 * interrupt wakes up an idle processor that has
-		 * switched off its hz timer.
-		 */
-		tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
-		asm volatile ("SCKC %0" : : "m" (tmp));
+	if (time < S390_lowcore.jiffy_timer)
 		return;
-	}
-	tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
+	tmp = time - S390_lowcore.jiffy_timer;
 	if (tmp >= 2*CLK_TICKS_PER_JIFFY) {  /* more than two ticks ? */
 		ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
 		S390_lowcore.jiffy_timer +=
@@ -124,10 +121,6 @@
 		S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
 	}
 
-	/* set clock comparator for next tick */
-	tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
-        asm volatile ("SCKC %0" : : "m" (tmp));
-
 #ifdef CONFIG_SMP
 	/*
 	 * Do not rely on the boot cpu to do the calls to do_timer.
@@ -173,7 +166,7 @@
  * Stop the HZ tick on the current CPU.
  * Only cpu_idle may call this function.
  */
-static inline void stop_hz_timer(void)
+static void stop_hz_timer(void)
 {
 	unsigned long flags;
 	unsigned long seq, next;
@@ -210,20 +203,21 @@
 		if (timer >= jiffies_timer_cc)
 			todval = timer;
 	}
-	asm volatile ("SCKC %0" : : "m" (todval));
+	set_clock_comparator(todval);
 }
 
 /*
  * Start the HZ tick on the current CPU.
  * Only cpu_idle may call this function.
  */
-static inline void start_hz_timer(void)
+static void start_hz_timer(void)
 {
 	BUG_ON(!in_interrupt());
 
 	if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
 		return;
-	account_ticks();
+	account_ticks(get_clock());
+	set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
 	cpu_clear(smp_processor_id(), nohz_cpu_mask);
 }
 
@@ -245,7 +239,7 @@
 	.notifier_call = nohz_idle_notify,
 };
 
-void __init nohz_init(void)
+static void __init nohz_init(void)
 {
 	if (register_idle_notifier(&nohz_idle_nb))
 		panic("Couldn't register idle notifier");
@@ -254,24 +248,57 @@
 #endif
 
 /*
- * Start the clock comparator on the current CPU.
+ * Set up per cpu jiffy timer and set the clock comparator.
+ */
+static void setup_jiffy_timer(void)
+{
+	/* Set up clock comparator to next jiffy. */
+	S390_lowcore.jiffy_timer =
+		jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY;
+	set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+}
+
+/*
+ * Set up lowcore and control register of the current cpu to
+ * enable TOD clock and clock comparator interrupts.
  */
 void init_cpu_timer(void)
 {
-	unsigned long cr0;
-	__u64 timer;
+	setup_jiffy_timer();
 
-	timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY;
-	S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY;
-	timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION;
-	asm volatile ("SCKC %0" : : "m" (timer));
-        /* allow clock comparator timer interrupt */
-	__ctl_store(cr0, 0, 0);
-        cr0 |= 0x800;
-	__ctl_load(cr0, 0, 0);
+	/* Enable clock comparator timer interrupt. */
+	__ctl_set_bit(0,11);
+
+	/* Always allow ETR external interrupts, even without an ETR. */
+	__ctl_set_bit(0, 4);
 }
 
-extern void vtime_init(void);
+static void clock_comparator_interrupt(__u16 code)
+{
+	/* set clock comparator for next tick */
+	set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+}
+
+static void etr_reset(void);
+static void etr_init(void);
+static void etr_ext_handler(__u16);
+
+/*
+ * Get the TOD clock running.
+ */
+static u64 __init reset_tod_clock(void)
+{
+	u64 time;
+
+	etr_reset();
+	if (store_clock(&time) == 0)
+		return time;
+	/* TOD clock not running. Set the clock to Unix Epoch. */
+	if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0)
+		panic("TOD clock not operational.");
+
+	return TOD_UNIX_EPOCH;
+}
 
 static cycle_t read_tod_clock(void)
 {
@@ -295,48 +322,31 @@
  */
 void __init time_init(void)
 {
-	__u64 set_time_cc;
-	int cc;
-
-        /* kick the TOD clock */
-	asm volatile(
-		"	stck	0(%2)\n"
-		"	ipm	%0\n"
-		"	srl	%0,28"
-		: "=d" (cc), "=m" (init_timer_cc)
-		: "a" (&init_timer_cc) : "cc");
-        switch (cc) {
-        case 0: /* clock in set state: all is fine */
-                break;
-        case 1: /* clock in non-set state: FIXME */
-                printk("time_init: TOD clock in non-set state\n");
-                break;
-        case 2: /* clock in error state: FIXME */
-                printk("time_init: TOD clock in error state\n");
-                break;
-        case 3: /* clock in stopped or not-operational state: FIXME */
-                printk("time_init: TOD clock stopped/non-operational\n");
-                break;
-        }
+	init_timer_cc = reset_tod_clock();
+	xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
 	jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
 
 	/* set xtime */
-	xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
-	set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
-		(0x3c26700LL*1000000*4096);
-        tod_to_timeval(set_time_cc, &xtime);
+	tod_to_timeval(init_timer_cc - TOD_UNIX_EPOCH, &xtime);
         set_normalized_timespec(&wall_to_monotonic,
                                 -xtime.tv_sec, -xtime.tv_nsec);
 
 	/* request the clock comparator external interrupt */
-	if (register_early_external_interrupt(0x1004, NULL,
+	if (register_early_external_interrupt(0x1004,
+					      clock_comparator_interrupt,
 					      &ext_int_info_cc) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
 	if (clocksource_register(&clocksource_tod) != 0)
 		panic("Could not register TOD clock source");
 
-        init_cpu_timer();
+	/* request the etr external interrupt */
+	if (register_early_external_interrupt(0x1406, etr_ext_handler,
+					      &ext_int_etr_cc) != 0)
+		panic("Couldn't request external interrupt 0x1406");
+
+	/* Enable TOD clock interrupts on the boot cpu. */
+	init_cpu_timer();
 
 #ifdef CONFIG_NO_IDLE_HZ
 	nohz_init();
@@ -345,5 +355,1048 @@
 #ifdef CONFIG_VIRT_TIMER
 	vtime_init();
 #endif
+	etr_init();
 }
 
+/*
+ * External Time Reference (ETR) code.
+ */
+static int etr_port0_online;
+static int etr_port1_online;
+
+static int __init early_parse_etr(char *p)
+{
+	if (strncmp(p, "off", 3) == 0)
+		etr_port0_online = etr_port1_online = 0;
+	else if (strncmp(p, "port0", 5) == 0)
+		etr_port0_online = 1;
+	else if (strncmp(p, "port1", 5) == 0)
+		etr_port1_online = 1;
+	else if (strncmp(p, "on", 2) == 0)
+		etr_port0_online = etr_port1_online = 1;
+	return 0;
+}
+early_param("etr", early_parse_etr);
+
+enum etr_event {
+	ETR_EVENT_PORT0_CHANGE,
+	ETR_EVENT_PORT1_CHANGE,
+	ETR_EVENT_PORT_ALERT,
+	ETR_EVENT_SYNC_CHECK,
+	ETR_EVENT_SWITCH_LOCAL,
+	ETR_EVENT_UPDATE,
+};
+
+enum etr_flags {
+	ETR_FLAG_ENOSYS,
+	ETR_FLAG_EACCES,
+	ETR_FLAG_STEAI,
+};
+
+/*
+ * Valid bit combinations of the eacr register are (x = don't care):
+ * e0 e1 dp p0 p1 ea es sl
+ *  0  0  x  0	0  0  0  0  initial, disabled state
+ *  0  0  x  0	1  1  0  0  port 1 online
+ *  0  0  x  1	0  1  0  0  port 0 online
+ *  0  0  x  1	1  1  0  0  both ports online
+ *  0  1  x  0	1  1  0  0  port 1 online and usable, ETR or PPS mode
+ *  0  1  x  0	1  1  0  1  port 1 online, usable and ETR mode
+ *  0  1  x  0	1  1  1  0  port 1 online, usable, PPS mode, in-sync
+ *  0  1  x  0	1  1  1  1  port 1 online, usable, ETR mode, in-sync
+ *  0  1  x  1	1  1  0  0  both ports online, port 1 usable
+ *  0  1  x  1	1  1  1  0  both ports online, port 1 usable, PPS mode, in-sync
+ *  0  1  x  1	1  1  1  1  both ports online, port 1 usable, ETR mode, in-sync
+ *  1  0  x  1	0  1  0  0  port 0 online and usable, ETR or PPS mode
+ *  1  0  x  1	0  1  0  1  port 0 online, usable and ETR mode
+ *  1  0  x  1	0  1  1  0  port 0 online, usable, PPS mode, in-sync
+ *  1  0  x  1	0  1  1  1  port 0 online, usable, ETR mode, in-sync
+ *  1  0  x  1	1  1  0  0  both ports online, port 0 usable
+ *  1  0  x  1	1  1  1  0  both ports online, port 0 usable, PPS mode, in-sync
+ *  1  0  x  1	1  1  1  1  both ports online, port 0 usable, ETR mode, in-sync
+ *  1  1  x  1	1  1  1  0  both ports online & usable, ETR, in-sync
+ *  1  1  x  1	1  1  1  1  both ports online & usable, ETR, in-sync
+ */
+static struct etr_eacr etr_eacr;
+static u64 etr_tolec;			/* time of last eacr update */
+static unsigned long etr_flags;
+static struct etr_aib etr_port0;
+static int etr_port0_uptodate;
+static struct etr_aib etr_port1;
+static int etr_port1_uptodate;
+static unsigned long etr_events;
+static struct timer_list etr_timer;
+static struct tasklet_struct etr_tasklet;
+static DEFINE_PER_CPU(atomic_t, etr_sync_word);
+
+static void etr_timeout(unsigned long dummy);
+static void etr_tasklet_fn(unsigned long dummy);
+
+/*
+ * The etr get_clock function. It will write the current clock value
+ * to the clock pointer and return 0 if the clock is in sync with the
+ * external time source. If the clock mode is local it will return
+ * -ENOSYS and -EAGAIN if the clock is not in sync with the external
+ * reference. This function is what ETR is all about..
+ */
+int get_sync_clock(unsigned long long *clock)
+{
+	atomic_t *sw_ptr;
+	unsigned int sw0, sw1;
+
+	sw_ptr = &get_cpu_var(etr_sync_word);
+	sw0 = atomic_read(sw_ptr);
+	*clock = get_clock();
+	sw1 = atomic_read(sw_ptr);
+	put_cpu_var(etr_sync_sync);
+	if (sw0 == sw1 && (sw0 & 0x80000000U))
+		/* Success: time is in sync. */
+		return 0;
+	if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+		return -ENOSYS;
+	if (test_bit(ETR_FLAG_EACCES, &etr_flags))
+		return -EACCES;
+	return -EAGAIN;
+}
+EXPORT_SYMBOL(get_sync_clock);
+
+/*
+ * Make get_sync_clock return -EAGAIN.
+ */
+static void etr_disable_sync_clock(void *dummy)
+{
+	atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word);
+	/*
+	 * Clear the in-sync bit 2^31. All get_sync_clock calls will
+	 * fail until the sync bit is turned back on. In addition
+	 * increase the "sequence" counter to avoid the race of an
+	 * etr event and the complete recovery against get_sync_clock.
+	 */
+	atomic_clear_mask(0x80000000, sw_ptr);
+	atomic_inc(sw_ptr);
+}
+
+/*
+ * Make get_sync_clock return 0 again.
+ * Needs to be called from a context disabled for preemption.
+ */
+static void etr_enable_sync_clock(void)
+{
+	atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word);
+	atomic_set_mask(0x80000000, sw_ptr);
+}
+
+/*
+ * Reset ETR attachment.
+ */
+static void etr_reset(void)
+{
+	etr_eacr =  (struct etr_eacr) {
+		.e0 = 0, .e1 = 0, ._pad0 = 4, .dp = 0,
+		.p0 = 0, .p1 = 0, ._pad1 = 0, .ea = 0,
+		.es = 0, .sl = 0 };
+	if (etr_setr(&etr_eacr) == 0)
+		etr_tolec = get_clock();
+	else {
+		set_bit(ETR_FLAG_ENOSYS, &etr_flags);
+		if (etr_port0_online || etr_port1_online) {
+			printk(KERN_WARNING "Running on non ETR capable "
+			       "machine, only local mode available.\n");
+			etr_port0_online = etr_port1_online = 0;
+		}
+	}
+}
+
+static void etr_init(void)
+{
+	struct etr_aib aib;
+
+	if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+		return;
+	/* Check if this machine has the steai instruction. */
+	if (etr_steai(&aib, ETR_STEAI_STEPPING_PORT) == 0)
+		set_bit(ETR_FLAG_STEAI, &etr_flags);
+	setup_timer(&etr_timer, etr_timeout, 0UL);
+	tasklet_init(&etr_tasklet, etr_tasklet_fn, 0);
+	if (!etr_port0_online && !etr_port1_online)
+		set_bit(ETR_FLAG_EACCES, &etr_flags);
+	if (etr_port0_online) {
+		set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
+		tasklet_hi_schedule(&etr_tasklet);
+	}
+	if (etr_port1_online) {
+		set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
+		tasklet_hi_schedule(&etr_tasklet);
+	}
+}
+
+/*
+ * Two sorts of ETR machine checks. The architecture reads:
+ * "When a machine-check niterruption occurs and if a switch-to-local or
+ *  ETR-sync-check interrupt request is pending but disabled, this pending
+ *  disabled interruption request is indicated and is cleared".
+ * Which means that we can get etr_switch_to_local events from the machine
+ * check handler although the interruption condition is disabled. Lovely..
+ */
+
+/*
+ * Switch to local machine check. This is called when the last usable
+ * ETR port goes inactive. After switch to local the clock is not in sync.
+ */
+void etr_switch_to_local(void)
+{
+	if (!etr_eacr.sl)
+		return;
+	etr_disable_sync_clock(NULL);
+	set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
+	tasklet_hi_schedule(&etr_tasklet);
+}
+
+/*
+ * ETR sync check machine check. This is called when the ETR OTE and the
+ * local clock OTE are farther apart than the ETR sync check tolerance.
+ * After a ETR sync check the clock is not in sync. The machine check
+ * is broadcasted to all cpus at the same time.
+ */
+void etr_sync_check(void)
+{
+	if (!etr_eacr.es)
+		return;
+	etr_disable_sync_clock(NULL);
+	set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
+	tasklet_hi_schedule(&etr_tasklet);
+}
+
+/*
+ * ETR external interrupt. There are two causes:
+ * 1) port state change, check the usability of the port
+ * 2) port alert, one of the ETR-data-validity bits (v1-v2 bits of the
+ *    sldr-status word) or ETR-data word 1 (edf1) or ETR-data word 3 (edf3)
+ *    or ETR-data word 4 (edf4) has changed.
+ */
+static void etr_ext_handler(__u16 code)
+{
+	struct etr_interruption_parameter *intparm =
+		(struct etr_interruption_parameter *) &S390_lowcore.ext_params;
+
+	if (intparm->pc0)
+		/* ETR port 0 state change. */
+		set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
+	if (intparm->pc1)
+		/* ETR port 1 state change. */
+		set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
+	if (intparm->eai)
+		/*
+		 * ETR port alert on either port 0, 1 or both.
+		 * Both ports are not up-to-date now.
+		 */
+		set_bit(ETR_EVENT_PORT_ALERT, &etr_events);
+	tasklet_hi_schedule(&etr_tasklet);
+}
+
+static void etr_timeout(unsigned long dummy)
+{
+	set_bit(ETR_EVENT_UPDATE, &etr_events);
+	tasklet_hi_schedule(&etr_tasklet);
+}
+
+/*
+ * Check if the etr mode is pss.
+ */
+static inline int etr_mode_is_pps(struct etr_eacr eacr)
+{
+	return eacr.es && !eacr.sl;
+}
+
+/*
+ * Check if the etr mode is etr.
+ */
+static inline int etr_mode_is_etr(struct etr_eacr eacr)
+{
+	return eacr.es && eacr.sl;
+}
+
+/*
+ * Check if the port can be used for TOD synchronization.
+ * For PPS mode the port has to receive OTEs. For ETR mode
+ * the port has to receive OTEs, the ETR stepping bit has to
+ * be zero and the validity bits for data frame 1, 2, and 3
+ * have to be 1.
+ */
+static int etr_port_valid(struct etr_aib *aib, int port)
+{
+	unsigned int psc;
+
+	/* Check that this port is receiving OTEs. */
+	if (aib->tsp == 0)
+		return 0;
+
+	psc = port ? aib->esw.psc1 : aib->esw.psc0;
+	if (psc == etr_lpsc_pps_mode)
+		return 1;
+	if (psc == etr_lpsc_operational_step)
+		return !aib->esw.y && aib->slsw.v1 &&
+			aib->slsw.v2 && aib->slsw.v3;
+	return 0;
+}
+
+/*
+ * Check if two ports are on the same network.
+ */
+static int etr_compare_network(struct etr_aib *aib1, struct etr_aib *aib2)
+{
+	// FIXME: any other fields we have to compare?
+	return aib1->edf1.net_id == aib2->edf1.net_id;
+}
+
+/*
+ * Wrapper for etr_stei that converts physical port states
+ * to logical port states to be consistent with the output
+ * of stetr (see etr_psc vs. etr_lpsc).
+ */
+static void etr_steai_cv(struct etr_aib *aib, unsigned int func)
+{
+	BUG_ON(etr_steai(aib, func) != 0);
+	/* Convert port state to logical port state. */
+	if (aib->esw.psc0 == 1)
+		aib->esw.psc0 = 2;
+	else if (aib->esw.psc0 == 0 && aib->esw.p == 0)
+		aib->esw.psc0 = 1;
+	if (aib->esw.psc1 == 1)
+		aib->esw.psc1 = 2;
+	else if (aib->esw.psc1 == 0 && aib->esw.p == 1)
+		aib->esw.psc1 = 1;
+}
+
+/*
+ * Check if the aib a2 is still connected to the same attachment as
+ * aib a1, the etv values differ by one and a2 is valid.
+ */
+static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p)
+{
+	int state_a1, state_a2;
+
+	/* Paranoia check: e0/e1 should better be the same. */
+	if (a1->esw.eacr.e0 != a2->esw.eacr.e0 ||
+	    a1->esw.eacr.e1 != a2->esw.eacr.e1)
+		return 0;
+
+	/* Still connected to the same etr ? */
+	state_a1 = p ? a1->esw.psc1 : a1->esw.psc0;
+	state_a2 = p ? a2->esw.psc1 : a2->esw.psc0;
+	if (state_a1 == etr_lpsc_operational_step) {
+		if (state_a2 != etr_lpsc_operational_step ||
+		    a1->edf1.net_id != a2->edf1.net_id ||
+		    a1->edf1.etr_id != a2->edf1.etr_id ||
+		    a1->edf1.etr_pn != a2->edf1.etr_pn)
+			return 0;
+	} else if (state_a2 != etr_lpsc_pps_mode)
+		return 0;
+
+	/* The ETV value of a2 needs to be ETV of a1 + 1. */
+	if (a1->edf2.etv + 1 != a2->edf2.etv)
+		return 0;
+
+	if (!etr_port_valid(a2, p))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * The time is "clock". xtime is what we think the time is.
+ * Adjust the value by a multiple of jiffies and add the delta to ntp.
+ * "delay" is an approximation how long the synchronization took. If
+ * the time correction is positive, then "delay" is subtracted from
+ * the time difference and only the remaining part is passed to ntp.
+ */
+static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
+{
+	unsigned long long delta, ticks;
+	struct timex adjust;
+
+	/*
+	 * We don't have to take the xtime lock because the cpu
+	 * executing etr_adjust_time is running disabled in
+	 * tasklet context and all other cpus are looping in
+	 * etr_sync_cpu_start.
+	 */
+	if (clock > xtime_cc) {
+		/* It is later than we thought. */
+		delta = ticks = clock - xtime_cc;
+		delta = ticks = (delta < delay) ? 0 : delta - delay;
+		delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+		init_timer_cc = init_timer_cc + delta;
+		jiffies_timer_cc = jiffies_timer_cc + delta;
+		xtime_cc = xtime_cc + delta;
+		adjust.offset = ticks * (1000000 / HZ);
+	} else {
+		/* It is earlier than we thought. */
+		delta = ticks = xtime_cc - clock;
+		delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+		init_timer_cc = init_timer_cc - delta;
+		jiffies_timer_cc = jiffies_timer_cc - delta;
+		xtime_cc = xtime_cc - delta;
+		adjust.offset = -ticks * (1000000 / HZ);
+	}
+	if (adjust.offset != 0) {
+		printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
+		       adjust.offset);
+		adjust.modes = ADJ_OFFSET_SINGLESHOT;
+		do_adjtimex(&adjust);
+	}
+}
+
+static void etr_sync_cpu_start(void *dummy)
+{
+	int *in_sync = dummy;
+
+	etr_enable_sync_clock();
+	/*
+	 * This looks like a busy wait loop but it isn't. etr_sync_cpus
+	 * is called on all other cpus while the TOD clocks is stopped.
+	 * __udelay will stop the cpu on an enabled wait psw until the
+	 * TOD is running again.
+	 */
+	while (*in_sync == 0)
+		__udelay(1);
+	if (*in_sync != 1)
+		/* Didn't work. Clear per-cpu in sync bit again. */
+		etr_disable_sync_clock(NULL);
+	/*
+	 * This round of TOD syncing is done. Set the clock comparator
+	 * to the next tick and let the processor continue.
+	 */
+	setup_jiffy_timer();
+}
+
+static void etr_sync_cpu_end(void *dummy)
+{
+}
+
+/*
+ * Sync the TOD clock using the port refered to by aibp. This port
+ * has to be enabled and the other port has to be disabled. The
+ * last eacr update has to be more than 1.6 seconds in the past.
+ */
+static int etr_sync_clock(struct etr_aib *aib, int port)
+{
+	struct etr_aib *sync_port;
+	unsigned long long clock, delay;
+	int in_sync, follows;
+	int rc;
+
+	/* Check if the current aib is adjacent to the sync port aib. */
+	sync_port = (port == 0) ? &etr_port0 : &etr_port1;
+	follows = etr_aib_follows(sync_port, aib, port);
+	memcpy(sync_port, aib, sizeof(*aib));
+	if (!follows)
+		return -EAGAIN;
+
+	/*
+	 * Catch all other cpus and make them wait until we have
+	 * successfully synced the clock. smp_call_function will
+	 * return after all other cpus are in etr_sync_cpu_start.
+	 */
+	in_sync = 0;
+	preempt_disable();
+	smp_call_function(etr_sync_cpu_start,&in_sync,0,0);
+	local_irq_disable();
+	etr_enable_sync_clock();
+
+	/* Set clock to next OTE. */
+	__ctl_set_bit(14, 21);
+	__ctl_set_bit(0, 29);
+	clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32;
+	if (set_clock(clock) == 0) {
+		__udelay(1);	/* Wait for the clock to start. */
+		__ctl_clear_bit(0, 29);
+		__ctl_clear_bit(14, 21);
+		etr_stetr(aib);
+		/* Adjust Linux timing variables. */
+		delay = (unsigned long long)
+			(aib->edf2.etv - sync_port->edf2.etv) << 32;
+		etr_adjust_time(clock, delay);
+		setup_jiffy_timer();
+		/* Verify that the clock is properly set. */
+		if (!etr_aib_follows(sync_port, aib, port)) {
+			/* Didn't work. */
+			etr_disable_sync_clock(NULL);
+			in_sync = -EAGAIN;
+			rc = -EAGAIN;
+		} else {
+			in_sync = 1;
+			rc = 0;
+		}
+	} else {
+		/* Could not set the clock ?!? */
+		__ctl_clear_bit(0, 29);
+		__ctl_clear_bit(14, 21);
+		etr_disable_sync_clock(NULL);
+		in_sync = -EAGAIN;
+		rc = -EAGAIN;
+	}
+	local_irq_enable();
+	smp_call_function(etr_sync_cpu_end,NULL,0,0);
+	preempt_enable();
+	return rc;
+}
+
+/*
+ * Handle the immediate effects of the different events.
+ * The port change event is used for online/offline changes.
+ */
+static struct etr_eacr etr_handle_events(struct etr_eacr eacr)
+{
+	if (test_and_clear_bit(ETR_EVENT_SYNC_CHECK, &etr_events))
+		eacr.es = 0;
+	if (test_and_clear_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events))
+		eacr.es = eacr.sl = 0;
+	if (test_and_clear_bit(ETR_EVENT_PORT_ALERT, &etr_events))
+		etr_port0_uptodate = etr_port1_uptodate = 0;
+
+	if (test_and_clear_bit(ETR_EVENT_PORT0_CHANGE, &etr_events)) {
+		if (eacr.e0)
+			/*
+			 * Port change of an enabled port. We have to
+			 * assume that this can have caused an stepping
+			 * port switch.
+			 */
+			etr_tolec = get_clock();
+		eacr.p0 = etr_port0_online;
+		if (!eacr.p0)
+			eacr.e0 = 0;
+		etr_port0_uptodate = 0;
+	}
+	if (test_and_clear_bit(ETR_EVENT_PORT1_CHANGE, &etr_events)) {
+		if (eacr.e1)
+			/*
+			 * Port change of an enabled port. We have to
+			 * assume that this can have caused an stepping
+			 * port switch.
+			 */
+			etr_tolec = get_clock();
+		eacr.p1 = etr_port1_online;
+		if (!eacr.p1)
+			eacr.e1 = 0;
+		etr_port1_uptodate = 0;
+	}
+	clear_bit(ETR_EVENT_UPDATE, &etr_events);
+	return eacr;
+}
+
+/*
+ * Set up a timer that expires after the etr_tolec + 1.6 seconds if
+ * one of the ports needs an update.
+ */
+static void etr_set_tolec_timeout(unsigned long long now)
+{
+	unsigned long micros;
+
+	if ((!etr_eacr.p0 || etr_port0_uptodate) &&
+	    (!etr_eacr.p1 || etr_port1_uptodate))
+		return;
+	micros = (now > etr_tolec) ? ((now - etr_tolec) >> 12) : 0;
+	micros = (micros > 1600000) ? 0 : 1600000 - micros;
+	mod_timer(&etr_timer, jiffies + (micros * HZ) / 1000000 + 1);
+}
+
+/*
+ * Set up a time that expires after 1/2 second.
+ */
+static void etr_set_sync_timeout(void)
+{
+	mod_timer(&etr_timer, jiffies + HZ/2);
+}
+
+/*
+ * Update the aib information for one or both ports.
+ */
+static struct etr_eacr etr_handle_update(struct etr_aib *aib,
+					 struct etr_eacr eacr)
+{
+	/* With both ports disabled the aib information is useless. */
+	if (!eacr.e0 && !eacr.e1)
+		return eacr;
+
+	/* Update port0 or port1 with aib stored in etr_tasklet_fn. */
+	if (aib->esw.q == 0) {
+		/* Information for port 0 stored. */
+		if (eacr.p0 && !etr_port0_uptodate) {
+			etr_port0 = *aib;
+			if (etr_port0_online)
+				etr_port0_uptodate = 1;
+		}
+	} else {
+		/* Information for port 1 stored. */
+		if (eacr.p1 && !etr_port1_uptodate) {
+			etr_port1 = *aib;
+			if (etr_port0_online)
+				etr_port1_uptodate = 1;
+		}
+	}
+
+	/*
+	 * Do not try to get the alternate port aib if the clock
+	 * is not in sync yet.
+	 */
+	if (!eacr.es)
+		return eacr;
+
+	/*
+	 * If steai is available we can get the information about
+	 * the other port immediately. If only stetr is available the
+	 * data-port bit toggle has to be used.
+	 */
+	if (test_bit(ETR_FLAG_STEAI, &etr_flags)) {
+		if (eacr.p0 && !etr_port0_uptodate) {
+			etr_steai_cv(&etr_port0, ETR_STEAI_PORT_0);
+			etr_port0_uptodate = 1;
+		}
+		if (eacr.p1 && !etr_port1_uptodate) {
+			etr_steai_cv(&etr_port1, ETR_STEAI_PORT_1);
+			etr_port1_uptodate = 1;
+		}
+	} else {
+		/*
+		 * One port was updated above, if the other
+		 * port is not uptodate toggle dp bit.
+		 */
+		if ((eacr.p0 && !etr_port0_uptodate) ||
+		    (eacr.p1 && !etr_port1_uptodate))
+			eacr.dp ^= 1;
+		else
+			eacr.dp = 0;
+	}
+	return eacr;
+}
+
+/*
+ * Write new etr control register if it differs from the current one.
+ * Return 1 if etr_tolec has been updated as well.
+ */
+static void etr_update_eacr(struct etr_eacr eacr)
+{
+	int dp_changed;
+
+	if (memcmp(&etr_eacr, &eacr, sizeof(eacr)) == 0)
+		/* No change, return. */
+		return;
+	/*
+	 * The disable of an active port of the change of the data port
+	 * bit can/will cause a change in the data port.
+	 */
+	dp_changed = etr_eacr.e0 > eacr.e0 || etr_eacr.e1 > eacr.e1 ||
+		(etr_eacr.dp ^ eacr.dp) != 0;
+	etr_eacr = eacr;
+	etr_setr(&etr_eacr);
+	if (dp_changed)
+		etr_tolec = get_clock();
+}
+
+/*
+ * ETR tasklet. In this function you'll find the main logic. In
+ * particular this is the only function that calls etr_update_eacr(),
+ * it "controls" the etr control register.
+ */
+static void etr_tasklet_fn(unsigned long dummy)
+{
+	unsigned long long now;
+	struct etr_eacr eacr;
+	struct etr_aib aib;
+	int sync_port;
+
+	/* Create working copy of etr_eacr. */
+	eacr = etr_eacr;
+
+	/* Check for the different events and their immediate effects. */
+	eacr = etr_handle_events(eacr);
+
+	/* Check if ETR is supposed to be active. */
+	eacr.ea = eacr.p0 || eacr.p1;
+	if (!eacr.ea) {
+		/* Both ports offline. Reset everything. */
+		eacr.dp = eacr.es = eacr.sl = 0;
+		on_each_cpu(etr_disable_sync_clock, NULL, 0, 1);
+		del_timer_sync(&etr_timer);
+		etr_update_eacr(eacr);
+		set_bit(ETR_FLAG_EACCES, &etr_flags);
+		return;
+	}
+
+	/* Store aib to get the current ETR status word. */
+	BUG_ON(etr_stetr(&aib) != 0);
+	etr_port0.esw = etr_port1.esw = aib.esw;	/* Copy status word. */
+	now = get_clock();
+
+	/*
+	 * Update the port information if the last stepping port change
+	 * or data port change is older than 1.6 seconds.
+	 */
+	if (now >= etr_tolec + (1600000 << 12))
+		eacr = etr_handle_update(&aib, eacr);
+
+	/*
+	 * Select ports to enable. The prefered synchronization mode is PPS.
+	 * If a port can be enabled depends on a number of things:
+	 * 1) The port needs to be online and uptodate. A port is not
+	 *    disabled just because it is not uptodate, but it is only
+	 *    enabled if it is uptodate.
+	 * 2) The port needs to have the same mode (pps / etr).
+	 * 3) The port needs to be usable -> etr_port_valid() == 1
+	 * 4) To enable the second port the clock needs to be in sync.
+	 * 5) If both ports are useable and are ETR ports, the network id
+	 *    has to be the same.
+	 * The eacr.sl bit is used to indicate etr mode vs. pps mode.
+	 */
+	if (eacr.p0 && aib.esw.psc0 == etr_lpsc_pps_mode) {
+		eacr.sl = 0;
+		eacr.e0 = 1;
+		if (!etr_mode_is_pps(etr_eacr))
+			eacr.es = 0;
+		if (!eacr.es || !eacr.p1 || aib.esw.psc1 != etr_lpsc_pps_mode)
+			eacr.e1 = 0;
+		// FIXME: uptodate checks ?
+		else if (etr_port0_uptodate && etr_port1_uptodate)
+			eacr.e1 = 1;
+		sync_port = (etr_port0_uptodate &&
+			     etr_port_valid(&etr_port0, 0)) ? 0 : -1;
+		clear_bit(ETR_FLAG_EACCES, &etr_flags);
+	} else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_pps_mode) {
+		eacr.sl = 0;
+		eacr.e0 = 0;
+		eacr.e1 = 1;
+		if (!etr_mode_is_pps(etr_eacr))
+			eacr.es = 0;
+		sync_port = (etr_port1_uptodate &&
+			     etr_port_valid(&etr_port1, 1)) ? 1 : -1;
+		clear_bit(ETR_FLAG_EACCES, &etr_flags);
+	} else if (eacr.p0 && aib.esw.psc0 == etr_lpsc_operational_step) {
+		eacr.sl = 1;
+		eacr.e0 = 1;
+		if (!etr_mode_is_etr(etr_eacr))
+			eacr.es = 0;
+		if (!eacr.es || !eacr.p1 ||
+		    aib.esw.psc1 != etr_lpsc_operational_alt)
+			eacr.e1 = 0;
+		else if (etr_port0_uptodate && etr_port1_uptodate &&
+			 etr_compare_network(&etr_port0, &etr_port1))
+			eacr.e1 = 1;
+		sync_port = (etr_port0_uptodate &&
+			     etr_port_valid(&etr_port0, 0)) ? 0 : -1;
+		clear_bit(ETR_FLAG_EACCES, &etr_flags);
+	} else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_operational_step) {
+		eacr.sl = 1;
+		eacr.e0 = 0;
+		eacr.e1 = 1;
+		if (!etr_mode_is_etr(etr_eacr))
+			eacr.es = 0;
+		sync_port = (etr_port1_uptodate &&
+			     etr_port_valid(&etr_port1, 1)) ? 1 : -1;
+		clear_bit(ETR_FLAG_EACCES, &etr_flags);
+	} else {
+		/* Both ports not usable. */
+		eacr.es = eacr.sl = 0;
+		sync_port = -1;
+		set_bit(ETR_FLAG_EACCES, &etr_flags);
+	}
+
+	/*
+	 * If the clock is in sync just update the eacr and return.
+	 * If there is no valid sync port wait for a port update.
+	 */
+	if (eacr.es || sync_port < 0) {
+		etr_update_eacr(eacr);
+		etr_set_tolec_timeout(now);
+		return;
+	}
+
+	/*
+	 * Prepare control register for clock syncing
+	 * (reset data port bit, set sync check control.
+	 */
+	eacr.dp = 0;
+	eacr.es = 1;
+
+	/*
+	 * Update eacr and try to synchronize the clock. If the update
+	 * of eacr caused a stepping port switch (or if we have to
+	 * assume that a stepping port switch has occured) or the
+	 * clock syncing failed, reset the sync check control bit
+	 * and set up a timer to try again after 0.5 seconds
+	 */
+	etr_update_eacr(eacr);
+	if (now < etr_tolec + (1600000 << 12) ||
+	    etr_sync_clock(&aib, sync_port) != 0) {
+		/* Sync failed. Try again in 1/2 second. */
+		eacr.es = 0;
+		etr_update_eacr(eacr);
+		etr_set_sync_timeout();
+	} else
+		etr_set_tolec_timeout(now);
+}
+
+/*
+ * Sysfs interface functions
+ */
+static struct sysdev_class etr_sysclass = {
+	set_kset_name("etr")
+};
+
+static struct sys_device etr_port0_dev = {
+	.id	= 0,
+	.cls	= &etr_sysclass,
+};
+
+static struct sys_device etr_port1_dev = {
+	.id	= 1,
+	.cls	= &etr_sysclass,
+};
+
+/*
+ * ETR class attributes
+ */
+static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf)
+{
+	return sprintf(buf, "%i\n", etr_port0.esw.p);
+}
+
+static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL);
+
+static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf)
+{
+	char *mode_str;
+
+	if (etr_mode_is_pps(etr_eacr))
+		mode_str = "pps";
+	else if (etr_mode_is_etr(etr_eacr))
+		mode_str = "etr";
+	else
+		mode_str = "local";
+	return sprintf(buf, "%s\n", mode_str);
+}
+
+static SYSDEV_CLASS_ATTR(stepping_mode, 0400, etr_stepping_mode_show, NULL);
+
+/*
+ * ETR port attributes
+ */
+static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev)
+{
+	if (dev == &etr_port0_dev)
+		return etr_port0_online ? &etr_port0 : NULL;
+	else
+		return etr_port1_online ? &etr_port1 : NULL;
+}
+
+static ssize_t etr_online_show(struct sys_device *dev, char *buf)
+{
+	unsigned int online;
+
+	online = (dev == &etr_port0_dev) ? etr_port0_online : etr_port1_online;
+	return sprintf(buf, "%i\n", online);
+}
+
+static ssize_t etr_online_store(struct sys_device *dev,
+			      const char *buf, size_t count)
+{
+	unsigned int value;
+
+	value = simple_strtoul(buf, NULL, 0);
+	if (value != 0 && value != 1)
+		return -EINVAL;
+	if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+		return -ENOSYS;
+	if (dev == &etr_port0_dev) {
+		if (etr_port0_online == value)
+			return count;	/* Nothing to do. */
+		etr_port0_online = value;
+		set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
+		tasklet_hi_schedule(&etr_tasklet);
+	} else {
+		if (etr_port1_online == value)
+			return count;	/* Nothing to do. */
+		etr_port1_online = value;
+		set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
+		tasklet_hi_schedule(&etr_tasklet);
+	}
+	return count;
+}
+
+static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store);
+
+static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf)
+{
+	return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
+		       etr_eacr.e0 : etr_eacr.e1);
+}
+
+static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL);
+
+static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf)
+{
+	if (!etr_port0_online && !etr_port1_online)
+		/* Status word is not uptodate if both ports are offline. */
+		return -ENODATA;
+	return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
+		       etr_port0.esw.psc0 : etr_port0.esw.psc1);
+}
+
+static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL);
+
+static ssize_t etr_untuned_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v1)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf1.u);
+}
+
+static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL);
+
+static ssize_t etr_network_id_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v1)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf1.net_id);
+}
+
+static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL);
+
+static ssize_t etr_id_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v1)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf1.etr_id);
+}
+
+static SYSDEV_ATTR(id, 0400, etr_id_show, NULL);
+
+static ssize_t etr_port_number_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v1)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf1.etr_pn);
+}
+
+static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL);
+
+static ssize_t etr_coupled_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v3)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf3.c);
+}
+
+static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL);
+
+static ssize_t etr_local_time_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v3)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf3.blto);
+}
+
+static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL);
+
+static ssize_t etr_utc_offset_show(struct sys_device *dev, char *buf)
+{
+	struct etr_aib *aib = etr_aib_from_dev(dev);
+
+	if (!aib || !aib->slsw.v3)
+		return -ENODATA;
+	return sprintf(buf, "%i\n", aib->edf3.buo);
+}
+
+static SYSDEV_ATTR(utc_offset, 0400, etr_utc_offset_show, NULL);
+
+static struct sysdev_attribute *etr_port_attributes[] = {
+	&attr_online,
+	&attr_stepping_control,
+	&attr_state_code,
+	&attr_untuned,
+	&attr_network,
+	&attr_id,
+	&attr_port,
+	&attr_coupled,
+	&attr_local_time,
+	&attr_utc_offset,
+	NULL
+};
+
+static int __init etr_register_port(struct sys_device *dev)
+{
+	struct sysdev_attribute **attr;
+	int rc;
+
+	rc = sysdev_register(dev);
+	if (rc)
+		goto out;
+	for (attr = etr_port_attributes; *attr; attr++) {
+		rc = sysdev_create_file(dev, *attr);
+		if (rc)
+			goto out_unreg;
+	}
+	return 0;
+out_unreg:
+	for (; attr >= etr_port_attributes; attr--)
+		sysdev_remove_file(dev, *attr);
+	sysdev_unregister(dev);
+out:
+	return rc;
+}
+
+static void __init etr_unregister_port(struct sys_device *dev)
+{
+	struct sysdev_attribute **attr;
+
+	for (attr = etr_port_attributes; *attr; attr++)
+		sysdev_remove_file(dev, *attr);
+	sysdev_unregister(dev);
+}
+
+static int __init etr_init_sysfs(void)
+{
+	int rc;
+
+	rc = sysdev_class_register(&etr_sysclass);
+	if (rc)
+		goto out;
+	rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_port);
+	if (rc)
+		goto out_unreg_class;
+	rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_mode);
+	if (rc)
+		goto out_remove_stepping_port;
+	rc = etr_register_port(&etr_port0_dev);
+	if (rc)
+		goto out_remove_stepping_mode;
+	rc = etr_register_port(&etr_port1_dev);
+	if (rc)
+		goto out_remove_port0;
+	return 0;
+
+out_remove_port0:
+	etr_unregister_port(&etr_port0_dev);
+out_remove_stepping_mode:
+	sysdev_class_remove_file(&etr_sysclass, &attr_stepping_mode);
+out_remove_stepping_port:
+	sysdev_class_remove_file(&etr_sysclass, &attr_stepping_port);
+out_unreg_class:
+	sysdev_class_unregister(&etr_sysclass);
+out:
+	return rc;
+}
+
+device_initcall(etr_init_sysfs);
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 3cbb0dc..f0e5a32 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -283,7 +283,7 @@
 	return buffer;
 }
 
-DEFINE_SPINLOCK(die_lock);
+static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -364,8 +364,7 @@
 		force_sig(SIGTRAP, current);
 }
 
-asmlinkage void
-default_trap_handler(struct pt_regs * regs, long interruption_code)
+static void default_trap_handler(struct pt_regs * regs, long interruption_code)
 {
         if (regs->psw.mask & PSW_MASK_PSTATE) {
 		local_irq_enable();
@@ -376,7 +375,7 @@
 }
 
 #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \
-asmlinkage void name(struct pt_regs * regs, long interruption_code) \
+static void name(struct pt_regs * regs, long interruption_code) \
 { \
         siginfo_t info; \
         info.si_signo = signr; \
@@ -442,7 +441,7 @@
 		"floating point exception", regs, &si);
 }
 
-asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
+static void illegal_op(struct pt_regs * regs, long interruption_code)
 {
 	siginfo_t info;
         __u8 opcode[6];
@@ -491,8 +490,15 @@
 #endif
 		} else
 			signal = SIGILL;
-	} else
-		signal = SIGILL;
+	} else {
+		/*
+		 * If we get an illegal op in kernel mode, send it through the
+		 * kprobes notifier. If kprobes doesn't pick it up, SIGILL
+		 */
+		if (notify_die(DIE_BPT, "bpt", regs, interruption_code,
+			       3, SIGTRAP) != NOTIFY_STOP)
+			signal = SIGILL;
+	}
 
 #ifdef CONFIG_MATHEMU
         if (signal == SIGFPE)
@@ -585,7 +591,7 @@
 	      ILL_ILLOPN, get_check_address(regs));
 #endif
 
-asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
+static void data_exception(struct pt_regs * regs, long interruption_code)
 {
 	__u16 __user *location;
 	int signal = 0;
@@ -675,7 +681,7 @@
 	}
 }
 
-asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code)
+static void space_switch_exception(struct pt_regs * regs, long int_code)
 {
         siginfo_t info;
 
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index fe0f2e9..a489073 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -31,19 +31,20 @@
 
   _etext = .;			/* End of text section */
 
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
   RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
   . = ALIGN(1048576);		/* VM shared segments are 1MB aligned */
-
-  _eshared = .;			/* End of shareable data */
 #endif
 
+  . = ALIGN(4096);
+  _eshared = .;			/* End of shareable data */
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
   .data : {			/* Data */
 	*(.data)
 	CONSTRUCTORS
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 21baaf5..9d5b028 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -25,7 +25,7 @@
 #include <asm/irq_regs.h>
 
 static ext_int_info_t ext_int_info_timer;
-DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -524,16 +524,15 @@
 void init_cpu_vtimer(void)
 {
 	struct vtimer_queue *vt_list;
-	unsigned long cr0;
 
 	/* kick the virtual timer */
 	S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
 	S390_lowcore.last_update_timer = VTIMER_MAX_SLICE;
 	asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
 	asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
-	__ctl_store(cr0, 0, 0);
-	cr0 |= 0x400;
-	__ctl_load(cr0, 0, 0);
+
+	/* enable cpu timer interrupts */
+	__ctl_set_bit(0,10);
 
 	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
 	INIT_LIST_HEAD(&vt_list->list);
@@ -572,6 +571,7 @@
 	if (register_idle_notifier(&vtimer_idle_nb))
 		panic("Couldn't register idle notifier");
 
+	/* Enable cpu timer interrupts on the boot cpu. */
 	init_cpu_vtimer();
 }
 
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index b5f94cf..7a44fed 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
 lib-$(CONFIG_32BIT) += div64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 027c474..0285444 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -1,5 +1,5 @@
 /*
- *  arch/s390/kernel/delay.c
+ *  arch/s390/lib/delay.c
  *    Precise Delay Loops for S390
  *
  *  S390 version
@@ -13,10 +13,8 @@
 
 #include <linux/sched.h>
 #include <linux/delay.h>
-
-#ifdef CONFIG_SMP
-#include <asm/smp.h>
-#endif
+#include <linux/timex.h>
+#include <linux/irqflags.h>
 
 void __delay(unsigned long loops)
 {
@@ -31,17 +29,39 @@
 }
 
 /*
- * Waits for 'usecs' microseconds using the tod clock, giving up the time slice
- * of the virtual PU inbetween to avoid congestion.
+ * Waits for 'usecs' microseconds using the TOD clock comparator.
  */
 void __udelay(unsigned long usecs)
 {
-	uint64_t start_cc;
+	u64 end, time, jiffy_timer = 0;
+	unsigned long flags, cr0, mask, dummy;
 
-        if (usecs == 0)
-                return;
-	start_cc = get_clock();
-        do {
-		cpu_relax();
-	} while (((get_clock() - start_cc)/4096) < usecs);
+	local_irq_save(flags);
+	if (raw_irqs_disabled_flags(flags)) {
+		jiffy_timer = S390_lowcore.jiffy_timer;
+		S390_lowcore.jiffy_timer = -1ULL - (4096 << 12);
+		__ctl_store(cr0, 0, 0);
+		dummy = (cr0 & 0xffff00e0) | 0x00000800;
+		__ctl_load(dummy , 0, 0);
+		mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+	} else
+		mask = psw_kernel_bits | PSW_MASK_WAIT |
+			PSW_MASK_EXT | PSW_MASK_IO;
+
+	end = get_clock() + ((u64) usecs << 12);
+	do {
+		time = end < S390_lowcore.jiffy_timer ?
+			end : S390_lowcore.jiffy_timer;
+		set_clock_comparator(time);
+		trace_hardirqs_on();
+		__load_psw_mask(mask);
+		local_irq_disable();
+	} while (get_clock() < end);
+
+	if (raw_irqs_disabled_flags(flags)) {
+		__ctl_load(cr0, 0, 0);
+		S390_lowcore.jiffy_timer = jiffy_timer;
+	}
+	set_clock_comparator(S390_lowcore.jiffy_timer);
+	local_irq_restore(flags);
 }
diff --git a/arch/s390/lib/qrnnd.S b/arch/s390/lib/qrnnd.S
new file mode 100644
index 0000000..eb1df63
--- /dev/null
+++ b/arch/s390/lib/qrnnd.S
@@ -0,0 +1,77 @@
+# S/390 __udiv_qrnnd
+
+# r2 : &__r
+# r3 : upper half of 64 bit word n
+# r4 : lower half of 64 bit word n
+# r5 : divisor d
+# the reminder r of the division is to be stored to &__r and
+# the quotient q is to be returned
+
+	.text
+	.globl __udiv_qrnnd
+__udiv_qrnnd:
+	st    %r2,24(%r15)	  # store pointer to reminder for later
+	lr    %r0,%r3		  # reload n
+	lr    %r1,%r4
+	ltr   %r2,%r5		  # reload and test divisor
+	jp    5f
+	# divisor >= 0x80000000
+	srdl  %r0,2		  # n/4
+	srl   %r2,1		  # d/2
+	slr   %r1,%r2		  # special case if last bit of d is set
+	brc   3,0f		  #  (n/4) div (n/2) can overflow by 1
+	ahi   %r0,-1		  #  trick: subtract n/2, then divide
+0:	dr    %r0,%r2		  # signed division
+	ahi   %r1,1		  #  trick part 2: add 1 to the quotient
+	# now (n >> 2) = (d >> 1) * %r1 + %r0
+	lhi   %r3,1
+	nr    %r3,%r1		  # test last bit of q
+	jz    1f
+	alr   %r0,%r2		  # add (d>>1) to r
+1:	srl   %r1,1		  # q >>= 1
+	# now (n >> 2) = (d&-2) * %r1 + %r0
+	lhi   %r3,1
+	nr    %r3,%r5		  # test last bit of d
+	jz    2f
+	slr   %r0,%r1		  # r -= q
+	brc   3,2f		  # borrow ?
+	alr   %r0,%r5		  # r += d
+	ahi   %r1,-1
+2:	# now (n >> 2) = d * %r1 + %r0
+	alr   %r1,%r1		  # q <<= 1
+	alr   %r0,%r0		  # r <<= 1
+	brc   12,3f		  # overflow on r ?
+	slr   %r0,%r5		  # r -= d
+	ahi   %r1,1		  # q += 1
+3:	lhi   %r3,2
+	nr    %r3,%r4		  # test next to last bit of n
+	jz    4f
+	ahi   %r0,1		  # r += 1
+4:	clr   %r0,%r5		  # r >= d ?
+	jl    6f
+	slr   %r0,%r5		  # r -= d
+	ahi   %r1,1		  # q += 1
+	# now (n >> 1) = d * %r1 + %r0
+	j     6f
+5:	# divisor < 0x80000000
+	srdl  %r0,1
+	dr    %r0,%r2		  # signed division
+	# now (n >> 1) = d * %r1 + %r0
+6:	alr   %r1,%r1		  # q <<= 1
+	alr   %r0,%r0		  # r <<= 1
+	brc   12,7f		  # overflow on r ?
+	slr   %r0,%r5		  # r -= d
+	ahi   %r1,1		  # q += 1
+7:	lhi   %r3,1
+	nr    %r3,%r4		  # isolate last bit of n
+	alr   %r0,%r3		  # r += (n & 1)
+	clr   %r0,%r5		  # r >= d ?
+	jl    8f
+	slr   %r0,%r5		  # r -= d
+	ahi   %r1,1		  # q += 1
+8:	# now n = d * %r1 + %r0
+	l     %r2,24(%r15)
+	st    %r0,0(%r2)
+	lr    %r2,%r1
+	br    %r14
+	.end	__udiv_qrnnd
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
new file mode 100644
index 0000000..126011d
--- /dev/null
+++ b/arch/s390/lib/uaccess.h
@@ -0,0 +1,23 @@
+/*
+ *  arch/s390/uaccess.h
+ *
+ *    Copyright IBM Corp. 2007
+ *
+ */
+
+#ifndef __ARCH_S390_LIB_UACCESS_H
+#define __ARCH_S390_LIB_UACCESS_H
+
+extern size_t copy_from_user_std(size_t, const void __user *, void *);
+extern size_t copy_to_user_std(size_t, void __user *, const void *);
+extern size_t strnlen_user_std(size_t, const char __user *);
+extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
+extern int futex_atomic_cmpxchg_std(int __user *, int, int);
+extern int futex_atomic_op_std(int, int __user *, int, int *);
+
+extern size_t copy_from_user_pt(size_t, const void __user *, void *);
+extern size_t copy_to_user_pt(size_t, void __user *, const void *);
+extern int futex_atomic_op_pt(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+
+#endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index f9a23d5..6d87723 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
+#include "uaccess.h"
 
 #ifndef __s390x__
 #define AHI	"ahi"
@@ -27,10 +28,7 @@
 #define SLR	"slgr"
 #endif
 
-extern size_t copy_from_user_std(size_t, const void __user *, void *);
-extern size_t copy_to_user_std(size_t, void __user *, const void *);
-
-size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
+static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
 {
 	register unsigned long reg0 asm("0") = 0x81UL;
 	unsigned long tmp1, tmp2;
@@ -69,14 +67,14 @@
 	return size;
 }
 
-size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
+static size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
 {
 	if (size <= 256)
 		return copy_from_user_std(size, ptr, x);
 	return copy_from_user_mvcos(size, ptr, x);
 }
 
-size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
+static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
 {
 	register unsigned long reg0 asm("0") = 0x810000UL;
 	unsigned long tmp1, tmp2;
@@ -105,14 +103,16 @@
 	return size;
 }
 
-size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, const void *x)
+static size_t copy_to_user_mvcos_check(size_t size, void __user *ptr,
+				       const void *x)
 {
 	if (size <= 256)
 		return copy_to_user_std(size, ptr, x);
 	return copy_to_user_mvcos(size, ptr, x);
 }
 
-size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from)
+static size_t copy_in_user_mvcos(size_t size, void __user *to,
+				 const void __user *from)
 {
 	register unsigned long reg0 asm("0") = 0x810081UL;
 	unsigned long tmp1, tmp2;
@@ -134,7 +134,7 @@
 	return size;
 }
 
-size_t clear_user_mvcos(size_t size, void __user *to)
+static size_t clear_user_mvcos(size_t size, void __user *to)
 {
 	register unsigned long reg0 asm("0") = 0x810000UL;
 	unsigned long tmp1, tmp2;
@@ -162,10 +162,43 @@
 	return size;
 }
 
-extern size_t strnlen_user_std(size_t, const char __user *);
-extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_op(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg(int __user *, int, int);
+static size_t strnlen_user_mvcos(size_t count, const char __user *src)
+{
+	char buf[256];
+	int rc;
+	size_t done, len, len_str;
+
+	done = 0;
+	do {
+		len = min(count - done, (size_t) 256);
+		rc = uaccess.copy_from_user(len, src + done, buf);
+		if (unlikely(rc == len))
+			return 0;
+		len -= rc;
+		len_str = strnlen(buf, len);
+		done += len_str;
+	} while ((len_str == len) && (done < count));
+	return done + 1;
+}
+
+static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
+				      char *dst)
+{
+	int rc;
+	size_t done, len, len_str;
+
+	done = 0;
+	do {
+		len = min(count - done, (size_t) 4096);
+		rc = uaccess.copy_from_user(len, src + done, dst);
+		if (unlikely(rc == len))
+			return -EFAULT;
+		len -= rc;
+		len_str = strnlen(dst, len);
+		done += len_str;
+	} while ((len_str == len) && (done < count));
+	return done;
+}
 
 struct uaccess_ops uaccess_mvcos = {
 	.copy_from_user = copy_from_user_mvcos_check,
@@ -176,6 +209,21 @@
 	.clear_user = clear_user_mvcos,
 	.strnlen_user = strnlen_user_std,
 	.strncpy_from_user = strncpy_from_user_std,
-	.futex_atomic_op = futex_atomic_op,
-	.futex_atomic_cmpxchg = futex_atomic_cmpxchg,
+	.futex_atomic_op = futex_atomic_op_std,
+	.futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
 };
+
+#ifdef CONFIG_S390_SWITCH_AMODE
+struct uaccess_ops uaccess_mvcos_switch = {
+	.copy_from_user = copy_from_user_mvcos,
+	.copy_from_user_small = copy_from_user_mvcos,
+	.copy_to_user = copy_to_user_mvcos,
+	.copy_to_user_small = copy_to_user_mvcos,
+	.copy_in_user = copy_in_user_mvcos,
+	.clear_user = clear_user_mvcos,
+	.strnlen_user = strnlen_user_mvcos,
+	.strncpy_from_user = strncpy_from_user_mvcos,
+	.futex_atomic_op = futex_atomic_op_pt,
+	.futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt,
+};
+#endif
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 633249c..6318167 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -1,23 +1,28 @@
 /*
  *  arch/s390/lib/uaccess_pt.c
  *
- *  User access functions based on page table walks.
+ *  User access functions based on page table walks for enhanced
+ *  system layout without hardware support.
  *
  *    Copyright IBM Corp. 2006
  *    Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
  */
 
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
+#include "uaccess.h"
 
-static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
-				 int write_access)
+static int __handle_fault(struct mm_struct *mm, unsigned long address,
+			  int write_access)
 {
 	struct vm_area_struct *vma;
 	int ret = -EFAULT;
 
+	if (in_atomic())
+		return ret;
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (unlikely(!vma))
@@ -76,8 +81,8 @@
 	return ret;
 }
 
-static inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
-				    size_t n, int write_user)
+static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
+			     size_t n, int write_user)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long offset, pfn, done, size;
@@ -130,6 +135,49 @@
 	goto retry;
 }
 
+/*
+ * Do DAT for user address by page table walk, return kernel address.
+ * This function needs to be called with current->mm->page_table_lock held.
+ */
+static unsigned long __dat_user_addr(unsigned long uaddr)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long pfn, ret;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int rc;
+
+	ret = 0;
+retry:
+	pgd = pgd_offset(mm, uaddr);
+	if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+		goto fault;
+
+	pmd = pmd_offset(pgd, uaddr);
+	if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+		goto fault;
+
+	pte = pte_offset_map(pmd, uaddr);
+	if (!pte || !pte_present(*pte))
+		goto fault;
+
+	pfn = pte_pfn(*pte);
+	if (!pfn_valid(pfn))
+		goto out;
+
+	ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
+out:
+	return ret;
+fault:
+	spin_unlock(&mm->page_table_lock);
+	rc = __handle_fault(mm, uaddr, 0);
+	spin_lock(&mm->page_table_lock);
+	if (rc)
+		goto out;
+	goto retry;
+}
+
 size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
 {
 	size_t rc;
@@ -152,3 +200,277 @@
 	}
 	return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
 }
+
+static size_t clear_user_pt(size_t n, void __user *to)
+{
+	long done, size, ret;
+
+	if (segment_eq(get_fs(), KERNEL_DS)) {
+		memset((void __kernel __force *) to, 0, n);
+		return 0;
+	}
+	done = 0;
+	do {
+		if (n - done > PAGE_SIZE)
+			size = PAGE_SIZE;
+		else
+			size = n - done;
+		ret = __user_copy_pt((unsigned long) to + done,
+				      &empty_zero_page, size, 1);
+		done += size;
+		if (ret)
+			return ret + n - done;
+	} while (done < n);
+	return 0;
+}
+
+static size_t strnlen_user_pt(size_t count, const char __user *src)
+{
+	char *addr;
+	unsigned long uaddr = (unsigned long) src;
+	struct mm_struct *mm = current->mm;
+	unsigned long offset, pfn, done, len;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	size_t len_str;
+
+	if (segment_eq(get_fs(), KERNEL_DS))
+		return strnlen((const char __kernel __force *) src, count) + 1;
+	done = 0;
+retry:
+	spin_lock(&mm->page_table_lock);
+	do {
+		pgd = pgd_offset(mm, uaddr);
+		if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+			goto fault;
+
+		pmd = pmd_offset(pgd, uaddr);
+		if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+			goto fault;
+
+		pte = pte_offset_map(pmd, uaddr);
+		if (!pte || !pte_present(*pte))
+			goto fault;
+
+		pfn = pte_pfn(*pte);
+		if (!pfn_valid(pfn)) {
+			done = -1;
+			goto out;
+		}
+
+		offset = uaddr & (PAGE_SIZE-1);
+		addr = (char *)(pfn << PAGE_SHIFT) + offset;
+		len = min(count - done, PAGE_SIZE - offset);
+		len_str = strnlen(addr, len);
+		done += len_str;
+		uaddr += len_str;
+	} while ((len_str == len) && (done < count));
+out:
+	spin_unlock(&mm->page_table_lock);
+	return done + 1;
+fault:
+	spin_unlock(&mm->page_table_lock);
+	if (__handle_fault(mm, uaddr, 0)) {
+		return 0;
+	}
+	goto retry;
+}
+
+static size_t strncpy_from_user_pt(size_t count, const char __user *src,
+				   char *dst)
+{
+	size_t n = strnlen_user_pt(count, src);
+
+	if (!n)
+		return -EFAULT;
+	if (n > count)
+		n = count;
+	if (segment_eq(get_fs(), KERNEL_DS)) {
+		memcpy(dst, (const char __kernel __force *) src, n);
+		if (dst[n-1] == '\0')
+			return n-1;
+		else
+			return n;
+	}
+	if (__user_copy_pt((unsigned long) src, dst, n, 0))
+		return -EFAULT;
+	if (dst[n-1] == '\0')
+		return n-1;
+	else
+		return n;
+}
+
+static size_t copy_in_user_pt(size_t n, void __user *to,
+			      const void __user *from)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,
+		      uaddr, done, size;
+	unsigned long uaddr_from = (unsigned long) from;
+	unsigned long uaddr_to = (unsigned long) to;
+	pgd_t *pgd_from, *pgd_to;
+	pmd_t *pmd_from, *pmd_to;
+	pte_t *pte_from, *pte_to;
+	int write_user;
+
+	done = 0;
+retry:
+	spin_lock(&mm->page_table_lock);
+	do {
+		pgd_from = pgd_offset(mm, uaddr_from);
+		if (pgd_none(*pgd_from) || unlikely(pgd_bad(*pgd_from))) {
+			uaddr = uaddr_from;
+			write_user = 0;
+			goto fault;
+		}
+		pgd_to = pgd_offset(mm, uaddr_to);
+		if (pgd_none(*pgd_to) || unlikely(pgd_bad(*pgd_to))) {
+			uaddr = uaddr_to;
+			write_user = 1;
+			goto fault;
+		}
+
+		pmd_from = pmd_offset(pgd_from, uaddr_from);
+		if (pmd_none(*pmd_from) || unlikely(pmd_bad(*pmd_from))) {
+			uaddr = uaddr_from;
+			write_user = 0;
+			goto fault;
+		}
+		pmd_to = pmd_offset(pgd_to, uaddr_to);
+		if (pmd_none(*pmd_to) || unlikely(pmd_bad(*pmd_to))) {
+			uaddr = uaddr_to;
+			write_user = 1;
+			goto fault;
+		}
+
+		pte_from = pte_offset_map(pmd_from, uaddr_from);
+		if (!pte_from || !pte_present(*pte_from)) {
+			uaddr = uaddr_from;
+			write_user = 0;
+			goto fault;
+		}
+		pte_to = pte_offset_map(pmd_to, uaddr_to);
+		if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) {
+			uaddr = uaddr_to;
+			write_user = 1;
+			goto fault;
+		}
+
+		pfn_from = pte_pfn(*pte_from);
+		if (!pfn_valid(pfn_from))
+			goto out;
+		pfn_to = pte_pfn(*pte_to);
+		if (!pfn_valid(pfn_to))
+			goto out;
+
+		offset_from = uaddr_from & (PAGE_SIZE-1);
+		offset_to = uaddr_from & (PAGE_SIZE-1);
+		offset_max = max(offset_from, offset_to);
+		size = min(n - done, PAGE_SIZE - offset_max);
+
+		memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to,
+		       (void *)(pfn_from << PAGE_SHIFT) + offset_from, size);
+		done += size;
+		uaddr_from += size;
+		uaddr_to += size;
+	} while (done < n);
+out:
+	spin_unlock(&mm->page_table_lock);
+	return n - done;
+fault:
+	spin_unlock(&mm->page_table_lock);
+	if (__handle_fault(mm, uaddr, write_user))
+		return n - done;
+	goto retry;
+}
+
+#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)	\
+	asm volatile("0: l   %1,0(%6)\n"				\
+		     "1: " insn						\
+		     "2: cs  %1,%2,0(%6)\n"				\
+		     "3: jl  1b\n"					\
+		     "   lhi %0,0\n"					\
+		     "4:\n"						\
+		     EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)	\
+		     : "=d" (ret), "=&d" (oldval), "=&d" (newval),	\
+		       "=m" (*uaddr)					\
+		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
+		       "m" (*uaddr) : "cc" );
+
+int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+{
+	int oldval = 0, newval, ret;
+
+	spin_lock(&current->mm->page_table_lock);
+	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+	if (!uaddr) {
+		spin_unlock(&current->mm->page_table_lock);
+		return -EFAULT;
+	}
+	get_page(virt_to_page(uaddr));
+	spin_unlock(&current->mm->page_table_lock);
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("lr %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("lr %2,%1\nar %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("lr %2,%1\nor %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("lr %2,%1\nnr %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("lr %2,%1\nxr %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+	put_page(virt_to_page(uaddr));
+	*old = oldval;
+	return ret;
+}
+
+int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+{
+	int ret;
+
+	spin_lock(&current->mm->page_table_lock);
+	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+	if (!uaddr) {
+		spin_unlock(&current->mm->page_table_lock);
+		return -EFAULT;
+	}
+	get_page(virt_to_page(uaddr));
+	spin_unlock(&current->mm->page_table_lock);
+	asm volatile("   cs   %1,%4,0(%5)\n"
+		     "0: lr   %0,%1\n"
+		     "1:\n"
+		     EX_TABLE(0b,1b)
+		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+		     : "cc", "memory" );
+	put_page(virt_to_page(uaddr));
+	return ret;
+}
+
+struct uaccess_ops uaccess_pt = {
+	.copy_from_user		= copy_from_user_pt,
+	.copy_from_user_small	= copy_from_user_pt,
+	.copy_to_user		= copy_to_user_pt,
+	.copy_to_user_small	= copy_to_user_pt,
+	.copy_in_user		= copy_in_user_pt,
+	.clear_user		= clear_user_pt,
+	.strnlen_user		= strnlen_user_pt,
+	.strncpy_from_user	= strncpy_from_user_pt,
+	.futex_atomic_op	= futex_atomic_op_pt,
+	.futex_atomic_cmpxchg	= futex_atomic_cmpxchg_pt,
+};
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index bbaca66..28c4500 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/uaccess.h>
 #include <asm/futex.h>
+#include "uaccess.h"
 
 #ifndef __s390x__
 #define AHI	"ahi"
@@ -28,9 +29,6 @@
 #define SLR	"slgr"
 #endif
 
-extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to);
-extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from);
-
 size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
 {
 	unsigned long tmp1, tmp2;
@@ -72,7 +70,8 @@
 	return size;
 }
 
-size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x)
+static size_t copy_from_user_std_check(size_t size, const void __user *ptr,
+				       void *x)
 {
 	if (size <= 1024)
 		return copy_from_user_std(size, ptr, x);
@@ -110,14 +109,16 @@
 	return size;
 }
 
-size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x)
+static size_t copy_to_user_std_check(size_t size, void __user *ptr,
+				     const void *x)
 {
 	if (size <= 1024)
 		return copy_to_user_std(size, ptr, x);
 	return copy_to_user_pt(size, ptr, x);
 }
 
-size_t copy_in_user_std(size_t size, void __user *to, const void __user *from)
+static size_t copy_in_user_std(size_t size, void __user *to,
+			       const void __user *from)
 {
 	unsigned long tmp1;
 
@@ -148,7 +149,7 @@
 	return size;
 }
 
-size_t clear_user_std(size_t size, void __user *to)
+static size_t clear_user_std(size_t size, void __user *to)
 {
 	unsigned long tmp1, tmp2;
 
@@ -254,12 +255,10 @@
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		  "m" (*uaddr) : "cc");
 
-int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
-	pagefault_disable();
-
 	switch (op) {
 	case FUTEX_OP_SET:
 		__futex_atomic_op("lr %2,%5\n",
@@ -284,12 +283,11 @@
 	default:
 		ret = -ENOSYS;
 	}
-	pagefault_enable();
 	*old = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
 {
 	int ret;
 
@@ -314,6 +312,6 @@
 	.clear_user = clear_user_std,
 	.strnlen_user = strnlen_user_std,
 	.strncpy_from_user = strncpy_from_user_std,
-	.futex_atomic_op = futex_atomic_op,
-	.futex_atomic_cmpxchg = futex_atomic_cmpxchg,
+	.futex_atomic_op = futex_atomic_op_std,
+	.futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
 };
diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile
index c10df14..73b3e72 100644
--- a/arch/s390/math-emu/Makefile
+++ b/arch/s390/math-emu/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the FPU instruction emulation.
 #
 
-obj-$(CONFIG_MATHEMU) := math.o qrnnd.o
+obj-$(CONFIG_MATHEMU) := math.o
 
 EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
 EXTRA_AFLAGS := -traditional
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
index 6b9aec5..3ee78cc 100644
--- a/arch/s390/math-emu/math.c
+++ b/arch/s390/math-emu/math.c
@@ -15,7 +15,7 @@
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
 
-#include "sfp-util.h"
+#include <asm/sfp-util.h>
 #include <math-emu/soft-fp.h>
 #include <math-emu/single.h>
 #include <math-emu/double.h>
diff --git a/arch/s390/math-emu/qrnnd.S b/arch/s390/math-emu/qrnnd.S
deleted file mode 100644
index b01c2b6..0000000
--- a/arch/s390/math-emu/qrnnd.S
+++ /dev/null
@@ -1,77 +0,0 @@
-# S/390 __udiv_qrnnd
-
-# r2 : &__r
-# r3 : upper half of 64 bit word n
-# r4 : lower half of 64 bit word n
-# r5 : divisor d
-# the reminder r of the division is to be stored to &__r and
-# the quotient q is to be returned
-
-        .text
-        .globl __udiv_qrnnd
-__udiv_qrnnd:
-        st    %r2,24(%r15)        # store pointer to reminder for later
-        lr    %r0,%r3             # reload n
-	lr    %r1,%r4
-	ltr   %r2,%r5             # reload and test divisor
-        jp    5f
-        # divisor >= 0x80000000
-	srdl  %r0,2               # n/4
-        srl   %r2,1               # d/2
-        slr   %r1,%r2             # special case if last bit of d is set
-        brc   3,0f                #  (n/4) div (n/2) can overflow by 1
-        ahi   %r0,-1              #  trick: subtract n/2, then divide
-0:      dr    %r0,%r2             # signed division
-        ahi   %r1,1               #  trick part 2: add 1 to the quotient
-        # now (n >> 2) = (d >> 1) * %r1 + %r0
-	lhi   %r3,1
-        nr    %r3,%r1             # test last bit of q
-        jz    1f
-        alr   %r0,%r2             # add (d>>1) to r
-1:      srl   %r1,1               # q >>= 1
-        # now (n >> 2) = (d&-2) * %r1 + %r0
-        lhi   %r3,1
-        nr    %r3,%r5             # test last bit of d
-        jz    2f
-        slr   %r0,%r1             # r -= q
-	brc   3,2f                # borrow ?
-	alr   %r0,%r5             # r += d
-	ahi   %r1,-1
-2:      # now (n >> 2) = d * %r1 + %r0
-        alr   %r1,%r1             # q <<= 1
-        alr   %r0,%r0             # r <<= 1
-        brc   12,3f               # overflow on r ?
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-3:      lhi   %r3,2
-        nr    %r3,%r4             # test next to last bit of n
-        jz    4f
-        ahi   %r0,1               # r += 1
-4:      clr   %r0,%r5             # r >= d ?
-        jl    6f
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-        # now (n >> 1) = d * %r1 + %r0
-        j     6f
-5:      # divisor < 0x80000000
-	srdl  %r0,1
-        dr    %r0,%r2             # signed division
-        # now (n >> 1) = d * %r1 + %r0
-6:      alr   %r1,%r1             # q <<= 1
-        alr   %r0,%r0             # r <<= 1
-        brc   12,7f               # overflow on r ?
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-7:      lhi   %r3,1
-        nr    %r3,%r4             # isolate last bit of n
-        alr   %r0,%r3             # r += (n & 1)
-        clr   %r0,%r5             # r >= d ?
-        jl    8f
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-8:      # now n = d * %r1 + %r0
-	l     %r2,24(%r15)
-        st    %r0,0(%r2)
-        lr    %r2,%r1
-        br    %r14
-	.end	__udiv_qrnnd
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 607f50e..f93a056 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -245,7 +245,7 @@
 	cmm_set_timer();
 }
 
-static inline int
+static int
 cmm_skip_blanks(char *cp, char **endp)
 {
 	char *str;
@@ -414,7 +414,7 @@
 }
 #endif
 
-struct ctl_table_header *cmm_sysctl_header;
+static struct ctl_table_header *cmm_sysctl_header;
 
 static int
 cmm_init (void)
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 775bf19..394980b 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/ctype.h>
+#include <linux/ioport.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/ebcdic.h>
@@ -70,6 +71,7 @@
 struct dcss_segment {
 	struct list_head list;
 	char dcss_name[8];
+	char res_name[15];
 	unsigned long start_addr;
 	unsigned long end;
 	atomic_t ref_count;
@@ -77,6 +79,7 @@
 	unsigned int vm_segtype;
 	struct qrange range[6];
 	int segcnt;
+	struct resource *res;
 };
 
 static DEFINE_MUTEX(dcss_lock);
@@ -88,7 +91,7 @@
  * Create the 8 bytes, ebcdic VM segment name from
  * an ascii name.
  */
-static void inline
+static void
 dcss_mkname(char *name, char *dcss_name)
 {
 	int i;
@@ -303,6 +306,29 @@
 		goto out_free;
 	}
 
+	seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+	if (seg->res == NULL) {
+		rc = -ENOMEM;
+		goto out_shared;
+	}
+	seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+	seg->res->start = seg->start_addr;
+	seg->res->end = seg->end;
+	memcpy(&seg->res_name, seg->dcss_name, 8);
+	EBCASC(seg->res_name, 8);
+	seg->res_name[8] = '\0';
+	strncat(seg->res_name, " (DCSS)", 7);
+	seg->res->name = seg->res_name;
+	rc = seg->vm_segtype;
+	if (rc == SEG_TYPE_SC ||
+	    ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared))
+		seg->res->flags |= IORESOURCE_READONLY;
+	if (request_resource(&iomem_resource, seg->res)) {
+		rc = -EBUSY;
+		kfree(seg->res);
+		goto out_shared;
+	}
+
 	if (do_nonshared)
 		dcss_command = DCSS_LOADNSR;
 	else
@@ -316,12 +342,11 @@
 		rc = dcss_diag_translate_rc (seg->end);
 		dcss_diag(DCSS_PURGESEG, seg->dcss_name,
 				&seg->start_addr, &seg->end);
-		goto out_shared;
+		goto out_resource;
 	}
 	seg->do_nonshared = do_nonshared;
 	atomic_set(&seg->ref_count, 1);
 	list_add(&seg->list, &dcss_list);
-	rc = seg->vm_segtype;
 	*addr = seg->start_addr;
 	*end  = seg->end;
 	if (do_nonshared)
@@ -329,12 +354,16 @@
 				"type %s in non-shared mode\n", name,
 				(void*)seg->start_addr, (void*)seg->end,
 				segtype_string[seg->vm_segtype]);
-	else
+	else {
 		PRINT_INFO ("segment_load: loaded segment %s range %p .. %p "
 				"type %s in shared mode\n", name,
 				(void*)seg->start_addr, (void*)seg->end,
 				segtype_string[seg->vm_segtype]);
+	}
 	goto out;
+ out_resource:
+	release_resource(seg->res);
+	kfree(seg->res);
  out_shared:
 	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
  out_free:
@@ -401,6 +430,7 @@
  * -ENOENT  : no such segment (segment gone!)
  * -EAGAIN  : segment is in use by other exploiters, try later
  * -EINVAL  : no segment with the given name is currently loaded - name invalid
+ * -EBUSY   : segment can temporarily not be used (overlaps with dcss)
  * 0	    : operation succeeded
  */
 int
@@ -428,12 +458,24 @@
 		rc = -EAGAIN;
 		goto out_unlock;
 	}
-	dcss_diag(DCSS_PURGESEG, seg->dcss_name,
-		  &dummy, &dummy);
-	if (do_nonshared)
+	release_resource(seg->res);
+	if (do_nonshared) {
 		dcss_command = DCSS_LOADNSR;
-	else
-	dcss_command = DCSS_LOADNOLY;
+		seg->res->flags &= ~IORESOURCE_READONLY;
+	} else {
+		dcss_command = DCSS_LOADNOLY;
+		if (seg->vm_segtype == SEG_TYPE_SR ||
+		    seg->vm_segtype == SEG_TYPE_ER)
+			seg->res->flags |= IORESOURCE_READONLY;
+	}
+	if (request_resource(&iomem_resource, seg->res)) {
+		PRINT_WARN("segment_modify_shared: could not reload segment %s"
+			   " - overlapping resources\n", name);
+		rc = -EBUSY;
+		kfree(seg->res);
+		goto out_del;
+	}
+	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
 	diag_cc = dcss_diag(dcss_command, seg->dcss_name,
 			&seg->start_addr, &seg->end);
 	if (diag_cc > 1) {
@@ -446,9 +488,9 @@
 	rc = 0;
 	goto out_unlock;
  out_del:
+	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
 	list_del(&seg->list);
-	dcss_diag(DCSS_PURGESEG, seg->dcss_name,
-		  &dummy, &dummy);
+	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
 	kfree(seg);
  out_unlock:
 	mutex_unlock(&dcss_lock);
@@ -478,6 +520,8 @@
 	}
 	if (atomic_dec_return(&seg->ref_count) != 0)
 		goto out_unlock;
+	release_resource(seg->res);
+	kfree(seg->res);
 	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
 	list_del(&seg->list);
 	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index cd85e34..9ff143e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -52,7 +52,7 @@
 extern void die(const char *,struct pt_regs *,long);
 
 #ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
 int register_page_fault_notifier(struct notifier_block *nb)
 {
 	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
@@ -137,7 +137,9 @@
 
 /*
  * Check which address space the address belongs to.
- * Returns 1 for user space and 0 for kernel space.
+ * May return 1 or 2 for user space and 0 for kernel space.
+ * Returns 2 for user space in primary addressing mode with
+ * CONFIG_S390_EXEC_PROTECT on and kernel parameter noexec=on.
  */
 static inline int check_user_space(struct pt_regs *regs, int error_code)
 {
@@ -154,7 +156,7 @@
 		return __check_access_register(regs, error_code);
 	if (descriptor == 2)
 		return current->thread.mm_segment.ar4;
-	return descriptor != 0;
+	return ((descriptor != 0) ^ (switch_amode)) << s390_noexec;
 }
 
 /*
@@ -183,6 +185,77 @@
 	force_sig_info(SIGSEGV, &si, current);
 }
 
+#ifdef CONFIG_S390_EXEC_PROTECT
+extern long sys_sigreturn(struct pt_regs *regs);
+extern long sys_rt_sigreturn(struct pt_regs *regs);
+extern long sys32_sigreturn(struct pt_regs *regs);
+extern long sys32_rt_sigreturn(struct pt_regs *regs);
+
+static inline void do_sigreturn(struct mm_struct *mm, struct pt_regs *regs,
+				int rt)
+{
+	up_read(&mm->mmap_sem);
+	clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+#ifdef CONFIG_COMPAT
+	if (test_tsk_thread_flag(current, TIF_31BIT)) {
+		if (rt)
+			sys32_rt_sigreturn(regs);
+		else
+			sys32_sigreturn(regs);
+		return;
+	}
+#endif /* CONFIG_COMPAT */
+	if (rt)
+		sys_rt_sigreturn(regs);
+	else
+		sys_sigreturn(regs);
+	return;
+}
+
+static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
+			 unsigned long address, unsigned long error_code)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	u16 *instruction;
+	unsigned long pfn, uaddr = regs->psw.addr;
+
+	spin_lock(&mm->page_table_lock);
+	pgd = pgd_offset(mm, uaddr);
+	if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+		goto out_fault;
+	pmd = pmd_offset(pgd, uaddr);
+	if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+		goto out_fault;
+	pte = pte_offset_map(pmd_offset(pgd_offset(mm, uaddr), uaddr), uaddr);
+	if (!pte || !pte_present(*pte))
+		goto out_fault;
+	pfn = pte_pfn(*pte);
+	if (!pfn_valid(pfn))
+		goto out_fault;
+	spin_unlock(&mm->page_table_lock);
+
+	instruction = (u16 *) ((pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE-1)));
+	if (*instruction == 0x0a77)
+		do_sigreturn(mm, regs, 0);
+	else if (*instruction == 0x0aad)
+		do_sigreturn(mm, regs, 1);
+	else {
+		printk("- XXX - do_exception: task = %s, primary, NO EXEC "
+		       "-> SIGSEGV\n", current->comm);
+		up_read(&mm->mmap_sem);
+		current->thread.prot_addr = address;
+		current->thread.trap_no = error_code;
+		do_sigsegv(regs, error_code, SEGV_MAPERR, address);
+	}
+	return 0;
+out_fault:
+	spin_unlock(&mm->page_table_lock);
+	return -EFAULT;
+}
+#endif /* CONFIG_S390_EXEC_PROTECT */
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -260,6 +333,17 @@
         vma = find_vma(mm, address);
         if (!vma)
                 goto bad_area;
+
+#ifdef CONFIG_S390_EXEC_PROTECT
+	if (unlikely((user_address == 2) && !(vma->vm_flags & VM_EXEC)))
+		if (!signal_return(mm, regs, address, error_code))
+			/*
+			 * signal_return() has done an up_read(&mm->mmap_sem)
+			 * if it returns 0.
+			 */
+			return;
+#endif
+
         if (vma->vm_start <= address) 
                 goto good_area;
         if (!(vma->vm_flags & VM_GROWSDOWN))
@@ -452,8 +536,7 @@
 		: : "a" (&refbk), "m" (refbk) : "cc");
 }
 
-asmlinkage void
-pfault_interrupt(__u16 error_code)
+static void pfault_interrupt(__u16 error_code)
 {
 	struct task_struct *tsk;
 	__u16 subcode;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 4bb21be..b3e7c45 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -25,7 +25,7 @@
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
 #include <linux/poison.h>
-
+#include <linux/initrd.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -95,20 +95,18 @@
 	pte_t new_pte;
 	unsigned long address, end;
 
-	address = ((unsigned long)&__start_rodata) & PAGE_MASK;
-	end = PFN_ALIGN((unsigned long)&__end_rodata);
+	address = ((unsigned long)&_stext) & PAGE_MASK;
+	end = PFN_ALIGN((unsigned long)&_eshared);
 
 	for (; address < end; address += PAGE_SIZE) {
 		pgd = pgd_offset_k(address);
 		pmd = pmd_offset(pgd, address);
 		pte = pte_offset_kernel(pmd, address);
 		new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
-		set_pte(pte, new_pte);
+		*pte = new_pte;
 	}
 }
 
-extern void vmem_map_init(void);
-
 /*
  * paging_init() sets up the page tables
  */
@@ -125,11 +123,11 @@
 #ifdef CONFIG_64BIT
 	pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE;
 	for (i = 0; i < PTRS_PER_PGD; i++)
-		pgd_clear(pg_dir + i);
+		pgd_clear_kernel(pg_dir + i);
 #else
 	pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
 	for (i = 0; i < PTRS_PER_PGD; i++)
-		pmd_clear((pmd_t *)(pg_dir + i));
+		pmd_clear_kernel((pmd_t *)(pg_dir + i));
 #endif
 	vmem_map_init();
 	setup_ro_region();
@@ -174,10 +172,8 @@
                 datasize >>10,
                 initsize >> 10);
 	printk("Write protected kernel read-only data: %#lx - %#lx\n",
-	       (unsigned long)&__start_rodata,
-	       PFN_ALIGN((unsigned long)&__end_rodata) - 1);
-	printk("Virtual memmap size: %ldk\n",
-	       (max_pfn * sizeof(struct page)) >> 10);
+	       (unsigned long)&_stext,
+	       PFN_ALIGN((unsigned long)&_eshared) - 1);
 }
 
 void free_initmem(void)
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 7f2944d..92a5651 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -61,7 +61,8 @@
 
 		if (map_start < map_end)
 			memmap_init_zone((unsigned long)(map_end - map_start),
-					 nid, zone, page_to_pfn(map_start));
+					 nid, zone, page_to_pfn(map_start),
+					 MEMMAP_EARLY);
 	}
 }
 
@@ -81,7 +82,7 @@
 	if (!pmd)
 		return NULL;
 	for (i = 0; i < PTRS_PER_PMD; i++)
-		pmd_clear(pmd + i);
+		pmd_clear_kernel(pmd + i);
 	return pmd;
 }
 
@@ -96,7 +97,7 @@
 		return NULL;
 	pte_val(empty_pte) = _PAGE_TYPE_EMPTY;
 	for (i = 0; i < PTRS_PER_PTE; i++)
-		set_pte(pte + i, empty_pte);
+		pte[i] = empty_pte;
 	return pte;
 }
 
@@ -118,7 +119,7 @@
 			pm_dir = vmem_pmd_alloc();
 			if (!pm_dir)
 				goto out;
-			pgd_populate(&init_mm, pg_dir, pm_dir);
+			pgd_populate_kernel(&init_mm, pg_dir, pm_dir);
 		}
 
 		pm_dir = pmd_offset(pg_dir, address);
@@ -131,7 +132,7 @@
 
 		pt_dir = pte_offset_kernel(pm_dir, address);
 		pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL);
-		set_pte(pt_dir, pte);
+		*pt_dir = pte;
 	}
 	ret = 0;
 out:
@@ -160,7 +161,7 @@
 		if (pmd_none(*pm_dir))
 			continue;
 		pt_dir = pte_offset_kernel(pm_dir, address);
-		set_pte(pt_dir, pte);
+		*pt_dir = pte;
 	}
 	flush_tlb_kernel_range(start, start + size);
 }
@@ -190,7 +191,7 @@
 			pm_dir = vmem_pmd_alloc();
 			if (!pm_dir)
 				goto out;
-			pgd_populate(&init_mm, pg_dir, pm_dir);
+			pgd_populate_kernel(&init_mm, pg_dir, pm_dir);
 		}
 
 		pm_dir = pmd_offset(pg_dir, address);
@@ -209,7 +210,7 @@
 			if (!new_page)
 				goto out;
 			pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
-			set_pte(pt_dir, pte);
+			*pt_dir = pte;
 		}
 	}
 	ret = 0;
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 89a28cc..113bd48 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -54,6 +54,7 @@
  * handler when auxio is not present-- unused for now...
  */
 void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
 
 /*
  * sysctl - toggle power-off restriction for serial console 
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 276f228..6b5f26b 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -292,8 +292,8 @@
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	extern void smp4m_boot_cpus(void);
-	extern void smp4d_boot_cpus(void);
+	extern void __init smp4m_boot_cpus(void);
+	extern void __init smp4d_boot_cpus(void);
 	int i, cpuid, extra;
 
 	printk("Entering SMP Mode...\n");
@@ -375,8 +375,8 @@
 
 int __cpuinit __cpu_up(unsigned int cpu)
 {
-	extern int smp4m_boot_one_cpu(int);
-	extern int smp4d_boot_one_cpu(int);
+	extern int __cpuinit smp4m_boot_one_cpu(int);
+	extern int __cpuinit smp4d_boot_one_cpu(int);
 	int ret=0;
 
 	switch(sparc_cpu_model) {
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index c80ea61..c69de5d 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -164,7 +164,7 @@
 	local_flush_cache_all();
 }
 
-int smp4d_boot_one_cpu(int i)
+int __cpuinit smp4d_boot_one_cpu(int i)
 {
 			extern unsigned long sun4d_cpu_startup;
 			unsigned long *entry = &sun4d_cpu_startup;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 0a49585..fc99f7b 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1388,7 +1388,7 @@
 {
 }
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	int ret = smp_boot_one_cpu(cpu);
 
diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S
index b731881..9871dbb 100644
--- a/arch/sparc64/kernel/sun4v_tlb_miss.S
+++ b/arch/sparc64/kernel/sun4v_tlb_miss.S
@@ -142,9 +142,9 @@
 	rdpr	%tl, %g1
 	cmp	%g1, 1
 	bgu,pn	%xcc, winfix_trampoline
-	 nop
-	ba,pt	%xcc, sparc64_realfault_common
 	 mov	FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
+	ba,pt	%xcc, sparc64_realfault_common
+	 nop
 
 	/* Called from trap table:
 	 * %g4:	vaddr
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index f191a55..d6cffb2 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -19,31 +19,31 @@
 choice
 	prompt "Host memory split"
 	default HOST_VMSPLIT_3G
-	---help---
-	   This is needed when the host kernel on which you run has a non-default
-	   (like 2G/2G) memory split, instead of the customary 3G/1G. If you did
-	   not recompile your own kernel but use the default distro's one, you can
-	   safely accept the "Default split" option.
+	help
+        This is needed when the host kernel on which you run has a non-default
+	(like 2G/2G) memory split, instead of the customary 3G/1G. If you did
+	not recompile your own kernel but use the default distro's one, you can
+	safely accept the "Default split" option.
 
-	   It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via
-	   CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck
-	   patchset by Con Kolivas, or other ones) - option names match closely the
-	   host CONFIG_VM_SPLIT_* ones.
+	It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via
+	CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck
+	patchset by Con Kolivas, or other ones) - option names match closely the
+	host CONFIG_VM_SPLIT_* ones.
 
-	   A lower setting (where 1G/3G is lowest and 3G/1G is higher) will
-	   tolerate even more "normal" host kernels, but an higher setting will be
-	   stricter.
+	A lower setting (where 1G/3G is lowest and 3G/1G is higher) will
+	tolerate even more "normal" host kernels, but an higher setting will be
+	stricter.
 
-	   So, if you do not know what to do here, say 'Default split'.
+	So, if you do not know what to do here, say 'Default split'.
 
-	config HOST_VMSPLIT_3G
-		bool "Default split (3G/1G user/kernel host split)"
-	config HOST_VMSPLIT_3G_OPT
-		bool "3G/1G user/kernel host split (for full 1G low memory)"
-	config HOST_VMSPLIT_2G
-		bool "2G/2G user/kernel host split"
-	config HOST_VMSPLIT_1G
-		bool "1G/3G user/kernel host split"
+config HOST_VMSPLIT_3G
+	bool "Default split (3G/1G user/kernel host split)"
+config HOST_VMSPLIT_3G_OPT
+	bool "3G/1G user/kernel host split (for full 1G low memory)"
+config HOST_VMSPLIT_2G
+	bool "2G/2G user/kernel host split"
+config HOST_VMSPLIT_1G
+	bool "1G/3G user/kernel host split"
 endchoice
 
 config TOP_ADDR
@@ -67,13 +67,13 @@
 
 config STUB_CODE
 	hex
-	default 0xbfffe000 if !HOST_2G_2G
-	default 0x7fffe000 if HOST_2G_2G
+	default 0xbfffe000 if !HOST_VMSPLIT_2G
+	default 0x7fffe000 if HOST_VMSPLIT_2G
 
 config STUB_DATA
 	hex
-	default 0xbffff000 if !HOST_2G_2G
-	default 0x7ffff000 if HOST_2G_2G
+	default 0xbffff000 if !HOST_VMSPLIT_2G
+	default 0x7ffff000 if HOST_VMSPLIT_2G
 
 config STUB_START
 	hex
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 0709fc6..3f6acd6 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -219,7 +219,8 @@
 	unsigned long save_sp = PT_REGS_SP(regs);
 	int err = 0;
 
-	stack_top &= -8UL;
+	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
+	stack_top = ((stack_top + 4) & -16UL) - 4;
 	frame = (struct sigframe __user *) stack_top - 1;
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return 1;
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 9edf114..af2f017 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -191,8 +191,9 @@
 	struct task_struct *me = current;
 
 	frame = (struct rt_sigframe __user *)
-		round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
-        frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128);
+		round_down(stack_top - sizeof(struct rt_sigframe), 16);
+	/* Subtract 128 for a red zone and 8 for proper alignment */
+        frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
 
 	if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
 		goto out;
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 9cc7c21..69584c2 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-git14
-# Sat Dec  9 21:23:09 2006
+# Linux kernel version: 2.6.20-rc3
+# Fri Jan  5 11:54:41 2007
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1056,6 +1056,7 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -1066,6 +1067,7 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
@@ -1311,6 +1313,11 @@
 #
 
 #
+# Virtualization
+#
+# CONFIG_KVM is not set
+
+#
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
@@ -1502,6 +1509,8 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_DETECT_SOFTLOCKUP=y
@@ -1519,12 +1528,10 @@
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_FORCED_INLINING is not set
-# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_DEBUG_RODATA is not set
@@ -1553,3 +1560,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index be87df5..fe83edb 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -241,7 +241,7 @@
 			get_user(c,p++);
 		} while (c);
 	}
-	put_user(NULL,argv);
+	put_user(0, argv);
 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 	while (envc-->0) {
 		char c;
@@ -250,7 +250,7 @@
 			get_user(c,p++);
 		} while (c);
 	}
-	put_user(NULL,envp);
+	put_user(0, envp);
 	current->mm->env_end = (unsigned long) p;
 	return sp;
 }
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 543ef4f..5ce0bd4 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -64,55 +64,6 @@
 #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents.  Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS	(find_vma(current->mm, VSYSCALL32_BASE) ?     \
-    (VSYSCALL32_EHDR->e_phnum) : 0)
-#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
-do {									      \
-	if (find_vma(current->mm, VSYSCALL32_BASE)) { 			      \
-		const struct elf32_phdr *const vsyscall_phdrs =		      \
-			(const struct elf32_phdr *) (VSYSCALL32_BASE	      \
-						   + VSYSCALL32_EHDR->e_phoff);\
-		int i;							      \
-		Elf32_Off ofs = 0;					      \
-		for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) {	      \
-			struct elf32_phdr phdr = vsyscall_phdrs[i];	      \
-			if (phdr.p_type == PT_LOAD) {			      \
-				BUG_ON(ofs != 0);			      \
-				ofs = phdr.p_offset = offset;		      \
-				phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);      \
-				phdr.p_filesz = phdr.p_memsz;		      \
-				offset += phdr.p_filesz;		      \
-			}						      \
-			else						      \
-				phdr.p_offset += ofs;			      \
-			phdr.p_paddr = 0; /* match other core phdrs */	      \
-			DUMP_WRITE(&phdr, sizeof(phdr));		      \
-		}							      \
-	}								      \
-} while (0)
-#define ELF_CORE_WRITE_EXTRA_DATA					      \
-do {									      \
-	if (find_vma(current->mm, VSYSCALL32_BASE)) { 			      \
-		const struct elf32_phdr *const vsyscall_phdrs =		      \
-			(const struct elf32_phdr *) (VSYSCALL32_BASE	      \
-						   + VSYSCALL32_EHDR->e_phoff);      \
-		int i;							      \
-		for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) {	      \
-			if (vsyscall_phdrs[i].p_type == PT_LOAD)	      \
-				DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
-				    PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));   \
-		}							      \
-	}								      \
-} while (0)
-
 struct elf_siginfo
 {
 	int	si_signo;			/* signal number */
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index 3e5ed20..59f1fa1 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -59,6 +59,13 @@
 	vma->vm_end = VSYSCALL32_END;
 	/* MAYWRITE to allow gdb to COW and set breakpoints */
 	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	vma->vm_flags |= VM_ALWAYSDUMP;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
 	vma->vm_ops = &syscall32_vm_ops;
@@ -75,6 +82,14 @@
 	return 0;
 }
 
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_start == VSYSCALL32_BASE &&
+	    vma->vm_mm && vma->vm_mm->task_size == IA32_PAGE_OFFSET)
+		return "[vdso]";
+	return NULL;
+}
+
 static int __init init_syscall32(void)
 { 
 	syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); 
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 186aebb..9cb42ec 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -302,8 +302,6 @@
 	if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
 		return 0;
 
-	if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
-		return 0;  /* no lapic support */
 	nmi_watchdog = nmi;
 	return 1;
 }
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 87d90cb..3d65b1d 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -1068,6 +1068,8 @@
 	if (!early_pci_allowed())
 		return;
 
+	printk(KERN_DEBUG "Calgary: detecting Calgary via BIOS EBDA area\n");
+
 	ptr = (unsigned long)phys_to_virt(get_bios_ebda());
 
 	rio_table_hdr = NULL;
@@ -1088,14 +1090,14 @@
 		offset = *((unsigned short *)(ptr + offset));
 	}
 	if (!rio_table_hdr) {
-		printk(KERN_ERR "Calgary: Unable to locate "
-				"Rio Grande Table in EBDA - bailing!\n");
+		printk(KERN_DEBUG "Calgary: Unable to locate Rio Grande table "
+		       "in EBDA - bailing!\n");
 		return;
 	}
 
 	ret = build_detail_arrays();
 	if (ret) {
-		printk(KERN_ERR "Calgary: build_detail_arrays ret %d\n", ret);
+		printk(KERN_DEBUG "Calgary: build_detail_arrays ret %d\n", ret);
 		return;
 	}
 
@@ -1128,6 +1130,9 @@
 		}
 	}
 
+	printk(KERN_DEBUG "Calgary: finished detection, Calgary %s\n",
+	       calgary_found ? "found" : "not found");
+
 	if (calgary_found) {
 		iommu_detected = 1;
 		calgary_detected = 1;
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index 697f0aa..eb18be5 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -29,7 +29,7 @@
 	.dma_supported = NULL,
 };
 
-void pci_swiotlb_init(void)
+void __init pci_swiotlb_init(void)
 {
 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
 	if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN)
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 9f05bc9..5cc76d0 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -656,6 +656,25 @@
  */
 
 #define TICK_COUNT 100000000
+#define TICK_MIN   5000
+
+/*
+ * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
+ * occurs between the reads of the hpet & TSC.
+ */
+static void __init read_hpet_tsc(int *hpet, int *tsc)
+{
+	int tsc1, tsc2, hpet1;
+
+	do {
+		tsc1 = get_cycles_sync();
+		hpet1 = hpet_readl(HPET_COUNTER);
+		tsc2 = get_cycles_sync();
+	} while (tsc2 - tsc1 > TICK_MIN);
+	*hpet = hpet1;
+	*tsc = tsc2;
+}
+
 
 static unsigned int __init hpet_calibrate_tsc(void)
 {
@@ -666,13 +685,11 @@
 	local_irq_save(flags);
 	local_irq_disable();
 
-	hpet_start = hpet_readl(HPET_COUNTER);
-	rdtscl(tsc_start);
+	read_hpet_tsc(&hpet_start, &tsc_start);
 
 	do {
 		local_irq_disable();
-		hpet_now = hpet_readl(HPET_COUNTER);
-		tsc_now = get_cycles_sync();
+		read_hpet_tsc(&hpet_now, &tsc_now);
 		local_irq_restore(flags);
 	} while ((tsc_now - tsc_start) < TICK_COUNT &&
 		 (hpet_now - hpet_start) < TICK_COUNT);
diff --git a/block/elevator.c b/block/elevator.c
index 536be74..f6dafa8 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -590,6 +590,12 @@
 		 */
 		rq->cmd_flags |= REQ_SOFTBARRIER;
 
+		/*
+		 * Most requeues happen because of a busy condition,
+		 * don't force unplug of the queue for that case.
+		 */
+		unplug_it = 0;
+
 		if (q->ordseq == 0) {
 			list_add(&rq->queuelist, &q->queue_head);
 			break;
@@ -604,11 +610,6 @@
 		}
 
 		list_add_tail(&rq->queuelist, pos);
-		/*
-		 * most requeues happen because of a busy condition, don't
-		 * force unplug of the queue for that case.
-		 */
-		unplug_it = 0;
 		break;
 
 	default:
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 2528a0c..65c6a3c 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -223,7 +223,7 @@
 static int sg_io(struct file *file, request_queue_t *q,
 		struct gendisk *bd_disk, struct sg_io_hdr *hdr)
 {
-	unsigned long start_time;
+	unsigned long start_time, timeout;
 	int writing = 0, ret = 0;
 	struct request *rq;
 	char sense[SCSI_SENSE_BUFFERSIZE];
@@ -271,7 +271,8 @@
 
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 
-	rq->timeout = jiffies_to_msecs(hdr->timeout);
+	timeout = msecs_to_jiffies(hdr->timeout);
+	rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
 	if (!rq->timeout)
 		rq->timeout = q->sg_timeout;
 	if (!rq->timeout)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 92ba249..918b4d8 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -74,14 +74,6 @@
 	help
 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 
-config CRYPTO_SHA1_S390
-	tristate "SHA1 digest algorithm (s390)"
-	depends on S390
-	select CRYPTO_ALGAPI
-	help
-	  This is the s390 hardware accelerated implementation of the
-	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
-
 config CRYPTO_SHA256
 	tristate "SHA256 digest algorithm"
 	select CRYPTO_ALGAPI
@@ -91,17 +83,6 @@
 	  This version of SHA implements a 256 bit hash with 128 bits of
 	  security against collision attacks.
 
-config CRYPTO_SHA256_S390
-	tristate "SHA256 digest algorithm (s390)"
-	depends on S390
-	select CRYPTO_ALGAPI
-	help
-	  This is the s390 hardware accelerated implementation of the
-	  SHA256 secure hash standard (DFIPS 180-2).
-
-	  This version of SHA implements a 256 bit hash with 128 bits of
-	  security against collision attacks.
-
 config CRYPTO_SHA512
 	tristate "SHA384 and SHA512 digest algorithms"
 	select CRYPTO_ALGAPI
@@ -187,14 +168,6 @@
 	help
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
-config CRYPTO_DES_S390
-	tristate "DES and Triple DES cipher algorithms (s390)"
-	depends on S390
-	select CRYPTO_ALGAPI
-	select CRYPTO_BLKCIPHER
-	help
-	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
-
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -336,28 +309,6 @@
 
 	  See <http://csrc.nist.gov/encryption/aes/> for more information.
 
-config CRYPTO_AES_S390
-	tristate "AES cipher algorithms (s390)"
-	depends on S390
-	select CRYPTO_ALGAPI
-	select CRYPTO_BLKCIPHER
-	help
-	  This is the s390 hardware accelerated implementation of the
-	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
-	  algorithm.
-
-	  Rijndael appears to be consistently a very good performer in
-	  both hardware and software across a wide range of computing
-	  environments regardless of its use in feedback or non-feedback
-	  modes. Its key setup time is excellent, and its key agility is
-	  good. Rijndael's very low memory requirements make it very well
-	  suited for restricted-space environments, in which it also
-	  demonstrates excellent performance. Rijndael's operations are
-	  among the easiest to defend against power and timing attacks.
-
-	  On s390 the System z9-109 currently only supports the key size
-	  of 128 bit.
-
 config CRYPTO_CAST5
 	tristate "CAST5 (CAST-128) cipher algorithm"
 	select CRYPTO_ALGAPI
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 1639998..f4f000a 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -225,17 +225,6 @@
 
 	  If you are not sure, say N here.
 
-config ACPI_IBM_BAY
-	bool "Legacy Removable Bay Support"
-	depends on ACPI_IBM
-	depends on ACPI_BAY=n
-	default n
-	---help---
-	  Allows the ibm_acpi driver to handle removable bays.
-	  This support is obsoleted by CONFIG_ACPI_BAY.
-
-	  If you are not sure, say N here.
-
 config ACPI_TOSHIBA
 	tristate "Toshiba Laptop Extras"
 	depends on X86
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 279c4ba..766332e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -561,6 +561,9 @@
 	case ACPI_IRQ_MODEL_IOSAPIC:
 		message = "IOSAPIC";
 		break;
+	case ACPI_IRQ_MODEL_PLATFORM:
+		message = "platform specific model";
+		break;
 	default:
 		printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
 		return -ENODEV;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 4144d5d..cbdf031 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1016,8 +1016,8 @@
 		acpi_ec_mode = EC_POLL;
 	}
 	acpi_ec_driver.ops.add = acpi_ec_add;
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n",
-			  intr ? "interrupt" : "polling"));
+	printk(KERN_NOTICE PREFIX "%s mode.\n",
+			  intr ? "interrupt" : "polling");
 
 	return 1;
 }
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index b72d13d..c6144ca 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -157,7 +157,6 @@
 	   "\\_SB.PCI.ISA.SLCE",	/* 570 */
     );				/* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
 #endif
-#ifdef CONFIG_ACPI_IBM_BAY
 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",	/* 570 */
 	   "\\_SB.PCI0.IDE0.IDES.IDSM",	/* 600e/x, 770e, 770x */
 	   "\\_SB.PCI0.SATA.SCND.MSTR",	/* T60, X60, Z60 */ 
@@ -175,7 +174,6 @@
 IBM_HANDLE(bay2_ej, bay2, "_EJ3",	/* 600e/x, 770e, A3x */
 	   "_EJ0",		/* 770x */
     );				/* all others */
-#endif
 
 /* don't list other alternatives as we install a notify handler on the 570 */
 IBM_HANDLE(pci, root, "\\_SB.PCI");	/* 570 */
@@ -1042,7 +1040,6 @@
 	return 0;
 }
 
-#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
 static int _sta(acpi_handle handle)
 {
 	int status;
@@ -1052,7 +1049,7 @@
 
 	return status;
 }
-#endif
+
 #ifdef CONFIG_ACPI_IBM_DOCK
 #define dock_docked() (_sta(dock_handle) & 1)
 
@@ -1118,7 +1115,6 @@
 }
 #endif
 
-#ifdef CONFIG_ACPI_IBM_BAY
 static int bay_status_supported;
 static int bay_status2_supported;
 static int bay_eject_supported;
@@ -1194,7 +1190,6 @@
 {
 	acpi_bus_generate_event(ibm->device, event, 0);
 }
-#endif
 
 static int cmos_read(char *p)
 {
@@ -2354,7 +2349,6 @@
 	 .type = ACPI_SYSTEM_NOTIFY,
 	 },
 #endif
-#ifdef CONFIG_ACPI_IBM_BAY
 	{
 	 .name = "bay",
 	 .init = bay_init,
@@ -2364,7 +2358,6 @@
 	 .handle = &bay_handle,
 	 .type = ACPI_SYSTEM_NOTIFY,
 	 },
-#endif
 	{
 	 .name = "cmos",
 	 .read = cmos_read,
@@ -2650,9 +2643,7 @@
 #ifdef CONFIG_ACPI_IBM_DOCK
 IBM_PARAM(dock);
 #endif
-#ifdef CONFIG_ACPI_IBM_BAY
 IBM_PARAM(bay);
-#endif
 IBM_PARAM(cmos);
 IBM_PARAM(led);
 IBM_PARAM(beep);
@@ -2735,14 +2726,12 @@
 	IBM_HANDLE_INIT(dock);
 #endif
 	IBM_HANDLE_INIT(pci);
-#ifdef CONFIG_ACPI_IBM_BAY
 	IBM_HANDLE_INIT(bay);
 	if (bay_handle)
 		IBM_HANDLE_INIT(bay_ej);
 	IBM_HANDLE_INIT(bay2);
 	if (bay2_handle)
 		IBM_HANDLE_INIT(bay2_ej);
-#endif
 	IBM_HANDLE_INIT(beep);
 	IBM_HANDLE_INIT(ecrd);
 	IBM_HANDLE_INIT(ecwr);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 25718fe..5f9496d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -476,9 +476,6 @@
 	if (cpu_index == -1) {
 		if (ACPI_FAILURE
 		    (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
-			printk(KERN_ERR PREFIX
-				    "Getting cpuindex for acpiid 0x%x\n",
-				    pr->acpi_id);
 			return -ENODEV;
 		}
 	}
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 0e60382..cbb6f08 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -322,10 +322,6 @@
 	if (result)
 		return result;
 
-	result = acpi_processor_get_platform_limit(pr);
-	if (result)
-		return result;
-
 	return 0;
 }
 
@@ -736,10 +732,6 @@
 	}
 
 err_ret:
-	if (retval) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n"));
-	}
-
 	for_each_possible_cpu(i) {
 		pr = processors[i];
 		if (!pr || !pr->performance)
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 36b37d7..3d54680 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1677,8 +1677,6 @@
 	struct acpi_video_device *video_device = data;
 	struct acpi_device *device = NULL;
 
-
-	printk("video device notify\n");
 	if (!video_device)
 		return;
 
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index da21552..1c94b43 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -19,6 +19,10 @@
 
 if ATA
 
+config ATA_NONSTANDARD
+       bool
+       default n
+
 config SATA_AHCI
 	tristate "AHCI SATA support"
 	depends on PCI
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index b517d24..48616c6 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -75,6 +75,7 @@
 	AHCI_CMD_CLR_BUSY	= (1 << 10),
 
 	RX_FIS_D2H_REG		= 0x40,	/* offset of D2H Register FIS data */
+	RX_FIS_SDB		= 0x58, /* offset of SDB FIS data */
 	RX_FIS_UNK		= 0x60, /* offset of Unknown FIS data */
 
 	board_ahci		= 0,
@@ -202,6 +203,10 @@
 	dma_addr_t		cmd_tbl_dma;
 	void			*rx_fis;
 	dma_addr_t		rx_fis_dma;
+	/* for NCQ spurious interrupt analysis */
+	int			ncq_saw_spurious_sdb_cnt;
+	unsigned int		ncq_saw_d2h:1;
+	unsigned int		ncq_saw_dmas:1;
 };
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -361,7 +366,7 @@
 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
-	{ PCI_VDEVICE(AL, 0x5288), board_ahci }, /* ULi M5288 */
+	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
@@ -586,35 +591,18 @@
 {
 	u32 cmd, scontrol;
 
+	if (!(cap & HOST_CAP_SSS))
+		return;
+
+	/* put device into listen mode, first set PxSCTL.DET to 0 */
+	scontrol = readl(port_mmio + PORT_SCR_CTL);
+	scontrol &= ~0xf;
+	writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+	/* then set PxCMD.SUD to 0 */
 	cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
-
-	if (cap & HOST_CAP_SSC) {
-		/* enable transitions to slumber mode */
-		scontrol = readl(port_mmio + PORT_SCR_CTL);
-		if ((scontrol & 0x0f00) > 0x100) {
-			scontrol &= ~0xf00;
-			writel(scontrol, port_mmio + PORT_SCR_CTL);
-		}
-
-		/* put device into slumber mode */
-		writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
-
-		/* wait for the transition to complete */
-		ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
-				  PORT_CMD_ICC_SLUMBER, 1, 50);
-	}
-
-	/* put device into listen mode */
-	if (cap & HOST_CAP_SSS) {
-		/* first set PxSCTL.DET to 0 */
-		scontrol = readl(port_mmio + PORT_SCR_CTL);
-		scontrol &= ~0xf;
-		writel(scontrol, port_mmio + PORT_SCR_CTL);
-
-		/* then set PxCMD.SUD to 0 */
-		cmd &= ~PORT_CMD_SPIN_UP;
-		writel(cmd, port_mmio + PORT_CMD);
-	}
+	cmd &= ~PORT_CMD_SPIN_UP;
+	writel(cmd, port_mmio + PORT_CMD);
 }
 
 static void ahci_init_port(void __iomem *port_mmio, u32 cap,
@@ -915,7 +903,7 @@
 
 	/* clear D2H reception area to properly wait for D2H FIS */
 	ata_tf_init(ap->device, &tf);
-	tf.command = 0xff;
+	tf.command = 0x80;
 	ata_tf_to_fis(&tf, d2h_fis, 0);
 
 	rc = sata_std_hardreset(ap, class);
@@ -1126,8 +1114,9 @@
 	void __iomem *mmio = ap->host->mmio_base;
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	struct ata_eh_info *ehi = &ap->eh_info;
+	struct ahci_port_priv *pp = ap->private_data;
 	u32 status, qc_active;
-	int rc;
+	int rc, known_irq = 0;
 
 	status = readl(port_mmio + PORT_IRQ_STAT);
 	writel(status, port_mmio + PORT_IRQ_STAT);
@@ -1154,17 +1143,53 @@
 
 	/* hmmm... a spurious interupt */
 
-	/* some devices send D2H reg with I bit set during NCQ command phase */
-	if (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS))
+	/* if !NCQ, ignore.  No modern ATA device has broken HSM
+	 * implementation for non-NCQ commands.
+	 */
+	if (!ap->sactive)
 		return;
 
-	/* ignore interim PIO setup fis interrupts */
-	if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS))
-		return;
+	if (status & PORT_IRQ_D2H_REG_FIS) {
+		if (!pp->ncq_saw_d2h)
+			ata_port_printk(ap, KERN_INFO,
+				"D2H reg with I during NCQ, "
+				"this message won't be printed again\n");
+		pp->ncq_saw_d2h = 1;
+		known_irq = 1;
+	}
 
-	if (ata_ratelimit())
+	if (status & PORT_IRQ_DMAS_FIS) {
+		if (!pp->ncq_saw_dmas)
+			ata_port_printk(ap, KERN_INFO,
+				"DMAS FIS during NCQ, "
+				"this message won't be printed again\n");
+		pp->ncq_saw_dmas = 1;
+		known_irq = 1;
+	}
+
+	if (status & PORT_IRQ_SDB_FIS &&
+		   pp->ncq_saw_spurious_sdb_cnt < 10) {
+		/* SDB FIS containing spurious completions might be
+		 * dangerous, we need to know more about them.  Print
+		 * more of it.
+		 */
+		const u32 *f = pp->rx_fis + RX_FIS_SDB;
+
+		ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ "
+				"issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n",
+				readl(port_mmio + PORT_CMD_ISSUE),
+				readl(port_mmio + PORT_SCR_ACT),
+				le32_to_cpu(f[0]), le32_to_cpu(f[1]),
+				pp->ncq_saw_spurious_sdb_cnt < 10 ?
+				"" : ", shutting up");
+
+		pp->ncq_saw_spurious_sdb_cnt++;
+		known_irq = 1;
+	}
+
+	if (!known_irq)
 		ata_port_printk(ap, KERN_INFO, "spurious interrupt "
-				"(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
+				"(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n",
 				status, ap->active_tag, ap->sactive);
 }
 
@@ -1257,7 +1282,7 @@
 	/* clear IRQ */
 	tmp = readl(port_mmio + PORT_IRQ_STAT);
 	writel(tmp, port_mmio + PORT_IRQ_STAT);
-	writel(1 << ap->id, mmio + HOST_IRQ_STAT);
+	writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
 
 	/* turn IRQ back on */
 	writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 908751d..24af560 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -64,6 +64,7 @@
 /**
  *	generic_set_mode	-	mode setting
  *	@ap: interface to set up
+ *	@unused: returned device on error
  *
  *	Use a non standard set_mode function. We don't want to be tuned.
  *	The BIOS configured everything. Our job is not to fiddle. We
@@ -71,7 +72,7 @@
  *	and respect them.
  */
 
-static void generic_set_mode(struct ata_port *ap)
+static int generic_set_mode(struct ata_port *ap, struct ata_device **unused)
 {
 	int dma_enabled = 0;
 	int i;
@@ -82,7 +83,7 @@
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
-		if (ata_dev_enabled(dev)) {
+		if (ata_dev_ready(dev)) {
 			/* We don't really care */
 			dev->pio_mode = XFER_PIO_0;
 			dev->dma_mode = XFER_MW_DMA_0;
@@ -99,6 +100,7 @@
 			}
 		}
 	}
+	return 0;
 }
 
 static struct scsi_host_template generic_sht = {
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 0d51d13..667acd2 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1037,7 +1037,7 @@
 		 * the PIO timing number for the maximum. Turn it into
 		 * a mask.
 		 */
-		u8 mode = id[ATA_ID_OLD_PIO_MODES] & 0xFF;
+		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
 		if (mode < 5)	/* Valid PIO range */
                 	pio_mask = (2 << mode) - 1;
 		else
@@ -1250,6 +1250,7 @@
 
 		ata_sg_init(qc, sg, n_elem);
 		qc->nsect = buflen / ATA_SECT_SIZE;
+		qc->nbytes = buflen;
 	}
 
 	qc->private_data = &wait;
@@ -2431,18 +2432,8 @@
 	int i, rc = 0, used_dma = 0, found = 0;
 
 	/* has private set_mode? */
-	if (ap->ops->set_mode) {
-		/* FIXME: make ->set_mode handle no device case and
-		 * return error code and failing device on failure.
-		 */
-		for (i = 0; i < ATA_MAX_DEVICES; i++) {
-			if (ata_dev_ready(&ap->device[i])) {
-				ap->ops->set_mode(ap);
-				break;
-			}
-		}
-		return 0;
-	}
+	if (ap->ops->set_mode)
+		return ap->ops->set_mode(ap, r_failed_dev);
 
 	/* step 1: calculate xfer_mask */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 08ad44b..7484358 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1796,7 +1796,7 @@
 		*r_failed_dev = dev;
 
 	DPRINTK("EXIT\n");
-	return 0;
+	return rc;
 }
 
 /**
@@ -1979,6 +1979,10 @@
 
 		ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
 
+		/* collect port action mask recorded in dev actions */
+		ehc->i.action |= ehc->i.dev_action[i] & ~ATA_EH_PERDEV_MASK;
+		ehc->i.dev_action[i] &= ATA_EH_PERDEV_MASK;
+
 		/* process hotplug request */
 		if (dev->flags & ATA_DFLAG_DETACH)
 			ata_eh_detach_dev(dev);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 836947d..73902d3 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -273,8 +273,8 @@
 {
 	int rc = 0;
 	u8 scsi_cmd[MAX_COMMAND_SIZE];
-	u8 args[7];
-	struct scsi_sense_hdr sshdr;
+	u8 args[7], *sensebuf = NULL;
+	int cmd_result;
 
 	if (arg == NULL)
 		return -EINVAL;
@@ -282,10 +282,14 @@
 	if (copy_from_user(args, arg, sizeof(args)))
 		return -EFAULT;
 
+	sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+	if (!sensebuf)
+		return -ENOMEM;
+
 	memset(scsi_cmd, 0, sizeof(scsi_cmd));
 	scsi_cmd[0]  = ATA_16;
 	scsi_cmd[1]  = (3 << 1); /* Non-data */
-	/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+	scsi_cmd[2]  = 0x20;     /* cc but no off.line or data xfer */
 	scsi_cmd[4]  = args[1];
 	scsi_cmd[6]  = args[2];
 	scsi_cmd[8]  = args[3];
@@ -295,11 +299,46 @@
 
 	/* Good values for timeout and retries?  Values below
 	   from scsi_ioctl_send_command() for default case... */
-	if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
-			     (10*HZ), 5))
-		rc = -EIO;
+	cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0,
+				sensebuf, (10*HZ), 5, 0);
 
-	/* Need code to retrieve data from check condition? */
+	if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
+		u8 *desc = sensebuf + 8;
+		cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
+
+		/* If we set cc then ATA pass-through will cause a
+		 * check condition even if no error. Filter that. */
+		if (cmd_result & SAM_STAT_CHECK_CONDITION) {
+			struct scsi_sense_hdr sshdr;
+			scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
+						&sshdr);
+			if (sshdr.sense_key==0 &&
+				sshdr.asc==0 && sshdr.ascq==0)
+				cmd_result &= ~SAM_STAT_CHECK_CONDITION;
+		}
+
+		/* Send userspace ATA registers */
+		if (sensebuf[0] == 0x72 &&	/* format is "descriptor" */
+				desc[0] == 0x09) {/* code is "ATA Descriptor" */
+			args[0] = desc[13];	/* status */
+			args[1] = desc[3];	/* error */
+			args[2] = desc[5];	/* sector count (0:7) */
+			args[3] = desc[7];	/* lbal */
+			args[4] = desc[9];	/* lbam */
+			args[5] = desc[11];	/* lbah */
+			args[6] = desc[12];	/* select */
+			if (copy_to_user(arg, args, sizeof(args)))
+				rc = -EFAULT;
+		}
+	}
+
+	if (cmd_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+ error:
+	kfree(sensebuf);
 	return rc;
 }
 
@@ -372,7 +411,7 @@
 		if (cmd->use_sg) {
 			qc->__sg = (struct scatterlist *) cmd->request_buffer;
 			qc->n_elem = cmd->use_sg;
-		} else {
+		} else if (cmd->request_bufflen) {
 			qc->__sg = &qc->sgent;
 			qc->n_elem = 1;
 		}
@@ -983,11 +1022,10 @@
 		}
 
 		tf->command = ATA_CMD_VERIFY;	/* READ VERIFY */
-	} else {
-		tf->nsect = 0;	/* time period value (0 implies now) */
-		tf->command = ATA_CMD_STANDBY;
-		/* Consider: ATA STANDBY IMMEDIATE command */
-	}
+	} else
+		/* Issue ATA STANDBY IMMEDIATE command */
+		tf->command = ATA_CMD_STANDBYNOW1;
+
 	/*
 	 * Standby and Idle condition timers could be implemented but that
 	 * would require libata to implement the Power condition mode page
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 623cec9..12c88c5 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -827,7 +827,8 @@
  */
 void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
 {
-	ata_bmdma_stop(qc);
+	if (qc->ap->ioaddr.bmdma_addr)
+		ata_bmdma_stop(qc);
 }
 
 #ifdef CONFIG_PCI
@@ -870,7 +871,8 @@
 			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
 		bmdma = pci_resource_start(pdev, 4);
 		if (bmdma) {
-			if (inb(bmdma + 2) & 0x80)
+			if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 			probe_ent->port[p].bmdma_addr = bmdma;
 		}
@@ -886,7 +888,8 @@
 		bmdma = pci_resource_start(pdev, 4);
 		if (bmdma) {
 			bmdma += 8;
-			if(inb(bmdma + 2) & 0x80)
+			if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 			probe_ent->port[p].bmdma_addr = bmdma;
 		}
@@ -914,13 +917,14 @@
 	probe_ent->irq_flags = IRQF_SHARED;
 
 	if (port_mask & ATA_PORT_PRIMARY) {
-		probe_ent->irq = ATA_PRIMARY_IRQ;
+		probe_ent->irq = ATA_PRIMARY_IRQ(pdev);
 		probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
 		probe_ent->port[0].altstatus_addr =
 		probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
 		if (bmdma) {
 			probe_ent->port[0].bmdma_addr = bmdma;
-			if (inb(bmdma + 2) & 0x80)
+			if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 2) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 		}
 		ata_std_ports(&probe_ent->port[0]);
@@ -929,15 +933,16 @@
 
 	if (port_mask & ATA_PORT_SECONDARY) {
 		if (probe_ent->irq)
-			probe_ent->irq2 = ATA_SECONDARY_IRQ;
+			probe_ent->irq2 = ATA_SECONDARY_IRQ(pdev);
 		else
-			probe_ent->irq = ATA_SECONDARY_IRQ;
+			probe_ent->irq = ATA_SECONDARY_IRQ(pdev);
 		probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
 		probe_ent->port[1].altstatus_addr =
 		probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
 		if (bmdma) {
 			probe_ent->port[1].bmdma_addr = bmdma + 8;
-			if (inb(bmdma + 10) & 0x80)
+			if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+			    (inb(bmdma + 10) & 0x80))
 				probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
 		}
 		ata_std_ports(&probe_ent->port[1]);
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 6f6672c..504e1db 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -36,15 +36,22 @@
 static int atiixp_pre_reset(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	static struct pci_bits atiixp_enable_bits[] = {
+	static const struct pci_bits atiixp_enable_bits[] = {
 		{ 0x48, 1, 0x01, 0x00 },
 		{ 0x48, 1, 0x08, 0x00 }
 	};
+	u8 udma;
 
 	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
 		return -ENOENT;
 
-	ap->cbl = ATA_CBL_PATA80;
+	/* Hack from drivers/ide/pci. Really we want to know how to do the
+	   raw detection not play follow the bios mode guess */
+	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma);
+	if ((udma & 0x07) >= 0x04 || (udma & 0x70) >= 0x40)
+		ap->cbl = ATA_CBL_PATA80;
+	else
+		ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
 
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 15841a5..449162c 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -197,7 +197,7 @@
 static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
 	static const u8 udma_data[] = {
-		0x31, 0x21, 0x11, 0x25, 0x15, 0x05
+		0x30, 0x20, 0x10, 0x20, 0x10, 0x00
 	};
 	static const u8 mwdma_data[] = {
 		0x30, 0x20, 0x10
@@ -213,12 +213,21 @@
 	pci_read_config_byte(pdev, pciD, &regD);
 	pci_read_config_byte(pdev, pciU, &regU);
 
-	regD &= ~(0x20 << shift);
-	regU &= ~(0x35 << shift);
+	/* DMA bits off */
+	regD &= ~(0x20 << adev->devno);
+	/* DMA control bits */
+	regU &= ~(0x30 << shift);
+	/* DMA timing bits */
+	regU &= ~(0x05 << adev->devno);
 
-	if (adev->dma_mode >= XFER_UDMA_0)
+	if (adev->dma_mode >= XFER_UDMA_0) {
+		/* Merge thge timing value */
 		regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
-	else
+		/* Merge the control bits */
+		regU |= 1 << adev->devno; /* UDMA on */
+		if (adev->dma_mode > 2)	/* 15nS timing */
+			regU |= 4 << adev->devno;
+	} else
 		regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift;
 
 	regD |= 0x20 << adev->devno;
@@ -239,8 +248,8 @@
 	struct ata_port *ap = qc->ap;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u8 dma_intr;
-	int dma_reg = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
-	int dma_mask = ap->port_no ? ARTTIM2 : CFR;
+	int dma_mask = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+	int dma_reg = ap->port_no ? ARTTIM2 : CFR;
 
 	ata_bmdma_stop(qc);
 
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index f6817b4..886fab9 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt3x2n"
-#define DRV_VERSION	"0.3"
+#define DRV_VERSION	"0.3.2"
 
 enum {
 	HPT_PCI_FAST	=	(1 << 31),
@@ -297,11 +297,11 @@
 	return 0;
 }
 
-static int hpt3x2n_use_dpll(struct ata_port *ap, int reading)
+static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
 {
 	long flags = (long)ap->host->private_data;
 	/* See if we should use the DPLL */
-	if (reading == 0)
+	if (writing)
 		return USE_DPLL;	/* Needed for write */
 	if (flags & PCI66)
 		return USE_DPLL;	/* Needed at 66Mhz */
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 0b56ff3..e8afd48 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -476,6 +476,7 @@
 /**
  *	it821x_smart_set_mode	-	mode setting
  *	@ap: interface to set up
+ *	@unused: device that failed (error only)
  *
  *	Use a non standard set_mode function. We don't want to be tuned.
  *	The BIOS configured everything. Our job is not to fiddle. We
@@ -483,7 +484,7 @@
  *	and respect them.
  */
 
-static void it821x_smart_set_mode(struct ata_port *ap)
+static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused)
 {
 	int dma_enabled = 0;
 	int i;
@@ -512,6 +513,7 @@
 			}
 		}
 	}
+	return 0;
 }
 
 /**
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index cb89241..23b8aab 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -23,9 +23,9 @@
 #include <scsi/scsi_host.h>
 
 #define DRV_NAME	"pata_ixp4xx_cf"
-#define DRV_VERSION	"0.1.1"
+#define DRV_VERSION	"0.1.1ac1"
 
-static void ixp4xx_set_mode(struct ata_port *ap)
+static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device *adev)
 {
 	int i;
 
@@ -38,6 +38,7 @@
 			dev->flags |= ATA_DFLAG_PIO;
 		}
 	}
+	return 0;
 }
 
 static void ixp4xx_phy_reset(struct ata_port *ap)
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 2d661cb..d50264a 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -204,20 +204,12 @@
 
 	u32 reg;
 
-	if (id->driver_data != 368) {
-		/* Put the controller into AHCI mode in case the AHCI driver
-		   has not yet been loaded. This can be done with either
-		   function present */
+	/* PATA controller is fn 1, AHCI is fn 0 */
+	if (id->driver_data != 368 && PCI_FUNC(pdev->devfn) != 1)
+		return -ENODEV;
 
-		/* FIXME: We may want a way to override this in future */
-		pci_write_config_byte(pdev, 0x41, 0xa1);
-
-		/* PATA controller is fn 1, AHCI is fn 0 */
-		if (PCI_FUNC(pdev->devfn) != 1)
-			return -ENODEV;
-	}
-	if ( id->driver_data == 365 || id->driver_data == 366) {
-		/* The 365/66 have two PATA channels, redirect the second */
+	/* The 365/66 have two PATA channels, redirect the second */
+	if (id->driver_data == 365 || id->driver_data == 366) {
 		pci_read_config_dword(pdev, 0x80, &reg);
 		reg |= (1 << 24);	/* IDE1 to PATA IDE secondary */
 		pci_write_config_dword(pdev, 0x80, reg);
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index e7bf9d8..581cb33 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -96,6 +96,7 @@
 /**
  *	legacy_set_mode		-	mode setting
  *	@ap: IDE interface
+ *	@unused: Device that failed when error is returned
  *
  *	Use a non standard set_mode function. We don't want to be tuned.
  *
@@ -105,7 +106,7 @@
  *	expand on this as per hdparm in the base kernel.
  */
 
-static void legacy_set_mode(struct ata_port *ap)
+static int legacy_set_mode(struct ata_port *ap, struct ata_device **unused)
 {
 	int i;
 
@@ -118,6 +119,7 @@
 			dev->flags |= ATA_DFLAG_PIO;
 		}
 	}
+	return 0;
 }
 
 static struct scsi_host_template legacy_sht = {
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 443b1d8..40ae11c 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -30,7 +30,7 @@
  * Provide our own set_mode() as we don't want to change anything that has
  * already been configured..
  */
-static void pata_platform_set_mode(struct ata_port *ap)
+static int pata_platform_set_mode(struct ata_port *ap, struct ata_device **unused)
 {
 	int i;
 
@@ -44,6 +44,7 @@
 			dev->flags |= ATA_DFLAG_PIO;
 		}
 	}
+	return 0;
 }
 
 static void pata_platform_host_stop(struct ata_host *host)
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index adf4cc1..cec0729 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -52,19 +52,20 @@
 /**
  *	rz1000_set_mode		-	mode setting function
  *	@ap: ATA interface
+ *	@unused: returned device on set_mode failure
  *
  *	Use a non standard set_mode function. We don't want to be tuned. We
  *	would prefer to be BIOS generic but for the fact our hardware is
  *	whacked out.
  */
 
-static void rz1000_set_mode(struct ata_port *ap)
+static int rz1000_set_mode(struct ata_port *ap, struct ata_device **unused)
 {
 	int i;
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
-		if (ata_dev_enabled(dev)) {
+		if (ata_dev_ready(dev)) {
 			/* We don't really care */
 			dev->pio_mode = XFER_PIO_0;
 			dev->xfer_mode = XFER_PIO_0;
@@ -72,6 +73,7 @@
 			dev->flags |= ATA_DFLAG_PIO;
 		}
 	}
+	return 0;
 }
 
 
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 32cf0bf..e8dfd8f 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -135,7 +135,7 @@
 static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
 	static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 };
-	static u16 speed_t[5] = { 0x328A, 0x1281, 0x1281, 0x10C3, 0x10C1 };
+	static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 };
 
 	unsigned long tfaddr = sil680_selreg(ap, 0x02);
 	unsigned long addr = sil680_seldev(ap, adev, 0x04);
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index f0d4f7e..f0b6c3b 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -23,6 +23,7 @@
  *	VIA VT8233c	-	UDMA100
  *	VIA VT8235	-	UDMA133
  *	VIA VT8237	-	UDMA133
+ *	VIA VT8237S	-	UDMA133
  *	VIA VT8251	-	UDMA133
  *
  *	Most registers remain compatible across chips. Others start reserved
@@ -61,7 +62,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_via"
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
 
 /*
  *	The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
@@ -95,6 +96,7 @@
 	u8 rev_max;
 	u16 flags;
 } via_isa_bridges[] = {
+	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 1b8e0eb..aae0b52 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -523,8 +523,7 @@
 	},
 	{  /* chip_7042 */
 		.sht		= &mv_sht,
-		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-				   MV_FLAG_DUAL_HC),
+		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &mv_iie_ops,
@@ -545,6 +544,8 @@
 
 	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
 
+	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
+
 	{ }			/* terminate list */
 };
 
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index f6d498e..f7a963e 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -700,7 +700,6 @@
 static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
 {
 	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-	int handled;
 
 	/* freeze if hotplugged */
 	if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
@@ -719,13 +718,7 @@
 	}
 
 	/* handle interrupt */
-	handled = ata_host_intr(ap, qc);
-	if (unlikely(!handled)) {
-		/* spurious, clear it */
-		ata_check_status(ap);
-	}
-
-	return 1;
+	return ata_host_intr(ap, qc);
 }
 
 static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
@@ -752,6 +745,11 @@
 			if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
 				u8 irq_stat = readb(host->mmio_base + NV_INT_STATUS_CK804)
 					>> (NV_INT_PORT_SHIFT * i);
+				if(ata_tag_valid(ap->active_tag))
+					/** NV_INT_DEV indication seems unreliable at times
+					    at least in ADMA mode. Force it on always when a
+					    command is active, to prevent losing interrupts. */
+					irq_stat |= NV_INT_DEV;
 				handled += nv_host_intr(ap, irq_stat);
 				continue;
 			}
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 5c603ca..a43aec6 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -128,7 +128,8 @@
 
 static struct ata_port_info uli_port_info = {
 	.sht            = &uli_sht,
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+			  ATA_FLAG_IGN_SIMPLEX,
 	.pio_mask       = 0x1f,		/* pio0-4 */
 	.udma_mask      = 0x7f,		/* udma0-6 */
 	.port_ops       = &uli_ops,
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1c7f19a..d3d5c0d 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -74,9 +74,11 @@
 static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static void svia_noop_freeze(struct ata_port *ap);
 static void vt6420_error_handler(struct ata_port *ap);
 
 static const struct pci_device_id svia_pci_tbl[] = {
+	{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
 	{ PCI_VDEVICE(VIA, 0x0591), vt6420 },
 	{ PCI_VDEVICE(VIA, 0x3149), vt6420 },
 	{ PCI_VDEVICE(VIA, 0x3249), vt6421 },
@@ -127,7 +129,7 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.freeze			= ata_bmdma_freeze,
+	.freeze			= svia_noop_freeze,
 	.thaw			= ata_bmdma_thaw,
 	.error_handler		= vt6420_error_handler,
 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
@@ -203,6 +205,15 @@
 	outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
 }
 
+static void svia_noop_freeze(struct ata_port *ap)
+{
+	/* Some VIA controllers choke if ATA_NIEN is manipulated in
+	 * certain way.  Leave it alone and just clear pending IRQ.
+	 */
+	ata_chk_status(ap);
+	ata_bmdma_irq_clear(ap);
+}
+
 /**
  *	vt6420_prereset - prereset for vt6420
  *	@ap: target ATA port
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 4dc1010..f96446c 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1845,7 +1845,7 @@
 
 /********** initialise a card **********/
 
-static int __init hrz_init (hrz_dev * dev) {
+static int __devinit hrz_init (hrz_dev * dev) {
   int onefivefive;
   
   u16 chan;
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index aeefec9..6bdf593 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -117,10 +117,17 @@
 
 	/* IBM/Lenovo ThinkPad with Broadcom chip */
 	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
+	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_WRONG_SCO_MTU },
 
 	/* ANYCOM Bluetooth USB-200 and USB-250 */
 	{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
 
+	/* HP laptop with Broadcom chip */
+	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_WRONG_SCO_MTU },
+
+	/* Dell laptop with Broadcom chip */
+	{ USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_WRONG_SCO_MTU },
+
 	/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
 	{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
 
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 51d0d56..c85c8ca 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -101,6 +101,11 @@
 	for (i = 0; i < nr_tables; i++) {
 		entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL);
 		if (entry == NULL) {
+			while (i > 0) {
+				kfree(tables[i-1]);
+				i--;
+			}
+			kfree(tables);
 			retval = -ENOMEM;
 			break;
 		}
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 9793004..93d2209 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -655,7 +655,7 @@
 	.class          = (PCI_CLASS_BRIDGE_HOST << 8),
 	.class_mask     = ~0,
 	.vendor         = PCI_VENDOR_ID_VIA,
-	.device         = PCI_DEVICE_ID_VIA_K8M890CE,
+	.device         = PCI_DEVICE_ID_VIA_VT3336,
 	.subvendor      = PCI_ANY_ID,
 	.subdevice      = PCI_ANY_ID,
 	},
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index f244c66..9987dc2 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -41,18 +41,18 @@
 };
 
 
-typedef struct _ati_page_map {
+struct ati_page_map {
 	unsigned long *real;
 	unsigned long __iomem *remapped;
-} ati_page_map;
+};
 
 static struct _ati_generic_private {
 	volatile u8 __iomem *registers;
-	ati_page_map **gatt_pages;
+	struct ati_page_map **gatt_pages;
 	int num_tables;
 } ati_generic_private;
 
-static int ati_create_page_map(ati_page_map *page_map)
+static int ati_create_page_map(struct ati_page_map *page_map)
 {
 	int i, err = 0;
 
@@ -82,7 +82,7 @@
 }
 
 
-static void ati_free_page_map(ati_page_map *page_map)
+static void ati_free_page_map(struct ati_page_map *page_map)
 {
 	unmap_page_from_agp(virt_to_page(page_map->real));
 	iounmap(page_map->remapped);
@@ -94,8 +94,8 @@
 static void ati_free_gatt_pages(void)
 {
 	int i;
-	ati_page_map **tables;
-	ati_page_map *entry;
+	struct ati_page_map **tables;
+	struct ati_page_map *entry;
 
 	tables = ati_generic_private.gatt_pages;
 	for (i = 0; i < ati_generic_private.num_tables; i++) {
@@ -112,30 +112,30 @@
 
 static int ati_create_gatt_pages(int nr_tables)
 {
-	ati_page_map **tables;
-	ati_page_map *entry;
+	struct ati_page_map **tables;
+	struct ati_page_map *entry;
 	int retval = 0;
 	int i;
 
-	tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL);
+	tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL);
 	if (tables == NULL)
 		return -ENOMEM;
 
 	for (i = 0; i < nr_tables; i++) {
-		entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL);
+		entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
 		if (entry == NULL) {
-			while (i>0) {
-				kfree (tables[i-1]);
+			while (i > 0) {
+				kfree(tables[i-1]);
 				i--;
 			}
-			kfree (tables);
-			tables = NULL;
+			kfree(tables);
 			retval = -ENOMEM;
 			break;
 		}
 		tables[i] = entry;
 		retval = ati_create_page_map(entry);
-		if (retval != 0) break;
+		if (retval != 0)
+			break;
 	}
 	ati_generic_private.num_tables = nr_tables;
 	ati_generic_private.gatt_pages = tables;
@@ -340,7 +340,7 @@
 static int ati_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	struct aper_size_info_lvl2 *value;
-	ati_page_map page_dir;
+	struct ati_page_map page_dir;
 	unsigned long addr;
 	int retval;
 	u32 temp;
@@ -400,7 +400,7 @@
 
 static int ati_free_gatt_table(struct agp_bridge_data *bridge)
 {
-	ati_page_map page_dir;
+	struct ati_page_map page_dir;
 
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
 	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index ab0a9c0..a3011de 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -1955,6 +1955,15 @@
 
 	pci_restore_state(pdev);
 
+	/* We should restore our graphics device's config space,
+	 * as host bridge (00:00) resumes before graphics device (02:00),
+	 * then our access to its pci space can work right.
+	 */
+	if (intel_i810_private.i810_dev)
+		pci_restore_state(intel_i810_private.i810_dev);
+	if (intel_i830_private.i830_dev)
+		pci_restore_state(intel_i830_private.i830_dev);
+
 	if (bridge->driver == &intel_generic_driver)
 		intel_configure();
 	else if (bridge->driver == &intel_850_driver)
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index c149ac9..2ded7a28 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -380,9 +380,23 @@
 	/* P4M800CE */
 	{
 		.device_id	= PCI_DEVICE_ID_VIA_P4M800CE,
-		.chipset_name	= "P4M800CE",
+		.chipset_name	= "VT3314",
 	},
-
+	/* CX700 */
+	{
+		.device_id  = PCI_DEVICE_ID_VIA_CX700,
+		.chipset_name   = "CX700",
+	},
+	/* VT3336 */
+	{
+		.device_id  = PCI_DEVICE_ID_VIA_VT3336,
+		.chipset_name   = "VT3336",
+	},
+	/* P4M890 */
+	{
+		.device_id  = PCI_DEVICE_ID_VIA_P4M890,
+		.chipset_name   = "P4M890",
+	},
 	{ }, /* dummy final entry, always present */
 };
 
@@ -524,6 +538,9 @@
 	ID(PCI_DEVICE_ID_VIA_83_87XX_1),
 	ID(PCI_DEVICE_ID_VIA_3296_0),
 	ID(PCI_DEVICE_ID_VIA_P4M800CE),
+	ID(PCI_DEVICE_ID_VIA_CX700),
+	ID(PCI_DEVICE_ID_VIA_VT3336),
+	ID(PCI_DEVICE_ID_VIA_P4M890),
 	{ }
 };
 
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index e2c4b3a..78c1ae2 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -500,7 +500,7 @@
 
 	if (!drm_get_drawable_info(dev, swap.drawable)) {
 		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-		DRM_ERROR("Invalid drawable ID %d\n", swap.drawable);
+		DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable);
 		return DRM_ERR(EINVAL);
 	}
 
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
index 71e4e0f..556fd81 100644
--- a/drivers/char/hw_random/amd-rng.c
+++ b/drivers/char/hw_random/amd-rng.c
@@ -144,7 +144,7 @@
 	hwrng_unregister(&amd_rng);
 }
 
-subsys_initcall(mod_init);
+module_init(mod_init);
 module_exit(mod_exit);
 
 MODULE_AUTHOR("The Linux Kernel team");
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index d37ced0..8e8658d 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -125,7 +125,7 @@
 	iounmap(mem);
 }
 
-subsys_initcall(mod_init);
+module_init(mod_init);
 module_exit(mod_exit);
 
 MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 8efbc9c..f22e78e 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -143,6 +143,11 @@
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
+static __initdata int no_fwh_detect;
+module_param(no_fwh_detect, int, 0);
+MODULE_PARM_DESC(no_fwh_detect, "Skip FWH detection:\n"
+                                " positive value - skip if FWH space locked read-only\n"
+                                " negative value - skip always");
 
 static inline u8 hwstatus_get(void __iomem *mem)
 {
@@ -240,6 +245,11 @@
 	if (!dev)
 		goto out; /* Device not found. */
 
+	if (no_fwh_detect < 0) {
+		pci_dev_put(dev);
+		goto fwh_done;
+	}
+
 	/* Check for Intel 82802 */
 	if (dev->device < 0x2640) {
 		fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
@@ -252,6 +262,23 @@
 	pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
 	pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
 
+	if ((bios_cntl_val &
+	     (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
+	    == BIOS_CNTL_LOCK_ENABLE_MASK) {
+		static __initdata /*const*/ char warning[] =
+			KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+			KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+			KERN_WARNING PFX "you are certain that your system has a functional\n"
+			KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
+
+		pci_dev_put(dev);
+		if (no_fwh_detect)
+			goto fwh_done;
+		printk(warning);
+		err = -EBUSY;
+		goto out;
+	}
+
 	mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
 	if (mem == NULL) {
 		pci_dev_put(dev);
@@ -280,8 +307,7 @@
 		pci_write_config_byte(dev,
 		                      fwh_dec_en1_off,
 		                      fwh_dec_en1_val | FWH_F8_EN_MASK);
-	if (!(bios_cntl_val &
-	      (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+	if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK))
 		pci_write_config_byte(dev,
 		                      bios_cntl_off,
 		                      bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
@@ -315,6 +341,8 @@
 		goto out;
 	}
 
+fwh_done:
+
 	err = -ENOMEM;
 	mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
 	if (!mem)
@@ -350,7 +378,7 @@
 	iounmap(mem);
 }
 
-subsys_initcall(mod_init);
+module_init(mod_init);
 module_exit(mod_exit);
 
 MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
index c9caff5..bab43ca 100644
--- a/drivers/char/hw_random/ixp4xx-rng.c
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -64,7 +64,7 @@
 	iounmap(rng_base);
 }
 
-subsys_initcall(ixp4xx_rng_init);
+module_init(ixp4xx_rng_init);
 module_exit(ixp4xx_rng_exit);
 
 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index 0e786b6..9ebf84d 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -176,7 +176,7 @@
 	hwrng_unregister(&via_rng);
 }
 
-subsys_initcall(mod_init);
+module_init(mod_init);
 module_exit(mod_exit);
 
 MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets");
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 4e4691a..53582b5 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3649,8 +3649,6 @@
 	unsigned long        flags;
 	int                  i;
 
-	INIT_LIST_HEAD(&timeouts);
-
 	rcu_read_lock();
 	list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
 		/* See if any waiting messages need to be processed. */
@@ -3671,6 +3669,7 @@
 		/* Go through the seq table and find any messages that
 		   have timed out, putting them in the timeouts
 		   list. */
+		INIT_LIST_HEAD(&timeouts);
 		spin_lock_irqsave(&intf->seq_lock, flags);
 		for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
 			check_msg_timeout(intf, &(intf->seq_table[i]),
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 4f1813e..f5c160c 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -293,8 +293,8 @@
 {
 	unsigned long pfn;
 
-	/* Turn a pfn offset into an absolute pfn */
-	pfn = PFN_DOWN(virt_to_phys((void *)PAGE_OFFSET)) + vma->vm_pgoff;
+	/* Turn a kernel-virtual address into a physical page frame */
+	pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
 
 	/*
 	 * RED-PEN: on some architectures there is more mapped memory
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 1393523..7fd3cd5 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -215,7 +215,7 @@
 }
 static struct sysrq_key_op sysrq_showstate_blocked_op = {
 	.handler	= sysrq_handle_showstate_blocked,
-	.help_msg	= "showBlockedTasks",
+	.help_msg	= "shoW-blocked-tasks",
 	.action_msg	= "Show Blocked State",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
@@ -315,15 +315,16 @@
 	&sysrq_loglevel_op,		/* 9 */
 
 	/*
-	 * Don't use for system provided sysrqs, it is handled specially on
-	 * sparc and will never arrive
+	 * a: Don't use for system provided sysrqs, it is handled specially on
+	 * sparc and will never arrive.
 	 */
 	NULL,				/* a */
 	&sysrq_reboot_op,		/* b */
-	&sysrq_crashdump_op,		/* c */
+	&sysrq_crashdump_op,		/* c & ibm_emac driver debug */
 	&sysrq_showlocks_op,		/* d */
 	&sysrq_term_op,			/* e */
 	&sysrq_moom_op,			/* f */
+	/* g: May be registered by ppc for kgdb */
 	NULL,				/* g */
 	NULL,				/* h */
 	&sysrq_kill_op,			/* i */
@@ -332,18 +333,19 @@
 	NULL,				/* l */
 	&sysrq_showmem_op,		/* m */
 	&sysrq_unrt_op,			/* n */
-	/* This will often be registered as 'Off' at init time */
+	/* o: This will often be registered as 'Off' at init time */
 	NULL,				/* o */
 	&sysrq_showregs_op,		/* p */
 	NULL,				/* q */
-	&sysrq_unraw_op,			/* r */
+	&sysrq_unraw_op,		/* r */
 	&sysrq_sync_op,			/* s */
 	&sysrq_showstate_op,		/* t */
 	&sysrq_mountro_op,		/* u */
-	/* May be assigned at init time by SMP VOYAGER */
+	/* v: May be registered at init time by SMP VOYAGER */
 	NULL,				/* v */
-	NULL,				/* w */
-	&sysrq_showstate_blocked_op,	/* x */
+	&sysrq_showstate_blocked_op,	/* w */
+	/* x: May be registered on ppc/powerpc for xmon */
+	NULL,				/* x */
 	NULL,				/* y */
 	NULL				/* z */
 };
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 448d508..4fac2bd 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -186,6 +186,7 @@
 static void switchover_timeout(unsigned long data);
 static struct timer_list switchover_timer =
 	TIMER_INITIALIZER(switchover_timeout , 0, 0);
+static unsigned long tlclk_timer_data;
 
 static struct tlclk_alarms *alarm_events;
 
@@ -197,10 +198,19 @@
 
 static DECLARE_WAIT_QUEUE_HEAD(wq);
 
+static unsigned long useflags;
+static DEFINE_MUTEX(tlclk_mutex);
+
 static int tlclk_open(struct inode *inode, struct file *filp)
 {
 	int result;
 
+	if (test_and_set_bit(0, &useflags))
+		return -EBUSY;
+		/* this legacy device is always one per system and it doesn't
+		 * know how to handle multiple concurrent clients.
+		 */
+
 	/* Make sure there is no interrupt pending while
 	 * initialising interrupt handler */
 	inb(TLCLK_REG6);
@@ -221,6 +231,7 @@
 static int tlclk_release(struct inode *inode, struct file *filp)
 {
 	free_irq(telclk_interrupt, tlclk_interrupt);
+	clear_bit(0, &useflags);
 
 	return 0;
 }
@@ -230,26 +241,25 @@
 {
 	if (count < sizeof(struct tlclk_alarms))
 		return -EIO;
+	if (mutex_lock_interruptible(&tlclk_mutex))
+		return -EINTR;
+
 
 	wait_event_interruptible(wq, got_event);
-	if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms)))
+	if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) {
+		mutex_unlock(&tlclk_mutex);
 		return -EFAULT;
+	}
 
 	memset(alarm_events, 0, sizeof(struct tlclk_alarms));
 	got_event = 0;
 
+	mutex_unlock(&tlclk_mutex);
 	return  sizeof(struct tlclk_alarms);
 }
 
-static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
-	    loff_t *f_pos)
-{
-	return 0;
-}
-
 static const struct file_operations tlclk_fops = {
 	.read = tlclk_read,
-	.write = tlclk_write,
 	.open = tlclk_open,
 	.release = tlclk_release,
 
@@ -540,7 +550,7 @@
 			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
 			switch (val) {
 			case CLK_8_592MHz:
-				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
 				break;
 			case CLK_11_184MHz:
 				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
@@ -549,7 +559,7 @@
 				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
 				break;
 			case CLK_44_736MHz:
-				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
 				break;
 			}
 		} else
@@ -839,11 +849,13 @@
 
 static void switchover_timeout(unsigned long data)
 {
-	if ((data & 1)) {
-		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+	unsigned long flags = *(unsigned long *) data;
+
+	if ((flags & 1)) {
+		if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
 			alarm_events->switchover_primary++;
 	} else {
-		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+		if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
 			alarm_events->switchover_secondary++;
 	}
 
@@ -901,8 +913,9 @@
 
 		/* TIMEOUT in ~10ms */
 		switchover_timer.expires = jiffies + msecs_to_jiffies(10);
-		switchover_timer.data = inb(TLCLK_REG1);
-		add_timer(&switchover_timer);
+		tlclk_timer_data = inb(TLCLK_REG1);
+		switchover_timer.data = (unsigned long) &tlclk_timer_data;
+		mod_timer(&switchover_timer, switchover_timer.expires);
 	} else {
 		got_event = 1;
 		wake_up(&wq);
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index a744dad..0cea8d4 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2002 MontaVista Software Inc.
  *	Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  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
@@ -125,30 +125,17 @@
 	return data;
 }
 
-static unsigned int startup_giuint_low_irq(unsigned int irq)
+static void ack_giuint_low(unsigned int irq)
 {
-	unsigned int pin;
-
-	pin = GPIO_PIN_OF_IRQ(irq);
-	giu_write(GIUINTSTATL, 1 << pin);
-	giu_set(GIUINTENL, 1 << pin);
-
-	return 0;
+	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
 }
 
-static void shutdown_giuint_low_irq(unsigned int irq)
+static void mask_giuint_low(unsigned int irq)
 {
 	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
 }
 
-static void enable_giuint_low_irq(unsigned int irq)
-{
-	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-#define disable_giuint_low_irq	shutdown_giuint_low_irq
-
-static void ack_giuint_low_irq(unsigned int irq)
+static void mask_ack_giuint_low(unsigned int irq)
 {
 	unsigned int pin;
 
@@ -157,46 +144,30 @@
 	giu_write(GIUINTSTATL, 1 << pin);
 }
 
-static void end_giuint_low_irq(unsigned int irq)
+static void unmask_giuint_low(unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
 }
 
-static struct hw_interrupt_type giuint_low_irq_type = {
-	.typename	= "GIUINTL",
-	.startup	= startup_giuint_low_irq,
-	.shutdown	= shutdown_giuint_low_irq,
-	.enable		= enable_giuint_low_irq,
-	.disable	= disable_giuint_low_irq,
-	.ack		= ack_giuint_low_irq,
-	.end		= end_giuint_low_irq,
+static struct irq_chip giuint_low_irq_chip = {
+	.name		= "GIUINTL",
+	.ack		= ack_giuint_low,
+	.mask		= mask_giuint_low,
+	.mask_ack	= mask_ack_giuint_low,
+	.unmask		= unmask_giuint_low,
 };
 
-static unsigned int startup_giuint_high_irq(unsigned int irq)
+static void ack_giuint_high(unsigned int irq)
 {
-	unsigned int pin;
-
-	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
-	giu_write(GIUINTSTATH, 1 << pin);
-	giu_set(GIUINTENH, 1 << pin);
-
-	return 0;
+	giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
 }
 
-static void shutdown_giuint_high_irq(unsigned int irq)
+static void mask_giuint_high(unsigned int irq)
 {
 	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
 }
 
-static void enable_giuint_high_irq(unsigned int irq)
-{
-	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-#define disable_giuint_high_irq	shutdown_giuint_high_irq
-
-static void ack_giuint_high_irq(unsigned int irq)
+static void mask_ack_giuint_high(unsigned int irq)
 {
 	unsigned int pin;
 
@@ -205,20 +176,17 @@
 	giu_write(GIUINTSTATH, 1 << pin);
 }
 
-static void end_giuint_high_irq(unsigned int irq)
+static void unmask_giuint_high(unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
 }
 
-static struct hw_interrupt_type giuint_high_irq_type = {
-	.typename	= "GIUINTH",
-	.startup	= startup_giuint_high_irq,
-	.shutdown	= shutdown_giuint_high_irq,
-	.enable		= enable_giuint_high_irq,
-	.disable	= disable_giuint_high_irq,
-	.ack		= ack_giuint_high_irq,
-	.end		= end_giuint_high_irq,
+static struct irq_chip giuint_high_irq_chip = {
+	.name		= "GIUINTH",
+	.ack		= ack_giuint_high,
+	.mask		= mask_giuint_high,
+	.mask_ack	= mask_ack_giuint_high,
+	.unmask		= unmask_giuint_high,
 };
 
 static int giu_get_irq(unsigned int irq)
@@ -282,9 +250,15 @@
 					break;
 				}
 			}
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+			                         &giuint_low_irq_chip,
+			                         handle_edge_irq);
 		} else {
 			giu_clear(GIUINTTYPL, mask);
 			giu_clear(GIUINTHTSELL, mask);
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+			                         &giuint_low_irq_chip,
+			                         handle_level_irq);
 		}
 		giu_write(GIUINTSTATL, mask);
 	} else if (pin < GIUINT_HIGH_MAX) {
@@ -311,9 +285,15 @@
 					break;
 				}
 			}
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+			                         &giuint_high_irq_chip,
+			                         handle_edge_irq);
 		} else {
 			giu_clear(GIUINTTYPH, mask);
 			giu_clear(GIUINTHTSELH, mask);
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+			                         &giuint_high_irq_chip,
+			                         handle_level_irq);
 		}
 		giu_write(GIUINTSTATH, mask);
 	}
@@ -617,10 +597,11 @@
 static int __devinit giu_probe(struct platform_device *dev)
 {
 	unsigned long start, size, flags = 0;
-	unsigned int nr_pins = 0;
+	unsigned int nr_pins = 0, trigger, i, pin;
 	struct resource *res1, *res2 = NULL;
 	void *base;
-	int retval, i;
+	struct irq_chip *chip;
+	int retval;
 
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
@@ -688,11 +669,20 @@
 	giu_write(GIUINTENL, 0);
 	giu_write(GIUINTENH, 0);
 
+	trigger = giu_read(GIUINTTYPH) << 16;
+	trigger |= giu_read(GIUINTTYPL);
 	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
-		if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
-			irq_desc[i].chip = &giuint_low_irq_type;
+		pin = GPIO_PIN_OF_IRQ(i);
+		if (pin < GIUINT_HIGH_OFFSET)
+			chip = &giuint_low_irq_chip;
 		else
-			irq_desc[i].chip = &giuint_high_irq_type;
+			chip = &giuint_high_irq_chip;
+
+		if (trigger & (1 << pin))
+			set_irq_chip_and_handler(i, chip, handle_edge_irq);
+		else
+			set_irq_chip_and_handler(i, chip, handle_level_irq);
+
 	}
 
 	return cascade_irq(GIUINT_IRQ, giu_get_irq);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d913304..a45cc89 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -722,8 +722,13 @@
 			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 			dprintk("CPU already managed, adding link\n");
-			sysfs_create_link(&sys_dev->kobj,
-					  &managed_policy->kobj, "cpufreq");
+			ret = sysfs_create_link(&sys_dev->kobj,
+						&managed_policy->kobj,
+						"cpufreq");
+			if (ret) {
+				mutex_unlock(&policy->lock);
+				goto err_out_driver_exit;
+			}
 
 			cpufreq_debug_enable_ratelimit();
 			mutex_unlock(&policy->lock);
@@ -770,8 +775,12 @@
 		dprintk("CPU %u already managed, adding link\n", j);
 		cpufreq_cpu_get(cpu);
 		cpu_sys_dev = get_cpu_sysdev(j);
-		sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
-				  "cpufreq");
+		ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
+					"cpufreq");
+		if (ret) {
+			mutex_unlock(&policy->lock);
+			goto err_out_unregister;
+		}
 	}
 
 	policy->governor = NULL; /* to assure that the starting sequence is
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 879250d..ff8c4be 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -51,6 +51,8 @@
 	  If unsure say M. The compiled module will be
 	  called padlock-sha.ko
 
+source "arch/s390/crypto/Kconfig"
+
 config CRYPTO_DEV_GEODE
 	tristate "Support for the Geode LX AES engine"
 	depends on CRYPTO && X86_32 && PCI
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 5ab5e39..c6281cc 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -122,8 +122,6 @@
 	struct kobject kobj;
 };
 
-#define get_efivar_entry(n) list_entry(n, struct efivar_entry, list)
-
 struct efivar_attribute {
 	struct attribute attr;
 	ssize_t (*show) (struct efivar_entry *entry, char *buf);
@@ -386,9 +384,6 @@
 static void efivar_release(struct kobject *kobj)
 {
 	struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
-	spin_lock(&efivars_lock);
-	list_del(&var->list);
-	spin_unlock(&efivars_lock);
 	kfree(var);
 }
 
@@ -430,9 +425,8 @@
 efivar_create(struct subsystem *sub, const char *buf, size_t count)
 {
 	struct efi_variable *new_var = (struct efi_variable *)buf;
-	struct efivar_entry *search_efivar = NULL;
+	struct efivar_entry *search_efivar, *n;
 	unsigned long strsize1, strsize2;
-	struct list_head *pos, *n;
 	efi_status_t status = EFI_NOT_FOUND;
 	int found = 0;
 
@@ -444,8 +438,7 @@
 	/*
 	 * Does this variable already exist?
 	 */
-	list_for_each_safe(pos, n, &efivar_list) {
-		search_efivar = get_efivar_entry(pos);
+	list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
 		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 		strsize2 = utf8_strsize(new_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
@@ -490,9 +483,8 @@
 efivar_delete(struct subsystem *sub, const char *buf, size_t count)
 {
 	struct efi_variable *del_var = (struct efi_variable *)buf;
-	struct efivar_entry *search_efivar = NULL;
+	struct efivar_entry *search_efivar, *n;
 	unsigned long strsize1, strsize2;
-	struct list_head *pos, *n;
 	efi_status_t status = EFI_NOT_FOUND;
 	int found = 0;
 
@@ -504,8 +496,7 @@
 	/*
 	 * Does this variable already exist?
 	 */
-	list_for_each_safe(pos, n, &efivar_list) {
-		search_efivar = get_efivar_entry(pos);
+	list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
 		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 		strsize2 = utf8_strsize(del_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
@@ -537,9 +528,9 @@
 		spin_unlock(&efivars_lock);
 		return -EIO;
 	}
+	list_del(&search_efivar->list);
 	/* We need to release this lock before unregistering. */
 	spin_unlock(&efivars_lock);
-
 	efivar_unregister(search_efivar);
 
 	/* It's dead Jim.... */
@@ -768,10 +759,14 @@
 static void __exit
 efivars_exit(void)
 {
-	struct list_head *pos, *n;
+	struct efivar_entry *entry, *n;
 
-	list_for_each_safe(pos, n, &efivar_list)
-		efivar_unregister(get_efivar_entry(pos));
+	list_for_each_entry_safe(entry, n, &efivar_list, list) {
+		spin_lock(&efivars_lock);
+		list_del(&entry->list);
+		spin_unlock(&efivars_lock);
+		efivar_unregister(entry);
+	}
 
 	subsystem_unregister(&vars_subsys);
 	firmware_unregister(&efi_subsys);
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index ec796ad..850788f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -22,5 +22,19 @@
 
 	  If unsure, say Y
 
+config HID_DEBUG
+	bool "HID debugging support"
+	depends on HID
+	---help---
+	This option lets the HID layer output diagnostics about its internal
+	state, resolve HID usages, dump HID fields, etc. Individual HID drivers
+	use this debugging facility to output information about individual HID
+	devices, etc.
+
+	This feature is useful for those who are either debugging the HID parser
+	or any HID hardware device.
+
+	If unsure, say N
+
 endmenu
 
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 6432392..52e97d8 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -1,15 +1,8 @@
 #
 # Makefile for the HID driver
 #
-
-# Multipart objects.
-hid-objs	:= hid-core.o hid-input.o
-
-# Optional parts of multipart objects.
+hid-objs			:= hid-core.o hid-input.o
 
 obj-$(CONFIG_HID)		+= hid.o
-
-ifeq ($(CONFIG_INPUT_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+hid-$(CONFIG_HID_DEBUG)		+= hid-debug.o
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 18c2b3c..8c7d48e 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -28,11 +28,9 @@
 #include <linux/input.h>
 #include <linux/wait.h>
 
-#undef DEBUG
-#undef DEBUG_DATA
-
 #include <linux/hid.h>
 #include <linux/hiddev.h>
+#include <linux/hid-debug.h>
 
 /*
  * Version Information
@@ -40,18 +38,10 @@
 
 #define DRIVER_VERSION "v2.6"
 #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
-#define DRIVER_DESC "USB HID core driver"
+#define DRIVER_DESC "HID core driver"
 #define DRIVER_LICENSE "GPL"
 
 /*
- * Module parameters.
- */
-
-static unsigned int hid_mousepoll_interval;
-module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
-MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
-
-/*
  * Register a new report for a device.
  */
 
@@ -551,6 +541,7 @@
 	}
 
 	kfree(device->rdesc);
+	kfree(device->collection);
 	kfree(device);
 }
 EXPORT_SYMBOL_GPL(hid_free_device);
@@ -656,7 +647,7 @@
 	for (i = 0; i < HID_REPORT_TYPES; i++)
 		INIT_LIST_HEAD(&device->report_enum[i].report_list);
 
-	if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
+	if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) {
 		kfree(device->collection);
 		kfree(device);
 		return NULL;
@@ -888,6 +879,10 @@
 	unsigned size = field->report_size;
 	unsigned n;
 
+	/* make sure the unused bits in the last byte are zeros */
+	if (count > 0 && size > 0)
+		data[(count*size-1)/8] = 0;
+
 	for (n = 0; n < count; n++) {
 		if (field->logical_minimum < 0)	/* signed values */
 			implement(data, offset + n * size, size, s32ton(field->value[n], size));
@@ -954,8 +949,8 @@
 		return -1;
 	}
 
-#ifdef DEBUG_DATA
-	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
+#ifdef CONFIG_HID_DEBUG
+	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
 #endif
 
 	n = 0;                          /* Normally report number is 0 */
@@ -964,7 +959,7 @@
 		size--;
 	}
 
-#ifdef DEBUG_DATA
+#ifdef CONFIG_HID_DEBUG
 	{
 		int i;
 		printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
new file mode 100644
index 0000000..89241be
--- /dev/null
+++ b/drivers/hid/hid-debug.c
@@ -0,0 +1,764 @@
+/*
+ * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
+ *
+ *  (c) 1999 Andreas Gal		<gal@cs.uni-magdeburg.de>
+ *  (c) 2000-2001 Vojtech Pavlik	<vojtech@ucw.cz>
+ *  (c) 2007 Jiri Kosina
+ *
+ *  Some debug stuff for the HID parser.
+ */
+
+/*
+ * 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
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/hid.h>
+
+struct hid_usage_entry {
+	unsigned  page;
+	unsigned  usage;
+	char     *description;
+};
+
+static const struct hid_usage_entry hid_usage_table[] = {
+  {  0,      0, "Undefined" },
+  {  1,      0, "GenericDesktop" },
+    {0, 0x01, "Pointer"},
+    {0, 0x02, "Mouse"},
+    {0, 0x04, "Joystick"},
+    {0, 0x05, "GamePad"},
+    {0, 0x06, "Keyboard"},
+    {0, 0x07, "Keypad"},
+    {0, 0x08, "MultiAxis"},
+      {0, 0x30, "X"},
+      {0, 0x31, "Y"},
+      {0, 0x32, "Z"},
+      {0, 0x33, "Rx"},
+      {0, 0x34, "Ry"},
+      {0, 0x35, "Rz"},
+      {0, 0x36, "Slider"},
+      {0, 0x37, "Dial"},
+      {0, 0x38, "Wheel"},
+      {0, 0x39, "HatSwitch"},
+    {0, 0x3a, "CountedBuffer"},
+      {0, 0x3b, "ByteCount"},
+      {0, 0x3c, "MotionWakeup"},
+      {0, 0x3d, "Start"},
+      {0, 0x3e, "Select"},
+      {0, 0x40, "Vx"},
+      {0, 0x41, "Vy"},
+      {0, 0x42, "Vz"},
+      {0, 0x43, "Vbrx"},
+      {0, 0x44, "Vbry"},
+      {0, 0x45, "Vbrz"},
+      {0, 0x46, "Vno"},
+    {0, 0x80, "SystemControl"},
+      {0, 0x81, "SystemPowerDown"},
+      {0, 0x82, "SystemSleep"},
+      {0, 0x83, "SystemWakeUp"},
+      {0, 0x84, "SystemContextMenu"},
+      {0, 0x85, "SystemMainMenu"},
+      {0, 0x86, "SystemAppMenu"},
+      {0, 0x87, "SystemMenuHelp"},
+      {0, 0x88, "SystemMenuExit"},
+      {0, 0x89, "SystemMenuSelect"},
+      {0, 0x8a, "SystemMenuRight"},
+      {0, 0x8b, "SystemMenuLeft"},
+      {0, 0x8c, "SystemMenuUp"},
+      {0, 0x8d, "SystemMenuDown"},
+      {0, 0x90, "D-PadUp"},
+      {0, 0x91, "D-PadDown"},
+      {0, 0x92, "D-PadRight"},
+      {0, 0x93, "D-PadLeft"},
+  {  2, 0, "Simulation" },
+      {0, 0xb0, "Aileron"},
+      {0, 0xb1, "AileronTrim"},
+      {0, 0xb2, "Anti-Torque"},
+      {0, 0xb3, "Autopilot"},
+      {0, 0xb4, "Chaff"},
+      {0, 0xb5, "Collective"},
+      {0, 0xb6, "DiveBrake"},
+      {0, 0xb7, "ElectronicCountermeasures"},
+      {0, 0xb8, "Elevator"},
+      {0, 0xb9, "ElevatorTrim"},
+      {0, 0xba, "Rudder"},
+      {0, 0xbb, "Throttle"},
+      {0, 0xbc, "FlightCommunications"},
+      {0, 0xbd, "FlareRelease"},
+      {0, 0xbe, "LandingGear"},
+      {0, 0xbf, "ToeBrake"},
+  {  7, 0, "Keyboard" },
+  {  8, 0, "LED" },
+      {0, 0x01, "NumLock"},
+      {0, 0x02, "CapsLock"},
+      {0, 0x03, "ScrollLock"},
+      {0, 0x04, "Compose"},
+      {0, 0x05, "Kana"},
+      {0, 0x4b, "GenericIndicator"},
+  {  9, 0, "Button" },
+  { 10, 0, "Ordinal" },
+  { 12, 0, "Consumer" },
+      {0, 0x238, "HorizontalWheel"},
+  { 13, 0, "Digitizers" },
+    {0, 0x01, "Digitizer"},
+    {0, 0x02, "Pen"},
+    {0, 0x03, "LightPen"},
+    {0, 0x04, "TouchScreen"},
+    {0, 0x05, "TouchPad"},
+    {0, 0x20, "Stylus"},
+    {0, 0x21, "Puck"},
+    {0, 0x22, "Finger"},
+    {0, 0x30, "TipPressure"},
+    {0, 0x31, "BarrelPressure"},
+    {0, 0x32, "InRange"},
+    {0, 0x33, "Touch"},
+    {0, 0x34, "UnTouch"},
+    {0, 0x35, "Tap"},
+    {0, 0x39, "TabletFunctionKey"},
+    {0, 0x3a, "ProgramChangeKey"},
+    {0, 0x3c, "Invert"},
+    {0, 0x42, "TipSwitch"},
+    {0, 0x43, "SecondaryTipSwitch"},
+    {0, 0x44, "BarrelSwitch"},
+    {0, 0x45, "Eraser"},
+    {0, 0x46, "TabletPick"},
+  { 15, 0, "PhysicalInterfaceDevice" },
+    {0, 0x00, "Undefined"},
+    {0, 0x01, "Physical_Interface_Device"},
+      {0, 0x20, "Normal"},
+    {0, 0x21, "Set_Effect_Report"},
+      {0, 0x22, "Effect_Block_Index"},
+      {0, 0x23, "Parameter_Block_Offset"},
+      {0, 0x24, "ROM_Flag"},
+      {0, 0x25, "Effect_Type"},
+        {0, 0x26, "ET_Constant_Force"},
+        {0, 0x27, "ET_Ramp"},
+        {0, 0x28, "ET_Custom_Force_Data"},
+        {0, 0x30, "ET_Square"},
+        {0, 0x31, "ET_Sine"},
+        {0, 0x32, "ET_Triangle"},
+        {0, 0x33, "ET_Sawtooth_Up"},
+        {0, 0x34, "ET_Sawtooth_Down"},
+        {0, 0x40, "ET_Spring"},
+        {0, 0x41, "ET_Damper"},
+        {0, 0x42, "ET_Inertia"},
+        {0, 0x43, "ET_Friction"},
+      {0, 0x50, "Duration"},
+      {0, 0x51, "Sample_Period"},
+      {0, 0x52, "Gain"},
+      {0, 0x53, "Trigger_Button"},
+      {0, 0x54, "Trigger_Repeat_Interval"},
+      {0, 0x55, "Axes_Enable"},
+        {0, 0x56, "Direction_Enable"},
+      {0, 0x57, "Direction"},
+      {0, 0x58, "Type_Specific_Block_Offset"},
+        {0, 0x59, "Block_Type"},
+        {0, 0x5A, "Set_Envelope_Report"},
+          {0, 0x5B, "Attack_Level"},
+          {0, 0x5C, "Attack_Time"},
+          {0, 0x5D, "Fade_Level"},
+          {0, 0x5E, "Fade_Time"},
+        {0, 0x5F, "Set_Condition_Report"},
+        {0, 0x60, "CP_Offset"},
+        {0, 0x61, "Positive_Coefficient"},
+        {0, 0x62, "Negative_Coefficient"},
+        {0, 0x63, "Positive_Saturation"},
+        {0, 0x64, "Negative_Saturation"},
+        {0, 0x65, "Dead_Band"},
+      {0, 0x66, "Download_Force_Sample"},
+      {0, 0x67, "Isoch_Custom_Force_Enable"},
+      {0, 0x68, "Custom_Force_Data_Report"},
+        {0, 0x69, "Custom_Force_Data"},
+        {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
+      {0, 0x6B, "Set_Custom_Force_Report"},
+        {0, 0x6C, "Custom_Force_Data_Offset"},
+        {0, 0x6D, "Sample_Count"},
+      {0, 0x6E, "Set_Periodic_Report"},
+        {0, 0x6F, "Offset"},
+        {0, 0x70, "Magnitude"},
+        {0, 0x71, "Phase"},
+        {0, 0x72, "Period"},
+      {0, 0x73, "Set_Constant_Force_Report"},
+        {0, 0x74, "Set_Ramp_Force_Report"},
+        {0, 0x75, "Ramp_Start"},
+        {0, 0x76, "Ramp_End"},
+      {0, 0x77, "Effect_Operation_Report"},
+        {0, 0x78, "Effect_Operation"},
+          {0, 0x79, "Op_Effect_Start"},
+          {0, 0x7A, "Op_Effect_Start_Solo"},
+          {0, 0x7B, "Op_Effect_Stop"},
+          {0, 0x7C, "Loop_Count"},
+      {0, 0x7D, "Device_Gain_Report"},
+        {0, 0x7E, "Device_Gain"},
+    {0, 0x7F, "PID_Pool_Report"},
+      {0, 0x80, "RAM_Pool_Size"},
+      {0, 0x81, "ROM_Pool_Size"},
+      {0, 0x82, "ROM_Effect_Block_Count"},
+      {0, 0x83, "Simultaneous_Effects_Max"},
+      {0, 0x84, "Pool_Alignment"},
+    {0, 0x85, "PID_Pool_Move_Report"},
+      {0, 0x86, "Move_Source"},
+      {0, 0x87, "Move_Destination"},
+      {0, 0x88, "Move_Length"},
+    {0, 0x89, "PID_Block_Load_Report"},
+      {0, 0x8B, "Block_Load_Status"},
+      {0, 0x8C, "Block_Load_Success"},
+      {0, 0x8D, "Block_Load_Full"},
+      {0, 0x8E, "Block_Load_Error"},
+      {0, 0x8F, "Block_Handle"},
+      {0, 0x90, "PID_Block_Free_Report"},
+      {0, 0x91, "Type_Specific_Block_Handle"},
+    {0, 0x92, "PID_State_Report"},
+      {0, 0x94, "Effect_Playing"},
+      {0, 0x95, "PID_Device_Control_Report"},
+        {0, 0x96, "PID_Device_Control"},
+        {0, 0x97, "DC_Enable_Actuators"},
+        {0, 0x98, "DC_Disable_Actuators"},
+        {0, 0x99, "DC_Stop_All_Effects"},
+        {0, 0x9A, "DC_Device_Reset"},
+        {0, 0x9B, "DC_Device_Pause"},
+        {0, 0x9C, "DC_Device_Continue"},
+      {0, 0x9F, "Device_Paused"},
+      {0, 0xA0, "Actuators_Enabled"},
+      {0, 0xA4, "Safety_Switch"},
+      {0, 0xA5, "Actuator_Override_Switch"},
+      {0, 0xA6, "Actuator_Power"},
+    {0, 0xA7, "Start_Delay"},
+    {0, 0xA8, "Parameter_Block_Size"},
+    {0, 0xA9, "Device_Managed_Pool"},
+    {0, 0xAA, "Shared_Parameter_Blocks"},
+    {0, 0xAB, "Create_New_Effect_Report"},
+    {0, 0xAC, "RAM_Pool_Available"},
+  { 0x84, 0, "Power Device" },
+    { 0x84, 0x02, "PresentStatus" },
+    { 0x84, 0x03, "ChangeStatus" },
+    { 0x84, 0x04, "UPS" },
+    { 0x84, 0x05, "PowerSupply" },
+    { 0x84, 0x10, "BatterySystem" },
+    { 0x84, 0x11, "BatterySystemID" },
+    { 0x84, 0x12, "Battery" },
+    { 0x84, 0x13, "BatteryID" },
+    { 0x84, 0x14, "Charger" },
+    { 0x84, 0x15, "ChargerID" },
+    { 0x84, 0x16, "PowerConverter" },
+    { 0x84, 0x17, "PowerConverterID" },
+    { 0x84, 0x18, "OutletSystem" },
+    { 0x84, 0x19, "OutletSystemID" },
+    { 0x84, 0x1a, "Input" },
+    { 0x84, 0x1b, "InputID" },
+    { 0x84, 0x1c, "Output" },
+    { 0x84, 0x1d, "OutputID" },
+    { 0x84, 0x1e, "Flow" },
+    { 0x84, 0x1f, "FlowID" },
+    { 0x84, 0x20, "Outlet" },
+    { 0x84, 0x21, "OutletID" },
+    { 0x84, 0x22, "Gang" },
+    { 0x84, 0x24, "PowerSummary" },
+    { 0x84, 0x25, "PowerSummaryID" },
+    { 0x84, 0x30, "Voltage" },
+    { 0x84, 0x31, "Current" },
+    { 0x84, 0x32, "Frequency" },
+    { 0x84, 0x33, "ApparentPower" },
+    { 0x84, 0x35, "PercentLoad" },
+    { 0x84, 0x40, "ConfigVoltage" },
+    { 0x84, 0x41, "ConfigCurrent" },
+    { 0x84, 0x43, "ConfigApparentPower" },
+    { 0x84, 0x53, "LowVoltageTransfer" },
+    { 0x84, 0x54, "HighVoltageTransfer" },
+    { 0x84, 0x56, "DelayBeforeStartup" },
+    { 0x84, 0x57, "DelayBeforeShutdown" },
+    { 0x84, 0x58, "Test" },
+    { 0x84, 0x5a, "AudibleAlarmControl" },
+    { 0x84, 0x60, "Present" },
+    { 0x84, 0x61, "Good" },
+    { 0x84, 0x62, "InternalFailure" },
+    { 0x84, 0x65, "Overload" },
+    { 0x84, 0x66, "OverCharged" },
+    { 0x84, 0x67, "OverTemperature" },
+    { 0x84, 0x68, "ShutdownRequested" },
+    { 0x84, 0x69, "ShutdownImminent" },
+    { 0x84, 0x6b, "SwitchOn/Off" },
+    { 0x84, 0x6c, "Switchable" },
+    { 0x84, 0x6d, "Used" },
+    { 0x84, 0x6e, "Boost" },
+    { 0x84, 0x73, "CommunicationLost" },
+    { 0x84, 0xfd, "iManufacturer" },
+    { 0x84, 0xfe, "iProduct" },
+    { 0x84, 0xff, "iSerialNumber" },
+  { 0x85, 0, "Battery System" },
+    { 0x85, 0x01, "SMBBatteryMode" },
+    { 0x85, 0x02, "SMBBatteryStatus" },
+    { 0x85, 0x03, "SMBAlarmWarning" },
+    { 0x85, 0x04, "SMBChargerMode" },
+    { 0x85, 0x05, "SMBChargerStatus" },
+    { 0x85, 0x06, "SMBChargerSpecInfo" },
+    { 0x85, 0x07, "SMBSelectorState" },
+    { 0x85, 0x08, "SMBSelectorPresets" },
+    { 0x85, 0x09, "SMBSelectorInfo" },
+    { 0x85, 0x29, "RemainingCapacityLimit" },
+    { 0x85, 0x2c, "CapacityMode" },
+    { 0x85, 0x42, "BelowRemainingCapacityLimit" },
+    { 0x85, 0x44, "Charging" },
+    { 0x85, 0x45, "Discharging" },
+    { 0x85, 0x4b, "NeedReplacement" },
+    { 0x85, 0x66, "RemainingCapacity" },
+    { 0x85, 0x68, "RunTimeToEmpty" },
+    { 0x85, 0x6a, "AverageTimeToFull" },
+    { 0x85, 0x83, "DesignCapacity" },
+    { 0x85, 0x85, "ManufacturerDate" },
+    { 0x85, 0x89, "iDeviceChemistry" },
+    { 0x85, 0x8b, "Rechargable" },
+    { 0x85, 0x8f, "iOEMInformation" },
+    { 0x85, 0x8d, "CapacityGranularity1" },
+    { 0x85, 0xd0, "ACPresent" },
+  /* pages 0xff00 to 0xffff are vendor-specific */
+  { 0xffff, 0, "Vendor-specific-FF" },
+  { 0, 0, NULL }
+};
+
+static void resolv_usage_page(unsigned page) {
+	const struct hid_usage_entry *p;
+
+	for (p = hid_usage_table; p->description; p++)
+		if (p->page == page) {
+			printk("%s", p->description);
+			return;
+		}
+	printk("%04x", page);
+}
+
+void hid_resolv_usage(unsigned usage) {
+	const struct hid_usage_entry *p;
+
+	resolv_usage_page(usage >> 16);
+	printk(".");
+	for (p = hid_usage_table; p->description; p++)
+		if (p->page == (usage >> 16)) {
+			for(++p; p->description && p->usage != 0; p++)
+				if (p->usage == (usage & 0xffff)) {
+					printk("%s", p->description);
+					return;
+				}
+			break;
+		}
+	printk("%04x", usage & 0xffff);
+}
+EXPORT_SYMBOL_GPL(hid_resolv_usage);
+
+__inline__ static void tab(int n) {
+	while (n--) printk(" ");
+}
+
+void hid_dump_field(struct hid_field *field, int n) {
+	int j;
+
+	if (field->physical) {
+		tab(n);
+		printk("Physical(");
+		hid_resolv_usage(field->physical); printk(")\n");
+	}
+	if (field->logical) {
+		tab(n);
+		printk("Logical(");
+		hid_resolv_usage(field->logical); printk(")\n");
+	}
+	tab(n); printk("Usage(%d)\n", field->maxusage);
+	for (j = 0; j < field->maxusage; j++) {
+		tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n");
+	}
+	if (field->logical_minimum != field->logical_maximum) {
+		tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
+		tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
+	}
+	if (field->physical_minimum != field->physical_maximum) {
+		tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
+		tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
+	}
+	if (field->unit_exponent) {
+		tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
+	}
+	if (field->unit) {
+		char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
+		char *units[5][8] = {
+			{ "None", "None", "None", "None", "None", "None", "None", "None" },
+			{ "None", "Centimeter", "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
+			{ "None", "Radians",    "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
+			{ "None", "Inch",       "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
+			{ "None", "Degrees",    "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
+		};
+
+		int i;
+		int sys;
+                __u32 data = field->unit;
+
+		/* First nibble tells us which system we're in. */
+		sys = data & 0xf;
+		data >>= 4;
+
+		if(sys > 4) {
+			tab(n); printk("Unit(Invalid)\n");
+		}
+		else {
+			int earlier_unit = 0;
+
+			tab(n); printk("Unit(%s : ", systems[sys]);
+
+			for (i=1 ; i<sizeof(__u32)*2 ; i++) {
+				char nibble = data & 0xf;
+				data >>= 4;
+				if (nibble != 0) {
+					if(earlier_unit++ > 0)
+						printk("*");
+					printk("%s", units[sys][i]);
+					if(nibble != 1) {
+						/* This is a _signed_ nibble(!) */
+
+						int val = nibble & 0x7;
+						if(nibble & 0x08)
+							val = -((0x7 & ~val) +1);
+						printk("^%d", val);
+					}
+				}
+			}
+			printk(")\n");
+		}
+	}
+	tab(n); printk("Report Size(%u)\n", field->report_size);
+	tab(n); printk("Report Count(%u)\n", field->report_count);
+	tab(n); printk("Report Offset(%u)\n", field->report_offset);
+
+	tab(n); printk("Flags( ");
+	j = field->flags;
+	printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
+	printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
+	printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
+	printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
+	printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
+	printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
+	printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
+	printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
+	printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
+	printk(")\n");
+}
+EXPORT_SYMBOL_GPL(hid_dump_field);
+
+void hid_dump_device(struct hid_device *device) {
+	struct hid_report_enum *report_enum;
+	struct hid_report *report;
+	struct list_head *list;
+	unsigned i,k;
+	static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
+
+	for (i = 0; i < HID_REPORT_TYPES; i++) {
+		report_enum = device->report_enum + i;
+		list = report_enum->report_list.next;
+		while (list != &report_enum->report_list) {
+			report = (struct hid_report *) list;
+			tab(2);
+			printk("%s", table[i]);
+			if (report->id)
+				printk("(%d)", report->id);
+			printk("[%s]", table[report->type]);
+			printk("\n");
+			for (k = 0; k < report->maxfield; k++) {
+				tab(4);
+				printk("Field(%d)\n", k);
+				hid_dump_field(report->field[k], 6);
+			}
+			list = list->next;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(hid_dump_device);
+
+void hid_dump_input(struct hid_usage *usage, __s32 value) {
+	printk("hid-debug: input ");
+	hid_resolv_usage(usage->hid);
+	printk(" = %d\n", value);
+}
+EXPORT_SYMBOL_GPL(hid_dump_input);
+
+static char *events[EV_MAX + 1] = {
+	[EV_SYN] = "Sync",			[EV_KEY] = "Key",
+	[EV_REL] = "Relative",			[EV_ABS] = "Absolute",
+	[EV_MSC] = "Misc",			[EV_LED] = "LED",
+	[EV_SND] = "Sound",			[EV_REP] = "Repeat",
+	[EV_FF] = "ForceFeedback",		[EV_PWR] = "Power",
+	[EV_FF_STATUS] = "ForceFeedbackStatus",
+};
+
+static char *syncs[2] = {
+	[SYN_REPORT] = "Report",		[SYN_CONFIG] = "Config",
+};
+static char *keys[KEY_MAX + 1] = {
+	[KEY_RESERVED] = "Reserved",		[KEY_ESC] = "Esc",
+	[KEY_1] = "1",				[KEY_2] = "2",
+	[KEY_3] = "3",				[KEY_4] = "4",
+	[KEY_5] = "5",				[KEY_6] = "6",
+	[KEY_7] = "7",				[KEY_8] = "8",
+	[KEY_9] = "9",				[KEY_0] = "0",
+	[KEY_MINUS] = "Minus",			[KEY_EQUAL] = "Equal",
+	[KEY_BACKSPACE] = "Backspace",		[KEY_TAB] = "Tab",
+	[KEY_Q] = "Q",				[KEY_W] = "W",
+	[KEY_E] = "E",				[KEY_R] = "R",
+	[KEY_T] = "T",				[KEY_Y] = "Y",
+	[KEY_U] = "U",				[KEY_I] = "I",
+	[KEY_O] = "O",				[KEY_P] = "P",
+	[KEY_LEFTBRACE] = "LeftBrace",		[KEY_RIGHTBRACE] = "RightBrace",
+	[KEY_ENTER] = "Enter",			[KEY_LEFTCTRL] = "LeftControl",
+	[KEY_A] = "A",				[KEY_S] = "S",
+	[KEY_D] = "D",				[KEY_F] = "F",
+	[KEY_G] = "G",				[KEY_H] = "H",
+	[KEY_J] = "J",				[KEY_K] = "K",
+	[KEY_L] = "L",				[KEY_SEMICOLON] = "Semicolon",
+	[KEY_APOSTROPHE] = "Apostrophe",	[KEY_GRAVE] = "Grave",
+	[KEY_LEFTSHIFT] = "LeftShift",		[KEY_BACKSLASH] = "BackSlash",
+	[KEY_Z] = "Z",				[KEY_X] = "X",
+	[KEY_C] = "C",				[KEY_V] = "V",
+	[KEY_B] = "B",				[KEY_N] = "N",
+	[KEY_M] = "M",				[KEY_COMMA] = "Comma",
+	[KEY_DOT] = "Dot",			[KEY_SLASH] = "Slash",
+	[KEY_RIGHTSHIFT] = "RightShift",	[KEY_KPASTERISK] = "KPAsterisk",
+	[KEY_LEFTALT] = "LeftAlt",		[KEY_SPACE] = "Space",
+	[KEY_CAPSLOCK] = "CapsLock",		[KEY_F1] = "F1",
+	[KEY_F2] = "F2",			[KEY_F3] = "F3",
+	[KEY_F4] = "F4",			[KEY_F5] = "F5",
+	[KEY_F6] = "F6",			[KEY_F7] = "F7",
+	[KEY_F8] = "F8",			[KEY_F9] = "F9",
+	[KEY_F10] = "F10",			[KEY_NUMLOCK] = "NumLock",
+	[KEY_SCROLLLOCK] = "ScrollLock",	[KEY_KP7] = "KP7",
+	[KEY_KP8] = "KP8",			[KEY_KP9] = "KP9",
+	[KEY_KPMINUS] = "KPMinus",		[KEY_KP4] = "KP4",
+	[KEY_KP5] = "KP5",			[KEY_KP6] = "KP6",
+	[KEY_KPPLUS] = "KPPlus",		[KEY_KP1] = "KP1",
+	[KEY_KP2] = "KP2",			[KEY_KP3] = "KP3",
+	[KEY_KP0] = "KP0",			[KEY_KPDOT] = "KPDot",
+	[KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
+	[KEY_F11] = "F11",			[KEY_F12] = "F12",
+	[KEY_RO] = "RO",			[KEY_KATAKANA] = "Katakana",
+	[KEY_HIRAGANA] = "HIRAGANA",		[KEY_HENKAN] = "Henkan",
+	[KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
+	[KEY_KPJPCOMMA] = "KPJpComma",		[KEY_KPENTER] = "KPEnter",
+	[KEY_RIGHTCTRL] = "RightCtrl",		[KEY_KPSLASH] = "KPSlash",
+	[KEY_SYSRQ] = "SysRq",			[KEY_RIGHTALT] = "RightAlt",
+	[KEY_LINEFEED] = "LineFeed",		[KEY_HOME] = "Home",
+	[KEY_UP] = "Up",			[KEY_PAGEUP] = "PageUp",
+	[KEY_LEFT] = "Left",			[KEY_RIGHT] = "Right",
+	[KEY_END] = "End",			[KEY_DOWN] = "Down",
+	[KEY_PAGEDOWN] = "PageDown",		[KEY_INSERT] = "Insert",
+	[KEY_DELETE] = "Delete",		[KEY_MACRO] = "Macro",
+	[KEY_MUTE] = "Mute",			[KEY_VOLUMEDOWN] = "VolumeDown",
+	[KEY_VOLUMEUP] = "VolumeUp",		[KEY_POWER] = "Power",
+	[KEY_KPEQUAL] = "KPEqual",		[KEY_KPPLUSMINUS] = "KPPlusMinus",
+	[KEY_PAUSE] = "Pause",			[KEY_KPCOMMA] = "KPComma",
+	[KEY_HANGUEL] = "Hangeul",		[KEY_HANJA] = "Hanja",
+	[KEY_YEN] = "Yen",			[KEY_LEFTMETA] = "LeftMeta",
+	[KEY_RIGHTMETA] = "RightMeta",		[KEY_COMPOSE] = "Compose",
+	[KEY_STOP] = "Stop",			[KEY_AGAIN] = "Again",
+	[KEY_PROPS] = "Props",			[KEY_UNDO] = "Undo",
+	[KEY_FRONT] = "Front",			[KEY_COPY] = "Copy",
+	[KEY_OPEN] = "Open",			[KEY_PASTE] = "Paste",
+	[KEY_FIND] = "Find",			[KEY_CUT] = "Cut",
+	[KEY_HELP] = "Help",			[KEY_MENU] = "Menu",
+	[KEY_CALC] = "Calc",			[KEY_SETUP] = "Setup",
+	[KEY_SLEEP] = "Sleep",			[KEY_WAKEUP] = "WakeUp",
+	[KEY_FILE] = "File",			[KEY_SENDFILE] = "SendFile",
+	[KEY_DELETEFILE] = "DeleteFile",	[KEY_XFER] = "X-fer",
+	[KEY_PROG1] = "Prog1",			[KEY_PROG2] = "Prog2",
+	[KEY_WWW] = "WWW",			[KEY_MSDOS] = "MSDOS",
+	[KEY_COFFEE] = "Coffee",		[KEY_DIRECTION] = "Direction",
+	[KEY_CYCLEWINDOWS] = "CycleWindows",	[KEY_MAIL] = "Mail",
+	[KEY_BOOKMARKS] = "Bookmarks",		[KEY_COMPUTER] = "Computer",
+	[KEY_BACK] = "Back",			[KEY_FORWARD] = "Forward",
+	[KEY_CLOSECD] = "CloseCD",		[KEY_EJECTCD] = "EjectCD",
+	[KEY_EJECTCLOSECD] = "EjectCloseCD",	[KEY_NEXTSONG] = "NextSong",
+	[KEY_PLAYPAUSE] = "PlayPause",		[KEY_PREVIOUSSONG] = "PreviousSong",
+	[KEY_STOPCD] = "StopCD",		[KEY_RECORD] = "Record",
+	[KEY_REWIND] = "Rewind",		[KEY_PHONE] = "Phone",
+	[KEY_ISO] = "ISOKey",			[KEY_CONFIG] = "Config",
+	[KEY_HOMEPAGE] = "HomePage",		[KEY_REFRESH] = "Refresh",
+	[KEY_EXIT] = "Exit",			[KEY_MOVE] = "Move",
+	[KEY_EDIT] = "Edit",			[KEY_SCROLLUP] = "ScrollUp",
+	[KEY_SCROLLDOWN] = "ScrollDown",	[KEY_KPLEFTPAREN] = "KPLeftParenthesis",
+	[KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
+	[KEY_REDO] = "Redo",			[KEY_F13] = "F13",
+	[KEY_F14] = "F14",			[KEY_F15] = "F15",
+	[KEY_F16] = "F16",			[KEY_F17] = "F17",
+	[KEY_F18] = "F18",			[KEY_F19] = "F19",
+	[KEY_F20] = "F20",			[KEY_F21] = "F21",
+	[KEY_F22] = "F22",			[KEY_F23] = "F23",
+	[KEY_F24] = "F24",			[KEY_PLAYCD] = "PlayCD",
+	[KEY_PAUSECD] = "PauseCD",		[KEY_PROG3] = "Prog3",
+	[KEY_PROG4] = "Prog4",			[KEY_SUSPEND] = "Suspend",
+	[KEY_CLOSE] = "Close",			[KEY_PLAY] = "Play",
+	[KEY_FASTFORWARD] = "FastForward",	[KEY_BASSBOOST] = "BassBoost",
+	[KEY_PRINT] = "Print",			[KEY_HP] = "HP",
+	[KEY_CAMERA] = "Camera",		[KEY_SOUND] = "Sound",
+	[KEY_QUESTION] = "Question",		[KEY_EMAIL] = "Email",
+	[KEY_CHAT] = "Chat",			[KEY_SEARCH] = "Search",
+	[KEY_CONNECT] = "Connect",		[KEY_FINANCE] = "Finance",
+	[KEY_SPORT] = "Sport",			[KEY_SHOP] = "Shop",
+	[KEY_ALTERASE] = "AlternateErase",	[KEY_CANCEL] = "Cancel",
+	[KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
+	[KEY_MEDIA] = "Media",			[KEY_UNKNOWN] = "Unknown",
+	[BTN_0] = "Btn0",			[BTN_1] = "Btn1",
+	[BTN_2] = "Btn2",			[BTN_3] = "Btn3",
+	[BTN_4] = "Btn4",			[BTN_5] = "Btn5",
+	[BTN_6] = "Btn6",			[BTN_7] = "Btn7",
+	[BTN_8] = "Btn8",			[BTN_9] = "Btn9",
+	[BTN_LEFT] = "LeftBtn",			[BTN_RIGHT] = "RightBtn",
+	[BTN_MIDDLE] = "MiddleBtn",		[BTN_SIDE] = "SideBtn",
+	[BTN_EXTRA] = "ExtraBtn",		[BTN_FORWARD] = "ForwardBtn",
+	[BTN_BACK] = "BackBtn",			[BTN_TASK] = "TaskBtn",
+	[BTN_TRIGGER] = "Trigger",		[BTN_THUMB] = "ThumbBtn",
+	[BTN_THUMB2] = "ThumbBtn2",		[BTN_TOP] = "TopBtn",
+	[BTN_TOP2] = "TopBtn2",			[BTN_PINKIE] = "PinkieBtn",
+	[BTN_BASE] = "BaseBtn",			[BTN_BASE2] = "BaseBtn2",
+	[BTN_BASE3] = "BaseBtn3",		[BTN_BASE4] = "BaseBtn4",
+	[BTN_BASE5] = "BaseBtn5",		[BTN_BASE6] = "BaseBtn6",
+	[BTN_DEAD] = "BtnDead",			[BTN_A] = "BtnA",
+	[BTN_B] = "BtnB",			[BTN_C] = "BtnC",
+	[BTN_X] = "BtnX",			[BTN_Y] = "BtnY",
+	[BTN_Z] = "BtnZ",			[BTN_TL] = "BtnTL",
+	[BTN_TR] = "BtnTR",			[BTN_TL2] = "BtnTL2",
+	[BTN_TR2] = "BtnTR2",			[BTN_SELECT] = "BtnSelect",
+	[BTN_START] = "BtnStart",		[BTN_MODE] = "BtnMode",
+	[BTN_THUMBL] = "BtnThumbL",		[BTN_THUMBR] = "BtnThumbR",
+	[BTN_TOOL_PEN] = "ToolPen",		[BTN_TOOL_RUBBER] = "ToolRubber",
+	[BTN_TOOL_BRUSH] = "ToolBrush",		[BTN_TOOL_PENCIL] = "ToolPencil",
+	[BTN_TOOL_AIRBRUSH] = "ToolAirbrush",	[BTN_TOOL_FINGER] = "ToolFinger",
+	[BTN_TOOL_MOUSE] = "ToolMouse",		[BTN_TOOL_LENS] = "ToolLens",
+	[BTN_TOUCH] = "Touch",			[BTN_STYLUS] = "Stylus",
+	[BTN_STYLUS2] = "Stylus2",		[BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
+	[BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
+	[BTN_GEAR_UP] = "Gear up",		[KEY_OK] = "Ok",
+	[KEY_SELECT] = "Select",		[KEY_GOTO] = "Goto",
+	[KEY_CLEAR] = "Clear",			[KEY_POWER2] = "Power2",
+	[KEY_OPTION] = "Option",		[KEY_INFO] = "Info",
+	[KEY_TIME] = "Time",			[KEY_VENDOR] = "Vendor",
+	[KEY_ARCHIVE] = "Archive",		[KEY_PROGRAM] = "Program",
+	[KEY_CHANNEL] = "Channel",		[KEY_FAVORITES] = "Favorites",
+	[KEY_EPG] = "EPG",			[KEY_PVR] = "PVR",
+	[KEY_MHP] = "MHP",			[KEY_LANGUAGE] = "Language",
+	[KEY_TITLE] = "Title",			[KEY_SUBTITLE] = "Subtitle",
+	[KEY_ANGLE] = "Angle",			[KEY_ZOOM] = "Zoom",
+	[KEY_MODE] = "Mode",			[KEY_KEYBOARD] = "Keyboard",
+	[KEY_SCREEN] = "Screen",		[KEY_PC] = "PC",
+	[KEY_TV] = "TV",			[KEY_TV2] = "TV2",
+	[KEY_VCR] = "VCR",			[KEY_VCR2] = "VCR2",
+	[KEY_SAT] = "Sat",			[KEY_SAT2] = "Sat2",
+	[KEY_CD] = "CD",			[KEY_TAPE] = "Tape",
+	[KEY_RADIO] = "Radio",			[KEY_TUNER] = "Tuner",
+	[KEY_PLAYER] = "Player",		[KEY_TEXT] = "Text",
+	[KEY_DVD] = "DVD",			[KEY_AUX] = "Aux",
+	[KEY_MP3] = "MP3",			[KEY_AUDIO] = "Audio",
+	[KEY_VIDEO] = "Video",			[KEY_DIRECTORY] = "Directory",
+	[KEY_LIST] = "List",			[KEY_MEMO] = "Memo",
+	[KEY_CALENDAR] = "Calendar",		[KEY_RED] = "Red",
+	[KEY_GREEN] = "Green",			[KEY_YELLOW] = "Yellow",
+	[KEY_BLUE] = "Blue",			[KEY_CHANNELUP] = "ChannelUp",
+	[KEY_CHANNELDOWN] = "ChannelDown",	[KEY_FIRST] = "First",
+	[KEY_LAST] = "Last",			[KEY_AB] = "AB",
+	[KEY_NEXT] = "Next",			[KEY_RESTART] = "Restart",
+	[KEY_SLOW] = "Slow",			[KEY_SHUFFLE] = "Shuffle",
+	[KEY_BREAK] = "Break",			[KEY_PREVIOUS] = "Previous",
+	[KEY_DIGITS] = "Digits",		[KEY_TEEN] = "TEEN",
+	[KEY_TWEN] = "TWEN",			[KEY_DEL_EOL] = "DeleteEOL",
+	[KEY_DEL_EOS] = "DeleteEOS",		[KEY_INS_LINE] = "InsertLine",
+	[KEY_DEL_LINE] = "DeleteLine",
+	[KEY_SEND] = "Send",			[KEY_REPLY] = "Reply",
+	[KEY_FORWARDMAIL] = "ForwardMail",	[KEY_SAVE] = "Save",
+	[KEY_DOCUMENTS] = "Documents",
+	[KEY_FN] = "Fn",			[KEY_FN_ESC] = "Fn+ESC",
+	[KEY_FN_1] = "Fn+1",			[KEY_FN_2] = "Fn+2",
+	[KEY_FN_B] = "Fn+B",			[KEY_FN_D] = "Fn+D",
+	[KEY_FN_E] = "Fn+E",			[KEY_FN_F] = "Fn+F",
+	[KEY_FN_S] = "Fn+S",
+	[KEY_FN_F1] = "Fn+F1",			[KEY_FN_F2] = "Fn+F2",
+	[KEY_FN_F3] = "Fn+F3",			[KEY_FN_F4] = "Fn+F4",
+	[KEY_FN_F5] = "Fn+F5",			[KEY_FN_F6] = "Fn+F6",
+	[KEY_FN_F7] = "Fn+F7",			[KEY_FN_F8] = "Fn+F8",
+	[KEY_FN_F9] = "Fn+F9",			[KEY_FN_F10] = "Fn+F10",
+	[KEY_FN_F11] = "Fn+F11",		[KEY_FN_F12] = "Fn+F12",
+	[KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
+	[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
+	[KEY_KBDILLUMUP] = "KbdIlluminationUp",
+	[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
+};
+
+static char *relatives[REL_MAX + 1] = {
+	[REL_X] = "X",			[REL_Y] = "Y",
+	[REL_Z] = "Z",			[REL_RX] = "Rx",
+	[REL_RY] = "Ry",		[REL_RZ] = "Rz",
+	[REL_HWHEEL] = "HWheel",	[REL_DIAL] = "Dial",
+	[REL_WHEEL] = "Wheel",		[REL_MISC] = "Misc",
+};
+
+static char *absolutes[ABS_MAX + 1] = {
+	[ABS_X] = "X",			[ABS_Y] = "Y",
+	[ABS_Z] = "Z",			[ABS_RX] = "Rx",
+	[ABS_RY] = "Ry",		[ABS_RZ] = "Rz",
+	[ABS_THROTTLE] = "Throttle",	[ABS_RUDDER] = "Rudder",
+	[ABS_WHEEL] = "Wheel",		[ABS_GAS] = "Gas",
+	[ABS_BRAKE] = "Brake",		[ABS_HAT0X] = "Hat0X",
+	[ABS_HAT0Y] = "Hat0Y",		[ABS_HAT1X] = "Hat1X",
+	[ABS_HAT1Y] = "Hat1Y",		[ABS_HAT2X] = "Hat2X",
+	[ABS_HAT2Y] = "Hat2Y",		[ABS_HAT3X] = "Hat3X",
+	[ABS_HAT3Y] = "Hat 3Y",		[ABS_PRESSURE] = "Pressure",
+	[ABS_DISTANCE] = "Distance",	[ABS_TILT_X] = "XTilt",
+	[ABS_TILT_Y] = "YTilt",		[ABS_TOOL_WIDTH] = "Tool Width",
+	[ABS_VOLUME] = "Volume",	[ABS_MISC] = "Misc",
+};
+
+static char *misc[MSC_MAX + 1] = {
+	[MSC_SERIAL] = "Serial",	[MSC_PULSELED] = "Pulseled",
+	[MSC_GESTURE] = "Gesture",	[MSC_RAW] = "RawData"
+};
+
+static char *leds[LED_MAX + 1] = {
+	[LED_NUML] = "NumLock",		[LED_CAPSL] = "CapsLock",
+	[LED_SCROLLL] = "ScrollLock",	[LED_COMPOSE] = "Compose",
+	[LED_KANA] = "Kana",		[LED_SLEEP] = "Sleep",
+	[LED_SUSPEND] = "Suspend",	[LED_MUTE] = "Mute",
+	[LED_MISC] = "Misc",
+};
+
+static char *repeats[REP_MAX + 1] = {
+	[REP_DELAY] = "Delay",		[REP_PERIOD] = "Period"
+};
+
+static char *sounds[SND_MAX + 1] = {
+	[SND_CLICK] = "Click",		[SND_BELL] = "Bell",
+	[SND_TONE] = "Tone"
+};
+
+static char **names[EV_MAX + 1] = {
+	[EV_SYN] = syncs,			[EV_KEY] = keys,
+	[EV_REL] = relatives,			[EV_ABS] = absolutes,
+	[EV_MSC] = misc,			[EV_LED] = leds,
+	[EV_SND] = sounds,			[EV_REP] = repeats,
+};
+
+void hid_resolv_event(__u8 type, __u16 code) {
+
+	printk("%s.%s", events[type] ? events[type] : "?",
+		names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
+}
+EXPORT_SYMBOL_GPL(hid_resolv_event);
+
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 9986380..25d180a 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -30,11 +30,14 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
-#include <linux/usb/input.h>
-
-#undef DEBUG
 
 #include <linux/hid.h>
+#include <linux/hid-debug.h>
+
+static int hid_pb_fnmode = 1;
+module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
+MODULE_PARM_DESC(pb_fnmode,
+		"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
 
 #define unk	KEY_UNKNOWN
 
@@ -68,6 +71,7 @@
 #define map_led(c)	do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
 
 #define map_abs_clear(c)	do { map_abs(c); clear_bit(c, bit); } while (0)
+#define map_rel_clear(c)	do { map_rel(c); clear_bit(c, bit); } while (0)
 #define map_key_clear(c)	do { map_key(c); clear_bit(c, bit); } while (0)
 
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
@@ -154,7 +158,7 @@
 		return 1;
 	}
 
-	if (hid->pb_fnmode) {
+	if (hid_pb_fnmode) {
 		int do_translate;
 
 		trans = find_translation(powerbook_fn_keys, usage->code);
@@ -163,8 +167,8 @@
 				do_translate = 1;
 			else if (trans->flags & POWERBOOK_FLAG_FKEY)
 				do_translate =
-					(hid->pb_fnmode == 2 &&  (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
-					(hid->pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
+					(hid_pb_fnmode == 2 &&  (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
+					(hid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
 			else
 				do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
 
@@ -247,9 +251,9 @@
 
 	field->hidinput = hidinput;
 
-#ifdef DEBUG
+#ifdef CONFIG_HID_DEBUG
 	printk(KERN_DEBUG "Mapping: ");
-	resolv_usage(usage->hid);
+	hid_resolv_usage(usage->hid);
 	printk(" ---> ");
 #endif
 
@@ -292,7 +296,7 @@
 					}
 			}
 
-			map_key(code);
+			map_key_clear(code);
 			break;
 
 
@@ -343,9 +347,9 @@
 				case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
 				case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
 					if (field->flags & HID_MAIN_ITEM_RELATIVE)
-						map_rel(usage->hid & 0xf);
+						map_rel_clear(usage->hid & 0xf);
 					else
-						map_abs(usage->hid & 0xf);
+						map_abs_clear(usage->hid & 0xf);
 					break;
 
 				case HID_GD_HATSWITCH:
@@ -363,9 +367,22 @@
 			break;
 
 		case HID_UP_LED:
-			if (((usage->hid - 1) & 0xffff) >= LED_MAX)
-				goto ignore;
-			map_led((usage->hid - 1) & 0xffff);
+
+			switch (usage->hid & 0xffff) {                        /* HID-Value:                   */
+				case 0x01:  map_led (LED_NUML);     break;    /*   "Num Lock"                 */
+				case 0x02:  map_led (LED_CAPSL);    break;    /*   "Caps Lock"                */
+				case 0x03:  map_led (LED_SCROLLL);  break;    /*   "Scroll Lock"              */
+				case 0x04:  map_led (LED_COMPOSE);  break;    /*   "Compose"                  */
+				case 0x05:  map_led (LED_KANA);     break;    /*   "Kana"                     */
+				case 0x27:  map_led (LED_SLEEP);    break;    /*   "Stand-By"                 */
+				case 0x4c:  map_led (LED_SUSPEND);  break;    /*   "System Suspend"           */
+				case 0x09:  map_led (LED_MUTE);     break;    /*   "Mute"                     */
+				case 0x4b:  map_led (LED_MISC);     break;    /*   "Generic Indicator"        */
+				case 0x19:  map_led (LED_MAIL);     break;    /*   "Message Waiting"          */
+				case 0x4d:  map_led (LED_CHARGING); break;    /*   "External Power Connected" */
+
+				default: goto ignore;
+			}
 			break;
 
 		case HID_UP_DIGITIZER:
@@ -418,6 +435,7 @@
 				case 0x040: map_key_clear(KEY_MENU);		break;
 				case 0x045: map_key_clear(KEY_RADIO);		break;
 
+				case 0x083: map_key_clear(KEY_LAST);		break;
 				case 0x088: map_key_clear(KEY_PC);		break;
 				case 0x089: map_key_clear(KEY_TV);		break;
 				case 0x08a: map_key_clear(KEY_WWW);		break;
@@ -435,6 +453,7 @@
 				case 0x096: map_key_clear(KEY_TAPE);		break;
 				case 0x097: map_key_clear(KEY_TV2);		break;
 				case 0x098: map_key_clear(KEY_SAT);		break;
+				case 0x09a: map_key_clear(KEY_PVR);		break;
 
 				case 0x09c: map_key_clear(KEY_CHANNELUP);	break;
 				case 0x09d: map_key_clear(KEY_CHANNELDOWN);	break;
@@ -500,7 +519,7 @@
 				case 0x22f: map_key_clear(KEY_ZOOMRESET);	break;
 				case 0x233: map_key_clear(KEY_SCROLLUP);	break;
 				case 0x234: map_key_clear(KEY_SCROLLDOWN);	break;
-				case 0x238: map_rel(REL_HWHEEL);		break;
+				case 0x238: map_rel_clear(REL_HWHEEL);		break;
 				case 0x25f: map_key_clear(KEY_CANCEL);		break;
 				case 0x279: map_key_clear(KEY_REDO);		break;
 
@@ -662,14 +681,14 @@
 			field->dpad = usage->code;
 	}
 
-#ifdef DEBUG
-	resolv_event(usage->type, usage->code);
+	hid_resolv_event(usage->type, usage->code);
+#ifdef CONFIG_HID_DEBUG
 	printk("\n");
 #endif
 	return;
 
 ignore:
-#ifdef DEBUG
+#ifdef CONFIG_HID_DEBUG
 	printk("IGNORED\n");
 #endif
 	return;
@@ -784,6 +803,18 @@
 }
 EXPORT_SYMBOL_GPL(hidinput_find_field);
 
+static int hidinput_open(struct input_dev *dev)
+{
+	struct hid_device *hid = dev->private;
+	return hid->hid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+	struct hid_device *hid = dev->private;
+	hid->hid_close(hid);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -796,6 +827,7 @@
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
 	int i, j, k;
+	int max_report_type = HID_OUTPUT_REPORT;
 
 	INIT_LIST_HEAD(&hid->inputs);
 
@@ -808,7 +840,10 @@
 	if (i == hid->maxcollection)
 		return -1;
 
-	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
+	if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
+		max_report_type = HID_INPUT_REPORT;
+
+	for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
 		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
 
 			if (!report->maxfield)
@@ -826,8 +861,8 @@
 
 				input_dev->private = hid;
 				input_dev->event = hid->hidinput_input_event;
-				input_dev->open = hid->hidinput_open;
-				input_dev->close = hid->hidinput_close;
+				input_dev->open = hidinput_open;
+				input_dev->close = hidinput_close;
 
 				input_dev->name = hid->name;
 				input_dev->phys = hid->phys;
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 31c4200..b80f6ed 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -93,7 +93,7 @@
 	case 110:		/* Intel Conroe */
 				/* compute in uV, round to mV */
 		val &= 0xff;
-		if(((val & 0x7e) == 0xfe) || (!(val & 0x7e)))
+		if (val < 0x02 || val > 0xb2)
 			return 0;
 		return((1600000 - (val - 2) * 6250 + 500) / 1000);
 	case 24:                /* Opteron processor */
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index c12ac5a..253ffaf 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -117,6 +117,7 @@
 /* Low Bits of Vcore A/B Vtt Read/High/Low */
 static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 };
 static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 };
+static u8 scale_in_add[] = { 0, 0, 0, 0, 0, 0, 0, 150, 150, 0 };
 
 #define W83793_REG_FAN(index)		(0x23 + 2 * (index))	/* High byte */
 #define W83793_REG_FAN_MIN(index)	(0x90 + 2 * (index))	/* High byte */
@@ -203,6 +204,8 @@
 	u8 temp_fan_map[6];	/* Temp controls which pwm fan, bit field */
 
 	u8 has_pwm;
+	u8 has_temp;
+	u8 has_vid;
 	u8 pwm_enable;		/* Register value, each Temp has 1 bit */
 	u8 pwm_uptime;		/* Register value */
 	u8 pwm_downtime;	/* Register value */
@@ -500,7 +503,7 @@
 	each has 4 mode:(2 bits)
 	0:	Stop monitor
 	1:	Use internal temp sensor(default)
-	2:	Use sensor in AMD CPU and get result by AMDSI
+	2:	Reserved
 	3:	Use sensor in Intel CPU and get result by PECI
 
 	TR1-TR2
@@ -509,8 +512,8 @@
 	1:	To enable temp sensors monitor
 */
 
-/* 0 disable, 5 AMDSI, 6 PECI */
-static u8 TO_TEMP_MODE[] = { 0, 0, 5, 6 };
+/* 0 disable, 6 PECI */
+static u8 TO_TEMP_MODE[] = { 0, 0, 0, 6 };
 
 static ssize_t
 show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
@@ -550,11 +553,10 @@
 	u8 val = simple_strtoul(buf, NULL, 10);
 
 	/* transform the sysfs interface values into table above */
-	if ((val == 5 || val == 6) && (index < 4)) {
+	if ((val == 6) && (index < 4)) {
 		val -= 3;
 	} else if ((val == 3 && index < 4)
-		|| (val == 4 && index >= 4)
-		|| val == 0) {
+		|| (val == 4 && index >= 4)) {
 		/* transform diode or thermistor into internal enable */
 		val = !!val;
 	} else {
@@ -839,7 +841,9 @@
 		val <<= 2;
 		val += (data->in_low_bits[nr] >> (index * 2)) & 0x3;
 	}
-	return sprintf(buf, "%d\n", val * scale_in[index]);
+	/* voltage inputs 5VDD and 5VSB needs 150mV offset */
+	val = val * scale_in[index] + scale_in_add[index];
+	return sprintf(buf, "%d\n", val);
 }
 
 static ssize_t
@@ -859,6 +863,10 @@
 	     scale_in[index] / 2) / scale_in[index];
 	mutex_lock(&data->update_lock);
 	if (index > 2) {
+		/* fix the limit values of 5VDD and 5VSB to ALARM mechanism */
+		if (1 == nr || 2 == nr) {
+			val -= scale_in_add[index] / scale_in[index];
+		}
 		val = SENSORS_LIMIT(val, 0, 255);
 	} else {
 		val = SENSORS_LIMIT(val, 0, 0x3FF);
@@ -979,12 +987,6 @@
 	SENSOR_ATTR_IN(7),
 	SENSOR_ATTR_IN(8),
 	SENSOR_ATTR_IN(9),
-	SENSOR_ATTR_TEMP(1),
-	SENSOR_ATTR_TEMP(2),
-	SENSOR_ATTR_TEMP(3),
-	SENSOR_ATTR_TEMP(4),
-	SENSOR_ATTR_TEMP(5),
-	SENSOR_ATTR_TEMP(6),
 	SENSOR_ATTR_FAN(1),
 	SENSOR_ATTR_FAN(2),
 	SENSOR_ATTR_FAN(3),
@@ -995,6 +997,15 @@
 	SENSOR_ATTR_PWM(3),
 };
 
+static struct sensor_device_attribute_2 w83793_temp[] = {
+	SENSOR_ATTR_TEMP(1),
+	SENSOR_ATTR_TEMP(2),
+	SENSOR_ATTR_TEMP(3),
+	SENSOR_ATTR_TEMP(4),
+	SENSOR_ATTR_TEMP(5),
+	SENSOR_ATTR_TEMP(6),
+};
+
 /* Fan6-Fan12 */
 static struct sensor_device_attribute_2 w83793_left_fan[] = {
 	SENSOR_ATTR_FAN(6),
@@ -1015,9 +1026,12 @@
 	SENSOR_ATTR_PWM(8),
 };
 
-static struct sensor_device_attribute_2 sda_single_files[] = {
+static struct sensor_device_attribute_2 w83793_vid[] = {
 	SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
 	SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
+};
+
+static struct sensor_device_attribute_2 sda_single_files[] = {
 	SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
 		      NOT_USED, NOT_USED),
 	SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
@@ -1070,11 +1084,17 @@
 		for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
 			device_remove_file(dev, &sda_single_files[i].dev_attr);
 
+		for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+			device_remove_file(dev, &w83793_vid[i].dev_attr);
+
 		for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
 			device_remove_file(dev, &w83793_left_fan[i].dev_attr);
 
 		for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
 			device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+		for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+			device_remove_file(dev, &w83793_temp[i].dev_attr);
 	}
 
 	if ((err = i2c_detach_client(client)))
@@ -1187,6 +1207,7 @@
 	struct w83793_data *data;
 	int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
 	int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
+	int files_temp = ARRAY_SIZE(w83793_temp) / 6;
 	int err = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -1313,6 +1334,44 @@
 		data->has_pwm |= 0x80;
 	}
 
+	tmp = w83793_read_value(client, W83793_REG_FANIN_SEL);
+	if ((tmp & 0x01) && (val & 0x08)) {	/* fan 9, second location */
+		data->has_fan |= 0x100;
+	}
+	if ((tmp & 0x02) && (val & 0x10)) {	/* fan 10, second location */
+		data->has_fan |= 0x200;
+	}
+	if ((tmp & 0x04) && (val & 0x20)) {	/* fan 11, second location */
+		data->has_fan |= 0x400;
+	}
+	if ((tmp & 0x08) && (val & 0x40)) {	/* fan 12, second location */
+		data->has_fan |= 0x800;
+	}
+
+	/* check the temp1-6 mode, ignore former AMDSI selected inputs */
+	tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[0]);
+	if (tmp & 0x01)
+		data->has_temp |= 0x01;
+	if (tmp & 0x04)
+		data->has_temp |= 0x02;
+	if (tmp & 0x10)
+		data->has_temp |= 0x04;
+	if (tmp & 0x40)
+		data->has_temp |= 0x08;
+
+	tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[1]);
+	if (tmp & 0x01)
+		data->has_temp |= 0x10;
+	if (tmp & 0x02)
+		data->has_temp |= 0x20;
+
+	/* Detect the VID usage and ignore unused input */
+	tmp = w83793_read_value(client, W83793_REG_MFC);
+	if (!(tmp & 0x29))
+		data->has_vid |= 0x1;	/* has VIDA */
+	if (tmp & 0x80)
+		data->has_vid |= 0x2;	/* has VIDB */
+
 	/* Register sysfs hooks */
 	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
 		err = device_create_file(dev,
@@ -1321,6 +1380,14 @@
 			goto exit_remove;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) {
+		if (!(data->has_vid & (1 << i)))
+			continue;
+		err = device_create_file(dev, &w83793_vid[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
 		err = device_create_file(dev, &sda_single_files[i].dev_attr);
 		if (err)
@@ -1328,6 +1395,19 @@
 
 	}
 
+	for (i = 0; i < 6; i++) {
+		int j;
+		if (!(data->has_temp & (1 << i)))
+			continue;
+		for (j = 0; j < files_temp; j++) {
+			err = device_create_file(dev,
+						&w83793_temp[(i) * files_temp
+								+ j].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+
 	for (i = 5; i < 12; i++) {
 		int j;
 		if (!(data->has_fan & (1 << i)))
@@ -1371,12 +1451,18 @@
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
 		device_remove_file(dev, &sda_single_files[i].dev_attr);
 
+	for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+		device_remove_file(dev, &w83793_vid[i].dev_attr);
+
 	for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
 		device_remove_file(dev, &w83793_left_fan[i].dev_attr);
 
 	for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
 		device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
 
+	for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+		device_remove_file(dev, &w83793_temp[i].dev_attr);
+
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
 		kfree(data->lm75[0]);
@@ -1428,6 +1514,8 @@
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) {
+		if (!(data->has_temp & (1 << i)))
+			continue;
 		data->temp_fan_map[i] =
 		    w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i));
 		for (j = 1; j < 5; j++) {
@@ -1510,9 +1598,12 @@
 		    w83793_read_value(client, W83793_REG_FAN(i) + 1);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+	for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+		if (!(data->has_temp & (1 << i)))
+			continue;
 		data->temp[i][TEMP_READ] =
 		    w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]);
+	}
 
 	data->temp_low_bits =
 	    w83793_read_value(client, W83793_REG_TEMP_LOW_BITS);
@@ -1527,8 +1618,10 @@
 	for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
 		data->alarms[i] =
 		    w83793_read_value(client, W83793_REG_ALARM(i));
-	data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
-	data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
+	if (data->has_vid & 0x01)
+		data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
+	if (data->has_vid & 0x02)
+		data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
 	w83793_update_nonvolatile(dev);
 	data->last_updated = jiffies;
 	data->valid = 1;
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index df7d150..98410ca 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -73,3 +73,8 @@
 {
 	pnp_register_driver(&idepnp_driver);
 }
+
+void __exit pnpide_exit(void)
+{
+	pnp_unregister_driver(&idepnp_driver);
+}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 1689076..6c9bd51 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1781,8 +1781,9 @@
 	return 1;
 }
 
-extern void pnpide_init(void);
-extern void h8300_ide_init(void);
+extern void __init pnpide_init(void);
+extern void __exit pnpide_exit(void);
+extern void __init h8300_ide_init(void);
 
 /*
  * probe_for_hwifs() finds/initializes "known" IDE interfaces
@@ -2087,13 +2088,17 @@
 	return ide_init();
 }
 
-void cleanup_module (void)
+void __exit cleanup_module (void)
 {
 	int index;
 
 	for (index = 0; index < MAX_HWIFS; ++index)
 		ide_unregister(index);
 
+#ifdef CONFIG_BLK_DEV_IDEPNP
+	pnpide_exit();
+#endif
+
 #ifdef CONFIG_PROC_FS
 	proc_ide_destroy();
 #endif
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index f286079..d261bfb 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -441,7 +441,7 @@
 	.probe		= aec62xx_init_one,
 };
 
-static int aec62xx_ide_init(void)
+static int __init aec62xx_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 89109be..68df77e 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -907,7 +907,7 @@
 	.probe		= alim15x3_init_one,
 };
 
-static int ali15x3_ide_init(void)
+static int __init ali15x3_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 753fe0e..a433699 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -544,7 +544,7 @@
 	.probe		= amd74xx_probe,
 };
 
-static int amd74xx_ide_init(void)
+static int __init amd74xx_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 524e65d..982ac31 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -291,8 +291,12 @@
 
 static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
 {
+	u8 udma_mode = 0;
+	u8 ch = hwif->channel;
+	struct pci_dev *pdev = hwif->pci_dev;
+
 	if (!hwif->irq)
-		hwif->irq = hwif->channel ? 15 : 14;
+		hwif->irq = ch ? 15 : 14;
 
 	hwif->autodma = 0;
 	hwif->tuneproc = &atiixp_tuneproc;
@@ -308,8 +312,12 @@
 	hwif->mwdma_mask = 0x06;
 	hwif->swdma_mask = 0x04;
 
-	/* FIXME: proper cable detection needed */
-	hwif->udma_four = 1;
+	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
+		hwif->udma_four = 1;
+	else
+		hwif->udma_four = 0;
+
 	hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
 	hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
 	hwif->ide_dma_check = &atiixp_dma_check;
@@ -320,19 +328,6 @@
 	hwif->drives[0].autodma = hwif->autodma;
 }
 
-static void __devinit init_hwif_sb600_legacy(ide_hwif_t *hwif)
-{
-
-	hwif->atapi_dma = 1;
-	hwif->ultra_mask = 0x7f;
-	hwif->mwdma_mask = 0x07;
-	hwif->swdma_mask = 0x07;
-
-	if (!noautodma)
-		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
-}
 
 static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
 	{	/* 0 */
@@ -343,12 +338,13 @@
 		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
 		.bootable	= ON_BOARD,
 	},{	/* 1 */
-		.name		= "ATI SB600 SATA Legacy IDE",
-		.init_hwif	= init_hwif_sb600_legacy,
-		.channels	= 2,
+		.name		= "SB600_PATA",
+		.init_hwif	= init_hwif_atiixp,
+		.channels	= 1,
 		.autodma	= AUTODMA,
-		.bootable	= ON_BOARD,
-	}
+		.enablebits	= {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
+ 		.bootable	= ON_BOARD,
+ 	},
 };
 
 /**
@@ -369,7 +365,7 @@
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
@@ -380,7 +376,7 @@
 	.probe		= atiixp_init_one,
 };
 
-static int atiixp_ide_init(void)
+static int __init atiixp_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 20c3271..aee947e 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -793,7 +793,7 @@
 	.probe		= cmd64x_init_one,
 };
 
-static int cmd64x_ide_init(void)
+static int __init cmd64x_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 079f7c8..ba6786a 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -260,7 +260,7 @@
 	.probe		= cs5520_init_one,
 };
 
-static int cs5520_ide_init(void)
+static int __init cs5520_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index ae405fa..9bf5fdf 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -374,7 +374,7 @@
 	.probe		= cs5530_init_one,
 };
 
-static int cs5530_ide_init(void)
+static int __init cs5530_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 64330c4..9eafcbf 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -519,7 +519,7 @@
 	.probe		= cy82c693_init_one,
 };
 
-static int cy82c693_ide_init(void)
+static int __init cy82c693_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 9f30688..b408c6c 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -185,36 +185,6 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
-	},{	/* 15 */
-		.name		= "JMB361",
-		.init_hwif	= init_hwif_generic,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.bootable	= OFF_BOARD,
-	},{	/* 16 */
-		.name		= "JMB363",
-		.init_hwif	= init_hwif_generic,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.bootable	= OFF_BOARD,
-	},{	/* 17 */
-		.name		= "JMB365",
-		.init_hwif	= init_hwif_generic,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.bootable	= OFF_BOARD,
-	},{	/* 18 */
-		.name		= "JMB366",
-		.init_hwif	= init_hwif_generic,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.bootable	= OFF_BOARD,
-	},{	/* 19 */
-		.name		= "JMB368",
-		.init_hwif	= init_hwif_generic,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.bootable	= OFF_BOARD,
 	}
 };
 
@@ -281,11 +251,6 @@
 	{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
 	{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
 	{ PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION,          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
-	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
-	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
-	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
-	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
-	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
 	/* Must come last. If you add entries adjust this table appropriately and the init_one code */
 	{ PCI_ANY_ID,		PCI_ANY_ID,			   PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
 	{ 0, },
@@ -298,7 +263,7 @@
 	.probe		= generic_init_one,
 };
 
-static int generic_ide_init(void)
+static int __init generic_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index b46cb04..ce7b08f 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -265,7 +265,7 @@
 	.probe		= hpt34x_init_one,
 };
 
-static int hpt34x_ide_init(void)
+static int __init hpt34x_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 08119da..b486442 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1613,7 +1613,7 @@
 	.probe		= hpt366_init_one,
 };
 
-static int hpt366_ide_init(void)
+static int __init hpt366_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index c1cec23..f07bbbe 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -86,15 +86,16 @@
 	{
 	case PORT_PATA0:
 		if (control & (1 << 3))	/* 40/80 pin primary */
-			return 1;
-		return 0;
+			return 0;
+		return 1;
 	case PORT_PATA1:
 		if (control5 & (1 << 19))	/* 40/80 pin secondary */
 			return 0;
 		return 1;
 	case PORT_SATA:
-		return 1;
+		break;
 	}
+	return 1; /* Avoid bogus "control reaches end of non-void function" */
 }
 
 static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -240,11 +241,11 @@
 }
 
 static struct pci_device_id jmicron_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 0},
-	{ PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 1},
-	{ PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 2},
-	{ PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 3},
-	{ PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 4},
+	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
 	{ 0, },
 };
 
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index d95714b..8aaea4e 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -302,7 +302,7 @@
 	.probe		= ns87415_init_one,
 };
 
-static int ns87415_ide_init(void)
+static int __init ns87415_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 7a7c2ef..22bbf61 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -382,7 +382,7 @@
 	.probe		= opti621_init_one,
 };
 
-static int opti621_ide_init(void)
+static int __init opti621_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 7cb4857..77a9aaa 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -756,7 +756,7 @@
 	.probe		= pdc202new_init_one,
 };
 
-static int pdc202new_ide_init(void)
+static int __init pdc202new_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 184cdac..143239c 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -719,7 +719,7 @@
 	.probe		= pdc202xx_init_one,
 };
 
-static int pdc202xx_ide_init(void)
+static int __init pdc202xx_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 5f6950c..c185531 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -77,7 +77,7 @@
 	.probe		= rz1000_init_one,
 };
 
-static int rz1000_ide_init(void)
+static int __init rz1000_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index ff80937..8d762d3 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -507,7 +507,7 @@
 #endif
 };
 
-static int sc1200_ide_init(void)
+static int __init sc1200_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 057548d..ea9a28a 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -666,7 +666,7 @@
 	.probe		= svwks_init_one,
 };
 
-static int svwks_ide_init(void)
+static int __init svwks_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index cfad09a..b0bf018 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -762,8 +762,7 @@
 /*	.is_remove = ioc4_ide_remove_one,	*/
 };
 
-static int __devinit
-ioc4_ide_init(void)
+static int __init ioc4_ide_init(void)
 {
 	return ioc4_register_submodule(&ioc4_ide_submodule);
 }
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 697f566..4ff89c7 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1096,7 +1096,7 @@
 	.probe		= siimage_init_one,
 };
 
-static int siimage_ide_init(void)
+static int __init siimage_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 6b31313..1afff65 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -968,7 +968,7 @@
 	.probe		= sis5513_init_one,
 };
 
-static int sis5513_ide_init(void)
+static int __init sis5513_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 5afefe8..170a261 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -492,7 +492,7 @@
 	.probe		= sl82c105_init_one,
 };
 
-static int sl82c105_ide_init(void)
+static int __init sl82c105_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 9be7e49..90e79c0 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -253,7 +253,7 @@
 	.probe		= slc90e66_init_one,
 };
 
-static int slc90e66_ide_init(void)
+static int __init slc90e66_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index 56d8493..b13cce1 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -173,7 +173,7 @@
 	.probe		= triflex_init_one,
 };
 
-static int triflex_ide_init(void)
+static int __init triflex_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 2a28252..174b88c 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -355,7 +355,7 @@
 	.probe		= trm290_init_one,
 };
 
-static int trm290_ide_init(void)
+static int __init trm290_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 381cc6f..6fb6e50 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -78,6 +78,8 @@
 	u8 rev_max;
 	u16 flags;
 } via_isa_bridges[] = {
+	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
@@ -504,6 +506,7 @@
 	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_SATA_EIDE,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, via_pci_tbl);
@@ -514,7 +517,7 @@
 	.probe 		= via_init_one,
 };
 
-static int via_ide_init(void)
+static int __init via_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
 }
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 2b5d7ab..4325aac 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2020,6 +2020,8 @@
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 	sdev->use_10_for_rw = 1;
 
+	if (sdev->type == TYPE_ROM)
+		sdev->use_10_for_ms = 1;
 	if (sdev->type == TYPE_DISK &&
 	    lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
 		sdev->skip_ms_page_8 = 1;
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index af93979..d2bb5a9 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -360,8 +360,7 @@
 	if (event == NETEVENT_NEIGH_UPDATE) {
 		struct neighbour *neigh = ctx;
 
-		if (neigh->dev->type == ARPHRD_INFINIBAND &&
-		    (neigh->nud_state & NUD_VALID)) {
+		if (neigh->nud_state & NUD_VALID) {
 			set_timeout(jiffies);
 		}
 	}
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 533193d..9e0ab04 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1088,10 +1088,21 @@
 		*sin = iw_event->local_addr;
 		sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr;
 		*sin = iw_event->remote_addr;
-		if (iw_event->status)
-			event.event = RDMA_CM_EVENT_REJECTED;
-		else
+		switch (iw_event->status) {
+		case 0:
 			event.event = RDMA_CM_EVENT_ESTABLISHED;
+			break;
+		case -ECONNRESET:
+		case -ECONNREFUSED:
+			event.event = RDMA_CM_EVENT_REJECTED;
+			break;
+		case -ETIMEDOUT:
+			event.event = RDMA_CM_EVENT_UNREACHABLE;
+			break;
+		default:
+			event.event = RDMA_CM_EVENT_CONNECT_ERROR;
+			break;
+		}
 		break;
 	case IW_CM_EVENT_ESTABLISHED:
 		event.event = RDMA_CM_EVENT_ESTABLISHED;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 5ed141e..13efd41 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -642,7 +642,8 @@
 	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 }
 
-static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
+static void build_smp_wc(struct ib_qp *qp,
+			 u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
 			 struct ib_wc *wc)
 {
 	memset(wc, 0, sizeof *wc);
@@ -652,7 +653,7 @@
 	wc->pkey_index = pkey_index;
 	wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh);
 	wc->src_qp = IB_QP0;
-	wc->qp_num = IB_QP0;
+	wc->qp = qp;
 	wc->slid = slid;
 	wc->sl = 0;
 	wc->dlid_path_bits = 0;
@@ -713,7 +714,8 @@
 		goto out;
 	}
 
-	build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),
+	build_smp_wc(mad_agent_priv->agent.qp,
+		     send_wr->wr_id, be16_to_cpu(smp->dr_slid),
 		     send_wr->wr.ud.pkey_index,
 		     send_wr->wr.ud.port_num, &mad_wc);
 
@@ -2355,7 +2357,8 @@
 			 * Defined behavior is to complete response
 			 * before request
 			 */
-			build_smp_wc((unsigned long) local->mad_send_wr,
+			build_smp_wc(recv_mad_agent->agent.qp,
+				     (unsigned long) local->mad_send_wr,
 				     be16_to_cpu(IB_LID_PERMISSIVE),
 				     0, recv_mad_agent->agent.port_num, &wc);
 
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 81a5cdc..e2e8d32 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -209,10 +209,21 @@
 	if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
 		if (!ctx->backlog) {
 			ret = -EDQUOT;
+			kfree(uevent);
 			goto out;
 		}
 		ctx->backlog--;
+	} else if (!ctx->uid) {
+		/*
+		 * We ignore events for new connections until userspace has set
+		 * their context.  This can only happen if an error occurs on a
+		 * new connection before the user accepts it.  This is okay,
+		 * since the accept will just fail later.
+		 */
+		kfree(uevent);
+		goto out;
 	}
+
 	list_add_tail(&uevent->list, &ctx->file->event_list);
 	wake_up_interruptible(&ctx->file->poll_wait);
 out:
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 743247e..df1efbc 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -933,7 +933,7 @@
 		resp->wc[i].vendor_err 	   = wc[i].vendor_err;
 		resp->wc[i].byte_len 	   = wc[i].byte_len;
 		resp->wc[i].imm_data 	   = (__u32 __force) wc[i].imm_data;
-		resp->wc[i].qp_num 	   = wc[i].qp_num;
+		resp->wc[i].qp_num 	   = wc[i].qp->qp_num;
 		resp->wc[i].src_qp 	   = wc[i].src_qp;
 		resp->wc[i].wc_flags 	   = wc[i].wc_flags;
 		resp->wc[i].pkey_index 	   = wc[i].pkey_index;
diff --git a/drivers/infiniband/hw/amso1100/c2_cq.c b/drivers/infiniband/hw/amso1100/c2_cq.c
index 05c9154..5175c99 100644
--- a/drivers/infiniband/hw/amso1100/c2_cq.c
+++ b/drivers/infiniband/hw/amso1100/c2_cq.c
@@ -153,7 +153,7 @@
 
 	entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce));
 	entry->wr_id = ce->hdr.context;
-	entry->qp_num = ce->handle;
+	entry->qp = &qp->ibqp;
 	entry->wc_flags = 0;
 	entry->slid = 0;
 	entry->sl = 0;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1c72203..cf95ee4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -119,13 +119,14 @@
 	struct ipz_qp_handle ipz_qp_handle;
 	struct ehca_pfqp pf;
 	struct ib_qp_init_attr init_attr;
-	u64 uspace_squeue;
-	u64 uspace_rqueue;
-	u64 uspace_fwh;
 	struct ehca_cq *send_cq;
 	struct ehca_cq *recv_cq;
 	unsigned int sqerr_purgeflag;
 	struct hlist_node list_entries;
+	/* mmap counter for resources mapped into user space */
+	u32 mm_count_squeue;
+	u32 mm_count_rqueue;
+	u32 mm_count_galpa;
 };
 
 /* must be power of 2 */
@@ -142,13 +143,14 @@
 	struct ipz_cq_handle ipz_cq_handle;
 	struct ehca_pfcq pf;
 	spinlock_t cb_lock;
-	u64 uspace_queue;
-	u64 uspace_fwh;
 	struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
 	struct list_head entry;
 	u32 nr_callbacks;
 	spinlock_t task_lock;
 	u32 ownpid;
+	/* mmap counter for resources mapped into user space */
+	u32 mm_count_queue;
+	u32 mm_count_galpa;
 };
 
 enum ehca_mr_flag {
@@ -248,20 +250,6 @@
 	struct ib_ucontext ib_ucontext;
 };
 
-struct ehca_module *ehca_module_new(void);
-
-int ehca_module_delete(struct ehca_module *me);
-
-int ehca_eq_ctor(struct ehca_eq *eq);
-
-int ehca_eq_dtor(struct ehca_eq *eq);
-
-struct ehca_shca *ehca_shca_new(void);
-
-int ehca_shca_delete(struct ehca_shca *me);
-
-struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor);
-
 int ehca_init_pd_cache(void);
 void ehca_cleanup_pd_cache(void);
 int ehca_init_cq_cache(void);
@@ -283,7 +271,6 @@
 extern int ehca_use_hp_mr;
 
 struct ipzu_queue_resp {
-	u64 queue;        /* points to first queue entry */
 	u32 qe_size;      /* queue entry size */
 	u32 act_nr_of_sg;
 	u32 queue_length; /* queue length allocated in bytes */
@@ -296,7 +283,6 @@
 	u32 cq_number;
 	u32 token;
 	struct ipzu_queue_resp ipz_queue;
-	struct h_galpas galpas;
 };
 
 struct ehca_create_qp_resp {
@@ -309,7 +295,6 @@
 	u32 dummy; /* padding for 8 byte alignment */
 	struct ipzu_queue_resp ipz_squeue;
 	struct ipzu_queue_resp ipz_rqueue;
-	struct h_galpas galpas;
 };
 
 struct ehca_alloc_cq_parms {
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 93995b6..9291a86 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -267,7 +267,6 @@
 	if (context) {
 		struct ipz_queue *ipz_queue = &my_cq->ipz_queue;
 		struct ehca_create_cq_resp resp;
-		struct vm_area_struct *vma;
 		memset(&resp, 0, sizeof(resp));
 		resp.cq_number = my_cq->cq_number;
 		resp.token = my_cq->token;
@@ -276,40 +275,14 @@
 		resp.ipz_queue.queue_length = ipz_queue->queue_length;
 		resp.ipz_queue.pagesize = ipz_queue->pagesize;
 		resp.ipz_queue.toggle_state = ipz_queue->toggle_state;
-		ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000,
-				       ipz_queue->queue_length,
-				       (void**)&resp.ipz_queue.queue,
-				       &vma);
-		if (ret) {
-			ehca_err(device, "Could not mmap queue pages");
-			cq = ERR_PTR(ret);
-			goto create_cq_exit4;
-		}
-		my_cq->uspace_queue = resp.ipz_queue.queue;
-		resp.galpas = my_cq->galpas;
-		ret = ehca_mmap_register(my_cq->galpas.user.fw_handle,
-					 (void**)&resp.galpas.kernel.fw_handle,
-					 &vma);
-		if (ret) {
-			ehca_err(device, "Could not mmap fw_handle");
-			cq = ERR_PTR(ret);
-			goto create_cq_exit5;
-		}
-		my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle;
 		if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
 			ehca_err(device, "Copy to udata failed.");
-			goto create_cq_exit6;
+			goto create_cq_exit4;
 		}
 	}
 
 	return cq;
 
-create_cq_exit6:
-	ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE);
-
-create_cq_exit5:
-	ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length);
-
 create_cq_exit4:
 	ipz_queue_dtor(&my_cq->ipz_queue);
 
@@ -333,7 +306,6 @@
 int ehca_destroy_cq(struct ib_cq *cq)
 {
 	u64 h_ret;
-	int ret;
 	struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
 	int cq_num = my_cq->cq_number;
 	struct ib_device *device = cq->device;
@@ -343,32 +315,30 @@
 	u32 cur_pid = current->tgid;
 	unsigned long flags;
 
+	if (cq->uobject) {
+		if (my_cq->mm_count_galpa || my_cq->mm_count_queue) {
+			ehca_err(device, "Resources still referenced in "
+				 "user space cq_num=%x", my_cq->cq_number);
+			return -EINVAL;
+		}
+		if (my_cq->ownpid != cur_pid) {
+			ehca_err(device, "Invalid caller pid=%x ownpid=%x "
+				 "cq_num=%x",
+				 cur_pid, my_cq->ownpid, my_cq->cq_number);
+			return -EINVAL;
+		}
+	}
+
 	spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-	while (my_cq->nr_callbacks)
+	while (my_cq->nr_callbacks) {
+		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 		yield();
+		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+	}
 
 	idr_remove(&ehca_cq_idr, my_cq->token);
 	spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
-	if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) {
-		ehca_err(device, "Invalid caller pid=%x ownpid=%x",
-			 cur_pid, my_cq->ownpid);
-		return -EINVAL;
-	}
-
-	/* un-mmap if vma alloc */
-	if (my_cq->uspace_queue ) {
-		ret = ehca_munmap(my_cq->uspace_queue,
-				  my_cq->ipz_queue.queue_length);
-		if (ret)
-			ehca_err(device, "Could not munmap queue ehca_cq=%p "
-				 "cq_num=%x", my_cq, cq_num);
-		ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE);
-		if (ret)
-			ehca_err(device, "Could not munmap fwh ehca_cq=%p "
-				 "cq_num=%x", my_cq, cq_num);
-	}
-
 	h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
 	if (h_ret == H_R_STATE) {
 		/* cq in err: read err data and destroy it forcibly */
@@ -397,7 +367,7 @@
 	struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
 	u32 cur_pid = current->tgid;
 
-	if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) {
+	if (cq->uobject && my_cq->ownpid != cur_pid) {
 		ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x",
 			 cur_pid, my_cq->ownpid);
 		return -EINVAL;
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index e1b618c..b7be950 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -50,7 +50,7 @@
 					      ib_device);
 	struct hipz_query_hca *rblock;
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
 		return -ENOMEM;
@@ -110,7 +110,7 @@
 					      ib_device);
 	struct hipz_query_port *rblock;
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
 		return -ENOMEM;
@@ -179,7 +179,7 @@
 		return -EINVAL;
 	}
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
 		return -ENOMEM;
@@ -212,7 +212,7 @@
 		return -EINVAL;
 	}
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
 		return -ENOMEM;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index c3ea746..c069be8 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -138,7 +138,7 @@
 	u64 *rblock;
 	unsigned long block_count;
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
 	if (!rblock) {
 		ehca_err(&shca->ib_device, "Cannot allocate rblock memory.");
 		ret = -ENOMEM;
@@ -440,7 +440,8 @@
 					cq = idr_find(&ehca_cq_idr, token);
 
 					if (cq == NULL) {
-						spin_unlock(&ehca_cq_idr_lock);
+						spin_unlock_irqrestore(&ehca_cq_idr_lock,
+								       flags);
 						break;
 					}
 
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 3720e30..95fd59f 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -171,19 +171,11 @@
 
 void ehca_poll_eqs(unsigned long data);
 
-int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped,
-		     struct vm_area_struct **vma);
-
-int ehca_mmap_register(u64 physical,void **mapped,
-		       struct vm_area_struct **vma);
-
-int ehca_munmap(unsigned long addr, size_t len);
-
 #ifdef CONFIG_PPC_64K_PAGES
-void *ehca_alloc_fw_ctrlblock(void);
+void *ehca_alloc_fw_ctrlblock(gfp_t flags);
 void ehca_free_fw_ctrlblock(void *ptr);
 #else
-#define ehca_alloc_fw_ctrlblock() ((void *) get_zeroed_page(GFP_KERNEL))
+#define ehca_alloc_fw_ctrlblock(flags) ((void *) get_zeroed_page(flags))
 #define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
 #endif
 
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index cc47e4c..1155bcf 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0019");
+MODULE_VERSION("SVNEHCA_0020");
 
 int ehca_open_aqp1     = 0;
 int ehca_debug_level   = 0;
@@ -106,9 +106,9 @@
 #ifdef CONFIG_PPC_64K_PAGES
 static struct kmem_cache *ctblk_cache = NULL;
 
-void *ehca_alloc_fw_ctrlblock(void)
+void *ehca_alloc_fw_ctrlblock(gfp_t flags)
 {
-	void *ret = kmem_cache_zalloc(ctblk_cache, GFP_KERNEL);
+	void *ret = kmem_cache_zalloc(ctblk_cache, flags);
 	if (!ret)
 		ehca_gen_err("Out of memory for ctblk");
 	return ret;
@@ -206,7 +206,7 @@
 	u64 h_ret;
 	struct hipz_query_hca *rblock;
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_gen_err("Cannot allocate rblock memory.");
 		return -ENOMEM;
@@ -258,7 +258,7 @@
 	int ret = 0;
 	struct hipz_query_hca *rblock;
 
-	rblock = ehca_alloc_fw_ctrlblock();
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!rblock) {
 		ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
 		return -ENOMEM;
@@ -288,7 +288,7 @@
 	strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
 	shca->ib_device.owner               = THIS_MODULE;
 
-	shca->ib_device.uverbs_abi_ver	    = 5;
+	shca->ib_device.uverbs_abi_ver	    = 6;
 	shca->ib_device.uverbs_cmd_mask	    =
 		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)		|
 		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)	|
@@ -469,7 +469,7 @@
 									   \
 	shca = dev->driver_data;					   \
 									   \
-	rblock = ehca_alloc_fw_ctrlblock();				   \
+	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);			   \
 	if (!rblock) {						           \
 		dev_err(dev, "Can't allocate rblock memory.");		   \
 		return 0;						   \
@@ -790,7 +790,7 @@
 	int ret;
 
 	printk(KERN_INFO "eHCA Infiniband Device Driver "
-	                 "(Rel.: SVNEHCA_0019)\n");
+	                 "(Rel.: SVNEHCA_0020)\n");
 	idr_init(&ehca_qp_idr);
 	idr_init(&ehca_cq_idr);
 	spin_lock_init(&ehca_qp_idr_lock);
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 0a5e221..cfb362a 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -1013,7 +1013,7 @@
 	u32 i;
 	u64 *kpage;
 
-	kpage = ehca_alloc_fw_ctrlblock();
+	kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!kpage) {
 		ehca_err(&shca->ib_device, "kpage alloc failed");
 		ret = -ENOMEM;
@@ -1124,7 +1124,7 @@
 	ehca_mrmw_map_acl(acl, &hipz_acl);
 	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
 
-	kpage = ehca_alloc_fw_ctrlblock();
+	kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!kpage) {
 		ehca_err(&shca->ib_device, "kpage alloc failed");
 		ret = -ENOMEM;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index c6c9cef..95efef9 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -637,7 +637,6 @@
 		struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue;
 		struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue;
 		struct ehca_create_qp_resp resp;
-		struct vm_area_struct * vma;
 		memset(&resp, 0, sizeof(resp));
 
 		resp.qp_num = my_qp->real_qp_num;
@@ -651,59 +650,21 @@
 		resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length;
 		resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize;
 		resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state;
-		ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000,
-				       ipz_rqueue->queue_length,
-				       (void**)&resp.ipz_rqueue.queue,
-				       &vma);
-		if (ret) {
-			ehca_err(pd->device, "Could not mmap rqueue pages");
-			goto create_qp_exit3;
-		}
-		my_qp->uspace_rqueue = resp.ipz_rqueue.queue;
 		/* squeue properties */
 		resp.ipz_squeue.qe_size = ipz_squeue->qe_size;
 		resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg;
 		resp.ipz_squeue.queue_length = ipz_squeue->queue_length;
 		resp.ipz_squeue.pagesize = ipz_squeue->pagesize;
 		resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state;
-		ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000,
-				       ipz_squeue->queue_length,
-				       (void**)&resp.ipz_squeue.queue,
-				       &vma);
-		if (ret) {
-			ehca_err(pd->device, "Could not mmap squeue pages");
-			goto create_qp_exit4;
-		}
-		my_qp->uspace_squeue = resp.ipz_squeue.queue;
-		/* fw_handle */
-		resp.galpas = my_qp->galpas;
-		ret = ehca_mmap_register(my_qp->galpas.user.fw_handle,
-					 (void**)&resp.galpas.kernel.fw_handle,
-					 &vma);
-		if (ret) {
-			ehca_err(pd->device, "Could not mmap fw_handle");
-			goto create_qp_exit5;
-		}
-		my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle;
-
 		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
 			ehca_err(pd->device, "Copy to udata failed");
 			ret = -EINVAL;
-			goto create_qp_exit6;
+			goto create_qp_exit3;
 		}
 	}
 
 	return &my_qp->ib_qp;
 
-create_qp_exit6:
-	ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE);
-
-create_qp_exit5:
-	ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length);
-
-create_qp_exit4:
-	ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length);
-
 create_qp_exit3:
 	ipz_queue_dtor(&my_qp->ipz_rqueue);
 	ipz_queue_dtor(&my_qp->ipz_squeue);
@@ -807,7 +768,7 @@
 	unsigned long spl_flags = 0;
 
 	/* do query_qp to obtain current attr values */
-	mqpcb = ehca_alloc_fw_ctrlblock();
+	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!mqpcb) {
 		ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
 			 "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
@@ -931,7 +892,7 @@
 	     my_qp->qp_type == IB_QPT_SMI) &&
 	    statetrans == IB_QPST_SQE2RTS) {
 		/* mark next free wqe if kernel */
-		if (my_qp->uspace_squeue == 0) {
+		if (!ibqp->uobject) {
 			struct ehca_wqe *wqe;
 			/* lock send queue */
 			spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
@@ -1273,7 +1234,7 @@
 		return -EINVAL;
 	}
 
-	qpcb = ehca_alloc_fw_ctrlblock();
+	qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!qpcb) {
 		ehca_err(qp->device,"Out of memory for qpcb "
 			 "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num);
@@ -1417,11 +1378,18 @@
 	enum ib_qp_type	qp_type;
 	unsigned long flags;
 
-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-	    my_pd->ownpid != cur_pid) {
-		ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
-			 cur_pid, my_pd->ownpid);
-		return -EINVAL;
+	if (ibqp->uobject) {
+		if (my_qp->mm_count_galpa ||
+		    my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
+			ehca_err(ibqp->device, "Resources still referenced in "
+				 "user space qp_num=%x", ibqp->qp_num);
+			return -EINVAL;
+		}
+		if (my_pd->ownpid != cur_pid) {
+			ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
+				 cur_pid, my_pd->ownpid);
+			return -EINVAL;
+		}
 	}
 
 	if (my_qp->send_cq) {
@@ -1439,24 +1407,6 @@
 	idr_remove(&ehca_qp_idr, my_qp->token);
 	spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
-	/* un-mmap if vma alloc */
-	if (my_qp->uspace_rqueue) {
-		ret = ehca_munmap(my_qp->uspace_rqueue,
-				  my_qp->ipz_rqueue.queue_length);
-		if (ret)
-			ehca_err(ibqp->device, "Could not munmap rqueue "
-				 "qp_num=%x", qp_num);
-		ret = ehca_munmap(my_qp->uspace_squeue,
-				  my_qp->ipz_squeue.queue_length);
-		if (ret)
-			ehca_err(ibqp->device, "Could not munmap squeue "
-				 "qp_num=%x", qp_num);
-		ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE);
-		if (ret)
-			ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x",
-				 qp_num);
-	}
-
 	h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
 	if (h_ret != H_SUCCESS) {
 		ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx "
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index b46bda1..08d3f89 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -579,7 +579,7 @@
 	} else
 		wc->status = IB_WC_SUCCESS;
 
-	wc->qp_num = cqe->local_qp_number;
+	wc->qp = NULL;
 	wc->byte_len = cqe->nr_bytes_transferred;
 	wc->pkey_index = cqe->pkey_index;
 	wc->slid = cqe->rlid;
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index e08764e..73db920 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -68,104 +68,182 @@
 	return 0;
 }
 
-struct page *ehca_nopage(struct vm_area_struct *vma,
-			 unsigned long address, int *type)
+static void ehca_mm_open(struct vm_area_struct *vma)
 {
-	struct page *mypage = NULL;
-	u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT;
-	u32 idr_handle = fileoffset >> 32;
-	u32 q_type = (fileoffset >> 28) & 0xF;	  /* CQ, QP,...        */
-	u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
-	u32 cur_pid = current->tgid;
-	unsigned long flags;
-	struct ehca_cq *cq;
-	struct ehca_qp *qp;
-	struct ehca_pd *pd;
-	u64 offset;
-	void *vaddr;
+	u32 *count = (u32*)vma->vm_private_data;
+	if (!count) {
+		ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
+			     vma->vm_start, vma->vm_end);
+		return;
+	}
+	(*count)++;
+	if (!(*count))
+		ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx",
+			     vma->vm_start, vma->vm_end);
+	ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
+		     vma->vm_start, vma->vm_end, *count);
+}
 
-	switch (q_type) {
-	case 1: /* CQ */
-		spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-		cq = idr_find(&ehca_cq_idr, idr_handle);
-		spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+static void ehca_mm_close(struct vm_area_struct *vma)
+{
+	u32 *count = (u32*)vma->vm_private_data;
+	if (!count) {
+		ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
+			     vma->vm_start, vma->vm_end);
+		return;
+	}
+	(*count)--;
+	ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
+		     vma->vm_start, vma->vm_end, *count);
+}
 
-		/* make sure this mmap really belongs to the authorized user */
-		if (!cq) {
-			ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS");
-			return NOPAGE_SIGBUS;
+static struct vm_operations_struct vm_ops = {
+	.open =	ehca_mm_open,
+	.close = ehca_mm_close,
+};
+
+static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
+			u32 *mm_count)
+{
+	int ret;
+	u64 vsize, physical;
+
+	vsize = vma->vm_end - vma->vm_start;
+	if (vsize != EHCA_PAGESIZE) {
+		ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
+		return -EINVAL;
+	}
+
+	physical = galpas->user.fw_handle;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical);
+	/* VM_IO | VM_RESERVED are set by remap_pfn_range() */
+	ret = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT,
+			      vsize, vma->vm_page_prot);
+	if (unlikely(ret)) {
+		ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
+		return -ENOMEM;
+	}
+
+	vma->vm_private_data = mm_count;
+	(*mm_count)++;
+	vma->vm_ops = &vm_ops;
+
+	return 0;
+}
+
+static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
+			   u32 *mm_count)
+{
+	int ret;
+	u64 start, ofs;
+	struct page *page;
+
+	vma->vm_flags |= VM_RESERVED;
+	start = vma->vm_start;
+	for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
+		u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
+		page = virt_to_page(virt_addr);
+		ret = vm_insert_page(vma, start, page);
+		if (unlikely(ret)) {
+			ehca_gen_err("vm_insert_page() failed rc=%x", ret);
+			return ret;
 		}
+		start +=  PAGE_SIZE;
+	}
+	vma->vm_private_data = mm_count;
+	(*mm_count)++;
+	vma->vm_ops = &vm_ops;
 
-		if (cq->ownpid != cur_pid) {
+	return 0;
+}
+
+static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq,
+			u32 rsrc_type)
+{
+	int ret;
+
+	switch (rsrc_type) {
+	case 1: /* galpa fw handle */
+		ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
+		ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
+		if (unlikely(ret)) {
 			ehca_err(cq->ib_cq.device,
-				 "Invalid caller pid=%x ownpid=%x",
-				 cur_pid, cq->ownpid);
-			return NOPAGE_SIGBUS;
-		}
-
-		if (rsrc_type == 2) {
-			ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq);
-			offset = address - vma->vm_start;
-			vaddr = ipz_qeit_calc(&cq->ipz_queue, offset);
-			ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p",
-				 offset, vaddr);
-			mypage = virt_to_page(vaddr);
+				 "ehca_mmap_fw() failed rc=%x cq_num=%x",
+				 ret, cq->cq_number);
+			return ret;
 		}
 		break;
 
-	case 2: /* QP */
-		spin_lock_irqsave(&ehca_qp_idr_lock, flags);
-		qp = idr_find(&ehca_qp_idr, idr_handle);
-		spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
-
-		/* make sure this mmap really belongs to the authorized user */
-		if (!qp) {
-			ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS");
-			return NOPAGE_SIGBUS;
-		}
-
-		pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd);
-		if (pd->ownpid != cur_pid) {
-			ehca_err(qp->ib_qp.device,
-				 "Invalid caller pid=%x ownpid=%x",
-				 cur_pid, pd->ownpid);
-			return NOPAGE_SIGBUS;
-		}
-
-		if (rsrc_type == 2) {	/* rqueue */
-			ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp);
-			offset = address - vma->vm_start;
-			vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset);
-			ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p",
-				 offset, vaddr);
-			mypage = virt_to_page(vaddr);
-		} else if (rsrc_type == 3) {	/* squeue */
-			ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp);
-			offset = address - vma->vm_start;
-			vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset);
-			ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p",
-				 offset, vaddr);
-			mypage = virt_to_page(vaddr);
+	case 2: /* cq queue_addr */
+		ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
+		ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
+		if (unlikely(ret)) {
+			ehca_err(cq->ib_cq.device,
+				 "ehca_mmap_queue() failed rc=%x cq_num=%x",
+				 ret, cq->cq_number);
+			return ret;
 		}
 		break;
 
 	default:
-		ehca_gen_err("bad queue type %x", q_type);
-		return NOPAGE_SIGBUS;
+		ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x",
+			 rsrc_type, cq->cq_number);
+		return -EINVAL;
 	}
 
-	if (!mypage) {
-		ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS");
-		return NOPAGE_SIGBUS;
-	}
-	get_page(mypage);
-
-	return mypage;
+	return 0;
 }
 
-static struct vm_operations_struct ehcau_vm_ops = {
-	.nopage = ehca_nopage,
-};
+static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+			u32 rsrc_type)
+{
+	int ret;
+
+	switch (rsrc_type) {
+	case 1: /* galpa fw handle */
+		ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
+		ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
+		if (unlikely(ret)) {
+			ehca_err(qp->ib_qp.device,
+				 "remap_pfn_range() failed ret=%x qp_num=%x",
+				 ret, qp->ib_qp.qp_num);
+			return -ENOMEM;
+		}
+		break;
+
+	case 2: /* qp rqueue_addr */
+		ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
+			 qp->ib_qp.qp_num);
+		ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, &qp->mm_count_rqueue);
+		if (unlikely(ret)) {
+			ehca_err(qp->ib_qp.device,
+				 "ehca_mmap_queue(rq) failed rc=%x qp_num=%x",
+				 ret, qp->ib_qp.qp_num);
+			return ret;
+		}
+		break;
+
+	case 3: /* qp squeue_addr */
+		ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
+			 qp->ib_qp.qp_num);
+		ret = ehca_mmap_queue(vma, &qp->ipz_squeue, &qp->mm_count_squeue);
+		if (unlikely(ret)) {
+			ehca_err(qp->ib_qp.device,
+				 "ehca_mmap_queue(sq) failed rc=%x qp_num=%x",
+				 ret, qp->ib_qp.qp_num);
+			return ret;
+		}
+		break;
+
+	default:
+		ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x",
+			 rsrc_type, qp->ib_qp.qp_num);
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 {
@@ -175,7 +253,6 @@
 	u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
 	u32 cur_pid = current->tgid;
 	u32 ret;
-	u64 vsize, physical;
 	unsigned long flags;
 	struct ehca_cq *cq;
 	struct ehca_qp *qp;
@@ -201,44 +278,12 @@
 		if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
 			return -EINVAL;
 
-		switch (rsrc_type) {
-		case 1: /* galpa fw handle */
-			ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq);
-			vma->vm_flags |= VM_RESERVED;
-			vsize = vma->vm_end - vma->vm_start;
-			if (vsize != EHCA_PAGESIZE) {
-				ehca_err(cq->ib_cq.device, "invalid vsize=%lx",
-					 vma->vm_end - vma->vm_start);
-				return -EINVAL;
-			}
-
-			physical = cq->galpas.user.fw_handle;
-			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-			vma->vm_flags |= VM_IO | VM_RESERVED;
-
-			ehca_dbg(cq->ib_cq.device,
-				 "vsize=%lx physical=%lx", vsize, physical);
-			ret = remap_pfn_range(vma, vma->vm_start,
-					      physical >> PAGE_SHIFT, vsize,
-					      vma->vm_page_prot);
-			if (ret) {
-				ehca_err(cq->ib_cq.device,
-					 "remap_pfn_range() failed ret=%x",
-					 ret);
-				return -ENOMEM;
-			}
-			break;
-
-		case 2: /* cq queue_addr */
-			ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq);
-			vma->vm_flags |= VM_RESERVED;
-			vma->vm_ops = &ehcau_vm_ops;
-			break;
-
-		default:
-			ehca_err(cq->ib_cq.device, "bad resource type %x",
-				 rsrc_type);
-			return -EINVAL;
+		ret = ehca_mmap_cq(vma, cq, rsrc_type);
+		if (unlikely(ret)) {
+			ehca_err(cq->ib_cq.device,
+				 "ehca_mmap_cq() failed rc=%x cq_num=%x",
+				 ret, cq->cq_number);
+			return ret;
 		}
 		break;
 
@@ -262,50 +307,12 @@
 		if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context)
 			return -EINVAL;
 
-		switch (rsrc_type) {
-		case 1: /* galpa fw handle */
-			ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp);
-			vma->vm_flags |= VM_RESERVED;
-			vsize = vma->vm_end - vma->vm_start;
-			if (vsize != EHCA_PAGESIZE) {
-				ehca_err(qp->ib_qp.device, "invalid vsize=%lx",
-					 vma->vm_end - vma->vm_start);
-				return -EINVAL;
-			}
-
-			physical = qp->galpas.user.fw_handle;
-			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-			vma->vm_flags |= VM_IO | VM_RESERVED;
-
-			ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx",
-				 vsize, physical);
-			ret = remap_pfn_range(vma, vma->vm_start,
-					      physical >> PAGE_SHIFT, vsize,
-					      vma->vm_page_prot);
-			if (ret) {
-				ehca_err(qp->ib_qp.device,
-					 "remap_pfn_range() failed ret=%x",
-					 ret);
-				return -ENOMEM;
-			}
-			break;
-
-		case 2: /* qp rqueue_addr */
-			ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp);
-			vma->vm_flags |= VM_RESERVED;
-			vma->vm_ops = &ehcau_vm_ops;
-			break;
-
-		case 3: /* qp squeue_addr */
-			ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp);
-			vma->vm_flags |= VM_RESERVED;
-			vma->vm_ops = &ehcau_vm_ops;
-			break;
-
-		default:
-			ehca_err(qp->ib_qp.device, "bad resource type %x",
-				 rsrc_type);
-			return -EINVAL;
+		ret = ehca_mmap_qp(vma, qp, rsrc_type);
+		if (unlikely(ret)) {
+			ehca_err(qp->ib_qp.device,
+				 "ehca_mmap_qp() failed rc=%x qp_num=%x",
+				 ret, qp->ib_qp.qp_num);
+			return ret;
 		}
 		break;
 
@@ -316,77 +323,3 @@
 
 	return 0;
 }
-
-int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped,
-		     struct vm_area_struct **vma)
-{
-	down_write(&current->mm->mmap_sem);
-	*mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE,
-				 MAP_SHARED | MAP_ANONYMOUS,
-				 foffset);
-	up_write(&current->mm->mmap_sem);
-	if (!(*mapped)) {
-		ehca_gen_err("couldn't mmap foffset=%lx length=%lx",
-			     foffset, length);
-		return -EINVAL;
-	}
-
-	*vma = find_vma(current->mm, (u64)*mapped);
-	if (!(*vma)) {
-		down_write(&current->mm->mmap_sem);
-		do_munmap(current->mm, 0, length);
-		up_write(&current->mm->mmap_sem);
-		ehca_gen_err("couldn't find vma queue=%p", *mapped);
-		return -EINVAL;
-	}
-	(*vma)->vm_flags |= VM_RESERVED;
-	(*vma)->vm_ops = &ehcau_vm_ops;
-
-	return 0;
-}
-
-int ehca_mmap_register(u64 physical, void **mapped,
-		       struct vm_area_struct **vma)
-{
-	int ret;
-	unsigned long vsize;
-	/* ehca hw supports only 4k page */
-	ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma);
-	if (ret) {
-		ehca_gen_err("could'nt mmap physical=%lx", physical);
-		return ret;
-	}
-
-	(*vma)->vm_flags |= VM_RESERVED;
-	vsize = (*vma)->vm_end - (*vma)->vm_start;
-	if (vsize != EHCA_PAGESIZE) {
-		ehca_gen_err("invalid vsize=%lx",
-			     (*vma)->vm_end - (*vma)->vm_start);
-		return -EINVAL;
-	}
-
-	(*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot);
-	(*vma)->vm_flags |= VM_IO | VM_RESERVED;
-
-	ret = remap_pfn_range((*vma), (*vma)->vm_start,
-			      physical >> PAGE_SHIFT, vsize,
-			      (*vma)->vm_page_prot);
-	if (ret) {
-		ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
-		return -ENOMEM;
-	}
-
-	return 0;
-
-}
-
-int ehca_munmap(unsigned long addr, size_t len) {
-	int ret = 0;
-	struct mm_struct *mm = current->mm;
-	if (mm) {
-		down_write(&mm->mmap_sem);
-		ret = do_munmap(mm, addr, len);
-		up_write(&mm->mmap_sem);
-	}
-	return ret;
-}
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
index 46c1c89..64f07b1 100644
--- a/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -379,7 +379,7 @@
 	wc.vendor_err = 0;
 	wc.byte_len = 0;
 	wc.imm_data = 0;
-	wc.qp_num = qp->ibqp.qp_num;
+	wc.qp = &qp->ibqp;
 	wc.src_qp = 0;
 	wc.wc_flags = 0;
 	wc.pkey_index = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index ce60387..5ff20cb 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -702,7 +702,7 @@
 		wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
 		wc->vendor_err = 0;
 		wc->byte_len = 0;
-		wc->qp_num = qp->ibqp.qp_num;
+		wc->qp = &qp->ibqp;
 		wc->src_qp = qp->remote_qpn;
 		wc->pkey_index = 0;
 		wc->slid = qp->remote_ah_attr.dlid;
@@ -836,7 +836,7 @@
 			wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
 			wc.vendor_err = 0;
 			wc.byte_len = wqe->length;
-			wc.qp_num = qp->ibqp.qp_num;
+			wc.qp = &qp->ibqp;
 			wc.src_qp = qp->remote_qpn;
 			wc.pkey_index = 0;
 			wc.slid = qp->remote_ah_attr.dlid;
@@ -951,7 +951,7 @@
 			wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
 			wc.vendor_err = 0;
 			wc.byte_len = 0;
-			wc.qp_num = qp->ibqp.qp_num;
+			wc.qp = &qp->ibqp;
 			wc.src_qp = qp->remote_qpn;
 			wc.pkey_index = 0;
 			wc.slid = qp->remote_ah_attr.dlid;
@@ -1511,7 +1511,7 @@
 		wc.status = IB_WC_SUCCESS;
 		wc.opcode = IB_WC_RECV;
 		wc.vendor_err = 0;
-		wc.qp_num = qp->ibqp.qp_num;
+		wc.qp = &qp->ibqp;
 		wc.src_qp = qp->remote_qpn;
 		wc.pkey_index = 0;
 		wc.slid = qp->remote_ah_attr.dlid;
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index f753051..e86cb17 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -137,7 +137,7 @@
 	wc.vendor_err = 0;
 	wc.byte_len = 0;
 	wc.imm_data = 0;
-	wc.qp_num = qp->ibqp.qp_num;
+	wc.qp = &qp->ibqp;
 	wc.src_qp = 0;
 	wc.wc_flags = 0;
 	wc.pkey_index = 0;
@@ -336,7 +336,7 @@
 			wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
 			wc.vendor_err = 0;
 			wc.byte_len = 0;
-			wc.qp_num = sqp->ibqp.qp_num;
+			wc.qp = &sqp->ibqp;
 			wc.src_qp = sqp->remote_qpn;
 			wc.pkey_index = 0;
 			wc.slid = sqp->remote_ah_attr.dlid;
@@ -426,7 +426,7 @@
 	wc.status = IB_WC_SUCCESS;
 	wc.vendor_err = 0;
 	wc.byte_len = wqe->length;
-	wc.qp_num = qp->ibqp.qp_num;
+	wc.qp = &qp->ibqp;
 	wc.src_qp = qp->remote_qpn;
 	/* XXX do we know which pkey matched? Only needed for GSI. */
 	wc.pkey_index = 0;
@@ -447,7 +447,7 @@
 		wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
 		wc.vendor_err = 0;
 		wc.byte_len = wqe->length;
-		wc.qp_num = sqp->ibqp.qp_num;
+		wc.qp = &sqp->ibqp;
 		wc.src_qp = 0;
 		wc.pkey_index = 0;
 		wc.slid = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
index e636cfd..325d663 100644
--- a/drivers/infiniband/hw/ipath/ipath_uc.c
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -49,7 +49,7 @@
 		wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
 		wc->vendor_err = 0;
 		wc->byte_len = wqe->length;
-		wc->qp_num = qp->ibqp.qp_num;
+		wc->qp = &qp->ibqp;
 		wc->src_qp = qp->remote_qpn;
 		wc->pkey_index = 0;
 		wc->slid = qp->remote_ah_attr.dlid;
@@ -411,7 +411,7 @@
 		wc.status = IB_WC_SUCCESS;
 		wc.opcode = IB_WC_RECV;
 		wc.vendor_err = 0;
-		wc.qp_num = qp->ibqp.qp_num;
+		wc.qp = &qp->ibqp;
 		wc.src_qp = qp->remote_qpn;
 		wc.pkey_index = 0;
 		wc.slid = qp->remote_ah_attr.dlid;
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
index 49f1102..9a3e546 100644
--- a/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -66,7 +66,7 @@
 	wc.vendor_err = 0;
 	wc.byte_len = 0;
 	wc.imm_data = 0;
-	wc.qp_num = qp->ibqp.qp_num;
+	wc.qp = &qp->ibqp;
 	wc.src_qp = 0;
 	wc.wc_flags = 0;
 	wc.pkey_index = 0;
@@ -255,7 +255,7 @@
 	wc->status = IB_WC_SUCCESS;
 	wc->opcode = IB_WC_RECV;
 	wc->vendor_err = 0;
-	wc->qp_num = qp->ibqp.qp_num;
+	wc->qp = &qp->ibqp;
 	wc->src_qp = sqp->ibqp.qp_num;
 	/* XXX do we know which pkey matched? Only needed for GSI. */
 	wc->pkey_index = 0;
@@ -474,7 +474,7 @@
 		wc.vendor_err = 0;
 		wc.opcode = IB_WC_SEND;
 		wc.byte_len = len;
-		wc.qp_num = qp->ibqp.qp_num;
+		wc.qp = &qp->ibqp;
 		wc.src_qp = 0;
 		wc.wc_flags = 0;
 		/* XXX initialize other fields? */
@@ -651,7 +651,7 @@
 	wc.status = IB_WC_SUCCESS;
 	wc.opcode = IB_WC_RECV;
 	wc.vendor_err = 0;
-	wc.qp_num = qp->ibqp.qp_num;
+	wc.qp = &qp->ibqp;
 	wc.src_qp = src_qp;
 	/* XXX do we know which pkey matched? Only needed for GSI. */
 	wc.pkey_index = 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 768df72..968d151 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1854,7 +1854,7 @@
 
 		memset(inbox + 256, 0, 256);
 
-		MTHCA_PUT(inbox, in_wc->qp_num,     MAD_IFC_MY_QPN_OFFSET);
+		MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET);
 		MTHCA_PUT(inbox, in_wc->src_qp,     MAD_IFC_RQPN_OFFSET);
 
 		val = in_wc->sl << 4;
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 283d50b..efd79ef 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -54,6 +54,10 @@
 	MTHCA_CQ_ENTRY_SIZE = 0x20
 };
 
+enum {
+	MTHCA_ATOMIC_BYTE_LEN = 8
+};
+
 /*
  * Must be packed because start is 64 bits but only aligned to 32 bits.
  */
@@ -530,7 +534,7 @@
 		}
 	}
 
-	entry->qp_num = (*cur_qp)->qpn;
+	entry->qp = &(*cur_qp)->ibqp;
 
 	if (is_send) {
 		wq = &(*cur_qp)->sq;
@@ -599,11 +603,11 @@
 			break;
 		case MTHCA_OPCODE_ATOMIC_CS:
 			entry->opcode    = IB_WC_COMP_SWAP;
-			entry->byte_len  = be32_to_cpu(cqe->byte_cnt);
+			entry->byte_len  = MTHCA_ATOMIC_BYTE_LEN;
 			break;
 		case MTHCA_OPCODE_ATOMIC_FA:
 			entry->opcode    = IB_WC_FETCH_ADD;
-			entry->byte_len  = be32_to_cpu(cqe->byte_cnt);
+			entry->byte_len  = MTHCA_ATOMIC_BYTE_LEN;
 			break;
 		case MTHCA_OPCODE_BIND_MW:
 			entry->opcode    = IB_WC_BIND_MW;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 15cc2f6..6b19645 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -232,7 +232,7 @@
 
 	list_for_each_entry(chunk, &icm->chunk_list, list) {
 		for (i = 0; i < chunk->npages; ++i) {
-			if (chunk->mem[i].length >= offset) {
+			if (chunk->mem[i].length > offset) {
 				page = chunk->mem[i].page;
 				goto out;
 			}
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index d844a25..5f5214c 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -429,13 +429,18 @@
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
 	struct mthca_qp *qp = to_mqp(ibqp);
-	int err;
-	struct mthca_mailbox *mailbox;
+	int err = 0;
+	struct mthca_mailbox *mailbox = NULL;
 	struct mthca_qp_param *qp_param;
 	struct mthca_qp_context *context;
 	int mthca_state;
 	u8 status;
 
+	if (qp->state == IB_QPS_RESET) {
+		qp_attr->qp_state = IB_QPS_RESET;
+		goto done;
+	}
+
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox))
 		return PTR_ERR(mailbox);
@@ -454,7 +459,6 @@
 	mthca_state = be32_to_cpu(context->flags) >> 28;
 
 	qp_attr->qp_state 	     = to_ib_qp_state(mthca_state);
-	qp_attr->cur_qp_state 	     = qp_attr->qp_state;
 	qp_attr->path_mtu 	     = context->mtu_msgmax >> 5;
 	qp_attr->path_mig_state      =
 		to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3);
@@ -464,11 +468,6 @@
 	qp_attr->dest_qp_num 	     = be32_to_cpu(context->remote_qpn) & 0xffffff;
 	qp_attr->qp_access_flags     =
 		to_ib_qp_access_flags(be32_to_cpu(context->params2));
-	qp_attr->cap.max_send_wr     = qp->sq.max;
-	qp_attr->cap.max_recv_wr     = qp->rq.max;
-	qp_attr->cap.max_send_sge    = qp->sq.max_gs;
-	qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
-	qp_attr->cap.max_inline_data = qp->max_inline_data;
 
 	if (qp->transport == RC || qp->transport == UC) {
 		to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
@@ -495,7 +494,16 @@
 	qp_attr->retry_cnt 	    = (be32_to_cpu(context->params1) >> 16) & 0x7;
 	qp_attr->rnr_retry 	    = context->pri_path.rnr_retry >> 5;
 	qp_attr->alt_timeout 	    = context->alt_path.ackto >> 3;
-	qp_init_attr->cap 	    = qp_attr->cap;
+
+done:
+	qp_attr->cur_qp_state	     = qp_attr->qp_state;
+	qp_attr->cap.max_send_wr     = qp->sq.max;
+	qp_attr->cap.max_recv_wr     = qp->rq.max;
+	qp_attr->cap.max_send_sge    = qp->sq.max_gs;
+	qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
+	qp_attr->cap.max_inline_data = qp->max_inline_data;
+
+	qp_init_attr->cap	     = qp_attr->cap;
 
 out:
 	mthca_free_mailbox(dev, mailbox);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 9b2041e..dd221ed 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -177,7 +177,7 @@
 	 * - if yes, the mtask is recycled at iscsi_complete_pdu
 	 * - if no,  the mtask is recycled at iser_snd_completion
 	 */
-	if (error && error != -EAGAIN)
+	if (error && error != -ENOBUFS)
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 
 	return error;
@@ -241,7 +241,7 @@
 		error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask);
 
  iscsi_iser_ctask_xmit_exit:
-	if (error && error != -EAGAIN)
+	if (error && error != -ENOBUFS)
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 	return error;
 }
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index e73c87b..0a7d1ab 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -304,18 +304,14 @@
 static int
 iser_check_xmit(struct iscsi_conn *conn, void *task)
 {
-	int rc = 0;
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 
-	write_lock_bh(conn->recv_lock);
 	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
 	    ISER_QP_MAX_REQ_DTOS) {
-		iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task);
-		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
-		rc = -EAGAIN;
+		iser_dbg("%ld can't xmit task %p\n",jiffies,task);
+		return -ENOBUFS;
 	}
-	write_unlock_bh(conn->recv_lock);
-	return rc;
+	return 0;
 }
 
 
@@ -340,7 +336,7 @@
 		return -EPERM;
 	}
 	if (iser_check_xmit(conn, ctask))
-		return -EAGAIN;
+		return -ENOBUFS;
 
 	edtl = ntohl(hdr->data_length);
 
@@ -426,7 +422,7 @@
 	}
 
 	if (iser_check_xmit(conn, ctask))
-		return -EAGAIN;
+		return -ENOBUFS;
 
 	itt = ntohl(hdr->itt);
 	data_seg_len = ntoh24(hdr->dlength);
@@ -498,7 +494,7 @@
 	}
 
 	if (iser_check_xmit(conn,mtask))
-		return -EAGAIN;
+		return -ENOBUFS;
 
 	/* build the tx desc regd header and add it to the tx desc dto */
 	mdesc->type = ISCSI_TX_CONTROL;
@@ -605,6 +601,7 @@
 	struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
 	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
 	struct iscsi_mgmt_task *mtask;
+	int resume_tx = 0;
 
 	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
 
@@ -613,15 +610,16 @@
 	if (tx_desc->type == ISCSI_TX_DATAOUT)
 		kmem_cache_free(ig.desc_cache, tx_desc);
 
+	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
+	    ISER_QP_MAX_REQ_DTOS)
+		resume_tx = 1;
+
 	atomic_dec(&ib_conn->post_send_buf_count);
 
-	write_lock(conn->recv_lock);
-	if (conn->suspend_tx) {
+	if (resume_tx) {
 		iser_dbg("%ld resuming tx\n",jiffies);
-		clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 		scsi_queue_work(conn->session->host, &conn->xmitwork);
 	}
-	write_unlock(conn->recv_lock);
 
 	if (tx_desc->type == ISCSI_TX_CONTROL) {
 		/* this arithmetic is legal by libiscsi dd_data allocation */
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index cdecbf5..5e8ac57 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -548,6 +548,7 @@
 	target->tx_head	 = 0;
 	target->tx_tail  = 0;
 
+	target->qp_in_error = 0;
 	ret = srp_connect_target(target);
 	if (ret)
 		goto err;
@@ -878,6 +879,7 @@
 			printk(KERN_ERR PFX "failed %s status %d\n",
 			       wc.wr_id & SRP_OP_RECV ? "receive" : "send",
 			       wc.status);
+			target->qp_in_error = 1;
 			break;
 		}
 
@@ -1337,6 +1339,8 @@
 
 	printk(KERN_ERR "SRP abort called\n");
 
+	if (target->qp_in_error)
+		return FAILED;
 	if (srp_find_req(target, scmnd, &req))
 		return FAILED;
 	if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
@@ -1365,6 +1369,8 @@
 
 	printk(KERN_ERR "SRP reset_device called\n");
 
+	if (target->qp_in_error)
+		return FAILED;
 	if (srp_find_req(target, scmnd, &req))
 		return FAILED;
 	if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
@@ -1621,18 +1627,30 @@
 		switch (token) {
 		case SRP_OPT_ID_EXT:
 			p = match_strdup(args);
+			if (!p) {
+				ret = -ENOMEM;
+				goto out;
+			}
 			target->id_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
 			kfree(p);
 			break;
 
 		case SRP_OPT_IOC_GUID:
 			p = match_strdup(args);
+			if (!p) {
+				ret = -ENOMEM;
+				goto out;
+			}
 			target->ioc_guid = cpu_to_be64(simple_strtoull(p, NULL, 16));
 			kfree(p);
 			break;
 
 		case SRP_OPT_DGID:
 			p = match_strdup(args);
+			if (!p) {
+				ret = -ENOMEM;
+				goto out;
+			}
 			if (strlen(p) != 32) {
 				printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
 				kfree(p);
@@ -1656,6 +1674,10 @@
 
 		case SRP_OPT_SERVICE_ID:
 			p = match_strdup(args);
+			if (!p) {
+				ret = -ENOMEM;
+				goto out;
+			}
 			target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));
 			kfree(p);
 			break;
@@ -1693,6 +1715,10 @@
 
 		case SRP_OPT_INITIATOR_EXT:
 			p = match_strdup(args);
+			if (!p) {
+				ret = -ENOMEM;
+				goto out;
+			}
 			target->initiator_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
 			kfree(p);
 			break;
@@ -1781,6 +1807,7 @@
 		goto err_free;
 	}
 
+	target->qp_in_error = 0;
 	ret = srp_connect_target(target);
 	if (ret) {
 		printk(KERN_ERR PFX "Connection failed\n");
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index c217723..2f3319c 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -158,6 +158,7 @@
 	struct completion	done;
 	int			status;
 	enum srp_target_state	state;
+	int			qp_in_error;
 };
 
 struct srp_iu {
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 95eff3b..4f75cce 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -356,16 +356,17 @@
 {
 	unsigned long flags;
 	unsigned i;
-	static struct cardstate *ret = NULL;
+	struct cardstate *ret = NULL;
 
 	spin_lock_irqsave(&drv->lock, flags);
 	for (i = 0; i < drv->minors; ++i) {
 		if (!(drv->flags[i] & VALID_MINOR)) {
-			drv->flags[i] = VALID_MINOR;
-			ret = drv->cs + i;
-		}
-		if (ret)
+			if (try_module_get(drv->owner)) {
+				drv->flags[i] = VALID_MINOR;
+				ret = drv->cs + i;
+			}
 			break;
+		}
 	}
 	spin_unlock_irqrestore(&drv->lock, flags);
 	return ret;
@@ -376,6 +377,8 @@
 	unsigned long flags;
 	struct gigaset_driver *drv = cs->driver;
 	spin_lock_irqsave(&drv->lock, flags);
+	if (drv->flags[cs->minor_index] & VALID_MINOR)
+		module_put(drv->owner);
 	drv->flags[cs->minor_index] = 0;
 	spin_unlock_irqrestore(&drv->lock, flags);
 }
@@ -579,7 +582,7 @@
 	} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
 		skb_reserve(bcs->skb, HW_HDR_LEN);
 	else {
-		warn("could not allocate skb\n");
+		warn("could not allocate skb");
 		bcs->inputstate |= INS_skip_frame;
 	}
 
@@ -632,17 +635,25 @@
 	int i;
 
 	gig_dbg(DEBUG_INIT, "allocating cs");
-	cs = alloc_cs(drv);
-	if (!cs)
-		goto error;
+	if (!(cs = alloc_cs(drv))) {
+		err("maximum number of devices exceeded");
+		return NULL;
+	}
+	mutex_init(&cs->mutex);
+	mutex_lock(&cs->mutex);
+
 	gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
 	cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
-	if (!cs->bcs)
+	if (!cs->bcs) {
+		err("out of memory");
 		goto error;
+	}
 	gig_dbg(DEBUG_INIT, "allocating inbuf");
 	cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
-	if (!cs->inbuf)
+	if (!cs->inbuf) {
+		err("out of memory");
 		goto error;
+	}
 
 	cs->cs_init = 0;
 	cs->channels = channels;
@@ -654,8 +665,6 @@
 	spin_lock_init(&cs->ev_lock);
 	cs->ev_tail = 0;
 	cs->ev_head = 0;
-	mutex_init(&cs->mutex);
-	mutex_lock(&cs->mutex);
 
 	tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
 		     (unsigned long) cs);
@@ -684,8 +693,10 @@
 
 	for (i = 0; i < channels; ++i) {
 		gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
-		if (!gigaset_initbcs(cs->bcs + i, cs, i))
+		if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
+			err("could not allocate channel %d data", i);
 			goto error;
+		}
 	}
 
 	++cs->cs_init;
@@ -720,8 +731,10 @@
 	make_valid(cs, VALID_ID);
 	++cs->cs_init;
 	gig_dbg(DEBUG_INIT, "setting up hw");
-	if (!cs->ops->initcshw(cs))
+	if (!cs->ops->initcshw(cs)) {
+		err("could not allocate device specific data");
 		goto error;
+	}
 
 	++cs->cs_init;
 
@@ -743,8 +756,8 @@
 	mutex_unlock(&cs->mutex);
 	return cs;
 
-error:	if (cs)
-		mutex_unlock(&cs->mutex);
+error:
+	mutex_unlock(&cs->mutex);
 	gig_dbg(DEBUG_INIT, "failed");
 	gigaset_freecs(cs);
 	return NULL;
@@ -1040,7 +1053,6 @@
 	spin_unlock_irqrestore(&driver_lock, flags);
 
 	gigaset_if_freedriver(drv);
-	module_put(drv->owner);
 
 	kfree(drv->cs);
 	kfree(drv->flags);
@@ -1072,10 +1084,6 @@
 	if (!drv)
 		return NULL;
 
-	if (!try_module_get(owner))
-		goto out1;
-
-	drv->cs = NULL;
 	drv->have_tty = 0;
 	drv->minor = minor;
 	drv->minors = minors;
@@ -1087,11 +1095,11 @@
 
 	drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
 	if (!drv->cs)
-		goto out2;
+		goto error;
 
 	drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
 	if (!drv->flags)
-		goto out3;
+		goto error;
 
 	for (i = 0; i < minors; ++i) {
 		drv->flags[i] = 0;
@@ -1108,11 +1116,8 @@
 
 	return drv;
 
-out3:
+error:
 	kfree(drv->cs);
-out2:
-	module_put(owner);
-out1:
 	kfree(drv);
 	return NULL;
 }
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 91e0c75..2db1ca4 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -242,6 +242,7 @@
 	u64 pdptrs[4]; /* pae */
 	u64 shadow_efer;
 	u64 apic_base;
+	u64 ia32_misc_enable_msr;
 	int nmsrs;
 	struct vmx_msr_entry *guest_msrs;
 	struct vmx_msr_entry *host_msrs;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 67c1154..b10972e 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -272,7 +272,9 @@
 
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
+	vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
 	kvm_mmu_destroy(vcpu);
+	vcpu_put(vcpu);
 	kvm_arch_ops->vcpu_free(vcpu);
 }
 
@@ -1224,6 +1226,9 @@
 	case MSR_IA32_APICBASE:
 		data = vcpu->apic_base;
 		break;
+	case MSR_IA32_MISC_ENABLE:
+		data = vcpu->ia32_misc_enable_msr;
+		break;
 #ifdef CONFIG_X86_64
 	case MSR_EFER:
 		data = vcpu->shadow_efer;
@@ -1295,6 +1300,9 @@
 	case MSR_IA32_APICBASE:
 		vcpu->apic_base = data;
 		break;
+	case MSR_IA32_MISC_ENABLE:
+		vcpu->ia32_misc_enable_msr = data;
+		break;
 	default:
 		printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr);
 		return 1;
@@ -1598,6 +1606,10 @@
 
 static unsigned num_msrs_to_save;
 
+static u32 emulated_msrs[] = {
+	MSR_IA32_MISC_ENABLE,
+};
+
 static __init void kvm_init_msr_list(void)
 {
 	u32 dummy[2];
@@ -1923,7 +1935,7 @@
 		if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
 			goto out;
 		n = msr_list.nmsrs;
-		msr_list.nmsrs = num_msrs_to_save;
+		msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs);
 		if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
 			goto out;
 		r = -E2BIG;
@@ -1933,6 +1945,11 @@
 		if (copy_to_user(user_msr_list->indices, &msrs_to_save,
 				 num_msrs_to_save * sizeof(u32)))
 			goto out;
+		if (copy_to_user(user_msr_list->indices
+				 + num_msrs_to_save * sizeof(u32),
+				 &emulated_msrs,
+				 ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
+			goto out;
 		r = 0;
 		break;
 	}
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index c6f9729..22c426c 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -143,6 +143,7 @@
 #define PFERR_PRESENT_MASK (1U << 0)
 #define PFERR_WRITE_MASK (1U << 1)
 #define PFERR_USER_MASK (1U << 2)
+#define PFERR_FETCH_MASK (1U << 4)
 
 #define PT64_ROOT_LEVEL 4
 #define PT32_ROOT_LEVEL 2
@@ -168,6 +169,11 @@
 	return 1;
 }
 
+static int is_nx(struct kvm_vcpu *vcpu)
+{
+	return vcpu->shadow_efer & EFER_NX;
+}
+
 static int is_present_pte(unsigned long pte)
 {
 	return pte & PT_PRESENT_MASK;
@@ -992,16 +998,6 @@
 	return 0;
 }
 
-static int may_access(u64 pte, int write, int user)
-{
-
-	if (user && !(pte & PT_USER_MASK))
-		return 0;
-	if (write && !(pte & PT_WRITABLE_MASK))
-		return 0;
-	return 1;
-}
-
 static void paging_free(struct kvm_vcpu *vcpu)
 {
 	nonpaging_free(vcpu);
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 2dbf430..149fa45 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -63,13 +63,15 @@
 	pt_element_t *ptep;
 	pt_element_t inherited_ar;
 	gfn_t gfn;
+	u32 error_code;
 };
 
 /*
  * Fetch a guest pte for a guest virtual address
  */
-static void FNAME(walk_addr)(struct guest_walker *walker,
-			     struct kvm_vcpu *vcpu, gva_t addr)
+static int FNAME(walk_addr)(struct guest_walker *walker,
+			    struct kvm_vcpu *vcpu, gva_t addr,
+			    int write_fault, int user_fault, int fetch_fault)
 {
 	hpa_t hpa;
 	struct kvm_memory_slot *slot;
@@ -86,7 +88,7 @@
 		walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3];
 		root = *walker->ptep;
 		if (!(root & PT_PRESENT_MASK))
-			return;
+			goto not_present;
 		--walker->level;
 	}
 #endif
@@ -111,11 +113,23 @@
 		ASSERT(((unsigned long)walker->table & PAGE_MASK) ==
 		       ((unsigned long)ptep & PAGE_MASK));
 
-		if (is_present_pte(*ptep) && !(*ptep &  PT_ACCESSED_MASK))
-			*ptep |= PT_ACCESSED_MASK;
-
 		if (!is_present_pte(*ptep))
-			break;
+			goto not_present;
+
+		if (write_fault && !is_writeble_pte(*ptep))
+			if (user_fault || is_write_protection(vcpu))
+				goto access_error;
+
+		if (user_fault && !(*ptep & PT_USER_MASK))
+			goto access_error;
+
+#if PTTYPE == 64
+		if (fetch_fault && is_nx(vcpu) && (*ptep & PT64_NX_MASK))
+			goto access_error;
+#endif
+
+		if (!(*ptep & PT_ACCESSED_MASK))
+			*ptep |= PT_ACCESSED_MASK; 	/* avoid rmw */
 
 		if (walker->level == PT_PAGE_TABLE_LEVEL) {
 			walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
@@ -146,6 +160,23 @@
 	}
 	walker->ptep = ptep;
 	pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep);
+	return 1;
+
+not_present:
+	walker->error_code = 0;
+	goto err;
+
+access_error:
+	walker->error_code = PFERR_PRESENT_MASK;
+
+err:
+	if (write_fault)
+		walker->error_code |= PFERR_WRITE_MASK;
+	if (user_fault)
+		walker->error_code |= PFERR_USER_MASK;
+	if (fetch_fault)
+		walker->error_code |= PFERR_FETCH_MASK;
+	return 0;
 }
 
 static void FNAME(release_walker)(struct guest_walker *walker)
@@ -274,7 +305,7 @@
 	struct kvm_mmu_page *page;
 
 	if (is_writeble_pte(*shadow_ent))
-		return 0;
+		return !user || (*shadow_ent & PT_USER_MASK);
 
 	writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK;
 	if (user) {
@@ -347,8 +378,8 @@
 			       u32 error_code)
 {
 	int write_fault = error_code & PFERR_WRITE_MASK;
-	int pte_present = error_code & PFERR_PRESENT_MASK;
 	int user_fault = error_code & PFERR_USER_MASK;
+	int fetch_fault = error_code & PFERR_FETCH_MASK;
 	struct guest_walker walker;
 	u64 *shadow_pte;
 	int fixed;
@@ -365,19 +396,20 @@
 	/*
 	 * Look up the shadow pte for the faulting address.
 	 */
-	FNAME(walk_addr)(&walker, vcpu, addr);
-	shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
+	r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault,
+			     fetch_fault);
 
 	/*
 	 * The page is not mapped by the guest.  Let the guest handle it.
 	 */
-	if (!shadow_pte) {
-		pgprintk("%s: not mapped\n", __FUNCTION__);
-		inject_page_fault(vcpu, addr, error_code);
+	if (!r) {
+		pgprintk("%s: guest page fault\n", __FUNCTION__);
+		inject_page_fault(vcpu, addr, walker.error_code);
 		FNAME(release_walker)(&walker);
 		return 0;
 	}
 
+	shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
 	pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__,
 		 shadow_pte, *shadow_pte);
 
@@ -399,22 +431,7 @@
 	 * mmio: emulate if accessible, otherwise its a guest fault.
 	 */
 	if (is_io_pte(*shadow_pte)) {
-		if (may_access(*shadow_pte, write_fault, user_fault))
-			return 1;
-		pgprintk("%s: io work, no access\n", __FUNCTION__);
-		inject_page_fault(vcpu, addr,
-				  error_code | PFERR_PRESENT_MASK);
-		kvm_mmu_audit(vcpu, "post page fault (io)");
-		return 0;
-	}
-
-	/*
-	 * pte not present, guest page fault.
-	 */
-	if (pte_present && !fixed && !write_pt) {
-		inject_page_fault(vcpu, addr, error_code);
-		kvm_mmu_audit(vcpu, "post page fault (guest)");
-		return 0;
+		return 1;
 	}
 
 	++kvm_stat.pf_fixed;
@@ -429,7 +446,7 @@
 	pt_element_t guest_pte;
 	gpa_t gpa;
 
-	FNAME(walk_addr)(&walker, vcpu, vaddr);
+	FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
 	guest_pte = *walker.ptep;
 	FNAME(release_walker)(&walker);
 
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index ccc06b1..c79df79 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
+#include <linux/profile.h>
 #include <asm/desc.h>
 
 #include "kvm_svm.h"
@@ -501,6 +502,7 @@
 				(1ULL << INTERCEPT_IOIO_PROT) |
 				(1ULL << INTERCEPT_MSR_PROT) |
 				(1ULL << INTERCEPT_TASK_SWITCH) |
+				(1ULL << INTERCEPT_SHUTDOWN) |
 				(1ULL << INTERCEPT_VMRUN) |
 				(1ULL << INTERCEPT_VMMCALL) |
 				(1ULL << INTERCEPT_VMLOAD) |
@@ -679,14 +681,14 @@
 
 static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
 {
-	dt->limit = vcpu->svm->vmcb->save.ldtr.limit;
-	dt->base = vcpu->svm->vmcb->save.ldtr.base;
+	dt->limit = vcpu->svm->vmcb->save.idtr.limit;
+	dt->base = vcpu->svm->vmcb->save.idtr.base;
 }
 
 static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
 {
-	vcpu->svm->vmcb->save.ldtr.limit = dt->limit;
-	vcpu->svm->vmcb->save.ldtr.base = dt->base ;
+	vcpu->svm->vmcb->save.idtr.limit = dt->limit;
+	vcpu->svm->vmcb->save.idtr.base = dt->base ;
 }
 
 static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
@@ -891,6 +893,19 @@
 	return 0;
 }
 
+static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	/*
+	 * VMCB is undefined after a SHUTDOWN intercept
+	 * so reinitialize it.
+	 */
+	memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+	init_vmcb(vcpu->svm->vmcb);
+
+	kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+	return 0;
+}
+
 static int io_get_override(struct kvm_vcpu *vcpu,
 			  struct vmcb_seg **seg,
 			  int *addr_override)
@@ -1148,7 +1163,7 @@
 	case MSR_K6_STAR:
 		vcpu->svm->vmcb->save.star = data;
 		break;
-#ifdef CONFIG_X86_64_
+#ifdef CONFIG_X86_64
 	case MSR_LSTAR:
 		vcpu->svm->vmcb->save.lstar = data;
 		break;
@@ -1248,6 +1263,7 @@
 	[SVM_EXIT_IOIO] 		  	= io_interception,
 	[SVM_EXIT_MSR]				= msr_interception,
 	[SVM_EXIT_TASK_SWITCH]			= task_switch_interception,
+	[SVM_EXIT_SHUTDOWN]			= shutdown_interception,
 	[SVM_EXIT_VMRUN]			= invalid_op_interception,
 	[SVM_EXIT_VMMCALL]			= invalid_op_interception,
 	[SVM_EXIT_VMLOAD]			= invalid_op_interception,
@@ -1406,7 +1422,8 @@
 	int r;
 
 again:
-	do_interrupt_requests(vcpu, kvm_run);
+	if (!vcpu->mmio_read_completed)
+		do_interrupt_requests(vcpu, kvm_run);
 
 	clgi();
 
@@ -1558,6 +1575,13 @@
 
 	reload_tss(vcpu);
 
+	/*
+	 * Profile KVM exit RIPs:
+	 */
+	if (unlikely(prof_on == KVM_PROFILING))
+		profile_hit(KVM_PROFILING,
+			(void *)(unsigned long)vcpu->svm->vmcb->save.rip);
+
 	stgi();
 
 	kvm_reput_irq(vcpu);
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index d4701cb..54c35c0 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/profile.h>
 #include <asm/io.h>
 #include <asm/desc.h>
 
@@ -1115,6 +1116,8 @@
 
 		if (rdmsr_safe(index, &data_low, &data_high) < 0)
 			continue;
+		if (wrmsr_safe(index, data_low, data_high) < 0)
+			continue;
 		data = data_low | ((u64)data_high << 32);
 		vcpu->host_msrs[j].index = index;
 		vcpu->host_msrs[j].reserved = 0;
@@ -1716,7 +1719,8 @@
 	vmcs_writel(HOST_GS_BASE, segment_base(gs_sel));
 #endif
 
-	do_interrupt_requests(vcpu, kvm_run);
+	if (!vcpu->mmio_read_completed)
+		do_interrupt_requests(vcpu, kvm_run);
 
 	if (vcpu->guest_debug.enabled)
 		kvm_guest_debug_pre(vcpu);
@@ -1823,7 +1827,7 @@
 #endif
 		"setbe %0 \n\t"
 		"popf \n\t"
-	      : "=g" (fail)
+	      : "=q" (fail)
 	      : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP),
 		"c"(vcpu),
 		[rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])),
@@ -1859,6 +1863,12 @@
 	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 #endif
 
+	/*
+	 * Profile KVM exit RIPs:
+	 */
+	if (unlikely(prof_on == KVM_PROFILING))
+		profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
+
 	kvm_run->exit_type = 0;
 	if (fail) {
 		kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index be70795..7513cdd 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -61,6 +61,7 @@
 #define ModRM       (1<<6)
 /* Destination is only written; never read. */
 #define Mov         (1<<7)
+#define BitOp       (1<<8)
 
 static u8 opcode_table[256] = {
 	/* 0x00 - 0x07 */
@@ -148,7 +149,7 @@
 	0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
 };
 
-static u8 twobyte_table[256] = {
+static u16 twobyte_table[256] = {
 	/* 0x00 - 0x0F */
 	0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
 	0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
@@ -180,16 +181,16 @@
 	/* 0x90 - 0x9F */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xA0 - 0xA7 */
-	0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0,
+	0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
 	/* 0xA8 - 0xAF */
-	0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0,
+	0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
 	/* 0xB0 - 0xB7 */
 	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,
-	    DstMem | SrcReg | ModRM,
+	    DstMem | SrcReg | ModRM | BitOp,
 	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
 	    DstReg | SrcMem16 | ModRM | Mov,
 	/* 0xB8 - 0xBF */
-	0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM,
+	0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp,
 	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
 	    DstReg | SrcMem16 | ModRM | Mov,
 	/* 0xC0 - 0xCF */
@@ -469,7 +470,8 @@
 int
 x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
-	u8 b, d, sib, twobyte = 0, rex_prefix = 0;
+	unsigned d;
+	u8 b, sib, twobyte = 0, rex_prefix = 0;
 	u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
 	unsigned long *override_base = NULL;
 	unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
@@ -726,46 +728,6 @@
 		;
 	}
 
-	/* Decode and fetch the destination operand: register or memory. */
-	switch (d & DstMask) {
-	case ImplicitOps:
-		/* Special instructions do their own operand decoding. */
-		goto special_insn;
-	case DstReg:
-		dst.type = OP_REG;
-		if ((d & ByteOp)
-		    && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
-			dst.ptr = decode_register(modrm_reg, _regs,
-						  (rex_prefix == 0));
-			dst.val = *(u8 *) dst.ptr;
-			dst.bytes = 1;
-		} else {
-			dst.ptr = decode_register(modrm_reg, _regs, 0);
-			switch ((dst.bytes = op_bytes)) {
-			case 2:
-				dst.val = *(u16 *)dst.ptr;
-				break;
-			case 4:
-				dst.val = *(u32 *)dst.ptr;
-				break;
-			case 8:
-				dst.val = *(u64 *)dst.ptr;
-				break;
-			}
-		}
-		break;
-	case DstMem:
-		dst.type = OP_MEM;
-		dst.ptr = (unsigned long *)cr2;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-		if (!(d & Mov) && /* optimisation - avoid slow emulated read */
-		    ((rc = ops->read_emulated((unsigned long)dst.ptr,
-					      &dst.val, dst.bytes, ctxt)) != 0))
-			goto done;
-		break;
-	}
-	dst.orig_val = dst.val;
-
 	/*
 	 * Decode and fetch the source operand: register, memory
 	 * or immediate.
@@ -838,6 +800,50 @@
 		break;
 	}
 
+	/* Decode and fetch the destination operand: register or memory. */
+	switch (d & DstMask) {
+	case ImplicitOps:
+		/* Special instructions do their own operand decoding. */
+		goto special_insn;
+	case DstReg:
+		dst.type = OP_REG;
+		if ((d & ByteOp)
+		    && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
+			dst.ptr = decode_register(modrm_reg, _regs,
+						  (rex_prefix == 0));
+			dst.val = *(u8 *) dst.ptr;
+			dst.bytes = 1;
+		} else {
+			dst.ptr = decode_register(modrm_reg, _regs, 0);
+			switch ((dst.bytes = op_bytes)) {
+			case 2:
+				dst.val = *(u16 *)dst.ptr;
+				break;
+			case 4:
+				dst.val = *(u32 *)dst.ptr;
+				break;
+			case 8:
+				dst.val = *(u64 *)dst.ptr;
+				break;
+			}
+		}
+		break;
+	case DstMem:
+		dst.type = OP_MEM;
+		dst.ptr = (unsigned long *)cr2;
+		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+		if (d & BitOp) {
+			dst.ptr += src.val / BITS_PER_LONG;
+			dst.bytes = sizeof(long);
+		}
+		if (!(d & Mov) && /* optimisation - avoid slow emulated read */
+		    ((rc = ops->read_emulated((unsigned long)dst.ptr,
+					      &dst.val, dst.bytes, ctxt)) != 0))
+			goto done;
+		break;
+	}
+	dst.orig_val = dst.val;
+
 	if (twobyte)
 		goto twobyte_insn;
 
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 5432d07..1110816 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -479,9 +479,12 @@
 	int err = -EINVAL;
 
 	/* page 0 is the superblock, read it... */
-	if (bitmap->file)
-		bitmap->sb_page = read_page(bitmap->file, 0, bitmap, PAGE_SIZE);
-	else {
+	if (bitmap->file) {
+		loff_t isize = i_size_read(bitmap->file->f_mapping->host);
+		int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize;
+
+		bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes);
+	} else {
 		bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
 	}
 	if (IS_ERR(bitmap->sb_page)) {
@@ -877,7 +880,8 @@
 			int count;
 			/* unmap the old page, we're done with it */
 			if (index == num_pages-1)
-				count = bytes - index * PAGE_SIZE;
+				count = bytes + sizeof(bitmap_super_t)
+					- index * PAGE_SIZE;
 			else
 				count = PAGE_SIZE;
 			if (index == 0) {
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index fe7c56e..3668b17 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1116,7 +1116,8 @@
 	if (size != get_capacity(md->disk))
 		memset(&md->geometry, 0, sizeof(md->geometry));
 
-	__set_size(md, size);
+	if (md->suspended_bdev)
+		__set_size(md, size);
 	if (size == 0)
 		return 0;
 
@@ -1264,6 +1265,11 @@
 	if (!dm_suspended(md))
 		goto out;
 
+	/* without bdev, the device size cannot be changed */
+	if (!md->suspended_bdev)
+		if (get_capacity(md->disk) != dm_table_get_size(table))
+			goto out;
+
 	__unbind(md);
 	r = __bind(md, table);
 
@@ -1341,11 +1347,14 @@
 	/* This does not get reverted if there's an error later. */
 	dm_table_presuspend_targets(map);
 
-	md->suspended_bdev = bdget_disk(md->disk, 0);
-	if (!md->suspended_bdev) {
-		DMWARN("bdget failed in dm_suspend");
-		r = -ENOMEM;
-		goto flush_and_out;
+	/* bdget() can stall if the pending I/Os are not flushed */
+	if (!noflush) {
+		md->suspended_bdev = bdget_disk(md->disk, 0);
+		if (!md->suspended_bdev) {
+			DMWARN("bdget failed in dm_suspend");
+			r = -ENOMEM;
+			goto flush_and_out;
+		}
 	}
 
 	/*
@@ -1473,8 +1482,10 @@
 
 	unlock_fs(md);
 
-	bdput(md->suspended_bdev);
-	md->suspended_bdev = NULL;
+	if (md->suspended_bdev) {
+		bdput(md->suspended_bdev);
+		md->suspended_bdev = NULL;
+	}
 
 	clear_bit(DMF_SUSPENDED, &md->flags);
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d1cb45f..e8807ea 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1633,7 +1633,8 @@
 	 * and 'events' is odd, we can roll back to the previous clean state */
 	if (nospares
 	    && (mddev->in_sync && mddev->recovery_cp == MaxSector)
-	    && (mddev->events & 1))
+	    && (mddev->events & 1)
+	    && mddev->events != 1)
 		mddev->events--;
 	else {
 		/* otherwise we have to go forward and ... */
@@ -3563,6 +3564,8 @@
 	char *ptr, *buf = NULL;
 	int err = -ENOMEM;
 
+	md_allow_write(mddev);
+
 	file = kmalloc(sizeof(*file), GFP_KERNEL);
 	if (!file)
 		goto out;
@@ -5031,6 +5034,33 @@
 	}
 }
 
+/* md_allow_write(mddev)
+ * Calling this ensures that the array is marked 'active' so that writes
+ * may proceed without blocking.  It is important to call this before
+ * attempting a GFP_KERNEL allocation while holding the mddev lock.
+ * Must be called with mddev_lock held.
+ */
+void md_allow_write(mddev_t *mddev)
+{
+	if (!mddev->pers)
+		return;
+	if (mddev->ro)
+		return;
+
+	spin_lock_irq(&mddev->write_lock);
+	if (mddev->in_sync) {
+		mddev->in_sync = 0;
+		set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+		if (mddev->safemode_delay &&
+		    mddev->safemode == 0)
+			mddev->safemode = 1;
+		spin_unlock_irq(&mddev->write_lock);
+		md_update_sb(mddev, 0);
+	} else
+		spin_unlock_irq(&mddev->write_lock);
+}
+EXPORT_SYMBOL_GPL(md_allow_write);
+
 static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
 
 #define SYNC_MARKS	10
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index b30f74b..97ee870 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -775,6 +775,7 @@
 	struct bio_list bl;
 	struct page **behind_pages = NULL;
 	const int rw = bio_data_dir(bio);
+	const int do_sync = bio_sync(bio);
 	int do_barriers;
 
 	/*
@@ -835,7 +836,7 @@
 		read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
 		read_bio->bi_bdev = mirror->rdev->bdev;
 		read_bio->bi_end_io = raid1_end_read_request;
-		read_bio->bi_rw = READ;
+		read_bio->bi_rw = READ | do_sync;
 		read_bio->bi_private = r1_bio;
 
 		generic_make_request(read_bio);
@@ -906,7 +907,7 @@
 		mbio->bi_sector	= r1_bio->sector + conf->mirrors[i].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= raid1_end_write_request;
-		mbio->bi_rw = WRITE | do_barriers;
+		mbio->bi_rw = WRITE | do_barriers | do_sync;
 		mbio->bi_private = r1_bio;
 
 		if (behind_pages) {
@@ -941,6 +942,8 @@
 	blk_plug_device(mddev->queue);
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 
+	if (do_sync)
+		md_wakeup_thread(mddev->thread);
 #if 0
 	while ((bio = bio_list_pop(&bl)) != NULL)
 		generic_make_request(bio);
@@ -1263,6 +1266,11 @@
 					sbio->bi_sector = r1_bio->sector +
 						conf->mirrors[i].rdev->data_offset;
 					sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+					for (j = 0; j < vcnt ; j++)
+						memcpy(page_address(sbio->bi_io_vec[j].bv_page),
+						       page_address(pbio->bi_io_vec[j].bv_page),
+						       PAGE_SIZE);
+
 				}
 			}
 	}
@@ -1541,6 +1549,7 @@
 			 * We already have a nr_pending reference on these rdevs.
 			 */
 			int i;
+			const int do_sync = bio_sync(r1_bio->master_bio);
 			clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
 			clear_bit(R1BIO_Barrier, &r1_bio->state);
 			for (i=0; i < conf->raid_disks; i++)
@@ -1561,7 +1570,7 @@
 						conf->mirrors[i].rdev->data_offset;
 					bio->bi_bdev = conf->mirrors[i].rdev->bdev;
 					bio->bi_end_io = raid1_end_write_request;
-					bio->bi_rw = WRITE;
+					bio->bi_rw = WRITE | do_sync;
 					bio->bi_private = r1_bio;
 					r1_bio->bios[i] = bio;
 					generic_make_request(bio);
@@ -1593,6 +1602,7 @@
 				       (unsigned long long)r1_bio->sector);
 				raid_end_bio_io(r1_bio);
 			} else {
+				const int do_sync = bio_sync(r1_bio->master_bio);
 				r1_bio->bios[r1_bio->read_disk] =
 					mddev->ro ? IO_BLOCKED : NULL;
 				r1_bio->read_disk = disk;
@@ -1608,7 +1618,7 @@
 				bio->bi_sector = r1_bio->sector + rdev->data_offset;
 				bio->bi_bdev = rdev->bdev;
 				bio->bi_end_io = raid1_end_read_request;
-				bio->bi_rw = READ;
+				bio->bi_rw = READ | do_sync;
 				bio->bi_private = r1_bio;
 				unplug = 1;
 				generic_make_request(bio);
@@ -2094,6 +2104,8 @@
 		return -EINVAL;
 	}
 
+	md_allow_write(mddev);
+
 	raid_disks = mddev->raid_disks + mddev->delta_disks;
 
 	if (raid_disks < conf->raid_disks) {
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index f014191..a9401c0 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -782,6 +782,7 @@
 	int i;
 	int chunk_sects = conf->chunk_mask + 1;
 	const int rw = bio_data_dir(bio);
+	const int do_sync = bio_sync(bio);
 	struct bio_list bl;
 	unsigned long flags;
 
@@ -863,7 +864,7 @@
 			mirror->rdev->data_offset;
 		read_bio->bi_bdev = mirror->rdev->bdev;
 		read_bio->bi_end_io = raid10_end_read_request;
-		read_bio->bi_rw = READ;
+		read_bio->bi_rw = READ | do_sync;
 		read_bio->bi_private = r10_bio;
 
 		generic_make_request(read_bio);
@@ -909,7 +910,7 @@
 			conf->mirrors[d].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
 		mbio->bi_end_io	= raid10_end_write_request;
-		mbio->bi_rw = WRITE;
+		mbio->bi_rw = WRITE | do_sync;
 		mbio->bi_private = r10_bio;
 
 		atomic_inc(&r10_bio->remaining);
@@ -922,6 +923,9 @@
 	blk_plug_device(mddev->queue);
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 
+	if (do_sync)
+		md_wakeup_thread(mddev->thread);
+
 	return 0;
 }
 
@@ -1563,6 +1567,7 @@
 				       (unsigned long long)r10_bio->sector);
 				raid_end_bio_io(r10_bio);
 			} else {
+				const int do_sync = bio_sync(r10_bio->master_bio);
 				rdev = conf->mirrors[mirror].rdev;
 				if (printk_ratelimit())
 					printk(KERN_ERR "raid10: %s: redirecting sector %llu to"
@@ -1574,7 +1579,7 @@
 				bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
 					+ rdev->data_offset;
 				bio->bi_bdev = rdev->bdev;
-				bio->bi_rw = READ;
+				bio->bi_rw = READ | do_sync;
 				bio->bi_private = r10_bio;
 				bio->bi_end_io = raid10_end_read_request;
 				unplug = 1;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index be008f0..467c169 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -405,6 +405,8 @@
 	if (newsize <= conf->pool_size)
 		return 0; /* never bother to shrink */
 
+	md_allow_write(conf->mddev);
+
 	/* Step 1 */
 	sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
 			       sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
@@ -2678,7 +2680,7 @@
 	mdk_rdev_t *rdev;
 
 	if (!in_chunk_boundary(mddev, raid_bio)) {
-		printk("chunk_aligned_read : non aligned\n");
+		PRINTK("chunk_aligned_read : non aligned\n");
 		return 0;
 	}
 	/*
@@ -3250,6 +3252,7 @@
 		else
 			break;
 	}
+	md_allow_write(mddev);
 	while (new > conf->max_nr_stripes) {
 		if (grow_one_stripe(conf))
 			conf->max_nr_stripes++;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 3482e01..2bd84d3 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
+#include <linux/freezer.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
@@ -961,6 +962,7 @@
 		msleep_interruptible(1000);
 		if (kthread_should_stop())
 			break;
+		try_to_freeze();
 
 		/* just monitor the audio status for now ... */
 		memset(&t, 0, sizeof(t));
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
index c1a377f..b6cd21e 100644
--- a/drivers/media/video/ks0127.c
+++ b/drivers/media/video/ks0127.c
@@ -712,13 +712,13 @@
 		*iarg = 0;
 		status = ks0127_read(ks, KS_STAT);
 		if (!(status & 0x20))		 /* NOVID not set */
-			*iarg = (*iarg & DECODER_STATUS_GOOD);
+			*iarg = (*iarg | DECODER_STATUS_GOOD);
 		if ((status & 0x01))		      /* CLOCK set */
-			*iarg = (*iarg & DECODER_STATUS_COLOR);
+			*iarg = (*iarg | DECODER_STATUS_COLOR);
 		if ((status & 0x08))		   /* PALDET set */
-			*iarg = (*iarg & DECODER_STATUS_PAL);
+			*iarg = (*iarg | DECODER_STATUS_PAL);
 		else
-			*iarg = (*iarg & DECODER_STATUS_NTSC);
+			*iarg = (*iarg | DECODER_STATUS_NTSC);
 		break;
 
 	//Catch any unknown command
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 4dead84..ae984bb 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2570,6 +2570,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 1 << 21,
 		.inputs = {{
 			.name   = name_tv,
 			.vmux   = 1,
@@ -2578,15 +2579,20 @@
 		},{
 			.name   = name_comp1,
 			.vmux   = 3,
-			.amux   = LINE1,
+			.amux   = LINE2,	/* unconfirmed, taken from Philips driver */
+		},{
+			.name   = name_comp2,
+			.vmux   = 0,		/* untested, Composite over S-Video */
+			.amux   = LINE2,
 		},{
 			.name   = name_svideo,
-			.vmux   = 0,
-			.amux   = LINE1,
+			.vmux   = 8,
+			.amux   = LINE2,
 		}},
 		.radio = {
 			.name   = name_radio,
-			.amux   = LINE1,
+			.amux   = TV,
+			.gpio   = 0x0200000,
 		},
 	},
 	[SAA7134_BOARD_CINERGY250PCI] = {
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 2624e3f..4e7c1fa 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -184,7 +184,7 @@
 	{ TUNER_ABSENT,        "Thompson DTT757"},
 	/* 80-89 */
 	{ TUNER_ABSENT,        "Philips FQ1216LME MK3"},
-	{ TUNER_ABSENT,        "LG TAPC G701D"},
+	{ TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"},
 	{ TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
 	{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
 	{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h
index baab9c0..17ace39 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.h
+++ b/drivers/media/video/usbvideo/quickcam_messenger.h
@@ -35,27 +35,13 @@
 };
 
 struct bayL0 {
-#ifdef __BIG_ENDIAN
-	u8 r;
-	u8 g;
-#elif __LITTLE_ENDIAN
 	u8 g;
 	u8 r;
-#else
-#error not byte order defined
-#endif
 };
 
 struct bayL1 {
-#ifdef __BIG_ENDIAN
-	u8 g;
-	u8 b;
-#elif __LITTLE_ENDIAN
 	u8 b;
 	u8 g;
-#else
-#error not byte order defined
-#endif
 };
 
 struct cam_size {
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 8c7eba2..7243337 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1080,7 +1080,6 @@
 	int noblock = file->f_flags & O_NONBLOCK;
 	unsigned long lock_flags;
 
-	int frmx = -1;
 	int ret,i;
 	struct usbvision_frame *frame;
 
@@ -1155,7 +1154,7 @@
 		frame->bytes_read = 0;
 
 		/* Mark it as available to be used again. */
-		usbvision->frame[frmx].grabstate = FrameState_Unused;
+		frame->grabstate = FrameState_Unused;
 /* 	} */
 
 	return count;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 752c82c..b87d571 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -90,8 +90,15 @@
 char *v4l2_norm_to_name(v4l2_std_id id)
 {
 	char *name;
+	u32 myid = id;
 
-	switch (id) {
+	/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
+	   64 bit comparations. So, on that architecture, with some gcc variants,
+	   compilation fails. Currently, the max value is 30bit wide.
+	 */
+	BUG_ON(myid != id);
+
+	switch (myid) {
 	case V4L2_STD_PAL:
 		name="PAL";		break;
 	case V4L2_STD_PAL_BG:
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index f429f49..6504a58 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -700,6 +700,7 @@
 		goto done;
 	}
 	if (buf->state == STATE_QUEUED ||
+	    buf->state == STATE_PREPARED ||
 	    buf->state == STATE_ACTIVE) {
 		dprintk(1,"qbuf: buffer is already queued or active.\n");
 		goto done;
@@ -1229,7 +1230,7 @@
 		vaddr,vma->vm_start,vma->vm_end);
 	if (vaddr > vma->vm_end)
 		return NOPAGE_SIGBUS;
-	page = alloc_page(GFP_USER);
+	page = alloc_page(GFP_USER | __GFP_DMA32);
 	if (!page)
 		return NOPAGE_OOM;
 	clear_user_page(page_address(page), vaddr, page);
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index bacb311..d4cf556 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -270,10 +270,15 @@
 	char *p,*s,*basep;
 	struct page *pg;
 	u8   chr,r,g,b,color;
+	unsigned long flags;
+	spinlock_t spinlock;
+
+	spin_lock_init(&spinlock);
 
 	/* Get first addr pointed to pixel position */
 	oldpg=get_addr_pos(pos,pages,to_addr);
 	pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT);
+	spin_lock_irqsave(&spinlock,flags);
 	basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
 
 	/* We will just duplicate the second pixel at the packet */
@@ -376,6 +381,8 @@
 
 end:
 	kunmap_atomic(basep, KM_BOUNCE_READ);
+	spin_unlock_irqrestore(&spinlock,flags);
+
 }
 static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
 {
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 6e068cf..b3f28a0 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -5,7 +5,7 @@
  *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
@@ -73,6 +73,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*
  *  cmd line parameters
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index a4afad4..e316708 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -5,7 +5,7 @@
  *          LSIFC9xx/LSI409xx Fibre Channel
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
@@ -72,11 +72,11 @@
 #endif
 
 #ifndef COPYRIGHT
-#define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
+#define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.02"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.02"
+#define MPT_LINUX_VERSION_COMMON	"3.04.03"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.03"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -1059,7 +1059,7 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #endif		/* } __KERNEL__ */
 
-#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc__)
 #define CAST_U32_TO_PTR(x)	((void *)(u64)x)
 #define CAST_PTR_TO_U32(x)	((u32)(u64)x)
 #else
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 30975cc..504632d 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -4,7 +4,7 @@
  *      For use with LSI Logic PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
@@ -66,7 +66,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-#define COPYRIGHT	"Copyright (c) 1999-2005 LSI Logic Corporation"
+#define COPYRIGHT	"Copyright (c) 1999-2007 LSI Logic Corporation"
 #define MODULEAUTHOR	"LSI Logic Corporation"
 #include "mptbase.h"
 #include "mptctl.h"
@@ -79,6 +79,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index 0439418..e65a1cf 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -5,7 +5,7 @@
  *          LSIFC9xx/LSI409xx Fibre Channel
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ca2f910..c819c23 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -3,7 +3,7 @@
  *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
@@ -75,6 +75,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /* Command line args */
 #define MPTFC_DEV_LOSS_TMO (60)
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index b7c4407..2936204 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -4,7 +4,7 @@
  *      For use with LSI Logic Fibre Channel PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 2000-2005 LSI Logic Corporation
+ *  Copyright (c) 2000-2007 LSI Logic Corporation
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -56,9 +56,11 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
 #define MYNAM		"mptlan"
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 3726ecb..70ab75e 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -4,7 +4,7 @@
  *      For use with LSI Logic Fibre Channel PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 2000-2005 LSI Logic Corporation
+ *  Copyright (c) 2000-2007 LSI Logic Corporation
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 4f0c530..09e9a9d 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -3,9 +3,9 @@
  *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
- *  Copyright (c) 2005-2006 Dell
+ *  Copyright (c) 2005-2007 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -75,6 +75,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 static int mpt_pt_clear;
 module_param(mpt_pt_clear, int, 0);
@@ -245,7 +246,8 @@
 	printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
 	printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
 	printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
-	printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
+	printk("SAS Address=0x%llX\n", (unsigned long long)
+	    le64_to_cpu(sas_address));
 	printk("Target ID=0x%X\n", pg0->TargetID);
 	printk("Bus=0x%X\n", pg0->Bus);
 	/* The PhyNum field specifies the PHY number of the parent
@@ -349,9 +351,9 @@
 	phy_info = port_info->phy_info;
 
 	dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
-	    	"bitmask=0x%016llX\n",
-		__FUNCTION__, port_details, port_details->num_phys,
-		    port_details->phy_bitmask));
+	    "bitmask=0x%016llX\n", __FUNCTION__, port_details,
+	    port_details->num_phys, (unsigned long long)
+	    port_details->phy_bitmask));
 
 	for (i = 0; i < port_info->num_phys; i++, phy_info++) {
 		if(phy_info->port_details != port_details)
@@ -476,7 +478,7 @@
 	for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
 		sas_address = phy_info->attached.sas_address;
 		dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
-			i, sas_address));
+		    i, (unsigned long long)sas_address));
 		if (!sas_address)
 			continue;
 		port_details = phy_info->port_details;
@@ -495,8 +497,8 @@
 				    (1 << phy_info->phy_id);
 			phy_info->sas_port_add_phy=1;
 			dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
-				"phy_id=%d sas_address=0x%018llX\n",
-				i, sas_address));
+			    "phy_id=%d sas_address=0x%018llX\n",
+			    i, (unsigned long long)sas_address));
 			phy_info->port_details = port_details;
 		}
 
@@ -512,8 +514,9 @@
 			if (phy_info_cmp->port_details == port_details )
 				continue;
 			dsaswideprintk((KERN_DEBUG
-				"\t\tphy_id=%d sas_address=0x%018llX\n",
-				j, phy_info_cmp->attached.sas_address));
+			    "\t\tphy_id=%d sas_address=0x%018llX\n",
+			    j, (unsigned long long)
+			    phy_info_cmp->attached.sas_address));
 			if (phy_info_cmp->port_details) {
 				port_details->rphy =
 				    mptsas_get_rphy(phy_info_cmp);
@@ -546,11 +549,10 @@
 		if (!port_details)
 			continue;
 		dsaswideprintk((KERN_DEBUG
-			"%s: [%p]: phy_id=%02d num_phys=%02d "
-		    	"bitmask=0x%016llX\n",
-			__FUNCTION__,
-			port_details, i, port_details->num_phys,
-			port_details->phy_bitmask));
+		    "%s: [%p]: phy_id=%02d num_phys=%02d "
+		    "bitmask=0x%016llX\n", __FUNCTION__,
+		    port_details, i, port_details->num_phys,
+		    (unsigned long long)port_details->phy_bitmask));
 		dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
 			port_details->port, port_details->rphy));
 	}
@@ -2079,8 +2081,10 @@
 static void
 mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
 {
+	int rc;
+
 	sdev->no_uld_attach = data ? 1 : 0;
-	scsi_device_reprobe(sdev);
+	rc = scsi_device_reprobe(sdev);
 }
 
 static void
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 2c72c36..f0cca3e 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -3,7 +3,7 @@
  *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
@@ -76,6 +76,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -701,6 +702,17 @@
 						break;
 					}
 				}
+			} else if (ioc->bus_type == FC) {
+				/*
+				 * The FC IOC may kill a request for variety of
+				 * reasons, some of which may be recovered by a
+				 * retry, some which are unlikely to be
+				 * recovered. Return DID_ERROR instead of
+				 * DID_RESET to permit retry of the command,
+				 * just not an infinite number of them
+				 */
+				sc->result = DID_ERROR << 16;
+				break;
 			}
 
 			/*
@@ -2688,7 +2700,8 @@
 		    struct scsi_device *sdev)
 {
 	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
-		hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
+		hd->ioc->name, vtarget->bus_id, vtarget->target_id,
+		sdev->lun, hd));
 
 	/* Is LUN supported? If so, upper 2 bits will be 0
 	* in first byte of inquiry data.
@@ -2770,7 +2783,7 @@
 				else {
 					factor = MPT_ULTRA320;
 					if (scsi_device_qas(sdev)) {
-						ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+						ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
 						noQas = 0;
 					}
 					if (sdev->type == TYPE_TAPE &&
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 14a5b6c..187c8af 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -5,7 +5,7 @@
  *          LSIFC9xx/LSI409xx Fibre Channel
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 36641da..203c661 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -3,7 +3,7 @@
  *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
  */
@@ -77,6 +77,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /* Command line args */
 static int mpt_saf_te = MPTSCSIH_SAF_TE;
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 2ab7add..e21e490 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -11,66 +11,25 @@
 
 #include <linux/tifm.h>
 #include <linux/dma-mapping.h>
+#include <linux/freezer.h>
 
 #define DRIVER_NAME "tifm_7xx1"
-#define DRIVER_VERSION "0.6"
+#define DRIVER_VERSION "0.7"
 
 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
 {
-	int cnt;
 	unsigned long flags;
 
 	spin_lock_irqsave(&fm->lock, flags);
-	if (!fm->inhibit_new_cards) {
-		for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-			if (fm->sockets[cnt] == sock) {
-				fm->remove_mask |= (1 << cnt);
-				queue_work(fm->wq, &fm->media_remover);
-				break;
-			}
-		}
-	}
+	fm->socket_change_set |= 1 << sock->socket_id;
+	wake_up_all(&fm->change_set_notify);
 	spin_unlock_irqrestore(&fm->lock, flags);
 }
 
-static void tifm_7xx1_remove_media(struct work_struct *work)
-{
-	struct tifm_adapter *fm =
-		container_of(work, struct tifm_adapter, media_remover);
-	unsigned long flags;
-	int cnt;
-	struct tifm_dev *sock;
-
-	if (!class_device_get(&fm->cdev))
-		return;
-	spin_lock_irqsave(&fm->lock, flags);
-	for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-		if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) {
-			printk(KERN_INFO DRIVER_NAME
-			       ": demand removing card from socket %d\n", cnt);
-			sock = fm->sockets[cnt];
-			fm->sockets[cnt] = NULL;
-			fm->remove_mask &= ~(1 << cnt);
-
-			writel(0x0e00, sock->addr + SOCK_CONTROL);
-
-			writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-				fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-			writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-				fm->addr + FM_SET_INTERRUPT_ENABLE);
-
-			spin_unlock_irqrestore(&fm->lock, flags);
-			device_unregister(&sock->dev);
-			spin_lock_irqsave(&fm->lock, flags);
-		}
-	}
-	spin_unlock_irqrestore(&fm->lock, flags);
-	class_device_put(&fm->cdev);
-}
-
 static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
 {
 	struct tifm_adapter *fm = dev_id;
+	struct tifm_dev *sock;
 	unsigned int irq_status;
 	unsigned int sock_irq_status, cnt;
 
@@ -84,42 +43,32 @@
 	if (irq_status & TIFM_IRQ_ENABLE) {
 		writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 
-		for (cnt = 0; cnt <  fm->max_sockets; cnt++) {
-			sock_irq_status = (irq_status >> cnt) &
-					(TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK);
+		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+			sock = fm->sockets[cnt];
+			sock_irq_status = (irq_status >> cnt)
+					  & (TIFM_IRQ_FIFOMASK(1)
+					     | TIFM_IRQ_CARDMASK(1));
 
-			if (fm->sockets[cnt]) {
-				if (sock_irq_status &&
-						fm->sockets[cnt]->signal_irq)
-					sock_irq_status = fm->sockets[cnt]->
-						signal_irq(fm->sockets[cnt],
-							sock_irq_status);
-
-				if (irq_status & (1 << cnt))
-					fm->remove_mask |= 1 << cnt;
-			} else {
-				if (irq_status & (1 << cnt))
-					fm->insert_mask |= 1 << cnt;
-			}
+			if (sock && sock_irq_status)
+				sock->signal_irq(sock, sock_irq_status);
 		}
+
+		fm->socket_change_set |= irq_status
+					 & ((1 << fm->num_sockets) - 1);
 	}
 	writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
 
-	if (!fm->inhibit_new_cards) {
-		if (!fm->remove_mask && !fm->insert_mask) {
-			writel(TIFM_IRQ_ENABLE,
-				fm->addr + FM_SET_INTERRUPT_ENABLE);
-		} else {
-			queue_work(fm->wq, &fm->media_remover);
-			queue_work(fm->wq, &fm->media_inserter);
-		}
-	}
+	if (!fm->socket_change_set)
+		writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
+	else
+		wake_up_all(&fm->change_set_notify);
 
 	spin_unlock(&fm->lock);
 	return IRQ_HANDLED;
 }
 
-static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2)
+static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr,
+						 int is_x2)
 {
 	unsigned int s_state;
 	int cnt;
@@ -127,8 +76,8 @@
 	writel(0x0e00, sock_addr + SOCK_CONTROL);
 
 	for (cnt = 0; cnt < 100; cnt++) {
-		if (!(TIFM_SOCK_STATE_POWERED &
-				readl(sock_addr + SOCK_PRESENT_STATE)))
+		if (!(TIFM_SOCK_STATE_POWERED
+		      & readl(sock_addr + SOCK_PRESENT_STATE)))
 			break;
 		msleep(10);
 	}
@@ -151,8 +100,8 @@
 	}
 
 	for (cnt = 0; cnt < 100; cnt++) {
-		if ((TIFM_SOCK_STATE_POWERED &
-				readl(sock_addr + SOCK_PRESENT_STATE)))
+		if ((TIFM_SOCK_STATE_POWERED
+		     & readl(sock_addr + SOCK_PRESENT_STATE)))
 			break;
 		msleep(10);
 	}
@@ -170,130 +119,209 @@
 	return base_addr + ((sock_num + 1) << 10);
 }
 
-static void tifm_7xx1_insert_media(struct work_struct *work)
+static int tifm_7xx1_switch_media(void *data)
 {
-	struct tifm_adapter *fm =
-		container_of(work, struct tifm_adapter, media_inserter);
+	struct tifm_adapter *fm = data;
 	unsigned long flags;
 	tifm_media_id media_id;
 	char *card_name = "xx";
-	int cnt, ok_to_register;
-	unsigned int insert_mask;
-	struct tifm_dev *new_sock = NULL;
+	int cnt, rc;
+	struct tifm_dev *sock;
+	unsigned int socket_change_set;
 
-	if (!class_device_get(&fm->cdev))
-		return;
-	spin_lock_irqsave(&fm->lock, flags);
-	insert_mask = fm->insert_mask;
-	fm->insert_mask = 0;
-	if (fm->inhibit_new_cards) {
+	while (1) {
+		rc = wait_event_interruptible(fm->change_set_notify,
+					      fm->socket_change_set);
+		if (rc == -ERESTARTSYS)
+			try_to_freeze();
+
+		spin_lock_irqsave(&fm->lock, flags);
+		socket_change_set = fm->socket_change_set;
+		fm->socket_change_set = 0;
+
+		dev_dbg(fm->dev, "checking media set %x\n",
+			socket_change_set);
+
+		if (kthread_should_stop())
+			socket_change_set = (1 << fm->num_sockets) - 1;
 		spin_unlock_irqrestore(&fm->lock, flags);
-		class_device_put(&fm->cdev);
-		return;
-	}
-	spin_unlock_irqrestore(&fm->lock, flags);
 
-	for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-		if (!(insert_mask & (1 << cnt)))
+		if (!socket_change_set)
 			continue;
 
-		media_id = tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt),
-						       fm->max_sockets == 2);
-		if (media_id) {
-			ok_to_register = 0;
-			new_sock = tifm_alloc_device(fm, cnt);
-			if (new_sock) {
-				new_sock->addr = tifm_7xx1_sock_addr(fm->addr,
-									cnt);
-				new_sock->media_id = media_id;
-				switch (media_id) {
-				case 1:
-					card_name = "xd";
-					break;
-				case 2:
-					card_name = "ms";
-					break;
-				case 3:
-					card_name = "sd";
-					break;
-				default:
-					break;
-				}
-				snprintf(new_sock->dev.bus_id, BUS_ID_SIZE,
-					"tifm_%s%u:%u", card_name, fm->id, cnt);
+		spin_lock_irqsave(&fm->lock, flags);
+		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+			if (!(socket_change_set & (1 << cnt)))
+				continue;
+			sock = fm->sockets[cnt];
+			if (sock) {
 				printk(KERN_INFO DRIVER_NAME
-					": %s card detected in socket %d\n",
-					card_name, cnt);
-				spin_lock_irqsave(&fm->lock, flags);
-				if (!fm->sockets[cnt]) {
-					fm->sockets[cnt] = new_sock;
-					ok_to_register = 1;
-				}
+				       ": demand removing card from socket %d\n",
+				       cnt);
+				fm->sockets[cnt] = NULL;
 				spin_unlock_irqrestore(&fm->lock, flags);
-				if (!ok_to_register ||
-					    device_register(&new_sock->dev)) {
-					spin_lock_irqsave(&fm->lock, flags);
-					fm->sockets[cnt] = NULL;
-					spin_unlock_irqrestore(&fm->lock,
-								flags);
-					tifm_free_device(&new_sock->dev);
+				device_unregister(&sock->dev);
+				spin_lock_irqsave(&fm->lock, flags);
+				writel(0x0e00,
+				       tifm_7xx1_sock_addr(fm->addr, cnt)
+				       + SOCK_CONTROL);
+			}
+			if (kthread_should_stop())
+				continue;
+
+			spin_unlock_irqrestore(&fm->lock, flags);
+			media_id = tifm_7xx1_toggle_sock_power(
+					tifm_7xx1_sock_addr(fm->addr, cnt),
+					fm->num_sockets == 2);
+			if (media_id) {
+				sock = tifm_alloc_device(fm);
+				if (sock) {
+					sock->addr = tifm_7xx1_sock_addr(fm->addr,
+									 cnt);
+					sock->media_id = media_id;
+					sock->socket_id = cnt;
+					switch (media_id) {
+					case 1:
+						card_name = "xd";
+						break;
+					case 2:
+						card_name = "ms";
+						break;
+					case 3:
+						card_name = "sd";
+						break;
+					default:
+						tifm_free_device(&sock->dev);
+						spin_lock_irqsave(&fm->lock, flags);
+						continue;
+					}
+					snprintf(sock->dev.bus_id, BUS_ID_SIZE,
+						 "tifm_%s%u:%u", card_name,
+						 fm->id, cnt);
+					printk(KERN_INFO DRIVER_NAME
+					       ": %s card detected in socket %d\n",
+					       card_name, cnt);
+					if (!device_register(&sock->dev)) {
+						spin_lock_irqsave(&fm->lock, flags);
+						if (!fm->sockets[cnt]) {
+							fm->sockets[cnt] = sock;
+							sock = NULL;
+						}
+						spin_unlock_irqrestore(&fm->lock, flags);
+					}
+					if (sock)
+						tifm_free_device(&sock->dev);
 				}
+				spin_lock_irqsave(&fm->lock, flags);
 			}
 		}
-		writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-		       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-		writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-		       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	}
 
-	writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
-	class_device_put(&fm->cdev);
+		if (!kthread_should_stop()) {
+			writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+			       | TIFM_IRQ_CARDMASK(socket_change_set),
+			       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+			writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+			       | TIFM_IRQ_CARDMASK(socket_change_set),
+			       fm->addr + FM_SET_INTERRUPT_ENABLE);
+			writel(TIFM_IRQ_ENABLE,
+			       fm->addr + FM_SET_INTERRUPT_ENABLE);
+			spin_unlock_irqrestore(&fm->lock, flags);
+		} else {
+			for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+				if (fm->sockets[cnt])
+					fm->socket_change_set |= 1 << cnt;
+			}
+			if (!fm->socket_change_set) {
+				spin_unlock_irqrestore(&fm->lock, flags);
+				return 0;
+			} else {
+				spin_unlock_irqrestore(&fm->lock, flags);
+			}
+		}
+	}
+	return 0;
 }
 
+#ifdef CONFIG_PM
+
 static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
 {
-	struct tifm_adapter *fm = pci_get_drvdata(dev);
-	unsigned long flags;
+	dev_dbg(&dev->dev, "suspending host\n");
 
-	spin_lock_irqsave(&fm->lock, flags);
-	fm->inhibit_new_cards = 1;
-	fm->remove_mask = 0xf;
-	fm->insert_mask = 0;
-	writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-	spin_unlock_irqrestore(&fm->lock, flags);
-	flush_workqueue(fm->wq);
-
-	tifm_7xx1_remove_media(&fm->media_remover);
-
-	pci_set_power_state(dev, PCI_D3hot);
-        pci_disable_device(dev);
-        pci_save_state(dev);
+	pci_save_state(dev);
+	pci_enable_wake(dev, pci_choose_state(dev, state), 0);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
 	return 0;
 }
 
 static int tifm_7xx1_resume(struct pci_dev *dev)
 {
 	struct tifm_adapter *fm = pci_get_drvdata(dev);
+	int cnt, rc;
 	unsigned long flags;
+	tifm_media_id new_ids[fm->num_sockets];
 
+	pci_set_power_state(dev, PCI_D0);
 	pci_restore_state(dev);
-        pci_enable_device(dev);
-        pci_set_power_state(dev, PCI_D0);
-        pci_set_master(dev);
+	rc = pci_enable_device(dev);
+	if (rc)
+		return rc;
+	pci_set_master(dev);
+
+	dev_dbg(&dev->dev, "resuming host\n");
+
+	for (cnt = 0; cnt < fm->num_sockets; cnt++)
+		new_ids[cnt] = tifm_7xx1_toggle_sock_power(
+					tifm_7xx1_sock_addr(fm->addr, cnt),
+					fm->num_sockets == 2);
+	spin_lock_irqsave(&fm->lock, flags);
+	fm->socket_change_set = 0;
+	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+		if (fm->sockets[cnt]) {
+			if (fm->sockets[cnt]->media_id == new_ids[cnt])
+				fm->socket_change_set |= 1 << cnt;
+
+			fm->sockets[cnt]->media_id = new_ids[cnt];
+		}
+	}
+
+	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+	if (!fm->socket_change_set) {
+		spin_unlock_irqrestore(&fm->lock, flags);
+		return 0;
+	} else {
+		fm->socket_change_set = 0;
+		spin_unlock_irqrestore(&fm->lock, flags);
+	}
+
+	wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ);
 
 	spin_lock_irqsave(&fm->lock, flags);
-	fm->inhibit_new_cards = 0;
-	writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS);
-	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
-		fm->addr + FM_SET_INTERRUPT_ENABLE);
-	fm->insert_mask = 0xf;
+	writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
+	       | TIFM_IRQ_CARDMASK(fm->socket_change_set),
+	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+	writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
+	       | TIFM_IRQ_CARDMASK(fm->socket_change_set),
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+	writel(TIFM_IRQ_ENABLE,
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+	fm->socket_change_set = 0;
+
 	spin_unlock_irqrestore(&fm->lock, flags);
 	return 0;
 }
 
+#else
+
+#define tifm_7xx1_suspend NULL
+#define tifm_7xx1_resume NULL
+
+#endif /* CONFIG_PM */
+
 static int tifm_7xx1_probe(struct pci_dev *dev,
-			const struct pci_device_id *dev_id)
+			   const struct pci_device_id *dev_id)
 {
 	struct tifm_adapter *fm;
 	int pci_dev_busy = 0;
@@ -324,19 +352,18 @@
 	}
 
 	fm->dev = &dev->dev;
-	fm->max_sockets = (dev->device == 0x803B) ? 2 : 4;
-	fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets,
-				GFP_KERNEL);
+	fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
+			  ? 4 : 2;
+	fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
+			      GFP_KERNEL);
 	if (!fm->sockets)
 		goto err_out_free;
 
-	INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media);
-	INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media);
 	fm->eject = tifm_7xx1_eject;
 	pci_set_drvdata(dev, fm);
 
 	fm->addr = ioremap(pci_resource_start(dev, 0),
-				pci_resource_len(dev, 0));
+			   pci_resource_len(dev, 0));
 	if (!fm->addr)
 		goto err_out_free;
 
@@ -344,16 +371,15 @@
 	if (rc)
 		goto err_out_unmap;
 
-	rc = tifm_add_adapter(fm);
+	init_waitqueue_head(&fm->change_set_notify);
+	rc = tifm_add_adapter(fm, tifm_7xx1_switch_media);
 	if (rc)
 		goto err_out_irq;
 
 	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
-		fm->addr + FM_SET_INTERRUPT_ENABLE);
-
-	fm->insert_mask = 0xf;
-
+	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+	wake_up_process(fm->media_switcher);
 	return 0;
 
 err_out_irq:
@@ -377,19 +403,15 @@
 	struct tifm_adapter *fm = pci_get_drvdata(dev);
 	unsigned long flags;
 
+	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+	mmiowb();
+	free_irq(dev->irq, fm);
+
 	spin_lock_irqsave(&fm->lock, flags);
-	fm->inhibit_new_cards = 1;
-	fm->remove_mask = 0xf;
-	fm->insert_mask = 0;
-	writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+	fm->socket_change_set = (1 << fm->num_sockets) - 1;
 	spin_unlock_irqrestore(&fm->lock, flags);
 
-	flush_workqueue(fm->wq);
-
-	tifm_7xx1_remove_media(&fm->media_remover);
-
-	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-	free_irq(dev->irq, fm);
+	kthread_stop(fm->media_switcher);
 
 	tifm_remove_adapter(fm);
 
@@ -404,10 +426,12 @@
 }
 
 static struct pci_device_id tifm_7xx1_pci_tbl [] = {
-	{ PCI_VENDOR_ID_TI, 0x8033, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-	  0 }, /* xx21 - the one I have */
-        { PCI_VENDOR_ID_TI, 0x803B, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-	  0 }, /* xx12 - should be also supported */
+	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID,
+	  PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */
+        { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID,
+	  PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID,
+	  PCI_ANY_ID, 0, 0, 0 },
 	{ }
 };
 
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index d61df5c..6b10ebe 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -14,7 +14,7 @@
 #include <linux/idr.h>
 
 #define DRIVER_NAME "tifm_core"
-#define DRIVER_VERSION "0.6"
+#define DRIVER_VERSION "0.7"
 
 static DEFINE_IDR(tifm_adapter_idr);
 static DEFINE_SPINLOCK(tifm_adapter_lock);
@@ -60,10 +60,41 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+
+static int tifm_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = fm_dev->drv;
+
+	if (drv && drv->suspend)
+		return drv->suspend(fm_dev, state);
+	return 0;
+}
+
+static int tifm_device_resume(struct device *dev)
+{
+	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = fm_dev->drv;
+
+	if (drv && drv->resume)
+		return drv->resume(fm_dev);
+	return 0;
+}
+
+#else
+
+#define tifm_device_suspend NULL
+#define tifm_device_resume NULL
+
+#endif /* CONFIG_PM */
+
 static struct bus_type tifm_bus_type = {
 	.name    = "tifm",
 	.match   = tifm_match,
 	.uevent  = tifm_uevent,
+	.suspend = tifm_device_suspend,
+	.resume  = tifm_device_resume
 };
 
 static void tifm_free(struct class_device *cdev)
@@ -71,8 +102,6 @@
 	struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
 
 	kfree(fm->sockets);
-	if (fm->wq)
-		destroy_workqueue(fm->wq);
 	kfree(fm);
 }
 
@@ -101,7 +130,8 @@
 }
 EXPORT_SYMBOL(tifm_free_adapter);
 
-int tifm_add_adapter(struct tifm_adapter *fm)
+int tifm_add_adapter(struct tifm_adapter *fm,
+		     int (*mediathreadfn)(void *data))
 {
 	int rc;
 
@@ -113,10 +143,10 @@
 	spin_unlock(&tifm_adapter_lock);
 	if (!rc) {
 		snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
-		strncpy(fm->wq_name, fm->cdev.class_id, KOBJ_NAME_LEN);
+		fm->media_switcher = kthread_create(mediathreadfn,
+						    fm, "tifm/%u", fm->id);
 
-		fm->wq = create_singlethread_workqueue(fm->wq_name);
-		if (fm->wq)
+		if (!IS_ERR(fm->media_switcher))
 			return class_device_add(&fm->cdev);
 
 		spin_lock(&tifm_adapter_lock);
@@ -141,27 +171,27 @@
 void tifm_free_device(struct device *dev)
 {
 	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	if (fm_dev->wq)
-		destroy_workqueue(fm_dev->wq);
 	kfree(fm_dev);
 }
 EXPORT_SYMBOL(tifm_free_device);
 
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id)
+static void tifm_dummy_signal_irq(struct tifm_dev *sock,
+				  unsigned int sock_irq_status)
+{
+	return;
+}
+
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
 {
 	struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
 
 	if (dev) {
 		spin_lock_init(&dev->lock);
-		snprintf(dev->wq_name, KOBJ_NAME_LEN, "tifm%u:%u", fm->id, id);
-		dev->wq = create_singlethread_workqueue(dev->wq_name);
-		if (!dev->wq) {
-			kfree(dev);
-			return NULL;
-		}
+
 		dev->dev.parent = fm->dev;
 		dev->dev.bus = &tifm_bus_type;
 		dev->dev.release = tifm_free_device;
+		dev->signal_irq = tifm_dummy_signal_irq;
 	}
 	return dev;
 }
@@ -219,6 +249,7 @@
 	struct tifm_driver *drv = fm_dev->drv;
 
 	if (drv) {
+		fm_dev->signal_irq = tifm_dummy_signal_irq;
 		if (drv->remove)
 			drv->remove(fm_dev);
 		fm_dev->drv = NULL;
@@ -233,6 +264,8 @@
 	drv->driver.bus = &tifm_bus_type;
 	drv->driver.probe = tifm_device_probe;
 	drv->driver.remove = tifm_device_remove;
+	drv->driver.suspend = tifm_device_suspend;
+	drv->driver.resume = tifm_device_resume;
 
 	return driver_register(&drv->driver);
 }
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 08a33c3..2ce50f3 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -768,7 +768,7 @@
 	return IRQ_HANDLED;
 }
 
-int at91_mci_get_ro(struct mmc_host *mmc)
+static int at91_mci_get_ro(struct mmc_host *mmc)
 {
 	int read_only = 0;
 	struct at91mci_host *host = mmc_priv(mmc);
@@ -794,7 +794,7 @@
 /*
  * Probe for the device
  */
-static int at91_mci_probe(struct platform_device *pdev)
+static int __init at91_mci_probe(struct platform_device *pdev)
 {
 	struct mmc_host *mmc;
 	struct at91mci_host *host;
@@ -823,6 +823,9 @@
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 	mmc->caps = MMC_CAP_BYTEBLOCK;
 
+	mmc->max_blk_size = 4095;
+	mmc->max_blk_count = mmc->max_req_size;
+
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 	host->buffer = NULL;
@@ -910,7 +913,7 @@
 /*
  * Remove a device
  */
-static int at91_mci_remove(struct platform_device *pdev)
+static int __exit at91_mci_remove(struct platform_device *pdev)
 {
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
 	struct at91mci_host *host;
@@ -972,8 +975,7 @@
 #endif
 
 static struct platform_driver at91_mci_driver = {
-	.probe		= at91_mci_probe,
-	.remove		= at91_mci_remove,
+	.remove		= __exit_p(at91_mci_remove),
 	.suspend	= at91_mci_suspend,
 	.resume		= at91_mci_resume,
 	.driver		= {
@@ -984,7 +986,7 @@
 
 static int __init at91_mci_init(void)
 {
-	return platform_driver_register(&at91_mci_driver);
+	return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
 }
 
 static void __exit at91_mci_exit(void)
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 800527c..b834be2 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -152,8 +152,9 @@
 		? 1 : 0;
 }
 
-static inline int au1xmmc_card_readonly(struct au1xmmc_host *host)
+static int au1xmmc_card_readonly(struct mmc_host *mmc)
 {
+	struct au1xmmc_host *host = mmc_priv(mmc);
 	return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
 		? 1 : 0;
 }
@@ -193,6 +194,8 @@
 	u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
 
 	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		break;
 	case MMC_RSP_R1:
 		mmccmd |= SD_CMD_RT_1;
 		break;
@@ -205,6 +208,10 @@
 	case MMC_RSP_R3:
 		mmccmd |= SD_CMD_RT_3;
 		break;
+	default:
+		printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
+			mmc_resp_type(cmd));
+		return MMC_ERR_INVALID;
 	}
 
 	switch(cmd->opcode) {
@@ -878,6 +885,7 @@
 static const struct mmc_host_ops au1xmmc_ops = {
 	.request	= au1xmmc_request,
 	.set_ios	= au1xmmc_set_ios,
+	.get_ro		= au1xmmc_card_readonly,
 };
 
 static int __devinit au1xmmc_probe(struct platform_device *pdev)
@@ -914,6 +922,9 @@
 		mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
 		mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
 
+		mmc->max_blk_size = 2048;
+		mmc->max_blk_count = 512;
+
 		mmc->ocr_avail = AU1XMMC_OCR;
 
 		host = mmc_priv(mmc);
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 06e7fcd..b060d4b 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -351,9 +351,6 @@
 	case MMC_RSP_R3: /* short */
 		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
 		break;
-	case MMC_RSP_R6: /* short CRC */
-		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6;
-		break;
 	default:
 		break;
 	}
@@ -961,8 +958,10 @@
 	/* MMC core transfer sizes tunable parameters */
 	mmc->max_hw_segs = 64;
 	mmc->max_phys_segs = 64;
-	mmc->max_sectors = 64;		/* default 1 << (PAGE_CACHE_SHIFT - 9) */
 	mmc->max_seg_size = 64*512;	/* default PAGE_CACHE_SIZE */
+	mmc->max_req_size = 64*512;	/* default PAGE_CACHE_SIZE */
+	mmc->max_blk_size = 2048;
+	mmc->max_blk_count = 65535;
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 6f2a282..5046a16 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -103,11 +103,16 @@
 		 mmc_hostname(host), mrq->cmd->opcode,
 		 mrq->cmd->arg, mrq->cmd->flags);
 
-	WARN_ON(host->card_busy == NULL);
+	WARN_ON(!host->claimed);
 
 	mrq->cmd->error = 0;
 	mrq->cmd->mrq = mrq;
 	if (mrq->data) {
+		BUG_ON(mrq->data->blksz > host->max_blk_size);
+		BUG_ON(mrq->data->blocks > host->max_blk_count);
+		BUG_ON(mrq->data->blocks * mrq->data->blksz >
+			host->max_req_size);
+
 		mrq->cmd->data = mrq->data;
 		mrq->data->error = 0;
 		mrq->data->mrq = mrq;
@@ -157,7 +162,7 @@
 {
 	struct mmc_request mrq;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 
 	memset(&mrq, 0, sizeof(struct mmc_request));
 
@@ -195,7 +200,7 @@
 
 	int i, err;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 	BUG_ON(retries < 0);
 
 	err = MMC_ERR_INVALID;
@@ -289,7 +294,10 @@
 		else
 			limit_us = 100000;
 
-		if (timeout_us > limit_us) {
+		/*
+		 * SDHC cards always use these fixed values.
+		 */
+		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
 			data->timeout_ns = limit_us * 1000;
 			data->timeout_clks = 0;
 		}
@@ -320,14 +328,14 @@
 	spin_lock_irqsave(&host->lock, flags);
 	while (1) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (host->card_busy == NULL)
+		if (!host->claimed)
 			break;
 		spin_unlock_irqrestore(&host->lock, flags);
 		schedule();
 		spin_lock_irqsave(&host->lock, flags);
 	}
 	set_current_state(TASK_RUNNING);
-	host->card_busy = card;
+	host->claimed = 1;
 	spin_unlock_irqrestore(&host->lock, flags);
 	remove_wait_queue(&host->wq, &wait);
 
@@ -353,10 +361,10 @@
 {
 	unsigned long flags;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 
 	spin_lock_irqsave(&host->lock, flags);
-	host->card_busy = NULL;
+	host->claimed = 0;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	wake_up(&host->wq);
@@ -372,7 +380,7 @@
 		 mmc_hostname(host), ios->clock, ios->bus_mode,
 		 ios->power_mode, ios->chip_select, ios->vdd,
 		 ios->bus_width);
-	
+
 	host->ops->set_ios(host, ios);
 }
 
@@ -381,7 +389,7 @@
 	int err;
 	struct mmc_command cmd;
 
-	BUG_ON(host->card_busy == NULL);
+	BUG_ON(!host->claimed);
 
 	if (host->card_selected == card)
 		return MMC_ERR_NONE;
@@ -588,34 +596,65 @@
 
 	if (mmc_card_sd(card)) {
 		csd_struct = UNSTUFF_BITS(resp, 126, 2);
-		if (csd_struct != 0) {
+
+		switch (csd_struct) {
+		case 0:
+			m = UNSTUFF_BITS(resp, 115, 4);
+			e = UNSTUFF_BITS(resp, 112, 3);
+			csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+			csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+			m = UNSTUFF_BITS(resp, 99, 4);
+			e = UNSTUFF_BITS(resp, 96, 3);
+			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+			e = UNSTUFF_BITS(resp, 47, 3);
+			m = UNSTUFF_BITS(resp, 62, 12);
+			csd->capacity	  = (1 + m) << (e + 2);
+
+			csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+			csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+			csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+			csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+			csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+			csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+			csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+			break;
+		case 1:
+			/*
+			 * This is a block-addressed SDHC card. Most
+			 * interesting fields are unused and have fixed
+			 * values. To avoid getting tripped by buggy cards,
+			 * we assume those fixed values ourselves.
+			 */
+			mmc_card_set_blockaddr(card);
+
+			csd->tacc_ns	 = 0; /* Unused */
+			csd->tacc_clks	 = 0; /* Unused */
+
+			m = UNSTUFF_BITS(resp, 99, 4);
+			e = UNSTUFF_BITS(resp, 96, 3);
+			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+			m = UNSTUFF_BITS(resp, 48, 22);
+			csd->capacity     = (1 + m) << 10;
+
+			csd->read_blkbits = 9;
+			csd->read_partial = 0;
+			csd->write_misalign = 0;
+			csd->read_misalign = 0;
+			csd->r2w_factor = 4; /* Unused */
+			csd->write_blkbits = 9;
+			csd->write_partial = 0;
+			break;
+		default:
 			printk("%s: unrecognised CSD structure version %d\n",
 				mmc_hostname(card->host), csd_struct);
 			mmc_card_set_bad(card);
 			return;
 		}
-
-		m = UNSTUFF_BITS(resp, 115, 4);
-		e = UNSTUFF_BITS(resp, 112, 3);
-		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-		m = UNSTUFF_BITS(resp, 99, 4);
-		e = UNSTUFF_BITS(resp, 96, 3);
-		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-		e = UNSTUFF_BITS(resp, 47, 3);
-		m = UNSTUFF_BITS(resp, 62, 12);
-		csd->capacity	  = (1 + m) << (e + 2);
-
-		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
 	} else {
 		/*
 		 * We only understand CSD structure v1.1 and v1.2.
@@ -848,6 +887,41 @@
 	return err;
 }
 
+static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
+{
+	struct mmc_command cmd;
+	int err, sd2;
+	static const u8 test_pattern = 0xAA;
+
+	/*
+	* To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+	* before SD_APP_OP_COND. This command will harmlessly fail for
+	* SD 1.0 cards.
+	*/
+	cmd.opcode = SD_SEND_IF_COND;
+	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err == MMC_ERR_NONE) {
+		if ((cmd.resp[0] & 0xFF) == test_pattern) {
+			sd2 = 1;
+		} else {
+			sd2 = 0;
+			err = MMC_ERR_FAILED;
+		}
+	} else {
+		/*
+		 * Treat errors as SD 1.0 card.
+		 */
+		sd2 = 0;
+		err = MMC_ERR_NONE;
+	}
+	if (rsd2)
+		*rsd2 = sd2;
+	return err;
+}
+
 /*
  * Discover cards by requesting their CID.  If this command
  * times out, it is not an error; there are no further cards
@@ -1018,7 +1092,8 @@
 		mmc_wait_for_req(host, &mrq);
 
 		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
+			printk("%s: unable to read EXT_CSD, performance "
+				"might suffer.\n", mmc_hostname(card->host));
 			continue;
 		}
 
@@ -1034,7 +1109,6 @@
 			printk("%s: card is mmc v4 but doesn't support "
 			       "any high-speed modes.\n",
 				mmc_hostname(card->host));
-			mmc_card_set_bad(card);
 			continue;
 		}
 
@@ -1215,7 +1289,9 @@
 		mmc_wait_for_req(host, &mrq);
 
 		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
+			printk("%s: unable to read switch capabilities, "
+				"performance might suffer.\n",
+				mmc_hostname(card->host));
 			continue;
 		}
 
@@ -1247,12 +1323,8 @@
 
 		mmc_wait_for_req(host, &mrq);
 
-		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		if ((status[16] & 0xF) != 1) {
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
+			(status[16] & 0xF) != 1) {
 			printk(KERN_WARNING "%s: Problem switching card "
 				"into high-speed mode!\n",
 				mmc_hostname(host));
@@ -1334,6 +1406,10 @@
 		mmc_power_up(host);
 		mmc_idle_cards(host);
 
+		err = mmc_send_if_cond(host, host->ocr_avail, NULL);
+		if (err != MMC_ERR_NONE) {
+			return;
+		}
 		err = mmc_send_app_op_cond(host, 0, &ocr);
 
 		/*
@@ -1386,10 +1462,21 @@
 	 * all get the idea that they should be ready for CMD2.
 	 * (My SanDisk card seems to need this.)
 	 */
-	if (host->mode == MMC_MODE_SD)
-		mmc_send_app_op_cond(host, host->ocr, NULL);
-	else
+	if (host->mode == MMC_MODE_SD) {
+		int err, sd2;
+		err = mmc_send_if_cond(host, host->ocr, &sd2);
+		if (err == MMC_ERR_NONE) {
+			/*
+			* If SD_SEND_IF_COND indicates an SD 2.0
+			* compliant card and we should set bit 30
+			* of the ocr to indicate that we can handle
+			* block-addressed SDHC cards.
+			*/
+			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
+		}
+	} else {
 		mmc_send_op_cond(host, host->ocr, NULL);
+	}
 
 	mmc_discover_cards(host);
 
@@ -1519,8 +1606,11 @@
 		 */
 		host->max_hw_segs = 1;
 		host->max_phys_segs = 1;
-		host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
 		host->max_seg_size = PAGE_CACHE_SIZE;
+
+		host->max_req_size = PAGE_CACHE_SIZE;
+		host->max_blk_size = 512;
+		host->max_blk_count = PAGE_CACHE_SIZE / 512;
 	}
 
 	return host;
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 8771357..05ba8ac 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -237,13 +237,17 @@
 		brq.mrq.cmd = &brq.cmd;
 		brq.mrq.data = &brq.data;
 
-		brq.cmd.arg = req->sector << 9;
+		brq.cmd.arg = req->sector;
+		if (!mmc_card_blockaddr(card))
+			brq.cmd.arg <<= 9;
 		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
 		brq.data.blksz = 1 << md->block_bits;
-		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+		if (brq.data.blocks > card->host->max_blk_count)
+			brq.data.blocks = card->host->max_blk_count;
 
 		mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
 
@@ -375,9 +379,10 @@
 		spin_unlock_irq(&md->lock);
 	}
 
+flush_queue:
+
 	mmc_card_release_host(card);
 
-flush_queue:
 	spin_lock_irq(&md->lock);
 	while (ret) {
 		ret = end_that_request_chunk(req, 0,
@@ -494,6 +499,10 @@
 	struct mmc_command cmd;
 	int err;
 
+	/* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
+	if (mmc_card_blockaddr(card))
+		return 0;
+
 	mmc_card_claim_host(card);
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = 1 << md->block_bits;
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 3e35a43..c27e426 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -147,7 +147,7 @@
 
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
 	blk_queue_bounce_limit(mq->queue, limit);
-	blk_queue_max_sectors(mq->queue, host->max_sectors);
+	blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
 	blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
 	blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
 	blk_queue_max_segment_size(mq->queue, host->max_seg_size);
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index e334acd..d32698b 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -199,7 +199,7 @@
 	memset(card, 0, sizeof(struct mmc_card));
 	card->host = host;
 	device_initialize(&card->dev);
-	card->dev.parent = mmc_dev(host);
+	card->dev.parent = mmc_classdev(host);
 	card->dev.bus = &mmc_bus_type;
 	card->dev.release = mmc_release_card;
 }
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index ccfe656..5941dd9 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -524,15 +524,24 @@
 	/*
 	 * Since we only have a 16-bit data length register, we must
 	 * ensure that we don't exceed 2^16-1 bytes in a single request.
-	 * Choose 64 (512-byte) sectors as the limit.
 	 */
-	mmc->max_sectors = 64;
+	mmc->max_req_size = 65535;
 
 	/*
 	 * Set the maximum segment size.  Since we aren't doing DMA
 	 * (yet) we are only limited by the data length register.
 	 */
-	mmc->max_seg_size = mmc->max_sectors << 9;
+	mmc->max_seg_size = mmc->max_req_size;
+
+	/*
+	 * Block size can be up to 2048 bytes, but must be a power of two.
+	 */
+	mmc->max_blk_size = 2048;
+
+	/*
+	 * No limit on the number of blocks transferred.
+	 */
+	mmc->max_blk_count = mmc->max_req_size;
 
 	spin_lock_init(&host->lock);
 
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index 435d331..1e96a2f 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -91,7 +91,6 @@
 
 
 #define DRIVER_NAME "mmci-omap"
-#define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
 /* Specifies how often in millisecs to poll for card status changes
  * when the cover switch is open */
@@ -204,18 +203,22 @@
 	cmdtype = 0;
 
 	/* Our hardware needs to know exact type */
-	switch (RSP_TYPE(mmc_resp_type(cmd))) {
-	case RSP_TYPE(MMC_RSP_R1):
-		/* resp 1, resp 1b */
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		break;
+	case MMC_RSP_R1:
+	case MMC_RSP_R1B:
+		/* resp 1, 1b, 6, 7 */
 		resptype = 1;
 		break;
-	case RSP_TYPE(MMC_RSP_R2):
+	case MMC_RSP_R2:
 		resptype = 2;
 		break;
-	case RSP_TYPE(MMC_RSP_R3):
+	case MMC_RSP_R3:
 		resptype = 3;
 		break;
 	default:
+		dev_err(mmc_dev(host->mmc), "Invalid response type: %04x\n", mmc_resp_type(cmd));
 		break;
 	}
 
@@ -581,9 +584,9 @@
 	schedule_work(&host->switch_work);
 }
 
-static void mmc_omap_switch_handler(void *data)
+static void mmc_omap_switch_handler(struct work_struct *work)
 {
-	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+	struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work);
 	struct mmc_card *card;
 	static int complained = 0;
 	int cards = 0, cover_open;
@@ -1096,8 +1099,10 @@
 	 */
 	mmc->max_phys_segs = 32;
 	mmc->max_hw_segs = 32;
-	mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */
-	mmc->max_seg_size = mmc->max_sectors * 512;
+	mmc->max_blk_size = 2048;	/* BLEN is 11 bits (+1) */
+	mmc->max_blk_count = 2048;	/* NBLK is 11 bits (+1) */
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_seg_size = mmc->max_req_size;
 
 	if (host->power_pin >= 0) {
 		if ((ret = omap_request_gpio(host->power_pin)) != 0) {
@@ -1116,7 +1121,7 @@
 	platform_set_drvdata(pdev, host);
 
 	if (host->switch_pin >= 0) {
-		INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
+		INIT_WORK(&host->switch_work, mmc_omap_switch_handler);
 		init_timer(&host->switch_timer);
 		host->switch_timer.function = mmc_omap_switch_timer;
 		host->switch_timer.data = (unsigned long) host;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index 45a9283..9774fc6 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -171,7 +171,7 @@
 
 #define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
 	switch (RSP_TYPE(mmc_resp_type(cmd))) {
-	case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */
+	case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */
 		cmdat |= CMDAT_RESP_SHORT;
 		break;
 	case RSP_TYPE(MMC_RSP_R3):
@@ -450,6 +450,16 @@
 	 */
 	mmc->max_seg_size = PAGE_SIZE;
 
+	/*
+	 * Block length register is 10 bits.
+	 */
+	mmc->max_blk_size = 1023;
+
+	/*
+	 * Block count register is 16 bits.
+	 */
+	mmc->max_blk_count = 65535;
+
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 	host->dma = -1;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c2d13d7..4bf1fea 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -37,6 +37,7 @@
 #define SDHCI_QUIRK_FORCE_DMA				(1<<1)
 /* Controller doesn't like some resets when there is no card inserted. */
 #define SDHCI_QUIRK_NO_CARD_NO_RESET			(1<<2)
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE			(1<<3)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
 	{
@@ -65,6 +66,14 @@
 		.driver_data	= SDHCI_QUIRK_FORCE_DMA,
 	},
 
+	{
+		.vendor		= PCI_VENDOR_ID_ENE,
+		.device		= PCI_DEVICE_ID_ENE_CB712_SD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= SDHCI_QUIRK_SINGLE_POWER_WRITE,
+	},
+
 	{	/* Generic SD host controller */
 		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
 	},
@@ -197,15 +206,9 @@
  *                                                                           *
 \*****************************************************************************/
 
-static inline char* sdhci_kmap_sg(struct sdhci_host* host)
+static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
 {
-	host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ);
-	return host->mapped_sg + host->cur_sg->offset;
-}
-
-static inline void sdhci_kunmap_sg(struct sdhci_host* host)
-{
-	kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
+	return page_address(host->cur_sg->page) + host->cur_sg->offset;
 }
 
 static inline int sdhci_next_sg(struct sdhci_host* host)
@@ -240,7 +243,7 @@
 	chunk_remain = 0;
 	data = 0;
 
-	buffer = sdhci_kmap_sg(host) + host->offset;
+	buffer = sdhci_sg_to_buffer(host) + host->offset;
 
 	while (blksize) {
 		if (chunk_remain == 0) {
@@ -264,16 +267,13 @@
 		}
 
 		if (host->remain == 0) {
-			sdhci_kunmap_sg(host);
 			if (sdhci_next_sg(host) == 0) {
 				BUG_ON(blksize != 0);
 				return;
 			}
-			buffer = sdhci_kmap_sg(host);
+			buffer = sdhci_sg_to_buffer(host);
 		}
 	}
-
-	sdhci_kunmap_sg(host);
 }
 
 static void sdhci_write_block_pio(struct sdhci_host *host)
@@ -290,7 +290,7 @@
 	data = 0;
 
 	bytes = 0;
-	buffer = sdhci_kmap_sg(host) + host->offset;
+	buffer = sdhci_sg_to_buffer(host) + host->offset;
 
 	while (blksize) {
 		size = min(host->size, host->remain);
@@ -314,16 +314,13 @@
 		}
 
 		if (host->remain == 0) {
-			sdhci_kunmap_sg(host);
 			if (sdhci_next_sg(host) == 0) {
 				BUG_ON(blksize != 0);
 				return;
 			}
-			buffer = sdhci_kmap_sg(host);
+			buffer = sdhci_sg_to_buffer(host);
 		}
 	}
-
-	sdhci_kunmap_sg(host);
 }
 
 static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -372,7 +369,7 @@
 
 	/* Sanity checks */
 	BUG_ON(data->blksz * data->blocks > 524288);
-	BUG_ON(data->blksz > host->max_block);
+	BUG_ON(data->blksz > host->mmc->max_blk_size);
 	BUG_ON(data->blocks > 65535);
 
 	/* timeout in us */
@@ -674,10 +671,17 @@
 	if (host->power == power)
 		return;
 
-	writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
-
-	if (power == (unsigned short)-1)
+	if (power == (unsigned short)-1) {
+		writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
 		goto out;
+	}
+
+	/*
+	 * Spec says that we should clear the power reg before setting
+	 * a new value. Some controllers don't seem to like this though.
+	 */
+	if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+		writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
 
 	pwr = SDHCI_POWER_ON;
 
@@ -1109,7 +1113,9 @@
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	pci_enable_device(pdev);
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
 
 	for (i = 0;i < chip->num_slots;i++) {
 		if (!chip->hosts[i])
@@ -1274,15 +1280,6 @@
 	if (caps & SDHCI_TIMEOUT_CLK_UNIT)
 		host->timeout_clk *= 1000;
 
-	host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
-	if (host->max_block >= 3) {
-		printk(KERN_ERR "%s: Invalid maximum block size.\n",
-			host->slot_descr);
-		ret = -ENODEV;
-		goto unmap;
-	}
-	host->max_block = 512 << host->max_block;
-
 	/*
 	 * Set host parameters.
 	 */
@@ -1294,9 +1291,9 @@
 	mmc->ocr_avail = 0;
 	if (caps & SDHCI_CAN_VDD_330)
 		mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
-	else if (caps & SDHCI_CAN_VDD_300)
+	if (caps & SDHCI_CAN_VDD_300)
 		mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
-	else if (caps & SDHCI_CAN_VDD_180)
+	if (caps & SDHCI_CAN_VDD_180)
 		mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
 	if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
@@ -1326,15 +1323,33 @@
 
 	/*
 	 * Maximum number of sectors in one transfer. Limited by DMA boundary
-	 * size (512KiB), which means (512 KiB/512=) 1024 entries.
+	 * size (512KiB).
 	 */
-	mmc->max_sectors = 1024;
+	mmc->max_req_size = 524288;
 
 	/*
 	 * Maximum segment size. Could be one segment with the maximum number
-	 * of sectors.
+	 * of bytes.
 	 */
-	mmc->max_seg_size = mmc->max_sectors * 512;
+	mmc->max_seg_size = mmc->max_req_size;
+
+	/*
+	 * Maximum block size. This varies from controller to controller and
+	 * is specified in the capabilities register.
+	 */
+	mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+	if (mmc->max_blk_size >= 3) {
+		printk(KERN_ERR "%s: Invalid maximum block size.\n",
+			host->slot_descr);
+		ret = -ENODEV;
+		goto unmap;
+	}
+	mmc->max_blk_size = 512 << mmc->max_blk_size;
+
+	/*
+	 * Maximum block count.
+	 */
+	mmc->max_blk_count = 65535;
 
 	/*
 	 * Init tasklets.
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
index f9d1a0a..e324f0a 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/sdhci.h
@@ -174,7 +174,6 @@
 
 	unsigned int		max_clk;	/* Max possible freq (MHz) */
 	unsigned int		timeout_clk;	/* Timeout freq (KHz) */
-	unsigned int		max_block;	/* Max block size (bytes) */
 
 	unsigned int		clock;		/* Current clock (MHz) */
 	unsigned short		power;		/* Current voltage */
@@ -184,7 +183,6 @@
 	struct mmc_data		*data;		/* Current data request */
 
 	struct scatterlist	*cur_sg;	/* We're working on this */
-	char			*mapped_sg;	/* This is where it's mapped */
 	int			num_sg;		/* Entries left */
 	int			offset;		/* Offset into current sg */
 	int			remain;		/* Bytes left in current */
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
index f18ad99..e65f8a0 100644
--- a/drivers/mmc/tifm_sd.c
+++ b/drivers/mmc/tifm_sd.c
@@ -17,7 +17,7 @@
 #include <asm/io.h>
 
 #define DRIVER_NAME "tifm_sd"
-#define DRIVER_VERSION "0.6"
+#define DRIVER_VERSION "0.7"
 
 static int no_dma = 0;
 static int fixed_timeout = 0;
@@ -79,7 +79,6 @@
 
 enum {
 	FIFO_RDY   = 0x0001,     /* hardware dependent value */
-	HOST_REG   = 0x0002,
 	EJECT      = 0x0004,
 	EJECT_DONE = 0x0008,
 	CARD_BUSY  = 0x0010,
@@ -95,46 +94,53 @@
 	card_state_t        state;
 	unsigned int        clk_freq;
 	unsigned int        clk_div;
-	unsigned long       timeout_jiffies; // software timeout - 2 sec
+	unsigned long       timeout_jiffies;
 
+	struct tasklet_struct finish_tasklet;
+	struct timer_list     timer;
 	struct mmc_request    *req;
-	struct work_struct    cmd_handler;
-	struct delayed_work   abort_handler;
-	wait_queue_head_t     can_eject;
+	wait_queue_head_t     notify;
 
 	size_t                written_blocks;
-	char                  *buffer;
 	size_t                buffer_size;
 	size_t                buffer_pos;
 
 };
 
+static char* tifm_sd_data_buffer(struct mmc_data *data)
+{
+	return page_address(data->sg->page) + data->sg->offset;
+}
+
 static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
-					unsigned int host_status)
+				 unsigned int host_status)
 {
 	struct mmc_command *cmd = host->req->cmd;
 	unsigned int t_val = 0, cnt = 0;
+	char *buffer;
 
 	if (host_status & TIFM_MMCSD_BRS) {
 		/* in non-dma rx mode BRS fires when fifo is still not empty */
-		if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) {
+		if (no_dma && (cmd->data->flags & MMC_DATA_READ)) {
+			buffer = tifm_sd_data_buffer(host->req->data);
 			while (host->buffer_size > host->buffer_pos) {
 				t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-				host->buffer[host->buffer_pos++] = t_val & 0xff;
-				host->buffer[host->buffer_pos++] =
+				buffer[host->buffer_pos++] = t_val & 0xff;
+				buffer[host->buffer_pos++] =
 							(t_val >> 8) & 0xff;
 			}
 		}
 		return 1;
-	} else if (host->buffer) {
+	} else if (no_dma) {
+		buffer = tifm_sd_data_buffer(host->req->data);
 		if ((cmd->data->flags & MMC_DATA_READ) &&
 				(host_status & TIFM_MMCSD_AF)) {
 			for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
 				t_val = readl(sock->addr + SOCK_MMCSD_DATA);
 				if (host->buffer_size > host->buffer_pos) {
-					host->buffer[host->buffer_pos++] =
+					buffer[host->buffer_pos++] =
 							t_val & 0xff;
-					host->buffer[host->buffer_pos++] =
+					buffer[host->buffer_pos++] =
 							(t_val >> 8) & 0xff;
 				}
 			}
@@ -142,11 +148,12 @@
 			   && (host_status & TIFM_MMCSD_AE)) {
 			for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
 				if (host->buffer_size > host->buffer_pos) {
-					t_val = host->buffer[host->buffer_pos++] & 0x00ff;
-					t_val |= ((host->buffer[host->buffer_pos++]) << 8)
-						 & 0xff00;
+					t_val = buffer[host->buffer_pos++]
+						& 0x00ff;
+					t_val |= ((buffer[host->buffer_pos++])
+						  << 8) & 0xff00;
 					writel(t_val,
-						sock->addr + SOCK_MMCSD_DATA);
+					       sock->addr + SOCK_MMCSD_DATA);
 				}
 			}
 		}
@@ -173,9 +180,6 @@
 	case MMC_RSP_R3:
 		rc |= TIFM_MMCSD_RSP_R3;
 		break;
-	case MMC_RSP_R6:
-		rc |= TIFM_MMCSD_RSP_R6;
-		break;
 	default:
 		BUG();
 	}
@@ -209,7 +213,7 @@
 		cmd_mask |= TIFM_MMCSD_READ;
 
 	dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
-				cmd->opcode, cmd->arg, cmd_mask);
+		cmd->opcode, cmd->arg, cmd_mask);
 
 	writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
 	writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
@@ -242,65 +246,78 @@
 			tifm_sd_fetch_resp(cmd, sock);
 			if (cmd->data) {
 				host->state = BRS;
-			} else
+			} else {
 				host->state = READY;
+			}
 			goto change_state;
 		}
 		break;
 	case BRS:
 		if (tifm_sd_transfer_data(sock, host, host_status)) {
-			if (!host->req->stop) {
-				if (cmd->data->flags & MMC_DATA_WRITE) {
-					host->state = CARD;
+			if (cmd->data->flags & MMC_DATA_WRITE) {
+				host->state = CARD;
+			} else {
+				if (no_dma) {
+					if (host->req->stop) {
+						tifm_sd_exec(host, host->req->stop);
+						host->state = SCMD;
+					} else {
+						host->state = READY;
+					}
 				} else {
-					host->state =
-						host->buffer ? READY : FIFO;
+					host->state = FIFO;
 				}
-				goto change_state;
 			}
-			tifm_sd_exec(host, host->req->stop);
-			host->state = SCMD;
+			goto change_state;
 		}
 		break;
 	case SCMD:
 		if (host_status & TIFM_MMCSD_EOC) {
 			tifm_sd_fetch_resp(host->req->stop, sock);
-			if (cmd->error) {
-				host->state = READY;
-			} else if (cmd->data->flags & MMC_DATA_WRITE) {
-				host->state = CARD;
-			} else {
-				host->state = host->buffer ? READY : FIFO;
-			}
+			host->state = READY;
 			goto change_state;
 		}
 		break;
 	case CARD:
+		dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n",
+			host->written_blocks);
 		if (!(host->flags & CARD_BUSY)
 		    && (host->written_blocks == cmd->data->blocks)) {
-			host->state = host->buffer ? READY : FIFO;
+			if (no_dma) {
+				if (host->req->stop) {
+					tifm_sd_exec(host, host->req->stop);
+					host->state = SCMD;
+				} else {
+					host->state = READY;
+				}
+			} else {
+				host->state = FIFO;
+			}
 			goto change_state;
 		}
 		break;
 	case FIFO:
 		if (host->flags & FIFO_RDY) {
-			host->state = READY;
 			host->flags &= ~FIFO_RDY;
+			if (host->req->stop) {
+				tifm_sd_exec(host, host->req->stop);
+				host->state = SCMD;
+			} else {
+				host->state = READY;
+			}
 			goto change_state;
 		}
 		break;
 	case READY:
-		queue_work(sock->wq, &host->cmd_handler);
+		tasklet_schedule(&host->finish_tasklet);
 		return;
 	}
 
-	queue_delayed_work(sock->wq, &host->abort_handler,
-				host->timeout_jiffies);
 }
 
 /* Called from interrupt handler */
-static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
-					unsigned int sock_irq_status)
+static void tifm_sd_signal_irq(struct tifm_dev *sock,
+			       unsigned int sock_irq_status)
 {
 	struct tifm_sd *host;
 	unsigned int host_status = 0, fifo_status = 0;
@@ -308,7 +325,6 @@
 
 	spin_lock(&sock->lock);
 	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
-	cancel_delayed_work(&host->abort_handler);
 
 	if (sock_irq_status & FIFO_EVENT) {
 		fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
@@ -321,19 +337,17 @@
 		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
 		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
 
-		if (!(host->flags & HOST_REG))
-			queue_work(sock->wq, &host->cmd_handler);
 		if (!host->req)
 			goto done;
 
 		if (host_status & TIFM_MMCSD_ERRMASK) {
 			if (host_status & TIFM_MMCSD_CERR)
 				error_code = MMC_ERR_FAILED;
-			else if (host_status &
-					(TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
+			else if (host_status
+				 & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
 				error_code = MMC_ERR_TIMEOUT;
-			else if (host_status &
-					(TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
+			else if (host_status
+				 & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
 				error_code = MMC_ERR_BADCRC;
 
 			writel(TIFM_FIFO_INT_SETALL,
@@ -343,12 +357,11 @@
 			if (host->req->stop) {
 				if (host->state == SCMD) {
 					host->req->stop->error = error_code;
-				} else if(host->state == BRS) {
+				} else if (host->state == BRS
+					   || host->state == CARD
+					   || host->state == FIFO) {
 					host->req->cmd->error = error_code;
 					tifm_sd_exec(host, host->req->stop);
-					queue_delayed_work(sock->wq,
-						&host->abort_handler,
-						host->timeout_jiffies);
 					host->state = SCMD;
 					goto done;
 				} else {
@@ -362,8 +375,8 @@
 
 		if (host_status & TIFM_MMCSD_CB)
 			host->flags |= CARD_BUSY;
-		if ((host_status & TIFM_MMCSD_EOFB) &&
-				(host->flags & CARD_BUSY)) {
+		if ((host_status & TIFM_MMCSD_EOFB)
+		    && (host->flags & CARD_BUSY)) {
 			host->written_blocks++;
 			host->flags &= ~CARD_BUSY;
 		}
@@ -373,22 +386,22 @@
 		tifm_sd_process_cmd(sock, host, host_status);
 done:
 	dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n",
-			host_status, fifo_status);
+		host_status, fifo_status);
 	spin_unlock(&sock->lock);
-	return sock_irq_status;
 }
 
-static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd)
+static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd)
 {
-	struct tifm_dev *sock = card->dev;
+	struct tifm_dev *sock = host->dev;
 	unsigned int dest_cnt;
 
 	/* DMA style IO */
-
+	dev_dbg(&sock->dev, "setting dma for %d blocks\n",
+		cmd->data->blocks);
 	writel(TIFM_FIFO_INT_SETALL,
-		sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+	       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
 	writel(ilog2(cmd->data->blksz) - 2,
-			sock->addr + SOCK_FIFO_PAGE_SIZE);
+	       sock->addr + SOCK_FIFO_PAGE_SIZE);
 	writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
 	writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
 
@@ -402,7 +415,7 @@
 	if (cmd->data->flags & MMC_DATA_WRITE) {
 		writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
 		writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN,
-			sock->addr + SOCK_DMA_CONTROL);
+		       sock->addr + SOCK_DMA_CONTROL);
 	} else {
 		writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
 		writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL);
@@ -410,7 +423,7 @@
 }
 
 static void tifm_sd_set_data_timeout(struct tifm_sd *host,
-					struct mmc_data *data)
+				     struct mmc_data *data)
 {
 	struct tifm_dev *sock = host->dev;
 	unsigned int data_timeout = data->timeout_clks;
@@ -419,22 +432,21 @@
 		return;
 
 	data_timeout += data->timeout_ns /
-			((1000000000 / host->clk_freq) * host->clk_div);
-	data_timeout *= 10; // call it fudge factor for now
+			((1000000000UL / host->clk_freq) * host->clk_div);
 
 	if (data_timeout < 0xffff) {
-		writel((~TIFM_MMCSD_DPE) &
-				readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
 		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+		writel((~TIFM_MMCSD_DPE)
+		       & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
 	} else {
-		writel(TIFM_MMCSD_DPE |
-				readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-			sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
 		data_timeout = (data_timeout >> 10) + 1;
-		if(data_timeout > 0xffff)
+		if (data_timeout > 0xffff)
 			data_timeout = 0;	/* set to unlimited */
 		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+		writel(TIFM_MMCSD_DPE
+		       | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
 	}
 }
 
@@ -477,11 +489,10 @@
 	}
 
 	host->req = mrq;
+	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
 	host->state = CMD;
-	queue_delayed_work(sock->wq, &host->abort_handler,
-				host->timeout_jiffies);
 	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-		sock->addr + SOCK_CONTROL);
+	       sock->addr + SOCK_CONTROL);
 	tifm_sd_exec(host, mrq->cmd);
 	spin_unlock_irqrestore(&sock->lock, flags);
 	return;
@@ -496,9 +507,9 @@
 	mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd(struct work_struct *work)
+static void tifm_sd_end_cmd(unsigned long data)
 {
-	struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
+	struct tifm_sd *host = (struct tifm_sd*)data;
 	struct tifm_dev *sock = host->dev;
 	struct mmc_host *mmc = tifm_get_drvdata(sock);
 	struct mmc_request *mrq;
@@ -507,6 +518,7 @@
 
 	spin_lock_irqsave(&sock->lock, flags);
 
+	del_timer(&host->timer);
 	mrq = host->req;
 	host->req = NULL;
 	host->state = IDLE;
@@ -520,8 +532,8 @@
 	r_data = mrq->cmd->data;
 	if (r_data) {
 		if (r_data->flags & MMC_DATA_WRITE) {
-			r_data->bytes_xfered = host->written_blocks *
-						r_data->blksz;
+			r_data->bytes_xfered = host->written_blocks
+					       * r_data->blksz;
 		} else {
 			r_data->bytes_xfered = r_data->blocks -
 				readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
@@ -535,7 +547,7 @@
 	}
 
 	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-			sock->addr + SOCK_CONTROL);
+	       sock->addr + SOCK_CONTROL);
 
 	spin_unlock_irqrestore(&sock->lock, flags);
 	mmc_request_done(mmc, mrq);
@@ -547,15 +559,6 @@
 	struct tifm_dev *sock = host->dev;
 	unsigned long flags;
 	struct mmc_data *r_data = mrq->cmd->data;
-	char *t_buffer = NULL;
-
-	if (r_data) {
-		t_buffer = kmap(r_data->sg->page);
-		if (!t_buffer) {
-			printk(KERN_ERR DRIVER_NAME ": kmap failed\n");
-			goto err_out;
-		}
-	}
 
 	spin_lock_irqsave(&sock->lock, flags);
 	if (host->flags & EJECT) {
@@ -572,15 +575,14 @@
 	if (r_data) {
 		tifm_sd_set_data_timeout(host, r_data);
 
-		host->buffer = t_buffer + r_data->sg->offset;
-		host->buffer_size = mrq->cmd->data->blocks *
-					mrq->cmd->data->blksz;
+		host->buffer_size = mrq->cmd->data->blocks
+				    * mrq->cmd->data->blksz;
 
-		writel(TIFM_MMCSD_BUFINT |
-				readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+		writel(TIFM_MMCSD_BUFINT
+		       | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
 		       sock->addr + SOCK_MMCSD_INT_ENABLE);
-		writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
-				(TIFM_MMCSD_FIFO_SIZE - 1),
+		writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
+		       | (TIFM_MMCSD_FIFO_SIZE - 1),
 		       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
 
 		host->written_blocks = 0;
@@ -591,26 +593,22 @@
 	}
 
 	host->req = mrq;
+	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
 	host->state = CMD;
-	queue_delayed_work(sock->wq, &host->abort_handler,
-				host->timeout_jiffies);
 	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-		sock->addr + SOCK_CONTROL);
+	       sock->addr + SOCK_CONTROL);
 	tifm_sd_exec(host, mrq->cmd);
 	spin_unlock_irqrestore(&sock->lock, flags);
 	return;
 
 err_out:
-	if (t_buffer)
-		kunmap(r_data->sg->page);
-
 	mrq->cmd->error = MMC_ERR_TIMEOUT;
 	mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd_nodma(struct work_struct *work)
+static void tifm_sd_end_cmd_nodma(unsigned long data)
 {
-	struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
+	struct tifm_sd *host = (struct tifm_sd*)data;
 	struct tifm_dev *sock = host->dev;
 	struct mmc_host *mmc = tifm_get_drvdata(sock);
 	struct mmc_request *mrq;
@@ -619,6 +617,7 @@
 
 	spin_lock_irqsave(&sock->lock, flags);
 
+	del_timer(&host->timer);
 	mrq = host->req;
 	host->req = NULL;
 	host->state = IDLE;
@@ -636,8 +635,8 @@
 			sock->addr + SOCK_MMCSD_INT_ENABLE);
 
 		if (r_data->flags & MMC_DATA_WRITE) {
-			r_data->bytes_xfered = host->written_blocks *
-						r_data->blksz;
+			r_data->bytes_xfered = host->written_blocks
+					       * r_data->blksz;
 		} else {
 			r_data->bytes_xfered = r_data->blocks -
 				readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
@@ -645,29 +644,44 @@
 			r_data->bytes_xfered += r_data->blksz -
 				readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
 		}
-		host->buffer = NULL;
 		host->buffer_pos = 0;
 		host->buffer_size = 0;
 	}
 
 	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-			sock->addr + SOCK_CONTROL);
+	       sock->addr + SOCK_CONTROL);
 
 	spin_unlock_irqrestore(&sock->lock, flags);
 
-        if (r_data)
-		kunmap(r_data->sg->page);
-
 	mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_abort(struct work_struct *work)
+static void tifm_sd_terminate(struct tifm_sd *host)
 {
-	struct tifm_sd *host =
-		container_of(work, struct tifm_sd, abort_handler.work);
+	struct tifm_dev *sock = host->dev;
+	unsigned long flags;
+
+	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+	spin_lock_irqsave(&sock->lock, flags);
+	host->flags |= EJECT;
+	if (host->req) {
+		writel(TIFM_FIFO_INT_SETALL,
+		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+		writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+		tasklet_schedule(&host->finish_tasklet);
+	}
+	spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static void tifm_sd_abort(unsigned long data)
+{
+	struct tifm_sd *host = (struct tifm_sd*)data;
 
 	printk(KERN_ERR DRIVER_NAME
-		": card failed to respond for a long period of time");
+	       ": card failed to respond for a long period of time");
+
+	tifm_sd_terminate(host);
 	tifm_eject(host->dev);
 }
 
@@ -686,9 +700,9 @@
 		writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
 		       sock->addr + SOCK_MMCSD_CONFIG);
 	} else {
-		writel((~TIFM_MMCSD_4BBUS) &
-				readl(sock->addr + SOCK_MMCSD_CONFIG),
-			sock->addr + SOCK_MMCSD_CONFIG);
+		writel((~TIFM_MMCSD_4BBUS)
+		       & readl(sock->addr + SOCK_MMCSD_CONFIG),
+		       sock->addr + SOCK_MMCSD_CONFIG);
 	}
 
 	if (ios->clock) {
@@ -707,23 +721,24 @@
 		if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
 			host->clk_freq = 20000000;
 			host->clk_div = clk_div1;
-			writel((~TIFM_CTRL_FAST_CLK) &
-					readl(sock->addr + SOCK_CONTROL),
-				sock->addr + SOCK_CONTROL);
+			writel((~TIFM_CTRL_FAST_CLK)
+			       & readl(sock->addr + SOCK_CONTROL),
+			       sock->addr + SOCK_CONTROL);
 		} else {
 			host->clk_freq = 24000000;
 			host->clk_div = clk_div2;
-			writel(TIFM_CTRL_FAST_CLK |
-					readl(sock->addr + SOCK_CONTROL),
-				sock->addr + SOCK_CONTROL);
+			writel(TIFM_CTRL_FAST_CLK
+			       | readl(sock->addr + SOCK_CONTROL),
+			       sock->addr + SOCK_CONTROL);
 		}
 	} else {
 		host->clk_div = 0;
 	}
 	host->clk_div &= TIFM_MMCSD_CLKMASK;
-	writel(host->clk_div | ((~TIFM_MMCSD_CLKMASK) &
-			readl(sock->addr + SOCK_MMCSD_CONFIG)),
-		sock->addr + SOCK_MMCSD_CONFIG);
+	writel(host->clk_div
+	       | ((~TIFM_MMCSD_CLKMASK)
+		  & readl(sock->addr + SOCK_MMCSD_CONFIG)),
+	       sock->addr + SOCK_MMCSD_CONFIG);
 
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
 		host->flags |= OPENDRAIN;
@@ -737,7 +752,7 @@
 	// allow removal.
 	if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
 		host->flags |= EJECT_DONE;
-		wake_up_all(&host->can_eject);
+		wake_up_all(&host->notify);
 	}
 
 	spin_unlock_irqrestore(&sock->lock, flags);
@@ -765,20 +780,67 @@
 	.get_ro  = tifm_sd_ro
 };
 
-static void tifm_sd_register_host(struct work_struct *work)
+static int tifm_sd_initialize_host(struct tifm_sd *host)
 {
-	struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
+	int rc;
+	unsigned int host_status = 0;
 	struct tifm_dev *sock = host->dev;
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	unsigned long flags;
 
-	spin_lock_irqsave(&sock->lock, flags);
-	host->flags |= HOST_REG;
-	PREPARE_WORK(&host->cmd_handler,
-			no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd);
-	spin_unlock_irqrestore(&sock->lock, flags);
-	dev_dbg(&sock->dev, "adding host\n");
-	mmc_add_host(mmc);
+	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+	host->clk_div = 61;
+	host->clk_freq = 20000000;
+	writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
+	writel(host->clk_div | TIFM_MMCSD_POWER,
+	       sock->addr + SOCK_MMCSD_CONFIG);
+
+	/* wait up to 0.51 sec for reset */
+	for (rc = 2; rc <= 256; rc <<= 1) {
+		if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
+			rc = 0;
+			break;
+		}
+		msleep(rc);
+	}
+
+	if (rc) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": controller failed to reset\n");
+		return -ENODEV;
+	}
+
+	writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+	writel(host->clk_div | TIFM_MMCSD_POWER,
+	       sock->addr + SOCK_MMCSD_CONFIG);
+	writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+	// command timeout fixed to 64 clocks for now
+	writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
+	writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
+
+	/* INAB should take much less than reset */
+	for (rc = 1; rc <= 16; rc <<= 1) {
+		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+		if (!(host_status & TIFM_MMCSD_ERRMASK)
+		    && (host_status & TIFM_MMCSD_EOC)) {
+			rc = 0;
+			break;
+		}
+		msleep(rc);
+	}
+
+	if (rc) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": card not ready - probe failed on initialization\n");
+		return -ENODEV;
+	}
+
+	writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
+	       sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+
+	return 0;
 }
 
 static int tifm_sd_probe(struct tifm_dev *sock)
@@ -787,8 +849,8 @@
 	struct tifm_sd *host;
 	int rc = -EIO;
 
-	if (!(TIFM_SOCK_STATE_OCCUPIED &
-			readl(sock->addr + SOCK_PRESENT_STATE))) {
+	if (!(TIFM_SOCK_STATE_OCCUPIED
+	      & readl(sock->addr + SOCK_PRESENT_STATE))) {
 		printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n");
 		return rc;
 	}
@@ -798,78 +860,42 @@
 		return -ENOMEM;
 
 	host = mmc_priv(mmc);
-	host->dev = sock;
-	host->clk_div = 61;
-	init_waitqueue_head(&host->can_eject);
-	INIT_WORK(&host->cmd_handler, tifm_sd_register_host);
-	INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort);
-
 	tifm_set_drvdata(sock, mmc);
-	sock->signal_irq = tifm_sd_signal_irq;
-
-	host->clk_freq = 20000000;
+	host->dev = sock;
 	host->timeout_jiffies = msecs_to_jiffies(1000);
 
+	init_waitqueue_head(&host->notify);
+	tasklet_init(&host->finish_tasklet,
+		     no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
+		     (unsigned long)host);
+	setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
+
 	tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request;
 	mmc->ops = &tifm_sd_ops;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
 	mmc->f_min = 20000000 / 60;
 	mmc->f_max = 24000000;
 	mmc->max_hw_segs = 1;
 	mmc->max_phys_segs = 1;
-	mmc->max_sectors = 127;
-	mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length
+	// limited by DMA counter - it's safer to stick with
+	// block counter has 11 bits though
+	mmc->max_blk_count = 256;
+	// 2k maximum hw block length
+	mmc->max_blk_size = 2048;
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_seg_size = mmc->max_req_size;
+	sock->signal_irq = tifm_sd_signal_irq;
+	rc = tifm_sd_initialize_host(host);
 
-	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-	writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-			sock->addr + SOCK_MMCSD_CONFIG);
-
-	for (rc = 0; rc < 50; rc++) {
-		/* Wait for reset ack */
-		if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
-			rc = 0;
-			break;
-		}
-		msleep(10);
-        }
-
-	if (rc) {
-		printk(KERN_ERR DRIVER_NAME
-			": card not ready - probe failed\n");
-		mmc_free_host(mmc);
-		return -ENODEV;
-	}
-
-	writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-			sock->addr + SOCK_MMCSD_CONFIG);
-	writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-	writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
-			sock->addr + SOCK_MMCSD_INT_ENABLE);
-
-	writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); // command timeout 64 clocks for now
-	writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-			sock->addr + SOCK_MMCSD_CONFIG);
-
-	queue_delayed_work(sock->wq, &host->abort_handler,
-			host->timeout_jiffies);
+	if (!rc)
+		rc = mmc_add_host(mmc);
+	if (rc)
+		goto out_free_mmc;
 
 	return 0;
-}
-
-static int tifm_sd_host_is_down(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct tifm_sd *host = mmc_priv(mmc);
-	unsigned long flags;
-	int rc = 0;
-
-	spin_lock_irqsave(&sock->lock, flags);
-	rc = (host->flags & EJECT_DONE);
-	spin_unlock_irqrestore(&sock->lock, flags);
+out_free_mmc:
+	mmc_free_host(mmc);
 	return rc;
 }
 
@@ -877,31 +903,57 @@
 {
 	struct mmc_host *mmc = tifm_get_drvdata(sock);
 	struct tifm_sd *host = mmc_priv(mmc);
-	unsigned long flags;
 
-	spin_lock_irqsave(&sock->lock, flags);
-	host->flags |= EJECT;
-	if (host->req)
-		queue_work(sock->wq, &host->cmd_handler);
-	spin_unlock_irqrestore(&sock->lock, flags);
-	wait_event_timeout(host->can_eject, tifm_sd_host_is_down(sock),
-				host->timeout_jiffies);
-
-	if (host->flags & HOST_REG)
-		mmc_remove_host(mmc);
+	del_timer_sync(&host->timer);
+	tifm_sd_terminate(host);
+	wait_event_timeout(host->notify, host->flags & EJECT_DONE,
+			   host->timeout_jiffies);
+	tasklet_kill(&host->finish_tasklet);
+	mmc_remove_host(mmc);
 
 	/* The meaning of the bit majority in this constant is unknown. */
 	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-		sock->addr + SOCK_CONTROL);
-	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-	writel(TIFM_FIFO_INT_SETALL,
-		sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-	writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+	       sock->addr + SOCK_CONTROL);
 
 	tifm_set_drvdata(sock, NULL);
 	mmc_free_host(mmc);
 }
 
+#ifdef CONFIG_PM
+
+static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	int rc;
+
+	rc = mmc_suspend_host(mmc, state);
+	/* The meaning of the bit majority in this constant is unknown. */
+	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+	return rc;
+}
+
+static int tifm_sd_resume(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct tifm_sd *host = mmc_priv(mmc);
+
+	if (sock->media_id != FM_SD
+	    || tifm_sd_initialize_host(host)) {
+		tifm_eject(sock);
+		return 0;
+	} else {
+		return mmc_resume_host(mmc);
+	}
+}
+
+#else
+
+#define tifm_sd_suspend NULL
+#define tifm_sd_resume NULL
+
+#endif /* CONFIG_PM */
+
 static tifm_media_id tifm_sd_id_tbl[] = {
 	FM_SD, 0
 };
@@ -913,7 +965,9 @@
 	},
 	.id_table = tifm_sd_id_tbl,
 	.probe    = tifm_sd_probe,
-	.remove   = tifm_sd_remove
+	.remove   = tifm_sd_remove,
+	.suspend  = tifm_sd_suspend,
+	.resume   = tifm_sd_resume
 };
 
 static int __init tifm_sd_init(void)
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 7a28267..a44d877 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2006 Pierre Ossman, 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
@@ -272,16 +272,9 @@
 	return host->num_sg;
 }
 
-static inline char *wbsd_kmap_sg(struct wbsd_host *host)
+static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
 {
-	host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) +
-		host->cur_sg->offset;
-	return host->mapped_sg;
-}
-
-static inline void wbsd_kunmap_sg(struct wbsd_host *host)
-{
-	kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
+	return page_address(host->cur_sg->page) + host->cur_sg->offset;
 }
 
 static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
@@ -302,12 +295,11 @@
 	 * we do not transfer too much.
 	 */
 	for (i = 0; i < len; i++) {
-		sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
+		sgbuf = page_address(sg[i].page) + sg[i].offset;
 		if (size < sg[i].length)
 			memcpy(dmabuf, sgbuf, size);
 		else
 			memcpy(dmabuf, sgbuf, sg[i].length);
-		kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
 		dmabuf += sg[i].length;
 
 		if (size < sg[i].length)
@@ -347,7 +339,7 @@
 	 * we do not transfer too much.
 	 */
 	for (i = 0; i < len; i++) {
-		sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
+		sgbuf = page_address(sg[i].page) + sg[i].offset;
 		if (size < sg[i].length)
 			memcpy(sgbuf, dmabuf, size);
 		else
@@ -497,7 +489,7 @@
 	if (data->bytes_xfered == host->size)
 		return;
 
-	buffer = wbsd_kmap_sg(host) + host->offset;
+	buffer = wbsd_sg_to_buffer(host) + host->offset;
 
 	/*
 	 * Drain the fifo. This has a tendency to loop longer
@@ -526,17 +518,13 @@
 			/*
 			 * Transfer done?
 			 */
-			if (data->bytes_xfered == host->size) {
-				wbsd_kunmap_sg(host);
+			if (data->bytes_xfered == host->size)
 				return;
-			}
 
 			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0) {
-				wbsd_kunmap_sg(host);
-
 				/*
 				 * Get next entry. Check if last.
 				 */
@@ -554,13 +542,11 @@
 					return;
 				}
 
-				buffer = wbsd_kmap_sg(host);
+				buffer = wbsd_sg_to_buffer(host);
 			}
 		}
 	}
 
-	wbsd_kunmap_sg(host);
-
 	/*
 	 * This is a very dirty hack to solve a
 	 * hardware problem. The chip doesn't trigger
@@ -583,7 +569,7 @@
 	if (data->bytes_xfered == host->size)
 		return;
 
-	buffer = wbsd_kmap_sg(host) + host->offset;
+	buffer = wbsd_sg_to_buffer(host) + host->offset;
 
 	/*
 	 * Fill the fifo. This has a tendency to loop longer
@@ -612,17 +598,13 @@
 			/*
 			 * Transfer done?
 			 */
-			if (data->bytes_xfered == host->size) {
-				wbsd_kunmap_sg(host);
+			if (data->bytes_xfered == host->size)
 				return;
-			}
 
 			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0) {
-				wbsd_kunmap_sg(host);
-
 				/*
 				 * Get next entry. Check if last.
 				 */
@@ -640,13 +622,11 @@
 					return;
 				}
 
-				buffer = wbsd_kmap_sg(host);
+				buffer = wbsd_sg_to_buffer(host);
 			}
 		}
 	}
 
-	wbsd_kunmap_sg(host);
-
 	/*
 	 * The controller stops sending interrupts for
 	 * 'FIFO empty' under certain conditions. So we
@@ -910,6 +890,45 @@
 	 */
 	if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
 		/*
+		 * The hardware is so delightfully stupid that it has a list
+		 * of "data" commands. If a command isn't on this list, it'll
+		 * just go back to the idle state and won't send any data
+		 * interrupts.
+		 */
+		switch (cmd->opcode) {
+		case 11:
+		case 17:
+		case 18:
+		case 20:
+		case 24:
+		case 25:
+		case 26:
+		case 27:
+		case 30:
+		case 42:
+		case 56:
+			break;
+
+		/* ACMDs. We don't keep track of state, so we just treat them
+		 * like any other command. */
+		case 51:
+			break;
+
+		default:
+#ifdef CONFIG_MMC_DEBUG
+			printk(KERN_WARNING "%s: Data command %d is not "
+				"supported by this controller.\n",
+				mmc_hostname(host->mmc), cmd->opcode);
+#endif
+			cmd->data->error = MMC_ERR_INVALID;
+
+			if (cmd->data->stop)
+				wbsd_send_command(host, cmd->data->stop);
+
+			goto done;
+		};
+
+		/*
 		 * Dirty fix for hardware bug.
 		 */
 		if (host->dma == -1)
@@ -1343,16 +1362,27 @@
 	mmc->max_phys_segs = 128;
 
 	/*
-	 * Maximum number of sectors in one transfer. Also limited by 64kB
-	 * buffer.
+	 * Maximum request size. Also limited by 64KiB buffer.
 	 */
-	mmc->max_sectors = 128;
+	mmc->max_req_size = 65536;
 
 	/*
 	 * Maximum segment size. Could be one segment with the maximum number
-	 * of segments.
+	 * of bytes.
 	 */
-	mmc->max_seg_size = mmc->max_sectors * 512;
+	mmc->max_seg_size = mmc->max_req_size;
+
+	/*
+	 * Maximum block size. We have 12 bits (= 4095) but have to subtract
+	 * space for CRC. So the maximum is 4095 - 4*2 = 4087.
+	 */
+	mmc->max_blk_size = 4087;
+
+	/*
+	 * Maximum block count. There is no real limit so the maximum
+	 * request size will be the only restriction.
+	 */
+	mmc->max_blk_count = mmc->max_req_size;
 
 	dev_set_drvdata(dev, mmc);
 
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index 6072993..d06718b 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -154,7 +154,6 @@
 
 	struct scatterlist*	cur_sg;		/* Current SG entry */
 	unsigned int		num_sg;		/* Number of entries left */
-	void*			mapped_sg;	/* vaddr of mapped sg */
 
 	unsigned int		offset;		/* Offset into current entry */
 	unsigned int		remain;		/* Data left in curren entry */
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index a304b34..26f75c2 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -164,9 +164,15 @@
 	  memory chips, and also use ioctl() to obtain information about
 	  the device, or to erase parts of it.
 
+config MTD_BLKDEVS
+	tristate "Common interface to block layer for MTD 'translation layers'"
+	depends on MTD && BLOCK
+	default n
+
 config MTD_BLOCK
 	tristate "Caching block device access to MTD devices"
 	depends on MTD && BLOCK
+	select MTD_BLKDEVS
 	---help---
 	  Although most flash chips have an erase size too large to be useful
 	  as block devices, it is possible to use MTD devices which are based
@@ -189,6 +195,7 @@
 config MTD_BLOCK_RO
 	tristate "Readonly block device access to MTD devices"
 	depends on MTD_BLOCK!=y && MTD && BLOCK
+	select MTD_BLKDEVS
 	help
 	  This allows you to mount read-only file systems (such as cramfs)
 	  from an MTD device, without the overhead (and danger) of the caching
@@ -200,6 +207,7 @@
 config FTL
 	tristate "FTL (Flash Translation Layer) support"
 	depends on MTD && BLOCK
+	select MTD_BLKDEVS
 	---help---
 	  This provides support for the original Flash Translation Layer which
 	  is part of the PCMCIA specification. It uses a kind of pseudo-
@@ -216,6 +224,7 @@
 config NFTL
 	tristate "NFTL (NAND Flash Translation Layer) support"
 	depends on MTD && BLOCK
+	select MTD_BLKDEVS
 	---help---
 	  This provides support for the NAND Flash Translation Layer which is
 	  used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
@@ -239,6 +248,7 @@
 config INFTL
 	tristate "INFTL (Inverse NAND Flash Translation Layer) support"
 	depends on MTD && BLOCK
+	select MTD_BLKDEVS
 	---help---
 	  This provides support for the Inverse NAND Flash Translation
 	  Layer which is used on M-Systems' newer DiskOnChip devices. It
@@ -256,6 +266,7 @@
 config RFD_FTL
         tristate "Resident Flash Disk (Flash Translation Layer) support"
 	depends on MTD && BLOCK
+	select MTD_BLKDEVS
 	---help---
 	  This provides support for the flash translation layer known
 	  as the Resident Flash Disk (RFD), as used by the Embedded BIOS
@@ -265,8 +276,8 @@
 
 config SSFDC
 	tristate "NAND SSFDC (SmartMedia) read only translation layer"
-	depends on MTD
-	default n
+	depends on MTD && BLOCK
+	select MTD_BLKDEVS
 	help
 	  This enables read only access to SmartMedia formatted NAND
 	  flash. You can mount it with FAT file system.
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 1e36b9a..c130e62 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -15,13 +15,14 @@
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
-obj-$(CONFIG_MTD_BLOCK)		+= mtdblock.o mtd_blkdevs.o
-obj-$(CONFIG_MTD_BLOCK_RO)	+= mtdblock_ro.o mtd_blkdevs.o
-obj-$(CONFIG_FTL)		+= ftl.o mtd_blkdevs.o
-obj-$(CONFIG_NFTL)		+= nftl.o mtd_blkdevs.o
-obj-$(CONFIG_INFTL)		+= inftl.o mtd_blkdevs.o
-obj-$(CONFIG_RFD_FTL)		+= rfd_ftl.o mtd_blkdevs.o
-obj-$(CONFIG_SSFDC)		+= ssfdc.o mtd_blkdevs.o
+obj-$(CONFIG_MTD_BLKDEVS)	+= mtd_blkdevs.o
+obj-$(CONFIG_MTD_BLOCK)		+= mtdblock.o
+obj-$(CONFIG_MTD_BLOCK_RO)	+= mtdblock_ro.o
+obj-$(CONFIG_FTL)		+= ftl.o
+obj-$(CONFIG_NFTL)		+= nftl.o
+obj-$(CONFIG_INFTL)		+= inftl.o
+obj-$(CONFIG_RFD_FTL)		+= rfd_ftl.o
+obj-$(CONFIG_SSFDC)		+= ssfdc.o
 
 nftl-objs		:= nftlcore.o nftlmount.o
 inftl-objs		:= inftlcore.o inftlmount.o
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index 6a45be0..52d51eb 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -207,11 +207,10 @@
 	if (!sz)
 		return ret;
 
-	parts = kmalloc(sz, GFP_KERNEL);
+	parts = kzalloc(sz, GFP_KERNEL);
 	if (!parts)
 		return -ENOMEM;
 
-	memset(parts, 0, sz);
 	str = (char *)(parts + idx);
 
 	/*
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
index 16eaca6..e7999f1 100644
--- a/drivers/mtd/chips/amd_flash.c
+++ b/drivers/mtd/chips/amd_flash.c
@@ -643,13 +643,12 @@
 	int reg_idx;
 	int offset;
 
-	mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd) {
 		printk(KERN_WARNING
 		       "%s: kmalloc failed for info structure\n", map->name);
 		return NULL;
 	}
-	memset(mtd, 0, sizeof(*mtd));
 	mtd->priv = map;
 
 	memset(&temp, 0, sizeof(temp));
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 296159e..f69184a 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -337,12 +337,11 @@
 	struct mtd_info *mtd;
 	int i;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd) {
 		printk(KERN_ERR "Failed to allocate memory for MTD device\n");
 		return NULL;
 	}
-	memset(mtd, 0, sizeof(*mtd));
 	mtd->priv = map;
 	mtd->type = MTD_NORFLASH;
 
@@ -2224,6 +2223,8 @@
 		case FL_CFI_QUERY:
 		case FL_JEDEC_QUERY:
 			if (chip->oldstate == FL_READY) {
+				/* place the chip in a known state before suspend */
+				map_write(map, CMD(0xFF), cfi->chips[i].start);
 				chip->oldstate = chip->state;
 				chip->state = FL_PM_SUSPENDED;
 				/* No need to wake_up() on this state change -
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 702ae4c..e3acd39 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -48,6 +48,7 @@
 #define MANUFACTURER_ATMEL	0x001F
 #define MANUFACTURER_SST	0x00BF
 #define SST49LF004B	        0x0060
+#define SST49LF040B	        0x0050
 #define SST49LF008A		0x005a
 #define AT49BV6416		0x00d6
 
@@ -233,6 +234,7 @@
 };
 static struct cfi_fixup jedec_fixup_table[] = {
 	{ MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
+	{ MANUFACTURER_SST, SST49LF040B, fixup_use_fwh_lock, NULL, },
 	{ MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },
 	{ 0, 0, NULL, NULL }
 };
@@ -255,12 +257,11 @@
 	struct mtd_info *mtd;
 	int i;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd) {
 		printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
 		return NULL;
 	}
-	memset(mtd, 0, sizeof(*mtd));
 	mtd->priv = map;
 	mtd->type = MTD_NORFLASH;
 
@@ -519,10 +520,12 @@
 		if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
 			goto sleep;
 
-		if (!(mode == FL_READY || mode == FL_POINT
+		if (!(   mode == FL_READY
+		      || mode == FL_POINT
 		      || !cfip
 		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
-		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1))))
+		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)
+		    )))
 			goto sleep;
 
 		/* We could check to see if we're trying to access the sector
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index fae70a5..d56849f 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -172,7 +172,7 @@
 	int i,j;
 	unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
 
 	if (!mtd) {
@@ -181,7 +181,6 @@
 		return NULL;
 	}
 
-	memset(mtd, 0, sizeof(*mtd));
 	mtd->priv = map;
 	mtd->type = MTD_NORFLASH;
 	mtd->size = devsize * cfi->numchips;
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index cdb0f59..2eb696d 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -40,7 +40,7 @@
 	if (mtd) {
 		if (mtd->size > map->size) {
 			printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n",
-			       (unsigned long)mtd->size >> 10, 
+			       (unsigned long)mtd->size >> 10,
 			       (unsigned long)map->size >> 10);
 			mtd->size = map->size;
 		}
@@ -113,13 +113,12 @@
 	}
 
 	mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG;
-	chip_map = kmalloc(mapsize, GFP_KERNEL);
+	chip_map = kzalloc(mapsize, GFP_KERNEL);
 	if (!chip_map) {
 		printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
 		kfree(cfi.cfiq);
 		return NULL;
 	}
-	memset (chip_map, 0, mapsize);
 
 	set_bit(0, chip_map); /* Mark first chip valid */
 
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index 2c3f019..14e57b2 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -116,11 +116,10 @@
    char Part[200];
    memset(&priv,0,sizeof(priv));
 
-   MTD = kmalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
+   MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
    if (!MTD)
 	   return NULL;
 
-   memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));
    priv = (struct jedec_private *)&MTD[1];
 
    my_bank_size = map->size;
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 1154dac..58e561e 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -154,6 +154,7 @@
 #define SST39SF010A	0x00B5
 #define SST39SF020A	0x00B6
 #define SST49LF004B	0x0060
+#define SST49LF040B	0x0050
 #define SST49LF008A	0x005a
 #define SST49LF030A	0x001C
 #define SST49LF040A	0x0051
@@ -1401,6 +1402,20 @@
 		}
 	}, {
 		.mfr_id		= MANUFACTURER_SST,
+		.dev_id         = SST49LF040B,
+		.name           = "SST 49LF040B",
+		.uaddr          = {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize        = SIZE_512KiB,
+		.CmdSet         = P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions        = {
+			ERASEINFO(0x01000,128),
+		}
+	}, {
+
+		.mfr_id		= MANUFACTURER_SST,
 		.dev_id		= SST49LF004B,
 		.name		= "SST 49LF004B",
  		.uaddr		= {
@@ -1874,7 +1889,7 @@
 
 
 /*
- * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing
+ * There is a BIG problem properly ID'ing the JEDEC device and guaranteeing
  * the mapped address, unlock addresses, and proper chip ID.  This function
  * attempts to minimize errors.  It is doubtfull that this probe will ever
  * be perfect - consequently there should be some module parameters that
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c
index ac01a94..fc478c0 100644
--- a/drivers/mtd/chips/map_absent.c
+++ b/drivers/mtd/chips/map_absent.c
@@ -47,13 +47,11 @@
 {
 	struct mtd_info *mtd;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd) {
 		return NULL;
 	}
 
-	memset(mtd, 0, sizeof(*mtd));
-
 	map->fldrv 	= &map_absent_chipdrv;
 	mtd->priv 	= map;
 	mtd->name 	= map->name;
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c
index 3a66680..5cb6d52 100644
--- a/drivers/mtd/chips/map_ram.c
+++ b/drivers/mtd/chips/map_ram.c
@@ -55,12 +55,10 @@
 #endif
 	/* OK. It seems to be RAM. */
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd)
 		return NULL;
 
-	memset(mtd, 0, sizeof(*mtd));
-
 	map->fldrv = &mapram_chipdrv;
 	mtd->priv = map;
 	mtd->name = map->name;
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 1b328b1..cb27f85 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -31,12 +31,10 @@
 {
 	struct mtd_info *mtd;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd)
 		return NULL;
 
-	memset(mtd, 0, sizeof(*mtd));
-
 	map->fldrv = &maprom_chipdrv;
 	mtd->priv = map;
 	mtd->name = map->name;
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index 967abbe..c9cd3d2 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -112,18 +112,16 @@
 	struct sharp_info *sharp = NULL;
 	int width;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if(!mtd)
 		return NULL;
 
-	sharp = kmalloc(sizeof(*sharp), GFP_KERNEL);
+	sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
 	if(!sharp) {
 		kfree(mtd);
 		return NULL;
 	}
 
-	memset(mtd, 0, sizeof(*mtd));
-
 	width = sharp_probe_map(map,mtd);
 	if(!width){
 		kfree(mtd);
@@ -143,7 +141,6 @@
 	mtd->writesize = 1;
 	mtd->name = map->name;
 
-	memset(sharp, 0, sizeof(*sharp));
 	sharp->chipshift = 23;
 	sharp->numchips = 1;
 	sharp->chips[0].start = 0;
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index a7a7bfe..23fab14 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -163,13 +163,12 @@
 		*num_parts = this_part + 1;
 		alloc_size = *num_parts * sizeof(struct mtd_partition) +
 			     extra_mem_size;
-		parts = kmalloc(alloc_size, GFP_KERNEL);
+		parts = kzalloc(alloc_size, GFP_KERNEL);
 		if (!parts)
 		{
 			printk(KERN_ERR ERRP "out of memory\n");
 			return NULL;
 		}
-		memset(parts, 0, alloc_size);
 		extra_mem = (unsigned char *)(parts + *num_parts);
 	}
 	/* enter this partition (offset will be calculated later if it is zero at this point) */
@@ -346,7 +345,7 @@
  *
  * This function needs to be visible for bootloaders.
  */
-int mtdpart_setup(char *s)
+static int mtdpart_setup(char *s)
 {
 	cmdline = s;
 	return 1;
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 401c6a2..6d917a4 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -295,10 +295,9 @@
 	if (!devname)
 		return NULL;
 
-	dev = kmalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
-	memset(dev, 0, sizeof(*dev));
 
 	/* Get a handle on the device */
 	bdev = open_bdev_excl(devname, O_RDWR, NULL);
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 08dfb89..9cff119 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -131,11 +131,10 @@
 	int ret = -ENODEV;
 
 	/* The module decodes 8MiB of address space. */
-	mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL);
+	mod_res = kzalloc(sizeof(*mod_res), GFP_KERNEL);
 	if (!mod_res)
 		return -ENOMEM;
 
-	memset(mod_res, 0, sizeof(*mod_res));
 	mod_res->name = ms02nv_name;
 	mod_res->start = addr;
 	mod_res->end = addr + MS02NV_SLOT_SIZE - 1;
@@ -153,24 +152,21 @@
 	}
 
 	ret = -ENOMEM;
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
 	if (!mtd)
 		goto err_out_mod_res_rel;
-	memset(mtd, 0, sizeof(*mtd));
-	mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+	mp = kzalloc(sizeof(*mp), GFP_KERNEL);
 	if (!mp)
 		goto err_out_mtd;
-	memset(mp, 0, sizeof(*mp));
 
 	mtd->priv = mp;
 	mp->resource.module = mod_res;
 
 	/* Firmware's diagnostic NVRAM area. */
-	diag_res = kmalloc(sizeof(*diag_res), GFP_KERNEL);
+	diag_res = kzalloc(sizeof(*diag_res), GFP_KERNEL);
 	if (!diag_res)
 		goto err_out_mp;
 
-	memset(diag_res, 0, sizeof(*diag_res));
 	diag_res->name = ms02nv_res_diag_ram;
 	diag_res->start = addr;
 	diag_res->end = addr + MS02NV_RAM - 1;
@@ -180,11 +176,10 @@
 	mp->resource.diag_ram = diag_res;
 
 	/* User-available general-purpose NVRAM area. */
-	user_res = kmalloc(sizeof(*user_res), GFP_KERNEL);
+	user_res = kzalloc(sizeof(*user_res), GFP_KERNEL);
 	if (!user_res)
 		goto err_out_diag_res;
 
-	memset(user_res, 0, sizeof(*user_res));
 	user_res->name = ms02nv_res_user_ram;
 	user_res->start = addr + MS02NV_RAM;
 	user_res->end = addr + size - 1;
@@ -194,11 +189,10 @@
 	mp->resource.user_ram = user_res;
 
 	/* Control and status register. */
-	csr_res = kmalloc(sizeof(*csr_res), GFP_KERNEL);
+	csr_res = kzalloc(sizeof(*csr_res), GFP_KERNEL);
 	if (!csr_res)
 		goto err_out_user_res;
 
-	memset(csr_res, 0, sizeof(*csr_res));
 	csr_res->name = ms02nv_res_csr;
 	csr_res->start = addr + MS02NV_CSR;
 	csr_res->end = addr + MS02NV_CSR + 3;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 910e406..a987e91 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -480,7 +480,7 @@
 	device->writesize = pagesize;
 	device->owner = THIS_MODULE;
 	device->type = MTD_DATAFLASH;
-	device->flags = MTD_CAP_NORFLASH;
+	device->flags = MTD_WRITEABLE;
 	device->erase = dataflash_erase;
 	device->read = dataflash_read;
 	device->write = dataflash_write;
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 6c7337f..56cc1ca 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -126,12 +126,10 @@
 	struct phram_mtd_list *new;
 	int ret = -ENOMEM;
 
-	new = kmalloc(sizeof(*new), GFP_KERNEL);
+	new = kzalloc(sizeof(*new), GFP_KERNEL);
 	if (!new)
 		goto out0;
 
-	memset(new, 0, sizeof(*new));
-
 	ret = -EIO;
 	new->mtd.priv = ioremap(start, len);
 	if (!new->mtd.priv) {
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 542a0c0..5f49248 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -168,19 +168,16 @@
 		E("slram: Cannot allocate new MTD device.\n");
 		return(-ENOMEM);
 	}
-	(*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+	(*curmtd)->mtdinfo = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
 	(*curmtd)->next = NULL;
 
 	if ((*curmtd)->mtdinfo)	{
-		memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info));
 		(*curmtd)->mtdinfo->priv =
-			kmalloc(sizeof(slram_priv_t), GFP_KERNEL);
+			kzalloc(sizeof(slram_priv_t), GFP_KERNEL);
 
 		if (!(*curmtd)->mtdinfo->priv) {
 			kfree((*curmtd)->mtdinfo);
 			(*curmtd)->mtdinfo = NULL;
-		} else {
-			memset((*curmtd)->mtdinfo->priv,0,sizeof(slram_priv_t));
 		}
 	}
 
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 8a878b3..24235d4 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1033,7 +1033,7 @@
 {
 	partition_t *partition;
 
-	partition = kmalloc(sizeof(partition_t), GFP_KERNEL);
+	partition = kzalloc(sizeof(partition_t), GFP_KERNEL);
 
 	if (!partition) {
 		printk(KERN_WARNING "No memory to scan for FTL on %s\n",
@@ -1041,8 +1041,6 @@
 		return;
 	}
 
-	memset(partition, 0, sizeof(partition_t));
-
 	partition->mbd.mtd = mtd;
 
 	if ((scan_header(partition) == 0) &&
@@ -1054,7 +1052,7 @@
 		       le32_to_cpu(partition->header.FormattedSize) >> 10);
 #endif
 		partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9;
-		partition->mbd.blksize = SECTOR_SIZE;
+
 		partition->mbd.tr = tr;
 		partition->mbd.devnum = -1;
 		if (!add_mtd_blktrans_dev((void *)partition))
@@ -1076,6 +1074,7 @@
 	.name		= "ftl",
 	.major		= FTL_MAJOR,
 	.part_bits	= PART_BITS,
+	.blksize 	= SECTOR_SIZE,
 	.readsect	= ftl_readsect,
 	.writesect	= ftl_writesect,
 	.getgeo		= ftl_getgeo,
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 4116535..b0e3965 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -67,17 +67,16 @@
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
 
-	inftl = kmalloc(sizeof(*inftl), GFP_KERNEL);
+	inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
 
 	if (!inftl) {
 		printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
 		return;
 	}
-	memset(inftl, 0, sizeof(*inftl));
 
 	inftl->mbd.mtd = mtd;
 	inftl->mbd.devnum = -1;
-	inftl->mbd.blksize = 512;
+
 	inftl->mbd.tr = tr;
 
 	if (INFTL_mount(inftl) < 0) {
@@ -163,10 +162,9 @@
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
-	ops.len = len;
 
 	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
-	*retlen = ops.retlen;
+	*retlen = ops.oobretlen;
 	return res;
 }
 
@@ -184,10 +182,9 @@
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
-	ops.len = len;
 
 	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
-	*retlen = ops.retlen;
+	*retlen = ops.oobretlen;
 	return res;
 }
 
@@ -945,6 +942,7 @@
 	.name		= "inftl",
 	.major		= INFTL_MAJOR,
 	.part_bits	= INFTL_PARTN_BITS,
+	.blksize 	= 512,
 	.getgeo		= inftl_getgeo,
 	.readsect	= inftl_readblock,
 	.writesect	= inftl_writeblock,
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index d132ed5..f457315 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -60,6 +60,15 @@
 	  Ignore this option if you use run-time physmap configuration
 	  (i.e., run-time calling physmap_configure()).
 
+config MTD_PHYSMAP_OF
+	tristate "Flash device in physical memory map based on OF descirption"
+	depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM)
+	help
+	  This provides a 'mapping' driver which allows the NOR Flash and
+	  ROM driver code to communicate with chips which are mapped
+	  physically into the CPU's memory. The mapping description here is
+	  taken from OF device tree.
+
 config MTD_SUN_UFLASH
 	tristate "Sun Microsystems userflash support"
 	depends on SPARC && MTD_CFI
@@ -184,6 +193,24 @@
 
 	  BE VERY CAREFUL.
 
+config MTD_ESB2ROM
+        tristate "BIOS flash chip on Intel ESB Controller Hub 2"
+        depends on X86 && MTD_JEDECPROBE && PCI
+        help
+          Support for treating the BIOS flash chip on ESB2 motherboards
+          as an MTD device - with this you can reprogram your BIOS.
+
+          BE VERY CAREFUL.
+
+config MTD_CK804XROM
+	tristate "BIOS flash chip on Nvidia CK804"
+	depends on X86 && MTD_JEDECPROBE
+	help
+	  Support for treating the BIOS flash chip on nvidia motherboards
+	  as an MTD device - with this you can reprogram your BIOS.
+
+	  BE VERY CAREFUL.
+
 config MTD_SCB2_FLASH
 	tristate "BIOS flash chip on Intel SCB2 boards"
 	depends on X86 && MTD_JEDECPROBE
@@ -355,50 +382,6 @@
 	  TQ Components TQM834x boards. If you have one of these boards
 	  and would like to use the flash chips on it, say 'Y'.
 
-config MTD_CSTM_MIPS_IXX
-	tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board"
-	depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS
-	help
-	  This provides a mapping driver for the Integrated Technology
-	  Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR
-	  Reference Board. It provides the necessary addressing, length,
-	  buswidth, vpp code and addition setup of the flash device for
-	  these boards. In addition, this mapping driver can be used for
-	  other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/
-	  LEN/BUSWIDTH parameters. This mapping will provide one mtd device
-	  using one partition. The start address can be offset from the
-	  beginning of flash and the len can be less than the total flash
-	  device size to allow a window into the flash. Both CFI and JEDEC
-	  probes are called.
-
-config MTD_CSTM_MIPS_IXX_START
-	hex "Physical start address of flash mapping"
-	depends on MTD_CSTM_MIPS_IXX
-	default "0x8000000"
-	help
-	  This is the physical memory location that the MTD driver will
-	  use for the flash chips on your particular target board.
-	  Refer to the memory map which should hopefully be in the
-	  documentation for your board.
-
-config MTD_CSTM_MIPS_IXX_LEN
-	hex "Physical length of flash mapping"
-	depends on MTD_CSTM_MIPS_IXX
-	default "0x4000000"
-	help
-	  This is the total length that the MTD driver will use for the
-	  flash chips on your particular board.  Refer to the memory
-	  map which should hopefully be in the documentation for your
-	  board.
-
-config MTD_CSTM_MIPS_IXX_BUSWIDTH
-	int "Bus width in octets"
-	depends on MTD_CSTM_MIPS_IXX
-	default "2"
-	help
-	  This is the total bus width of the mapping of the flash chips
-	  on your particular board.
-
 config MTD_OCELOT
 	tristate "Momenco Ocelot boot flash device"
 	depends on MIPS && MOMENCO_OCELOT
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 191c192..071d0bf 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -12,12 +12,13 @@
 obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
 obj-$(CONFIG_MTD_BAST)		+= bast-flash.o
 obj-$(CONFIG_MTD_CFI_FLAGADM)	+= cfi_flagadm.o
-obj-$(CONFIG_MTD_CSTM_MIPS_IXX)	+= cstm_mips_ixx.o
 obj-$(CONFIG_MTD_DC21285)	+= dc21285.o
 obj-$(CONFIG_MTD_DILNETPC)	+= dilnetpc.o
 obj-$(CONFIG_MTD_L440GX)	+= l440gx.o
 obj-$(CONFIG_MTD_AMD76XROM)	+= amd76xrom.o
+obj-$(CONFIG_MTD_ESB2ROM)	+= esb2rom.o
 obj-$(CONFIG_MTD_ICHXROM)	+= ichxrom.o
+obj-$(CONFIG_MTD_CK804XROM)	+= ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_LUBBOCK)	+= lubbock-flash.o
 obj-$(CONFIG_MTD_MAINSTONE)	+= mainstone-flash.o
@@ -25,6 +26,7 @@
 obj-$(CONFIG_MTD_CEIVA)		+= ceiva.o
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
+obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
 obj-$(CONFIG_MTD_PNC2000)	+= pnc2000.o
 obj-$(CONFIG_MTD_PCMCIA)	+= pcmciamtd.o
 obj-$(CONFIG_MTD_RPXLITE)	+= rpxlite.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 797caff..78b6711 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -7,6 +7,7 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <asm/io.h>
@@ -44,6 +45,23 @@
 	char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
 };
 
+/* The 2 bits controlling the window size are often set to allow reading
+ * the BIOS, but too small to allow writing, since the lock registers are
+ * 4MiB lower in the address space than the data.
+ *
+ * This is intended to prevent flashing the bios, perhaps accidentally.
+ *
+ * This parameter allows the normal driver to over-ride the BIOS settings.
+ *
+ * The bits are 6 and 7.  If both bits are set, it is a 5MiB window.
+ * If only the 7 Bit is set, it is a 4MiB window.  Otherwise, a
+ * 64KiB window.
+ *
+ */
+static uint win_size_bits;
+module_param(win_size_bits, uint, 0);
+MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x43 byte, normally set by BIOS.");
+
 static struct amd76xrom_window amd76xrom_window = {
 	.maps = LIST_HEAD_INIT(amd76xrom_window.maps),
 };
@@ -95,6 +113,16 @@
 	/* Remember the pci dev I find the window in - already have a ref */
 	window->pdev = pdev;
 
+	/* Enable the selected rom window.  This is often incorrectly
+	 * set up by the BIOS, and the 4MiB offset for the lock registers
+	 * requires the full 5MiB of window space.
+	 *
+	 * This 'write, then read' approach leaves the bits for
+	 * other uses of the hardware info.
+	 */
+	pci_read_config_byte(pdev, 0x43, &byte);
+	pci_write_config_byte(pdev, 0x43, byte | win_size_bits );
+
 	/* Assume the rom window is properly setup, and find it's size */
 	pci_read_config_byte(pdev, 0x43, &byte);
 	if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
@@ -129,12 +157,6 @@
 			(unsigned long long)window->rsrc.end);
 	}
 
-#if 0
-
-	/* Enable the selected rom window */
-	pci_read_config_byte(pdev, 0x43, &byte);
-	pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
-#endif
 
 	/* Enable writes through the rom window */
 	pci_read_config_byte(pdev, 0x40, &byte);
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
index e074bb6..fc3b267 100644
--- a/drivers/mtd/maps/bast-flash.c
+++ b/drivers/mtd/maps/bast-flash.c
@@ -131,7 +131,7 @@
 
 	info->map.phys = res->start;
 	info->map.size = res->end - res->start + 1;
-	info->map.name = pdev->dev.bus_id;	
+	info->map.name = pdev->dev.bus_id;
 	info->map.bankwidth = 2;
 
 	if (info->map.size > AREA_MAXSIZE)
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index 0402c21..629e6e2 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -122,10 +122,9 @@
 	/*
 	 * Allocate the map_info structs in one go.
 	 */
-	maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
+	maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
 	if (!maps)
 		return -ENOMEM;
-	memset(maps, 0, sizeof(struct map_info) * nr);
 	/*
 	 * Claim and then map the memory regions.
 	 */
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
new file mode 100644
index 0000000..238d42e
--- /dev/null
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -0,0 +1,356 @@
+/*
+ * ck804xrom.c
+ *
+ * Normal mappings of chips in physical memory
+ *
+ * Dave Olsen <dolsen@lnxi.com>
+ * Ryan Jackson <rjackson@lnxi.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/list.h>
+
+
+#define MOD_NAME KBUILD_BASENAME
+
+#define ADDRESS_NAME_LEN 18
+
+#define ROM_PROBE_STEP_SIZE (64*1024)
+
+struct ck804xrom_window {
+	void __iomem *virt;
+	unsigned long phys;
+	unsigned long size;
+	struct list_head maps;
+	struct resource rsrc;
+	struct pci_dev *pdev;
+};
+
+struct ck804xrom_map_info {
+	struct list_head list;
+	struct map_info map;
+	struct mtd_info *mtd;
+	struct resource rsrc;
+	char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
+};
+
+
+/* The 2 bits controlling the window size are often set to allow reading
+ * the BIOS, but too small to allow writing, since the lock registers are
+ * 4MiB lower in the address space than the data.
+ *
+ * This is intended to prevent flashing the bios, perhaps accidentally.
+ *
+ * This parameter allows the normal driver to override the BIOS settings.
+ *
+ * The bits are 6 and 7.  If both bits are set, it is a 5MiB window.
+ * If only the 7 Bit is set, it is a 4MiB window.  Otherwise, a
+ * 64KiB window.
+ *
+ */
+static uint win_size_bits = 0;
+module_param(win_size_bits, uint, 0);
+MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS.");
+
+static struct ck804xrom_window ck804xrom_window = {
+	.maps = LIST_HEAD_INIT(ck804xrom_window.maps),
+};
+
+static void ck804xrom_cleanup(struct ck804xrom_window *window)
+{
+	struct ck804xrom_map_info *map, *scratch;
+	u8 byte;
+
+	if (window->pdev) {
+		/* Disable writes through the rom window */
+		pci_read_config_byte(window->pdev, 0x6d, &byte);
+		pci_write_config_byte(window->pdev, 0x6d, byte & ~1);
+	}
+
+	/* Free all of the mtd devices */
+	list_for_each_entry_safe(map, scratch, &window->maps, list) {
+		if (map->rsrc.parent)
+			release_resource(&map->rsrc);
+
+		del_mtd_device(map->mtd);
+		map_destroy(map->mtd);
+		list_del(&map->list);
+		kfree(map);
+	}
+	if (window->rsrc.parent)
+		release_resource(&window->rsrc);
+
+	if (window->virt) {
+		iounmap(window->virt);
+		window->virt = NULL;
+		window->phys = 0;
+		window->size = 0;
+	}
+	pci_dev_put(window->pdev);
+}
+
+
+static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+	u8 byte;
+	struct ck804xrom_window *window = &ck804xrom_window;
+	struct ck804xrom_map_info *map = NULL;
+	unsigned long map_top;
+
+	/* Remember the pci dev I find the window in */
+	window->pdev = pci_dev_get(pdev);
+
+	/* Enable the selected rom window.  This is often incorrectly
+	 * set up by the BIOS, and the 4MiB offset for the lock registers
+	 * requires the full 5MiB of window space.
+	 *
+	 * This 'write, then read' approach leaves the bits for
+	 * other uses of the hardware info.
+	 */
+        pci_read_config_byte(pdev, 0x88, &byte);
+        pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
+
+
+	/* Assume the rom window is properly setup, and find it's size */
+	pci_read_config_byte(pdev, 0x88, &byte);
+
+	if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
+		window->phys = 0xffb00000; /* 5MiB */
+	else if ((byte & (1<<7)) == (1<<7))
+		window->phys = 0xffc00000; /* 4MiB */
+	else
+		window->phys = 0xffff0000; /* 64KiB */
+
+	window->size = 0xffffffffUL - window->phys + 1UL;
+
+	/*
+	 * Try to reserve the window mem region.  If this fails then
+	 * it is likely due to a fragment of the window being
+	 * "reserved" by the BIOS.  In the case that the
+	 * request_mem_region() fails then once the rom size is
+	 * discovered we will try to reserve the unreserved fragment.
+	 */
+	window->rsrc.name = MOD_NAME;
+	window->rsrc.start = window->phys;
+	window->rsrc.end   = window->phys + window->size - 1;
+	window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (request_resource(&iomem_resource, &window->rsrc)) {
+		window->rsrc.parent = NULL;
+		printk(KERN_ERR MOD_NAME
+			" %s(): Unable to register resource"
+			" 0x%.016llx-0x%.016llx - kernel bug?\n",
+			__func__,
+			(unsigned long long)window->rsrc.start,
+			(unsigned long long)window->rsrc.end);
+	}
+
+
+	/* Enable writes through the rom window */
+	pci_read_config_byte(pdev, 0x6d, &byte);
+	pci_write_config_byte(pdev, 0x6d, byte | 1);
+
+	/* FIXME handle registers 0x80 - 0x8C the bios region locks */
+
+	/* For write accesses caches are useless */
+	window->virt = ioremap_nocache(window->phys, window->size);
+	if (!window->virt) {
+		printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
+			window->phys, window->size);
+		goto out;
+	}
+
+	/* Get the first address to look for a rom chip at */
+	map_top = window->phys;
+#if 1
+	/* The probe sequence run over the firmware hub lock
+	 * registers sets them to 0x7 (no access).
+	 * Probe at most the last 4MiB of the address space.
+	 */
+	if (map_top < 0xffc00000)
+		map_top = 0xffc00000;
+#endif
+	/* Loop  through and look for rom chips.  Since we don't know the
+	 * starting address for each chip, probe every ROM_PROBE_STEP_SIZE
+	 * bytes from the starting address of the window.
+	 */
+	while((map_top - 1) < 0xffffffffUL) {
+		struct cfi_private *cfi;
+		unsigned long offset;
+		int i;
+
+		if (!map)
+			map = kmalloc(sizeof(*map), GFP_KERNEL);
+
+		if (!map) {
+			printk(KERN_ERR MOD_NAME ": kmalloc failed");
+			goto out;
+		}
+		memset(map, 0, sizeof(*map));
+		INIT_LIST_HEAD(&map->list);
+		map->map.name = map->map_name;
+		map->map.phys = map_top;
+		offset = map_top - window->phys;
+		map->map.virt = (void __iomem *)
+			(((unsigned long)(window->virt)) + offset);
+		map->map.size = 0xffffffffUL - map_top + 1UL;
+		/* Set the name of the map to the address I am trying */
+		sprintf(map->map_name, "%s @%08lx",
+			MOD_NAME, map->map.phys);
+
+		/* There is no generic VPP support */
+		for(map->map.bankwidth = 32; map->map.bankwidth;
+			map->map.bankwidth >>= 1)
+		{
+			char **probe_type;
+			/* Skip bankwidths that are not supported */
+			if (!map_bankwidth_supported(map->map.bankwidth))
+				continue;
+
+			/* Setup the map methods */
+			simple_map_init(&map->map);
+
+			/* Try all of the probe methods */
+			probe_type = rom_probe_types;
+			for(; *probe_type; probe_type++) {
+				map->mtd = do_map_probe(*probe_type, &map->map);
+				if (map->mtd)
+					goto found;
+			}
+		}
+		map_top += ROM_PROBE_STEP_SIZE;
+		continue;
+	found:
+		/* Trim the size if we are larger than the map */
+		if (map->mtd->size > map->map.size) {
+			printk(KERN_WARNING MOD_NAME
+				" rom(%u) larger than window(%lu). fixing...\n",
+				map->mtd->size, map->map.size);
+			map->mtd->size = map->map.size;
+		}
+		if (window->rsrc.parent) {
+			/*
+			 * Registering the MTD device in iomem may not be possible
+			 * if there is a BIOS "reserved" and BUSY range.  If this
+			 * fails then continue anyway.
+			 */
+			map->rsrc.name  = map->map_name;
+			map->rsrc.start = map->map.phys;
+			map->rsrc.end   = map->map.phys + map->mtd->size - 1;
+			map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+			if (request_resource(&window->rsrc, &map->rsrc)) {
+				printk(KERN_ERR MOD_NAME
+					": cannot reserve MTD resource\n");
+				map->rsrc.parent = NULL;
+			}
+		}
+
+		/* Make the whole region visible in the map */
+		map->map.virt = window->virt;
+		map->map.phys = window->phys;
+		cfi = map->map.fldrv_priv;
+		for(i = 0; i < cfi->numchips; i++)
+			cfi->chips[i].start += offset;
+
+		/* Now that the mtd devices is complete claim and export it */
+		map->mtd->owner = THIS_MODULE;
+		if (add_mtd_device(map->mtd)) {
+			map_destroy(map->mtd);
+			map->mtd = NULL;
+			goto out;
+		}
+
+
+		/* Calculate the new value of map_top */
+		map_top += map->mtd->size;
+
+		/* File away the map structure */
+		list_add(&map->list, &window->maps);
+		map = NULL;
+	}
+
+ out:
+	/* Free any left over map structures */
+	if (map)
+		kfree(map);
+
+	/* See if I have any map structures */
+	if (list_empty(&window->maps)) {
+		ck804xrom_cleanup(window);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+
+static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
+{
+	struct ck804xrom_window *window = &ck804xrom_window;
+
+	ck804xrom_cleanup(window);
+}
+
+static struct pci_device_id ck804xrom_pci_tbl[] = {
+	{ PCI_VENDOR_ID_NVIDIA, 0x0051,
+        PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
+
+#if 0
+static struct pci_driver ck804xrom_driver = {
+	.name =		MOD_NAME,
+	.id_table =	ck804xrom_pci_tbl,
+	.probe =	ck804xrom_init_one,
+	.remove =	ck804xrom_remove_one,
+};
+#endif
+
+static int __init init_ck804xrom(void)
+{
+	struct pci_dev *pdev;
+	struct pci_device_id *id;
+	int retVal;
+	pdev = NULL;
+
+	for(id = ck804xrom_pci_tbl; id->vendor; id++) {
+		pdev = pci_find_device(id->vendor, id->device, NULL);
+		if (pdev)
+			break;
+	}
+	if (pdev) {
+		retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]);
+		pci_dev_put(pdev);
+		return retVal;
+	}
+	return -ENXIO;
+#if 0
+	return pci_module_init(&ck804xrom_driver);
+#endif
+}
+
+static void __exit cleanup_ck804xrom(void)
+{
+	ck804xrom_remove_one(ck804xrom_window.pdev);
+}
+
+module_init(init_ck804xrom);
+module_exit(cleanup_ck804xrom);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>, Dave Olsen <dolsen@lnxi.com>");
+MODULE_DESCRIPTION("MTD map driver for BIOS chips on the Nvidia ck804 southbridge");
+
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c
deleted file mode 100644
index df2c38e..0000000
--- a/drivers/mtd/maps/cstm_mips_ixx.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * $Id: cstm_mips_ixx.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
- *
- * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
- * Config with both CFI and JEDEC device support.
- *
- * Basically physmap.c with the addition of partitions and
- * an array of mapping info to accomodate more than one flash type per board.
- *
- * Copyright 2000 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License 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/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/delay.h>
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-#define CC_GCR             0xB4013818
-#define CC_GPBCR           0xB401380A
-#define CC_GPBDR           0xB4013808
-#define CC_M68K_DEVICE     1
-#define CC_M68K_FUNCTION   6
-#define CC_CONFADDR        0xB8004000
-#define CC_CONFDATA        0xB8004004
-#define CC_FC_FCR          0xB8002004
-#define CC_FC_DCR          0xB8002008
-#define CC_GPACR           0xB4013802
-#define CC_GPAICR          0xB4013804
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp)
-{
-	static DEFINE_SPINLOCK(vpp_lock);
-	static int vpp_count = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vpp_lock, flags);
-
-	if (vpp) {
-		if (!vpp_count++) {
-			__u16	data;
-			__u8	data1;
-			static u8 first = 1;
-
-			// Set GPIO port B pin3 to high
-			data = *(__u16 *)(CC_GPBCR);
-			data = (data & 0xff0f) | 0x0040;
-			*(__u16 *)CC_GPBCR = data;
-			*(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08;
-			if (first) {
-				first = 0;
-				/* need to have this delay for first
-				   enabling vpp after powerup */
-				udelay(40);
-			}
-		}
-	} else {
-		if (!--vpp_count) {
-			__u16	data;
-
-			// Set GPIO port B pin3 to high
-			data = *(__u16 *)(CC_GPBCR);
-			data = (data & 0xff3f) | 0x0040;
-			*(__u16 *)CC_GPBCR = data;
-			*(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7;
-		}
-	}
-	spin_unlock_irqrestore(&vpp_lock, flags);
-}
-#endif
-
-/* board and partition description */
-
-#define MAX_PHYSMAP_PARTITIONS    8
-struct cstm_mips_ixx_info {
-	char *name;
-	unsigned long window_addr;
-	unsigned long window_size;
-	int bankwidth;
-	int num_partitions;
-};
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-#define PHYSMAP_NUMBER  1  // number of board desc structs needed, one per contiguous flash type
-const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
-{
-    {   // 28F128J3A in 2x16 configuration
-        "big flash",     // name
-	0x08000000,      // window_addr
-	0x02000000,      // window_size
-        4,               // bankwidth
-	1,               // num_partitions
-    }
-
-};
-static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
-{   // 28F128J3A in 2x16 configuration
-	{
-		.name = "main partition ",
-		.size = 0x02000000, // 128 x 2 x 128k byte sectors
-		.offset = 0,
-	},
-},
-};
-#else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-#define PHYSMAP_NUMBER  1  // number of board desc structs needed, one per contiguous flash type
-const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
-{
-    {
-        "MTD flash",                   // name
-	CONFIG_MTD_CSTM_MIPS_IXX_START,      // window_addr
-	CONFIG_MTD_CSTM_MIPS_IXX_LEN,        // window_size
-        CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH,   // bankwidth
-	1,                             // num_partitions
-    },
-
-};
-static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
-{
-	{
-		.name = "main partition",
-		.size =  CONFIG_MTD_CSTM_MIPS_IXX_LEN,
-		.offset = 0,
-	},
-},
-};
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER];
-
-int __init init_cstm_mips_ixx(void)
-{
-	int i;
-	int jedec;
-        struct mtd_info *mymtd;
-        struct mtd_partition *parts;
-
-	/* Initialize mapping */
-	for (i=0;i<PHYSMAP_NUMBER;i++) {
-		printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n",
-		       cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr);
-
-
-		cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
-		cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
-		if (!cstm_mips_ixx_map[i].virt) {
-			int j = 0;
-			printk(KERN_WARNING "Failed to ioremap\n");
-			for (j = 0; j < i; j++) {
-				if (cstm_mips_ixx_map[j].virt) {
-					iounmap(cstm_mips_ixx_map[j].virt);
-					cstm_mips_ixx_map[j].virt = NULL;
-				}
-			}
-			return -EIO;
-	        }
-		cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
-		cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size;
-		cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth;
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-                cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp;
-#endif
-		simple_map_init(&cstm_mips_ixx_map[i]);
-		//printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt));
-	}
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-        setup_ITE_IVR_flash();
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-	for (i=0;i<PHYSMAP_NUMBER;i++) {
-                parts = &cstm_mips_ixx_partitions[i][0];
-		jedec = 0;
-		mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]);
-		//printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd);
-		if (!mymtd) {
-			jedec = 1;
-			mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]);
-		        printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd);
-		}
-		if (mymtd) {
-			mymtd->owner = THIS_MODULE;
-
-	                cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd;
-		        add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions);
-		}
-		else {
-			for (i = 0; i < PHYSMAP_NUMBER; i++) {
-				if (cstm_mips_ixx_map[i].virt) {
-					iounmap(cstm_mips_ixx_map[i].virt);
-					cstm_mips_ixx_map[i].virt = NULL;
-				}
-			}
-			return -ENXIO;
-		}
-	}
-	return 0;
-}
-
-static void __exit cleanup_cstm_mips_ixx(void)
-{
-	int i;
-        struct mtd_info *mymtd;
-
-	for (i=0;i<PHYSMAP_NUMBER;i++) {
-	        mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2;
-		if (mymtd) {
-			del_mtd_partitions(mymtd);
-			map_destroy(mymtd);
-		}
-		if (cstm_mips_ixx_map[i].virt) {
-			iounmap((void *)cstm_mips_ixx_map[i].virt);
-			cstm_mips_ixx_map[i].virt = 0;
-		}
-	}
-}
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data)
-{
-	__u32	offset;
-
-	offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ;
-
-	*(__u32 *)CC_CONFADDR = offset;
-	*(__u32 *)CC_CONFDATA = data;
-}
-void setup_ITE_IVR_flash()
-{
-		__u32	size, base;
-
-		size = 0x0e000000;		// 32MiB
-		base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit
-
-		/* need to set ITE flash to 32 bits instead of default 8 */
-#ifdef CONFIG_MIPS_IVR
-		*(__u32 *)CC_FC_FCR = 0x55;
-		*(__u32 *)CC_GPACR = 0xfffc;
-#else
-		*(__u32 *)CC_FC_FCR = 0x77;
-#endif
-		/* turn bursting off */
-		*(__u32 *)CC_FC_DCR = 0x0;
-
-		/* setup for one chip 4 byte PCI access */
-		PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base);
-		PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02);
-}
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-module_init(init_cstm_mips_ixx);
-module_exit(cleanup_cstm_mips_ixx);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
-MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards");
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
new file mode 100644
index 0000000..a9d808a
--- /dev/null
+++ b/drivers/mtd/maps/esb2rom.c
@@ -0,0 +1,450 @@
+/*
+ * esb2rom.c
+ *
+ * Normal mappings of flash chips in physical memory
+ * through the Intel ESB2 Southbridge.
+ *
+ * This was derived from ichxrom.c in May 2006 by
+ *	Lew Glendenning <lglendenning@lnxi.com>
+ *
+ * Eric Biederman, of course, was a major help in this effort.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/list.h>
+
+#define MOD_NAME KBUILD_BASENAME
+
+#define ADDRESS_NAME_LEN 18
+
+#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
+
+#define BIOS_CNTL	0xDC
+#define BIOS_LOCK_ENABLE	0x02
+#define BIOS_WRITE_ENABLE	0x01
+
+/* This became a 16-bit register, and EN2 has disappeared */
+#define FWH_DEC_EN1	0xD8
+#define FWH_F8_EN	0x8000
+#define FWH_F0_EN	0x4000
+#define FWH_E8_EN	0x2000
+#define FWH_E0_EN	0x1000
+#define FWH_D8_EN	0x0800
+#define FWH_D0_EN	0x0400
+#define FWH_C8_EN	0x0200
+#define FWH_C0_EN	0x0100
+#define FWH_LEGACY_F_EN	0x0080
+#define FWH_LEGACY_E_EN	0x0040
+/* reserved  0x0020 and 0x0010 */
+#define FWH_70_EN	0x0008
+#define FWH_60_EN	0x0004
+#define FWH_50_EN	0x0002
+#define FWH_40_EN	0x0001
+
+/* these are 32-bit values */
+#define FWH_SEL1	0xD0
+#define FWH_SEL2	0xD4
+
+#define FWH_8MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+			 FWH_70_EN | FWH_60_EN | FWH_50_EN | FWH_40_EN)
+
+#define FWH_7MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+			 FWH_70_EN | FWH_60_EN | FWH_50_EN)
+
+#define FWH_6MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+			 FWH_70_EN | FWH_60_EN)
+
+#define FWH_5MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+			 FWH_70_EN)
+
+#define FWH_4MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN)
+
+#define FWH_3_5MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN)
+
+#define FWH_3MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN | FWH_D0_EN)
+
+#define FWH_2_5MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+			 FWH_D8_EN)
+
+#define FWH_2MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN)
+
+#define FWH_1_5MiB	(FWH_F8_EN | FWH_F0_EN | FWH_E8_EN)
+
+#define FWH_1MiB	(FWH_F8_EN | FWH_F0_EN)
+
+#define FWH_0_5MiB	(FWH_F8_EN)
+
+
+struct esb2rom_window {
+	void __iomem* virt;
+	unsigned long phys;
+	unsigned long size;
+	struct list_head maps;
+	struct resource rsrc;
+	struct pci_dev *pdev;
+};
+
+struct esb2rom_map_info {
+	struct list_head list;
+	struct map_info map;
+	struct mtd_info *mtd;
+	struct resource rsrc;
+	char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
+};
+
+static struct esb2rom_window esb2rom_window = {
+	.maps = LIST_HEAD_INIT(esb2rom_window.maps),
+};
+
+static void esb2rom_cleanup(struct esb2rom_window *window)
+{
+	struct esb2rom_map_info *map, *scratch;
+	u8 byte;
+
+	/* Disable writes through the rom window */
+	pci_read_config_byte(window->pdev, BIOS_CNTL, &byte);
+	pci_write_config_byte(window->pdev, BIOS_CNTL,
+		byte & ~BIOS_WRITE_ENABLE);
+
+	/* Free all of the mtd devices */
+	list_for_each_entry_safe(map, scratch, &window->maps, list) {
+		if (map->rsrc.parent)
+			release_resource(&map->rsrc);
+		del_mtd_device(map->mtd);
+		map_destroy(map->mtd);
+		list_del(&map->list);
+		kfree(map);
+	}
+	if (window->rsrc.parent)
+		release_resource(&window->rsrc);
+	if (window->virt) {
+		iounmap(window->virt);
+		window->virt = NULL;
+		window->phys = 0;
+		window->size = 0;
+	}
+	pci_dev_put(window->pdev);
+}
+
+static int __devinit esb2rom_init_one(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+	struct esb2rom_window *window = &esb2rom_window;
+	struct esb2rom_map_info *map = NULL;
+	unsigned long map_top;
+	u8 byte;
+	u16 word;
+
+	/* For now I just handle the ecb2 and I assume there
+	 * are not a lot of resources up at the top of the address
+	 * space.  It is possible to handle other devices in the
+	 * top 16MiB but it is very painful.  Also since
+	 * you can only really attach a FWH to an ICHX there
+	 * a number of simplifications you can make.
+	 *
+	 * Also you can page firmware hubs if an 8MiB window isn't enough
+	 * but don't currently handle that case either.
+	 */
+	window->pdev = pci_dev_get(pdev);
+
+	/* RLG:  experiment 2.  Force the window registers to the widest values */
+
+/*
+	pci_read_config_word(pdev, FWH_DEC_EN1, &word);
+	printk(KERN_DEBUG "Original FWH_DEC_EN1 : %x\n", word);
+	pci_write_config_byte(pdev, FWH_DEC_EN1, 0xff);
+	pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
+	printk(KERN_DEBUG "New FWH_DEC_EN1 : %x\n", byte);
+
+	pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
+	printk(KERN_DEBUG "Original FWH_DEC_EN2 : %x\n", byte);
+	pci_write_config_byte(pdev, FWH_DEC_EN2, 0x0f);
+	pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
+	printk(KERN_DEBUG "New FWH_DEC_EN2 : %x\n", byte);
+*/
+
+	/* Find a region continuous to the end of the ROM window  */
+	window->phys = 0;
+	pci_read_config_word(pdev, FWH_DEC_EN1, &word);
+	printk(KERN_DEBUG "pci_read_config_byte : %x\n", word);
+
+	if ((word & FWH_8MiB) == FWH_8MiB)
+		window->phys = 0xff400000;
+	else if ((word & FWH_7MiB) == FWH_7MiB)
+		window->phys = 0xff500000;
+	else if ((word & FWH_6MiB) == FWH_6MiB)
+		window->phys = 0xff600000;
+	else if ((word & FWH_5MiB) == FWH_5MiB)
+		window->phys = 0xFF700000;
+	else if ((word & FWH_4MiB) == FWH_4MiB)
+		window->phys = 0xffc00000;
+	else if ((word & FWH_3_5MiB) == FWH_3_5MiB)
+		window->phys = 0xffc80000;
+	else if ((word & FWH_3MiB) == FWH_3MiB)
+		window->phys = 0xffd00000;
+	else if ((word & FWH_2_5MiB) == FWH_2_5MiB)
+		window->phys = 0xffd80000;
+	else if ((word & FWH_2MiB) == FWH_2MiB)
+		window->phys = 0xffe00000;
+	else if ((word & FWH_1_5MiB) == FWH_1_5MiB)
+		window->phys = 0xffe80000;
+	else if ((word & FWH_1MiB) == FWH_1MiB)
+		window->phys = 0xfff00000;
+	else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
+		window->phys = 0xfff80000;
+
+	/* reserved  0x0020 and 0x0010 */
+	window->phys -= 0x400000UL;
+	window->size = (0xffffffffUL - window->phys) + 1UL;
+
+	/* Enable writes through the rom window */
+	pci_read_config_byte(pdev, BIOS_CNTL, &byte);
+	if (!(byte & BIOS_WRITE_ENABLE)  && (byte & (BIOS_LOCK_ENABLE))) {
+		/* The BIOS will generate an error if I enable
+		 * this device, so don't even try.
+		 */
+		printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
+		goto out;
+	}
+	pci_write_config_byte(pdev, BIOS_CNTL, byte | BIOS_WRITE_ENABLE);
+
+	/*
+	 * Try to reserve the window mem region.  If this fails then
+	 * it is likely due to the window being "reseved" by the BIOS.
+	 */
+	window->rsrc.name = MOD_NAME;
+	window->rsrc.start = window->phys;
+	window->rsrc.end   = window->phys + window->size - 1;
+	window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (request_resource(&iomem_resource, &window->rsrc)) {
+		window->rsrc.parent = NULL;
+		printk(KERN_DEBUG MOD_NAME
+			": %s(): Unable to register resource"
+			" 0x%.08llx-0x%.08llx - kernel bug?\n",
+			__func__,
+			(unsigned long long)window->rsrc.start,
+			(unsigned long long)window->rsrc.end);
+	}
+
+	/* Map the firmware hub into my address space. */
+	window->virt = ioremap_nocache(window->phys, window->size);
+	if (!window->virt) {
+		printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
+			window->phys, window->size);
+		goto out;
+	}
+
+	/* Get the first address to look for an rom chip at */
+	map_top = window->phys;
+	if ((window->phys & 0x3fffff) != 0) {
+		/* if not aligned on 4MiB, look 4MiB lower in address space */
+		map_top = window->phys + 0x400000;
+	}
+#if 1
+	/* The probe sequence run over the firmware hub lock
+	 * registers sets them to 0x7 (no access).
+	 * (Insane hardware design, but most copied Intel's.)
+	 * ==> Probe at most the last 4M of the address space.
+	 */
+	if (map_top < 0xffc00000)
+		map_top = 0xffc00000;
+#endif
+	/* Loop through and look for rom chips */
+	while ((map_top - 1) < 0xffffffffUL) {
+		struct cfi_private *cfi;
+		unsigned long offset;
+		int i;
+
+		if (!map)
+			map = kmalloc(sizeof(*map), GFP_KERNEL);
+		if (!map) {
+			printk(KERN_ERR MOD_NAME ": kmalloc failed");
+			goto out;
+		}
+		memset(map, 0, sizeof(*map));
+		INIT_LIST_HEAD(&map->list);
+		map->map.name = map->map_name;
+		map->map.phys = map_top;
+		offset = map_top - window->phys;
+		map->map.virt = (void __iomem *)
+			(((unsigned long)(window->virt)) + offset);
+		map->map.size = 0xffffffffUL - map_top + 1UL;
+		/* Set the name of the map to the address I am trying */
+		sprintf(map->map_name, "%s @%08lx",
+			MOD_NAME, map->map.phys);
+
+		/* Firmware hubs only use vpp when being programmed
+		 * in a factory setting.  So in-place programming
+		 * needs to use a different method.
+		 */
+		for(map->map.bankwidth = 32; map->map.bankwidth;
+			map->map.bankwidth >>= 1) {
+			char **probe_type;
+			/* Skip bankwidths that are not supported */
+			if (!map_bankwidth_supported(map->map.bankwidth))
+				continue;
+
+			/* Setup the map methods */
+			simple_map_init(&map->map);
+
+			/* Try all of the probe methods */
+			probe_type = rom_probe_types;
+			for(; *probe_type; probe_type++) {
+				map->mtd = do_map_probe(*probe_type, &map->map);
+				if (map->mtd)
+					goto found;
+			}
+		}
+		map_top += ROM_PROBE_STEP_SIZE;
+		continue;
+	found:
+		/* Trim the size if we are larger than the map */
+		if (map->mtd->size > map->map.size) {
+			printk(KERN_WARNING MOD_NAME
+				" rom(%u) larger than window(%lu). fixing...\n",
+				map->mtd->size, map->map.size);
+			map->mtd->size = map->map.size;
+		}
+		if (window->rsrc.parent) {
+			/*
+			 * Registering the MTD device in iomem may not be possible
+			 * if there is a BIOS "reserved" and BUSY range.  If this
+			 * fails then continue anyway.
+			 */
+			map->rsrc.name  = map->map_name;
+			map->rsrc.start = map->map.phys;
+			map->rsrc.end   = map->map.phys + map->mtd->size - 1;
+			map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+			if (request_resource(&window->rsrc, &map->rsrc)) {
+				printk(KERN_ERR MOD_NAME
+					": cannot reserve MTD resource\n");
+				map->rsrc.parent = NULL;
+			}
+		}
+
+		/* Make the whole region visible in the map */
+		map->map.virt = window->virt;
+		map->map.phys = window->phys;
+		cfi = map->map.fldrv_priv;
+		for(i = 0; i < cfi->numchips; i++)
+			cfi->chips[i].start += offset;
+
+		/* Now that the mtd devices is complete claim and export it */
+		map->mtd->owner = THIS_MODULE;
+		if (add_mtd_device(map->mtd)) {
+			map_destroy(map->mtd);
+			map->mtd = NULL;
+			goto out;
+		}
+
+		/* Calculate the new value of map_top */
+		map_top += map->mtd->size;
+
+		/* File away the map structure */
+		list_add(&map->list, &window->maps);
+		map = NULL;
+	}
+
+ out:
+	/* Free any left over map structures */
+	kfree(map);
+
+	/* See if I have any map structures */
+	if (list_empty(&window->maps)) {
+		esb2rom_cleanup(window);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __devexit esb2rom_remove_one (struct pci_dev *pdev)
+{
+	struct esb2rom_window *window = &esb2rom_window;
+	esb2rom_cleanup(window);
+}
+
+static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
+	  PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+	  PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
+	  PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
+	  PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
+	  PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
+	  PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0, },
+};
+
+#if 0
+MODULE_DEVICE_TABLE(pci, esb2rom_pci_tbl);
+
+static struct pci_driver esb2rom_driver = {
+	.name =		MOD_NAME,
+	.id_table =	esb2rom_pci_tbl,
+	.probe =	esb2rom_init_one,
+	.remove =	esb2rom_remove_one,
+};
+#endif
+
+static int __init init_esb2rom(void)
+{
+	struct pci_dev *pdev;
+	struct pci_device_id *id;
+	int retVal;
+
+	pdev = NULL;
+	for (id = esb2rom_pci_tbl; id->vendor; id++) {
+		printk(KERN_DEBUG "device id = %x\n", id->device);
+		pdev = pci_get_device(id->vendor, id->device, NULL);
+		if (pdev) {
+			printk(KERN_DEBUG "matched device = %x\n", id->device);
+			break;
+		}
+	}
+	if (pdev) {
+		printk(KERN_DEBUG "matched device id %x\n", id->device);
+		retVal = esb2rom_init_one(pdev, &esb2rom_pci_tbl[0]);
+		pci_dev_put(pdev);
+		printk(KERN_DEBUG "retVal = %d\n", retVal);
+		return retVal;
+	}
+	return -ENXIO;
+#if 0
+	return pci_register_driver(&esb2rom_driver);
+#endif
+}
+
+static void __exit cleanup_esb2rom(void)
+{
+	esb2rom_remove_one(esb2rom_window.pdev);
+}
+
+module_init(init_esb2rom);
+module_exit(cleanup_esb2rom);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lew Glendenning <lglendenning@lnxi.com>");
+MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ESB2 southbridge");
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index c8db01b..6946d80 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -75,14 +75,12 @@
 	int err;
 	void __iomem *base;
 
-	info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL);
 	if (!info) {
 		err = -ENOMEM;
 		goto out;
 	}
 
-	memset(info, 0, sizeof(struct armflash_info));
-
 	info->plat = plat;
 	if (plat && plat->init) {
 		err = plat->init();
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index f9e8e5b..9f53c65 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -20,6 +20,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/cfi.h>
 #include <linux/reboot.h>
+#include <linux/err.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 #include <asm/io.h>
@@ -178,7 +179,7 @@
 
 	init_waitqueue_head(&wait_q);
 	mtd = get_mtd_device(NULL, 2);
-	if (mtd) {
+	if (!IS_ERR(mtd)) {
 		nettel_erase.mtd = mtd;
 		nettel_erase.callback = nettel_erasecallback;
 		nettel_erase.callback = NULL;
@@ -471,7 +472,7 @@
 	iounmap(nettel_amd_map.virt);
 
 	return(rc);
-		
+
 }
 
 /****************************************************************************/
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index 418afff..e8d9ae5 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -78,12 +78,10 @@
 	struct resource *res = pdev->resource;
 	unsigned long size = res->end - res->start + 1;
 
-	info = kmalloc(sizeof(struct omapflash_info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct omapflash_info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	memset(info, 0, sizeof(struct omapflash_info));
-
 	if (!request_mem_region(res->start, size, "flash")) {
 		err = -EBUSY;
 		goto out_free_info;
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 995347b..eaeb56a 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -735,11 +735,10 @@
 	struct pcmciamtd_dev *dev;
 
 	/* Create new memory card device */
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) return -ENOMEM;
 	DEBUG(1, "dev=0x%p", dev);
 
-	memset(dev, 0, sizeof(*dev));
 	dev->p_dev = link;
 	link->priv = dev;
 
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index d171776..28c5ffd 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -89,15 +89,14 @@
 		return -ENODEV;
 
        	printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
-	    (unsigned long long)dev->resource->end - dev->resource->start + 1,
+	    (unsigned long long)(dev->resource->end - dev->resource->start + 1),
 	    (unsigned long long)dev->resource->start);
 
-	info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
 	if (info == NULL) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	memset(info, 0, sizeof(*info));
 
 	platform_set_drvdata(dev, info);
 
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
new file mode 100644
index 0000000..7efe744
--- /dev/null
+++ b/drivers/mtd/maps/physmap_of.c
@@ -0,0 +1,255 @@
+/*
+ * Normal mappings of chips in physical memory for OF devices
+ *
+ * Copyright (C) 2006 MontaVista Software Inc.
+ * Author: Vitaly Wool <vwool@ru.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.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+
+struct physmap_flash_info {
+	struct mtd_info		*mtd;
+	struct map_info		map;
+	struct resource		*res;
+#ifdef CONFIG_MTD_PARTITIONS
+	int			nr_parts;
+	struct mtd_partition	*parts;
+#endif
+};
+
+static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+static int parse_flash_partitions(struct device_node *node,
+		struct mtd_partition **parts)
+{
+	int i, plen, retval = -ENOMEM;
+	const  u32  *part;
+	const  char *name;
+
+	part = get_property(node, "partitions", &plen);
+	if (part == NULL)
+		goto err;
+
+	retval = plen / (2 * sizeof(u32));
+	*parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL);
+	if (*parts == NULL) {
+		printk(KERN_ERR "Can't allocate the flash partition data!\n");
+		goto err;
+	}
+
+	name = get_property(node, "partition-names", &plen);
+
+	for (i = 0; i < retval; i++) {
+		(*parts)[i].offset = *part++;
+		(*parts)[i].size   = *part & ~1;
+		if (*part++ & 1) /* bit 0 set signifies read only partition */
+			(*parts)[i].mask_flags = MTD_WRITEABLE;
+
+		if (name != NULL && plen > 0) {
+			int len = strlen(name) + 1;
+
+			(*parts)[i].name = (char *)name;
+			plen -= len;
+			name += len;
+		} else
+			(*parts)[i].name = "unnamed";
+	}
+err:
+	return retval;
+}
+#endif
+
+static int of_physmap_remove(struct of_device *dev)
+{
+	struct physmap_flash_info *info;
+
+	info = dev_get_drvdata(&dev->dev);
+	if (info == NULL)
+		return 0;
+	dev_set_drvdata(&dev->dev, NULL);
+
+	if (info->mtd != NULL) {
+#ifdef CONFIG_MTD_PARTITIONS
+		if (info->nr_parts) {
+			del_mtd_partitions(info->mtd);
+			kfree(info->parts);
+		} else {
+			del_mtd_device(info->mtd);
+		}
+#else
+		del_mtd_device(info->mtd);
+#endif
+		map_destroy(info->mtd);
+	}
+
+	if (info->map.virt != NULL)
+		iounmap(info->map.virt);
+
+	if (info->res != NULL) {
+		release_resource(info->res);
+		kfree(info->res);
+	}
+
+	return 0;
+}
+
+static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct device_node *dp = dev->node;
+	struct resource res;
+	struct physmap_flash_info *info;
+	const char **probe_type;
+	const char *of_probe;
+	const u32 *width;
+	int err;
+
+
+	if (of_address_to_resource(dp, 0, &res)) {
+		dev_err(&dev->dev, "Can't get the flash mapping!\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+
+       	dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n",
+	    (unsigned long long)res.end - res.start + 1,
+	    (unsigned long long)res.start);
+
+	info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+	if (info == NULL) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	memset(info, 0, sizeof(*info));
+
+	dev_set_drvdata(&dev->dev, info);
+
+	info->res = request_mem_region(res.start, res.end - res.start + 1,
+			dev->dev.bus_id);
+	if (info->res == NULL) {
+		dev_err(&dev->dev, "Could not reserve memory region\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	width = get_property(dp, "bank-width", NULL);
+	if (width == NULL) {
+		dev_err(&dev->dev, "Can't get the flash bank width!\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	info->map.name = dev->dev.bus_id;
+	info->map.phys = res.start;
+	info->map.size = res.end - res.start + 1;
+	info->map.bankwidth = *width;
+
+	info->map.virt = ioremap(info->map.phys, info->map.size);
+	if (info->map.virt == NULL) {
+		dev_err(&dev->dev, "Failed to ioremap flash region\n");
+		err = EIO;
+		goto err_out;
+	}
+
+	simple_map_init(&info->map);
+
+	of_probe = get_property(dp, "probe-type", NULL);
+	if (of_probe == NULL) {
+		probe_type = rom_probe_types;
+		for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
+			info->mtd = do_map_probe(*probe_type, &info->map);
+	} else if (!strcmp(of_probe, "CFI"))
+		info->mtd = do_map_probe("cfi_probe", &info->map);
+	else if (!strcmp(of_probe, "JEDEC"))
+		info->mtd = do_map_probe("jedec_probe", &info->map);
+	else {
+ 		if (strcmp(of_probe, "ROM"))
+			dev_dbg(&dev->dev, "map_probe: don't know probe type "
+			"'%s', mapping as rom\n");
+		info->mtd = do_map_probe("mtd_rom", &info->map);
+	}
+	if (info->mtd == NULL) {
+		dev_err(&dev->dev, "map_probe failed\n");
+		err = -ENXIO;
+		goto err_out;
+	}
+	info->mtd->owner = THIS_MODULE;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
+	if (err > 0) {
+		add_mtd_partitions(info->mtd, info->parts, err);
+	} else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) {
+		dev_info(&dev->dev, "Using OF partition information\n");
+		add_mtd_partitions(info->mtd, info->parts, err);
+		info->nr_parts = err;
+	} else
+#endif
+
+	add_mtd_device(info->mtd);
+	return 0;
+
+err_out:
+	of_physmap_remove(dev);
+	return err;
+
+	return 0;
+
+
+}
+
+static struct of_device_id of_physmap_match[] = {
+	{
+		.type		= "rom",
+		.compatible	= "direct-mapped"
+	},
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, of_physmap_match);
+
+
+static struct of_platform_driver of_physmap_flash_driver = {
+	.name		= "physmap-flash",
+	.match_table	= of_physmap_match,
+	.probe		= of_physmap_probe,
+	.remove		= of_physmap_remove,
+};
+
+static int __init of_physmap_init(void)
+{
+	return of_register_platform_driver(&of_physmap_flash_driver);
+}
+
+static void __exit of_physmap_exit(void)
+{
+	of_unregister_platform_driver(&of_physmap_flash_driver);
+}
+
+module_init(of_physmap_init);
+module_exit(of_physmap_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
+MODULE_DESCRIPTION("Configurable MTD map driver for OF");
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 5d3c754..2b6504e 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -147,14 +147,13 @@
 
 	pdata = pdev->dev.platform_data;
 
-	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (info == NULL) {
 		dev_err(&pdev->dev, "no memory for flash info\n");
 		err = -ENOMEM;
 		goto exit_error;
 	}
 
-	memset(info, 0, sizeof(*info));
 	platform_set_drvdata(pdev, info);
 
 	info->dev = &pdev->dev;
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 950bf1c..f904e6b 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -273,14 +273,12 @@
 	/*
 	 * Allocate the map_info structs in one go.
 	 */
-	info = kmalloc(size, GFP_KERNEL);
+	info = kzalloc(size, GFP_KERNEL);
 	if (!info) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	memset(info, 0, size);
-
 	if (plat->init) {
 		ret = plat->init();
 		if (ret)
diff --git a/drivers/mtd/maps/tqm834x.c b/drivers/mtd/maps/tqm834x.c
index 58e5912..9adc970 100644
--- a/drivers/mtd/maps/tqm834x.c
+++ b/drivers/mtd/maps/tqm834x.c
@@ -132,20 +132,16 @@
 
 		pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx);
 
-		map_banks[idx] =
-			(struct map_info *)kmalloc(sizeof(struct map_info),
-						   GFP_KERNEL);
+		map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
 		if (map_banks[idx] == NULL) {
 			ret = -ENOMEM;
 			goto error_mem;
 		}
-		memset((void *)map_banks[idx], 0, sizeof(struct map_info));
-		map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
+		map_banks[idx]->name = kzalloc(16, GFP_KERNEL);
 		if (map_banks[idx]->name == NULL) {
 			ret = -ENOMEM;
 			goto error_mem;
 		}
-		memset((void *)map_banks[idx]->name, 0, 16);
 
 		sprintf(map_banks[idx]->name, "TQM834x-%d", idx);
 		map_banks[idx]->size = flash_size;
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 19578ba..37e4ded 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -134,14 +134,13 @@
 
 		printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
 
-		map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL);
+		map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
 		if(map_banks[idx] == NULL) {
 			ret = -ENOMEM;
 			/* FIXME: What if some MTD devices were probed already? */
 			goto error_mem;
 		}
 
-		memset((void *)map_banks[idx], 0, sizeof(struct map_info));
 		map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
 
 		if (!map_banks[idx]->name) {
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 178b53b..b879a66 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -42,19 +42,20 @@
 	unsigned long block, nsect;
 	char *buf;
 
-	block = req->sector;
-	nsect = req->current_nr_sectors;
+	block = req->sector << 9 >> tr->blkshift;
+	nsect = req->current_nr_sectors << 9 >> tr->blkshift;
+
 	buf = req->buffer;
 
 	if (!blk_fs_request(req))
 		return 0;
 
-	if (block + nsect > get_capacity(req->rq_disk))
+	if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk))
 		return 0;
 
 	switch(rq_data_dir(req)) {
 	case READ:
-		for (; nsect > 0; nsect--, block++, buf += 512)
+		for (; nsect > 0; nsect--, block++, buf += tr->blksize)
 			if (tr->readsect(dev, block, buf))
 				return 0;
 		return 1;
@@ -63,7 +64,7 @@
 		if (!tr->writesect)
 			return 0;
 
-		for (; nsect > 0; nsect--, block++, buf += 512)
+		for (; nsect > 0; nsect--, block++, buf += tr->blksize)
 			if (tr->writesect(dev, block, buf))
 				return 0;
 		return 1;
@@ -297,7 +298,7 @@
 
 	/* 2.5 has capacity in units of 512 bytes while still
 	   having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
-	set_capacity(gd, (new->size * new->blksize) >> 9);
+	set_capacity(gd, (new->size * tr->blksize) >> 9);
 
 	gd->private_data = new;
 	new->blkcore_priv = gd;
@@ -372,12 +373,10 @@
 	if (!blktrans_notifier.list.next)
 		register_mtd_user(&blktrans_notifier);
 
-	tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
+	tr->blkcore_priv = kzalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
 	if (!tr->blkcore_priv)
 		return -ENOMEM;
 
-	memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
-
 	mutex_lock(&mtd_table_mutex);
 
 	ret = register_blkdev(tr->major, tr->name);
@@ -401,6 +400,8 @@
 	}
 
 	tr->blkcore_priv->rq->queuedata = tr;
+	blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
+	tr->blkshift = ffs(tr->blksize) - 1;
 
 	ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL);
 	if (ret < 0) {
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 04ed3469..952da30 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -278,11 +278,10 @@
 	}
 
 	/* OK, it's not open. Create cache info for it */
-	mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
+	mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
 	if (!mtdblk)
 		return -ENOMEM;
 
-	memset(mtdblk, 0, sizeof(*mtdblk));
 	mtdblk->count = 1;
 	mtdblk->mtd = mtd;
 
@@ -339,16 +338,14 @@
 
 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 {
-	struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 
 	if (!dev)
 		return;
 
-	memset(dev, 0, sizeof(*dev));
-
 	dev->mtd = mtd;
 	dev->devnum = mtd->index;
-	dev->blksize = 512;
+
 	dev->size = mtd->size >> 9;
 	dev->tr = tr;
 
@@ -368,6 +365,7 @@
 	.name		= "mtdblock",
 	.major		= 31,
 	.part_bits	= 0,
+	.blksize 	= 512,
 	.open		= mtdblock_open,
 	.flush		= mtdblock_flush,
 	.release	= mtdblock_release,
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index 29563ed..f79dbb4 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -33,16 +33,14 @@
 
 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 {
-	struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 
 	if (!dev)
 		return;
 
-	memset(dev, 0, sizeof(*dev));
-
 	dev->mtd = mtd;
 	dev->devnum = mtd->index;
-	dev->blksize = 512;
+
 	dev->size = mtd->size >> 9;
 	dev->tr = tr;
 	dev->readonly = 1;
@@ -60,6 +58,7 @@
 	.name		= "mtdblock",
 	.major		= 31,
 	.part_bits	= 0,
+	.blksize 	= 512,
 	.readsect	= mtdblock_readsect,
 	.writesect	= mtdblock_writesect,
 	.add_mtd	= mtdblock_add_mtd,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 5b6acfc..3013d08 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -7,6 +7,7 @@
 
 #include <linux/device.h>
 #include <linux/fs.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -100,8 +101,8 @@
 
 	mtd = get_mtd_device(NULL, devnum);
 
-	if (!mtd)
-		return -ENODEV;
+	if (IS_ERR(mtd))
+		return PTR_ERR(mtd);
 
 	if (MTD_ABSENT == mtd->type) {
 		put_mtd_device(mtd);
@@ -431,7 +432,7 @@
 		if(!(file->f_mode & 2))
 			return -EPERM;
 
-		erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL);
+		erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
 		if (!erase)
 			ret = -ENOMEM;
 		else {
@@ -440,7 +441,6 @@
 
 			init_waitqueue_head(&waitq);
 
-			memset (erase,0,sizeof(struct erase_info));
 			if (copy_from_user(&erase->addr, argp,
 				    sizeof(struct erase_info_user))) {
 				kfree(erase);
@@ -499,13 +499,12 @@
 		if (ret)
 			return ret;
 
-		ops.len = buf.length;
 		ops.ooblen = buf.length;
 		ops.ooboffs = buf.start & (mtd->oobsize - 1);
 		ops.datbuf = NULL;
 		ops.mode = MTD_OOB_PLACE;
 
-		if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs))
+		if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 			return -EINVAL;
 
 		ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
@@ -520,7 +519,7 @@
 		buf.start &= ~(mtd->oobsize - 1);
 		ret = mtd->write_oob(mtd, buf.start, &ops);
 
-		if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen,
+		if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen,
 				 sizeof(uint32_t)))
 			ret = -EFAULT;
 
@@ -548,7 +547,6 @@
 		if (ret)
 			return ret;
 
-		ops.len = buf.length;
 		ops.ooblen = buf.length;
 		ops.ooboffs = buf.start & (mtd->oobsize - 1);
 		ops.datbuf = NULL;
@@ -564,10 +562,10 @@
 		buf.start &= ~(mtd->oobsize - 1);
 		ret = mtd->read_oob(mtd, buf.start, &ops);
 
-		if (put_user(ops.retlen, (uint32_t __user *)argp))
+		if (put_user(ops.oobretlen, (uint32_t __user *)argp))
 			ret = -EFAULT;
-		else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf,
-						    ops.retlen))
+		else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf,
+						    ops.oobretlen))
 			ret = -EFAULT;
 
 		kfree(ops.oobbuf);
@@ -616,6 +614,7 @@
 		memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
 		memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
 		       sizeof(oi.oobfree));
+		oi.eccbytes = mtd->ecclayout->eccbytes;
 
 		if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
 			return -EFAULT;
@@ -715,7 +714,7 @@
 		if (!mtd->ecclayout)
 			return -EOPNOTSUPP;
 
-		if (copy_to_user(argp, &mtd->ecclayout,
+		if (copy_to_user(argp, mtd->ecclayout,
 				 sizeof(struct nand_ecclayout)))
 			return -EFAULT;
 		break;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 1fea631..0690268 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -247,7 +247,7 @@
 	struct mtd_oob_ops devops = *ops;
 	int i, err, ret = 0;
 
-	ops->retlen = 0;
+	ops->retlen = ops->oobretlen = 0;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
@@ -263,6 +263,7 @@
 
 		err = subdev->read_oob(subdev, from, &devops);
 		ops->retlen += devops.retlen;
+		ops->oobretlen += devops.oobretlen;
 
 		/* Save information about bitflips! */
 		if (unlikely(err)) {
@@ -278,14 +279,18 @@
 				return err;
 		}
 
-		devops.len = ops->len - ops->retlen;
-		if (!devops.len)
-			return ret;
-
-		if (devops.datbuf)
+		if (devops.datbuf) {
+			devops.len = ops->len - ops->retlen;
+			if (!devops.len)
+				return ret;
 			devops.datbuf += devops.retlen;
-		if (devops.oobbuf)
-			devops.oobbuf += devops.ooblen;
+		}
+		if (devops.oobbuf) {
+			devops.ooblen = ops->ooblen - ops->oobretlen;
+			if (!devops.ooblen)
+				return ret;
+			devops.oobbuf += ops->oobretlen;
+		}
 
 		from = 0;
 	}
@@ -321,14 +326,18 @@
 		if (err)
 			return err;
 
-		devops.len = ops->len - ops->retlen;
-		if (!devops.len)
-			return 0;
-
-		if (devops.datbuf)
+		if (devops.datbuf) {
+			devops.len = ops->len - ops->retlen;
+			if (!devops.len)
+				return 0;
 			devops.datbuf += devops.retlen;
-		if (devops.oobbuf)
-			devops.oobbuf += devops.ooblen;
+		}
+		if (devops.oobbuf) {
+			devops.ooblen = ops->ooblen - ops->oobretlen;
+			if (!devops.ooblen)
+				return 0;
+			devops.oobbuf += devops.oobretlen;
+		}
 		to = 0;
 	}
 	return -EINVAL;
@@ -699,14 +708,13 @@
 
 	/* allocate the device structure */
 	size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
-	concat = kmalloc(size, GFP_KERNEL);
+	concat = kzalloc(size, GFP_KERNEL);
 	if (!concat) {
 		printk
 		    ("memory allocation error while creating concatenated device \"%s\"\n",
 		     name);
 		return NULL;
 	}
-	memset(concat, 0, size);
 	concat->subdev = (struct mtd_info **) (concat + 1);
 
 	/*
@@ -764,6 +772,7 @@
 		concat->mtd.ecc_stats.badblocks +=
 			subdev[i]->ecc_stats.badblocks;
 		if (concat->mtd.writesize   !=  subdev[i]->writesize ||
+		    concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
 		    concat->mtd.oobsize    !=  subdev[i]->oobsize ||
 		    concat->mtd.ecctype    !=  subdev[i]->ecctype ||
 		    concat->mtd.eccsize    !=  subdev[i]->eccsize ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c4d26de..7070110 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -15,6 +15,7 @@
 #include <linux/timer.h>
 #include <linux/major.h>
 #include <linux/fs.h>
+#include <linux/err.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <linux/mtd/compatmac.h>
@@ -192,14 +193,14 @@
  *	Given a number and NULL address, return the num'th entry in the device
  *	table, if any.	Given an address and num == -1, search the device table
  *	for a device with that address and return if it's still present. Given
- *	both, return the num'th driver only if its address matches. Return NULL
- *	if not.
+ *	both, return the num'th driver only if its address matches. Return
+ *	error code if not.
  */
 
 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
 {
 	struct mtd_info *ret = NULL;
-	int i;
+	int i, err = -ENODEV;
 
 	mutex_lock(&mtd_table_mutex);
 
@@ -213,14 +214,73 @@
 			ret = NULL;
 	}
 
-	if (ret && !try_module_get(ret->owner))
-		ret = NULL;
+	if (!ret)
+		goto out_unlock;
 
-	if (ret)
-		ret->usecount++;
+	if (!try_module_get(ret->owner))
+		goto out_unlock;
 
+	if (ret->get_device) {
+		err = ret->get_device(ret);
+		if (err)
+			goto out_put;
+	}
+
+	ret->usecount++;
 	mutex_unlock(&mtd_table_mutex);
 	return ret;
+
+out_put:
+	module_put(ret->owner);
+out_unlock:
+	mutex_unlock(&mtd_table_mutex);
+	return ERR_PTR(err);
+}
+
+/**
+ *	get_mtd_device_nm - obtain a validated handle for an MTD device by
+ *	device name
+ *	@name: MTD device name to open
+ *
+ * 	This function returns MTD device description structure in case of
+ * 	success and an error code in case of failure.
+ */
+
+struct mtd_info *get_mtd_device_nm(const char *name)
+{
+	int i, err = -ENODEV;
+	struct mtd_info *mtd = NULL;
+
+	mutex_lock(&mtd_table_mutex);
+
+	for (i = 0; i < MAX_MTD_DEVICES; i++) {
+		if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
+			mtd = mtd_table[i];
+			break;
+		}
+	}
+
+	if (!mtd)
+		goto out_unlock;
+
+	if (!try_module_get(mtd->owner))
+		goto out_unlock;
+
+	if (mtd->get_device) {
+		err = mtd->get_device(mtd);
+		if (err)
+			goto out_put;
+	}
+
+	mtd->usecount++;
+	mutex_unlock(&mtd_table_mutex);
+	return mtd;
+
+out_put:
+	module_put(mtd->owner);
+out_unlock:
+	mutex_unlock(&mtd_table_mutex);
+	return ERR_PTR(err);
 }
 
 void put_mtd_device(struct mtd_info *mtd)
@@ -229,6 +289,8 @@
 
 	mutex_lock(&mtd_table_mutex);
 	c = --mtd->usecount;
+	if (mtd->put_device)
+		mtd->put_device(mtd);
 	mutex_unlock(&mtd_table_mutex);
 	BUG_ON(c < 0);
 
@@ -236,7 +298,7 @@
 }
 
 /* default_mtd_writev - default mtd writev method for MTD devices that
- *			dont implement their own
+ *			don't implement their own
  */
 
 int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
@@ -264,13 +326,14 @@
 	return ret;
 }
 
-EXPORT_SYMBOL(add_mtd_device);
-EXPORT_SYMBOL(del_mtd_device);
-EXPORT_SYMBOL(get_mtd_device);
-EXPORT_SYMBOL(put_mtd_device);
-EXPORT_SYMBOL(register_mtd_user);
-EXPORT_SYMBOL(unregister_mtd_user);
-EXPORT_SYMBOL(default_mtd_writev);
+EXPORT_SYMBOL_GPL(add_mtd_device);
+EXPORT_SYMBOL_GPL(del_mtd_device);
+EXPORT_SYMBOL_GPL(get_mtd_device);
+EXPORT_SYMBOL_GPL(get_mtd_device_nm);
+EXPORT_SYMBOL_GPL(put_mtd_device);
+EXPORT_SYMBOL_GPL(register_mtd_user);
+EXPORT_SYMBOL_GPL(unregister_mtd_user);
+EXPORT_SYMBOL_GPL(default_mtd_writev);
 
 #ifdef CONFIG_PROC_FS
 
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 06a9303..bafd2fb 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -94,7 +94,7 @@
 
 	if (from >= mtd->size)
 		return -EINVAL;
-	if (from + ops->len > mtd->size)
+	if (ops->datbuf && from + ops->len > mtd->size)
 		return -EINVAL;
 	res = part->master->read_oob(part->master, from + part->offset, ops);
 
@@ -161,7 +161,7 @@
 
 	if (to >= mtd->size)
 		return -EINVAL;
-	if (to + ops->len > mtd->size)
+	if (ops->datbuf && to + ops->len > mtd->size)
 		return -EINVAL;
 	return part->master->write_oob(part->master, to + part->offset, ops);
 }
@@ -323,14 +323,13 @@
 	for (i = 0; i < nbparts; i++) {
 
 		/* allocate the partition structure */
-		slave = kmalloc (sizeof(*slave), GFP_KERNEL);
+		slave = kzalloc (sizeof(*slave), GFP_KERNEL);
 		if (!slave) {
 			printk ("memory allocation error while creating partitions for \"%s\"\n",
 				master->name);
 			del_mtd_partitions(master);
 			return -ENOMEM;
 		}
-		memset(slave, 0, sizeof(*slave));
 		list_add(&slave->list, &mtd_partitions);
 
 		/* set up the MTD object for this partition */
@@ -341,6 +340,7 @@
 		slave->mtd.oobsize = master->oobsize;
 		slave->mtd.ecctype = master->ecctype;
 		slave->mtd.eccsize = master->eccsize;
+		slave->mtd.subpage_sft = master->subpage_sft;
 
 		slave->mtd.name = parts[i].name;
 		slave->mtd.bank_size = master->bank_size;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1831340..358f55a 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -90,6 +90,7 @@
 	depends on MTD_NAND && SH_SOLUTION_ENGINE
 	select REED_SOLOMON
 	select REED_SOLOMON_DEC8
+	select BITREVERSE
 	help
 	  This enables the driver for the Renesas Technology AG-AND
 	  flash interface board (FROM_BOARD4)
@@ -132,6 +133,7 @@
 config MTD_NAND_NDFC
 	tristate "NDFC NanD Flash Controller"
 	depends on MTD_NAND && 44x
+	select MTD_NAND_ECC_SMC
 	help
 	 NDFC Nand Flash Controllers are integrated in EP44x SoCs
 
@@ -219,6 +221,13 @@
 	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
 	depends on MTD_NAND && ARCH_PXA
 
+config MTD_NAND_CAFE
+       tristate "NAND support for OLPC CAFÉ chip"
+       depends on PCI
+       help
+	 Use NAND flash attached to the CAFÉ chip designed for the $100
+	 laptop.
+
 config MTD_NAND_CS553X
 	tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
 	depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
@@ -232,6 +241,13 @@
 
 	  If you say "m", the module will be called "cs553x_nand.ko".
 
+config MTD_NAND_AT91
+	bool "Support for NAND Flash / SmartMedia on AT91"
+	depends on MTD_NAND && ARCH_AT91
+	help
+	  Enables support for NAND Flash / Smart Media Card interface
+	  on Atmel AT91 processors.
+
 config MTD_NAND_NANDSIM
 	tristate "Support for NAND Flash Simulator"
 	depends on MTD_NAND && MTD_PARTITIONS
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index f747593..f7a53f0 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_MTD_NAND)			+= nand.o nand_ecc.o
 obj-$(CONFIG_MTD_NAND_IDS)		+= nand_ids.o
 
+obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
 obj-$(CONFIG_MTD_NAND_SPIA)		+= spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_TOTO)		+= toto.o
@@ -22,5 +23,7 @@
 obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
 obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
+obj-$(CONFIG_MTD_NAND_AT91)		+= at91_nand.o
 
-nand-objs = nand_base.o nand_bbt.o
+nand-objs := nand_base.o nand_bbt.o
+cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
new file mode 100644
index 0000000..14b80cc
--- /dev/null
+++ b/drivers/mtd/nand/at91_nand.c
@@ -0,0 +1,223 @@
+/*
+ * drivers/mtd/nand/at91_nand.c
+ *
+ *  Copyright (C) 2003 Rick Bronson
+ *
+ *  Derived from drivers/mtd/nand/autcpu12.c
+ *	 Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ *  Derived from drivers/mtd/spia.c
+ *	 Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+struct at91_nand_host {
+	struct nand_chip	nand_chip;
+	struct mtd_info		mtd;
+	void __iomem		*io_base;
+	struct at91_nand_data	*board;
+};
+
+/*
+ * Hardware specific access to control-lines
+ */
+static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct at91_nand_host *host = nand_chip->priv;
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE)
+		writeb(cmd, host->io_base + (1 << host->board->cle));
+	else
+		writeb(cmd, host->io_base + (1 << host->board->ale));
+}
+
+/*
+ * Read the Device Ready pin.
+ */
+static int at91_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct at91_nand_host *host = nand_chip->priv;
+
+	return at91_get_gpio_value(host->board->rdy_pin);
+}
+
+/*
+ * Enable NAND.
+ */
+static void at91_nand_enable(struct at91_nand_host *host)
+{
+	if (host->board->enable_pin)
+		at91_set_gpio_value(host->board->enable_pin, 0);
+}
+
+/*
+ * Disable NAND.
+ */
+static void at91_nand_disable(struct at91_nand_host *host)
+{
+	if (host->board->enable_pin)
+		at91_set_gpio_value(host->board->enable_pin, 1);
+}
+
+/*
+ * Probe for the NAND device.
+ */
+static int __init at91_nand_probe(struct platform_device *pdev)
+{
+	struct at91_nand_host *host;
+	struct mtd_info *mtd;
+	struct nand_chip *nand_chip;
+	int res;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *partitions = NULL;
+	int num_partitions = 0;
+#endif
+
+	/* Allocate memory for the device structure (and zero it) */
+	host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
+	if (!host) {
+		printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	host->io_base = ioremap(pdev->resource[0].start,
+				pdev->resource[0].end - pdev->resource[0].start + 1);
+	if (host->io_base == NULL) {
+		printk(KERN_ERR "at91_nand: ioremap failed\n");
+		kfree(host);
+		return -EIO;
+	}
+
+	mtd = &host->mtd;
+	nand_chip = &host->nand_chip;
+	host->board = pdev->dev.platform_data;
+
+	nand_chip->priv = host;		/* link the private data structures */
+	mtd->priv = nand_chip;
+	mtd->owner = THIS_MODULE;
+
+	/* Set address of NAND IO lines */
+	nand_chip->IO_ADDR_R = host->io_base;
+	nand_chip->IO_ADDR_W = host->io_base;
+	nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
+	nand_chip->dev_ready = at91_nand_device_ready;
+	nand_chip->ecc.mode = NAND_ECC_SOFT;	/* enable ECC */
+	nand_chip->chip_delay = 20;		/* 20us command delay time */
+
+	if (host->board->bus_width_16)		/* 16-bit bus width */
+		nand_chip->options |= NAND_BUSWIDTH_16;
+
+	platform_set_drvdata(pdev, host);
+	at91_nand_enable(host);
+
+	if (host->board->det_pin) {
+		if (at91_get_gpio_value(host->board->det_pin)) {
+			printk ("No SmartMedia card inserted.\n");
+			res = ENXIO;
+			goto out;
+		}
+	}
+
+	/* Scan to find existance of the device */
+	if (nand_scan(mtd, 1)) {
+		res = -ENXIO;
+		goto out;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	if (host->board->partition_info)
+		partitions = host->board->partition_info(mtd->size, &num_partitions);
+
+	if ((!partitions) || (num_partitions == 0)) {
+		printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
+		res = ENXIO;
+		goto release;
+	}
+
+	res = add_mtd_partitions(mtd, partitions, num_partitions);
+#else
+	res = add_mtd_device(mtd);
+#endif
+
+	if (!res)
+		return res;
+
+release:
+	nand_release(mtd);
+out:
+	at91_nand_disable(host);
+	platform_set_drvdata(pdev, NULL);
+	iounmap(host->io_base);
+	kfree(host);
+	return res;
+}
+
+/*
+ * Remove a NAND device.
+ */
+static int __devexit at91_nand_remove(struct platform_device *pdev)
+{
+	struct at91_nand_host *host = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = &host->mtd;
+
+	nand_release(mtd);
+
+	at91_nand_disable(host);
+
+	iounmap(host->io_base);
+	kfree(host);
+
+	return 0;
+}
+
+static struct platform_driver at91_nand_driver = {
+	.probe		= at91_nand_probe,
+	.remove		= at91_nand_remove,
+	.driver		= {
+		.name	= "at91_nand",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_nand_init(void)
+{
+	return platform_driver_register(&at91_nand_driver);
+}
+
+
+static void __exit at91_nand_exit(void)
+{
+	platform_driver_unregister(&at91_nand_driver);
+}
+
+
+module_init(at91_nand_init);
+module_exit(at91_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
new file mode 100644
index 0000000..65f9bd3
--- /dev/null
+++ b/drivers/mtd/nand/cafe.c
@@ -0,0 +1,771 @@
+/*
+ * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
+ *
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ */
+
+#define DEBUG
+
+#include <linux/device.h>
+#undef DEBUG
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+
+#define CAFE_NAND_CTRL1		0x00
+#define CAFE_NAND_CTRL2		0x04
+#define CAFE_NAND_CTRL3		0x08
+#define CAFE_NAND_STATUS	0x0c
+#define CAFE_NAND_IRQ		0x10
+#define CAFE_NAND_IRQ_MASK	0x14
+#define CAFE_NAND_DATA_LEN	0x18
+#define CAFE_NAND_ADDR1		0x1c
+#define CAFE_NAND_ADDR2		0x20
+#define CAFE_NAND_TIMING1	0x24
+#define CAFE_NAND_TIMING2	0x28
+#define CAFE_NAND_TIMING3	0x2c
+#define CAFE_NAND_NONMEM	0x30
+#define CAFE_NAND_ECC_RESULT	0x3C
+#define CAFE_NAND_DMA_CTRL	0x40
+#define CAFE_NAND_DMA_ADDR0	0x44
+#define CAFE_NAND_DMA_ADDR1	0x48
+#define CAFE_NAND_ECC_SYN01	0x50
+#define CAFE_NAND_ECC_SYN23	0x54
+#define CAFE_NAND_ECC_SYN45	0x58
+#define CAFE_NAND_ECC_SYN67	0x5c
+#define CAFE_NAND_READ_DATA	0x1000
+#define CAFE_NAND_WRITE_DATA	0x2000
+
+#define CAFE_GLOBAL_CTRL	0x3004
+#define CAFE_GLOBAL_IRQ		0x3008
+#define CAFE_GLOBAL_IRQ_MASK	0x300c
+#define CAFE_NAND_RESET		0x3034
+
+int cafe_correct_ecc(unsigned char *buf,
+		     unsigned short *chk_syndrome_list);
+
+struct cafe_priv {
+	struct nand_chip nand;
+	struct pci_dev *pdev;
+	void __iomem *mmio;
+	uint32_t ctl1;
+	uint32_t ctl2;
+	int datalen;
+	int nr_data;
+	int data_pos;
+	int page_addr;
+	dma_addr_t dmaaddr;
+	unsigned char *dmabuf;
+};
+
+static int usedma = 1;
+module_param(usedma, int, 0644);
+
+static int skipbbt = 0;
+module_param(skipbbt, int, 0644);
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+static int regdebug = 0;
+module_param(regdebug, int, 0644);
+
+static int checkecc = 1;
+module_param(checkecc, int, 0644);
+
+static int slowtiming = 0;
+module_param(slowtiming, int, 0644);
+
+/* Hrm. Why isn't this already conditional on something in the struct device? */
+#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
+
+/* Make it easier to switch to PIO if we need to */
+#define cafe_readl(cafe, addr)			readl((cafe)->mmio + CAFE_##addr)
+#define cafe_writel(cafe, datum, addr)		writel(datum, (cafe)->mmio + CAFE_##addr)
+
+static int cafe_device_ready(struct mtd_info *mtd)
+{
+	struct cafe_priv *cafe = mtd->priv;
+	int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000);
+	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
+
+	cafe_writel(cafe, irqs, NAND_IRQ);
+
+	cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
+		result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ),
+		cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK));
+
+	return result;
+}
+
+
+static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	struct cafe_priv *cafe = mtd->priv;
+
+	if (usedma)
+		memcpy(cafe->dmabuf + cafe->datalen, buf, len);
+	else
+		memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len);
+
+	cafe->datalen += len;
+
+	cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
+		len, cafe->datalen);
+}
+
+static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct cafe_priv *cafe = mtd->priv;
+
+	if (usedma)
+		memcpy(buf, cafe->dmabuf + cafe->datalen, len);
+	else
+		memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len);
+
+	cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
+		  len, cafe->datalen);
+	cafe->datalen += len;
+}
+
+static uint8_t cafe_read_byte(struct mtd_info *mtd)
+{
+	struct cafe_priv *cafe = mtd->priv;
+	uint8_t d;
+
+	cafe_read_buf(mtd, &d, 1);
+	cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
+
+	return d;
+}
+
+static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+			      int column, int page_addr)
+{
+	struct cafe_priv *cafe = mtd->priv;
+	int adrbytes = 0;
+	uint32_t ctl1;
+	uint32_t doneint = 0x80000000;
+
+	cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
+		command, column, page_addr);
+
+	if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
+		/* Second half of a command we already calculated */
+		cafe_writel(cafe, cafe->ctl2 | 0x100 | command, NAND_CTRL2);
+		ctl1 = cafe->ctl1;
+		cafe->ctl2 &= ~(1<<30);
+		cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
+			  cafe->ctl1, cafe->nr_data);
+		goto do_command;
+	}
+	/* Reset ECC engine */
+	cafe_writel(cafe, 0, NAND_CTRL2);
+
+	/* Emulate NAND_CMD_READOOB on large-page chips */
+	if (mtd->writesize > 512 &&
+	    command == NAND_CMD_READOOB) {
+		column += mtd->writesize;
+		command = NAND_CMD_READ0;
+	}
+
+	/* FIXME: Do we need to send read command before sending data
+	   for small-page chips, to position the buffer correctly? */
+
+	if (column != -1) {
+		cafe_writel(cafe, column, NAND_ADDR1);
+		adrbytes = 2;
+		if (page_addr != -1)
+			goto write_adr2;
+	} else if (page_addr != -1) {
+		cafe_writel(cafe, page_addr & 0xffff, NAND_ADDR1);
+		page_addr >>= 16;
+	write_adr2:
+		cafe_writel(cafe, page_addr, NAND_ADDR2);
+		adrbytes += 2;
+		if (mtd->size > mtd->writesize << 16)
+			adrbytes++;
+	}
+
+	cafe->data_pos = cafe->datalen = 0;
+
+	/* Set command valid bit */
+	ctl1 = 0x80000000 | command;
+
+	/* Set RD or WR bits as appropriate */
+	if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
+		ctl1 |= (1<<26); /* rd */
+		/* Always 5 bytes, for now */
+		cafe->datalen = 4;
+		/* And one address cycle -- even for STATUS, since the controller doesn't work without */
+		adrbytes = 1;
+	} else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
+		   command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) {
+		ctl1 |= 1<<26; /* rd */
+		/* For now, assume just read to end of page */
+		cafe->datalen = mtd->writesize + mtd->oobsize - column;
+	} else if (command == NAND_CMD_SEQIN)
+		ctl1 |= 1<<25; /* wr */
+
+	/* Set number of address bytes */
+	if (adrbytes)
+		ctl1 |= ((adrbytes-1)|8) << 27;
+
+	if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) {
+		/* Ignore the first command of a pair; the hardware
+		   deals with them both at once, later */
+		cafe->ctl1 = ctl1;
+		cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
+			  cafe->ctl1, cafe->datalen);
+		return;
+	}
+	/* RNDOUT and READ0 commands need a following byte */
+	if (command == NAND_CMD_RNDOUT)
+		cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_RNDOUTSTART, NAND_CTRL2);
+	else if (command == NAND_CMD_READ0 && mtd->writesize > 512)
+		cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_READSTART, NAND_CTRL2);
+
+ do_command:
+	cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
+		cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2));
+
+	/* NB: The datasheet lies -- we really should be subtracting 1 here */
+	cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN);
+	cafe_writel(cafe, 0x90000000, NAND_IRQ);
+	if (usedma && (ctl1 & (3<<25))) {
+		uint32_t dmactl = 0xc0000000 + cafe->datalen;
+		/* If WR or RD bits set, set up DMA */
+		if (ctl1 & (1<<26)) {
+			/* It's a read */
+			dmactl |= (1<<29);
+			/* ... so it's done when the DMA is done, not just
+			   the command. */
+			doneint = 0x10000000;
+		}
+		cafe_writel(cafe, dmactl, NAND_DMA_CTRL);
+	}
+	cafe->datalen = 0;
+
+	if (unlikely(regdebug)) {
+		int i;
+		printk("About to write command %08x to register 0\n", ctl1);
+		for (i=4; i< 0x5c; i+=4)
+			printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
+	}
+
+	cafe_writel(cafe, ctl1, NAND_CTRL1);
+	/* Apply this short delay always to ensure that we do wait tWB in
+	 * any case on any machine. */
+	ndelay(100);
+
+	if (1) {
+		int c = 500000;
+		uint32_t irqs;
+
+		while (c--) {
+			irqs = cafe_readl(cafe, NAND_IRQ);
+			if (irqs & doneint)
+				break;
+			udelay(1);
+			if (!(c % 100000))
+				cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
+			cpu_relax();
+		}
+		cafe_writel(cafe, doneint, NAND_IRQ);
+		cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
+			     command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
+	}
+
+	WARN_ON(cafe->ctl2 & (1<<30));
+
+	switch (command) {
+
+	case NAND_CMD_CACHEDPROG:
+	case NAND_CMD_PAGEPROG:
+	case NAND_CMD_ERASE1:
+	case NAND_CMD_ERASE2:
+	case NAND_CMD_SEQIN:
+	case NAND_CMD_RNDIN:
+	case NAND_CMD_STATUS:
+	case NAND_CMD_DEPLETE1:
+	case NAND_CMD_RNDOUT:
+	case NAND_CMD_STATUS_ERROR:
+	case NAND_CMD_STATUS_ERROR0:
+	case NAND_CMD_STATUS_ERROR1:
+	case NAND_CMD_STATUS_ERROR2:
+	case NAND_CMD_STATUS_ERROR3:
+		cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
+		return;
+	}
+	nand_wait_ready(mtd);
+	cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
+}
+
+static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
+{
+	//struct cafe_priv *cafe = mtd->priv;
+	//	cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+}
+
+static int cafe_nand_interrupt(int irq, void *id)
+{
+	struct mtd_info *mtd = id;
+	struct cafe_priv *cafe = mtd->priv;
+	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
+	cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
+	if (!irqs)
+		return IRQ_NONE;
+
+	cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
+	return IRQ_HANDLED;
+}
+
+static void cafe_nand_bug(struct mtd_info *mtd)
+{
+	BUG();
+}
+
+static int cafe_nand_write_oob(struct mtd_info *mtd,
+			       struct nand_chip *chip, int page)
+{
+	int status = 0;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	status = chip->waitfunc(mtd, chip);
+
+	return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+/* Don't use -- use nand_read_oob_std for now */
+static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			      int page, int sndcmd)
+{
+	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+	return 1;
+}
+/**
+ * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	buffer to store read data
+ *
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+			       uint8_t *buf)
+{
+	struct cafe_priv *cafe = mtd->priv;
+
+	cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
+		     cafe_readl(cafe, NAND_ECC_RESULT),
+		     cafe_readl(cafe, NAND_ECC_SYN01));
+
+	chip->read_buf(mtd, buf, mtd->writesize);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
+		unsigned short syn[8];
+		int i;
+
+		for (i=0; i<8; i+=2) {
+			uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
+			syn[i] = tmp & 0xfff;
+			syn[i+1] = (tmp >> 16) & 0xfff;
+		}
+
+		if ((i = cafe_correct_ecc(buf, syn)) < 0) {
+			dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
+				cafe_readl(cafe, NAND_ADDR2) * 2048);
+			for (i=0; i< 0x5c; i+=4)
+				printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
+			mtd->ecc_stats.failed++;
+		} else {
+			dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i);
+			mtd->ecc_stats.corrected += i;
+		}
+	}
+
+
+	return 0;
+}
+
+static struct nand_ecclayout cafe_oobinfo_2048 = {
+	.eccbytes = 14,
+	.eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
+	.oobfree = {{14, 50}}
+};
+
+/* Ick. The BBT code really ought to be able to work this bit out
+   for itself from the above, at least for the 2KiB case */
+static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
+static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
+
+static uint8_t cafe_bbt_pattern_512[] = { 0xBB };
+static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
+
+
+static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs =	14,
+	.len = 4,
+	.veroffs = 18,
+	.maxblocks = 4,
+	.pattern = cafe_bbt_pattern_2048
+};
+
+static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs =	14,
+	.len = 4,
+	.veroffs = 18,
+	.maxblocks = 4,
+	.pattern = cafe_mirror_pattern_2048
+};
+
+static struct nand_ecclayout cafe_oobinfo_512 = {
+	.eccbytes = 14,
+	.eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
+	.oobfree = {{14, 2}}
+};
+
+static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs =	14,
+	.len = 1,
+	.veroffs = 15,
+	.maxblocks = 4,
+	.pattern = cafe_bbt_pattern_512
+};
+
+static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs =	14,
+	.len = 1,
+	.veroffs = 15,
+	.maxblocks = 4,
+	.pattern = cafe_mirror_pattern_512
+};
+
+
+static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
+					  struct nand_chip *chip, const uint8_t *buf)
+{
+	struct cafe_priv *cafe = mtd->priv;
+
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	/* Set up ECC autogeneration */
+	cafe->ctl2 |= (1<<30);
+}
+
+static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+				const uint8_t *buf, int page, int cached, int raw)
+{
+	int status;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+	if (unlikely(raw))
+		chip->ecc.write_page_raw(mtd, chip, buf);
+	else
+		chip->ecc.write_page(mtd, chip, buf);
+
+	/*
+	 * Cached progamming disabled for now, Not sure if its worth the
+	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+	 */
+	cached = 0;
+
+	if (!cached || !(chip->options & NAND_CACHEPRG)) {
+
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available
+		 */
+		if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+			status = chip->errstat(mtd, chip, FL_WRITING, status,
+					       page);
+
+		if (status & NAND_STATUS_FAIL)
+			return -EIO;
+	} else {
+		chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+	}
+
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+	/* Send command to read back the data */
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+	if (chip->verify_buf(mtd, buf, mtd->writesize))
+		return -EIO;
+#endif
+	return 0;
+}
+
+static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+static int __devinit cafe_nand_probe(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	struct mtd_info *mtd;
+	struct cafe_priv *cafe;
+	uint32_t ctrl;
+	int err = 0;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	pci_set_master(pdev);
+
+	mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
+	if (!mtd) {
+		dev_warn(&pdev->dev, "failed to alloc mtd_info\n");
+		return  -ENOMEM;
+	}
+	cafe = (void *)(&mtd[1]);
+
+	mtd->priv = cafe;
+	mtd->owner = THIS_MODULE;
+
+	cafe->pdev = pdev;
+	cafe->mmio = pci_iomap(pdev, 0, 0);
+	if (!cafe->mmio) {
+		dev_warn(&pdev->dev, "failed to iomap\n");
+		err = -ENOMEM;
+		goto out_free_mtd;
+	}
+	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers),
+					  &cafe->dmaaddr, GFP_KERNEL);
+	if (!cafe->dmabuf) {
+		err = -ENOMEM;
+		goto out_ior;
+	}
+	cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
+
+	cafe->nand.cmdfunc = cafe_nand_cmdfunc;
+	cafe->nand.dev_ready = cafe_device_ready;
+	cafe->nand.read_byte = cafe_read_byte;
+	cafe->nand.read_buf = cafe_read_buf;
+	cafe->nand.write_buf = cafe_write_buf;
+	cafe->nand.select_chip = cafe_select_chip;
+
+	cafe->nand.chip_delay = 0;
+
+	/* Enable the following for a flash based bad block table */
+	cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
+
+	if (skipbbt) {
+		cafe->nand.options |= NAND_SKIP_BBTSCAN;
+		cafe->nand.block_bad = cafe_nand_block_bad;
+	}
+
+	/* Start off by resetting the NAND controller completely */
+	cafe_writel(cafe, 1, NAND_RESET);
+	cafe_writel(cafe, 0, NAND_RESET);
+
+	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+
+	/* Timings from Marvell's test code (not verified or calculated by us) */
+	if (!slowtiming) {
+		cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
+		cafe_writel(cafe, 0x24121212, NAND_TIMING2);
+		cafe_writel(cafe, 0x11000000, NAND_TIMING3);
+	} else {
+		cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
+		cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
+		cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
+	}
+	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+	err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd);
+	if (err) {
+		dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
+
+		goto out_free_dma;
+	}
+#if 1
+	/* Disable master reset, enable NAND clock */
+	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
+	ctrl &= 0xffffeff0;
+	ctrl |= 0x00007000;
+	cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
+	cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
+	cafe_writel(cafe, 0, NAND_DMA_CTRL);
+
+	cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
+	cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
+
+	/* Set up DMA address */
+	cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
+	if (sizeof(cafe->dmaaddr) > 4)
+		/* Shift in two parts to shut the compiler up */
+		cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
+	else
+		cafe_writel(cafe, 0, NAND_DMA_ADDR1);
+
+	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
+		cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
+
+	/* Enable NAND IRQ in global IRQ mask register */
+	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
+	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
+		cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
+#endif
+#if 1
+	mtd->writesize=2048;
+	mtd->oobsize = 0x40;
+	memset(cafe->dmabuf, 0x5a, 2112);
+	cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+#endif
+#if 0
+	cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
+	//	nand_wait_ready(mtd);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+	cafe->nand.read_byte(mtd);
+#endif
+#if 0
+	writel(0x84600070, cafe->mmio);
+	udelay(10);
+	cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
+#endif
+	/* Scan to find existance of the device */
+	if (nand_scan_ident(mtd, 1)) {
+		err = -ENXIO;
+		goto out_irq;
+	}
+
+	cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
+	if (mtd->writesize == 2048)
+		cafe->ctl2 |= 1<<29; /* 2KiB page size */
+
+	/* Set up ECC according to the type of chip we found */
+	if (mtd->writesize == 2048) {
+		cafe->nand.ecc.layout = &cafe_oobinfo_2048;
+		cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
+		cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
+	} else if (mtd->writesize == 512) {
+		cafe->nand.ecc.layout = &cafe_oobinfo_512;
+		cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
+		cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
+	} else {
+		printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
+		       mtd->writesize);
+		goto out_irq;
+	}
+	cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
+	cafe->nand.ecc.size = mtd->writesize;
+	cafe->nand.ecc.bytes = 14;
+	cafe->nand.ecc.hwctl  = (void *)cafe_nand_bug;
+	cafe->nand.ecc.calculate = (void *)cafe_nand_bug;
+	cafe->nand.ecc.correct  = (void *)cafe_nand_bug;
+	cafe->nand.write_page = cafe_nand_write_page;
+	cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
+	cafe->nand.ecc.write_oob = cafe_nand_write_oob;
+	cafe->nand.ecc.read_page = cafe_nand_read_page;
+	cafe->nand.ecc.read_oob = cafe_nand_read_oob;
+
+	err = nand_scan_tail(mtd);
+	if (err)
+		goto out_irq;
+
+	pci_set_drvdata(pdev, mtd);
+	add_mtd_device(mtd);
+	goto out;
+
+ out_irq:
+	/* Disable NAND IRQ in global IRQ mask register */
+	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
+	free_irq(pdev->irq, mtd);
+ out_free_dma:
+	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+ out_ior:
+	pci_iounmap(pdev, cafe->mmio);
+ out_free_mtd:
+	kfree(mtd);
+ out:
+	return err;
+}
+
+static void __devexit cafe_nand_remove(struct pci_dev *pdev)
+{
+	struct mtd_info *mtd = pci_get_drvdata(pdev);
+	struct cafe_priv *cafe = mtd->priv;
+
+	del_mtd_device(mtd);
+	/* Disable NAND IRQ in global IRQ mask register */
+	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
+	free_irq(pdev->irq, mtd);
+	nand_release(mtd);
+	pci_iounmap(pdev, cafe->mmio);
+	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+	kfree(mtd);
+}
+
+static struct pci_device_id cafe_nand_tbl[] = {
+	{ 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
+};
+
+MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
+
+static struct pci_driver cafe_nand_pci_driver = {
+	.name = "CAFÉ NAND",
+	.id_table = cafe_nand_tbl,
+	.probe = cafe_nand_probe,
+	.remove = __devexit_p(cafe_nand_remove),
+#ifdef CONFIG_PMx
+	.suspend = cafe_nand_suspend,
+	.resume = cafe_nand_resume,
+#endif
+};
+
+static int cafe_nand_init(void)
+{
+	return pci_register_driver(&cafe_nand_pci_driver);
+}
+
+static void cafe_nand_exit(void)
+{
+	pci_unregister_driver(&cafe_nand_pci_driver);
+}
+module_init(cafe_nand_init);
+module_exit(cafe_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
+
+/* Correct ECC for 2048 bytes of 0xff:
+   41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
+
+/* dwmw2's B-test board, in case of completely screwing it:
+Bad eraseblock 2394 at 0x12b40000
+Bad eraseblock 2627 at 0x14860000
+Bad eraseblock 3349 at 0x1a2a0000
+*/
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
new file mode 100644
index 0000000..1b9fa05
--- /dev/null
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -0,0 +1,1381 @@
+/* Error correction for CAFÉ NAND controller
+ *
+ * © 2006 Marvell, Inc.
+ * Author: Tom Chiou
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+static unsigned short gf4096_mul(unsigned short, unsigned short);
+static unsigned short gf64_mul(unsigned short, unsigned short);
+static unsigned short gf4096_inv(unsigned short);
+static unsigned short err_pos(unsigned short);
+static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short,
+				unsigned short, unsigned short, unsigned short,
+				unsigned short, unsigned short, unsigned short *);
+static void zero_4x5_col3(unsigned short[4][5]);
+static void zero_4x5_col2(unsigned short[4][5]);
+static void zero_4x5_col1(unsigned short[4][5]);
+static void swap_4x5_rows(unsigned short[4][5], int, int, int);
+static void swap_2x3_rows(unsigned short m[2][3]);
+static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
+static void sort_coefs(int *, unsigned short *, int);
+static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short,
+			       unsigned short, unsigned short, unsigned short,
+			       unsigned short, unsigned short, unsigned short *);
+static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
+				unsigned short, unsigned short, unsigned short,
+				unsigned short *);
+static void zero_3x4_col2(unsigned short[3][4]);
+static void zero_3x4_col1(unsigned short[3][4]);
+static void swap_3x4_rows(unsigned short[3][4], int, int, int);
+static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
+static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
+			       unsigned short, unsigned short, unsigned short,
+			       unsigned short *);
+
+static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
+			       unsigned short, unsigned short *);
+static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
+			  unsigned short, unsigned short, unsigned short,
+			  unsigned short *);
+static void solve_2x3(unsigned short[2][3], unsigned short *);
+static int chk_no_err_only(unsigned short *, unsigned short *);
+static int chk_1_err_only(unsigned short *, unsigned short *);
+static int chk_2_err_only(unsigned short *, unsigned short *);
+static int chk_3_err_only(unsigned short *, unsigned short *);
+static int chk_4_err_only(unsigned short *, unsigned short *);
+
+static unsigned short gf64_mul(unsigned short a, unsigned short b)
+{
+	unsigned short tmp1, tmp2, tmp3, tmp4, tmp5;
+	unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c;
+
+	tmp1 = ((a) ^ (a >> 5));
+	tmp2 = ((a >> 4) ^ (a >> 5));
+	tmp3 = ((a >> 3) ^ (a >> 4));
+	tmp4 = ((a >> 2) ^ (a >> 3));
+	tmp5 = ((a >> 1) ^ (a >> 2));
+
+	c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^
+		  ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1;
+
+	c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^
+		  (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1;
+
+	c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^
+		  (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1;
+
+	c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^
+		  (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1;
+
+	c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^
+		  ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1;
+
+	c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^
+		  ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1;
+
+	c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5);
+
+	return c;
+}
+
+static unsigned short gf4096_mul(unsigned short a, unsigned short b)
+{
+	unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c;
+
+	ah = (a >> 6) & 0x3f;
+	al = a & 0x3f;
+	bh = (b >> 6) & 0x3f;
+	bl = b & 0x3f;
+	alxah = al ^ ah;
+	blxbh = bl ^ bh;
+
+	ablh = gf64_mul(alxah, blxbh);
+	albl = gf64_mul(al, bl);
+	ahbh = gf64_mul(ah, bh);
+
+	ahbhB = ((ahbh & 0x1) << 5) |
+	    ((ahbh & 0x20) >> 1) |
+	    ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1);
+
+	c = ((ablh ^ albl) << 6) | (ahbhB ^ albl);
+	return c;
+}
+
+static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats)
+{
+	find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats);
+}
+
+static void find_3bit_err_coefs(unsigned short s0, unsigned short s1,
+				unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs)
+{
+	unsigned short m[3][4];
+	int row_order[3];
+
+	row_order[0] = 0;
+	row_order[1] = 1;
+	row_order[2] = 2;
+	m[0][0] = s2;
+	m[0][1] = s1;
+	m[0][2] = s0;
+	m[0][3] = s3;
+	m[1][0] = s3;
+	m[1][1] = s2;
+	m[1][2] = s1;
+	m[1][3] = s4;
+	m[2][0] = s4;
+	m[2][1] = s3;
+	m[2][2] = s2;
+	m[2][3] = s5;
+
+	if (m[0][2] != 0x0) {
+		zero_3x4_col2(m);
+	} else if (m[1][2] != 0x0) {
+		swap_3x4_rows(m, 0, 1, 4);
+		zero_3x4_col2(m);
+	} else if (m[2][2] != 0x0) {
+		swap_3x4_rows(m, 0, 2, 4);
+		zero_3x4_col2(m);
+	} else {
+		printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n");
+	}
+
+	if (m[1][1] != 0x0) {
+		zero_3x4_col1(m);
+	} else if (m[2][1] != 0x0) {
+		swap_3x4_rows(m, 1, 2, 4);
+		zero_3x4_col1(m);
+	} else {
+		printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n");
+	}
+
+	/* solve coefs */
+	solve_3x4(m, coefs, row_order);
+}
+
+static void zero_3x4_col2(unsigned short m[3][4])
+{
+	unsigned short minv1, minv2;
+
+	minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2]));
+	minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2]));
+	m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
+	m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
+	m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1);
+	m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
+	m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
+	m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2);
+}
+
+static void zero_3x4_col1(unsigned short m[3][4])
+{
+	unsigned short minv;
+	minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1]));
+	m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv);
+	m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv);
+}
+
+static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width)
+{
+	unsigned short tmp0;
+	int cnt;
+	for (cnt = 0; cnt < col_width; cnt++) {
+		tmp0 = m[i][cnt];
+		m[i][cnt] = m[j][cnt];
+		m[j][cnt] = tmp0;
+	}
+}
+
+static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order)
+{
+	unsigned short tmp[3];
+	tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0]));
+	tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1]));
+	tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2]));
+	sort_coefs(row_order, tmp, 3);
+	coefs[0] = tmp[0];
+	coefs[1] = tmp[1];
+	coefs[2] = tmp[2];
+}
+
+static void find_3bit_err_pats(unsigned short s0, unsigned short s1,
+			       unsigned short s2, unsigned short r0,
+			       unsigned short r1, unsigned short r2,
+			       unsigned short *pats)
+{
+	find_2x2_soln(r0 ^ r2, r1 ^ r2,
+		      gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2),
+		      gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats);
+	pats[2] = s0 ^ pats[0] ^ pats[1];
+}
+
+static void find_4bit_err_coefs(unsigned short s0, unsigned short s1,
+				unsigned short s2, unsigned short s3,
+				unsigned short s4, unsigned short s5,
+				unsigned short s6, unsigned short s7,
+				unsigned short *coefs)
+{
+	unsigned short m[4][5];
+	int row_order[4];
+
+	row_order[0] = 0;
+	row_order[1] = 1;
+	row_order[2] = 2;
+	row_order[3] = 3;
+
+	m[0][0] = s3;
+	m[0][1] = s2;
+	m[0][2] = s1;
+	m[0][3] = s0;
+	m[0][4] = s4;
+	m[1][0] = s4;
+	m[1][1] = s3;
+	m[1][2] = s2;
+	m[1][3] = s1;
+	m[1][4] = s5;
+	m[2][0] = s5;
+	m[2][1] = s4;
+	m[2][2] = s3;
+	m[2][3] = s2;
+	m[2][4] = s6;
+	m[3][0] = s6;
+	m[3][1] = s5;
+	m[3][2] = s4;
+	m[3][3] = s3;
+	m[3][4] = s7;
+
+	if (m[0][3] != 0x0) {
+		zero_4x5_col3(m);
+	} else if (m[1][3] != 0x0) {
+		swap_4x5_rows(m, 0, 1, 5);
+		zero_4x5_col3(m);
+	} else if (m[2][3] != 0x0) {
+		swap_4x5_rows(m, 0, 2, 5);
+		zero_4x5_col3(m);
+	} else if (m[3][3] != 0x0) {
+		swap_4x5_rows(m, 0, 3, 5);
+		zero_4x5_col3(m);
+	} else {
+		printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n");
+	}
+
+	if (m[1][2] != 0x0) {
+		zero_4x5_col2(m);
+	} else if (m[2][2] != 0x0) {
+		swap_4x5_rows(m, 1, 2, 5);
+		zero_4x5_col2(m);
+	} else if (m[3][2] != 0x0) {
+		swap_4x5_rows(m, 1, 3, 5);
+		zero_4x5_col2(m);
+	} else {
+		printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n");
+	}
+
+	if (m[2][1] != 0x0) {
+		zero_4x5_col1(m);
+	} else if (m[3][1] != 0x0) {
+		swap_4x5_rows(m, 2, 3, 5);
+		zero_4x5_col1(m);
+	} else {
+		printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n");
+	}
+
+	solve_4x5(m, coefs, row_order);
+}
+
+static void zero_4x5_col3(unsigned short m[4][5])
+{
+	unsigned short minv1, minv2, minv3;
+
+	minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3]));
+	minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3]));
+	minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3]));
+
+	m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
+	m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
+	m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1);
+	m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1);
+	m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
+	m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
+	m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2);
+	m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2);
+	m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3);
+	m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3);
+	m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3);
+	m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3);
+}
+
+static void zero_4x5_col2(unsigned short m[4][5])
+{
+	unsigned short minv2, minv3;
+
+	minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2]));
+	minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2]));
+
+	m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2);
+	m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2);
+	m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2);
+	m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3);
+	m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3);
+	m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3);
+}
+
+static void zero_4x5_col1(unsigned short m[4][5])
+{
+	unsigned short minv;
+
+	minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1]));
+
+	m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv);
+	m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv);
+}
+
+static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width)
+{
+	unsigned short tmp0;
+	int cnt;
+
+	for (cnt = 0; cnt < col_width; cnt++) {
+		tmp0 = m[i][cnt];
+		m[i][cnt] = m[j][cnt];
+		m[j][cnt] = tmp0;
+	}
+}
+
+static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order)
+{
+	unsigned short tmp[4];
+
+	tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0]));
+	tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1]));
+	tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2]));
+	tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^
+			gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3]));
+	sort_coefs(row_order, tmp, 4);
+	coefs[0] = tmp[0];
+	coefs[1] = tmp[1];
+	coefs[2] = tmp[2];
+	coefs[3] = tmp[3];
+}
+
+static void sort_coefs(int *order, unsigned short *soln, int len)
+{
+	int cnt, start_cnt, least_ord, least_cnt;
+	unsigned short tmp0;
+	for (start_cnt = 0; start_cnt < len; start_cnt++) {
+		for (cnt = start_cnt; cnt < len; cnt++) {
+			if (cnt == start_cnt) {
+				least_ord = order[cnt];
+				least_cnt = start_cnt;
+			} else {
+				if (least_ord > order[cnt]) {
+					least_ord = order[cnt];
+					least_cnt = cnt;
+				}
+			}
+		}
+		if (least_cnt != start_cnt) {
+			tmp0 = order[least_cnt];
+			order[least_cnt] = order[start_cnt];
+			order[start_cnt] = tmp0;
+			tmp0 = soln[least_cnt];
+			soln[least_cnt] = soln[start_cnt];
+			soln[start_cnt] = tmp0;
+		}
+	}
+}
+
+static void find_4bit_err_pats(unsigned short s0, unsigned short s1,
+			       unsigned short s2, unsigned short s3,
+			       unsigned short z1, unsigned short z2,
+			       unsigned short z3, unsigned short z4,
+			       unsigned short *pats)
+{
+	unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1,
+		z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3;
+	unsigned short tmp0, tmp1, tmp2, tmp3;
+
+	z4_z1 = z4 ^ z1;
+	z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3);
+	z4_z2 = z4 ^ z2;
+	s0z4_s1 = gf4096_mul(s0, z4) ^ s1;
+	z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1);
+	z4_z3 = z4 ^ z3;
+	z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2);
+	s1z4_s2 = gf4096_mul(s1, z4) ^ s2;
+	z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3);
+	z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1);
+	z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2);
+	s2z4_s3 = gf4096_mul(s2, z4) ^ s3;
+
+	//find err pat 0,1
+	find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^
+		      gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2,
+							       z3z4_z3z3) ^
+		      gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1,
+							       z3z3z4_z3z3z3) ^
+		      gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3),
+		      gf4096_mul(z2z4_z2z2,
+				 z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2,
+							     z3z4_z3z3),
+		      gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2,
+								  z4_z3),
+		      gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats);
+	tmp0 = pats[0];
+	tmp1 = pats[1];
+	tmp2 = pats[0] ^ pats[1] ^ s0;
+	tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1;
+
+	//find err pat 2,3
+	find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats);
+	pats[2] = pats[0];
+	pats[3] = pats[1];
+	pats[0] = tmp0;
+	pats[1] = tmp1;
+}
+
+static void find_2x2_soln(unsigned short c00, unsigned short c01,
+			  unsigned short c10, unsigned short c11,
+			  unsigned short lval0, unsigned short lval1,
+			  unsigned short *soln)
+{
+	unsigned short m[2][3];
+	m[0][0] = c00;
+	m[0][1] = c01;
+	m[0][2] = lval0;
+	m[1][0] = c10;
+	m[1][1] = c11;
+	m[1][2] = lval1;
+
+	if (m[0][1] != 0x0) {
+		/* */
+	} else if (m[1][1] != 0x0) {
+		swap_2x3_rows(m);
+	} else {
+		printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n");
+	}
+
+	solve_2x3(m, soln);
+}
+
+static void swap_2x3_rows(unsigned short m[2][3])
+{
+	unsigned short tmp0;
+	int cnt;
+
+	for (cnt = 0; cnt < 3; cnt++) {
+		tmp0 = m[0][cnt];
+		m[0][cnt] = m[1][cnt];
+		m[1][cnt] = tmp0;
+	}
+}
+
+static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
+{
+	unsigned short minv;
+
+	minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1]));
+	m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv);
+	m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv);
+	coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0]));
+	coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1]));
+}
+
+static unsigned char gf64_inv[64] = {
+	 0,  1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
+	61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45,  6,
+	63,  2, 27, 21, 56,  9, 50, 19, 13, 47, 48,  5,  7, 30, 12, 41,
+	42,  4, 38, 18, 10, 29, 17, 60, 36,  8, 59, 58, 55, 16,  3, 32
+};
+
+static unsigned short gf4096_inv(unsigned short din)
+{
+	unsigned short alahxal, ah2B, deno, inv, bl, bh;
+	unsigned short ah, al, ahxal;
+	unsigned short dout;
+
+	ah = (din >> 6) & 0x3f;
+	al = din & 0x3f;
+	ahxal = ah ^ al;
+	ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) |
+		((ah >> 1) & 0x10) |
+		((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) |
+		((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1);
+	alahxal = gf64_mul(ahxal, al);
+	deno = alahxal ^ ah2B;
+	inv = gf64_inv[deno];
+	bl = gf64_mul(inv, ahxal);
+	bh = gf64_mul(inv, ah);
+	dout = ((bh & 0x3f) << 6) | (bl & 0x3f);
+	return (((bh & 0x3f) << 6) | (bl & 0x3f));
+}
+
+static unsigned short err_pos_lut[4096] = {
+	0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff,
+	0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff,
+	0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff,
+	0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff,
+	0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7,
+	0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff,
+	0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff,
+	0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f,
+	0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8,
+	0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe,
+	0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff,
+	0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1,
+	0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff,
+	0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff,
+	0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff,
+	0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8,
+	0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e,
+	0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff,
+	0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff,
+	0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff,
+	0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535,
+	0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d,
+	0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff,
+	0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5,
+	0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff,
+	0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294,
+	0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff,
+	0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4,
+	0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f,
+	0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b,
+	0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff,
+	0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff,
+	0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff,
+	0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158,
+	0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a,
+	0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff,
+	0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff,
+	0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017,
+	0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a,
+	0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351,
+	0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff,
+	0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff,
+	0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074,
+	0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da,
+	0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433,
+	0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285,
+	0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff,
+	0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d,
+	0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff,
+	0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff,
+	0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331,
+	0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff,
+	0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6,
+	0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3,
+	0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff,
+	0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf,
+	0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc,
+	0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381,
+	0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff,
+	0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f,
+	0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff,
+	0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488,
+	0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442,
+	0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6,
+	0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1,
+	0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae,
+	0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff,
+	0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff,
+	0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2,
+	0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec,
+	0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134,
+	0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b,
+	0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff,
+	0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff,
+	0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff,
+	0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5,
+	0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff,
+	0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff,
+	0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff,
+	0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff,
+	0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2,
+	0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff,
+	0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff,
+	0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff,
+	0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff,
+	0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff,
+	0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff,
+	0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff,
+	0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8,
+	0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb,
+	0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff,
+	0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff,
+	0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd,
+	0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff,
+	0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8,
+	0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9,
+	0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f,
+	0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7,
+	0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff,
+	0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d,
+	0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178,
+	0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff,
+	0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba,
+	0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff,
+	0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e,
+	0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff,
+	0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6,
+	0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff,
+	0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff,
+	0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc,
+	0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6,
+	0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5,
+	0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff,
+	0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc,
+	0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff,
+	0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3,
+	0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff,
+	0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6,
+	0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff,
+	0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a,
+	0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff,
+	0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff,
+	0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff,
+	0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff,
+	0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7,
+	0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff,
+	0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff,
+	0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af,
+	0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff,
+	0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2,
+	0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff,
+	0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff,
+	0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff,
+	0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339,
+	0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff,
+	0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff,
+	0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402,
+	0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff,
+	0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368,
+	0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b,
+	0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f,
+	0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff,
+	0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1,
+	0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff,
+	0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff,
+	0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb,
+	0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc,
+	0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097,
+	0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431,
+	0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1,
+	0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff,
+	0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6,
+	0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd,
+	0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff,
+	0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb,
+	0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff,
+	0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd,
+	0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff,
+	0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff,
+	0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519,
+	0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff,
+	0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084,
+	0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0,
+	0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c,
+	0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f,
+	0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a,
+	0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211,
+	0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff,
+	0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff,
+	0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff,
+	0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff,
+	0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff,
+	0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff,
+	0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180,
+	0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0,
+	0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004,
+	0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302,
+	0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff,
+	0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff,
+	0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272,
+	0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff,
+	0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344,
+	0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff,
+	0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e,
+	0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d,
+	0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff,
+	0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330,
+	0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042,
+	0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364,
+	0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff,
+	0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff,
+	0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f,
+	0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb,
+	0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e,
+	0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c,
+	0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194,
+	0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff,
+	0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff,
+	0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff,
+	0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff,
+	0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6,
+	0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff,
+	0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290,
+	0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff,
+	0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9,
+	0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d,
+	0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff,
+	0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9,
+	0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167,
+	0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020,
+	0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347,
+	0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff,
+	0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff,
+	0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff,
+	0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff,
+	0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff,
+	0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039,
+	0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096,
+	0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff,
+	0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8,
+	0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff,
+	0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd,
+	0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e,
+	0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f,
+	0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff,
+	0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7,
+	0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb,
+	0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff,
+	0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078,
+	0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300,
+	0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200,
+	0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f,
+	0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff,
+	0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216,
+	0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d,
+	0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0,
+	0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff,
+	0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff,
+	0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff,
+	0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff,
+	0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff,
+	0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff,
+	0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086,
+	0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff,
+	0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444,
+	0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff,
+	0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110,
+	0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099,
+	0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff,
+	0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da,
+	0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff,
+	0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff,
+	0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff,
+	0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff,
+	0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff,
+	0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283,
+	0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff,
+	0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff,
+	0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff,
+	0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff,
+	0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff,
+	0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195,
+	0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff,
+	0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff,
+	0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff,
+	0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff,
+	0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff,
+	0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245,
+	0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff,
+	0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6,
+	0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+	0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1,
+	0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da,
+	0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff,
+	0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff,
+	0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5,
+	0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223,
+	0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002
+};
+
+static unsigned short err_pos(unsigned short din)
+{
+	BUG_ON(din > 4096);
+	return err_pos_lut[din];
+}
+static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+	if ((chk_syndrome_list[0] | chk_syndrome_list[1] |
+	     chk_syndrome_list[2] | chk_syndrome_list[3] |
+	     chk_syndrome_list[4] | chk_syndrome_list[5] |
+	     chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) {
+		return -EINVAL;
+	} else {
+		err_info[0] = 0x0;
+		return 0;
+	}
+}
+static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+	unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+	tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0]));
+	tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1]));
+	tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2]));
+	tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3]));
+	tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4]));
+	tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5]));
+	tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6]));
+	if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) {
+		err_info[0] = 0x1;	// encode 1-symbol error as 0x1
+		err_info[1] = err_pos(tmp0);
+		err_info[1] = (unsigned short)(0x55e - err_info[1]);
+		err_info[5] = chk_syndrome_list[0];
+		return 0;
+	} else
+		return -EINVAL;
+}
+static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+	unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+	unsigned short coefs[4];
+	unsigned short err_pats[4];
+	int found_num_root = 0;
+	unsigned short bit2_root0, bit2_root1;
+	unsigned short bit2_root0_inv, bit2_root1_inv;
+	unsigned short err_loc_eqn, test_root;
+	unsigned short bit2_loc0, bit2_loc1;
+	unsigned short bit2_pat0, bit2_pat1;
+
+	find_2x2_soln(chk_syndrome_list[1],
+		      chk_syndrome_list[0],
+		      chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs);
+	for (test_root = 0x1; test_root < 0xfff; test_root++) {
+		err_loc_eqn =
+		    gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
+		if (err_loc_eqn == 0x0) {
+			if (found_num_root == 0) {
+				bit2_root0 = test_root;
+				found_num_root = 1;
+			} else if (found_num_root == 1) {
+				bit2_root1 = test_root;
+				found_num_root = 2;
+				break;
+			}
+		}
+	}
+	if (found_num_root != 2)
+		return -EINVAL;
+	else {
+		bit2_root0_inv = gf4096_inv(bit2_root0);
+		bit2_root1_inv = gf4096_inv(bit2_root1);
+		find_2bit_err_pats(chk_syndrome_list[0],
+				   chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats);
+		bit2_pat0 = err_pats[0];
+		bit2_pat1 = err_pats[1];
+		//for(x+1)
+		tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv));	//rinv0^4
+		tmp1 = gf4096_mul(bit2_root0_inv, tmp0);	//rinv0^5
+		tmp2 = gf4096_mul(bit2_root0_inv, tmp1);	//rinv0^6
+		tmp3 = gf4096_mul(bit2_root0_inv, tmp2);	//rinv0^7
+		tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv));	//rinv1^4
+		tmp5 = gf4096_mul(bit2_root1_inv, tmp4);	//rinv1^5
+		tmp6 = gf4096_mul(bit2_root1_inv, tmp5);	//rinv1^6
+		tmp7 = gf4096_mul(bit2_root1_inv, tmp6);	//rinv1^7
+		//check if only 2-bit error
+		if ((chk_syndrome_list[4] ==
+		     (gf4096_mul(bit2_pat0, tmp0) ^
+		      gf4096_mul(bit2_pat1,
+				 tmp4))) & (chk_syndrome_list[5] ==
+					    (gf4096_mul(bit2_pat0, tmp1) ^
+					     gf4096_mul(bit2_pat1,
+							tmp5))) &
+		    (chk_syndrome_list[6] ==
+		     (gf4096_mul(bit2_pat0, tmp2) ^
+		      gf4096_mul(bit2_pat1,
+				 tmp6))) & (chk_syndrome_list[7] ==
+					    (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) {
+			if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) {
+				return -EINVAL;
+			} else {
+				bit2_loc0 = 0x55e - err_pos(bit2_root0_inv);
+				bit2_loc1 = 0x55e - err_pos(bit2_root1_inv);
+				err_info[0] = 0x2;	// encode 2-symbol error as 0x2
+				err_info[1] = bit2_loc0;
+				err_info[2] = bit2_loc1;
+				err_info[5] = bit2_pat0;
+				err_info[6] = bit2_pat1;
+				return 0;
+			}
+		} else
+			return -EINVAL;
+	}
+}
+static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+	unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+	unsigned short coefs[4];
+	unsigned short err_pats[4];
+	int found_num_root = 0;
+	unsigned short bit3_root0, bit3_root1, bit3_root2;
+	unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv;
+	unsigned short err_loc_eqn, test_root;
+
+	find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1],
+			    chk_syndrome_list[2], chk_syndrome_list[3],
+			    chk_syndrome_list[4], chk_syndrome_list[5], coefs);
+
+	for (test_root = 0x1; test_root < 0xfff; test_root++) {
+		err_loc_eqn = gf4096_mul(coefs[2],
+					 gf4096_mul(gf4096_mul(test_root, test_root),
+						    test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root))
+			^ gf4096_mul(coefs[0], test_root) ^ 0x1;
+
+		if (err_loc_eqn == 0x0) {
+			if (found_num_root == 0) {
+				bit3_root0 = test_root;
+				found_num_root = 1;
+			} else if (found_num_root == 1) {
+				bit3_root1 = test_root;
+				found_num_root = 2;
+			} else if (found_num_root == 2) {
+				bit3_root2 = test_root;
+				found_num_root = 3;
+				break;
+			}
+		}
+	}
+	if (found_num_root != 3)
+		return -EINVAL;
+	else {
+		bit3_root0_inv = gf4096_inv(bit3_root0);
+		bit3_root1_inv = gf4096_inv(bit3_root1);
+		bit3_root2_inv = gf4096_inv(bit3_root2);
+
+		find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1],
+				   chk_syndrome_list[2], bit3_root0_inv,
+				   bit3_root1_inv, bit3_root2_inv, err_pats);
+
+		//check if only 3-bit error
+		tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv);
+		tmp0 = gf4096_mul(tmp0, tmp0);
+		tmp0 = gf4096_mul(tmp0, bit3_root0_inv);
+		tmp0 = gf4096_mul(tmp0, bit3_root0_inv);	//rinv0^6
+		tmp1 = gf4096_mul(tmp0, bit3_root0_inv);	//rinv0^7
+		tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv);
+		tmp2 = gf4096_mul(tmp2, tmp2);
+		tmp2 = gf4096_mul(tmp2, bit3_root1_inv);
+		tmp2 = gf4096_mul(tmp2, bit3_root1_inv);	//rinv1^6
+		tmp3 = gf4096_mul(tmp2, bit3_root1_inv);	//rinv1^7
+		tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv);
+		tmp4 = gf4096_mul(tmp4, tmp4);
+		tmp4 = gf4096_mul(tmp4, bit3_root2_inv);
+		tmp4 = gf4096_mul(tmp4, bit3_root2_inv);	//rinv2^6
+		tmp5 = gf4096_mul(tmp4, bit3_root2_inv);	//rinv2^7
+
+		//check if only 3 errors
+		if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^
+					      gf4096_mul(err_pats[1], tmp2) ^
+					      gf4096_mul(err_pats[2], tmp4))) &
+		    (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^
+					      gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) {
+			if ((err_pos(bit3_root0_inv) == 0xfff) |
+			    (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) {
+				return -EINVAL;
+			} else {
+				err_info[0] = 0x3;
+				err_info[1] = (0x55e - err_pos(bit3_root0_inv));
+				err_info[2] = (0x55e - err_pos(bit3_root1_inv));
+				err_info[3] = (0x55e - err_pos(bit3_root2_inv));
+				err_info[5] = err_pats[0];
+				err_info[6] = err_pats[1];
+				err_info[7] = err_pats[2];
+				return 0;
+			}
+		} else
+			return -EINVAL;
+	}
+}
+static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+	unsigned short coefs[4];
+	unsigned short err_pats[4];
+	int found_num_root = 0;
+	unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3;
+	unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv;
+	unsigned short err_loc_eqn, test_root;
+
+	find_4bit_err_coefs(chk_syndrome_list[0],
+			    chk_syndrome_list[1],
+			    chk_syndrome_list[2],
+			    chk_syndrome_list[3],
+			    chk_syndrome_list[4],
+			    chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs);
+
+	for (test_root = 0x1; test_root < 0xfff; test_root++) {
+		err_loc_eqn =
+		    gf4096_mul(coefs[3],
+			       gf4096_mul(gf4096_mul
+					  (gf4096_mul(test_root, test_root),
+					   test_root),
+					  test_root)) ^ gf4096_mul(coefs[2],
+								   gf4096_mul
+								   (gf4096_mul(test_root, test_root), test_root))
+		    ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root)
+		    ^ 0x1;
+		if (err_loc_eqn == 0x0) {
+			if (found_num_root == 0) {
+				bit4_root0 = test_root;
+				found_num_root = 1;
+			} else if (found_num_root == 1) {
+				bit4_root1 = test_root;
+				found_num_root = 2;
+			} else if (found_num_root == 2) {
+				bit4_root2 = test_root;
+				found_num_root = 3;
+			} else {
+				found_num_root = 4;
+				bit4_root3 = test_root;
+				break;
+			}
+		}
+	}
+	if (found_num_root != 4) {
+		return -EINVAL;
+	} else {
+		bit4_root0_inv = gf4096_inv(bit4_root0);
+		bit4_root1_inv = gf4096_inv(bit4_root1);
+		bit4_root2_inv = gf4096_inv(bit4_root2);
+		bit4_root3_inv = gf4096_inv(bit4_root3);
+		find_4bit_err_pats(chk_syndrome_list[0],
+				   chk_syndrome_list[1],
+				   chk_syndrome_list[2],
+				   chk_syndrome_list[3],
+				   bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats);
+		err_info[0] = 0x4;
+		err_info[1] = (0x55e - err_pos(bit4_root0_inv));
+		err_info[2] = (0x55e - err_pos(bit4_root1_inv));
+		err_info[3] = (0x55e - err_pos(bit4_root2_inv));
+		err_info[4] = (0x55e - err_pos(bit4_root3_inv));
+		err_info[5] = err_pats[0];
+		err_info[6] = err_pats[1];
+		err_info[7] = err_pats[2];
+		err_info[8] = err_pats[3];
+		return 0;
+	}
+}
+
+void correct_12bit_symbol(unsigned char *buf, unsigned short sym,
+			  unsigned short val)
+{
+	if (unlikely(sym > 1366)) {
+		printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym);
+	} else if (sym == 0) {
+		buf[0] ^= val;
+	} else if (sym & 1) {
+		buf[1+(3*(sym-1))/2] ^= (val >> 4);
+		buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4);
+	} else {
+		buf[2+(3*(sym-2))/2] ^= (val >> 8);
+		buf[3+(3*(sym-2))/2] ^= (val & 0xff);
+	}
+}
+
+static int debugecc = 0;
+module_param(debugecc, int, 0644);
+
+int cafe_correct_ecc(unsigned char *buf,
+		     unsigned short *chk_syndrome_list)
+{
+	unsigned short err_info[9];
+	int i;
+
+	if (debugecc) {
+		printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n",
+		       chk_syndrome_list[0], chk_syndrome_list[1],
+		       chk_syndrome_list[2], chk_syndrome_list[3],
+		       chk_syndrome_list[4], chk_syndrome_list[5],
+		       chk_syndrome_list[6], chk_syndrome_list[7]);
+		for (i=0; i < 2048; i+=16) {
+			printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			       i,
+			       buf[i], buf[i+1], buf[i+2], buf[i+3],
+			       buf[i+4], buf[i+5], buf[i+6], buf[i+7],
+			       buf[i+8], buf[i+9], buf[i+10], buf[i+11],
+			       buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
+		}
+		for ( ; i < 2112; i+=16) {
+			printk(KERN_WARNING "O   %02x: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			       i - 2048,
+			       buf[i], buf[i+1], buf[i+2], buf[i+3],
+			       buf[i+4], buf[i+5], buf[i+6], buf[i+7],
+			       buf[i+8], buf[i+9], buf[i+10], buf[i+11],
+			       buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
+		}
+	}
+
+
+
+	if (chk_no_err_only(chk_syndrome_list, err_info) &&
+	    chk_1_err_only(chk_syndrome_list, err_info) &&
+	    chk_2_err_only(chk_syndrome_list, err_info) &&
+	    chk_3_err_only(chk_syndrome_list, err_info) &&
+	    chk_4_err_only(chk_syndrome_list, err_info)) {
+		return -EIO;
+	}
+
+	for (i=0; i < err_info[0]; i++) {
+		if (debugecc)
+			printk(KERN_WARNING "Correct symbol %d with 0x%03x\n",
+			       err_info[1+i], err_info[5+i]);
+
+		correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]);
+	}
+
+	return err_info[0];
+}
+
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 94924d5..8296305 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  *
  *  Overview:
- *   This is a device driver for the NAND flash controller found on 
+ *   This is a device driver for the NAND flash controller found on
  *   the AMD CS5535/CS5536 companion chipsets for the Geode processor.
  *
  */
@@ -303,7 +303,7 @@
 			err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
 	}
 
-	/* Register all devices together here. This means we can easily hack it to 
+	/* Register all devices together here. This means we can easily hack it to
 	   do mtdconcat etc. if we want to. */
 	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
 		if (cs553x_mtd[i]) {
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 6107f53..12608c1 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1635,13 +1635,12 @@
 
 	len = sizeof(struct mtd_info) +
 	    sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
-	mtd = kmalloc(len, GFP_KERNEL);
+	mtd = kzalloc(len, GFP_KERNEL);
 	if (!mtd) {
 		printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
 		ret = -ENOMEM;
 		goto fail;
 	}
-	memset(mtd, 0, len);
 
 	nand			= (struct nand_chip *) (mtd + 1);
 	doc			= (struct doc_priv *) (nand + 1);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 41bfcae..dfe56e0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -362,7 +362,7 @@
 		 * access
 		 */
 		ofs += mtd->oobsize;
-		chip->ops.len = 2;
+		chip->ops.len = chip->ops.ooblen = 2;
 		chip->ops.datbuf = NULL;
 		chip->ops.oobbuf = buf;
 		chip->ops.ooboffs = chip->badblockpos & ~0x01;
@@ -755,7 +755,7 @@
 }
 
 /**
- * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
+ * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
@@ -795,7 +795,7 @@
 }
 
 /**
- * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
+ * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
@@ -839,7 +839,7 @@
 }
 
 /**
- * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
@@ -897,12 +897,11 @@
  * @chip:	nand chip structure
  * @oob:	oob destination address
  * @ops:	oob ops structure
+ * @len:	size of oob to transfer
  */
 static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
-				  struct mtd_oob_ops *ops)
+				  struct mtd_oob_ops *ops, size_t len)
 {
-	size_t len = ops->ooblen;
-
 	switch(ops->mode) {
 
 	case MTD_OOB_PLACE:
@@ -960,6 +959,7 @@
 	int sndcmd = 1;
 	int ret = 0;
 	uint32_t readlen = ops->len;
+	uint32_t oobreadlen = ops->ooblen;
 	uint8_t *bufpoi, *oob, *buf;
 
 	stats = mtd->ecc_stats;
@@ -971,7 +971,6 @@
 	page = realpage & chip->pagemask;
 
 	col = (int)(from & (mtd->writesize - 1));
-	chip->oob_poi = chip->buffers->oobrbuf;
 
 	buf = ops->datbuf;
 	oob = ops->oobbuf;
@@ -1007,10 +1006,17 @@
 
 			if (unlikely(oob)) {
 				/* Raw mode does data:oob:data:oob */
-				if (ops->mode != MTD_OOB_RAW)
-					oob = nand_transfer_oob(chip, oob, ops);
-				else
-					buf = nand_transfer_oob(chip, buf, ops);
+				if (ops->mode != MTD_OOB_RAW) {
+					int toread = min(oobreadlen,
+						chip->ecc.layout->oobavail);
+					if (toread) {
+						oob = nand_transfer_oob(chip,
+							oob, ops, toread);
+						oobreadlen -= toread;
+					}
+				} else
+					buf = nand_transfer_oob(chip,
+						buf, ops, mtd->oobsize);
 			}
 
 			if (!(chip->options & NAND_NO_READRDY)) {
@@ -1057,6 +1063,8 @@
 	}
 
 	ops->retlen = ops->len - (size_t) readlen;
+	if (oob)
+		ops->oobretlen = ops->ooblen - oobreadlen;
 
 	if (ret)
 		return ret;
@@ -1257,12 +1265,18 @@
 	int page, realpage, chipnr, sndcmd = 1;
 	struct nand_chip *chip = mtd->priv;
 	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
-	int readlen = ops->len;
+	int readlen = ops->ooblen;
+	int len;
 	uint8_t *buf = ops->oobbuf;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
 	      (unsigned long long)from, readlen);
 
+	if (ops->mode == MTD_OOB_RAW)
+		len = mtd->oobsize;
+	else
+		len = chip->ecc.layout->oobavail;
+
 	chipnr = (int)(from >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
 
@@ -1270,11 +1284,11 @@
 	realpage = (int)(from >> chip->page_shift);
 	page = realpage & chip->pagemask;
 
-	chip->oob_poi = chip->buffers->oobrbuf;
-
 	while(1) {
 		sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
-		buf = nand_transfer_oob(chip, buf, ops);
+
+		len = min(len, readlen);
+		buf = nand_transfer_oob(chip, buf, ops, len);
 
 		if (!(chip->options & NAND_NO_READRDY)) {
 			/*
@@ -1289,7 +1303,7 @@
 				nand_wait_ready(mtd);
 		}
 
-		readlen -= ops->ooblen;
+		readlen -= len;
 		if (!readlen)
 			break;
 
@@ -1311,7 +1325,7 @@
 			sndcmd = 1;
 	}
 
-	ops->retlen = ops->len;
+	ops->oobretlen = ops->ooblen;
 	return 0;
 }
 
@@ -1332,7 +1346,7 @@
 	ops->retlen = 0;
 
 	/* Do not allow reads past end of device */
-	if ((from + ops->len) > mtd->size) {
+	if (ops->datbuf && (from + ops->len) > mtd->size) {
 		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
 		      "Attempt read beyond end of device\n");
 		return -EINVAL;
@@ -1375,7 +1389,7 @@
 }
 
 /**
- * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
+ * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	data buffer
@@ -1401,7 +1415,7 @@
 }
 
 /**
- * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
+ * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	data buffer
@@ -1429,7 +1443,7 @@
 }
 
 /**
- * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
+ * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	data buffer
@@ -1577,7 +1591,7 @@
 	return NULL;
 }
 
-#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
+#define NOTALIGNED(x)	(x & (chip->subpagesize - 1)) != 0
 
 /**
  * nand_do_write_ops - [Internal] NAND write with ECC
@@ -1590,15 +1604,16 @@
 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
 {
-	int chipnr, realpage, page, blockmask;
+	int chipnr, realpage, page, blockmask, column;
 	struct nand_chip *chip = mtd->priv;
 	uint32_t writelen = ops->len;
 	uint8_t *oob = ops->oobbuf;
 	uint8_t *buf = ops->datbuf;
-	int bytes = mtd->writesize;
-	int ret;
+	int ret, subpage;
 
 	ops->retlen = 0;
+	if (!writelen)
+		return 0;
 
 	/* reject writes, which are not page aligned */
 	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
@@ -1607,8 +1622,11 @@
 		return -EINVAL;
 	}
 
-	if (!writelen)
-		return 0;
+	column = to & (mtd->writesize - 1);
+	subpage = column || (writelen & (mtd->writesize - 1));
+
+	if (subpage && oob)
+		return -EINVAL;
 
 	chipnr = (int)(to >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
@@ -1626,15 +1644,29 @@
 	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
 		chip->pagebuf = -1;
 
-	chip->oob_poi = chip->buffers->oobwbuf;
+	/* If we're not given explicit OOB data, let it be 0xFF */
+	if (likely(!oob))
+		memset(chip->oob_poi, 0xff, mtd->oobsize);
 
 	while(1) {
+		int bytes = mtd->writesize;
 		int cached = writelen > bytes && page != blockmask;
+		uint8_t *wbuf = buf;
+
+		/* Partial page write ? */
+		if (unlikely(column || writelen < (mtd->writesize - 1))) {
+			cached = 0;
+			bytes = min_t(int, bytes - column, (int) writelen);
+			chip->pagebuf = -1;
+			memset(chip->buffers->databuf, 0xff, mtd->writesize);
+			memcpy(&chip->buffers->databuf[column], buf, bytes);
+			wbuf = chip->buffers->databuf;
+		}
 
 		if (unlikely(oob))
 			oob = nand_fill_oob(chip, oob, ops);
 
-		ret = chip->write_page(mtd, chip, buf, page, cached,
+		ret = chip->write_page(mtd, chip, wbuf, page, cached,
 				       (ops->mode == MTD_OOB_RAW));
 		if (ret)
 			break;
@@ -1643,6 +1675,7 @@
 		if (!writelen)
 			break;
 
+		column = 0;
 		buf += bytes;
 		realpage++;
 
@@ -1655,10 +1688,9 @@
 		}
 	}
 
-	if (unlikely(oob))
-		memset(chip->oob_poi, 0xff, mtd->oobsize);
-
 	ops->retlen = ops->len - writelen;
+	if (unlikely(oob))
+		ops->oobretlen = ops->ooblen;
 	return ret;
 }
 
@@ -1714,10 +1746,10 @@
 	struct nand_chip *chip = mtd->priv;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
-	      (unsigned int)to, (int)ops->len);
+	      (unsigned int)to, (int)ops->ooblen);
 
 	/* Do not allow write past end of page */
-	if ((ops->ooboffs + ops->len) > mtd->oobsize) {
+	if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
 		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
 		      "Attempt to write past end of page\n");
 		return -EINVAL;
@@ -1745,7 +1777,6 @@
 	if (page == chip->pagebuf)
 		chip->pagebuf = -1;
 
-	chip->oob_poi = chip->buffers->oobwbuf;
 	memset(chip->oob_poi, 0xff, mtd->oobsize);
 	nand_fill_oob(chip, ops->oobbuf, ops);
 	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
@@ -1754,7 +1785,7 @@
 	if (status)
 		return status;
 
-	ops->retlen = ops->len;
+	ops->oobretlen = ops->ooblen;
 
 	return 0;
 }
@@ -1774,7 +1805,7 @@
 	ops->retlen = 0;
 
 	/* Do not allow writes past end of device */
-	if ((to + ops->len) > mtd->size) {
+	if (ops->datbuf && (to + ops->len) > mtd->size) {
 		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
 		      "Attempt read beyond end of device\n");
 		return -EINVAL;
@@ -2188,8 +2219,8 @@
 	/* Newer devices have all the information in additional id bytes */
 	if (!type->pagesize) {
 		int extid;
-		/* The 3rd id byte contains non relevant data ATM */
-		extid = chip->read_byte(mtd);
+		/* The 3rd id byte holds MLC / multichip data */
+		chip->cellinfo = chip->read_byte(mtd);
 		/* The 4th id byte is the important one */
 		extid = chip->read_byte(mtd);
 		/* Calc pagesize */
@@ -2349,8 +2380,8 @@
 	if (!chip->buffers)
 		return -ENOMEM;
 
-	/* Preset the internal oob write buffer */
-	memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize);
+	/* Set the internal oob buffer location, just after the page data */
+	chip->oob_poi = chip->buffers->databuf + mtd->writesize;
 
 	/*
 	 * If no default placement scheme is given, select an appropriate one
@@ -2469,6 +2500,24 @@
 	}
 	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
 
+	/*
+	 * Allow subpage writes up to ecc.steps. Not possible for MLC
+	 * FLASH.
+	 */
+	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+	    !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+		switch(chip->ecc.steps) {
+		case 2:
+			mtd->subpage_sft = 1;
+			break;
+		case 4:
+		case 8:
+			mtd->subpage_sft = 2;
+			break;
+		}
+	}
+	chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
+
 	/* Initialize state */
 	chip->state = FL_READY;
 
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 9402653..5e121ce 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -333,7 +333,6 @@
 	struct mtd_oob_ops ops;
 	int j, ret;
 
-	ops.len = mtd->oobsize;
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = buf;
 	ops.ooboffs = 0;
@@ -676,10 +675,10 @@
 				       "bad block table\n");
 			}
 			/* Read oob data */
-			ops.len = (len >> this->page_shift) * mtd->oobsize;
+			ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
 			ops.oobbuf = &buf[len];
 			res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
-			if (res < 0 || ops.retlen != ops.len)
+			if (res < 0 || ops.oobretlen != ops.ooblen)
 				goto outerr;
 
 			/* Calc the byte offset in the buffer */
@@ -961,14 +960,12 @@
 	struct nand_bbt_descr *md = this->bbt_md;
 
 	len = mtd->size >> (this->bbt_erase_shift + 2);
-	/* Allocate memory (2bit per block) */
-	this->bbt = kmalloc(len, GFP_KERNEL);
+	/* Allocate memory (2bit per block) and clear the memory bad block table */
+	this->bbt = kzalloc(len, GFP_KERNEL);
 	if (!this->bbt) {
 		printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
 		return -ENOMEM;
 	}
-	/* Clear the memory bad block table */
-	memset(this->bbt, 0x00, len);
 
 	/* If no primary table decriptor is given, scan the device
 	 * to build a memory based bad block table
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index dd438ca..fde593e 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -112,7 +112,7 @@
 	tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
 
 	/* Calculate final ECC code */
-#ifdef CONFIG_NAND_ECC_SMC
+#ifdef CONFIG_MTD_NAND_ECC_SMC
 	ecc_code[0] = ~tmp2;
 	ecc_code[1] = ~tmp1;
 #else
@@ -148,7 +148,7 @@
 {
 	uint8_t s0, s1, s2;
 
-#ifdef CONFIG_NAND_ECC_SMC
+#ifdef CONFIG_MTD_NAND_ECC_SMC
 	s0 = calc_ecc[0] ^ read_ecc[0];
 	s1 = calc_ecc[1] ^ read_ecc[1];
 	s2 = calc_ecc[2] ^ read_ecc[2];
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 545ff25..c3bca95 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -37,10 +37,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
-#ifdef CONFIG_NS_ABS_POS
-#include <asm/io.h>
-#endif
-
 
 /* Default simulator parameters values */
 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE)  || \
@@ -164,7 +160,7 @@
 /* After a command is input, the simulator goes to one of the following states */
 #define STATE_CMD_READ0        0x00000001 /* read data from the beginning of page */
 #define STATE_CMD_READ1        0x00000002 /* read data from the second half of page */
-#define STATE_CMD_READSTART      0x00000003 /* read data second command (large page devices) */
+#define STATE_CMD_READSTART    0x00000003 /* read data second command (large page devices) */
 #define STATE_CMD_PAGEPROG     0x00000004 /* start page programm */
 #define STATE_CMD_READOOB      0x00000005 /* read OOB area */
 #define STATE_CMD_ERASE1       0x00000006 /* sector erase first command */
@@ -231,6 +227,14 @@
 #define NS_MAX_PREVSTATES 1
 
 /*
+ * A union to represent flash memory contents and flash buffer.
+ */
+union ns_mem {
+	u_char *byte;    /* for byte access */
+	uint16_t *word;  /* for 16-bit word access */
+};
+
+/*
  * The structure which describes all the internal simulator data.
  */
 struct nandsim {
@@ -247,17 +251,11 @@
 	uint16_t npstates;      /* number of previous states saved */
 	uint16_t stateidx;      /* current state index */
 
-	/* The simulated NAND flash image */
-	union flash_media {
-		u_char *byte;
-		uint16_t    *word;
-	} mem;
+	/* The simulated NAND flash pages array */
+	union ns_mem *pages;
 
 	/* Internal buffer of page + OOB size bytes */
-	union internal_buffer {
-		u_char *byte;    /* for byte access */
-		uint16_t *word;  /* for 16-bit word access */
-	} buf;
+	union ns_mem buf;
 
 	/* NAND flash "geometry" */
 	struct nandsin_geometry {
@@ -346,12 +344,49 @@
 static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
 
 /*
+ * Allocate array of page pointers and initialize the array to NULL
+ * pointers.
+ *
+ * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
+ */
+static int alloc_device(struct nandsim *ns)
+{
+	int i;
+
+	ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
+	if (!ns->pages) {
+		NS_ERR("alloc_map: unable to allocate page array\n");
+		return -ENOMEM;
+	}
+	for (i = 0; i < ns->geom.pgnum; i++) {
+		ns->pages[i].byte = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * Free any allocated pages, and free the array of page pointers.
+ */
+static void free_device(struct nandsim *ns)
+{
+	int i;
+
+	if (ns->pages) {
+		for (i = 0; i < ns->geom.pgnum; i++) {
+			if (ns->pages[i].byte)
+				kfree(ns->pages[i].byte);
+		}
+		vfree(ns->pages);
+	}
+}
+
+/*
  * Initialize the nandsim structure.
  *
  * RETURNS: 0 if success, -ERRNO if failure.
  */
-static int
-init_nandsim(struct mtd_info *mtd)
+static int init_nandsim(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
 	struct nandsim   *ns   = (struct nandsim *)(chip->priv);
@@ -405,7 +440,7 @@
 		}
 	} else {
 		if (ns->geom.totsz <= (128 << 20)) {
-			ns->geom.pgaddrbytes  = 5;
+			ns->geom.pgaddrbytes  = 4;
 			ns->geom.secaddrbytes = 2;
 		} else {
 			ns->geom.pgaddrbytes  = 5;
@@ -439,23 +474,8 @@
 	printk("sector address bytes: %u\n",    ns->geom.secaddrbytes);
 	printk("options: %#x\n",                ns->options);
 
-	/* Map / allocate and initialize the flash image */
-#ifdef CONFIG_NS_ABS_POS
-	ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob);
-	if (!ns->mem.byte) {
-		NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n",
-			(void *)CONFIG_NS_ABS_POS);
-		return -ENOMEM;
-	}
-#else
-	ns->mem.byte = vmalloc(ns->geom.totszoob);
-	if (!ns->mem.byte) {
-		NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n",
-			ns->geom.totszoob);
-		return -ENOMEM;
-	}
-	memset(ns->mem.byte, 0xFF, ns->geom.totszoob);
-#endif
+	if (alloc_device(ns) != 0)
+		goto error;
 
 	/* Allocate / initialize the internal buffer */
 	ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
@@ -474,11 +494,7 @@
 	return 0;
 
 error:
-#ifdef CONFIG_NS_ABS_POS
-	iounmap(ns->mem.byte);
-#else
-	vfree(ns->mem.byte);
-#endif
+	free_device(ns);
 
 	return -ENOMEM;
 }
@@ -486,16 +502,10 @@
 /*
  * Free the nandsim structure.
  */
-static void
-free_nandsim(struct nandsim *ns)
+static void free_nandsim(struct nandsim *ns)
 {
 	kfree(ns->buf.byte);
-
-#ifdef CONFIG_NS_ABS_POS
-	iounmap(ns->mem.byte);
-#else
-	vfree(ns->mem.byte);
-#endif
+	free_device(ns);
 
 	return;
 }
@@ -503,8 +513,7 @@
 /*
  * Returns the string representation of 'state' state.
  */
-static char *
-get_state_name(uint32_t state)
+static char *get_state_name(uint32_t state)
 {
 	switch (NS_STATE(state)) {
 		case STATE_CMD_READ0:
@@ -562,8 +571,7 @@
  *
  * RETURNS: 1 if wrong command, 0 if right.
  */
-static int
-check_command(int cmd)
+static int check_command(int cmd)
 {
 	switch (cmd) {
 
@@ -589,8 +597,7 @@
 /*
  * Returns state after command is accepted by command number.
  */
-static uint32_t
-get_state_by_command(unsigned command)
+static uint32_t get_state_by_command(unsigned command)
 {
 	switch (command) {
 		case NAND_CMD_READ0:
@@ -626,8 +633,7 @@
 /*
  * Move an address byte to the correspondent internal register.
  */
-static inline void
-accept_addr_byte(struct nandsim *ns, u_char bt)
+static inline void accept_addr_byte(struct nandsim *ns, u_char bt)
 {
 	uint byte = (uint)bt;
 
@@ -645,8 +651,7 @@
 /*
  * Switch to STATE_READY state.
  */
-static inline void
-switch_to_ready_state(struct nandsim *ns, u_char status)
+static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
 {
 	NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY));
 
@@ -705,8 +710,7 @@
  *          -1 - several matches.
  *           0 - operation is found.
  */
-static int
-find_operation(struct nandsim *ns, uint32_t flag)
+static int find_operation(struct nandsim *ns, uint32_t flag)
 {
 	int opsfound = 0;
 	int i, j, idx = 0;
@@ -791,14 +795,93 @@
 }
 
 /*
+ * Returns a pointer to the current page.
+ */
+static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns)
+{
+	return &(ns->pages[ns->regs.row]);
+}
+
+/*
+ * Retuns a pointer to the current byte, within the current page.
+ */
+static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
+{
+	return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
+}
+
+/*
+ * Fill the NAND buffer with data read from the specified page.
+ */
+static void read_page(struct nandsim *ns, int num)
+{
+	union ns_mem *mypage;
+
+	mypage = NS_GET_PAGE(ns);
+	if (mypage->byte == NULL) {
+		NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
+		memset(ns->buf.byte, 0xFF, num);
+	} else {
+		NS_DBG("read_page: page %d allocated, reading from %d\n",
+			ns->regs.row, ns->regs.column + ns->regs.off);
+		memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
+	}
+}
+
+/*
+ * Erase all pages in the specified sector.
+ */
+static void erase_sector(struct nandsim *ns)
+{
+	union ns_mem *mypage;
+	int i;
+
+	mypage = NS_GET_PAGE(ns);
+	for (i = 0; i < ns->geom.pgsec; i++) {
+		if (mypage->byte != NULL) {
+			NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
+			kfree(mypage->byte);
+			mypage->byte = NULL;
+		}
+		mypage++;
+	}
+}
+
+/*
+ * Program the specified page with the contents from the NAND buffer.
+ */
+static int prog_page(struct nandsim *ns, int num)
+{
+	int i;
+	union ns_mem *mypage;
+	u_char *pg_off;
+
+	mypage = NS_GET_PAGE(ns);
+	if (mypage->byte == NULL) {
+		NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
+		mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
+		if (mypage->byte == NULL) {
+			NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
+			return -1;
+		}
+		memset(mypage->byte, 0xFF, ns->geom.pgszoob);
+	}
+
+	pg_off = NS_PAGE_BYTE_OFF(ns);
+	for (i = 0; i < num; i++)
+		pg_off[i] &= ns->buf.byte[i];
+
+	return 0;
+}
+
+/*
  * If state has any action bit, perform this action.
  *
  * RETURNS: 0 if success, -1 if error.
  */
-static int
-do_state_action(struct nandsim *ns, uint32_t action)
+static int do_state_action(struct nandsim *ns, uint32_t action)
 {
-	int i, num;
+	int num;
 	int busdiv = ns->busw == 8 ? 1 : 2;
 
 	action &= ACTION_MASK;
@@ -822,7 +905,7 @@
 			break;
 		}
 		num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
-		memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num);
+		read_page(ns, num);
 
 		NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n",
 			num, NS_RAW_OFFSET(ns) + ns->regs.off);
@@ -863,7 +946,7 @@
 				ns->regs.row, NS_RAW_OFFSET(ns));
 		NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift));
 
-		memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob);
+		erase_sector(ns);
 
 		NS_MDELAY(erase_delay);
 
@@ -886,8 +969,8 @@
 			return -1;
 		}
 
-		for (i = 0; i < num; i++)
-			ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i];
+		if (prog_page(ns, num) == -1)
+			return -1;
 
 		NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
 			num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
@@ -928,8 +1011,7 @@
 /*
  * Switch simulator's state.
  */
-static void
-switch_state(struct nandsim *ns)
+static void switch_state(struct nandsim *ns)
 {
 	if (ns->op) {
 		/*
@@ -1070,8 +1152,7 @@
 	}
 }
 
-static u_char
-ns_nand_read_byte(struct mtd_info *mtd)
+static u_char ns_nand_read_byte(struct mtd_info *mtd)
 {
         struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
 	u_char outb = 0x00;
@@ -1144,8 +1225,7 @@
 	return outb;
 }
 
-static void
-ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
+static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
 {
         struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
 
@@ -1308,15 +1388,13 @@
 		ns_nand_write_byte(mtd, cmd);
 }
 
-static int
-ns_device_ready(struct mtd_info *mtd)
+static int ns_device_ready(struct mtd_info *mtd)
 {
 	NS_DBG("device_ready\n");
 	return 1;
 }
 
-static uint16_t
-ns_nand_read_word(struct mtd_info *mtd)
+static uint16_t ns_nand_read_word(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
 
@@ -1325,8 +1403,7 @@
 	return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
 }
 
-static void
-ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
         struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
 
@@ -1353,8 +1430,7 @@
 	}
 }
 
-static void
-ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
         struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
 
@@ -1407,8 +1483,7 @@
 	return;
 }
 
-static int
-ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
 
@@ -1436,14 +1511,12 @@
 	}
 
 	/* Allocate and initialize mtd_info, nand_chip and nandsim structures */
-	nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
+	nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
 				+ sizeof(struct nandsim), GFP_KERNEL);
 	if (!nsmtd) {
 		NS_ERR("unable to allocate core structures.\n");
 		return -ENOMEM;
 	}
-	memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) +
-			sizeof(struct nandsim));
 	chip        = (struct nand_chip *)(nsmtd + 1);
         nsmtd->priv = (void *)chip;
 	nand        = (struct nandsim *)(chip + 1);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 039c759..fd7a8d5 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -56,7 +56,7 @@
 		ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
 	} else
 		ccr |= NDFC_CCR_RESET_CE;
-	writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+	__raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
 }
 
 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index f8c4964..9189ec8 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/rslib.h>
+#include <linux/bitrev.h>
 #include <linux/module.h>
 #include <linux/mtd/compatmac.h>
 #include <linux/mtd/mtd.h>
@@ -152,47 +153,6 @@
 	.oobfree = {{32, 32}}
 };
 
-/* Aargh. I missed the reversed bit order, when I
- * was talking to Renesas about the FPGA.
- *
- * The table is used for bit reordering and inversion
- * of the ecc byte which we get from the FPGA
- */
-static uint8_t revbits[256] = {
-	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-};
-
 #endif
 
 /*
@@ -397,7 +357,7 @@
 	/* Read the syndrom pattern from the FPGA and correct the bitorder */
 	rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
 	for (i = 0; i < 8; i++) {
-		ecc[i] = revbits[(*rs_ecc) & 0xFF];
+		ecc[i] = bitrev8(*rs_ecc);
 		rs_ecc++;
 	}
 
@@ -496,7 +456,7 @@
 		rtn = nand_do_read(mtd, page, len, &retlen, buf);
 
 		/* if read failed or > 1-bit error corrected */
-		if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
+		if (rtn || (mtd->ecc_stats.corrected - corrected) > 1)
 			er_stat |= 1 << 1;
 		kfree(buf);
 	}
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index ff5cef2..8b32035 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -283,7 +283,7 @@
 				   unsigned int ctrl)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-	
+
 	if (cmd == NAND_CMD_NONE)
 		return;
 
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index b5a5f8d..4b1ba4f 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -57,17 +57,16 @@
 
 	DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
 
-	nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
+	nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
 
 	if (!nftl) {
 		printk(KERN_WARNING "NFTL: out of memory for data structures\n");
 		return;
 	}
-	memset(nftl, 0, sizeof(*nftl));
 
 	nftl->mbd.mtd = mtd;
 	nftl->mbd.devnum = -1;
-	nftl->mbd.blksize = 512;
+
 	nftl->mbd.tr = tr;
 
         if (NFTL_mount(nftl) < 0) {
@@ -147,10 +146,9 @@
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
-	ops.len = len;
 
 	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
-	*retlen = ops.retlen;
+	*retlen = ops.oobretlen;
 	return res;
 }
 
@@ -168,10 +166,9 @@
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
-	ops.len = len;
 
 	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
-	*retlen = ops.retlen;
+	*retlen = ops.oobretlen;
 	return res;
 }
 
@@ -797,6 +794,7 @@
 	.name		= "nftl",
 	.major		= NFTL_MAJOR,
 	.part_bits	= NFTL_PARTN_BITS,
+	.blksize 	= 512,
 	.getgeo		= nftl_getgeo,
 	.readsect	= nftl_readblock,
 #ifdef CONFIG_NFTL_RW
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index af06a80..3d44d04 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -45,12 +45,10 @@
 	unsigned long size = res->end - res->start + 1;
 	int err;
 
-	info = kmalloc(sizeof(struct onenand_info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	memset(info, 0, sizeof(struct onenand_info));
-
 	if (!request_mem_region(res->start, size, dev->driver->name)) {
 		err = -EBUSY;
 		goto out_free_info;
@@ -63,6 +61,7 @@
 	}
 
 	info->onenand.mmcontrol = pdata->mmcontrol;
+	info->onenand.irq = platform_get_irq(pdev, 0);
 
 	info->mtd.name = pdev->dev.bus_id;
 	info->mtd.priv = &info->onenand;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 8ed68b2..2da6bb2 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
@@ -191,8 +192,6 @@
 	struct onenand_chip *this = mtd->priv;
 	int value, readcmd = 0, block_cmd = 0;
 	int block, page;
-	/* Now we use page size operation */
-	int sectors = 4, count = 4;
 
 	/* Address translation */
 	switch (cmd) {
@@ -244,6 +243,8 @@
 	}
 
 	if (page != -1) {
+		/* Now we use page size operation */
+		int sectors = 4, count = 4;
 		int dataram;
 
 		switch (cmd) {
@@ -297,7 +298,7 @@
 	unsigned long timeout;
 	unsigned int flags = ONENAND_INT_MASTER;
 	unsigned int interrupt = 0;
-	unsigned int ctrl, ecc;
+	unsigned int ctrl;
 
 	/* The 20 msec is enough */
 	timeout = jiffies + msecs_to_jiffies(20);
@@ -309,7 +310,6 @@
 
 		if (state != FL_READING)
 			cond_resched();
-		touch_softlockup_watchdog();
 	}
 	/* To get correct interrupt status in timeout case */
 	interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -317,28 +317,126 @@
 	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
 	if (ctrl & ONENAND_CTRL_ERROR) {
-		/* It maybe occur at initial bad block */
 		DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
-		/* Clear other interrupt bits for preventing ECC error */
-		interrupt &= ONENAND_INT_MASTER;
-	}
-
-	if (ctrl & ONENAND_CTRL_LOCK) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
-		return -EACCES;
+		if (ctrl & ONENAND_CTRL_LOCK)
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");
+		return ctrl;
 	}
 
 	if (interrupt & ONENAND_INT_READ) {
-		ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
-		if (ecc & ONENAND_ECC_2BIT_ALL) {
+		int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+		if (ecc) {
 			DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
-			return -EBADMSG;
+			if (ecc & ONENAND_ECC_2BIT_ALL) {
+				mtd->ecc_stats.failed++;
+				return ecc;
+			} else if (ecc & ONENAND_ECC_1BIT_ALL)
+				mtd->ecc_stats.corrected++;
 		}
 	}
 
 	return 0;
 }
 
+/*
+ * onenand_interrupt - [DEFAULT] onenand interrupt handler
+ * @param irq		onenand interrupt number
+ * @param dev_id	interrupt data
+ *
+ * complete the work
+ */
+static irqreturn_t onenand_interrupt(int irq, void *data)
+{
+	struct onenand_chip *this = (struct onenand_chip *) data;
+
+	/* To handle shared interrupt */
+	if (!this->complete.done)
+		complete(&this->complete);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * onenand_interrupt_wait - [DEFAULT] wait until the command is done
+ * @param mtd		MTD device structure
+ * @param state		state to select the max. timeout value
+ *
+ * Wait for command done.
+ */
+static int onenand_interrupt_wait(struct mtd_info *mtd, int state)
+{
+	struct onenand_chip *this = mtd->priv;
+
+	wait_for_completion(&this->complete);
+
+	return onenand_wait(mtd, state);
+}
+
+/*
+ * onenand_try_interrupt_wait - [DEFAULT] try interrupt wait
+ * @param mtd		MTD device structure
+ * @param state		state to select the max. timeout value
+ *
+ * Try interrupt based wait (It is used one-time)
+ */
+static int onenand_try_interrupt_wait(struct mtd_info *mtd, int state)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned long remain, timeout;
+
+	/* We use interrupt wait first */
+	this->wait = onenand_interrupt_wait;
+
+	timeout = msecs_to_jiffies(100);
+	remain = wait_for_completion_timeout(&this->complete, timeout);
+	if (!remain) {
+		printk(KERN_INFO "OneNAND: There's no interrupt. "
+				"We use the normal wait\n");
+
+		/* Release the irq */
+		free_irq(this->irq, this);
+
+		this->wait = onenand_wait;
+	}
+
+	return onenand_wait(mtd, state);
+}
+
+/*
+ * onenand_setup_wait - [OneNAND Interface] setup onenand wait method
+ * @param mtd		MTD device structure
+ *
+ * There's two method to wait onenand work
+ * 1. polling - read interrupt status register
+ * 2. interrupt - use the kernel interrupt method
+ */
+static void onenand_setup_wait(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	int syscfg;
+
+	init_completion(&this->complete);
+
+	if (this->irq <= 0) {
+		this->wait = onenand_wait;
+		return;
+	}
+
+	if (request_irq(this->irq, &onenand_interrupt,
+				IRQF_SHARED, "onenand", this)) {
+		/* If we can't get irq, use the normal wait */
+		this->wait = onenand_wait;
+		return;
+	}
+
+	/* Enable interrupt */
+	syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
+	syscfg |= ONENAND_SYS_CFG1_IOBE;
+	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
+
+	this->wait = onenand_try_interrupt_wait;
+}
+
 /**
  * onenand_bufferram_offset - [DEFAULT] BufferRAM offset
  * @param mtd		MTD data structure
@@ -609,9 +707,10 @@
 	size_t *retlen, u_char *buf)
 {
 	struct onenand_chip *this = mtd->priv;
+	struct mtd_ecc_stats stats;
 	int read = 0, column;
 	int thislen;
-	int ret = 0;
+	int ret = 0, boundary = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
 
@@ -627,38 +726,61 @@
 
 	/* TODO handling oob */
 
-	while (read < len) {
-		thislen = min_t(int, mtd->writesize, len - read);
+	stats = mtd->ecc_stats;
 
-		column = from & (mtd->writesize - 1);
-		if (column + thislen > mtd->writesize)
-			thislen = mtd->writesize - column;
+ 	/* Read-while-load method */
 
-		if (!onenand_check_bufferram(mtd, from)) {
-			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
+ 	/* Do first load to bufferRAM */
+ 	if (read < len) {
+ 		if (!onenand_check_bufferram(mtd, from)) {
+ 			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
+ 			ret = this->wait(mtd, FL_READING);
+ 			onenand_update_bufferram(mtd, from, !ret);
+ 		}
+ 	}
 
-			ret = this->wait(mtd, FL_READING);
-			/* First copy data and check return value for ECC handling */
-			onenand_update_bufferram(mtd, from, 1);
-		}
+ 	thislen = min_t(int, mtd->writesize, len - read);
+ 	column = from & (mtd->writesize - 1);
+ 	if (column + thislen > mtd->writesize)
+ 		thislen = mtd->writesize - column;
 
-		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
+ 	while (!ret) {
+ 		/* If there is more to load then start next load */
+ 		from += thislen;
+ 		if (read + thislen < len) {
+ 			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
+ 			/*
+ 			 * Chip boundary handling in DDP
+ 			 * Now we issued chip 1 read and pointed chip 1
+ 			 * bufferam so we have to point chip 0 bufferam.
+ 			 */
+ 			if (this->device_id & ONENAND_DEVICE_IS_DDP &&
+ 					unlikely(from == (this->chipsize >> 1))) {
+ 				this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2);
+ 				boundary = 1;
+ 			} else
+ 				boundary = 0;
+ 			ONENAND_SET_PREV_BUFFERRAM(this);
+ 		}
+ 		/* While load is going, read from last bufferRAM */
+ 		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
+ 		/* See if we are done */
+ 		read += thislen;
+ 		if (read == len)
+ 			break;
+ 		/* Set up for next read from bufferRAM */
+ 		if (unlikely(boundary))
+ 			this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2);
+ 		ONENAND_SET_NEXT_BUFFERRAM(this);
+ 		buf += thislen;
+ 		thislen = min_t(int, mtd->writesize, len - read);
+ 		column = 0;
+ 		cond_resched();
+ 		/* Now wait for load */
+ 		ret = this->wait(mtd, FL_READING);
+ 		onenand_update_bufferram(mtd, from, !ret);
+ 	}
 
-		read += thislen;
-
-		if (read == len)
-			break;
-
-		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
-			goto out;
-		}
-
-		from += thislen;
-		buf += thislen;
-	}
-
-out:
 	/* Deselect and wake up anyone waiting on the device */
 	onenand_release_device(mtd);
 
@@ -668,7 +790,14 @@
 	 * retlen == desired len and result == -EBADMSG
 	 */
 	*retlen = read;
-	return ret;
+
+	if (mtd->ecc_stats.failed - stats.failed)
+		return -EBADMSG;
+
+	if (ret)
+		return ret;
+
+	return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
 /**
@@ -705,6 +834,8 @@
 	column = from & (mtd->oobsize - 1);
 
 	while (read < len) {
+		cond_resched();
+
 		thislen = mtd->oobsize - column;
 		thislen = min_t(int, thislen, len);
 
@@ -717,16 +848,16 @@
 
 		this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
 
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);
+			goto out;
+		}
+
 		read += thislen;
 
 		if (read == len)
 			break;
 
-		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret);
-			goto out;
-		}
-
 		buf += thislen;
 
 		/* Read more? */
@@ -756,8 +887,8 @@
 {
 	BUG_ON(ops->mode != MTD_OOB_PLACE);
 
-	return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len,
-				   &ops->retlen, ops->oobbuf);
+	return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen,
+				   &ops->oobretlen, ops->oobbuf);
 }
 
 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
@@ -804,6 +935,10 @@
 	void __iomem *dataram0, *dataram1;
 	int ret = 0;
 
+	/* In partial page write, just skip it */
+	if ((addr & (mtd->writesize - 1)) != 0)
+		return 0;
+
 	this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
 
 	ret = this->wait(mtd, FL_READING);
@@ -826,7 +961,7 @@
 #define onenand_verify_oob(...)		(0)
 #endif
 
-#define NOTALIGNED(x)	((x & (mtd->writesize - 1)) != 0)
+#define NOTALIGNED(x)	((x & (this->subpagesize - 1)) != 0)
 
 /**
  * onenand_write - [MTD Interface] write buffer to FLASH
@@ -844,6 +979,7 @@
 	struct onenand_chip *this = mtd->priv;
 	int written = 0;
 	int ret = 0;
+	int column, subpage;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
 
@@ -862,45 +998,63 @@
                 return -EINVAL;
         }
 
+	column = to & (mtd->writesize - 1);
+	subpage = column || (len & (mtd->writesize - 1));
+
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_WRITING);
 
 	/* Loop until all data write */
 	while (written < len) {
-		int thislen = min_t(int, mtd->writesize, len - written);
+		int bytes = mtd->writesize;
+		int thislen = min_t(int, bytes, len - written);
+		u_char *wbuf = (u_char *) buf;
 
-		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
+		cond_resched();
 
-		this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
+		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes);
+
+		/* Partial page write */
+		if (subpage) {
+			bytes = min_t(int, bytes - column, (int) len);
+			memset(this->page_buf, 0xff, mtd->writesize);
+			memcpy(this->page_buf + column, buf, bytes);
+			wbuf = this->page_buf;
+			/* Even though partial write, we need page size */
+			thislen = mtd->writesize;
+		}
+
+		this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
 
 		this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
 
-		onenand_update_bufferram(mtd, to, 1);
+		/* In partial page write we don't update bufferram */
+		onenand_update_bufferram(mtd, to, !subpage);
 
 		ret = this->wait(mtd, FL_WRITING);
 		if (ret) {
 			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
-			goto out;
+			break;
+		}
+
+		/* Only check verify write turn on */
+		ret = onenand_verify_page(mtd, (u_char *) wbuf, to);
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
+			break;
 		}
 
 		written += thislen;
 
-		/* Only check verify write turn on */
-		ret = onenand_verify_page(mtd, (u_char *) buf, to);
-		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
-			goto out;
-		}
-
 		if (written == len)
 			break;
 
+		column = 0;
 		to += thislen;
 		buf += thislen;
 	}
 
-out:
 	/* Deselect and wake up anyone waiting on the device */
 	onenand_release_device(mtd);
 
@@ -944,6 +1098,8 @@
 	while (written < len) {
 		int thislen = min_t(int, mtd->oobsize, len - written);
 
+		cond_resched();
+
 		column = to & (mtd->oobsize - 1);
 
 		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
@@ -999,8 +1155,8 @@
 {
 	BUG_ON(ops->mode != MTD_OOB_PLACE);
 
-	return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len,
-				    &ops->retlen, ops->oobbuf);
+	return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen,
+				    &ops->oobretlen, ops->oobbuf);
 }
 
 /**
@@ -1071,6 +1227,7 @@
 	instr->state = MTD_ERASING;
 
 	while (len) {
+		cond_resched();
 
 		/* Check if we have a bad block, we do not erase bad blocks */
 		if (onenand_block_checkbad(mtd, addr, 0, 0)) {
@@ -1084,10 +1241,7 @@
 		ret = this->wait(mtd, FL_ERASING);
 		/* Check, if it is write protected */
 		if (ret) {
-			if (ret == -EPERM)
-				DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n");
-			else
-				DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr = addr;
 			goto erase_exit;
@@ -1129,7 +1283,6 @@
 	onenand_release_device(mtd);
 }
 
-
 /**
  * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
  * @param mtd		MTD device structure
@@ -1196,32 +1349,38 @@
 }
 
 /**
- * onenand_unlock - [MTD Interface] Unlock block(s)
+ * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s)
  * @param mtd		MTD device structure
  * @param ofs		offset relative to mtd start
- * @param len		number of bytes to unlock
+ * @param len		number of bytes to lock or unlock
  *
- * Unlock one or more blocks
+ * Lock or unlock one or more blocks
  */
-static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
 {
 	struct onenand_chip *this = mtd->priv;
 	int start, end, block, value, status;
+	int wp_status_mask;
 
 	start = ofs >> this->erase_shift;
 	end = len >> this->erase_shift;
 
+	if (cmd == ONENAND_CMD_LOCK)
+		wp_status_mask = ONENAND_WP_LS;
+	else
+		wp_status_mask = ONENAND_WP_US;
+
 	/* Continuous lock scheme */
 	if (this->options & ONENAND_HAS_CONT_LOCK) {
 		/* Set start block address */
 		this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
 		/* Set end block address */
 		this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
-		/* Write unlock command */
-		this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+		/* Write lock command */
+		this->command(mtd, cmd, 0, 0);
 
 		/* There's no return value */
-		this->wait(mtd, FL_UNLOCKING);
+		this->wait(mtd, FL_LOCKING);
 
 		/* Sanity check */
 		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1230,7 +1389,7 @@
 
 		/* Check lock status */
 		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
-		if (!(status & ONENAND_WP_US))
+		if (!(status & wp_status_mask))
 			printk(KERN_ERR "wp status = 0x%x\n", status);
 
 		return 0;
@@ -1246,11 +1405,11 @@
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
 		/* Set start block address */
 		this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
-		/* Write unlock command */
-		this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+		/* Write lock command */
+		this->command(mtd, cmd, 0, 0);
 
 		/* There's no return value */
-		this->wait(mtd, FL_UNLOCKING);
+		this->wait(mtd, FL_LOCKING);
 
 		/* Sanity check */
 		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1259,7 +1418,7 @@
 
 		/* Check lock status */
 		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
-		if (!(status & ONENAND_WP_US))
+		if (!(status & wp_status_mask))
 			printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
 	}
 
@@ -1267,6 +1426,32 @@
 }
 
 /**
+ * onenand_lock - [MTD Interface] Lock block(s)
+ * @param mtd		MTD device structure
+ * @param ofs		offset relative to mtd start
+ * @param len		number of bytes to unlock
+ *
+ * Lock one or more blocks
+ */
+static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
+}
+
+/**
+ * onenand_unlock - [MTD Interface] Unlock block(s)
+ * @param mtd		MTD device structure
+ * @param ofs		offset relative to mtd start
+ * @param len		number of bytes to unlock
+ *
+ * Unlock one or more blocks
+ */
+static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+}
+
+/**
  * onenand_check_lock_status - [OneNAND Interface] Check lock status
  * @param this		onenand chip data structure
  *
@@ -1310,7 +1495,7 @@
 		this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
 
 		/* There's no return value */
-		this->wait(mtd, FL_UNLOCKING);
+		this->wait(mtd, FL_LOCKING);
 
 		/* Sanity check */
 		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1334,7 +1519,7 @@
 		return 0;
 	}
 
-	mtd->unlock(mtd, 0x0, this->chipsize);
+	onenand_unlock(mtd, 0x0, this->chipsize);
 
 	return 0;
 }
@@ -1762,7 +1947,7 @@
 	/* Read manufacturer and device IDs from Register */
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
 	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
-	ver_id= this->read_word(this->base + ONENAND_REG_VERSION_ID);
+	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
 
 	/* Check OneNAND device */
 	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
@@ -1846,7 +2031,7 @@
 	if (!this->command)
 		this->command = onenand_command;
 	if (!this->wait)
-		this->wait = onenand_wait;
+		onenand_setup_wait(mtd);
 
 	if (!this->read_bufferram)
 		this->read_bufferram = onenand_read_bufferram;
@@ -1883,23 +2068,30 @@
 	init_waitqueue_head(&this->wq);
 	spin_lock_init(&this->chip_lock);
 
+	/*
+	 * Allow subpage writes up to oobsize.
+	 */
 	switch (mtd->oobsize) {
 	case 64:
 		this->ecclayout = &onenand_oob_64;
+		mtd->subpage_sft = 2;
 		break;
 
 	case 32:
 		this->ecclayout = &onenand_oob_32;
+		mtd->subpage_sft = 1;
 		break;
 
 	default:
 		printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
 			mtd->oobsize);
+		mtd->subpage_sft = 0;
 		/* To prevent kernel oops */
 		this->ecclayout = &onenand_oob_32;
 		break;
 	}
 
+	this->subpagesize = mtd->writesize >> mtd->subpage_sft;
 	mtd->ecclayout = this->ecclayout;
 
 	/* Fill in remaining MTD driver data */
@@ -1922,7 +2114,7 @@
 	mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
 #endif
 	mtd->sync = onenand_sync;
-	mtd->lock = NULL;
+	mtd->lock = onenand_lock;
 	mtd->unlock = onenand_unlock;
 	mtd->suspend = onenand_suspend;
 	mtd->resume = onenand_resume;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 1b00dac..98f8fd1 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -93,13 +93,15 @@
 			ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
 						  readlen, &retlen, &buf[0]);
 
-			if (ret)
+			/* If it is a initial bad block, just ignore it */
+			if (ret && !(ret & ONENAND_CTRL_LOAD))
 				return ret;
 
 			if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
 				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
 					i >> 1, (unsigned int) from);
+				mtd->ecc_stats.badblocks++;
 				break;
 			}
 		}
@@ -177,14 +179,12 @@
 	int len, ret = 0;
 
 	len = mtd->size >> (this->erase_shift + 2);
-	/* Allocate memory (2bit per block) */
-	bbm->bbt = kmalloc(len, GFP_KERNEL);
+	/* Allocate memory (2bit per block) and clear the memory bad block table */
+	bbm->bbt = kzalloc(len, GFP_KERNEL);
 	if (!bbm->bbt) {
 		printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
 		return -ENOMEM;
 	}
-	/* Clear the memory bad block table */
-	memset(bbm->bbt, 0x00, len);
 
 	/* Set the bad block position */
 	bbm->badblockpos = ONENAND_BADBLOCK_POS;
@@ -230,14 +230,12 @@
 	struct onenand_chip *this = mtd->priv;
 	struct bbm_info *bbm;
 
-	this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL);
+	this->bbm = kzalloc(sizeof(struct bbm_info), GFP_KERNEL);
 	if (!this->bbm)
 		return -ENOMEM;
 
 	bbm = this->bbm;
 
-	memset(bbm, 0, sizeof(struct bbm_info));
-
 	/* 1KB page has same configuration as 2KB page */
 	if (!bbm->badblock_pattern)
 		bbm->badblock_pattern = &largepage_memorybased;
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 5b58523..035cd9b 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -96,7 +96,19 @@
 			 */
 			if (swab32(buf[i].size) == master->erasesize) {
 				int j;
-				for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) {
+				for (j = 0; j < numslots; ++j) {
+
+					/* A single 0xff denotes a deleted entry.
+					 * Two of them in a row is the end of the table.
+					 */
+					if (buf[j].name[0] == 0xff) {
+				  		if (buf[j].name[1] == 0xff) {
+							break;
+						} else {
+							continue;
+						}
+					}
+
 					/* The unsigned long fields were written with the
 					 * wrong byte sex, name and pad have no byte sex.
 					 */
@@ -110,6 +122,9 @@
 				}
 			}
 			break;
+		} else {
+			/* re-calculate of real numslots */
+			numslots = buf[i].size / sizeof(struct fis_image_desc);
 		}
 	}
 	if (i == numslots) {
@@ -123,8 +138,13 @@
 	for (i = 0; i < numslots; i++) {
 		struct fis_list *new_fl, **prev;
 
-		if (buf[i].name[0] == 0xff)
-			continue;
+		if (buf[i].name[0] == 0xff) {
+			if (buf[i].name[1] == 0xff) {
+				break;
+			} else {
+				continue;
+			}
+		}
 		if (!redboot_checksum(&buf[i]))
 			break;
 
@@ -165,15 +185,13 @@
 		}
 	}
 #endif
-	parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
+	parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
 
 	if (!parts) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
-
 	nullname = (char *)&parts[nrparts];
 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
 	if (nulllen > 0) {
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 0f3baa5..d4b1ba8 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -787,7 +787,6 @@
 
 	if (scan_header(part) == 0) {
 		part->mbd.size = part->sector_count;
-		part->mbd.blksize = SECTOR_SIZE;
 		part->mbd.tr = tr;
 		part->mbd.devnum = -1;
 		if (!(mtd->flags & MTD_WRITEABLE))
@@ -829,6 +828,8 @@
 	.name		= "rfd",
 	.major		= RFD_FTL_MAJOR,
 	.part_bits	= PART_BITS,
+	.blksize 	= SECTOR_SIZE,
+
 	.readsect	= rfd_ftl_readsect,
 	.writesect	= rfd_ftl_writesect,
 	.getgeo		= rfd_ftl_getgeo,
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 79d3bb6..a5f3d60 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -172,13 +172,12 @@
 
 	ops.mode = MTD_OOB_RAW;
 	ops.ooboffs = 0;
-	ops.ooblen = mtd->oobsize;
-	ops.len = OOB_SIZE;
+	ops.ooblen = OOB_SIZE;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
 
 	ret = mtd->read_oob(mtd, offs, &ops);
-	if (ret < 0 || ops.retlen != OOB_SIZE)
+	if (ret < 0 || ops.oobretlen != OOB_SIZE)
 		return -1;
 
 	return 0;
@@ -312,7 +311,6 @@
 
 	ssfdc->mbd.mtd = mtd;
 	ssfdc->mbd.devnum = -1;
-	ssfdc->mbd.blksize = SECTOR_SIZE;
 	ssfdc->mbd.tr = tr;
 	ssfdc->mbd.readonly = 1;
 
@@ -447,6 +445,7 @@
 	.name		= "ssfdc",
 	.major		= SSFDCR_MAJOR,
 	.part_bits	= SSFDCR_PARTN_BITS,
+	.blksize	= SECTOR_SIZE,
 	.getgeo		= ssfdcr_getgeo,
 	.readsect	= ssfdcr_readsect,
 	.add_mtd	= ssfdcr_add_mtd,
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index e2cb19b..6f93a76 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -765,17 +765,18 @@
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned entry;
 	u32 eor, flags;
+	unsigned long intr_flags;
 #if CP_VLAN_TAG_USED
 	u32 vlan_tag = 0;
 #endif
 	int mss = 0;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, intr_flags);
 
 	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
-		spin_unlock_irq(&cp->lock);
+		spin_unlock_irqrestore(&cp->lock, intr_flags);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
 		return 1;
@@ -908,7 +909,7 @@
 	if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
 		netif_stop_queue(dev);
 
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, intr_flags);
 
 	cpw8(TxPoll, NormalTxPoll);
 	dev->trans_start = jiffies;
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 8236f26..640d7ca 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -1066,8 +1066,8 @@
 	short length = skb->len;
 	dev->trans_start = jiffies;
 
-	DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%x) called\n", dev->name,
-				skb->len, (unsigned int)skb->data));
+	DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%p) called\n",
+				dev->name, skb->len, skb->data));
 
 	if (skb->len < ETH_ZLEN) {
 		if (skb_padto(skb, ETH_ZLEN))
@@ -1246,7 +1246,8 @@
 	dev->priv = (void *)(dev->mem_start);
 
 	lp = dev->priv;
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
+	DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%zd bytes), "
+			"lp->scb at 0x%08lx\n",
 			dev->name, (unsigned long)lp,
 			sizeof(struct i596_private), (unsigned long)&lp->scb));
 	memset((void *) lp, 0, sizeof(struct i596_private));
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 5eb2ec6..303a8d9 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -110,6 +110,11 @@
 
 static void b44_halt(struct b44 *);
 static void b44_init_rings(struct b44 *);
+
+#define B44_FULL_RESET		1
+#define B44_FULL_RESET_SKIP_PHY	2
+#define B44_PARTIAL_RESET	3
+
 static void b44_init_hw(struct b44 *, int);
 
 static int dma_desc_align_mask;
@@ -752,7 +757,7 @@
 		                             dest_idx * sizeof(dest_desc),
 		                             DMA_BIDIRECTIONAL);
 
-	pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
+	pci_dma_sync_single_for_device(bp->pdev, le32_to_cpu(src_desc->addr),
 				       RX_PKT_BUF_SZ,
 				       PCI_DMA_FROMDEVICE);
 }
@@ -884,7 +889,7 @@
 		spin_lock_irqsave(&bp->lock, flags);
 		b44_halt(bp);
 		b44_init_rings(bp);
-		b44_init_hw(bp, 1);
+		b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
 		netif_wake_queue(bp->dev);
 		spin_unlock_irqrestore(&bp->lock, flags);
 		done = 1;
@@ -954,7 +959,7 @@
 
 	b44_halt(bp);
 	b44_init_rings(bp);
-	b44_init_hw(bp, 1);
+	b44_init_hw(bp, B44_FULL_RESET);
 
 	spin_unlock_irq(&bp->lock);
 
@@ -1071,7 +1076,7 @@
 	b44_halt(bp);
 	dev->mtu = new_mtu;
 	b44_init_rings(bp);
-	b44_init_hw(bp, 1);
+	b44_init_hw(bp, B44_FULL_RESET);
 	spin_unlock_irq(&bp->lock);
 
 	b44_enable_ints(bp);
@@ -1368,12 +1373,12 @@
  * packet processing.  Invoked with bp->lock held.
  */
 static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp, int full_reset)
+static void b44_init_hw(struct b44 *bp, int reset_kind)
 {
 	u32 val;
 
 	b44_chip_reset(bp);
-	if (full_reset) {
+	if (reset_kind == B44_FULL_RESET) {
 		b44_phy_reset(bp);
 		b44_setup_phy(bp);
 	}
@@ -1390,7 +1395,10 @@
 	bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
 
 	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
-	if (full_reset) {
+	if (reset_kind == B44_PARTIAL_RESET) {
+		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+	} else {
 		bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
 		bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
 		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
@@ -1401,9 +1409,6 @@
 		bp->rx_prod = bp->rx_pending;
 
 		bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-	} else {
-		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
 	}
 
 	val = br32(bp, B44_ENET_CTRL);
@@ -1420,7 +1425,7 @@
 		goto out;
 
 	b44_init_rings(bp);
-	b44_init_hw(bp, 1);
+	b44_init_hw(bp, B44_FULL_RESET);
 
 	b44_check_phy(bp);
 
@@ -1629,7 +1634,7 @@
 	netif_poll_enable(dev);
 
 	if (bp->flags & B44_FLAG_WOL_ENABLE) {
-		b44_init_hw(bp, 0);
+		b44_init_hw(bp, B44_PARTIAL_RESET);
 		b44_setup_wol(bp);
 	}
 
@@ -1905,7 +1910,7 @@
 
 	b44_halt(bp);
 	b44_init_rings(bp);
-	b44_init_hw(bp, 1);
+	b44_init_hw(bp, B44_FULL_RESET);
 	netif_wake_queue(bp->dev);
 	spin_unlock_irq(&bp->lock);
 
@@ -1948,7 +1953,7 @@
 	if (bp->flags & B44_FLAG_PAUSE_AUTO) {
 		b44_halt(bp);
 		b44_init_rings(bp);
-		b44_init_hw(bp, 1);
+		b44_init_hw(bp, B44_FULL_RESET);
 	} else {
 		__b44_set_flow_ctrl(bp, bp->flags);
 	}
@@ -2304,7 +2309,7 @@
 
 	free_irq(dev->irq, dev);
 	if (bp->flags & B44_FLAG_WOL_ENABLE) {
-		b44_init_hw(bp, 0);
+		b44_init_hw(bp, B44_PARTIAL_RESET);
 		b44_setup_wol(bp);
 	}
 	pci_disable_device(pdev);
@@ -2315,21 +2320,32 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct b44 *bp = netdev_priv(dev);
+	int rc = 0;
 
 	pci_restore_state(pdev);
-	pci_enable_device(pdev);
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		printk(KERN_ERR PFX "%s: pci_enable_device failed\n",
+			dev->name);
+		return rc;
+	}
+
 	pci_set_master(pdev);
 
 	if (!netif_running(dev))
 		return 0;
 
-	if (request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev))
+	rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
+	if (rc) {
 		printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
+		pci_disable_device(pdev);
+		return rc;
+	}
 
 	spin_lock_irq(&bp->lock);
 
 	b44_init_rings(bp);
-	b44_init_hw(bp, 1);
+	b44_init_hw(bp, B44_FULL_RESET);
 	netif_device_attach(bp->dev);
 	spin_unlock_irq(&bp->lock);
 
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index ada5e9b..ee7b75b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -57,8 +57,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.5.2"
-#define DRV_MODULE_RELDATE	"December 13, 2006"
+#define DRV_MODULE_VERSION	"1.5.5"
+#define DRV_MODULE_RELDATE	"February 1, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -1345,8 +1345,6 @@
 {
 	u32 val;
 
-	bp->phy_flags |= PHY_CRC_FIX_FLAG;
-
 	if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
 		bnx2_write_phy(bp, 0x18, 0x0c00);
 		bnx2_write_phy(bp, 0x17, 0x000a);
@@ -1358,6 +1356,14 @@
 		bnx2_write_phy(bp, 0x18, 0x0400);
 	}
 
+	if (bp->phy_flags & PHY_DIS_EARLY_DAC_FLAG) {
+		bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS,
+			       MII_BNX2_DSP_EXPAND_REG | 0x8);
+		bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
+		val &= ~(1 << 8);
+		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
+	}
+
 	if (bp->dev->mtu > 1500) {
 		/* Set extended packet length bit */
 		bnx2_write_phy(bp, 0x18, 0x7);
@@ -3085,7 +3091,7 @@
 		int buf_size)
 {
 	u32 written, offset32, len32;
-	u8 *buf, start[4], end[4], *flash_buffer = NULL;
+	u8 *buf, start[4], end[4], *align_buf = NULL, *flash_buffer = NULL;
 	int rc = 0;
 	int align_start, align_end;
 
@@ -3113,16 +3119,17 @@
 	}
 
 	if (align_start || align_end) {
-		buf = kmalloc(len32, GFP_KERNEL);
-		if (buf == NULL)
+		align_buf = kmalloc(len32, GFP_KERNEL);
+		if (align_buf == NULL)
 			return -ENOMEM;
 		if (align_start) {
-			memcpy(buf, start, 4);
+			memcpy(align_buf, start, 4);
 		}
 		if (align_end) {
-			memcpy(buf + len32 - 4, end, 4);
+			memcpy(align_buf + len32 - 4, end, 4);
 		}
-		memcpy(buf + align_start, data_buf, buf_size);
+		memcpy(align_buf + align_start, data_buf, buf_size);
+		buf = align_buf;
 	}
 
 	if (bp->flash_info->buffered == 0) {
@@ -3256,11 +3263,8 @@
 	}
 
 nvram_write_end:
-	if (bp->flash_info->buffered == 0)
-		kfree(flash_buffer);
-
-	if (align_start || align_end)
-		kfree(buf);
+	kfree(flash_buffer);
+	kfree(align_buf);
 	return rc;
 }
 
@@ -5645,6 +5649,44 @@
 }
 #endif
 
+static void __devinit
+bnx2_get_5709_media(struct bnx2 *bp)
+{
+	u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
+	u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID;
+	u32 strap;
+
+	if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
+		return;
+	else if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) {
+		bp->phy_flags |= PHY_SERDES_FLAG;
+		return;
+	}
+
+	if (val & BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
+		strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
+	else
+		strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
+
+	if (PCI_FUNC(bp->pdev->devfn) == 0) {
+		switch (strap) {
+		case 0x4:
+		case 0x5:
+		case 0x6:
+			bp->phy_flags |= PHY_SERDES_FLAG;
+			return;
+		}
+	} else {
+		switch (strap) {
+		case 0x1:
+		case 0x2:
+		case 0x4:
+			bp->phy_flags |= PHY_SERDES_FLAG;
+			return;
+		}
+	}
+}
+
 static int __devinit
 bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 {
@@ -5811,9 +5853,11 @@
 	reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE);
 
 	if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
-	    BNX2_SHM_HDR_SIGNATURE_SIG)
-		bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0);
-	else
+	    BNX2_SHM_HDR_SIGNATURE_SIG) {
+		u32 off = PCI_FUNC(pdev->devfn) << 2;
+
+		bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0 + off);
+	} else
 		bp->shmem_base = HOST_VIEW_SHMEM_BASE;
 
 	/* Get the permanent MAC address.  First we need to make sure the
@@ -5865,10 +5909,9 @@
 	bp->phy_addr = 1;
 
 	/* Disable WOL support if we are running on a SERDES chip. */
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		if (CHIP_BOND_ID(bp) != BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
-			bp->phy_flags |= PHY_SERDES_FLAG;
-	} else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		bnx2_get_5709_media(bp);
+	else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
 		bp->phy_flags |= PHY_SERDES_FLAG;
 
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
@@ -5880,7 +5923,11 @@
 			if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
 				bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
 		}
-	}
+	} else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
+		   CHIP_NUM(bp) == CHIP_NUM_5708)
+		bp->phy_flags |= PHY_CRC_FIX_FLAG;
+	else if (CHIP_ID(bp) == CHIP_ID_5709_A0)
+		bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG;
 
 	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
 	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 13b6f9b..ccbdf81 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6288,6 +6288,10 @@
 
 #define BCM5708S_TX_ACTL3			0x17
 
+#define MII_BNX2_DSP_RW_PORT			0x15
+#define MII_BNX2_DSP_ADDRESS			0x17
+#define MII_BNX2_DSP_EXPAND_REG			 0x0f00
+
 #define MIN_ETHERNET_PACKET_SIZE	60
 #define MAX_ETHERNET_PACKET_SIZE	1514
 #define MAX_ETHERNET_JUMBO_PACKET_SIZE	9014
@@ -6489,6 +6493,7 @@
 #define PHY_INT_MODE_MASK_FLAG		0x300
 #define PHY_INT_MODE_AUTO_POLLING_FLAG	0x100
 #define PHY_INT_MODE_LINK_READY_FLAG	0x200
+#define PHY_DIS_EARLY_DAC_FLAG		0x400
 
 	u32			chip_id;
 	/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
@@ -6512,6 +6517,7 @@
 #define CHIP_ID_5708_A0			0x57080000
 #define CHIP_ID_5708_B0			0x57081000
 #define CHIP_ID_5708_B1			0x57081010
+#define CHIP_ID_5709_A0			0x57090000
 
 #define CHIP_BOND_ID(bp)		(((bp)->chip_id) & 0xf)
 
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index dc434fb..0978c9a 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -151,8 +151,8 @@
 	struct slave *next;
 	struct slave *prev;
 	int    delay;
-	u32    jiffies;
-	u32    last_arp_rx;
+	unsigned long jiffies;
+	unsigned long last_arp_rx;
 	s8     link;    /* one of BOND_LINK_XXXX */
 	s8     state;   /* one of BOND_STATE_XXXX */
 	u32    original_flags;
@@ -242,7 +242,8 @@
 	return bond->params.arp_validate & (1 << slave->state);
 }
 
-extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave)
+extern inline unsigned long slave_last_rx(struct bonding *bond,
+					struct slave *slave)
 {
 	if (slave_do_arp_validate(bond, slave))
 		return slave->last_arp_rx;
diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c
index c7731b6..82fed1d 100644
--- a/drivers/net/chelsio/my3126.c
+++ b/drivers/net/chelsio/my3126.c
@@ -170,9 +170,10 @@
 {
 	struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
 
-	if (cphy)
-		cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
+	if (!cphy)
+		return NULL;
 
+	cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
 	INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
 	cphy->bmsr = 0;
 
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index c2ae2a2..0cefef5 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2718,12 +2718,11 @@
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
 
-#ifdef CONFIG_E100_NAPI
 	if (netif_running(netdev))
 		netif_poll_disable(nic->netdev);
-#endif
 	del_timer_sync(&nic->watchdog);
 	netif_carrier_off(nic->netdev);
+	netif_device_detach(netdev);
 
 	pci_save_state(pdev);
 
@@ -2736,6 +2735,7 @@
 	}
 
 	pci_disable_device(pdev);
+	free_irq(pdev->irq, netdev);
 	pci_set_power_state(pdev, PCI_D3hot);
 
 	return 0;
@@ -2759,16 +2759,13 @@
 }
 #endif /* CONFIG_PM */
 
-
 static void e100_shutdown(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
 
-#ifdef CONFIG_E100_NAPI
 	if (netif_running(netdev))
 		netif_poll_disable(nic->netdev);
-#endif
 	del_timer_sync(&nic->watchdog);
 	netif_carrier_off(nic->netdev);
 
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 4c1ff75..c6259c7 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -995,12 +995,6 @@
 	   (adapter->hw.mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 
-#ifdef CONFIG_DEBUG_SLAB
-	/* 82544's work arounds do not play nicely with DEBUG SLAB */
-	if (adapter->hw.mac_type == e1000_82544)
-		netdev->features &= ~NETIF_F_TSO;
-#endif
-
 #ifdef NETIF_F_TSO6
 	if (adapter->hw.mac_type > e1000_82547_rev_2)
 		netdev->features |= NETIF_F_TSO6;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 39ad9f7..272e1ec 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0043"
+#define DRV_VERSION	"EHEA_0045"
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
 	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 83fa32f..9de2d38 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -558,12 +558,12 @@
 	u32 qp_token;
 
 	eqe = ehea_poll_eq(port->qp_eq);
-	ehea_debug("eqe=%p", eqe);
+
 	while (eqe) {
-		ehea_debug("*eqe=%lx", *(u64*)eqe);
-		eqe = ehea_poll_eq(port->qp_eq);
 		qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
-		ehea_debug("next eqe=%p", eqe);
+		ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
+			   eqe->entry, qp_token);
+		eqe = ehea_poll_eq(port->qp_eq);
 	}
 
 	return IRQ_HANDLED;
@@ -575,8 +575,9 @@
 	int i;
 
 	for (i = 0; i < adapter->num_ports; i++)
-		if (adapter->port[i]->logical_port_id == logical_port)
-			return adapter->port[i];
+		if (adapter->port[i])
+	                if (adapter->port[i]->logical_port_id == logical_port)
+				return adapter->port[i];
 	return NULL;
 }
 
@@ -642,6 +643,8 @@
 		break;
 	}
 
+	port->autoneg = 1;
+
 	/* Number of default QPs */
 	port->num_def_qps = cb0->num_default_qps;
 
@@ -728,10 +731,7 @@
 		}
 	} else {
 		if (hret == H_AUTHORITY) {
-			ehea_info("Hypervisor denied setting port speed. Either"
-				  " this partition is not authorized to set "
-				  "port speed or another partition has modified"
-				  " port speed first.");
+			ehea_info("Hypervisor denied setting port speed");
 			ret = -EPERM;
 		} else {
 			ret = -EIO;
@@ -998,7 +998,7 @@
 		     | EHEA_BMASK_SET(PXLY_RC_JUMBO_FRAME, 1);
 
 	for (i = 0; i < port->num_def_qps; i++)
-		cb0->default_qpn_arr[i] = port->port_res[i].qp->init_attr.qp_nr;
+		cb0->default_qpn_arr[i] = port->port_res[0].qp->init_attr.qp_nr;
 
 	if (netif_msg_ifup(port))
 		ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port");
@@ -1485,11 +1485,12 @@
 
 static void ehea_promiscuous_error(u64 hret, int enable)
 {
-	ehea_info("Hypervisor denied %sabling promiscuous mode.%s",
-		  enable == 1 ? "en" : "dis",
-		  hret != H_AUTHORITY ? "" : " Another partition owning a "
-		  "logical port on the same physical port might have altered "
-		  "promiscuous mode first.");
+	if (hret == H_AUTHORITY)
+		ehea_info("Hypervisor denied %sabling promiscuous mode",
+			  enable == 1 ? "en" : "dis");
+	else
+		ehea_error("failed %sabling promiscuous mode",
+			   enable == 1 ? "en" : "dis");
 }
 
 static void ehea_promiscuous(struct net_device *dev, int enable)
@@ -2267,6 +2268,8 @@
 int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
 {
 	struct hcp_query_ehea *cb;
+	struct device_node *lhea_dn = NULL;
+	struct device_node *eth_dn = NULL;
 	u64 hret;
 	int ret;
 
@@ -2283,7 +2286,18 @@
 		goto out_herr;
 	}
 
-	adapter->num_ports = cb->num_ports;
+	/* Determine the number of available logical ports
+	 * by counting the child nodes of the lhea OFDT entry
+	 */
+	adapter->num_ports = 0;
+	lhea_dn = of_find_node_by_name(lhea_dn, "lhea");
+	do {
+		eth_dn = of_get_next_child(lhea_dn, eth_dn);
+		if (eth_dn)
+			adapter->num_ports++;
+	} while ( eth_dn );
+	of_node_put(lhea_dn);
+
 	adapter->max_mc_mac = cb->max_mc_mac - 1;
 	ret = 0;
 
@@ -2302,6 +2316,7 @@
 	struct ehea_adapter *adapter = port->adapter;
 	struct hcp_ehea_port_cb4 *cb4;
 	u32 *dn_log_port_id;
+	int jumbo = 0;
 
 	sema_init(&port->port_lock, 1);
 	port->state = EHEA_PORT_DOWN;
@@ -2334,8 +2349,6 @@
 
 	INIT_LIST_HEAD(&port->mc_list->list);
 
-	ehea_set_portspeed(port, EHEA_SPEED_AUTONEG);
-
 	ret = ehea_sense_port_attr(port);
 	if (ret)
 		goto out;
@@ -2345,13 +2358,25 @@
 	if (!cb4) {
 		ehea_error("no mem for cb4");
 	} else {
-		cb4->jumbo_frame = 1;
-		hret = ehea_h_modify_ehea_port(adapter->handle,
-					       port->logical_port_id,
-					       H_PORT_CB4, H_PORT_CB4_JUMBO,
-					       cb4);
-		if (hret != H_SUCCESS) {
-			ehea_info("Jumbo frames not activated");
+		hret = ehea_h_query_ehea_port(adapter->handle,
+					      port->logical_port_id,
+					      H_PORT_CB4,
+					      H_PORT_CB4_JUMBO, cb4);
+
+		if (hret == H_SUCCESS) {
+			if (cb4->jumbo_frame)
+				jumbo = 1;
+			else {
+				cb4->jumbo_frame = 1;
+				hret = ehea_h_modify_ehea_port(adapter->handle,
+							       port->
+							        logical_port_id,
+							       H_PORT_CB4,
+							       H_PORT_CB4_JUMBO,
+							       cb4);
+				if (hret == H_SUCCESS)
+					jumbo = 1;
+			}
 		}
 		kfree(cb4);
 	}
@@ -2390,6 +2415,9 @@
 		goto out_free;
 	}
 
+	ehea_info("%s: Jumbo frames are %sabled", dev->name,
+		  jumbo == 1 ? "en" : "dis");
+
 	port->netdev = dev;
 	ret = 0;
 	goto out;
@@ -2471,14 +2499,16 @@
 
 	adapter_handle = (u64*)get_property(dev->ofdev.node, "ibm,hea-handle",
 					    NULL);
-	if (!adapter_handle) {
+	if (adapter_handle)
+		adapter->handle = *adapter_handle;
+
+	if (!adapter->handle) {
 		dev_err(&dev->ofdev.dev, "failed getting handle for adapter"
 			" '%s'\n", dev->ofdev.node->full_name);
 		ret = -ENODEV;
 		goto out_free_ad;
 	}
 
-	adapter->handle = *adapter_handle;
 	adapter->pd = EHEA_PD_ID;
 
 	dev->ofdev.dev.driver_data = adapter;
@@ -2568,6 +2598,7 @@
 	destroy_workqueue(adapter->ehea_wq);
 
 	ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+	tasklet_kill(&adapter->neq_tasklet);
 
 	ehea_destroy_eq(adapter->neq);
 
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 0cfc2bc..37716e0 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -94,6 +94,7 @@
 {
 	long ret;
 	int i, sleep_msecs;
+	u8 cb_cat;
 
 	for (i = 0; i < 5; i++) {
 		ret = plpar_hcall9(opcode, outs,
@@ -106,7 +107,13 @@
 			continue;
 		}
 
-		if (ret < H_SUCCESS)
+		cb_cat = EHEA_BMASK_GET(H_MEHEAPORT_CAT, arg2);
+
+		if ((ret < H_SUCCESS) && !(((ret == H_AUTHORITY)
+		    && (opcode == H_MODIFY_HEA_PORT))
+		    && (((cb_cat == H_PORT_CB4) && ((arg3 == H_PORT_CB4_JUMBO)
+		    || (arg3 == H_PORT_CB4_SPEED))) || ((cb_cat == H_PORT_CB7)
+		    && (arg3 == H_PORT_CB7_DUCQPN)))))
 			ehea_error("opcode=%lx ret=%lx"
 				   " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
 				   " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
@@ -120,7 +127,6 @@
 				   outs[0], outs[1], outs[2], outs[3],
 				   outs[4], outs[5], outs[6], outs[7],
 				   outs[8]);
-
 		return ret;
 	}
 
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 2f48fe9..93f2b7a 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -234,6 +234,7 @@
 #define NVREG_XMITCTL_HOST_SEMA_MASK	0x0000f000
 #define NVREG_XMITCTL_HOST_SEMA_ACQ	0x0000f000
 #define NVREG_XMITCTL_HOST_LOADED	0x00004000
+#define NVREG_XMITCTL_TX_PATH_EN	0x01000000
 	NvRegTransmitterStatus = 0x088,
 #define NVREG_XMITSTAT_BUSY	0x01
 
@@ -249,6 +250,7 @@
 #define NVREG_OFFLOAD_NORMAL	RX_NIC_BUFSIZE
 	NvRegReceiverControl = 0x094,
 #define NVREG_RCVCTL_START	0x01
+#define NVREG_RCVCTL_RX_PATH_EN	0x01000000
 	NvRegReceiverStatus = 0x98,
 #define NVREG_RCVSTAT_BUSY	0x01
 
@@ -1169,16 +1171,21 @@
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
+	u32 rx_ctrl = readl(base + NvRegReceiverControl);
 
 	dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
 	/* Already running? Stop it. */
-	if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
-		writel(0, base + NvRegReceiverControl);
+	if ((readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) && !np->mac_in_use) {
+		rx_ctrl &= ~NVREG_RCVCTL_START;
+		writel(rx_ctrl, base + NvRegReceiverControl);
 		pci_push(base);
 	}
 	writel(np->linkspeed, base + NvRegLinkSpeed);
 	pci_push(base);
-	writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
+        rx_ctrl |= NVREG_RCVCTL_START;
+        if (np->mac_in_use)
+		rx_ctrl &= ~NVREG_RCVCTL_RX_PATH_EN;
+	writel(rx_ctrl, base + NvRegReceiverControl);
 	dprintk(KERN_DEBUG "%s: nv_start_rx to duplex %d, speed 0x%08x.\n",
 				dev->name, np->duplex, np->linkspeed);
 	pci_push(base);
@@ -1186,39 +1193,59 @@
 
 static void nv_stop_rx(struct net_device *dev)
 {
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
+	u32 rx_ctrl = readl(base + NvRegReceiverControl);
 
 	dprintk(KERN_DEBUG "%s: nv_stop_rx\n", dev->name);
-	writel(0, base + NvRegReceiverControl);
+	if (!np->mac_in_use)
+		rx_ctrl &= ~NVREG_RCVCTL_START;
+	else
+		rx_ctrl |= NVREG_RCVCTL_RX_PATH_EN;
+	writel(rx_ctrl, base + NvRegReceiverControl);
 	reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
 			NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
 			KERN_INFO "nv_stop_rx: ReceiverStatus remained busy");
 
 	udelay(NV_RXSTOP_DELAY2);
-	writel(0, base + NvRegLinkSpeed);
+	if (!np->mac_in_use)
+		writel(0, base + NvRegLinkSpeed);
 }
 
 static void nv_start_tx(struct net_device *dev)
 {
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
+	u32 tx_ctrl = readl(base + NvRegTransmitterControl);
 
 	dprintk(KERN_DEBUG "%s: nv_start_tx\n", dev->name);
-	writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl);
+	tx_ctrl |= NVREG_XMITCTL_START;
+	if (np->mac_in_use)
+		tx_ctrl &= ~NVREG_XMITCTL_TX_PATH_EN;
+	writel(tx_ctrl, base + NvRegTransmitterControl);
 	pci_push(base);
 }
 
 static void nv_stop_tx(struct net_device *dev)
 {
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
+	u32 tx_ctrl = readl(base + NvRegTransmitterControl);
 
 	dprintk(KERN_DEBUG "%s: nv_stop_tx\n", dev->name);
-	writel(0, base + NvRegTransmitterControl);
+	if (!np->mac_in_use)
+		tx_ctrl &= ~NVREG_XMITCTL_START;
+	else
+		tx_ctrl |= NVREG_XMITCTL_TX_PATH_EN;
+	writel(tx_ctrl, base + NvRegTransmitterControl);
 	reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
 			NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
 			KERN_INFO "nv_stop_tx: TransmitterStatus remained busy");
 
 	udelay(NV_TXSTOP_DELAY2);
-	writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
+	if (!np->mac_in_use)
+		writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+		       base + NvRegTransmitPoll);
 }
 
 static void nv_txrx_reset(struct net_device *dev)
@@ -4148,20 +4175,6 @@
 	return 0;
 }
 
-/* Indicate to mgmt unit whether driver is loaded or not */
-static void nv_mgmt_driver_loaded(struct net_device *dev, int loaded)
-{
-	u8 __iomem *base = get_hwbase(dev);
-	u32 tx_ctrl;
-
-	tx_ctrl = readl(base + NvRegTransmitterControl);
-	if (loaded)
-		tx_ctrl |= NVREG_XMITCTL_HOST_LOADED;
-	else
-		tx_ctrl &= ~NVREG_XMITCTL_HOST_LOADED;
-	writel(tx_ctrl, base + NvRegTransmitterControl);
-}
-
 static int nv_open(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -4659,33 +4672,24 @@
 	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
 
 	if (id->driver_data & DEV_HAS_MGMT_UNIT) {
-		writel(0x1, base + 0x204); pci_push(base);
-		msleep(500);
 		/* management unit running on the mac? */
-		np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
-		if (np->mac_in_use) {
-			u32 mgmt_sync;
-			/* management unit setup the phy already? */
-			mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK;
-			if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) {
-				if (!nv_mgmt_acquire_sema(dev)) {
-					for (i = 0; i < 5000; i++) {
-						msleep(1);
-						mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK;
-						if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY)
-							continue;
-						if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT)
-							phyinitialized = 1;
-						break;
+		if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) {
+			np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
+			dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use);
+			for (i = 0; i < 5000; i++) {
+				msleep(1);
+				if (nv_mgmt_acquire_sema(dev)) {
+					/* management unit setup the phy already? */
+					if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
+					    NVREG_XMITCTL_SYNC_PHY_INIT) {
+						/* phy is inited by mgmt unit */
+						phyinitialized = 1;
+						dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
+					} else {
+						/* we need to init the phy */
 					}
-				} else {
-					/* we need to init the phy */
+					break;
 				}
-			} else if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) {
-				/* phy is inited by SMU */
-				phyinitialized = 1;
-			} else {
-				/* we need to init the phy */
 			}
 		}
 	}
@@ -4724,10 +4728,12 @@
 	if (!phyinitialized) {
 		/* reset it */
 		phy_init(dev);
-	}
-
-	if (id->driver_data & DEV_HAS_MGMT_UNIT) {
-		nv_mgmt_driver_loaded(dev, 1);
+	} else {
+		/* see if it is a gigabit phy */
+		u32 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+		if (mii_status & PHY_GIGABIT) {
+			np->gigabit = PHY_GIGABIT;
+		}
 	}
 
 	/* set default link speed settings */
@@ -4749,8 +4755,6 @@
 out_error:
 	if (phystate_orig)
 		writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
-	if (np->mac_in_use)
-		nv_mgmt_driver_loaded(dev, 0);
 	pci_set_drvdata(pci_dev, NULL);
 out_freering:
 	free_rings(dev);
@@ -4780,9 +4784,6 @@
 	writel(np->orig_mac[0], base + NvRegMacAddrA);
 	writel(np->orig_mac[1], base + NvRegMacAddrB);
 
-	if (np->mac_in_use)
-		nv_mgmt_driver_loaded(dev, 0);
-
 	/* free all structures */
 	free_rings(dev);
 	iounmap(get_hwbase(dev));
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index c2c5fd4..ff68394 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -104,9 +104,9 @@
 	fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
 	if (fep->interrupt < 0)
 		return -EINVAL;
-	
+
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-	fep->fec.fecp =(void*)r->start;
+	fep->fec.fecp = ioremap(r->start, r->end - r->start + 1);
 
 	if(fep->fec.fecp == NULL)
 		return -EINVAL;
@@ -319,11 +319,14 @@
 	 * Clear any outstanding interrupt.
 	 */
 	FW(fecp, ievent, 0xffc0);
+#ifndef CONFIG_PPC_MERGE
 	FW(fecp, ivec, (fep->interrupt / 2) << 29);
-	
+#else
+	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
+#endif
 
 	/*
-	 * adjust to speed (only for DUET & RMII) 
+	 * adjust to speed (only for DUET & RMII)
 	 */
 #ifdef CONFIG_DUET
 	if (fpi->use_rmii) {
@@ -418,6 +421,7 @@
 
 static void pre_request_irq(struct net_device *dev, int irq)
 {
+#ifndef CONFIG_PPC_MERGE
 	immap_t *immap = fs_enet_immap;
 	u32 siel;
 
@@ -431,6 +435,7 @@
 			siel &= ~(0x80000000 >> (irq & ~1));
 		out_be32(&immap->im_siu_conf.sc_siel, siel);
 	}
+#endif
 }
 
 static void post_free_irq(struct net_device *dev, int irq)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 95ec587..afd7fca 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -121,13 +121,13 @@
 		return -EINVAL;
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-	fep->scc.sccp = (void *)r->start;
+	fep->scc.sccp = ioremap(r->start, r->end - r->start + 1);
 
 	if (fep->scc.sccp == NULL)
 		return -EINVAL;
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
-	fep->scc.ep = (void *)r->start;
+	fep->scc.ep = ioremap(r->start, r->end - r->start + 1);
 
 	if (fep->scc.ep == NULL)
 		return -EINVAL;
@@ -397,6 +397,7 @@
 
 static void pre_request_irq(struct net_device *dev, int irq)
 {
+#ifndef CONFIG_PPC_MERGE
 	immap_t *immap = fs_enet_immap;
 	u32 siel;
 
@@ -410,6 +411,7 @@
 			siel &= ~(0x80000000 >> (irq & ~1));
 		out_be32(&immap->im_siu_conf.sc_siel, siel);
 	}
+#endif
 }
 
 static void post_free_irq(struct net_device *dev, int irq)
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 896aa02..feb0ada 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -113,7 +113,7 @@
 
 config BAYCOM_SER_FDX
 	tristate "BAYCOM ser12 fullduplex driver for AX.25"
-	depends on AX25
+	depends on AX25 && !S390
 	select CRC_CCITT
 	---help---
 	  This is one of two drivers for Baycom style simple amateur radio
@@ -133,7 +133,7 @@
 
 config BAYCOM_SER_HDX
 	tristate "BAYCOM ser12 halfduplex driver for AX.25"
-	depends on AX25
+	depends on AX25 && !S390
 	select CRC_CCITT
 	---help---
 	  This is one of two drivers for Baycom style simple amateur radio
@@ -181,7 +181,7 @@
 
 config YAM
 	tristate "YAM driver for AX.25"
-	depends on AX25
+	depends on AX25 && !S390
 	help
 	  The YAM is a modem for packet radio which connects to the serial
 	  port and includes some of the functions of a Terminal Node
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 3ca1082..340ee99 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -441,25 +441,13 @@
 		goto drop;
 	}
 
-	/* Make sure there is room for IrDA-USB header. The actual
-	 * allocation will be done lower in skb_push().
-	 * Also, we don't use directly skb_cow(), because it require
-	 * headroom >= 16, which force unnecessary copies - Jean II */
-	if (skb_headroom(skb) < self->header_length) {
-		IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
-		if (skb_cow(skb, self->header_length)) {
-			IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
-			goto drop;
-		}
-	}
+	memcpy(self->tx_buff + self->header_length, skb->data, skb->len);
 
 	/* Change setting for next frame */
-
 	if (self->capability & IUC_STIR421X) {
 		__u8 turnaround_time;
-		__u8* frame;
+		__u8* frame = self->tx_buff;
 		turnaround_time = get_turnaround_time( skb );
-		frame= skb_push(skb, self->header_length);
 		irda_usb_build_header(self, frame, 0);
 		frame[2] = turnaround_time;
 		if ((skb->len != 0) &&
@@ -472,17 +460,17 @@
 			frame[1] = 0;
 		}
 	} else {
-		irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
+		irda_usb_build_header(self, self->tx_buff, 0);
 	}
 
 	/* FIXME: Make macro out of this one */
 	((struct irda_skb_cb *)skb->cb)->context = self;
 
-        usb_fill_bulk_urb(urb, self->usbdev, 
+	usb_fill_bulk_urb(urb, self->usbdev,
 		      usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
-                      skb->data, IRDA_SKB_MAX_MTU,
+                      self->tx_buff, skb->len + self->header_length,
                       write_bulk_callback, skb);
-	urb->transfer_buffer_length = skb->len;
+
 	/* This flag (URB_ZERO_PACKET) indicates that what we send is not
 	 * a continuous stream of data but separate packets.
 	 * In this case, the USB layer will insert an empty USB frame (TD)
@@ -1455,6 +1443,9 @@
 	/* Remove the speed buffer */
 	kfree(self->speed_buff);
 	self->speed_buff = NULL;
+
+	kfree(self->tx_buff);
+	self->tx_buff = NULL;
 }
 
 /********************** USB CONFIG SUBROUTINES **********************/
@@ -1524,8 +1515,6 @@
 
 	IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n",
 		__FUNCTION__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep);
-	/* Should be 8, 16, 32 or 64 bytes */
-	IRDA_ASSERT(self->bulk_out_mtu == 64, ;);
 
 	return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0));
 }
@@ -1753,9 +1742,14 @@
 
 	memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
 
+	self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length,
+				GFP_KERNEL);
+	if (self->tx_buff == NULL)
+		goto err_out_4;
+
 	ret = irda_usb_open(self);
 	if (ret) 
-		goto err_out_4;
+		goto err_out_5;
 
 	IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
 	usb_set_intfdata(intf, self);
@@ -1766,14 +1760,14 @@
 		self->needspatch = (ret < 0);
 		if (self->needspatch) {
 			IRDA_ERROR("STIR421X: Couldn't upload patch\n");
-			goto err_out_5;
+			goto err_out_6;
 		}
 
 		/* replace IrDA class descriptor with what patched device is now reporting */
 		irda_desc = irda_usb_find_class_desc (self->usbintf);
 		if (irda_desc == NULL) {
 			ret = -ENODEV;
-			goto err_out_5;
+			goto err_out_6;
 		}
 		if (self->irda_desc)
 			kfree (self->irda_desc);
@@ -1782,9 +1776,10 @@
 	}
 
 	return 0;
-
-err_out_5:
+err_out_6:
 	unregister_netdev(self->netdev);
+err_out_5:
+	kfree(self->tx_buff);
 err_out_4:
 	kfree(self->speed_buff);
 err_out_3:
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index 6b2271f..e846c38 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -156,6 +156,7 @@
 	struct irlap_cb   *irlap;	/* The link layer we are binded to */
 	struct qos_info qos;
 	char *speed_buff;		/* Buffer for speed changes */
+	char *tx_buff;
 
 	struct timeval stamp;
 	struct timeval now;
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index c14a746..20d306f 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -59,7 +59,7 @@
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
 MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 18c6819..e2b1af6 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -166,7 +166,7 @@
 	unsigned i;
 
 	seq_printf(seq, "\n%s (vid/did: %04x/%04x)\n",
-		   PCIDEV_NAME(pdev), (int)pdev->vendor, (int)pdev->device);
+		   pci_name(pdev), (int)pdev->vendor, (int)pdev->device);
 	seq_printf(seq, "pci-power-state: %u\n", (unsigned) pdev->current_state);
 	seq_printf(seq, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n",
 		   pdev->irq, (unsigned)pci_resource_start(pdev, 0), (unsigned long long)pdev->dma_mask);
@@ -1401,7 +1401,7 @@
 
 	if (vlsi_start_hw(idev))
 		IRDA_ERROR("%s: failed to restart hw - %s(%s) unusable!\n",
-			   __FUNCTION__, PCIDEV_NAME(idev->pdev), ndev->name);
+			   __FUNCTION__, pci_name(idev->pdev), ndev->name);
 	else
 		netif_start_queue(ndev);
 }
@@ -1643,7 +1643,7 @@
 		pdev->current_state = 0; /* hw must be running now */
 
 	IRDA_MESSAGE("%s: IrDA PCI controller %s detected\n",
-		     drivername, PCIDEV_NAME(pdev));
+		     drivername, pci_name(pdev));
 
 	if ( !pci_resource_start(pdev,0)
 	     || !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) {
@@ -1728,7 +1728,7 @@
 
 	pci_set_drvdata(pdev, NULL);
 
-	IRDA_MESSAGE("%s: %s removed\n", drivername, PCIDEV_NAME(pdev));
+	IRDA_MESSAGE("%s: %s removed\n", drivername, pci_name(pdev));
 }
 
 #ifdef CONFIG_PM
@@ -1748,7 +1748,7 @@
 
 	if (!ndev) {
 		IRDA_ERROR("%s - %s: no netdevice \n",
-			   __FUNCTION__, PCIDEV_NAME(pdev));
+			   __FUNCTION__, pci_name(pdev));
 		return 0;
 	}
 	idev = ndev->priv;	
@@ -1759,7 +1759,7 @@
 			pdev->current_state = state.event;
 		}
 		else
-			IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state.event);
+			IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event);
 		up(&idev->sem);
 		return 0;
 	}
@@ -1787,7 +1787,7 @@
 
 	if (!ndev) {
 		IRDA_ERROR("%s - %s: no netdevice \n",
-			   __FUNCTION__, PCIDEV_NAME(pdev));
+			   __FUNCTION__, pci_name(pdev));
 		return 0;
 	}
 	idev = ndev->priv;	
@@ -1795,7 +1795,7 @@
 	if (pdev->current_state == 0) {
 		up(&idev->sem);
 		IRDA_WARNING("%s - %s: already resumed\n",
-			     __FUNCTION__, PCIDEV_NAME(pdev));
+			     __FUNCTION__, pci_name(pdev));
 		return 0;
 	}
 	
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index c37f0bc..2d3b773 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -41,39 +41,6 @@
 #define PCI_CLASS_SUBCLASS_MASK		0xffff
 #endif
 
-/* in recent 2.5 interrupt handlers have non-void return value */
-#ifndef IRQ_RETVAL
-typedef void irqreturn_t;
-#define IRQ_NONE
-#define IRQ_HANDLED
-#define IRQ_RETVAL(x)
-#endif
-
-/* some stuff need to check kernelversion. Not all 2.5 stuff was present
- * in early 2.5.x - the test is merely to separate 2.4 from 2.5
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-/* PDE() introduced in 2.5.4 */
-#ifdef CONFIG_PROC_FS
-#define PDE(inode) ((inode)->i_private)
-#endif
-
-/* irda crc16 calculation exported in 2.5.42 */
-#define irda_calc_crc16(fcs,buf,len)	(GOOD_FCS)
-
-/* we use this for unified pci device name access */
-#define PCIDEV_NAME(pdev)	((pdev)->name)
-
-#else /* 2.5 or later */
-
-/* whatever we get from the associated struct device - bus:slot:dev.fn id */
-#define PCIDEV_NAME(pdev)	(pci_name(pdev))
-
-#endif
-
 /* ================================================================ */
 
 /* non-standard PCI registers */
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 50ffe90..f4aba43 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -171,6 +171,7 @@
 
 	/* TX */
 	struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
+	unsigned int restart_queue;
 	unsigned long timeo_start;
 	uint32_t tx_cmd_type;
 	uint64_t hw_csum_tx_good;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index cd22523..82c044d 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -79,6 +79,7 @@
 	{"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
 	{"tx_deferred_ok", IXGB_STAT(stats.dc)},
 	{"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
+	{"tx_restart_queue", IXGB_STAT(restart_queue) },
 	{"rx_long_length_errors", IXGB_STAT(stats.roc)},
 	{"rx_short_length_errors", IXGB_STAT(stats.ruc)},
 #ifdef NETIF_F_TSO
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index 02089b6..ecbf458 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -399,8 +399,9 @@
 	/* Zero out the other 15 receive addresses. */
 	DEBUGOUT("Clearing RAR[1-15]\n");
 	for(i = 1; i < IXGB_RAR_ENTRIES; i++) {
-		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+		/* Write high reg first to disable the AV bit first */
 		IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
 	}
 
 	return;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index e628126..a083a91 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -36,7 +36,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION		"1.0.117-k2"DRIVERNAPI
+#define DRV_VERSION		"1.0.126-k2"DRIVERNAPI
 char ixgb_driver_version[] = DRV_VERSION;
 static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
@@ -1287,6 +1287,7 @@
 	struct ixgb_buffer *buffer_info;
 	int len = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
+	unsigned int mss = skb_shinfo(skb)->gso_size;
 
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned int f;
@@ -1298,6 +1299,11 @@
 	while(len) {
 		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, IXGB_MAX_DATA_PER_TXD);
+		/* Workaround for premature desc write-backs
+		 * in TSO mode.  Append 4-byte sentinel desc */
+		if (unlikely(mss && !nr_frags && size == len && size > 8))
+			size -= 4;
+
 		buffer_info->length = size;
 		WARN_ON(buffer_info->dma != 0);
 		buffer_info->dma =
@@ -1324,6 +1330,13 @@
 		while(len) {
 			buffer_info = &tx_ring->buffer_info[i];
 			size = min(len, IXGB_MAX_DATA_PER_TXD);
+
+			/* Workaround for premature desc write-backs
+			 * in TSO mode.  Append 4-byte sentinel desc */
+			if (unlikely(mss && !nr_frags && size == len
+			             && size > 8))
+				size -= 4;
+
 			buffer_info->length = size;
 			buffer_info->dma =
 				pci_map_page(adapter->pdev,
@@ -1398,11 +1411,43 @@
 	IXGB_WRITE_REG(&adapter->hw, TDT, i);
 }
 
+static int __ixgb_maybe_stop_tx(struct net_device *netdev, int size)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+
+	netif_stop_queue(netdev);
+	/* Herbert's original patch had:
+	 *  smp_mb__after_netif_stop_queue();
+	 * but since that doesn't exist yet, just open code it. */
+	smp_mb();
+
+	/* We need to check again in a case another CPU has just
+	 * made room available. */
+	if (likely(IXGB_DESC_UNUSED(tx_ring) < size))
+		return -EBUSY;
+
+	/* A reprieve! */
+	netif_start_queue(netdev);
+	++adapter->restart_queue;
+	return 0;
+}
+
+static int ixgb_maybe_stop_tx(struct net_device *netdev,
+                              struct ixgb_desc_ring *tx_ring, int size)
+{
+	if (likely(IXGB_DESC_UNUSED(tx_ring) >= size))
+		return 0;
+	return __ixgb_maybe_stop_tx(netdev, size);
+}
+
+
 /* Tx Descriptors needed, worst case */
 #define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \
 			 (((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
-	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
+#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) /* skb->date */ + \
+	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 /* for context */ \
+	+ 1 /* one more needed for sentinel TSO workaround */
 
 static int
 ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1430,7 +1475,8 @@
 	spin_lock_irqsave(&adapter->tx_lock, flags);
 #endif
 
-	if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+	if (unlikely(ixgb_maybe_stop_tx(netdev, &adapter->tx_ring,
+                     DESC_NEEDED))) {
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&adapter->tx_lock, flags);
 		return NETDEV_TX_BUSY;
@@ -1468,8 +1514,7 @@
 
 #ifdef NETIF_F_LLTX
 	/* Make sure there is space in the ring for the next send. */
-	if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED))
-		netif_stop_queue(netdev);
+	ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED);
 
 	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index c41ae42..b3bf864 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -314,6 +314,13 @@
 
 	while (mp->tx_desc_count > 0) {
 		spin_lock_irqsave(&mp->lock, flags);
+
+		/* tx_desc_count might have changed before acquiring the lock */
+		if (mp->tx_desc_count <= 0) {
+			spin_unlock_irqrestore(&mp->lock, flags);
+			return released;
+		}
+
 		tx_index = mp->tx_used_desc_q;
 		desc = &mp->p_tx_desc_area[tx_index];
 		cmd_sts = desc->cmd_sts;
@@ -332,13 +339,13 @@
 		if (skb)
 			mp->tx_skb[tx_index] = NULL;
 
-		spin_unlock_irqrestore(&mp->lock, flags);
-
 		if (cmd_sts & ETH_ERROR_SUMMARY) {
 			printk("%s: Error in TX\n", dev->name);
 			mp->stats.tx_errors++;
 		}
 
+		spin_unlock_irqrestore(&mp->lock, flags);
+
 		if (cmd_sts & ETH_TX_FIRST_DESC)
 			dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE);
 		else
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 07cf574..61cbd4a 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -71,7 +71,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.1.0"
+#define MYRI10GE_VERSION_STR "1.2.0"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -274,6 +274,10 @@
 module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
 
+static int myri10ge_wcfifo = 1;
+module_param(myri10ge_wcfifo, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
+
 #define MYRI10GE_FW_OFFSET 1024*1024
 #define MYRI10GE_HIGHPART_TO_U32(X) \
 (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -1714,7 +1718,7 @@
 		goto abort_with_irq;
 	}
 
-	if (mgp->mtrr >= 0) {
+	if (myri10ge_wcfifo && mgp->mtrr >= 0) {
 		mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
 		mgp->rx_small.wc_fifo =
 		    (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
@@ -2878,7 +2882,6 @@
 	netdev->hard_start_xmit = myri10ge_xmit;
 	netdev->get_stats = myri10ge_get_stats;
 	netdev->base_addr = mgp->iomem_base;
-	netdev->irq = pdev->irq;
 	netdev->change_mtu = myri10ge_change_mtu;
 	netdev->set_multicast_list = myri10ge_set_multicast_list;
 	netdev->set_mac_address = myri10ge_set_mac_address;
@@ -2888,6 +2891,15 @@
 	netdev->poll = myri10ge_poll;
 	netdev->weight = myri10ge_napi_weight;
 
+	/* make sure we can get an irq, and that MSI can be
+	 * setup (if available).  Also ensure netdev->irq
+	 * is set to correct value if MSI is enabled */
+	status = myri10ge_request_irq(mgp);
+	if (status != 0)
+		goto abort_with_firmware;
+	netdev->irq = pdev->irq;
+	myri10ge_free_irq(mgp);
+
 	/* Save configuration space to be restored if the
 	 * nic resets due to a parity error */
 	pci_save_state(pdev);
@@ -2903,8 +2915,9 @@
 		dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
 		goto abort_with_state;
 	}
-	dev_info(dev, "%d, tx bndry %d, fw %s, WC %s\n",
-		 pdev->irq, mgp->tx.boundary, mgp->fw_name,
+	dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
+		 (mgp->msi_enabled ? "MSI" : "xPIC"),
+		 netdev->irq, mgp->tx.boundary, mgp->fw_name,
 		 (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
 
 	return 0;
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 6490acf..e8598b8 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -63,12 +63,11 @@
 
 #include "netxen_nic_hw.h"
 
-#define NETXEN_NIC_BUILD_NO     "4"
+#define NETXEN_NIC_BUILD_NO     "2"
 #define _NETXEN_NIC_LINUX_MAJOR 3
 #define _NETXEN_NIC_LINUX_MINOR 3
-#define _NETXEN_NIC_LINUX_SUBVERSION 2
-#define NETXEN_NIC_LINUX_VERSIONID  "3.3.2" "-" NETXEN_NIC_BUILD_NO
-#define NETXEN_NIC_FW_VERSIONID "3.3.2"
+#define _NETXEN_NIC_LINUX_SUBVERSION 3
+#define NETXEN_NIC_LINUX_VERSIONID  "3.3.3" "-" NETXEN_NIC_BUILD_NO
 
 #define RCV_DESC_RINGSIZE	\
 	(sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
@@ -240,49 +239,39 @@
 
 typedef u32 netxen_ctx_msg;
 
-#define _netxen_set_bits(config_word, start, bits, val)	{\
-	unsigned long long mask = (((1ULL << (bits)) - 1) << (start));	\
-	unsigned long long value = (val);	\
-	(config_word) &= ~mask;	\
-	(config_word) |= (((value) << (start)) & mask); \
-}
-
 #define netxen_set_msg_peg_id(config_word, val)	\
-	_netxen_set_bits(config_word, 0, 2, val)
+	((config_word) &= ~3, (config_word) |= val & 3)
 #define netxen_set_msg_privid(config_word)	\
-	set_bit(2, (unsigned long*)&config_word)
+	((config_word) |= 1 << 2)
 #define netxen_set_msg_count(config_word, val)	\
-	_netxen_set_bits(config_word, 3, 15, val)
+	((config_word) &= ~(0x7fff<<3), (config_word) |= (val & 0x7fff) << 3)
 #define netxen_set_msg_ctxid(config_word, val)	\
-	_netxen_set_bits(config_word, 18, 10, val)
+	((config_word) &= ~(0x3ff<<18), (config_word) |= (val & 0x3ff) << 18)
 #define netxen_set_msg_opcode(config_word, val)	\
-	_netxen_set_bits(config_word, 28, 4, val)
+	((config_word) &= ~(0xf<<24), (config_word) |= (val & 0xf) << 24)
 
 struct netxen_rcv_context {
-	u32 rcv_ring_addr_lo;
-	u32 rcv_ring_addr_hi;
-	u32 rcv_ring_size;
-	u32 rsrvd;
+	__le64 rcv_ring_addr;
+	__le32 rcv_ring_size;
+	__le32 rsrvd;
 };
 
 struct netxen_ring_ctx {
 
 	/* one command ring */
-	u64 cmd_consumer_offset;
-	u32 cmd_ring_addr_lo;
-	u32 cmd_ring_addr_hi;
-	u32 cmd_ring_size;
-	u32 rsrvd;
+	__le64 cmd_consumer_offset;
+	__le64 cmd_ring_addr;
+	__le32 cmd_ring_size;
+	__le32 rsrvd;
 
 	/* three receive rings */
 	struct netxen_rcv_context rcv_ctx[3];
 
 	/* one status ring */
-	u32 sts_ring_addr_lo;
-	u32 sts_ring_addr_hi;
-	u32 sts_ring_size;
+	__le64 sts_ring_addr;
+	__le32 sts_ring_size;
 
-	u32 ctx_id;
+	__le32 ctx_id;
 } __attribute__ ((aligned(64)));
 
 /*
@@ -306,81 +295,85 @@
 	((cmd_desc)->port_ctxid |= ((var) & 0x0F))
 
 #define netxen_set_cmd_desc_flags(cmd_desc, val)	\
-	_netxen_set_bits((cmd_desc)->flags_opcode, 0, 7, val)
+	((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x7f), \
+	(cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f))
 #define netxen_set_cmd_desc_opcode(cmd_desc, val)	\
-	_netxen_set_bits((cmd_desc)->flags_opcode, 7, 6, val)
+	((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \
+	(cmd_desc)->flags_opcode |= cpu_to_le16((val) & (0x3f<<7)))
 
 #define netxen_set_cmd_desc_num_of_buff(cmd_desc, val)	\
-	_netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 0, 8, val);
+	((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \
+	(cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff))
 #define netxen_set_cmd_desc_totallength(cmd_desc, val)	\
-	_netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 8, 24, val);
+	((cmd_desc)->num_of_buffers_total_length &= cpu_to_le32(0xff), \
+	(cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 24))
 
 #define netxen_get_cmd_desc_opcode(cmd_desc)	\
-	(((cmd_desc)->flags_opcode >> 7) & 0x003F)
+	((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F)
 #define netxen_get_cmd_desc_totallength(cmd_desc)	\
-	(((cmd_desc)->num_of_buffers_total_length >> 8) & 0x0FFFFFF)
+	(le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8)
 
 struct cmd_desc_type0 {
 	u8 tcp_hdr_offset;	/* For LSO only */
 	u8 ip_hdr_offset;	/* For LSO only */
 	/* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */
-	u16 flags_opcode;
+	__le16 flags_opcode;
 	/* Bit pattern: 0-7 total number of segments,
 	   8-31 Total size of the packet */
-	u32 num_of_buffers_total_length;
+	__le32 num_of_buffers_total_length;
 	union {
 		struct {
-			u32 addr_low_part2;
-			u32 addr_high_part2;
+			__le32 addr_low_part2;
+			__le32 addr_high_part2;
 		};
-		u64 addr_buffer2;
+		__le64 addr_buffer2;
 	};
 
-	u16 reference_handle;	/* changed to u16 to add mss */
-	u16 mss;		/* passed by NDIS_PACKET for LSO */
+	__le16 reference_handle;	/* changed to u16 to add mss */
+	__le16 mss;		/* passed by NDIS_PACKET for LSO */
 	/* Bit pattern 0-3 port, 0-3 ctx id */
 	u8 port_ctxid;
 	u8 total_hdr_length;	/* LSO only : MAC+IP+TCP Hdr size */
-	u16 conn_id;		/* IPSec offoad only */
+	__le16 conn_id;		/* IPSec offoad only */
 
 	union {
 		struct {
-			u32 addr_low_part3;
-			u32 addr_high_part3;
+			__le32 addr_low_part3;
+			__le32 addr_high_part3;
 		};
-		u64 addr_buffer3;
+		__le64 addr_buffer3;
 	};
 	union {
 		struct {
-			u32 addr_low_part1;
-			u32 addr_high_part1;
+			__le32 addr_low_part1;
+			__le32 addr_high_part1;
 		};
-		u64 addr_buffer1;
+		__le64 addr_buffer1;
 	};
 
-	u16 buffer1_length;
-	u16 buffer2_length;
-	u16 buffer3_length;
-	u16 buffer4_length;
+	__le16 buffer1_length;
+	__le16 buffer2_length;
+	__le16 buffer3_length;
+	__le16 buffer4_length;
 
 	union {
 		struct {
-			u32 addr_low_part4;
-			u32 addr_high_part4;
+			__le32 addr_low_part4;
+			__le32 addr_high_part4;
 		};
-		u64 addr_buffer4;
+		__le64 addr_buffer4;
 	};
 
-	u64 unused;
+	__le64 unused;
 
 } __attribute__ ((aligned(64)));
 
 /* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
 struct rcv_desc {
-	u16 reference_handle;
-	u16 reserved;
-	u32 buffer_length;	/* allocated buffer length (usually 2K) */
-	u64 addr_buffer;
+	__le16 reference_handle;
+	__le16 reserved;
+	__le32 buffer_length;	/* allocated buffer length (usually 2K) */
+	__le64 addr_buffer;
 };
 
 /* opcode field in status_desc */
@@ -406,36 +399,36 @@
 	(((status_desc)->lro & 0x80) >> 7)
 
 #define netxen_get_sts_port(status_desc)	\
-	((status_desc)->status_desc_data & 0x0F)
+	(le64_to_cpu((status_desc)->status_desc_data) & 0x0F)
 #define netxen_get_sts_status(status_desc)	\
-	(((status_desc)->status_desc_data >> 4) & 0x0F)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 4) & 0x0F)
 #define netxen_get_sts_type(status_desc)	\
-	(((status_desc)->status_desc_data >> 8) & 0x0F)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 8) & 0x0F)
 #define netxen_get_sts_totallength(status_desc)	\
-	(((status_desc)->status_desc_data >> 12) & 0xFFFF)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 12) & 0xFFFF)
 #define netxen_get_sts_refhandle(status_desc)	\
-	(((status_desc)->status_desc_data >> 28) & 0xFFFF)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 28) & 0xFFFF)
 #define netxen_get_sts_prot(status_desc)	\
-	(((status_desc)->status_desc_data >> 44) & 0x0F)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 44) & 0x0F)
 #define netxen_get_sts_owner(status_desc)	\
-	(((status_desc)->status_desc_data >> 56) & 0x03)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 56) & 0x03)
 #define netxen_get_sts_opcode(status_desc)	\
-	(((status_desc)->status_desc_data >> 58) & 0x03F)
+	((le64_to_cpu((status_desc)->status_desc_data) >> 58) & 0x03F)
 
 #define netxen_clear_sts_owner(status_desc)	\
 	((status_desc)->status_desc_data &=	\
-	~(((unsigned long long)3) << 56 ))
+	~cpu_to_le64(((unsigned long long)3) << 56 ))
 #define netxen_set_sts_owner(status_desc, val)	\
 	((status_desc)->status_desc_data |=	\
-	(((unsigned long long)((val) & 0x3)) << 56 ))
+	cpu_to_le64(((unsigned long long)((val) & 0x3)) << 56 ))
 
 struct status_desc {
 	/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
 	   28-43 reference_handle, 44-47 protocol, 48-52 unused
 	   53-55 desc_cnt, 56-57 owner, 58-63 opcode
 	 */
-	u64 status_desc_data;
-	u32 hash_value;
+	__le64 status_desc_data;
+	__le32 hash_value;
 	u8 hash_type;
 	u8 msg_type;
 	u8 unused;
@@ -1006,9 +999,9 @@
 void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port,
 				  long enable);
 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, long reg,
-			    __le32 * readval);
+			    __u32 * readval);
 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy,
-			     long reg, __le32 val);
+			     long reg, __u32 val);
 
 /* Functions available from netxen_nic_hw.c */
 int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 3404461..c381d77 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -218,7 +218,7 @@
 {
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
-	__le32 status;
+	__u32 status;
 
 	/* read which mode */
 	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -226,7 +226,7 @@
 		if (adapter->phy_write
 		    && adapter->phy_write(adapter, port->portnum,
 					  NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-					  (__le32) ecmd->autoneg) != 0)
+					  ecmd->autoneg) != 0)
 			return -EIO;
 		else
 			port->link_autoneg = ecmd->autoneg;
@@ -279,7 +279,7 @@
 }
 
 struct netxen_niu_regs {
-	__le32 reg[NETXEN_NIC_REGS_COUNT];
+	__u32 reg[NETXEN_NIC_REGS_COUNT];
 };
 
 static struct netxen_niu_regs niu_registers[] = {
@@ -372,7 +372,7 @@
 {
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
-	__le32 mode, *regs_buff = p;
+	__u32 mode, *regs_buff = p;
 	void __iomem *addr;
 	int i, window;
 
@@ -415,7 +415,7 @@
 {
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
-	__le32 status;
+	__u32 status;
 
 	/* read which mode */
 	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -482,13 +482,13 @@
 {
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
-	__le32 val;
+	__u32 val;
 
 	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
 		/* get flow control settings */
 		netxen_nic_read_w0(adapter,
 				   NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
-				   (u32 *) & val);
+				   &val);
 		pause->rx_pause = netxen_gb_get_rx_flowctl(val);
 		pause->tx_pause = netxen_gb_get_tx_flowctl(val);
 		/* get autoneg settings */
@@ -502,7 +502,7 @@
 {
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
-	__le32 val;
+	__u32 val;
 	unsigned int autoneg;
 
 	/* read mode */
@@ -522,13 +522,13 @@
 
 		netxen_nic_write_w0(adapter,
 				    NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
-				    *(u32 *) (&val));
+				    *&val);
 		/* set autoneg */
 		autoneg = pause->autoneg;
 		if (adapter->phy_write
 		    && adapter->phy_write(adapter, port->portnum,
 					  NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-					  (__le32) autoneg) != 0)
+					  autoneg) != 0)
 			return -EIO;
 		else {
 			port->link_autoneg = pause->autoneg;
@@ -543,7 +543,7 @@
 	struct netxen_port *port = netdev_priv(dev);
 	struct netxen_adapter *adapter = port->adapter;
 	u32 data_read, data_written, save;
-	__le32 mode;
+	__u32 mode;
 
 	/* 
 	 * first test the "Read Only" registers by writing which mode
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index c0c31d1..f263232 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -95,7 +95,7 @@
 	struct netxen_port *port = netdev_priv(netdev);
 	struct netxen_adapter *adapter = port->adapter;
 	struct dev_mc_list *mc_ptr;
-	__le32 netxen_mac_addr_cntl_data = 0;
+	__u32 netxen_mac_addr_cntl_data = 0;
 
 	mc_ptr = netdev->mc_list;
 	if (netdev->flags & IFF_PROMISC) {
@@ -236,8 +236,9 @@
 	}
 	memset(addr, 0, sizeof(struct netxen_ring_ctx));
 	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
-	adapter->ctx_desc->cmd_consumer_offset = adapter->ctx_desc_phys_addr
-	    + sizeof(struct netxen_ring_ctx);
+	adapter->ctx_desc->cmd_consumer_offset =
+	    cpu_to_le64(adapter->ctx_desc_phys_addr +
+			sizeof(struct netxen_ring_ctx));
 	adapter->cmd_consumer = (uint32_t *) (((char *)addr) +
 					      sizeof(struct netxen_ring_ctx));
 
@@ -253,11 +254,10 @@
 		return -ENOMEM;
 	}
 
-	adapter->ctx_desc->cmd_ring_addr_lo =
-	    hw->cmd_desc_phys_addr & 0xffffffffUL;
-	adapter->ctx_desc->cmd_ring_addr_hi =
-	    ((u64) hw->cmd_desc_phys_addr >> 32);
-	adapter->ctx_desc->cmd_ring_size = adapter->max_tx_desc_count;
+	adapter->ctx_desc->cmd_ring_addr =
+		cpu_to_le64(hw->cmd_desc_phys_addr);
+	adapter->ctx_desc->cmd_ring_size =
+		cpu_to_le32(adapter->max_tx_desc_count);
 
 	hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
 
@@ -278,12 +278,10 @@
 				return err;
 			}
 			rcv_desc->desc_head = (struct rcv_desc *)addr;
-			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_lo =
-			    rcv_desc->phys_addr & 0xffffffffUL;
-			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_hi =
-			    ((u64) rcv_desc->phys_addr >> 32);
+			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+			    cpu_to_le64(rcv_desc->phys_addr);
 			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
-			    rcv_desc->max_rx_desc_count;
+			    cpu_to_le32(rcv_desc->max_rx_desc_count);
 		}
 
 		addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
@@ -297,11 +295,10 @@
 			return err;
 		}
 		recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
-		adapter->ctx_desc->sts_ring_addr_lo =
-		    recv_ctx->rcv_status_desc_phys_addr & 0xffffffffUL;
-		adapter->ctx_desc->sts_ring_addr_hi =
-		    ((u64) recv_ctx->rcv_status_desc_phys_addr >> 32);
-		adapter->ctx_desc->sts_ring_size = adapter->max_rx_desc_count;
+		adapter->ctx_desc->sts_ring_addr =
+		    cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+		adapter->ctx_desc->sts_ring_size =
+		    cpu_to_le32(adapter->max_rx_desc_count);
 
 	}
 	/* Window = 1 */
@@ -387,10 +384,6 @@
 	}
 	adapter->stats.xmitcsummed++;
 	desc->tcp_hdr_offset = skb->h.raw - skb->data;
-	netxen_set_cmd_desc_totallength(desc,
-					cpu_to_le32
-					(netxen_get_cmd_desc_totallength
-					 (desc)));
 	desc->ip_hdr_offset = skb->nh.raw - skb->data;
 }
 
@@ -867,9 +860,9 @@
 void netxen_nic_set_link_parameters(struct netxen_port *port)
 {
 	struct netxen_adapter *adapter = port->adapter;
-	__le32 status;
-	__le32 autoneg;
-	__le32 mode;
+	__u32 status;
+	__u32 autoneg;
+	__u32 mode;
 
 	netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
 	if (netxen_get_niu_enable_ge(mode)) {	/* Gb 10/100/1000 Mbps mode */
@@ -984,7 +977,8 @@
 		       _NETXEN_NIC_LINUX_MAJOR, fw_major);
 		adapter->driver_mismatch = 1;
 	}
-	if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
+	if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
+			fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
 		printk(KERN_ERR "The mismatch in driver version and firmware "
 		       "version minor number\n"
 		       "Driver version minor number = %d \t"
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index 0685633..ab1112e 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -124,28 +124,28 @@
  */
 
 #define netxen_gb_enable_tx(config_word)	\
-	set_bit(0, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 0)
 #define netxen_gb_enable_rx(config_word)	\
-	set_bit(2, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 2)
 #define netxen_gb_tx_flowctl(config_word)	\
-	set_bit(4, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 4)
 #define netxen_gb_rx_flowctl(config_word)	\
-	set_bit(5, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 5)
 #define netxen_gb_tx_reset_pb(config_word)	\
-		set_bit(16, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 16)
 #define netxen_gb_rx_reset_pb(config_word)	\
-		set_bit(17, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 17)
 #define netxen_gb_tx_reset_mac(config_word)	\
-		set_bit(18, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 18)
 #define netxen_gb_rx_reset_mac(config_word)	\
-		set_bit(19, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 19)
 #define netxen_gb_soft_reset(config_word)	\
-		set_bit(31, (unsigned long*)(&config_word))
+	((config_word) |= 1 << 31)
 
 #define netxen_gb_unset_tx_flowctl(config_word)	\
-		clear_bit(4, (unsigned long *)(&config_word))
+	((config_word) &= ~(1 << 4))
 #define netxen_gb_unset_rx_flowctl(config_word)	\
-		clear_bit(5, (unsigned long*)(&config_word))
+	((config_word) &= ~(1 << 5))
 
 #define netxen_gb_get_tx_synced(config_word)	\
 		_netxen_crb_get_bit((config_word), 1)
@@ -171,15 +171,15 @@
  */
 
 #define netxen_gb_set_duplex(config_word)	\
-		set_bit(0, (unsigned long*)&config_word)
+		((config_word) |= 1 << 0)
 #define netxen_gb_set_crc_enable(config_word)	\
-		set_bit(1, (unsigned long*)&config_word)
+		((config_word) |= 1 << 1)
 #define netxen_gb_set_padshort(config_word)	\
-		set_bit(2, (unsigned long*)&config_word)
+		((config_word) |= 1 << 2)
 #define netxen_gb_set_checklength(config_word)	\
-		set_bit(4, (unsigned long*)&config_word)
+		((config_word) |= 1 << 4)
 #define netxen_gb_set_hugeframes(config_word)	\
-		set_bit(5, (unsigned long*)&config_word)
+		((config_word) |= 1 << 5)
 #define netxen_gb_set_preamblelen(config_word, val)	\
 		((config_word) |= ((val) << 12) & 0xF000)
 #define netxen_gb_set_intfmode(config_word, val)		\
@@ -190,9 +190,9 @@
 #define netxen_gb_set_mii_mgmt_clockselect(config_word, val)	\
 		((config_word) |= ((val) & 0x07))
 #define netxen_gb_mii_mgmt_reset(config_word)	\
-		set_bit(31, (unsigned long*)&config_word)
+		((config_word) |= 1 << 31)
 #define netxen_gb_mii_mgmt_unset(config_word)	\
-		clear_bit(31, (unsigned long*)&config_word)
+		((config_word) &= ~(1 << 31))
 
 /*
  * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
@@ -201,7 +201,7 @@
  */
 
 #define netxen_gb_mii_mgmt_set_read_cycle(config_word)	\
-		set_bit(0, (unsigned long*)&config_word)
+		((config_word) |= 1 << 0)
 #define netxen_gb_mii_mgmt_reg_addr(config_word, val)	\
 		((config_word) |= ((val) & 0x1F))
 #define netxen_gb_mii_mgmt_phy_addr(config_word, val)	\
@@ -274,9 +274,9 @@
 #define netxen_set_phy_speed(config_word, val)	\
 		((config_word) |= ((val & 0x03) << 14))
 #define netxen_set_phy_duplex(config_word)	\
-		set_bit(13, (unsigned long*)&config_word)
+		((config_word) |= 1 << 13)
 #define netxen_clear_phy_duplex(config_word)	\
-		clear_bit(13, (unsigned long*)&config_word)
+		((config_word) &= ~(1 << 13))
 
 #define netxen_get_phy_jabber(config_word)	\
 		_netxen_crb_get_bit(config_word, 0)
@@ -350,11 +350,11 @@
 		_netxen_crb_get_bit(config_word, 15)
 
 #define netxen_set_phy_int_link_status_changed(config_word)	\
-		set_bit(10, (unsigned long*)&config_word)
+		((config_word) |= 1 << 10)
 #define netxen_set_phy_int_autoneg_completed(config_word)	\
-		set_bit(11, (unsigned long*)&config_word)
+		((config_word) |= 1 << 11)
 #define netxen_set_phy_int_speed_changed(config_word)	\
-		set_bit(14, (unsigned long*)&config_word)
+		((config_word) |= 1 << 14)
 
 /*
  * NIU Mode Register.
@@ -382,22 +382,22 @@
  */
 
 #define netxen_set_gb_drop_gb0(config_word)	\
-		set_bit(0, (unsigned long*)&config_word)
+		((config_word) |= 1 << 0)
 #define netxen_set_gb_drop_gb1(config_word)	\
-		set_bit(1, (unsigned long*)&config_word)
+		((config_word) |= 1 << 1)
 #define netxen_set_gb_drop_gb2(config_word)	\
-		set_bit(2, (unsigned long*)&config_word)
+		((config_word) |= 1 << 2)
 #define netxen_set_gb_drop_gb3(config_word)	\
-		set_bit(3, (unsigned long*)&config_word)
+		((config_word) |= 1 << 3)
 
 #define netxen_clear_gb_drop_gb0(config_word)	\
-		clear_bit(0, (unsigned long*)&config_word)
+		((config_word) &= ~(1 << 0))
 #define netxen_clear_gb_drop_gb1(config_word)	\
-		clear_bit(1, (unsigned long*)&config_word)
+		((config_word) &= ~(1 << 1))
 #define netxen_clear_gb_drop_gb2(config_word)	\
-		clear_bit(2, (unsigned long*)&config_word)
+		((config_word) &= ~(1 << 2))
 #define netxen_clear_gb_drop_gb3(config_word)	\
-		clear_bit(3, (unsigned long*)&config_word)
+		((config_word) &= ~(1 << 3))
 
 /*
  * NIU XG MAC Config Register
@@ -413,7 +413,7 @@
  */
 
 #define netxen_xg_soft_reset(config_word)	\
-		set_bit(4, (unsigned long*)&config_word)
+		((config_word) |= 1 << 4)
 
 /*
  * MAC Control Register
@@ -433,19 +433,19 @@
 #define netxen_nic_mcr_set_id_pool0(config, val)	\
 		((config) |= ((val) &0x03))
 #define netxen_nic_mcr_set_enable_xtnd0(config)	\
-		(set_bit(3, (unsigned long *)&(config)))
+		((config) |= 1 << 3)
 #define netxen_nic_mcr_set_id_pool1(config, val)	\
 		((config) |= (((val) & 0x03) << 4))
 #define netxen_nic_mcr_set_enable_xtnd1(config)	\
-		(set_bit(6, (unsigned long *)&(config)))
+		((config) |= 1 << 6)
 #define netxen_nic_mcr_set_id_pool2(config, val)	\
 		((config) |= (((val) & 0x03) << 8))
 #define netxen_nic_mcr_set_enable_xtnd2(config)	\
-		(set_bit(10, (unsigned long *)&(config)))
+		((config) |= 1 << 10)
 #define netxen_nic_mcr_set_id_pool3(config, val)	\
 		((config) |= (((val) & 0x03) << 12))
 #define netxen_nic_mcr_set_enable_xtnd3(config)	\
-		(set_bit(14, (unsigned long *)&(config)))
+		((config) |= 1 << 14)
 #define netxen_nic_mcr_set_mode_select(config, val)	\
 		((config) |= (((val) & 0x03) << 24))
 #define netxen_nic_mcr_set_enable_pool(config, val)	\
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index c3e41f3..973af96 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -690,8 +690,7 @@
 		desc_head = recv_ctx->rcv_status_desc_head;
 		desc = &desc_head[consumer];
 
-		if (((le16_to_cpu(netxen_get_sts_owner(desc)))
-		     & STATUS_OWNER_HOST))
+		if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)
 			return 1;
 	}
 
@@ -787,11 +786,11 @@
 	struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)];
 	struct pci_dev *pdev = port->pdev;
 	struct net_device *netdev = port->netdev;
-	int index = le16_to_cpu(netxen_get_sts_refhandle(desc));
+	int index = netxen_get_sts_refhandle(desc);
 	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
 	struct netxen_rx_buffer *buffer;
 	struct sk_buff *skb;
-	u32 length = le16_to_cpu(netxen_get_sts_totallength(desc));
+	u32 length = netxen_get_sts_totallength(desc);
 	u32 desc_ctx;
 	struct netxen_rcv_desc_ctx *rcv_desc;
 	int ret;
@@ -918,16 +917,14 @@
 	 */
 	while (count < max) {
 		desc = &desc_head[consumer];
-		if (!
-		    (le16_to_cpu(netxen_get_sts_owner(desc)) &
-		     STATUS_OWNER_HOST)) {
+		if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) {
 			DPRINTK(ERR, "desc %p ownedby %x\n", desc,
 				netxen_get_sts_owner(desc));
 			break;
 		}
 		netxen_process_rcv(adapter, ctxid, desc);
 		netxen_clear_sts_owner(desc);
-		netxen_set_sts_owner(desc, cpu_to_le16(STATUS_OWNER_PHANTOM));
+		netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
 		consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
 		count++;
 	}
@@ -1232,7 +1229,7 @@
 
 		/* make a rcv descriptor  */
 		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-		pdesc->buffer_length = cpu_to_le16(rcv_desc->dma_size);
+		pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
 		DPRINTK(INFO, "done writing descripter\n");
 		producer =
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
index 06847d4..be366e4 100644
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ b/drivers/net/netxen/netxen_nic_isr.c
@@ -79,7 +79,7 @@
 void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
 			    u32 enable)
 {
-	__le32 int_src;
+	__u32 int_src;
 	struct netxen_port *port;
 
 	/*  This should clear the interrupt source */
@@ -110,7 +110,7 @@
 	/* write it down later.. */
 	if ((netxen_get_phy_int_speed_changed(int_src))
 	    || (netxen_get_phy_int_link_status_changed(int_src))) {
-		__le32 status;
+		__u32 status;
 
 		DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
 
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 8a5792f..69c1b9d 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -117,7 +117,7 @@
 	void __iomem *mem_ptr1 = NULL;
 	void __iomem *mem_ptr2 = NULL;
 
-	u8 *db_ptr = NULL;
+	u8 __iomem *db_ptr = NULL;
 	unsigned long mem_base, mem_len, db_base, db_len;
 	int pci_using_dac, i, err;
 	int ring;
@@ -191,7 +191,7 @@
 		db_len);
 
 	db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
-	if (db_ptr == 0UL) {
+	if (!db_ptr) {
 		printk(KERN_ERR "%s: Failed to allocate doorbell map.",
 		       netxen_nic_driver_name);
 		err = -EIO;
@@ -818,7 +818,7 @@
 	/* Take skb->data itself */
 	pbuf = &adapter->cmd_buf_arr[producer];
 	if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
-		pbuf->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+		pbuf->mss = skb_shinfo(skb)->gso_size;
 		hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
 	} else {
 		pbuf->mss = 0;
@@ -882,7 +882,7 @@
 			hwdesc->addr_buffer3 = cpu_to_le64(temp_dma);
 			break;
 		case 3:
-			hwdesc->buffer4_length = temp_len;
+			hwdesc->buffer4_length = cpu_to_le16(temp_len);
 			hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
 			break;
 		}
@@ -1144,7 +1144,7 @@
 	if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0)
 		return -ENOMEM;
 
-	return pci_module_init(&netxen_driver);
+	return pci_register_driver(&netxen_driver);
 }
 
 module_init(netxen_init_module);
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 4987dc7..40d7003 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -89,15 +89,15 @@
  *
  */
 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
-			    long reg, __le32 * readval)
+			    long reg, __u32 * readval)
 {
 	long timeout = 0;
 	long result = 0;
 	long restore = 0;
-	__le32 address;
-	__le32 command;
-	__le32 status;
-	__le32 mac_cfg0;
+	__u32 address;
+	__u32 command;
+	__u32 status;
+	__u32 mac_cfg0;
 
 	if (phy_lock(adapter) != 0) {
 		return -1;
@@ -112,7 +112,7 @@
 				  &mac_cfg0, 4))
 		return -EIO;
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
-		__le32 temp;
+		__u32 temp;
 		temp = 0;
 		netxen_gb_tx_reset_pb(temp);
 		netxen_gb_rx_reset_pb(temp);
@@ -184,15 +184,15 @@
  *
  */
 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
-			     long phy, long reg, __le32 val)
+			     long phy, long reg, __u32 val)
 {
 	long timeout = 0;
 	long result = 0;
 	long restore = 0;
-	__le32 address;
-	__le32 command;
-	__le32 status;
-	__le32 mac_cfg0;
+	__u32 address;
+	__u32 command;
+	__u32 status;
+	__u32 mac_cfg0;
 
 	/*
 	 * MII mgmt all goes through port 0 MAC interface, so it
@@ -203,7 +203,7 @@
 				  &mac_cfg0, 4))
 		return -EIO;
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
-		__le32 temp;
+		__u32 temp;
 		temp = 0;
 		netxen_gb_tx_reset_pb(temp);
 		netxen_gb_rx_reset_pb(temp);
@@ -269,7 +269,7 @@
 					 int port)
 {
 	int result = 0;
-	__le32 enable = 0;
+	__u32 enable = 0;
 	netxen_set_phy_int_link_status_changed(enable);
 	netxen_set_phy_int_autoneg_completed(enable);
 	netxen_set_phy_int_speed_changed(enable);
@@ -402,7 +402,7 @@
 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 {
 	int result = 0;
-	__le32 status;
+	__u32 status;
 	if (adapter->disable_phy_interrupts)
 		adapter->disable_phy_interrupts(adapter, port);
 	mdelay(2);
@@ -410,7 +410,7 @@
 	if (0 ==
 	    netxen_niu_gbe_phy_read(adapter, port,
 				    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-				    (__le32 *) & status)) {
+				    &status)) {
 		if (netxen_get_phy_link(status)) {
 			if (netxen_get_phy_speed(status) == 2) {
 				netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
@@ -489,7 +489,7 @@
 					int port, long enable)
 {
 	int result = 0;
-	__le32 int_src;
+	__u32 int_src;
 
 	printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
 	       " (device enable = %d)\n", (int)port, (int)enable);
@@ -530,7 +530,7 @@
 			printk(KERN_INFO PFX "autoneg_error ");
 		if ((netxen_get_phy_int_speed_changed(int_src))
 		    || (netxen_get_phy_int_link_status_changed(int_src))) {
-			__le32 status;
+			__u32 status;
 
 			printk(KERN_INFO PFX
 			       "speed_changed or link status changed");
@@ -583,9 +583,9 @@
 int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
 			   int phy, netxen_ethernet_macaddr_t * addr)
 {
-	u64 result = 0;
-	__le32 stationhigh;
-	__le32 stationlow;
+	u32 stationhigh;
+	u32 stationlow;
+	u8 val[8];
 
 	if (addr == NULL)
 		return -EINVAL;
@@ -598,10 +598,10 @@
 	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
 				  &stationlow, 4))
 		return -EIO;
+	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
+	((__le32 *)val)[0] = cpu_to_le32(stationlow);
 
-	result = (u64) netxen_gb_get_stationaddress_low(stationlow);
-	result |= (u64) stationhigh << 16;
-	memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+	memcpy(addr, val + 2, 6);
 
 	return 0;
 }
@@ -613,24 +613,25 @@
 int netxen_niu_macaddr_set(struct netxen_port *port,
 			   netxen_ethernet_macaddr_t addr)
 {
-	__le32 temp = 0;
+	u8 temp[4];
+	u32 val;
 	struct netxen_adapter *adapter = port->adapter;
 	int phy = port->portnum;
 	unsigned char mac_addr[6];
 	int i;
 
 	for (i = 0; i < 10; i++) {
-		memcpy(&temp, addr, 2);
-		temp <<= 16;
+		temp[0] = temp[1] = 0;
+		memcpy(temp + 2, addr, 2);
+		val = le32_to_cpu(*(__le32 *)temp);
 		if (netxen_nic_hw_write_wx
-		    (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &temp, 4))
+		    (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
 			return -EIO;
 
-		temp = 0;
-
-		memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
+		memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
+		val = le32_to_cpu(*(__le32 *)temp);
 		if (netxen_nic_hw_write_wx
-		    (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &temp, 4))
+		    (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
 			return -2;
 
 		netxen_niu_macaddr_get(adapter, phy,
@@ -659,9 +660,9 @@
 int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
 			       int port, netxen_niu_gbe_ifmode_t mode)
 {
-	__le32 mac_cfg0;
-	__le32 mac_cfg1;
-	__le32 mii_cfg;
+	__u32 mac_cfg0;
+	__u32 mac_cfg1;
+	__u32 mii_cfg;
 
 	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 		return -EINVAL;
@@ -736,7 +737,7 @@
 /* Disable a GbE interface */
 int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port)
 {
-	__le32 mac_cfg0;
+	__u32 mac_cfg0;
 
 	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 		return -EINVAL;
@@ -752,7 +753,7 @@
 /* Disable an XG interface */
 int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port)
 {
-	__le32 mac_cfg;
+	__u32 mac_cfg;
 
 	if (port != 0)
 		return -EINVAL;
@@ -769,7 +770,7 @@
 int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
 				    netxen_niu_prom_mode_t mode)
 {
-	__le32 reg;
+	__u32 reg;
 
 	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 		return -EINVAL;
@@ -826,22 +827,21 @@
 int netxen_niu_xg_macaddr_set(struct netxen_port *port,
 			      netxen_ethernet_macaddr_t addr)
 {
-	__le32 temp = 0;
+	u8 temp[4];
+	u32 val;
 	struct netxen_adapter *adapter = port->adapter;
 
-	memcpy(&temp, addr, 2);
-	temp = cpu_to_le32(temp);
-	temp <<= 16;
+	temp[0] = temp[1] = 0;
+	memcpy(temp + 2, addr, 2);
+	val = le32_to_cpu(*(__le32 *)temp);
 	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
-				   &temp, 4))
+				   &val, 4))
 		return -EIO;
 
-	temp = 0;
-
 	memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
-	temp = cpu_to_le32(temp);
+	val = le32_to_cpu(*(__le32 *)temp);
 	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
-				   &temp, 4))
+				   &val, 4))
 		return -EIO;
 
 	return 0;
@@ -854,9 +854,9 @@
 int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
 			      netxen_ethernet_macaddr_t * addr)
 {
-	__le32 stationhigh;
-	__le32 stationlow;
-	u64 result;
+	u32 stationhigh;
+	u32 stationlow;
+	u8 val[8];
 
 	if (addr == NULL)
 		return -EINVAL;
@@ -869,10 +869,10 @@
 	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
 				  &stationlow, 4))
 		return -EIO;
+	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
+	((__le32 *)val)[0] = cpu_to_le32(stationlow);
 
-	result = ((u64) stationlow) >> 16;
-	result |= (u64) stationhigh << 16;
-	memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+	memcpy(addr, val + 2, 6);
 
 	return 0;
 }
@@ -880,7 +880,7 @@
 int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
 				       int port, netxen_niu_prom_mode_t mode)
 {
-	__le32 reg;
+	__u32 reg;
 
 	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 		return -EINVAL;
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 794cc61..448bf4a 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -281,7 +281,6 @@
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
-	link->conf.Present = PRESENT_OPTION;
 
 	/* The EL3-specific entries in the device structure. */
 	dev->hard_start_xmit = &el3_start_xmit;
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 1e73ff7..461e827 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -195,7 +195,6 @@
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
 
     /* The EL3-specific entries in the device structure. */
     SET_MODULE_OWNER(dev);
@@ -607,11 +606,14 @@
 {
     kio_addr_t ioaddr = dev->base_addr;
     struct el3_private *priv = netdev_priv(dev);
+    unsigned long flags;
 
     DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
 	  "status %4.4x.\n", dev->name, (long)skb->len,
 	  inw(ioaddr + EL3_STATUS));
 
+    spin_lock_irqsave(&priv->lock, flags);    
+
     priv->stats.tx_bytes += skb->len;
 
     /* Put out the doubleword header... */
@@ -629,6 +631,7 @@
 
     dev_kfree_skb(skb);
     pop_tx_status(dev);
+    spin_unlock_irqrestore(&priv->lock, flags);    
     
     return 0;
 }
@@ -730,14 +733,13 @@
 
     if (!netif_device_present(dev)) goto reschedule;
 
-    EL3WINDOW(1);
     /* Check for pending interrupt with expired latency timer: with
        this, we can limp along even if the interrupt is blocked */
     if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
 	(inb(ioaddr + EL3_TIMER) == 0xff)) {
 	if (!lp->fast_poll)
 	    printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
-	el3_interrupt(dev->irq, lp);
+	el3_interrupt(dev->irq, dev);
 	lp->fast_poll = HZ;
     }
     if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 91f65e9..0d1c7a4 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -173,7 +173,6 @@
     p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
     p_dev->conf.IntType = INT_MEMORY_AND_IO;
-    p_dev->conf.Present = PRESENT_OPTION;
 
     p_dev->irq.Instance = info->dev = dev;
     p_dev->priv = info;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 2b1238e..d88e9b2 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1617,6 +1617,7 @@
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
 	PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
 	PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
 	PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
 	PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
 	PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
@@ -1667,6 +1668,7 @@
 	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
 	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
 	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
+	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
 	PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
 	PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
 	PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 8478dca..5879e7c 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -576,7 +576,6 @@
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
     link->irq.Handler = xirc2ps_interrupt;
     link->irq.Instance = dev;
 
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 096d4a1..8613539 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -349,7 +349,7 @@
 	fixed_mdio_register_device(0, 100, 1);
 #endif
 
-#ifdef CONFIX_FIXED_MII_10_FDX
+#ifdef CONFIG_FIXED_MII_10_FDX
 	fixed_mdio_register_device(0, 10, 1);
 #endif
 	return 0;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index e175f39..9765fa6 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -286,6 +286,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(phy_ethtool_sset);
 
 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
 {
@@ -302,7 +303,7 @@
 
 	return 0;
 }
-
+EXPORT_SYMBOL(phy_ethtool_gset);
 
 /* Note that this function is currently incompatible with the
  * PHYCONTROL layer.  It changes registers without regard to
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d79d141..8844c20 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -208,6 +208,15 @@
 	return;
 }
 
+static void ql_write_nvram_reg(struct ql3_adapter *qdev,
+				u32 __iomem *reg, u32 value)
+{
+	writel(value, reg);
+	readl(reg);
+	udelay(1);
+	return;
+}
+
 static void ql_write_page0_reg(struct ql3_adapter *qdev,
 			       u32 __iomem *reg, u32 value)
 {
@@ -336,9 +345,9 @@
 	    		qdev->mem_map_registers;
 
 	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1;
-	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+	ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
-	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+	ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    ((ISP_NVRAM_MASK << 16) | qdev->eeprom_cmd_data));
 }
 
@@ -355,14 +364,14 @@
 	    		qdev->mem_map_registers;
 
 	/* Clock in a zero, then do the start bit */
-	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+	ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
 			    AUBURN_EEPROM_DO_1);
-	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+	ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    ISP_NVRAM_MASK | qdev->
 			    eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
 			    AUBURN_EEPROM_CLK_RISE);
-	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+	ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    ISP_NVRAM_MASK | qdev->
 			    eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
 			    AUBURN_EEPROM_CLK_FALL);
@@ -378,20 +387,20 @@
 			 * If the bit changed, then change the DO state to
 			 * match
 			 */
-			ql_write_common_reg(qdev,
+			ql_write_nvram_reg(qdev,
 					    &port_regs->CommonRegs.
 					    serialPortInterfaceReg,
 					    ISP_NVRAM_MASK | qdev->
 					    eeprom_cmd_data | dataBit);
 			previousBit = dataBit;
 		}
-		ql_write_common_reg(qdev,
+		ql_write_nvram_reg(qdev,
 				    &port_regs->CommonRegs.
 				    serialPortInterfaceReg,
 				    ISP_NVRAM_MASK | qdev->
 				    eeprom_cmd_data | dataBit |
 				    AUBURN_EEPROM_CLK_RISE);
-		ql_write_common_reg(qdev,
+		ql_write_nvram_reg(qdev,
 				    &port_regs->CommonRegs.
 				    serialPortInterfaceReg,
 				    ISP_NVRAM_MASK | qdev->
@@ -412,20 +421,20 @@
 			 * If the bit changed, then change the DO state to
 			 * match
 			 */
-			ql_write_common_reg(qdev,
+			ql_write_nvram_reg(qdev,
 					    &port_regs->CommonRegs.
 					    serialPortInterfaceReg,
 					    ISP_NVRAM_MASK | qdev->
 					    eeprom_cmd_data | dataBit);
 			previousBit = dataBit;
 		}
-		ql_write_common_reg(qdev,
+		ql_write_nvram_reg(qdev,
 				    &port_regs->CommonRegs.
 				    serialPortInterfaceReg,
 				    ISP_NVRAM_MASK | qdev->
 				    eeprom_cmd_data | dataBit |
 				    AUBURN_EEPROM_CLK_RISE);
-		ql_write_common_reg(qdev,
+		ql_write_nvram_reg(qdev,
 				    &port_regs->CommonRegs.
 				    serialPortInterfaceReg,
 				    ISP_NVRAM_MASK | qdev->
@@ -443,7 +452,7 @@
 	struct ql3xxx_port_registers __iomem *port_regs =
 	    		qdev->mem_map_registers;
 	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0;
-	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+	ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
 }
 
@@ -461,12 +470,12 @@
 	/* Read the data bits */
 	/* The first bit is a dummy.  Clock right over it. */
 	for (i = 0; i < dataBits; i++) {
-		ql_write_common_reg(qdev,
+		ql_write_nvram_reg(qdev,
 				    &port_regs->CommonRegs.
 				    serialPortInterfaceReg,
 				    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
 				    AUBURN_EEPROM_CLK_RISE);
-		ql_write_common_reg(qdev,
+		ql_write_nvram_reg(qdev,
 				    &port_regs->CommonRegs.
 				    serialPortInterfaceReg,
 				    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
@@ -3370,7 +3379,6 @@
 	SET_MODULE_OWNER(ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
-	ndev->features = NETIF_F_LLTX;
 	if (pci_using_dac)
 		ndev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 250cdbe..1dd66b8 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -556,10 +556,9 @@
 		}
 	}
 
-	nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL);
+	nic->ufo_in_band_v = kcalloc(size, sizeof(u64), GFP_KERNEL);
 	if (!nic->ufo_in_band_v)
 		return -ENOMEM;
-	memset(nic->ufo_in_band_v, 0, size);
 
 	/* Allocation and initialization of RXDs in Rings */
 	size = 0;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b70ed79..45d91b1 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1562,7 +1562,7 @@
 	for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
 		__le16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
 
-		((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
+		((u16 *)dev->dev_addr)[i] = le16_to_cpu(w);
 	}
 
 	sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index deedfd5..45283f3 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -60,7 +60,7 @@
 #define LINK_HZ			(HZ/2)
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index a6601e8..822dd0b 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3639,29 +3639,6 @@
 out:
 	return err;
 }
-
-/* BIOS resume runs after device (it's a bug in PM)
- * as a temporary workaround on suspend/resume leave MSI disabled
- */
-static int sky2_suspend_late(struct pci_dev *pdev, pm_message_t state)
-{
-	struct sky2_hw *hw = pci_get_drvdata(pdev);
-
-	free_irq(pdev->irq, hw);
-	if (hw->msi) {
-		pci_disable_msi(pdev);
-		hw->msi = 0;
-	}
-	return 0;
-}
-
-static int sky2_resume_early(struct pci_dev *pdev)
-{
-	struct sky2_hw *hw = pci_get_drvdata(pdev);
-	struct net_device *dev = hw->dev[0];
-
-	return request_irq(pdev->irq, sky2_intr, IRQF_SHARED, dev->name, hw);
-}
 #endif
 
 static struct pci_driver sky2_driver = {
@@ -3672,8 +3649,6 @@
 #ifdef CONFIG_PM
 	.suspend = sky2_suspend,
 	.resume = sky2_resume,
-	.suspend_late = sky2_suspend_late,
-	.resume_early = sky2_resume_early,
 #endif
 };
 
@@ -3691,6 +3666,6 @@
 module_exit(sky2_cleanup_module);
 
 MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver");
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 880d9fd..43af614 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -968,11 +968,11 @@
 	 * We should not be called if phy_type is zero.
 	 */
 	if (lp->phy_type == 0)
-		 goto smc911x_phy_configure_exit;
+		 goto smc911x_phy_configure_exit_nolock;
 
 	if (smc911x_phy_reset(dev, phyaddr)) {
 		printk("%s: PHY reset timed out\n", dev->name);
-		goto smc911x_phy_configure_exit;
+		goto smc911x_phy_configure_exit_nolock;
 	}
 	spin_lock_irqsave(&lp->lock, flags);
 
@@ -1041,6 +1041,7 @@
 
 smc911x_phy_configure_exit:
 	spin_unlock_irqrestore(&lp->lock, flags);
+smc911x_phy_configure_exit_nolock:
 	lp->work_pending = 0;
 }
 
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index ebb6aa3..8ea2fc1 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1925,6 +1925,8 @@
 	/* release chains */
 	spider_net_release_tx_chain(card, 1);
 
+	spider_net_free_rx_chain_contents(card);
+
 	spider_net_free_chain(card, &card->tx_chain);
 	spider_net_free_chain(card, &card->rx_chain);
 
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 4056ba1..f4bf62c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.71"
-#define DRV_MODULE_RELDATE	"December 15, 2006"
+#define DRV_MODULE_VERSION	"3.72"
+#define DRV_MODULE_RELDATE	"January 8, 2007"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -1015,7 +1015,12 @@
 	else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) {
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
 		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
-		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_ADJUST_TRIM) {
+			tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
+			tg3_writephy(tp, MII_TG3_TEST1,
+				     MII_TG3_TEST1_TRIM_EN | 0x4);
+		} else
+			tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
 	}
 	/* Set Extended packet length bit (bit 14) on all chips that */
@@ -10803,9 +10808,11 @@
 
 	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
 			tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
-		else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
+			if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
+		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
 			tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
 	}
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index cf78a7e..80f59ac 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1658,6 +1658,9 @@
 #define MII_TG3_EPHY_TEST		0x1f /* 5906 PHY register */
 #define MII_TG3_EPHY_SHADOW_EN		0x80
 
+#define MII_TG3_TEST1			0x1e
+#define MII_TG3_TEST1_TRIM_EN		0x0010
+
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
@@ -2256,6 +2259,7 @@
 #define TG3_FLG2_1SHOT_MSI		0x10000000
 #define TG3_FLG2_PHY_JITTER_BUG		0x20000000
 #define TG3_FLG2_NO_FWARE_REPORTED	0x40000000
+#define TG3_FLG2_PHY_ADJUST_TRIM	0x80000000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 8243150..7e4b23c 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -29,6 +29,7 @@
 #include <linux/fsl_devices.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/workqueue.h>
 
 #include <asm/of_platform.h>
 #include <asm/uaccess.h>
@@ -472,7 +473,7 @@
 	kfree(enet_addr_cont);
 }
 
-static int set_mac_addr(__be16 __iomem *reg, u8 *mac)
+static void set_mac_addr(__be16 __iomem *reg, u8 *mac)
 {
 	out_be16(&reg[0], ((u16)mac[5] << 8) | mac[4]);
 	out_be16(&reg[1], ((u16)mac[3] << 8) | mac[2]);
@@ -3920,10 +3921,11 @@
 }
 
 /* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void ugeth_phy_change(void *data)
+static void ugeth_phy_change(struct work_struct *work)
 {
-	struct net_device *dev = (struct net_device *)data;
-	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth =
+		container_of(work, struct ucc_geth_private, tq);
+	struct net_device *dev = ugeth->dev;
 	struct ucc_geth *ug_regs;
 	int result = 0;
 
@@ -4080,7 +4082,7 @@
 #endif				/* CONFIG_UGETH_NAPI */
 
 	/* Set up the PHY change work queue */
-	INIT_WORK(&ugeth->tq, ugeth_phy_change, dev);
+	INIT_WORK(&ugeth->tq, ugeth_phy_change);
 
 	init_timer(&ugeth->phy_info_timer);
 	ugeth->phy_info_timer.function = &ugeth_phy_startup_timer;
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
index 5360ec0..3c86592 100644
--- a/drivers/net/ucc_geth_phy.c
+++ b/drivers/net/ucc_geth_phy.c
@@ -68,8 +68,31 @@
 static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
 static int genmii_update_link(struct ugeth_mii_info *mii_info);
 static int genmii_read_status(struct ugeth_mii_info *mii_info);
-u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum);
-void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val);
+
+static u16 ucc_geth_phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
+{
+	u16 retval;
+	unsigned long flags;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+	return retval;
+}
+
+static void ucc_geth_phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
+{
+	unsigned long flags;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
 
 /* Write value to the PHY for this device to the register at regnum, */
 /* waiting until the write is done before it returns.  All PHY */
@@ -184,7 +207,7 @@
 	advertise = mii_info->advertising;
 
 	/* Setup standard advertisement */
-	adv = phy_read(mii_info, MII_ADVERTISE);
+	adv = ucc_geth_phy_read(mii_info, MII_ADVERTISE);
 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
 	if (advertise & ADVERTISED_10baseT_Half)
 		adv |= ADVERTISE_10HALF;
@@ -194,7 +217,7 @@
 		adv |= ADVERTISE_100HALF;
 	if (advertise & ADVERTISED_100baseT_Full)
 		adv |= ADVERTISE_100FULL;
-	phy_write(mii_info, MII_ADVERTISE, adv);
+	ucc_geth_phy_write(mii_info, MII_ADVERTISE, adv);
 }
 
 static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
@@ -204,7 +227,7 @@
 
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
-	ctrl = phy_read(mii_info, MII_BMCR);
+	ctrl = ucc_geth_phy_read(mii_info, MII_BMCR);
 
 	ctrl &=
 	    ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
@@ -234,7 +257,7 @@
 		break;
 	}
 
-	phy_write(mii_info, MII_BMCR, ctrl);
+	ucc_geth_phy_write(mii_info, MII_BMCR, ctrl);
 }
 
 /* Enable and Restart Autonegotiation */
@@ -244,9 +267,9 @@
 
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
-	ctl = phy_read(mii_info, MII_BMCR);
+	ctl = ucc_geth_phy_read(mii_info, MII_BMCR);
 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write(mii_info, MII_BMCR, ctl);
+	ucc_geth_phy_write(mii_info, MII_BMCR, ctl);
 }
 
 static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
@@ -261,14 +284,14 @@
 		config_genmii_advert(mii_info);
 		advertise = mii_info->advertising;
 
-		adv = phy_read(mii_info, MII_1000BASETCONTROL);
+		adv = ucc_geth_phy_read(mii_info, MII_1000BASETCONTROL);
 		adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
 			 MII_1000BASETCONTROL_HALFDUPLEXCAP);
 		if (advertise & SUPPORTED_1000baseT_Half)
 			adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
 		if (advertise & SUPPORTED_1000baseT_Full)
 			adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
-		phy_write(mii_info, MII_1000BASETCONTROL, adv);
+		ucc_geth_phy_write(mii_info, MII_1000BASETCONTROL, adv);
 
 		/* Start/Restart aneg */
 		genmii_restart_aneg(mii_info);
@@ -298,10 +321,10 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	/* Do a fake read */
-	phy_read(mii_info, MII_BMSR);
+	ucc_geth_phy_read(mii_info, MII_BMSR);
 
 	/* Read link and autonegotiation status */
-	status = phy_read(mii_info, MII_BMSR);
+	status = ucc_geth_phy_read(mii_info, MII_BMSR);
 	if ((status & BMSR_LSTATUS) == 0)
 		mii_info->link = 0;
 	else
@@ -329,7 +352,7 @@
 		return err;
 
 	if (mii_info->autoneg) {
-		status = phy_read(mii_info, MII_LPA);
+		status = ucc_geth_phy_read(mii_info, MII_LPA);
 
 		if (status & (LPA_10FULL | LPA_100FULL))
 			mii_info->duplex = DUPLEX_FULL;
@@ -352,9 +375,9 @@
 {
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
-	phy_write(mii_info, 0x14, 0x0cd2);
-	phy_write(mii_info, MII_BMCR,
-		  phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+	ucc_geth_phy_write(mii_info, 0x14, 0x0cd2);
+	ucc_geth_phy_write(mii_info, MII_BMCR,
+		  ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
 	msleep(4000);
 
 	return 0;
@@ -367,13 +390,13 @@
 	/* The Marvell PHY has an errata which requires
 	 * that certain registers get written in order
 	 * to restart autonegotiation */
-	phy_write(mii_info, MII_BMCR, BMCR_RESET);
+	ucc_geth_phy_write(mii_info, MII_BMCR, BMCR_RESET);
 
-	phy_write(mii_info, 0x1d, 0x1f);
-	phy_write(mii_info, 0x1e, 0x200c);
-	phy_write(mii_info, 0x1d, 0x5);
-	phy_write(mii_info, 0x1e, 0);
-	phy_write(mii_info, 0x1e, 0x100);
+	ucc_geth_phy_write(mii_info, 0x1d, 0x1f);
+	ucc_geth_phy_write(mii_info, 0x1e, 0x200c);
+	ucc_geth_phy_write(mii_info, 0x1d, 0x5);
+	ucc_geth_phy_write(mii_info, 0x1e, 0);
+	ucc_geth_phy_write(mii_info, 0x1e, 0x100);
 
 	gbit_config_aneg(mii_info);
 
@@ -398,7 +421,7 @@
 	 * are as set */
 	if (mii_info->autoneg && mii_info->link) {
 		int speed;
-		status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+		status = ucc_geth_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
 
 		/* Get the duplexity */
 		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
@@ -430,7 +453,7 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	/* Clear the interrupts by reading the reg */
-	phy_read(mii_info, MII_M1011_IEVENT);
+	ucc_geth_phy_read(mii_info, MII_M1011_IEVENT);
 
 	return 0;
 }
@@ -440,9 +463,9 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+		ucc_geth_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
 	else
-		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+		ucc_geth_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
 
 	return 0;
 }
@@ -451,9 +474,9 @@
 {
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
-	phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
+	ucc_geth_phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
 		  MII_CIS8201_AUXCONSTAT_INIT);
-	phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
+	ucc_geth_phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
 
 	return 0;
 }
@@ -477,7 +500,7 @@
 	if (mii_info->autoneg && mii_info->link) {
 		int speed;
 
-		status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+		status = ucc_geth_phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
 		if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
 			mii_info->duplex = DUPLEX_FULL;
 		else
@@ -505,7 +528,7 @@
 {
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
-	phy_read(mii_info, MII_CIS8201_ISTAT);
+	ucc_geth_phy_read(mii_info, MII_CIS8201_ISTAT);
 
 	return 0;
 }
@@ -515,9 +538,9 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+		ucc_geth_phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
 	else
-		phy_write(mii_info, MII_CIS8201_IMASK, 0);
+		ucc_geth_phy_write(mii_info, MII_CIS8201_IMASK, 0);
 
 	return 0;
 }
@@ -541,7 +564,7 @@
 	/* If we aren't autonegotiating, assume speeds
 	 * are as set */
 	if (mii_info->autoneg && mii_info->link) {
-		status = phy_read(mii_info, MII_DM9161_SCSR);
+		status = ucc_geth_phy_read(mii_info, MII_DM9161_SCSR);
 		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
 			mii_info->speed = SPEED_100;
 		else
@@ -572,7 +595,7 @@
 {
 	struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
 	struct dm9161_private *priv = mii_info->priv;
-	u16 status = phy_read(mii_info, MII_BMSR);
+	u16 status = ucc_geth_phy_read(mii_info, MII_BMSR);
 
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
@@ -599,11 +622,11 @@
 	/* Reset is not done yet */
 	priv->resetdone = 0;
 
-	phy_write(mii_info, MII_BMCR,
-		  phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+	ucc_geth_phy_write(mii_info, MII_BMCR,
+		  ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
 
-	phy_write(mii_info, MII_BMCR,
-		  phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
+	ucc_geth_phy_write(mii_info, MII_BMCR,
+		  ucc_geth_phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
 
 	config_genmii_advert(mii_info);
 	/* Start/Restart aneg */
@@ -634,7 +657,7 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	/* Clear the interrupts by reading the reg */
-	phy_read(mii_info, MII_DM9161_INTR);
+	ucc_geth_phy_read(mii_info, MII_DM9161_INTR);
 
 
 	return 0;
@@ -645,9 +668,9 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
+		ucc_geth_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
 	else
-		phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
+		ucc_geth_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
 
 	return 0;
 }
@@ -718,31 +741,6 @@
 	NULL
 };
 
-u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
-{
-	u16 retval;
-	unsigned long flags;
-
-	ugphy_vdbg("%s: IN", __FUNCTION__);
-
-	spin_lock_irqsave(&mii_info->mdio_lock, flags);
-	retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
-	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
-	return retval;
-}
-
-void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
-{
-	unsigned long flags;
-
-	ugphy_vdbg("%s: IN", __FUNCTION__);
-
-	spin_lock_irqsave(&mii_info->mdio_lock, flags);
-	mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
-	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
 /* Use the PHY ID registers to determine what type of PHY is attached
  * to device dev.  return a struct phy_info structure describing that PHY
  */
@@ -757,11 +755,11 @@
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	/* Grab the bits from PHYIR1, and put them in the upper half */
-	phy_reg = phy_read(mii_info, MII_PHYSID1);
+	phy_reg = ucc_geth_phy_read(mii_info, MII_PHYSID1);
 	phy_ID = (phy_reg & 0xffff) << 16;
 
 	/* Grab the bits from PHYIR2, and put them in the lower half */
-	phy_reg = phy_read(mii_info, MII_PHYSID2);
+	phy_reg = ucc_geth_phy_read(mii_info, MII_PHYSID2);
 	phy_ID |= (phy_reg & 0xffff);
 
 	/* loop through all the known PHY types, and find one that */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 2ec2e5a..91b752e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -2701,8 +2701,8 @@
 		sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
 
 		/* extract core_id, core_rev, core_vendor */
-		core_id = (sb_id_hi & 0xFFF0) >> 4;
-		core_rev = (sb_id_hi & 0xF);
+		core_id = (sb_id_hi & 0x8FF0) >> 4;
+		core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
 		core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
 
 		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
@@ -2873,7 +2873,10 @@
 		sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
 		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
 		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
-		sbimconfiglow |= 0x32;
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+			sbimconfiglow |= 0x32;
+		else
+			sbimconfiglow |= 0x53;
 		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
 	}
 
@@ -3077,7 +3080,7 @@
 	if (err)
 		goto out;
 
-	if (bcm->current_core->rev < 6 ||
+	if (bcm->current_core->rev < 6 &&
 		bcm->current_core->id == BCM43xx_COREID_PCI) {
 		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
 		value |= (1 << backplane_flag_nr);
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 0e94fbb..b85857a 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2664,7 +2664,7 @@
 				break;
 			}
 #endif
-			if (stats.len < sizeof(u->rx_data.header))
+			if (stats.len < sizeof(struct ieee80211_hdr_3addr))
 				break;
 			switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) {
 			case IEEE80211_FTYPE_MGMT:
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 644b474..a009ab5 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -406,7 +406,6 @@
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
 
     /* Netwave private struct init. link/dev/node already taken care of,
      * other stuff zero'd - Jean II */
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 88e10c9..47b2ccb 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -331,7 +331,6 @@
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
     p_dev->conf.IntType = INT_MEMORY_AND_IO;
     p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
 
     p_dev->priv = dev;
     p_dev->irq.Instance = dev;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 583e0d6..c250f08 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1928,7 +1928,6 @@
 	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
 	p_dev->conf.IntType	= INT_MEMORY_AND_IO;
 	p_dev->conf.ConfigIndex	= 1;
-	p_dev->conf.Present	= PRESENT_OPTION;
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
 	if (!dev)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index b8d2385..92d5e8d 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -150,8 +150,7 @@
 }
 
 /**
- * pci_match_device - Tell if a PCI device structure has a matching
- *                    PCI device id structure
+ * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
  * @drv: the PCI driver to match against
  * @dev: the PCI device structure to match against
  *
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6bfb942..206c834 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -254,7 +254,8 @@
 		if ((cap & mask) == ht_cap)
 			return pos;
 
-		pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos,
+		pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn,
+					      pos + PCI_CAP_LIST_NEXT,
 					      PCI_CAP_ID_HT, &ttl);
 	}
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 8f0322d..c913ea4 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -654,19 +654,42 @@
  *	VIA bridges which have VLink
  */
 
-static const struct pci_device_id via_vlink_fixup_tbl[] = {
-	/* Internal devices need IRQ line routing, pre VLink */
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686), 0 },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8231), 17 },
-	/* Devices with VLink */
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_0), 17},
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233A), 17 },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233C_0), 17 },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8235), 16 },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237), 15 },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237A), 15 },
-	{ 0, },
-};
+static int via_vlink_dev_lo = -1, via_vlink_dev_hi = 18;
+
+static void quirk_via_bridge(struct pci_dev *dev)
+{
+	/* See what bridge we have and find the device ranges */
+	switch (dev->device) {
+	case PCI_DEVICE_ID_VIA_82C686:
+		/* The VT82C686 is special, it attaches to PCI and can have
+		   any device number. All its subdevices are functions of
+		   that single device. */
+		via_vlink_dev_lo = PCI_SLOT(dev->devfn);
+		via_vlink_dev_hi = PCI_SLOT(dev->devfn);
+		break;
+	case PCI_DEVICE_ID_VIA_8237:
+	case PCI_DEVICE_ID_VIA_8237A:
+		via_vlink_dev_lo = 15;
+		break;
+	case PCI_DEVICE_ID_VIA_8235:
+		via_vlink_dev_lo = 16;
+		break;
+	case PCI_DEVICE_ID_VIA_8231:
+	case PCI_DEVICE_ID_VIA_8233_0:
+	case PCI_DEVICE_ID_VIA_8233A:
+	case PCI_DEVICE_ID_VIA_8233C_0:
+		via_vlink_dev_lo = 17;
+		break;
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8231,		quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8233_0,	quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8233A,	quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8233C_0,	quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8235,		quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237,		quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237A,	quirk_via_bridge);
 
 /**
  *	quirk_via_vlink		-	VIA VLink IRQ number update
@@ -675,35 +698,20 @@
  *	If the device we are dealing with is on a PIC IRQ we need to
  *	ensure that the IRQ line register which usually is not relevant
  *	for PCI cards, is actually written so that interrupts get sent
- *	to the right place
+ *	to the right place.
+ *	We only do this on systems where a VIA south bridge was detected,
+ *	and only for VIA devices on the motherboard (see quirk_via_bridge
+ *	above).
  */
 
 static void quirk_via_vlink(struct pci_dev *dev)
 {
-	const struct pci_device_id *via_vlink_fixup;
-	static int dev_lo = -1, dev_hi = 18;
 	u8 irq, new_irq;
 
-	/* Check if we have VLink and cache the result */
-
-	/* Checked already - no */
-	if (dev_lo == -2)
+	/* Check if we have VLink at all */
+	if (via_vlink_dev_lo == -1)
 		return;
 
-	/* Not checked - see what bridge we have and find the device
-	   ranges */
-
-	if (dev_lo == -1) {
-		via_vlink_fixup = pci_find_present(via_vlink_fixup_tbl);
-		if (via_vlink_fixup == NULL) {
-			dev_lo = -2;
-			return;
-		}
-		dev_lo = via_vlink_fixup->driver_data;
-		/* 82C686 is special - 0/0 */
-		if (dev_lo == 0)
-			dev_hi = 0;
-	}
 	new_irq = dev->irq;
 
 	/* Don't quirk interrupts outside the legacy IRQ range */
@@ -711,8 +719,8 @@
 		return;
 
 	/* Internal device ? */
-	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) > dev_hi ||
-		PCI_SLOT(dev->devfn) < dev_lo)
+	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) > via_vlink_dev_hi ||
+	    PCI_SLOT(dev->devfn) < via_vlink_dev_lo)
 		return;
 
 	/* This is an internal VLink device on a PIC interrupt. The BIOS
@@ -955,7 +963,7 @@
  * becomes necessary to do this tweak in two steps -- I've chosen the Host
  * bridge as trigger.
  */
-static int __initdata asus_hides_smbus;
+static int asus_hides_smbus;
 
 static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 {
@@ -1002,6 +1010,11 @@
 			case 0x186a: /* M6Ne notebook */
 				asus_hides_smbus = 1;
 			}
+		if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
+			switch (dev->subsystem_device) {
+			case 0x80f2: /* P4P800-X */
+				asus_hides_smbus = 1;
+			}
 		if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
 			switch (dev->subsystem_device) {
 			case 0x1882: /* M6V notebook */
@@ -1117,10 +1130,11 @@
 static void quirk_sis_96x_smbus(struct pci_dev *dev)
 {
 	u8 val = 0;
-	printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
 	pci_read_config_byte(dev, 0x77, &val);
-	pci_write_config_byte(dev, 0x77, val & ~0x10);
-	pci_read_config_byte(dev, 0x77, &val);
+	if (val & 0x10) {
+		printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
+		pci_write_config_byte(dev, 0x77, val & ~0x10);
+	}
 }
 
 /*
@@ -1152,11 +1166,12 @@
 	printk(KERN_WARNING "Uncovering SIS%x that hid as a SIS503 (compatible=%d)\n", devid, sis_96x_compatible);
 
 	/*
-	 * Ok, it now shows up as a 96x.. The 96x quirks are after
-	 * the 503 quirk in the quirk table, so they'll automatically
-	 * run and enable things like the SMBus device
+	 * Ok, it now shows up as a 96x.. run the 96x quirk by
+	 * hand in case it has already been processed.
+	 * (depends on link order, which is apparently not guaranteed)
 	 */
 	dev->device = devid;
+	quirk_sis_96x_smbus(dev);
 }
 
 static void __init quirk_sis_96x_compatible(struct pci_dev *dev)
@@ -1247,8 +1262,8 @@
 			pci_read_config_dword(pdev, 0x40, &conf);
 			/* Enable dual function mode, AHCI on fn 0, IDE fn1 */
 			/* Set the class codes correctly and then direct IDE 0 */
-			conf &= ~0x000F0200;	/* Clear bit 9 and 16-19 */
-			conf |=  0x00C20002;	/* Set bit 1, 17, 22, 23 */
+			conf &= ~0x000FF200; /* Clear bit 9 and 12-19 */
+			conf |=  0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
 			pci_write_config_dword(pdev, 0x40, conf);
 
 			/* Reconfigure so that the PCI scanner discovers the
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index fab381e..b2653c4 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -200,11 +200,8 @@
 	 * can cause some machines to crash.  So here we detect and flag that
 	 * situation and bail out early.
 	 */
-	if (unlikely(list_empty(&pci_devices))) {
-		printk(KERN_INFO "pci_find_subsys() called while pci_devices "
-				"is still empty\n");
+	if (unlikely(list_empty(&pci_devices)))
 		return NULL;
-	}
 	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
 
@@ -278,11 +275,8 @@
 	 * can cause some machines to crash.  So here we detect and flag that
 	 * situation and bail out early.
 	 */
-	if (unlikely(list_empty(&pci_devices))) {
-		printk(KERN_NOTICE "pci_get_subsys() called while pci_devices "
-				"is still empty\n");
+	if (unlikely(list_empty(&pci_devices)))
 		return NULL;
-	}
 	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
 
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 72ba1a7..198b9f2 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -264,8 +264,6 @@
 	unsigned int tmp;
 
 	tmp = readb(rtc->regbase + RCR1);
-	seq_printf(seq, "alarm_IRQ\t: %s\n",
-		   (tmp & RCR1_AIE) ? "yes" : "no");
 	seq_printf(seq, "carry_IRQ\t: %s\n",
 		   (tmp & RCR1_CIE) ? "yes" : "no");
 
@@ -428,6 +426,8 @@
 		tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
 	tm->tm_year     = 0xffff;
 
+	wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0;
+
 	spin_unlock_irq(&rtc->lock);
 
 	return 0;
@@ -492,10 +492,10 @@
 
 	spin_lock_irq(&rtc->lock);
 
-	/* disable alarm interrupt and clear flag */
+	/* disable alarm interrupt and clear the alarm flag */
 	rcr1 = readb(rtc->regbase + RCR1);
-	rcr1 &= ~RCR1_AF;
-	writeb(rcr1 & ~RCR1_AIE, rtc->regbase + RCR1);
+	rcr1 &= ~(RCR1_AF|RCR1_AIE);
+	writeb(rcr1, rtc->regbase + RCR1);
 
 	rtc->rearm_aie = 0;
 
@@ -510,8 +510,10 @@
 		mon += 1;
 	sh_rtc_write_alarm_value(rtc, mon, RMONAR);
 
-	/* Restore interrupt activation status */
-	writeb(rcr1, rtc->regbase + RCR1);
+	if (wkalrm->enabled) {
+		rcr1 |= RCR1_AIE;
+		writeb(rcr1, rtc->regbase + RCR1);
+	}
 
 	spin_unlock_irq(&rtc->lock);
 
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 9418a59..2ddd0cf 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -78,7 +78,7 @@
 	.attrs = rtc_attrs,
 };
 
-static int __devinit rtc_sysfs_add_device(struct class_device *class_dev,
+static int rtc_sysfs_add_device(struct class_device *class_dev,
 					struct class_interface *class_intf)
 {
 	int err;
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index ae89b9b..165af39 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -103,14 +103,8 @@
  	depends on TN3215_CONSOLE || TN3270_CONSOLE
  	default y
  
-config SCLP
-	bool "Support for SCLP"
-	help
-	  Include support for the SCLP interface to the service element.
-
 config SCLP_TTY
 	bool "Support for SCLP line mode terminal"
-	depends on SCLP
 	help
 	  Include support for IBM SCLP line-mode terminals.
 
@@ -123,7 +117,6 @@
 
 config SCLP_VT220_TTY
 	bool "Support for SCLP VT220-compatible terminal"
-	depends on SCLP
 	help
 	  Include support for an IBM SCLP VT220-compatible terminal.
 
@@ -136,7 +129,6 @@
 
 config SCLP_CPI
 	tristate "Control-Program Identification"
-	depends on SCLP
 	help
 	  This option enables the hardware console interface for system
 	  identification. This is commonly used for workload management and
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
index 9803c93..5a88870 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -2,6 +2,8 @@
 # Makefile for the S/390 specific device drivers
 #
 
+CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
+
 obj-y += s390mach.o sysinfo.o s390_rdev.o
 obj-y += cio/ block/ char/ crypto/ net/ scsi/
 
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 492b68b..eb5dc62 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -37,6 +37,7 @@
  */
 debug_info_t *dasd_debug_area;
 struct dasd_discipline *dasd_diag_discipline_pointer;
+void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 
 MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
 MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
@@ -51,7 +52,6 @@
 static void dasd_setup_queue(struct dasd_device * device);
 static void dasd_free_queue(struct dasd_device * device);
 static void dasd_flush_request_queue(struct dasd_device *);
-static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 static int dasd_flush_ccw_queue(struct dasd_device *, int);
 static void dasd_tasklet(struct dasd_device *);
 static void do_kick_device(struct work_struct *);
@@ -483,7 +483,7 @@
 /*
  * Add profiling information for cqr before execution.
  */
-static inline void
+static void
 dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr,
 		   struct request *req)
 {
@@ -505,7 +505,7 @@
 /*
  * Add profiling information for cqr after execution.
  */
-static inline void
+static void
 dasd_profile_end(struct dasd_device *device, struct dasd_ccw_req * cqr,
 		 struct request *req)
 {
@@ -1022,8 +1022,6 @@
 		 irb->scsw.cstat == 0 &&
 		 !irb->esw.esw0.erw.cons)
 		era = dasd_era_none;
-	else if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags))
- 	        era = dasd_era_fatal; /* don't recover this request */
 	else if (irb->esw.esw0.erw.cons)
 		era = device->discipline->examine_error(cqr, irb);
 	else
@@ -1104,7 +1102,7 @@
 /*
  * Process ccw request queue.
  */
-static inline void
+static void
 __dasd_process_ccw_queue(struct dasd_device * device,
 			 struct list_head *final_queue)
 {
@@ -1127,7 +1125,9 @@
 				cqr->status = DASD_CQR_FAILED;
 				cqr->stopclk = get_clock();
 			} else {
-				if (cqr->irb.esw.esw0.erw.cons) {
+				if (cqr->irb.esw.esw0.erw.cons &&
+				    test_bit(DASD_CQR_FLAGS_USE_ERP,
+					     &cqr->flags)) {
 					erp_fn = device->discipline->
 						erp_action(cqr);
 					erp_fn(cqr);
@@ -1181,7 +1181,7 @@
 /*
  * Fetch requests from the block device queue.
  */
-static inline void
+static void
 __dasd_process_blk_queue(struct dasd_device * device)
 {
 	request_queue_t *queue;
@@ -1232,6 +1232,19 @@
 		if (IS_ERR(cqr)) {
 			if (PTR_ERR(cqr) == -ENOMEM)
 				break;	/* terminate request queue loop */
+			if (PTR_ERR(cqr) == -EAGAIN) {
+				/*
+				 * The current request cannot be build right
+				 * now, we have to try later. If this request
+				 * is the head-of-queue we stop the device
+				 * for 1/2 second.
+				 */
+				if (!list_empty(&device->ccw_queue))
+					break;
+				device->stopped |= DASD_STOPPED_PENDING;
+				dasd_set_timer(device, HZ/2);
+				break;
+			}
 			DBF_DEV_EVENT(DBF_ERR, device,
 				      "CCW creation failed (rc=%ld) "
 				      "on request %p",
@@ -1254,7 +1267,7 @@
  * Take a look at the first request on the ccw queue and check
  * if it reached its expire time. If so, terminate the IO.
  */
-static inline void
+static void
 __dasd_check_expire(struct dasd_device * device)
 {
 	struct dasd_ccw_req *cqr;
@@ -1285,7 +1298,7 @@
  * Take a look at the first request on the ccw queue and check
  * if it needs to be started.
  */
-static inline void
+static void
 __dasd_start_head(struct dasd_device * device)
 {
 	struct dasd_ccw_req *cqr;
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 4d01040..8b9d68f 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -170,7 +170,6 @@
 	/* log the erp chain if fatal error occurred */
 	if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) {
 		dasd_log_sense(cqr, irb);
-		dasd_log_ccw(cqr, 0, irb->scsw.cpa);
 	}
 
 	return era;
@@ -2640,7 +2639,6 @@
 
 	struct dasd_ccw_req *erp = NULL;
 	struct dasd_device *device = cqr->device;
-	__u32 cpa = cqr->irb.scsw.cpa;
 	struct dasd_ccw_req *temp_erp = NULL;
 
 	if (device->features & DASD_FEATURE_ERPLOG) {
@@ -2706,9 +2704,6 @@
 		}
 	}
 
-	if (erp->status == DASD_CQR_FAILED)
-		dasd_log_ccw(erp, 1, cpa);
-
 	/* enqueue added ERP request */
 	if (erp->status == DASD_CQR_FILLED) {
 		erp->status = DASD_CQR_QUEUED;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 5943266..ed70852 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -136,7 +136,7 @@
 /*
  * Read a device busid/devno from a string.
  */
-static inline int
+static int
 dasd_busid(char **str, int *id0, int *id1, int *devno)
 {
 	int val, old_style;
@@ -182,7 +182,7 @@
  * only one: "ro" for read-only devices. The default feature set
  * is empty (value 0).
  */
-static inline int
+static int
 dasd_feature_list(char *str, char **endp)
 {
 	int features, len, rc;
@@ -341,7 +341,7 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static inline char *
+static char *
 dasd_parse_next_element( char *parsestring ) {
 	char * residual_str;
 	residual_str = dasd_parse_keyword(parsestring);
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 53db58a..ab782bb 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -43,7 +43,7 @@
 #define DIAG_MAX_RETRIES	32
 #define DIAG_TIMEOUT		50 * HZ
 
-struct dasd_discipline dasd_diag_discipline;
+static struct dasd_discipline dasd_diag_discipline;
 
 struct dasd_diag_private {
 	struct dasd_diag_characteristics rdc_data;
@@ -90,7 +90,7 @@
  * block offset. On success, return zero and set end_block to contain the
  * number of blocks on the device minus the specified offset. Return non-zero
  * otherwise. */
-static __inline__ int
+static inline int
 mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
 	     blocknum_t offset, blocknum_t *end_block)
 {
@@ -117,7 +117,7 @@
 
 /* Remove block I/O environment for device. Return zero on success, non-zero
  * otherwise. */
-static __inline__ int
+static inline int
 mdsk_term_io(struct dasd_device * device)
 {
 	struct dasd_diag_private *private;
@@ -576,7 +576,7 @@
 		    "dump sense not available for DIAG data");
 }
 
-struct dasd_discipline dasd_diag_discipline = {
+static struct dasd_discipline dasd_diag_discipline = {
 	.owner = THIS_MODULE,
 	.name = "DIAG",
 	.ebcname = "DIAG",
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index fdaa471..cecab22 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -134,44 +134,7 @@
 	return (d1 + (d2 - 1)) / d2;
 }
 
-static inline int
-bytes_per_record(struct dasd_eckd_characteristics *rdc, int kl, int dl)
-{
-	unsigned int fl1, fl2, int1, int2;
-	int bpr;
-
-	switch (rdc->formula) {
-	case 0x01:
-		fl1 = round_up_multiple(ECKD_F2(rdc) + dl, ECKD_F1(rdc));
-		fl2 = round_up_multiple(kl ? ECKD_F2(rdc) + kl : 0,
-					ECKD_F1(rdc));
-		bpr = fl1 + fl2;
-		break;
-	case 0x02:
-		int1 = ceil_quot(dl + ECKD_F6(rdc), ECKD_F5(rdc) << 1);
-		int2 = ceil_quot(kl + ECKD_F6(rdc), ECKD_F5(rdc) << 1);
-		fl1 = round_up_multiple(ECKD_F1(rdc) * ECKD_F2(rdc) + dl +
-					ECKD_F6(rdc) + ECKD_F4(rdc) * int1,
-					ECKD_F1(rdc));
-		fl2 = round_up_multiple(ECKD_F1(rdc) * ECKD_F3(rdc) + kl +
-					ECKD_F6(rdc) + ECKD_F4(rdc) * int2,
-					ECKD_F1(rdc));
-		bpr = fl1 + fl2;
-		break;
-	default:
-		bpr = 0;
-		break;
-	}
-	return bpr;
-}
-
-static inline unsigned int
-bytes_per_track(struct dasd_eckd_characteristics *rdc)
-{
-	return *(unsigned int *) (rdc->byte_per_track) >> 8;
-}
-
-static inline unsigned int
+static unsigned int
 recs_per_track(struct dasd_eckd_characteristics * rdc,
 	       unsigned int kl, unsigned int dl)
 {
@@ -204,37 +167,39 @@
 	return 0;
 }
 
-static inline void
+static int
 check_XRC (struct ccw1         *de_ccw,
            struct DE_eckd_data *data,
            struct dasd_device  *device)
 {
         struct dasd_eckd_private *private;
+	int rc;
 
         private = (struct dasd_eckd_private *) device->private;
+	if (!private->rdc_data.facilities.XRC_supported)
+		return 0;
 
         /* switch on System Time Stamp - needed for XRC Support */
-        if (private->rdc_data.facilities.XRC_supported) {
+	data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid'   */
+	data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */
 
-                data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid'   */
-                data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */
+	rc = get_sync_clock(&data->ep_sys_time);
+	/* Ignore return code if sync clock is switched off. */
+	if (rc == -ENOSYS || rc == -EACCES)
+		rc = 0;
 
-                data->ep_sys_time = get_clock ();
+	de_ccw->count = sizeof (struct DE_eckd_data);
+	de_ccw->flags |= CCW_FLAG_SLI;
+	return rc;
+}
 
-                de_ccw->count = sizeof (struct DE_eckd_data);
-		de_ccw->flags |= CCW_FLAG_SLI;
-        }
-
-        return;
-
-} /* end check_XRC */
-
-static inline void
+static int
 define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
 	      int totrk, int cmd, struct dasd_device * device)
 {
 	struct dasd_eckd_private *private;
 	struct ch_t geo, beg, end;
+	int rc = 0;
 
 	private = (struct dasd_eckd_private *) device->private;
 
@@ -263,12 +228,12 @@
 	case DASD_ECKD_CCW_WRITE_KD_MT:
 		data->mask.perm = 0x02;
 		data->attributes.operation = private->attrib.operation;
-                check_XRC (ccw, data, device);
+		rc = check_XRC (ccw, data, device);
 		break;
 	case DASD_ECKD_CCW_WRITE_CKD:
 	case DASD_ECKD_CCW_WRITE_CKD_MT:
 		data->attributes.operation = DASD_BYPASS_CACHE;
-                check_XRC (ccw, data, device);
+		rc = check_XRC (ccw, data, device);
 		break;
 	case DASD_ECKD_CCW_ERASE:
 	case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
@@ -276,7 +241,7 @@
 		data->mask.perm = 0x3;
 		data->mask.auth = 0x1;
 		data->attributes.operation = DASD_BYPASS_CACHE;
-                check_XRC (ccw, data, device);
+		rc = check_XRC (ccw, data, device);
 		break;
 	default:
 		DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
@@ -312,9 +277,10 @@
 	data->beg_ext.head = beg.head;
 	data->end_ext.cyl = end.cyl;
 	data->end_ext.head = end.head;
+	return rc;
 }
 
-static inline void
+static void
 locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
 	      int rec_on_trk, int no_rec, int cmd,
 	      struct dasd_device * device, int reclen)
@@ -548,7 +514,7 @@
 /*
  * Build CP for Perform Subsystem Function - SSC.
  */
-struct dasd_ccw_req *
+static struct dasd_ccw_req *
 dasd_eckd_build_psf_ssc(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
@@ -1200,7 +1166,12 @@
 		return cqr;
 	ccw = cqr->cpaddr;
 	/* First ccw is define extent. */
-	define_extent(ccw++, cqr->data, first_trk, last_trk, cmd, device);
+	if (define_extent(ccw++, cqr->data, first_trk,
+			  last_trk, cmd, device) == -EAGAIN) {
+		/* Clock not in sync and XRC is enabled. Try again later. */
+		dasd_sfree_request(cqr, device);
+		return ERR_PTR(-EAGAIN);
+	}
 	/* Build locate_record+read/write/ccws. */
 	idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data));
 	LO_data = (struct LO_eckd_data *) (idaws + cidaw);
@@ -1380,7 +1351,7 @@
 	cqr->device = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
-	cqr->retries = 0;
+	cqr->retries = 2;	/* set retry counter to enable basic ERP */
 	cqr->expires = 2 * HZ;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
@@ -1420,7 +1391,7 @@
 	cqr->device = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
-	cqr->retries = 0;
+	cqr->retries = 2;	/* set retry counter to enable basic ERP */
 	cqr->expires = 2 * HZ;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
@@ -1459,7 +1430,7 @@
 	cqr->device = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
-	cqr->retries = 0;
+	cqr->retries = 2;	/* set retry counter to enable basic ERP */
 	cqr->expires = 2 * HZ;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
@@ -1609,7 +1580,7 @@
  * Dump the range of CCWs into 'page' buffer
  * and return number of printed chars.
  */
-static inline int
+static int
 dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
 {
 	int len, count;
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index e0bf30e..6cedc91 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -658,18 +658,24 @@
 	.owner		= THIS_MODULE,
 };
 
-static struct miscdevice dasd_eer_dev = {
-	.minor	    = MISC_DYNAMIC_MINOR,
-	.name	    = "dasd_eer",
-	.fops	    = &dasd_eer_fops,
-};
+static struct miscdevice *dasd_eer_dev = NULL;
 
 int __init dasd_eer_init(void)
 {
 	int rc;
 
-	rc = misc_register(&dasd_eer_dev);
+	dasd_eer_dev = kzalloc(sizeof(*dasd_eer_dev), GFP_KERNEL);
+	if (!dasd_eer_dev)
+		return -ENOMEM;
+
+	dasd_eer_dev->minor = MISC_DYNAMIC_MINOR;
+	dasd_eer_dev->name  = "dasd_eer";
+	dasd_eer_dev->fops  = &dasd_eer_fops;
+
+	rc = misc_register(dasd_eer_dev);
 	if (rc) {
+		kfree(dasd_eer_dev);
+		dasd_eer_dev = NULL;
 		MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
 		       "register misc device");
 		return rc;
@@ -680,5 +686,9 @@
 
 void dasd_eer_exit(void)
 {
-	WARN_ON(misc_deregister(&dasd_eer_dev) != 0);
+	if (dasd_eer_dev) {
+		WARN_ON(misc_deregister(dasd_eer_dev) != 0);
+		kfree(dasd_eer_dev);
+		dasd_eer_dev = NULL;
+	}
 }
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 58a6509..caa5d91 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -152,25 +152,6 @@
 
 }				/* end default_erp_postaction */
 
-/*
- * Print the hex dump of the memory used by a request. This includes
- * all error recovery ccws that have been chained in from of the
- * real request.
- */
-static inline void
-hex_dump_memory(struct dasd_device *device, void *data, int len)
-{
-	int *pint;
-
-	pint = (int *) data;
-	while (len > 0) {
-		DEV_MESSAGE(KERN_ERR, device, "%p: %08x %08x %08x %08x",
-			    pint, pint[0], pint[1], pint[2], pint[3]);
-		pint += 4;
-		len -= 16;
-	}
-}
-
 void
 dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
 {
@@ -182,69 +163,8 @@
 		device->discipline->dump_sense(device, cqr, irb);
 }
 
-void
-dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa)
-{
-	struct dasd_device *device;
-	struct dasd_ccw_req *lcqr;
-	struct ccw1 *ccw;
-	int cplength;
-
-	device = cqr->device;
-	/* log the channel program */
-	for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) {
-		DEV_MESSAGE(KERN_ERR, device,
-			    "(%s) ERP chain report for req: %p",
-			    caller == 0 ? "EXAMINE" : "ACTION", lcqr);
-		hex_dump_memory(device, lcqr, sizeof(struct dasd_ccw_req));
-
-		cplength = 1;
-		ccw = lcqr->cpaddr;
-		while (ccw++->flags & (CCW_FLAG_DC | CCW_FLAG_CC))
-			cplength++;
-
-		if (cplength > 40) {	/* log only parts of the CP */
-			DEV_MESSAGE(KERN_ERR, device, "%s",
-				    "Start of channel program:");
-			hex_dump_memory(device, lcqr->cpaddr,
-					40*sizeof(struct ccw1));
-
-			DEV_MESSAGE(KERN_ERR, device, "%s",
-				    "End of channel program:");
-			hex_dump_memory(device, lcqr->cpaddr + cplength - 10,
-					10*sizeof(struct ccw1));
-		} else {	/* log the whole CP */
-			DEV_MESSAGE(KERN_ERR, device, "%s",
-				    "Channel program (complete):");
-			hex_dump_memory(device, lcqr->cpaddr,
-					cplength*sizeof(struct ccw1));
-		}
-
-		if (lcqr != cqr)
-			continue;
-
-		/*
-		 * Log bytes arround failed CCW but only if we did
-		 * not log the whole CP of the CCW is outside the
-		 * logged CP.
-		 */
-		if (cplength > 40 ||
-		    ((addr_t) cpa < (addr_t) lcqr->cpaddr &&
-		     (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) {
-
-			DEV_MESSAGE(KERN_ERR, device,
-				    "Failed CCW (%p) (area):",
-				    (void *) (long) cpa);
-			hex_dump_memory(device, cqr->cpaddr - 10,
-					20*sizeof(struct ccw1));
-		}
-	}
-
-}				/* end log_erp_chain */
-
 EXPORT_SYMBOL(dasd_default_erp_action);
 EXPORT_SYMBOL(dasd_default_erp_postaction);
 EXPORT_SYMBOL(dasd_alloc_erp_request);
 EXPORT_SYMBOL(dasd_free_erp_request);
 EXPORT_SYMBOL(dasd_log_sense);
-EXPORT_SYMBOL(dasd_log_ccw);
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index b857fd5..be0909e 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -75,7 +75,7 @@
 	.notify      = dasd_generic_notify,
 };
 
-static inline void
+static void
 define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw,
 	      int blksize, int beg, int nr)
 {
@@ -95,7 +95,7 @@
 	data->ext_end = nr - 1;
 }
 
-static inline void
+static void
 locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw,
 	      int block_nr, int block_ct)
 {
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index d163632..47ba446 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -147,7 +147,7 @@
 	 */
 	memset(&bpart, 0, sizeof(struct blkpg_partition));
 	memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
-	barg.data = (void __user *) &bpart;
+	barg.data = (void __force __user *) &bpart;
 	barg.op = BLKPG_DEL_PARTITION;
 	for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
 		ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index fb725e3..a2cc69e 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -559,7 +559,6 @@
 					    struct dasd_device *);
 void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *);
 void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
-void dasd_log_ccw(struct dasd_ccw_req *, int, __u32);
 
 /* externals in dasd_3370_erp.c */
 dasd_era_t dasd_3370_erp_examine(struct dasd_ccw_req *, struct irb *);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index bfa010f..8b7e118 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -28,7 +28,7 @@
 static struct proc_dir_entry *dasd_devices_entry = NULL;
 static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
-static inline char *
+static char *
 dasd_get_user_string(const char __user *user_buf, size_t user_len)
 {
 	char *buffer;
@@ -154,7 +154,7 @@
 	.release	= seq_release,
 };
 
-static inline int
+static int
 dasd_calc_metrics(char *page, char **start, off_t off,
 		  int count, int *eof, int len)
 {
@@ -167,8 +167,8 @@
 	return len;
 }
 
-static inline char *
-dasd_statistics_array(char *str, int *array, int shift)
+static char *
+dasd_statistics_array(char *str, unsigned int *array, int shift)
 {
 	int i;
 
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index be9b053..1340451 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -102,7 +102,7 @@
  * device needs to be enqueued before the semaphore is
  * freed.
  */
-static inline int
+static int
 dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info)
 {
 	int minor, found;
@@ -230,7 +230,7 @@
 					   SEGMENT_SHARED);
 		if (rc < 0) {
 			BUG_ON(rc == -EINVAL);
-			if (rc == -EIO || rc == -ENOENT)
+			if (rc != -EAGAIN)
 				goto removeseg;
 		} else {
 			dev_info->is_shared = 1;
@@ -253,7 +253,7 @@
 					   SEGMENT_EXCLUSIVE);
 		if (rc < 0) {
 			BUG_ON(rc == -EINVAL);
-			if (rc == -EIO || rc == -ENOENT)
+			if (rc != -EAGAIN)
 				goto removeseg;
 		} else {
 			dev_info->is_shared = 0;
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index c3e97b4..293e667 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -2,7 +2,8 @@
 # S/390 character devices
 #
 
-obj-y += ctrlchar.o keyboard.o defkeymap.o
+obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
+	 sclp_info.o
 
 obj-$(CONFIG_TN3270) += raw3270.o
 obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
@@ -11,7 +12,6 @@
 
 obj-$(CONFIG_TN3215) += con3215.o
 
-obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o
 obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
 obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
 obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 25b5d7a..9a328f1 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -1121,7 +1121,7 @@
  * 3215 tty registration code called from tty_init().
  * Most kernel services (incl. kmalloc) are available at this poimt.
  */
-int __init
+static int __init
 tty3215_init(void)
 {
 	struct tty_driver *driver;
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 7566be8..8e7f2d7 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -69,8 +69,7 @@
 /*
  * Setup timeout for a device. On timeout trigger an update.
  */
-void
-con3270_set_timer(struct con3270 *cp, int expires)
+static void con3270_set_timer(struct con3270 *cp, int expires)
 {
 	if (expires == 0) {
 		if (timer_pending(&cp->timer))
diff --git a/drivers/s390/char/defkeymap.c b/drivers/s390/char/defkeymap.c
index 17027d9..564baca 100644
--- a/drivers/s390/char/defkeymap.c
+++ b/drivers/s390/char/defkeymap.c
@@ -5,6 +5,8 @@
 #include <linux/types.h>
 #include <linux/keyboard.h>
 #include <linux/kd.h>
+#include <linux/kbd_kern.h>
+#include <linux/kbd_diacr.h>
 
 u_short plain_map[NR_KEYS] = {
 	0xf000,	0xf000,	0xf000,	0xf000,	0xf000,	0xf000,	0xf000,	0xf000,
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 0893d30..e1a7462 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -23,7 +23,7 @@
 #include "raw3270.h"
 #include "ctrlchar.h"
 
-struct raw3270_fn fs3270_fn;
+static struct raw3270_fn fs3270_fn;
 
 struct fs3270 {
 	struct raw3270_view view;
@@ -401,7 +401,7 @@
 }
 
 /* View to a 3270 device. Can be console, tty or fullscreen. */
-struct raw3270_fn fs3270_fn = {
+static struct raw3270_fn fs3270_fn = {
 	.activate = fs3270_activate,
 	.deactivate = fs3270_deactivate,
 	.intv = (void *) fs3270_irq,
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 3e86fd1..f62f9a4 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -148,6 +148,7 @@
 	}
 }
 
+#if 0
 /*
  * Generate ebcdic -> ascii translation table from kbd_data.
  */
@@ -173,6 +174,7 @@
 		}
 	}
 }
+#endif
 
 /*
  * We have a combining character DIACR here, followed by the character CH.
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index cdb24f5..9e451ac 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -67,8 +67,8 @@
 	return -EINVAL;
 }
 
-static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv,
-						struct monwrite_hdr *monhdr)
+static struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv,
+					 struct monwrite_hdr *monhdr)
 {
 	struct mon_buf *entry, *next;
 
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 7a84014..8facd14 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -29,7 +29,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 
-struct class *class3270;
+static struct class *class3270;
 
 /* The main 3270 data structure. */
 struct raw3270 {
@@ -86,7 +86,7 @@
 /*
  * Encode array for 12 bit 3270 addresses.
  */
-unsigned char raw3270_ebcgraf[64] =	{
+static unsigned char raw3270_ebcgraf[64] =	{
 	0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
 	0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
 	0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 8a056df..f171de3 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -59,7 +59,8 @@
 /* Internal state: is a request active at the sclp? */
 static volatile enum sclp_running_state_t {
 	sclp_running_state_idle,
-	sclp_running_state_running
+	sclp_running_state_running,
+	sclp_running_state_reset_pending
 } sclp_running_state = sclp_running_state_idle;
 
 /* Internal state: is a read request pending? */
@@ -88,15 +89,15 @@
 
 /* Timeout intervals in seconds.*/
 #define SCLP_BUSY_INTERVAL	10
-#define SCLP_RETRY_INTERVAL	15
+#define SCLP_RETRY_INTERVAL	30
 
 static void sclp_process_queue(void);
 static int sclp_init_mask(int calculate);
 static int sclp_init(void);
 
 /* Perform service call. Return 0 on success, non-zero otherwise. */
-static int
-service_call(sclp_cmdw_t command, void *sccb)
+int
+sclp_service_call(sclp_cmdw_t command, void *sccb)
 {
 	int cc;
 
@@ -113,19 +114,17 @@
 	return 0;
 }
 
-/* Request timeout handler. Restart the request queue. If DATA is non-zero,
- * force restart of running request. */
-static void
-sclp_request_timeout(unsigned long data)
-{
-	unsigned long flags;
+static inline void __sclp_make_read_req(void);
 
-	if (data) {
-		spin_lock_irqsave(&sclp_lock, flags);
-		sclp_running_state = sclp_running_state_idle;
-		spin_unlock_irqrestore(&sclp_lock, flags);
+static void
+__sclp_queue_read_req(void)
+{
+	if (sclp_reading_state == sclp_reading_state_idle) {
+		sclp_reading_state = sclp_reading_state_reading;
+		__sclp_make_read_req();
+		/* Add request to head of queue */
+		list_add(&sclp_read_req.list, &sclp_req_queue);
 	}
-	sclp_process_queue();
 }
 
 /* Set up request retry timer. Called while sclp_lock is locked. */
@@ -140,6 +139,29 @@
 	add_timer(&sclp_request_timer);
 }
 
+/* Request timeout handler. Restart the request queue. If DATA is non-zero,
+ * force restart of running request. */
+static void
+sclp_request_timeout(unsigned long data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sclp_lock, flags);
+	if (data) {
+		if (sclp_running_state == sclp_running_state_running) {
+			/* Break running state and queue NOP read event request
+			 * to get a defined interface state. */
+			__sclp_queue_read_req();
+			sclp_running_state = sclp_running_state_idle;
+		}
+	} else {
+		__sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ,
+					 sclp_request_timeout, 0);
+	}
+	spin_unlock_irqrestore(&sclp_lock, flags);
+	sclp_process_queue();
+}
+
 /* Try to start a request. Return zero if the request was successfully
  * started or if it will be started at a later time. Return non-zero otherwise.
  * Called while sclp_lock is locked. */
@@ -151,7 +173,7 @@
 	if (sclp_running_state != sclp_running_state_idle)
 		return 0;
 	del_timer(&sclp_request_timer);
-	rc = service_call(req->command, req->sccb);
+	rc = sclp_service_call(req->command, req->sccb);
 	req->start_count++;
 
 	if (rc == 0) {
@@ -191,7 +213,15 @@
 		rc = __sclp_start_request(req);
 		if (rc == 0)
 			break;
-		/* Request failed. */
+		/* Request failed */
+		if (req->start_count > 1) {
+			/* Cannot abort already submitted request - could still
+			 * be active at the SCLP */
+			__sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ,
+						 sclp_request_timeout, 0);
+			break;
+		}
+		/* Post-processing for aborted request */
 		list_del(&req->list);
 		if (req->callback) {
 			spin_unlock_irqrestore(&sclp_lock, flags);
@@ -221,7 +251,8 @@
 	list_add_tail(&req->list, &sclp_req_queue);
 	rc = 0;
 	/* Start if request is first in list */
-	if (req->list.prev == &sclp_req_queue) {
+	if (sclp_running_state == sclp_running_state_idle &&
+	    req->list.prev == &sclp_req_queue) {
 		rc = __sclp_start_request(req);
 		if (rc)
 			list_del(&req->list);
@@ -294,7 +325,7 @@
 	sccb = (struct sccb_header *) sclp_read_sccb;
 	clear_page(sccb);
 	memset(&sclp_read_req, 0, sizeof(struct sclp_req));
-	sclp_read_req.command = SCLP_CMDW_READDATA;
+	sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA;
 	sclp_read_req.status = SCLP_REQ_QUEUED;
 	sclp_read_req.start_count = 0;
 	sclp_read_req.callback = sclp_read_cb;
@@ -334,6 +365,8 @@
 	finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
 	evbuf_pending = S390_lowcore.ext_params & 0x3;
 	if (finished_sccb) {
+		del_timer(&sclp_request_timer);
+		sclp_running_state = sclp_running_state_reset_pending;
 		req = __sclp_find_req(finished_sccb);
 		if (req) {
 			/* Request post-processing */
@@ -348,13 +381,8 @@
 		sclp_running_state = sclp_running_state_idle;
 	}
 	if (evbuf_pending && sclp_receive_mask != 0 &&
-	    sclp_reading_state == sclp_reading_state_idle &&
-	    sclp_activation_state == sclp_activation_state_active ) {
-		sclp_reading_state = sclp_reading_state_reading;
-		__sclp_make_read_req();
-		/* Add request to head of queue */
-		list_add(&sclp_read_req.list, &sclp_req_queue);
-	}
+	    sclp_activation_state == sclp_activation_state_active)
+		__sclp_queue_read_req();
 	spin_unlock(&sclp_lock);
 	sclp_process_queue();
 }
@@ -374,6 +402,7 @@
 	unsigned long flags;
 	unsigned long cr0, cr0_sync;
 	u64 timeout;
+	int irq_context;
 
 	/* We'll be disabling timer interrupts, so we need a custom timeout
 	 * mechanism */
@@ -386,7 +415,9 @@
 	}
 	local_irq_save(flags);
 	/* Prevent bottom half from executing once we force interrupts open */
-	local_bh_disable();
+	irq_context = in_interrupt();
+	if (!irq_context)
+		local_bh_disable();
 	/* Enable service-signal interruption, disable timer interrupts */
 	trace_hardirqs_on();
 	__ctl_store(cr0, 0, 0);
@@ -402,19 +433,19 @@
 		    get_clock() > timeout &&
 		    del_timer(&sclp_request_timer))
 			sclp_request_timer.function(sclp_request_timer.data);
-		barrier();
 		cpu_relax();
 	}
 	local_irq_disable();
 	__ctl_load(cr0, 0, 0);
-	_local_bh_enable();
+	if (!irq_context)
+		_local_bh_enable();
 	local_irq_restore(flags);
 }
 
 EXPORT_SYMBOL(sclp_sync_wait);
 
 /* Dispatch changes in send and receive mask to registered listeners. */
-static inline void
+static void
 sclp_dispatch_state_change(void)
 {
 	struct list_head *l;
@@ -597,7 +628,7 @@
 	sccb = (struct init_sccb *) sclp_init_sccb;
 	clear_page(sccb);
 	memset(&sclp_init_req, 0, sizeof(struct sclp_req));
-	sclp_init_req.command = SCLP_CMDW_WRITEMASK;
+	sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK;
 	sclp_init_req.status = SCLP_REQ_FILLED;
 	sclp_init_req.start_count = 0;
 	sclp_init_req.callback = NULL;
@@ -800,7 +831,7 @@
 	for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) {
 		__sclp_make_init_req(0, 0);
 		sccb = (struct init_sccb *) sclp_init_req.sccb;
-		rc = service_call(sclp_init_req.command, sccb);
+		rc = sclp_service_call(sclp_init_req.command, sccb);
 		if (rc == -EIO)
 			break;
 		sclp_init_req.status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 2c71d6e..7d29ab4 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
+#include <asm/sclp.h>
 #include <asm/ebcdic.h>
 
 /* maximum number of pages concerning our own memory management */
@@ -49,9 +49,11 @@
 
 typedef unsigned int sclp_cmdw_t;
 
-#define SCLP_CMDW_READDATA	0x00770005
-#define SCLP_CMDW_WRITEDATA	0x00760005
-#define SCLP_CMDW_WRITEMASK	0x00780005
+#define SCLP_CMDW_READ_EVENT_DATA	0x00770005
+#define SCLP_CMDW_WRITE_EVENT_DATA	0x00760005
+#define SCLP_CMDW_WRITE_EVENT_MASK	0x00780005
+#define SCLP_CMDW_READ_SCP_INFO		0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED	0x00120001
 
 #define GDS_ID_MDSMU		0x1310
 #define GDS_ID_MDSRouteInfo	0x1311
@@ -66,13 +68,6 @@
 
 typedef u32 sccb_mask_t;	/* ATTENTION: assumes 32bit mask !!! */
 
-struct sccb_header {
-	u16	length;
-	u8	function_code;
-	u8	control_mask[3];
-	u16	response_code;
-} __attribute__((packed));
-
 struct gds_subvector {
 	u8	length;
 	u8	key;
@@ -131,6 +126,7 @@
 int sclp_remove_processed(struct sccb_header *sccb);
 int sclp_deactivate(void);
 int sclp_reactivate(void);
+int sclp_service_call(sclp_cmdw_t command, void *sccb);
 
 /* useful inlines */
 
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
index 86864f6..ead1043 100644
--- a/drivers/s390/char/sclp_con.c
+++ b/drivers/s390/char/sclp_con.c
@@ -66,7 +66,7 @@
 	} while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback));
 }
 
-static inline void
+static void
 sclp_conbuf_emit(void)
 {
 	struct sclp_buffer* buffer;
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 4f873ae..65aa2c8 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -169,7 +169,7 @@
 	}
 
 	/* prepare request data structure presented to SCLP driver */
-	req->command = SCLP_CMDW_WRITEDATA;
+	req->command = SCLP_CMDW_WRITE_EVENT_DATA;
 	req->sccb = sccb;
 	req->status = SCLP_REQ_FILLED;
 	req->callback = cpi_callback;
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
new file mode 100644
index 0000000..7bcbe64
--- /dev/null
+++ b/drivers/s390/char/sclp_info.c
@@ -0,0 +1,57 @@
+/*
+ *  drivers/s390/char/sclp_info.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <asm/sclp.h>
+#include "sclp.h"
+
+struct sclp_readinfo_sccb s390_readinfo_sccb;
+
+void __init sclp_readinfo_early(void)
+{
+	sclp_cmdw_t command;
+	struct sccb_header *sccb;
+	int ret;
+
+	__ctl_set_bit(0, 9); /* enable service signal subclass mask */
+
+	sccb = &s390_readinfo_sccb.header;
+	command = SCLP_CMDW_READ_SCP_INFO_FORCED;
+	while (1) {
+		u16 response;
+
+		memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
+		sccb->length = sizeof(s390_readinfo_sccb);
+		sccb->control_mask[2] = 0x80;
+
+		ret = sclp_service_call(command, &s390_readinfo_sccb);
+
+		if (ret == -EIO)
+			goto out;
+		if (ret == -EBUSY)
+			continue;
+
+		__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
+				PSW_MASK_WAIT | PSW_DEFAULT_KEY);
+		local_irq_disable();
+		barrier();
+
+		response = sccb->response_code;
+
+		if (response == 0x10)
+			break;
+
+		if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
+			break;
+
+		command = SCLP_CMDW_READ_SCP_INFO;
+	}
+out:
+	__ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+}
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 0c92d39..2486783 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -460,7 +460,7 @@
 		sccb->msg_buf.header.type = EvTyp_PMsgCmd;
 	else
 		return -ENOSYS;
-	buffer->request.command = SCLP_CMDW_WRITEDATA;
+	buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
 	buffer->request.status = SCLP_REQ_FILLED;
 	buffer->request.callback = sclp_writedata_callback;
 	buffer->request.callback_data = buffer;
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 2d173e5..90536f6 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -721,7 +721,7 @@
 	.ioctl = sclp_tty_ioctl,
 };
 
-int __init
+static int __init
 sclp_tty_init(void)
 {
 	struct tty_driver *driver;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 723bf41..544f137 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -207,7 +207,7 @@
 		request->sclp_req.status = SCLP_REQ_FAILED;
 		return -EIO;
 	}
-	request->sclp_req.command = SCLP_CMDW_WRITEDATA;
+	request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
 	request->sclp_req.status = SCLP_REQ_FILLED;
 	request->sclp_req.callback = sclp_vt220_callback;
 	request->sclp_req.callback_data = (void *) request;
@@ -669,7 +669,7 @@
 /*
  * Register driver with SCLP and Linux and initialize internal tty structures.
  */
-int __init
+static int __init
 sclp_vt220_tty_init(void)
 {
 	struct tty_driver *driver;
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index c9f1c4c..bb4ff53 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -3,7 +3,7 @@
  *    tape device driver for 3480/3490E/3590 tapes.
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *		 Tuan Ngo-Anh <ngoanh@de.ibm.com>
  *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -99,7 +99,11 @@
 	TO_DIS,		/* Tape display */
 	TO_ASSIGN,	/* Assign tape to channel path */
 	TO_UNASSIGN,	/* Unassign tape from channel path */
-	TO_SIZE		/* #entries in tape_op_t */
+	TO_CRYPT_ON,	/* Enable encrpytion */
+	TO_CRYPT_OFF,	/* Disable encrpytion */
+	TO_KEKL_SET,	/* Set KEK label */
+	TO_KEKL_QUERY,	/* Query KEK label */
+	TO_SIZE,	/* #entries in tape_op_t */
 };
 
 /* Forward declaration */
@@ -112,6 +116,7 @@
 	TAPE_REQUEST_IN_IO,	/* request is currently in IO */
 	TAPE_REQUEST_DONE,	/* request is completed. */
 	TAPE_REQUEST_CANCEL,	/* request should be canceled. */
+	TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */
 };
 
 /* Tape CCW request */
@@ -164,10 +169,11 @@
  * The discipline irq function either returns an error code (<0) which
  * means that the request has failed with an error or one of the following:
  */
-#define TAPE_IO_SUCCESS 0	/* request successful */
-#define TAPE_IO_PENDING 1	/* request still running */
-#define TAPE_IO_RETRY	2	/* retry to current request */
-#define TAPE_IO_STOP	3	/* stop the running request */
+#define TAPE_IO_SUCCESS		0	/* request successful */
+#define TAPE_IO_PENDING		1	/* request still running */
+#define TAPE_IO_RETRY		2	/* retry to current request */
+#define TAPE_IO_STOP		3	/* stop the running request */
+#define TAPE_IO_LONG_BUSY	4	/* delay the running request */
 
 /* Char Frontend Data */
 struct tape_char_data {
@@ -242,6 +248,10 @@
 
 	/* Function to start or stop the next request later. */
 	struct delayed_work		tape_dnr;
+
+	/* Timer for long busy */
+	struct timer_list		lb_timeout;
+
 };
 
 /* Externals from tape_core.c */
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 9df912f..50f5eda 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -2,7 +2,7 @@
  *  drivers/s390/char/tape_3590.c
  *    tape device discipline for 3590 tapes.
  *
- *    Copyright (C) IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Stefan Bader <shbader@de.ibm.com>
  *		 Michael Holzheu <holzheu@de.ibm.com>
  *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/bio.h>
+#include <asm/ebcdic.h>
 
 #define TAPE_DBF_AREA	tape_3590_dbf
 
@@ -30,7 +31,7 @@
  * - Read Device (buffered) log: BRA
  * - Read Library log:		 BRA
  * - Swap Devices:		 BRA
- * - Long Busy:			 BRA
+ * - Long Busy:			 implemented
  * - Special Intercept:		 BRA
  * - Read Alternate:		 implemented
  *******************************************************************/
@@ -94,6 +95,332 @@
 	[0xae] = "Subsystem environmental alert",
 };
 
+static int crypt_supported(struct tape_device *device)
+{
+	return TAPE390_CRYPT_SUPPORTED(TAPE_3590_CRYPT_INFO(device));
+}
+
+static int crypt_enabled(struct tape_device *device)
+{
+	return TAPE390_CRYPT_ON(TAPE_3590_CRYPT_INFO(device));
+}
+
+static void ext_to_int_kekl(struct tape390_kekl *in,
+			    struct tape3592_kekl *out)
+{
+	int i;
+
+	memset(out, 0, sizeof(*out));
+	if (in->type == TAPE390_KEKL_TYPE_HASH)
+		out->flags |= 0x40;
+	if (in->type_on_tape == TAPE390_KEKL_TYPE_HASH)
+		out->flags |= 0x80;
+	strncpy(out->label, in->label, 64);
+	for (i = strlen(in->label); i < sizeof(out->label); i++)
+		out->label[i] = ' ';
+	ASCEBC(out->label, sizeof(out->label));
+}
+
+static void int_to_ext_kekl(struct tape3592_kekl *in,
+			    struct tape390_kekl *out)
+{
+	memset(out, 0, sizeof(*out));
+	if(in->flags & 0x40)
+		out->type = TAPE390_KEKL_TYPE_HASH;
+	else
+		out->type = TAPE390_KEKL_TYPE_LABEL;
+	if(in->flags & 0x80)
+		out->type_on_tape = TAPE390_KEKL_TYPE_HASH;
+	else
+		out->type_on_tape = TAPE390_KEKL_TYPE_LABEL;
+	memcpy(out->label, in->label, sizeof(in->label));
+	EBCASC(out->label, sizeof(in->label));
+	strstrip(out->label);
+}
+
+static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in,
+				 struct tape390_kekl_pair *out)
+{
+	if (in->count == 0) {
+		out->kekl[0].type = TAPE390_KEKL_TYPE_NONE;
+		out->kekl[0].type_on_tape = TAPE390_KEKL_TYPE_NONE;
+		out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;
+		out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;
+	} else if (in->count == 1) {
+		int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);
+		out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;
+		out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;
+	} else if (in->count == 2) {
+		int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);
+		int_to_ext_kekl(&in->kekl[1], &out->kekl[1]);
+	} else {
+		printk("Invalid KEKL number: %d\n", in->count);
+		BUG();
+	}
+}
+
+static int check_ext_kekl(struct tape390_kekl *kekl)
+{
+	if (kekl->type == TAPE390_KEKL_TYPE_NONE)
+		goto invalid;
+	if (kekl->type > TAPE390_KEKL_TYPE_HASH)
+		goto invalid;
+	if (kekl->type_on_tape == TAPE390_KEKL_TYPE_NONE)
+		goto invalid;
+	if (kekl->type_on_tape > TAPE390_KEKL_TYPE_HASH)
+		goto invalid;
+	if ((kekl->type == TAPE390_KEKL_TYPE_HASH) &&
+	    (kekl->type_on_tape == TAPE390_KEKL_TYPE_LABEL))
+		goto invalid;
+
+	return 0;
+invalid:
+	return -EINVAL;
+}
+
+static int check_ext_kekl_pair(struct tape390_kekl_pair *kekls)
+{
+	if (check_ext_kekl(&kekls->kekl[0]))
+		goto invalid;
+	if (check_ext_kekl(&kekls->kekl[1]))
+		goto invalid;
+
+	return 0;
+invalid:
+	return -EINVAL;
+}
+
+/*
+ * Query KEKLs
+ */
+static int tape_3592_kekl_query(struct tape_device *device,
+				struct tape390_kekl_pair *ext_kekls)
+{
+	struct tape_request *request;
+	struct tape3592_kekl_query_order *order;
+	struct tape3592_kekl_query_data *int_kekls;
+	int rc;
+
+	DBF_EVENT(6, "tape3592_kekl_query\n");
+	int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA);
+	if (!int_kekls)
+		return -ENOMEM;
+	request = tape_alloc_request(2, sizeof(*order));
+	if (IS_ERR(request)) {
+		rc = PTR_ERR(request);
+		goto fail_malloc;
+	}
+	order = request->cpdata;
+	memset(order,0,sizeof(*order));
+	order->code = 0xe2;
+	order->max_count = 2;
+	request->op = TO_KEKL_QUERY;
+	tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
+	tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls),
+		     int_kekls);
+	rc = tape_do_io(device, request);
+	if (rc)
+		goto fail_request;
+	int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls);
+
+	rc = 0;
+fail_request:
+	tape_free_request(request);
+fail_malloc:
+	kfree(int_kekls);
+	return rc;
+}
+
+/*
+ * IOCTL: Query KEKLs
+ */
+static int tape_3592_ioctl_kekl_query(struct tape_device *device,
+				      unsigned long arg)
+{
+	int rc;
+	struct tape390_kekl_pair *ext_kekls;
+
+	DBF_EVENT(6, "tape_3592_ioctl_kekl_query\n");
+	if (!crypt_supported(device))
+		return -ENOSYS;
+	if (!crypt_enabled(device))
+		return -EUNATCH;
+	ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);
+	if (!ext_kekls)
+		return -ENOMEM;
+	rc = tape_3592_kekl_query(device, ext_kekls);
+	if (rc != 0)
+		goto fail;
+	if (copy_to_user((char __user *) arg, ext_kekls, sizeof(*ext_kekls))) {
+		rc = -EFAULT;
+		goto fail;
+	}
+	rc = 0;
+fail:
+	kfree(ext_kekls);
+	return rc;
+}
+
+static int tape_3590_mttell(struct tape_device *device, int mt_count);
+
+/*
+ * Set KEKLs
+ */
+static int tape_3592_kekl_set(struct tape_device *device,
+			      struct tape390_kekl_pair *ext_kekls)
+{
+	struct tape_request *request;
+	struct tape3592_kekl_set_order *order;
+
+	DBF_EVENT(6, "tape3592_kekl_set\n");
+	if (check_ext_kekl_pair(ext_kekls)) {
+		DBF_EVENT(6, "invalid kekls\n");
+		return -EINVAL;
+	}
+	if (tape_3590_mttell(device, 0) != 0)
+		return -EBADSLT;
+	request = tape_alloc_request(1, sizeof(*order));
+	if (IS_ERR(request))
+		return PTR_ERR(request);
+	order = request->cpdata;
+	memset(order, 0, sizeof(*order));
+	order->code = 0xe3;
+	order->kekls.count = 2;
+	ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]);
+	ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]);
+	request->op = TO_KEKL_SET;
+	tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
+
+	return tape_do_io_free(device, request);
+}
+
+/*
+ * IOCTL: Set KEKLs
+ */
+static int tape_3592_ioctl_kekl_set(struct tape_device *device,
+				    unsigned long arg)
+{
+	int rc;
+	struct tape390_kekl_pair *ext_kekls;
+
+	DBF_EVENT(6, "tape_3592_ioctl_kekl_set\n");
+	if (!crypt_supported(device))
+		return -ENOSYS;
+	if (!crypt_enabled(device))
+		return -EUNATCH;
+	ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);
+	if (!ext_kekls)
+		return -ENOMEM;
+	if (copy_from_user(ext_kekls, (char __user *)arg, sizeof(*ext_kekls))) {
+		rc = -EFAULT;
+		goto out;
+	}
+	rc = tape_3592_kekl_set(device, ext_kekls);
+out:
+	kfree(ext_kekls);
+	return rc;
+}
+
+/*
+ * Enable encryption
+ */
+static int tape_3592_enable_crypt(struct tape_device *device)
+{
+	struct tape_request *request;
+	char *data;
+
+	DBF_EVENT(6, "tape_3592_enable_crypt\n");
+	if (!crypt_supported(device))
+		return -ENOSYS;
+	request = tape_alloc_request(2, 72);
+	if (IS_ERR(request))
+		return PTR_ERR(request);
+	data = request->cpdata;
+	memset(data,0,72);
+
+	data[0]       = 0x05;
+	data[36 + 0]  = 0x03;
+	data[36 + 1]  = 0x03;
+	data[36 + 4]  = 0x40;
+	data[36 + 6]  = 0x01;
+	data[36 + 14] = 0x2f;
+	data[36 + 18] = 0xc3;
+	data[36 + 35] = 0x72;
+	request->op = TO_CRYPT_ON;
+	tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
+	tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
+	return tape_do_io_free(device, request);
+}
+
+/*
+ * Disable encryption
+ */
+static int tape_3592_disable_crypt(struct tape_device *device)
+{
+	struct tape_request *request;
+	char *data;
+
+	DBF_EVENT(6, "tape_3592_disable_crypt\n");
+	if (!crypt_supported(device))
+		return -ENOSYS;
+	request = tape_alloc_request(2, 72);
+	if (IS_ERR(request))
+		return PTR_ERR(request);
+	data = request->cpdata;
+	memset(data,0,72);
+
+	data[0]       = 0x05;
+	data[36 + 0]  = 0x03;
+	data[36 + 1]  = 0x03;
+	data[36 + 35] = 0x32;
+
+	request->op = TO_CRYPT_OFF;
+	tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
+	tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
+
+	return tape_do_io_free(device, request);
+}
+
+/*
+ * IOCTL: Set encryption status
+ */
+static int tape_3592_ioctl_crypt_set(struct tape_device *device,
+				     unsigned long arg)
+{
+	struct tape390_crypt_info info;
+
+	DBF_EVENT(6, "tape_3592_ioctl_crypt_set\n");
+	if (!crypt_supported(device))
+		return -ENOSYS;
+	if (copy_from_user(&info, (char __user *)arg, sizeof(info)))
+		return -EFAULT;
+	if (info.status & ~TAPE390_CRYPT_ON_MASK)
+		return -EINVAL;
+	if (info.status & TAPE390_CRYPT_ON_MASK)
+		return tape_3592_enable_crypt(device);
+	else
+		return tape_3592_disable_crypt(device);
+}
+
+static int tape_3590_sense_medium(struct tape_device *device);
+
+/*
+ * IOCTL: Query enryption status
+ */
+static int tape_3592_ioctl_crypt_query(struct tape_device *device,
+				       unsigned long arg)
+{
+	DBF_EVENT(6, "tape_3592_ioctl_crypt_query\n");
+	if (!crypt_supported(device))
+		return -ENOSYS;
+	tape_3590_sense_medium(device);
+	if (copy_to_user((char __user *) arg, &TAPE_3590_CRYPT_INFO(device),
+		sizeof(TAPE_3590_CRYPT_INFO(device))))
+		return -EFAULT;
+	else
+		return 0;
+}
+
 /*
  * 3590 IOCTL Overload
  */
@@ -109,6 +436,14 @@
 
 		return tape_std_display(device, &disp);
 	}
+	case TAPE390_KEKL_SET:
+		return tape_3592_ioctl_kekl_set(device, arg);
+	case TAPE390_KEKL_QUERY:
+		return tape_3592_ioctl_kekl_query(device, arg);
+	case TAPE390_CRYPT_SET:
+		return tape_3592_ioctl_crypt_set(device, arg);
+	case TAPE390_CRYPT_QUERY:
+		return tape_3592_ioctl_crypt_query(device, arg);
 	default:
 		return -EINVAL;	/* no additional ioctls */
 	}
@@ -248,6 +583,12 @@
 	case TO_READ_ATTMSG:
 		tape_3590_read_attmsg(p->device);
 		break;
+	case TO_CRYPT_ON:
+		tape_3592_enable_crypt(p->device);
+		break;
+	case TO_CRYPT_OFF:
+		tape_3592_disable_crypt(p->device);
+		break;
 	default:
 		DBF_EVENT(3, "T3590: work handler undefined for "
 			  "operation 0x%02x\n", p->op);
@@ -365,6 +706,33 @@
 }
 #endif
 
+static void tape_3590_med_state_set(struct tape_device *device,
+				    struct tape_3590_med_sense *sense)
+{
+	struct tape390_crypt_info *c_info;
+
+	c_info = &TAPE_3590_CRYPT_INFO(device);
+
+	if (sense->masst == MSENSE_UNASSOCIATED) {
+		tape_med_state_set(device, MS_UNLOADED);
+		TAPE_3590_CRYPT_INFO(device).medium_status = 0;
+		return;
+	}
+	if (sense->masst != MSENSE_ASSOCIATED_MOUNT) {
+		PRINT_ERR("Unknown medium state: %x\n", sense->masst);
+		return;
+	}
+	tape_med_state_set(device, MS_LOADED);
+	c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK;
+	if (sense->flags & MSENSE_CRYPT_MASK) {
+		PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags);
+		c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK;
+	} else	{
+		DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags);
+		c_info->medium_status &= ~TAPE390_MEDIUM_ENCRYPTED_MASK;
+	}
+}
+
 /*
  * The done handler is called at device/channel end and wakes up the sleeping
  * process
@@ -372,9 +740,10 @@
 static int
 tape_3590_done(struct tape_device *device, struct tape_request *request)
 {
-	struct tape_3590_med_sense *sense;
+	struct tape_3590_disc_data *disc_data;
 
 	DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]);
+	disc_data = device->discdata;
 
 	switch (request->op) {
 	case TO_BSB:
@@ -394,13 +763,20 @@
 		break;
 	case TO_RUN:
 		tape_med_state_set(device, MS_UNLOADED);
+		tape_3590_schedule_work(device, TO_CRYPT_OFF);
 		break;
 	case TO_MSEN:
-		sense = (struct tape_3590_med_sense *) request->cpdata;
-		if (sense->masst == MSENSE_UNASSOCIATED)
-			tape_med_state_set(device, MS_UNLOADED);
-		if (sense->masst == MSENSE_ASSOCIATED_MOUNT)
-			tape_med_state_set(device, MS_LOADED);
+		tape_3590_med_state_set(device, request->cpdata);
+		break;
+	case TO_CRYPT_ON:
+		TAPE_3590_CRYPT_INFO(device).status
+			|= TAPE390_CRYPT_ON_MASK;
+		*(device->modeset_byte) |= 0x03;
+		break;
+	case TO_CRYPT_OFF:
+		TAPE_3590_CRYPT_INFO(device).status
+			&= ~TAPE390_CRYPT_ON_MASK;
+		*(device->modeset_byte) &= ~0x03;
 		break;
 	case TO_RBI:	/* RBI seems to succeed even without medium loaded. */
 	case TO_NOP:	/* Same to NOP. */
@@ -409,8 +785,9 @@
 	case TO_DIS:
 	case TO_ASSIGN:
 	case TO_UNASSIGN:
-		break;
 	case TO_SIZE:
+	case TO_KEKL_SET:
+	case TO_KEKL_QUERY:
 		break;
 	}
 	return TAPE_IO_SUCCESS;
@@ -540,10 +917,8 @@
 tape_3590_erp_long_busy(struct tape_device *device,
 			struct tape_request *request, struct irb *irb)
 {
-	/* FIXME: how about WAITING for a minute ? */
-	PRINT_WARN("(%s): Device is busy! Please wait a minute!\n",
-		   device->cdev->dev.bus_id);
-	return tape_3590_erp_basic(device, request, irb, -EBUSY);
+	DBF_EVENT(6, "Device is busy\n");
+	return TAPE_IO_LONG_BUSY;
 }
 
 /*
@@ -951,6 +1326,34 @@
 		   device->cdev->dev.bus_id, sense->mc);
 }
 
+static int tape_3590_crypt_error(struct tape_device *device,
+				 struct tape_request *request, struct irb *irb)
+{
+	u8 cu_rc, ekm_rc1;
+	u16 ekm_rc2;
+	u32 drv_rc;
+	char *bus_id, *sense;
+
+	sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data;
+	bus_id = device->cdev->dev.bus_id;
+	cu_rc = sense[0];
+	drv_rc = *((u32*) &sense[5]) & 0xffffff;
+	ekm_rc1 = sense[9];
+	ekm_rc2 = *((u16*) &sense[10]);
+	if ((cu_rc == 0) && (ekm_rc2 == 0xee31))
+		/* key not defined on EKM */
+		return tape_3590_erp_basic(device, request, irb, -EKEYREJECTED);
+	if ((cu_rc == 1) || (cu_rc == 2))
+		/* No connection to EKM */
+		return tape_3590_erp_basic(device, request, irb, -ENOTCONN);
+
+	PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id);
+	PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc,
+		drv_rc, ekm_rc1, ekm_rc2);
+
+	return tape_3590_erp_basic(device, request, irb, -ENOKEY);
+}
+
 /*
  *  3590 error Recovery routine:
  *  If possible, it tries to recover from the error. If this is not possible,
@@ -979,6 +1382,8 @@
 
 	sense = (struct tape_3590_sense *) irb->ecw;
 
+	DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
+
 	/*
 	 * First check all RC-QRCs where we want to do something special
 	 *   - "break":     basic error recovery is done
@@ -999,6 +1404,8 @@
 	case 0x2231:
 		tape_3590_print_era_msg(device, irb);
 		return tape_3590_erp_special_interrupt(device, request, irb);
+	case 0x2240:
+		return tape_3590_crypt_error(device, request, irb);
 
 	case 0x3010:
 		DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n",
@@ -1020,6 +1427,7 @@
 		DBF_EVENT(2, "(%08x): Rewind Unload complete\n",
 			  device->cdev_id);
 		tape_med_state_set(device, MS_UNLOADED);
+		tape_3590_schedule_work(device, TO_CRYPT_OFF);
 		return tape_3590_erp_basic(device, request, irb, 0);
 
 	case 0x4010:
@@ -1030,9 +1438,15 @@
 		PRINT_WARN("(%s): Tape operation when medium not loaded\n",
 			   device->cdev->dev.bus_id);
 		tape_med_state_set(device, MS_UNLOADED);
+		tape_3590_schedule_work(device, TO_CRYPT_OFF);
 		return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
 	case 0x4012:		/* Device Long Busy */
+		/* XXX: Also use long busy handling here? */
+		DBF_EVENT(6, "(%08x): LONG BUSY\n", device->cdev_id);
 		tape_3590_print_era_msg(device, irb);
+		return tape_3590_erp_basic(device, request, irb, -EBUSY);
+	case 0x4014:
+		DBF_EVENT(6, "(%08x): Crypto LONG BUSY\n", device->cdev_id);
 		return tape_3590_erp_long_busy(device, request, irb);
 
 	case 0x5010:
@@ -1064,6 +1478,7 @@
 	case 0x5120:
 	case 0x1120:
 		tape_med_state_set(device, MS_UNLOADED);
+		tape_3590_schedule_work(device, TO_CRYPT_OFF);
 		return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
 
 	case 0x6020:
@@ -1142,21 +1557,47 @@
 {
 	int rc;
 	struct tape_3590_disc_data *data;
+	char *rdc_data;
 
 	DBF_EVENT(6, "3590 device setup\n");
-	data = kmalloc(sizeof(struct tape_3590_disc_data),
-		       GFP_KERNEL | GFP_DMA);
+	data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);
 	if (data == NULL)
 		return -ENOMEM;
 	data->read_back_op = READ_PREVIOUS;
 	device->discdata = data;
 
-	if ((rc = tape_std_assign(device)) == 0) {
-		/* Try to find out if medium is loaded */
-		if ((rc = tape_3590_sense_medium(device)) != 0)
-			DBF_LH(3, "3590 medium sense returned %d\n", rc);
+	rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA);
+	if (!rdc_data) {
+		rc = -ENOMEM;
+		goto fail_kmalloc;
 	}
+	rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64);
+	if (rc) {
+		DBF_LH(3, "Read device characteristics failed!\n");
+		goto fail_kmalloc;
+	}
+	rc = tape_std_assign(device);
+	if (rc)
+		goto fail_rdc_data;
+	if (rdc_data[31] == 0x13) {
+		PRINT_INFO("Device has crypto support\n");
+		data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
+		tape_3592_disable_crypt(device);
+	} else {
+		DBF_EVENT(6, "Device has NO crypto support\n");
+	}
+	/* Try to find out if medium is loaded */
+	rc = tape_3590_sense_medium(device);
+	if (rc) {
+		DBF_LH(3, "3590 medium sense returned %d\n", rc);
+		goto fail_rdc_data;
+	}
+	return 0;
 
+fail_rdc_data:
+	kfree(rdc_data);
+fail_kmalloc:
+	kfree(data);
 	return rc;
 }
 
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h
index cf274b9..aa51388 100644
--- a/drivers/s390/char/tape_3590.h
+++ b/drivers/s390/char/tape_3590.h
@@ -2,7 +2,7 @@
  *  drivers/s390/char/tape_3590.h
  *    tape device discipline for 3590 tapes.
  *
- *    Copyright (C) IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Stefan Bader <shbader@de.ibm.com>
  *		 Michael Holzheu <holzheu@de.ibm.com>
  *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -38,16 +38,22 @@
 #define MSENSE_UNASSOCIATED	 0x00
 #define MSENSE_ASSOCIATED_MOUNT	 0x01
 #define MSENSE_ASSOCIATED_UMOUNT 0x02
+#define MSENSE_CRYPT_MASK	 0x00000010
 
 #define TAPE_3590_MAX_MSG	 0xb0
 
 /* Datatypes */
 
 struct tape_3590_disc_data {
-	unsigned char modeset_byte;
+	struct tape390_crypt_info crypt_info;
 	int read_back_op;
 };
 
+#define TAPE_3590_CRYPT_INFO(device) \
+	((struct tape_3590_disc_data*)(device->discdata))->crypt_info
+#define TAPE_3590_READ_BACK_OP(device) \
+	((struct tape_3590_disc_data*)(device->discdata))->read_back_op
+
 struct tape_3590_sense {
 
 	unsigned int command_rej:1;
@@ -118,7 +124,48 @@
 struct tape_3590_med_sense {
 	unsigned int macst:4;
 	unsigned int masst:4;
-	char pad[127];
+	char pad1[7];
+	unsigned int flags;
+	char pad2[116];
+} __attribute__ ((packed));
+
+/* Datastructures for 3592 encryption support */
+
+struct tape3592_kekl {
+	__u8 flags;
+	char label[64];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_pair {
+	__u8 count;
+	struct tape3592_kekl kekl[2];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_query_data {
+	__u16 len;
+	__u8  fmt;
+	__u8  mc;
+	__u32 id;
+	__u8  flags;
+	struct tape3592_kekl_pair kekls;
+	char reserved[116];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_query_order {
+	__u8 code;
+	__u8 flags;
+	char reserved1[2];
+	__u8 max_count;
+	char reserved2[35];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_set_order {
+	__u8 code;
+	__u8 flags;
+	char reserved1[2];
+	__u8 op;
+	struct tape3592_kekl_pair kekls;
+	char reserved2[120];
 } __attribute__ ((packed));
 
 #endif /* _TAPE_3590_H */
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index c8a89b3..dd0ecae 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -73,7 +73,7 @@
 /*
  * Post finished request.
  */
-static inline void
+static void
 tapeblock_end_request(struct request *req, int uptodate)
 {
 	if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
@@ -108,7 +108,7 @@
 /*
  * Feed the tape device CCW queue with requests supplied in a list.
  */
-static inline int
+static int
 tapeblock_start_request(struct tape_device *device, struct request *req)
 {
 	struct tape_request *	ccw_req;
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 31198c8..9faea04 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -3,7 +3,7 @@
  *    character device frontend for tape device driver
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *		 Michael Holzheu <holzheu@de.ibm.com>
  *		 Tuan Ngo-Anh <ngoanh@de.ibm.com>
@@ -89,22 +89,7 @@
 	device->nt = NULL;
 }
 
-/*
- * Terminate write command (we write two TMs and skip backward over last)
- * This ensures that the tape is always correctly terminated.
- * When the user writes afterwards a new file, he will overwrite the
- * second TM and therefore one TM will remain to separate the
- * two files on the tape...
- */
-static inline void
-tapechar_terminate_write(struct tape_device *device)
-{
-	if (tape_mtop(device, MTWEOF, 1) == 0 &&
-	    tape_mtop(device, MTWEOF, 1) == 0)
-		tape_mtop(device, MTBSR, 1);
-}
-
-static inline int
+static int
 tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
 {
 	struct idal_buffer *new;
@@ -137,7 +122,7 @@
 /*
  * Tape device read function
  */
-ssize_t
+static ssize_t
 tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
 {
 	struct tape_device *device;
@@ -201,7 +186,7 @@
 /*
  * Tape device write function
  */
-ssize_t
+static ssize_t
 tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos)
 {
 	struct tape_device *device;
@@ -291,7 +276,7 @@
 /*
  * Character frontend tape device open function.
  */
-int
+static int
 tapechar_open (struct inode *inode, struct file *filp)
 {
 	struct tape_device *device;
@@ -326,7 +311,7 @@
  * Character frontend tape device release function.
  */
 
-int
+static int
 tapechar_release(struct inode *inode, struct file *filp)
 {
 	struct tape_device *device;
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index c6c2e91..e2a8a1a 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -3,7 +3,7 @@
  *    basic function of the tape device driver
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *		 Michael Holzheu <holzheu@de.ibm.com>
  *		 Tuan Ngo-Anh <ngoanh@de.ibm.com>
@@ -26,9 +26,11 @@
 #include "tape_std.h"
 
 #define PRINTK_HEADER "TAPE_CORE: "
+#define LONG_BUSY_TIMEOUT 180 /* seconds */
 
 static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
 static void tape_delayed_next_request(struct work_struct *);
+static void tape_long_busy_timeout(unsigned long data);
 
 /*
  * One list to contain all tape devices of all disciplines, so
@@ -69,10 +71,12 @@
 	[TO_LOAD] = "LOA",	[TO_READ_CONFIG] = "RCF",
 	[TO_READ_ATTMSG] = "RAT",
 	[TO_DIS] = "DIS",	[TO_ASSIGN] = "ASS",
-	[TO_UNASSIGN] = "UAS"
+	[TO_UNASSIGN] = "UAS",  [TO_CRYPT_ON] = "CON",
+	[TO_CRYPT_OFF] = "COF",	[TO_KEKL_SET] = "KLS",
+	[TO_KEKL_QUERY] = "KLQ",
 };
 
-static inline int
+static int
 busid_to_int(char *bus_id)
 {
 	int	dec;
@@ -252,7 +256,7 @@
 /*
  * Stop running ccw. Has to be called with the device lock held.
  */
-static inline int
+static int
 __tape_cancel_io(struct tape_device *device, struct tape_request *request)
 {
 	int retries;
@@ -346,6 +350,9 @@
 		return -EINVAL;
 	}
 
+	init_timer(&device->lb_timeout);
+	device->lb_timeout.function = tape_long_busy_timeout;
+
 	/* Let the discipline have a go at the device. */
 	device->discipline = discipline;
 	if (!try_module_get(discipline->owner)) {
@@ -385,7 +392,7 @@
 	return rc;
 }
 
-static inline void
+static void
 tape_cleanup_device(struct tape_device *device)
 {
 	tapeblock_cleanup_device(device);
@@ -563,7 +570,7 @@
 	return ret;
 }
 
-static inline void
+static void
 __tape_discard_requests(struct tape_device *device)
 {
 	struct tape_request *	request;
@@ -703,7 +710,7 @@
 	kfree(request);
 }
 
-static inline int
+static int
 __tape_start_io(struct tape_device *device, struct tape_request *request)
 {
 	int rc;
@@ -733,7 +740,7 @@
 	return rc;
 }
 
-static inline void
+static void
 __tape_start_next_request(struct tape_device *device)
 {
 	struct list_head *l, *n;
@@ -801,7 +808,23 @@
 	spin_unlock_irq(get_ccwdev_lock(device->cdev));
 }
 
-static inline void
+static void tape_long_busy_timeout(unsigned long data)
+{
+	struct tape_request *request;
+	struct tape_device *device;
+
+	device = (struct tape_device *) data;
+	spin_lock_irq(get_ccwdev_lock(device->cdev));
+	request = list_entry(device->req_queue.next, struct tape_request, list);
+	if (request->status != TAPE_REQUEST_LONG_BUSY)
+		BUG();
+	DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
+	__tape_start_next_request(device);
+	device->lb_timeout.data = (unsigned long) tape_put_device(device);
+	spin_unlock_irq(get_ccwdev_lock(device->cdev));
+}
+
+static void
 __tape_end_request(
 	struct tape_device *	device,
 	struct tape_request *	request,
@@ -878,7 +901,7 @@
  * and starts it if the tape is idle. Has to be called with
  * the device lock held.
  */
-static inline int
+static int
 __tape_start_request(struct tape_device *device, struct tape_request *request)
 {
 	int rc;
@@ -1094,7 +1117,22 @@
 	/* May be an unsolicited irq */
 	if(request != NULL)
 		request->rescnt = irb->scsw.count;
-
+	else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) &&
+		 !list_empty(&device->req_queue)) {
+		/* Not Ready to Ready after long busy ? */
+		struct tape_request *req;
+		req = list_entry(device->req_queue.next,
+				 struct tape_request, list);
+		if (req->status == TAPE_REQUEST_LONG_BUSY) {
+			DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id);
+			if (del_timer(&device->lb_timeout)) {
+				device->lb_timeout.data = (unsigned long)
+					tape_put_device(device);
+				__tape_start_next_request(device);
+			}
+			return;
+		}
+	}
 	if (irb->scsw.dstat != 0x0c) {
 		/* Set the 'ONLINE' flag depending on sense byte 1 */
 		if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
@@ -1142,6 +1180,15 @@
 			break;
 		case TAPE_IO_PENDING:
 			break;
+		case TAPE_IO_LONG_BUSY:
+			device->lb_timeout.data =
+				(unsigned long)tape_get_device_reference(device);
+			device->lb_timeout.expires = jiffies +
+				LONG_BUSY_TIMEOUT * HZ;
+			DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id);
+			add_timer(&device->lb_timeout);
+			request->status = TAPE_REQUEST_LONG_BUSY;
+			break;
 		case TAPE_IO_RETRY:
 			rc = __tape_start_io(device, request);
 			if (rc)
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 0984462..bc33068 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -36,7 +36,7 @@
 struct tty_driver *tty3270_driver;
 static int tty3270_max_index;
 
-struct raw3270_fn tty3270_fn;
+static struct raw3270_fn tty3270_fn;
 
 struct tty3270_cell {
 	unsigned char character;
@@ -119,8 +119,7 @@
 /*
  * Setup timeout for a device. On timeout trigger an update.
  */
-void
-tty3270_set_timer(struct tty3270 *tp, int expires)
+static void tty3270_set_timer(struct tty3270 *tp, int expires)
 {
 	if (expires == 0) {
 		if (timer_pending(&tp->timer) && del_timer(&tp->timer))
@@ -841,7 +840,7 @@
 	}
 }
 
-struct raw3270_fn tty3270_fn = {
+static struct raw3270_fn tty3270_fn = {
 	.activate = tty3270_activate,
 	.deactivate = tty3270_deactivate,
 	.intv = (void *) tty3270_irq,
@@ -1754,8 +1753,7 @@
 	.set_termios = tty3270_set_termios
 };
 
-void
-tty3270_notifier(int index, int active)
+static void tty3270_notifier(int index, int active)
 {
 	if (active)
 		tty_register_device(tty3270_driver, index, NULL);
@@ -1767,8 +1765,7 @@
  * 3270 tty registration code called from tty_init().
  * Most kernel services (incl. kmalloc) are available at this poimt.
  */
-int __init
-tty3270_init(void)
+static int __init tty3270_init(void)
 {
 	struct tty_driver *driver;
 	int ret;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 1678b6c..a420cd0 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -117,7 +117,7 @@
 		return -ENOMEM;
 	}
 	debug_text_event(vmcp_debug, 1, cmd);
-	session->resp_size = __cpcmd(cmd, session->response,
+	session->resp_size = cpcmd(cmd, session->response,
 				     session->bufsize,
 				     &session->resp_code);
 	up(&session->mutex);
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 6cb2304..4f894dc 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -128,9 +128,8 @@
 	.MessagePending     = vmlogrdr_iucv_MessagePending,
 };
 
-
-DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
-DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
 
 /*
  * pointer to system service private structure
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 12c2d6b..aa65df4 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -43,7 +43,7 @@
  * Function: blacklist_range
  * (Un-)blacklist the devices from-to
  */
-static inline void
+static void
 blacklist_range (range_action action, unsigned int from, unsigned int to,
 		 unsigned int ssid)
 {
@@ -69,7 +69,7 @@
  * Get devno/busid from given string.
  * Shamelessly grabbed from dasd_devmap.c.
  */
-static inline int
+static int
 blacklist_busid(char **str, int *id0, int *ssid, int *devno)
 {
 	int val, old_style;
@@ -123,10 +123,10 @@
 	return 1;
 }
 
-static inline int
+static int
 blacklist_parse_parameters (char *str, range_action action)
 {
-	unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
+	int from, to, from_id0, to_id0, from_ssid, to_ssid;
 
 	while (*str != 0 && *str != '\n') {
 		range_action ra = action;
@@ -227,7 +227,7 @@
  * Function: blacklist_parse_proc_parameters
  * parse the stuff which is piped to /proc/cio_ignore
  */
-static inline void
+static void
 blacklist_parse_proc_parameters (char *buf)
 {
 	if (strncmp (buf, "free ", 5) == 0) {
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 38954f5..d48e3ca 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -53,7 +53,7 @@
 
 static struct bus_type ccwgroup_bus_type;
 
-static inline void
+static void
 __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 {
 	int i;
@@ -104,7 +104,7 @@
 	kfree(gdev);
 }
 
-static inline int
+static int
 __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 {
 	char str[8];
@@ -424,7 +424,7 @@
 	return 0;
 }
 
-static inline struct ccwgroup_device *
+static struct ccwgroup_device *
 __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
 {
 	struct ccwgroup_device *gdev;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index cbab8d2..6f05a44 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -93,7 +93,7 @@
 		u16 sch;	  /* subchannel */
 		u8 chpid[8];	  /* chpids 0-7 */
 		u16 fla[8];	  /* full link addresses 0-7 */
-	} *ssd_area;
+	} __attribute__ ((packed)) *ssd_area;
 
 	ssd_area = page;
 
@@ -277,7 +277,7 @@
 	return 0;
 }
 
-static inline void
+static void
 s390_set_chpid_offline( __u8 chpid)
 {
 	char dbf_txt[15];
@@ -338,7 +338,7 @@
 	return 0x80 >> chp;
 }
 
-static inline int
+static int
 s390_process_res_acc_new_sch(struct subchannel_id schid)
 {
 	struct schib schib;
@@ -444,7 +444,7 @@
 		u32 andesc[28];
 		/* incident-specific information */
 		u32 isinfo[28];
-	} *lir;
+	} __attribute__ ((packed)) *lir;
 
 	lir = data;
 	if (!(lir->iq&0x80))
@@ -461,154 +461,146 @@
 	return (u16) (lir->indesc[0]&0x000000ff);
 }
 
-int
-chsc_process_crw(void)
+struct chsc_sei_area {
+	struct chsc_header request;
+	u32 reserved1;
+	u32 reserved2;
+	u32 reserved3;
+	struct chsc_header response;
+	u32 reserved4;
+	u8  flags;
+	u8  vf;		/* validity flags */
+	u8  rs;		/* reporting source */
+	u8  cc;		/* content code */
+	u16 fla;	/* full link address */
+	u16 rsid;	/* reporting source id */
+	u32 reserved5;
+	u32 reserved6;
+	u8 ccdf[4096 - 16 - 24];	/* content-code dependent field */
+	/* ccdf has to be big enough for a link-incident record */
+} __attribute__ ((packed));
+
+static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
 {
-	int chpid, ret;
+	int chpid;
+
+	CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n",
+		      sei_area->rs, sei_area->rsid);
+	if (sei_area->rs != 4)
+		return 0;
+	chpid = __get_chpid_from_lir(sei_area->ccdf);
+	if (chpid < 0)
+		CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n");
+	else
+		s390_set_chpid_offline(chpid);
+
+	return 0;
+}
+
+static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
+{
 	struct res_acc_data res_data;
-	struct {
-		struct chsc_header request;
-		u32 reserved1;
-		u32 reserved2;
-		u32 reserved3;
-		struct chsc_header response;
-		u32 reserved4;
-		u8  flags;
-		u8  vf;		/* validity flags */
-		u8  rs;		/* reporting source */
-		u8  cc;		/* content code */
-		u16 fla;	/* full link address */
-		u16 rsid;	/* reporting source id */
-		u32 reserved5;
-		u32 reserved6;
-		u32 ccdf[96];	/* content-code dependent field */
-		/* ccdf has to be big enough for a link-incident record */
-	} *sei_area;
+	struct device *dev;
+	int status;
+	int rc;
+
+	CIO_CRW_EVENT(4, "chsc: resource accessibility event (rs=%02x, "
+		      "rs_id=%04x)\n", sei_area->rs, sei_area->rsid);
+	if (sei_area->rs != 4)
+		return 0;
+	/* allocate a new channel path structure, if needed */
+	status = get_chp_status(sei_area->rsid);
+	if (status < 0)
+		new_channel_path(sei_area->rsid);
+	else if (!status)
+		return 0;
+	dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
+	memset(&res_data, 0, sizeof(struct res_acc_data));
+	res_data.chp = to_channelpath(dev);
+	if ((sei_area->vf & 0xc0) != 0) {
+		res_data.fla = sei_area->fla;
+		if ((sei_area->vf & 0xc0) == 0xc0)
+			/* full link address */
+			res_data.fla_mask = 0xffff;
+		else
+			/* link address */
+			res_data.fla_mask = 0xff00;
+	}
+	rc = s390_process_res_acc(&res_data);
+	put_device(dev);
+
+	return rc;
+}
+
+static int chsc_process_sei(struct chsc_sei_area *sei_area)
+{
+	int rc;
+
+	/* Check if we might have lost some information. */
+	if (sei_area->flags & 0x40)
+		CIO_CRW_EVENT(2, "chsc: event overflow\n");
+	/* which kind of information was stored? */
+	rc = 0;
+	switch (sei_area->cc) {
+	case 1: /* link incident*/
+		rc = chsc_process_sei_link_incident(sei_area);
+		break;
+	case 2: /* i/o resource accessibiliy */
+		rc = chsc_process_sei_res_acc(sei_area);
+		break;
+	default: /* other stuff */
+		CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n",
+			      sei_area->cc);
+		break;
+	}
+
+	return rc;
+}
+
+int chsc_process_crw(void)
+{
+	struct chsc_sei_area *sei_area;
+	int ret;
+	int rc;
 
 	if (!sei_page)
 		return 0;
-	/*
-	 * build the chsc request block for store event information
-	 * and do the call
-	 * This function is only called by the machine check handler thread,
-	 * so we don't need locking for the sei_page.
-	 */
+	/* Access to sei_page is serialized through machine check handler
+	 * thread, so no need for locking. */
 	sei_area = sei_page;
 
 	CIO_TRACE_EVENT( 2, "prcss");
 	ret = 0;
 	do {
-		int ccode, status;
-		struct device *dev;
 		memset(sei_area, 0, sizeof(*sei_area));
-		memset(&res_data, 0, sizeof(struct res_acc_data));
 		sei_area->request.length = 0x0010;
 		sei_area->request.code = 0x000e;
+		if (chsc(sei_area))
+			break;
 
-		ccode = chsc(sei_area);
-		if (ccode > 0)
-			return 0;
-
-		switch (sei_area->response.code) {
-			/* for debug purposes, check for problems */
-		case 0x0001:
-			CIO_CRW_EVENT(4, "chsc_process_crw: event information "
-					"successfully stored\n");
-			break; /* everything ok */
-		case 0x0002:
-			CIO_CRW_EVENT(2,
-				      "chsc_process_crw: invalid command!\n");
-			return 0;
-		case 0x0003:
-			CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc "
-				      "request block!\n");
-			return 0;
-		case 0x0005:
-			CIO_CRW_EVENT(2, "chsc_process_crw: no event "
-				      "information stored\n");
-			return 0;
-		default:
-			CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n",
+		if (sei_area->response.code == 0x0001) {
+			CIO_CRW_EVENT(4, "chsc: sei successful\n");
+			rc = chsc_process_sei(sei_area);
+			if (rc)
+				ret = rc;
+		} else {
+			CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
 				      sei_area->response.code);
-			return 0;
-		}
-
-		/* Check if we might have lost some information. */
-		if (sei_area->flags & 0x40)
-			CIO_CRW_EVENT(2, "chsc_process_crw: Event information "
-				       "has been lost due to overflow!\n");
-
-		if (sei_area->rs != 4) {
-			CIO_CRW_EVENT(2, "chsc_process_crw: reporting source "
-				      "(%04X) isn't a chpid!\n",
-				      sei_area->rsid);
-			continue;
-		}
-
-		/* which kind of information was stored? */
-		switch (sei_area->cc) {
-		case 1: /* link incident*/
-			CIO_CRW_EVENT(4, "chsc_process_crw: "
-				      "channel subsystem reports link incident,"
-				      " reporting source is chpid %x\n",
-				      sei_area->rsid);
-			chpid = __get_chpid_from_lir(sei_area->ccdf);
-			if (chpid < 0)
-				CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n",
-					      __FUNCTION__);
-			else
-				s390_set_chpid_offline(chpid);
-			break;
-			
-		case 2: /* i/o resource accessibiliy */
-			CIO_CRW_EVENT(4, "chsc_process_crw: "
-				      "channel subsystem reports some I/O "
-				      "devices may have become accessible\n");
-			pr_debug("Data received after sei: \n");
-			pr_debug("Validity flags: %x\n", sei_area->vf);
-			
-			/* allocate a new channel path structure, if needed */
-			status = get_chp_status(sei_area->rsid);
-			if (status < 0)
-				new_channel_path(sei_area->rsid);
-			else if (!status)
-				break;
-			dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
-			res_data.chp = to_channelpath(dev);
-			pr_debug("chpid: %x", sei_area->rsid);
-			if ((sei_area->vf & 0xc0) != 0) {
-				res_data.fla = sei_area->fla;
-				if ((sei_area->vf & 0xc0) == 0xc0) {
-					pr_debug(" full link addr: %x",
-						 sei_area->fla);
-					res_data.fla_mask = 0xffff;
-				} else {
-					pr_debug(" link addr: %x",
-						 sei_area->fla);
-					res_data.fla_mask = 0xff00;
-				}
-			}
-			ret = s390_process_res_acc(&res_data);
-			pr_debug("\n\n");
-			put_device(dev);
-			break;
-			
-		default: /* other stuff */
-			CIO_CRW_EVENT(4, "chsc_process_crw: event %d\n",
-				      sei_area->cc);
+			ret = 0;
 			break;
 		}
 	} while (sei_area->flags & 0x80);
+
 	return ret;
 }
 
-static inline int
+static int
 __chp_add_new_sch(struct subchannel_id schid)
 {
 	struct schib schib;
 	int ret;
 
-	if (stsch(schid, &schib))
+	if (stsch_err(schid, &schib))
 		/* We're through */
 		return need_rescan ? -EAGAIN : -ENXIO;
 
@@ -709,7 +701,7 @@
 	return chp_add(chpid);
 }
 
-static inline int check_for_io_on_path(struct subchannel *sch, int index)
+static int check_for_io_on_path(struct subchannel *sch, int index)
 {
 	int cc;
 
@@ -741,7 +733,7 @@
 		sch->driver->termination(&sch->dev);
 }
 
-static inline void
+static void
 __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
 {
 	int chp, old_lpm;
@@ -967,8 +959,8 @@
 static void
 chsc_remove_chp_cmg_attr(struct channel_path *chp)
 {
-	sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_chars_attr);
-	sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_attr);
+	device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr);
+	device_remove_bin_file(&chp->dev, &chp_measurement_attr);
 }
 
 static int
@@ -976,14 +968,12 @@
 {
 	int ret;
 
-	ret = sysfs_create_bin_file(&chp->dev.kobj,
-				    &chp_measurement_chars_attr);
+	ret = device_create_bin_file(&chp->dev, &chp_measurement_chars_attr);
 	if (ret)
 		return ret;
-	ret = sysfs_create_bin_file(&chp->dev.kobj, &chp_measurement_attr);
+	ret = device_create_bin_file(&chp->dev, &chp_measurement_attr);
 	if (ret)
-		sysfs_remove_bin_file(&chp->dev.kobj,
-				      &chp_measurement_chars_attr);
+		device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr);
 	return ret;
 }
 
@@ -1042,7 +1032,7 @@
 		u32 : 4;
 		u32 fmt : 4;
 		u32 : 16;
-	} *secm_area;
+	} __attribute__ ((packed)) *secm_area;
 	int ret, ccode;
 
 	secm_area = page;
@@ -1253,7 +1243,7 @@
 		struct chsc_header response;
 		u32 zeroes2;
 		struct channel_path_desc desc;
-	} *scpd_area;
+	} __attribute__ ((packed)) *scpd_area;
 
 	scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scpd_area)
@@ -1350,7 +1340,7 @@
 		u32 cmg : 8;
 		u32 zeroes3;
 		u32 data[NR_MEASUREMENT_CHARS];
-	} *scmc_area;
+	} __attribute__ ((packed)) *scmc_area;
 
 	scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scmc_area)
@@ -1517,7 +1507,7 @@
 		u32 reserved5:4;
 		u32 format2:4;
 		u32 reserved6:24;
-	} *sda_area;
+	} __attribute__ ((packed)) *sda_area;
 
 	sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
 	if (!sda_area)
@@ -1569,7 +1559,7 @@
 		u32 reserved4;
 		u32 general_char[510];
 		u32 chsc_char[518];
-	} *scsc_area;
+	} __attribute__ ((packed)) *scsc_area;
 
 	scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scsc_area) {
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index a259245..0fb2b02 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -10,17 +10,17 @@
 struct chsc_header {
 	u16 length;
 	u16 code;
-};
+} __attribute__ ((packed));
 
 #define NR_MEASUREMENT_CHARS 5
 struct cmg_chars {
 	u32 values[NR_MEASUREMENT_CHARS];
-};
+} __attribute__ ((packed));
 
 #define NR_MEASUREMENT_ENTRIES 8
 struct cmg_entry {
 	u32 values[NR_MEASUREMENT_ENTRIES];
-};
+} __attribute__ ((packed));
 
 struct channel_path_desc {
 	u8 flags;
@@ -31,7 +31,7 @@
 	u8 zeroes;
 	u8 chla;
 	u8 chpp;
-};
+} __attribute__ ((packed));
 
 struct channel_path {
 	int id;
@@ -47,6 +47,9 @@
 extern void s390_process_css( void );
 extern void chsc_validate_chpids(struct subchannel *);
 extern void chpid_is_actually_online(int);
+extern int css_get_ssd_info(struct subchannel *);
+extern int chsc_process_crw(void);
+extern int chp_process_crw(int, int);
 
 struct css_general_char {
 	u64 : 41;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index b471ac4..b3a56dc 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -122,7 +122,7 @@
  * Use tpi to get a pending interrupt, call the interrupt handler and
  * return a pointer to the subchannel structure.
  */
-static inline int
+static int
 cio_tpi(void)
 {
 	struct tpi_info *tpi_info;
@@ -152,7 +152,7 @@
 	return 1;
 }
 
-static inline int
+static int
 cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
 {
 	char dbf_text[15];
@@ -585,7 +585,7 @@
 		 * This device must not be known to Linux. So we simply
 		 * say that there is no device and return ENODEV.
 		 */
-		CIO_MSG_EVENT(0, "Blacklisted device detected "
+		CIO_MSG_EVENT(4, "Blacklisted device detected "
 			      "at devno %04X, subchannel set %x\n",
 			      sch->schib.pmcw.dev, sch->schid.ssid);
 		err = -ENODEV;
@@ -646,7 +646,7 @@
 		 * Make sure that the i/o interrupt did not "overtake"
 		 * the last HZ timer interrupt.
 		 */
-		account_ticks();
+		account_ticks(S390_lowcore.int_clock);
 	/*
 	 * Get interrupt information from lowcore
 	 */
@@ -832,7 +832,7 @@
 }
 
 #endif
-static inline int
+static int
 __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
 {
 	int retry, cc;
@@ -850,7 +850,20 @@
 	return -EBUSY; /* uhm... */
 }
 
-static inline int
+/* we can't use the normal udelay here, since it enables external interrupts */
+
+static void udelay_reset(unsigned long usecs)
+{
+	uint64_t start_cc, end_cc;
+
+	asm volatile ("STCK %0" : "=m" (start_cc));
+	do {
+		cpu_relax();
+		asm volatile ("STCK %0" : "=m" (end_cc));
+	} while (((end_cc - start_cc)/4096) < usecs);
+}
+
+static int
 __clear_subchannel_easy(struct subchannel_id schid)
 {
 	int retry;
@@ -865,7 +878,7 @@
 			if (schid_equal(&ti.schid, &schid))
 				return 0;
 		}
-		udelay(100);
+		udelay_reset(100);
 	}
 	return -EBUSY;
 }
@@ -880,19 +893,15 @@
 static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
 {
 	int rc;
-	register struct subchannel_id reg1 asm ("1") = schid;
 
 	pgm_check_occured = 0;
-	s390_reset_pgm_handler = cio_reset_pgm_check_handler;
+	s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
+	rc = stsch(schid, addr);
+	s390_base_pgm_handler_fn = NULL;
 
-	asm volatile(
-		"       stsch   0(%2)\n"
-		"       ipm     %0\n"
-		"       srl     %0,28"
-		: "=d" (rc)
-		: "d" (reg1), "a" (addr), "m" (*addr) : "memory", "cc");
+	/* The program check handler could have changed pgm_check_occured. */
+	barrier();
 
-	s390_reset_pgm_handler = NULL;
 	if (pgm_check_occured)
 		return -EIO;
 	else
@@ -948,7 +957,7 @@
 	/* Reset subchannels. */
 	for_each_subchannel(__shutdown_subchannel_easy,  NULL);
 	/* Reset channel paths. */
-	s390_reset_mcck_handler = s390_reset_chpids_mcck_handler;
+	s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler;
 	/* Enable channel report machine checks. */
 	__ctl_set_bit(14, 28);
 	/* Temporarily reenable machine checks. */
@@ -973,7 +982,7 @@
 	local_mcck_disable();
 	/* Disable channel report machine checks. */
 	__ctl_clear_bit(14, 28);
-	s390_reset_mcck_handler = NULL;
+	s390_base_mcck_handler_fn = NULL;
 }
 
 static struct reset_call css_reset_call = {
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 828b2d3..90b22fa 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -519,8 +519,8 @@
 /* insert a single device into the cmb_area list
  * called with cmb_area.lock held from alloc_cmb
  */
-static inline int alloc_cmb_single (struct ccw_device *cdev,
-				    struct cmb_data *cmb_data)
+static int alloc_cmb_single(struct ccw_device *cdev,
+			    struct cmb_data *cmb_data)
 {
 	struct cmb *cmb;
 	struct ccw_device_private *node;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 9d6c024..fe0ace7 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -30,7 +30,7 @@
 
 int css_characteristics_avail = 0;
 
-inline int
+int
 for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
 {
 	struct subchannel_id schid;
@@ -108,9 +108,6 @@
 	}
 }
 
-extern int css_get_ssd_info(struct subchannel *sch);
-
-
 int css_sch_device_register(struct subchannel *sch)
 {
 	int ret;
@@ -187,7 +184,7 @@
 	return dev ? to_subchannel(dev) : NULL;
 }
 
-static inline int css_get_subchannel_status(struct subchannel *sch)
+static int css_get_subchannel_status(struct subchannel *sch)
 {
 	struct schib schib;
 
@@ -299,7 +296,7 @@
 		/* Will be done on the slow path. */
 		return -EAGAIN;
 	}
-	if (stsch(schid, &schib) || !schib.pmcw.dnv) {
+	if (stsch_err(schid, &schib) || !schib.pmcw.dnv) {
 		/* Unusable - ignore. */
 		return 0;
 	}
@@ -417,7 +414,7 @@
 		      need_reprobe);
 }
 
-DECLARE_WORK(css_reprobe_work, reprobe_all);
+static DECLARE_WORK(css_reprobe_work, reprobe_all);
 
 /* Schedule reprobing of all unregistered subchannels. */
 void css_schedule_reprobe(void)
@@ -578,7 +575,7 @@
 
 static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store);
 
-static inline int __init setup_css(int nr)
+static int __init setup_css(int nr)
 {
 	u32 tod_high;
 	int ret;
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 3464c5b..ca2bab9 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -143,6 +143,8 @@
 extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
 extern int css_init_done;
 extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
+extern int css_process_crw(int, int);
+extern void css_reiterate_subchannels(void);
 
 #define __MAX_SUBCHANNEL 65535
 #define __MAX_SSID 3
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 8035790..e322111 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -138,7 +138,6 @@
 
 static int io_subchannel_probe (struct subchannel *);
 static int io_subchannel_remove (struct subchannel *);
-void io_subchannel_irq (struct device *);
 static int io_subchannel_notify(struct device *, int);
 static void io_subchannel_verify(struct device *);
 static void io_subchannel_ioterm(struct device *);
@@ -235,11 +234,8 @@
 	ssize_t ret = 0;
 	int chp;
 
-	if (ssd)
-		for (chp = 0; chp < 8; chp++)
-			ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
-	else
-		ret += sprintf (buf, "n/a");
+	for (chp = 0; chp < 8; chp++)
+		ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
 	ret += sprintf (buf+ret, "\n");
 	return min((ssize_t)PAGE_SIZE, ret);
 }
@@ -552,13 +548,13 @@
 	.attrs = ccwdev_attrs,
 };
 
-static inline int
+static int
 device_add_files (struct device *dev)
 {
 	return sysfs_create_group(&dev->kobj, &ccwdev_attr_group);
 }
 
-static inline void
+static void
 device_remove_files(struct device *dev)
 {
 	sysfs_remove_group(&dev->kobj, &ccwdev_attr_group);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 29db634..b66338b 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -74,6 +74,7 @@
 extern wait_queue_head_t ccw_device_init_wq;
 extern atomic_t ccw_device_init_count;
 
+void io_subchannel_irq (struct device *pdev);
 void io_subchannel_recog_done(struct ccw_device *cdev);
 
 int ccw_device_cancel_halt_clear(struct ccw_device *);
@@ -118,6 +119,7 @@
 /* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
 extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
+extern struct bus_type ccw_bus_type;
 
 /* Channel measurement facility related */
 void retry_set_schib(struct ccw_device *cdev);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index eed1457..51238e7 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -206,7 +206,7 @@
  * been varied online on the SE so we have to find out by magic (i. e. driving
  * the channel subsystem to device selection and updating our path masks).
  */
-static inline void
+static void
 __recover_lost_chpids(struct subchannel *sch, int old_lpm)
 {
 	int mask, i;
@@ -387,7 +387,7 @@
 		put_device (&cdev->dev);
 }
 
-static inline int cmp_pgid(struct pgid *p1, struct pgid *p2)
+static int cmp_pgid(struct pgid *p1, struct pgid *p2)
 {
 	char *c1;
 	char *c2;
@@ -842,6 +842,8 @@
 call_handler_unsol:
 		if (cdev->handler)
 			cdev->handler (cdev, 0, irb);
+		if (cdev->private->flags.doverify)
+			ccw_device_online_verify(cdev, 0);
 		return;
 	}
 	/* Accumulate status and find out if a basic sense is needed. */
@@ -892,7 +894,7 @@
 /*
  * Got an interrupt for a basic sense.
  */
-void
+static void
 ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
 {
 	struct irb *irb;
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index d269607..d7b25b8 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -302,7 +302,7 @@
 	wake_up(&cdev->private->wait_q);
 }
 
-static inline int
+static int
 __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm)
 {
 	int ret;
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index bdcf930..6b1caea 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -25,7 +25,7 @@
  * Check for any kind of channel or interface control check but don't
  * issue the message for the console device
  */
-static inline void
+static void
 ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
 {
 	if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK |
@@ -72,7 +72,7 @@
 /*
  * Copy valid bits from the extended control word to device irb.
  */
-static inline void
+static void
 ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
 {
 	/*
@@ -94,7 +94,7 @@
 /*
  * Check if extended status word is valid.
  */
-static inline int
+static int
 ccw_device_accumulate_esw_valid(struct irb *irb)
 {
 	if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
@@ -109,7 +109,7 @@
 /*
  * Copy valid bits from the extended status word to device irb.
  */
-static inline void
+static void
 ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
 {
 	struct irb *cdev_irb;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 6fd1940..d726cd5 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -66,7 +66,6 @@
 /******************** HERE WE GO ***********************************/
 
 static const char version[] = "QDIO base support version 2";
-extern struct bus_type ccw_bus_type;
 
 static int qdio_performance_stats = 0;
 static int proc_perf_file_registration;
@@ -138,7 +137,7 @@
 }
 
 /*check ccq  */
-static inline int
+static int
 qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
 {
 	char dbf_text[15];
@@ -153,7 +152,7 @@
 	return -EIO;
 }
 /* EQBS: extract buffer states */
-static inline int
+static int
 qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
 	     unsigned int *start, unsigned int *cnt)
 {
@@ -188,7 +187,7 @@
 }
 
 /* SQBS: set buffer states */
-static inline int
+static int
 qdio_do_sqbs(struct qdio_q *q, unsigned char state,
 	     unsigned int *start, unsigned int *cnt)
 {
@@ -315,7 +314,7 @@
  * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
  * an access exception 
  */
-static inline int 
+static int
 qdio_siga_output(struct qdio_q *q)
 {
 	int cc;
@@ -349,7 +348,7 @@
 	return cc;
 }
 
-static inline int 
+static int
 qdio_siga_input(struct qdio_q *q)
 {
 	int cc;
@@ -421,7 +420,7 @@
 	tasklet_hi_schedule(&tiqdio_tasklet);
 }
 
-static inline void
+static void
 qdio_mark_tiq(struct qdio_q *q)
 {
 	unsigned long flags;
@@ -471,7 +470,7 @@
 	tasklet_schedule(&q->tasklet);
 }
 
-static inline int
+static int
 qdio_stop_polling(struct qdio_q *q)
 {
 #ifdef QDIO_USE_PROCESSING_STATE
@@ -525,7 +524,7 @@
  * sophisticated locking outside of unmark_q, so that we don't need to
  * disable the interrupts :-) 
 */
-static inline void
+static void
 qdio_unmark_q(struct qdio_q *q)
 {
 	unsigned long flags;
@@ -691,7 +690,7 @@
         return q->first_to_check;
 }
 
-static inline int
+static int
 qdio_get_outbound_buffer_frontier(struct qdio_q *q)
 {
 	struct qdio_irq *irq;
@@ -774,7 +773,7 @@
 }
 
 /* all buffers are processed */
-static inline int
+static int
 qdio_is_outbound_q_done(struct qdio_q *q)
 {
 	int no_used;
@@ -796,7 +795,7 @@
 	return (no_used==0);
 }
 
-static inline int
+static int
 qdio_has_outbound_q_moved(struct qdio_q *q)
 {
 	int i;
@@ -816,7 +815,7 @@
 	}
 }
 
-static inline void
+static void
 qdio_kick_outbound_q(struct qdio_q *q)
 {
 	int result;
@@ -905,7 +904,7 @@
 	}
 }
 
-static inline void
+static void
 qdio_kick_outbound_handler(struct qdio_q *q)
 {
 	int start, end, real_end, count;
@@ -942,7 +941,7 @@
 	q->error_status_flags=0;
 }
 
-static inline void
+static void
 __qdio_outbound_processing(struct qdio_q *q)
 {
 	int siga_attempts;
@@ -1002,7 +1001,7 @@
 /************************* INBOUND ROUTINES *******************************/
 
 
-static inline int
+static int
 qdio_get_inbound_buffer_frontier(struct qdio_q *q)
 {
 	struct qdio_irq *irq;
@@ -1133,7 +1132,7 @@
 	return q->first_to_check;
 }
 
-static inline int
+static int
 qdio_has_inbound_q_moved(struct qdio_q *q)
 {
 	int i;
@@ -1167,7 +1166,7 @@
 }
 
 /* means, no more buffers to be filled */
-static inline int
+static int
 tiqdio_is_inbound_q_done(struct qdio_q *q)
 {
 	int no_used;
@@ -1228,7 +1227,7 @@
 	return 0;
 }
 
-static inline int
+static int
 qdio_is_inbound_q_done(struct qdio_q *q)
 {
 	int no_used;
@@ -1296,7 +1295,7 @@
 	}
 }
 
-static inline void
+static void
 qdio_kick_inbound_handler(struct qdio_q *q)
 {
 	int count, start, end, real_end, i;
@@ -1343,7 +1342,7 @@
 	}
 }
 
-static inline void
+static void
 __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
 {
 	struct qdio_irq *irq_ptr;
@@ -1442,7 +1441,7 @@
 	__tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount));
 }
 
-static inline void
+static void
 __qdio_inbound_processing(struct qdio_q *q)
 {
 	int q_laps=0;
@@ -1493,7 +1492,7 @@
 /************************* MAIN ROUTINES *******************************/
 
 #ifdef QDIO_USE_PROCESSING_STATE
-static inline int
+static int
 tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
 {
 	if (!q) {
@@ -1545,7 +1544,7 @@
 }
 #endif /* QDIO_USE_PROCESSING_STATE */
 
-static inline void
+static void
 tiqdio_inbound_checks(void)
 {
 	struct qdio_q *q;
@@ -1949,7 +1948,7 @@
 	mb();
 }
 
-static inline void
+static void
 qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb)
 {
 	char dbf_text[15];
@@ -1966,7 +1965,7 @@
 		
 }
 
-static inline void
+static void
 qdio_handle_pci(struct qdio_irq *irq_ptr)
 {
 	int i;
@@ -2002,7 +2001,7 @@
 
 static void qdio_establish_handle_irq(struct ccw_device*, int, int);
 
-static inline void
+static void
 qdio_handle_activate_check(struct ccw_device *cdev, unsigned long intparm,
 			   int cstat, int dstat)
 {
@@ -2229,7 +2228,7 @@
 	return cc;
 }
 
-static inline void
+static void
 qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
 			    unsigned long token)
 {
@@ -2740,7 +2739,7 @@
 	return 0;
 }
 
-static inline void
+static void
 qdio_allocate_do_dbf(struct qdio_initialize *init_data)
 {
 	char dbf_text[20]; /* if a printf printed out more than 8 chars */
@@ -2773,7 +2772,7 @@
 	QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*));
 }
 
-static inline void
+static void
 qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt)
 {
 	irq_ptr->input_qs[i]->is_iqdio_q = iqfmt;
@@ -2792,7 +2791,7 @@
 	irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_KEY;
 }
 
-static inline void
+static void
 qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i,
 			       int j, int iqfmt)
 {
@@ -2813,7 +2812,7 @@
 }
 
 
-static inline void
+static void
 qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr)
 {
 	int i;
@@ -2839,7 +2838,7 @@
 	}
 }
 
-static inline void
+static void
 qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr)
 {
 	int i;
@@ -2865,7 +2864,7 @@
 	}
 }
 
-static inline int
+static int
 qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
 				    int dstat)
 {
@@ -3014,7 +3013,7 @@
 	return 0;
 }
 
-int qdio_fill_irq(struct qdio_initialize *init_data)
+static int qdio_fill_irq(struct qdio_initialize *init_data)
 {
 	int i;
 	char dbf_text[15];
@@ -3367,7 +3366,7 @@
 }
 
 /* buffers filled forwards again to make Rick happy */
-static inline void
+static void
 qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
 			unsigned int count, struct qdio_buffer *buffers)
 {
@@ -3386,7 +3385,7 @@
 	}
 }
 
-static inline void
+static void
 qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
 			 unsigned int count, struct qdio_buffer *buffers)
 {
@@ -3407,7 +3406,7 @@
 	}
 }
 
-static inline void
+static void
 do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags,
 		       unsigned int qidx, unsigned int count,
 		       struct qdio_buffer *buffers)
@@ -3443,7 +3442,7 @@
 	qdio_mark_q(q);
 }
 
-static inline void
+static void
 do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
 			unsigned int qidx, unsigned int count,
 			struct qdio_buffer *buffers)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 81b5899..c7d1355 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -465,7 +465,7 @@
  * Flush all requests from the request/pending queue of an AP device.
  * @ap_dev: pointer to the AP device.
  */
-static inline void __ap_flush_queue(struct ap_device *ap_dev)
+static void __ap_flush_queue(struct ap_device *ap_dev)
 {
 	struct ap_message *ap_msg, *next;
 
@@ -587,7 +587,7 @@
 /**
  * Pick one of the 16 ap domains.
  */
-static inline int ap_select_domain(void)
+static int ap_select_domain(void)
 {
 	int queue_depth, device_type, count, max_count, best_domain;
 	int rc, i, j;
@@ -825,7 +825,7 @@
  *	   required, bit 2^1 is set if the poll timer needs to get armed
  * Returns 0 if the device is still present, -ENODEV if not.
  */
-static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
+static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
 {
 	struct ap_queue_status status;
 	struct ap_message *ap_msg;
@@ -872,7 +872,7 @@
  *	   required, bit 2^1 is set if the poll timer needs to get armed
  * Returns 0 if the device is still present, -ENODEV if not.
  */
-static inline int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
+static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
 {
 	struct ap_queue_status status;
 	struct ap_message *ap_msg;
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 1edc10a..b9e59bc 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -791,7 +791,7 @@
 	return rc;
 }
 
-long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
+static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
 			 unsigned long arg)
 {
 	if (cmd == ICARSAMODEXPO)
@@ -833,8 +833,8 @@
  */
 static struct proc_dir_entry *zcrypt_entry;
 
-static inline int sprintcl(unsigned char *outaddr, unsigned char *addr,
-			   unsigned int len)
+static int sprintcl(unsigned char *outaddr, unsigned char *addr,
+		    unsigned int len)
 {
 	int hl, i;
 
@@ -845,8 +845,8 @@
 	return hl;
 }
 
-static inline int sprintrw(unsigned char *outaddr, unsigned char *addr,
-			   unsigned int len)
+static int sprintrw(unsigned char *outaddr, unsigned char *addr,
+		    unsigned int len)
 {
 	int hl, inl, c, cx;
 
@@ -865,8 +865,8 @@
 	return hl;
 }
 
-static inline int sprinthx(unsigned char *title, unsigned char *outaddr,
-			   unsigned char *addr, unsigned int len)
+static int sprinthx(unsigned char *title, unsigned char *outaddr,
+		    unsigned char *addr, unsigned int len)
 {
 	int hl, inl, r, rx;
 
@@ -885,8 +885,8 @@
 	return hl;
 }
 
-static inline int sprinthx4(unsigned char *title, unsigned char *outaddr,
-			    unsigned int *array, unsigned int len)
+static int sprinthx4(unsigned char *title, unsigned char *outaddr,
+		     unsigned int *array, unsigned int len)
 {
 	int hl, r;
 
@@ -943,7 +943,7 @@
 	zcrypt_qdepth_mask(workarea);
 	len += sprinthx("Waiting work element counts",
 			resp_buff+len, workarea, AP_DEVICES);
-	zcrypt_perdev_reqcnt((unsigned int *) workarea);
+	zcrypt_perdev_reqcnt((int *) workarea);
 	len += sprinthx4("Per-device successfully completed request counts",
 			 resp_buff+len,(unsigned int *) workarea, AP_DEVICES);
 	*eof = 1;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 32e3701..818ffe0 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -191,10 +191,10 @@
  *
  * Returns 0 on success or -EFAULT.
  */
-static inline int convert_type84(struct zcrypt_device *zdev,
-				 struct ap_message *reply,
-				 char __user *outputdata,
-				 unsigned int outputdatalength)
+static int convert_type84(struct zcrypt_device *zdev,
+			  struct ap_message *reply,
+			  char __user *outputdata,
+			  unsigned int outputdatalength)
 {
 	struct type84_hdr *t84h = reply->message;
 	char *data;
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index b7153c1..252443b 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -709,7 +709,8 @@
  *	  PCIXCC/CEX2C device to the request distributor
  * @xcRB: pointer to the send_cprb request buffer
  */
-long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB)
+static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
+				    struct ica_xcRB *xcRB)
 {
 	struct ap_message ap_msg;
 	struct response_type resp_type = {
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 1a93fa6..5262515 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -27,10 +27,7 @@
 	help
 	  Select this option if you want to use inter-user communication
 	  under VM or VIF. If unsure, say "Y" to enable a fast communication
-	  link between VM guests. At boot time the user ID of the guest needs
-	  to be passed to the kernel. Note that both kernels need to be
-	  compiled with this option and both need to be booted with the user ID
-	  of the other VM guest.
+	  link between VM guests.
 
 config NETIUCV
 	tristate "IUCV network device support (VM only)"
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 95f4e10..7809a79 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -121,7 +121,7 @@
 #define DEBUG
 #endif
 
- char debug_buffer[255];
+static char debug_buffer[255];
 /**
  * Debug Facility Stuff
  */
@@ -223,16 +223,14 @@
 /* Functions */
 static int add_claw_reads(struct net_device *dev,
 	struct ccwbk* p_first, struct ccwbk* p_last);
-static void inline ccw_check_return_code (struct ccw_device *cdev,
-        int return_code);
-static void inline ccw_check_unit_check (struct chbk * p_ch,
-	unsigned char sense );
+static void ccw_check_return_code (struct ccw_device *cdev, int return_code);
+static void ccw_check_unit_check (struct chbk * p_ch, unsigned char sense );
 static int find_link(struct net_device *dev, char *host_name, char *ws_name );
 static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid);
 static int init_ccw_bk(struct net_device *dev);
 static void probe_error( struct ccwgroup_device *cgdev);
 static struct net_device_stats *claw_stats(struct net_device *dev);
-static int inline pages_to_order_of_mag(int num_of_pages);
+static int pages_to_order_of_mag(int num_of_pages);
 static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
 #ifdef DEBUG
 static void dumpit (char *buf, int len);
@@ -1310,7 +1308,7 @@
 *    of magnitude get_free_pages() has an upper order of 9           *
 *--------------------------------------------------------------------*/
 
-static int inline
+static int
 pages_to_order_of_mag(int num_of_pages)
 {
 	int	order_of_mag=1;		/* assume 2 pages */
@@ -1482,7 +1480,7 @@
  *                                                                   *
  *-------------------------------------------------------------------*/
 
-static void inline
+static void
 ccw_check_return_code(struct ccw_device *cdev, int return_code)
 {
 #ifdef FUNCTRACE
@@ -1529,7 +1527,7 @@
 *       ccw_check_unit_check                                         *
 *--------------------------------------------------------------------*/
 
-static void inline
+static void
 ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
 {
 	struct net_device *dev = p_ch->ndev;
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 03cc263..5a84fbb 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -369,7 +369,7 @@
  * @param ch The channel where this skb has been received.
  * @param pskb The received skb.
  */
-static __inline__ void
+static void
 ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
 {
 	struct net_device *dev = ch->netdev;
@@ -512,7 +512,7 @@
  * @param ch          The channel, the error belongs to.
  * @param return_code The error code to inspect.
  */
-static void inline
+static void
 ccw_check_return_code(struct channel *ch, int return_code, char *msg)
 {
 	DBF_TEXT(trace, 5, __FUNCTION__);
@@ -547,7 +547,7 @@
  * @param ch    The channel, the sense code belongs to.
  * @param sense The sense code to inspect.
  */
-static void inline
+static void
 ccw_unit_check(struct channel *ch, unsigned char sense)
 {
 	DBF_TEXT(trace, 5, __FUNCTION__);
@@ -603,7 +603,7 @@
 	}
 }
 
-static __inline__ int
+static int
 ctc_checkalloc_buffer(struct channel *ch, int warn)
 {
 	DBF_TEXT(trace, 5, __FUNCTION__);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index e965f03..76728ae 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -57,7 +57,7 @@
 
 static struct ccw_driver cu3088_driver;
 
-struct device *cu3088_root_dev;
+static struct device *cu3088_root_dev;
 
 static ssize_t
 group_write(struct device_driver *drv, const char *buf, size_t count)
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index e5665b6..b97dd15 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -828,7 +828,7 @@
 /**
  * Emit buffer of a lan comand.
  */
-void
+static void
 lcs_lancmd_timeout(unsigned long data)
 {
 	struct lcs_reply *reply, *list_reply, *r;
@@ -1360,7 +1360,7 @@
 	return 0;
 }
 
-void
+static void
 lcs_schedule_recovery(struct lcs_card *card)
 {
 	LCS_DBF_TEXT(2, trace, "startrec");
@@ -1990,7 +1990,7 @@
 
 }
 
-DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
+static DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
 
 static ssize_t
 lcs_dev_recover_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index d7d1cc0..3346088 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -2053,7 +2053,7 @@
 	return ret;
 }
 
-DRIVER_ATTR(connection, 0200, NULL, conn_write);
+static DRIVER_ATTR(connection, 0200, NULL, conn_write);
 
 static ssize_t
 remove_write (struct device_driver *drv, const char *buf, size_t count)
@@ -2112,7 +2112,7 @@
         return -EINVAL;
 }
 
-DRIVER_ATTR(remove, 0200, NULL, remove_write);
+static DRIVER_ATTR(remove, 0200, NULL, remove_write);
 
 static void
 netiucv_banner(void)
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 53c358c..e95c281 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -710,7 +710,7 @@
 	int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
  	u32 seqno;
 	unsigned long offset;
-	int received;
+	atomic_t received;
 	int rc;
 	void *param;
 	struct qeth_card *card;
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 6bb558a..7c735e1 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -49,7 +49,7 @@
 	return buffers_needed;
 }
 
-static inline void
+static void
 qeth_eddp_free_context(struct qeth_eddp_context *ctx)
 {
 	int i;
@@ -91,7 +91,7 @@
 	}
 }
 
-static inline int
+static int
 qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
 			  struct qeth_eddp_context *ctx)
 {
@@ -196,7 +196,7 @@
 	return flush_cnt;
 }
 
-static inline void
+static void
 qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
 			      struct qeth_eddp_data *eddp, int data_len)
 {
@@ -256,7 +256,7 @@
 	ctx->offset += eddp->thl;
 }
 
-static inline void
+static void
 qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
 			__wsum *hcsum)
 {
@@ -302,7 +302,7 @@
 	}
 }
 
-static inline void
+static void
 qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
 				  struct qeth_eddp_data *eddp, int data_len,
 				  __wsum hcsum)
@@ -349,7 +349,7 @@
 	((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
 }
 
-static inline __wsum
+static __wsum
 qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
 {
 	__wsum phcsum; /* pseudo header checksum */
@@ -363,7 +363,7 @@
 	return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
 }
 
-static inline __wsum
+static __wsum
 qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
 {
 	__be32 proto;
@@ -381,7 +381,7 @@
 	return phcsum;
 }
 
-static inline struct qeth_eddp_data *
+static struct qeth_eddp_data *
 qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
 {
 	struct qeth_eddp_data *eddp;
@@ -399,7 +399,7 @@
 	return eddp;
 }
 
-static inline void
+static void
 __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
 			     struct qeth_eddp_data *eddp)
 {
@@ -464,7 +464,7 @@
 	}
 }
 
-static inline int
+static int
 qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
 			   struct sk_buff *skb, struct qeth_hdr *qhdr)
 {
@@ -505,7 +505,7 @@
 	return 0;
 }
 
-static inline void
+static void
 qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
 			 int hdr_len)
 {
@@ -529,7 +529,7 @@
 			    (skb_shinfo(skb)->gso_segs + 1);
 }
 
-static inline struct qeth_eddp_context *
+static struct qeth_eddp_context *
 qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
 				 int hdr_len)
 {
@@ -581,7 +581,7 @@
 	return ctx;
 }
 
-static inline struct qeth_eddp_context *
+static struct qeth_eddp_context *
 qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
 			     struct qeth_hdr *qhdr)
 {
@@ -625,5 +625,3 @@
 	}
 	return NULL;
 }
-
-
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 2bde4f1..2257e45 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -471,7 +471,7 @@
 	    channel->state == CH_STATE_UP)
 		qeth_issue_next_read(card);
 
-	tasklet_schedule(&channel->irq_tasklet);
+	qeth_irq_tasklet((unsigned long)channel);
 	return;
 out:
 	wake_up(&card->wait_q);
@@ -651,7 +651,7 @@
 		return 0;
 }
 
-static inline int
+static int
 __qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
 		              int same_type)
 {
@@ -795,7 +795,7 @@
 	return rc;
 }
 
-static inline void
+static void
 __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
 {
 	struct qeth_ipaddr *addr, *tmp;
@@ -882,7 +882,7 @@
 static void qeth_add_multicast_ipv6(struct qeth_card *);
 #endif
 
-static inline int
+static int
 qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
 {
 	unsigned long flags;
@@ -920,7 +920,7 @@
 	wake_up(&card->wait_q);
 }
 
-static inline int
+static int
 __qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
 {
 	unsigned long flags;
@@ -951,40 +951,6 @@
 }
 
 static int
-qeth_register_ip_addresses(void *ptr)
-{
-	struct qeth_card *card;
-
-	card = (struct qeth_card *) ptr;
-	daemonize("qeth_reg_ip");
-	QETH_DBF_TEXT(trace,4,"regipth1");
-	if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD))
-		return 0;
-	QETH_DBF_TEXT(trace,4,"regipth2");
-	qeth_set_ip_addr_list(card);
-	qeth_clear_thread_running_bit(card, QETH_SET_IP_THREAD);
-	return 0;
-}
-
-/*
- * Drive the SET_PROMISC_MODE thread
- */
-static int
-qeth_set_promisc_mode(void *ptr)
-{
-	struct qeth_card *card = (struct qeth_card *) ptr;
-
-	daemonize("qeth_setprm");
-	QETH_DBF_TEXT(trace,4,"setprm1");
-	if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
-		return 0;
-	QETH_DBF_TEXT(trace,4,"setprm2");
-	qeth_setadp_promisc_mode(card);
-	qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
-	return 0;
-}
-
-static int
 qeth_recover(void *ptr)
 {
 	struct qeth_card *card;
@@ -1047,11 +1013,6 @@
 	if (card->read.state != CH_STATE_UP &&
 	    card->write.state != CH_STATE_UP)
 		return;
-
-	if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
-		kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
-	if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
-		kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
 	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
 		kernel_thread(qeth_recover, (void *) card, SIGCHLD);
 }
@@ -1074,7 +1035,7 @@
 		card->options.layer2 = 1;
 	else
 		card->options.layer2 = 0;
-	card->options.performance_stats = 1;
+	card->options.performance_stats = 0;
 }
 
 /**
@@ -1613,8 +1574,6 @@
 		return -ENOMEM;
 	}
 	qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
-	wait_event(card->wait_q,
-		   atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
 	QETH_DBF_TEXT(trace, 6, "noirqpnd");
 	rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
 			      (addr_t) iob, 0, 0);
@@ -1635,6 +1594,7 @@
 	reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
 	if (reply){
 		atomic_set(&reply->refcnt, 1);
+		atomic_set(&reply->received, 0);
 		reply->card = card;
 	};
 	return reply;
@@ -1655,31 +1615,6 @@
 		kfree(reply);
 }
 
-static void
-qeth_cmd_timeout(unsigned long data)
-{
-	struct qeth_reply *reply, *list_reply, *r;
-	unsigned long flags;
-
-	reply = (struct qeth_reply *) data;
-	spin_lock_irqsave(&reply->card->lock, flags);
-	list_for_each_entry_safe(list_reply, r,
-				 &reply->card->cmd_waiter_list, list) {
-		if (reply == list_reply){
-			qeth_get_reply(reply);
-			list_del_init(&reply->list);
-			spin_unlock_irqrestore(&reply->card->lock, flags);
-			reply->rc = -ETIME;
-			reply->received = 1;
-			wake_up(&reply->wait_q);
-			qeth_put_reply(reply);
-			return;
-		}
-	}
-	spin_unlock_irqrestore(&reply->card->lock, flags);
-}
-
-
 static struct qeth_ipa_cmd *
 qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
 {
@@ -1745,7 +1680,7 @@
 	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
 		qeth_get_reply(reply);
 		reply->rc = -EIO;
-		reply->received = 1;
+		atomic_inc(&reply->received);
 		list_del_init(&reply->list);
 		wake_up(&reply->wait_q);
 		qeth_put_reply(reply);
@@ -1814,7 +1749,7 @@
 					      &card->cmd_waiter_list);
 				spin_unlock_irqrestore(&card->lock, flags);
 			} else {
-				reply->received = 1;
+				atomic_inc(&reply->received);
 				wake_up(&reply->wait_q);
 			}
 			qeth_put_reply(reply);
@@ -1829,9 +1764,9 @@
 	qeth_release_buffer(channel,iob);
 }
 
-static inline void
+static void
 qeth_prepare_control_data(struct qeth_card *card, int len,
-struct qeth_cmd_buffer *iob)
+			  struct qeth_cmd_buffer *iob)
 {
 	qeth_setup_ccw(&card->write,iob->data,len);
 	iob->callback = qeth_release_buffer;
@@ -1858,7 +1793,7 @@
 	int rc;
 	unsigned long flags;
 	struct qeth_reply *reply = NULL;
-	struct timer_list timer;
+	unsigned long timeout;
 
 	QETH_DBF_TEXT(trace, 2, "sendctl");
 
@@ -1873,21 +1808,20 @@
 		reply->seqno = QETH_IDX_COMMAND_SEQNO;
 	else
 		reply->seqno = card->seqno.ipa++;
-	init_timer(&timer);
-	timer.function = qeth_cmd_timeout;
-	timer.data = (unsigned long) reply;
 	init_waitqueue_head(&reply->wait_q);
 	spin_lock_irqsave(&card->lock, flags);
 	list_add_tail(&reply->list, &card->cmd_waiter_list);
 	spin_unlock_irqrestore(&card->lock, flags);
 	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
-	wait_event(card->wait_q,
-		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+
+	while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
 	qeth_prepare_control_data(card, len, iob);
+
 	if (IS_IPA(iob->data))
-		timer.expires = jiffies + QETH_IPA_TIMEOUT;
+		timeout = jiffies + QETH_IPA_TIMEOUT;
 	else
-		timer.expires = jiffies + QETH_TIMEOUT;
+		timeout = jiffies + QETH_TIMEOUT;
+
 	QETH_DBF_TEXT(trace, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
 	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1906,9 +1840,16 @@
 		wake_up(&card->wait_q);
 		return rc;
 	}
-	add_timer(&timer);
-	wait_event(reply->wait_q, reply->received);
-	del_timer_sync(&timer);
+	while (!atomic_read(&reply->received)) {
+		if (time_after(jiffies, timeout)) {
+			spin_lock_irqsave(&reply->card->lock, flags);
+			list_del_init(&reply->list);
+			spin_unlock_irqrestore(&reply->card->lock, flags);
+			reply->rc = -ETIME;
+			atomic_inc(&reply->received);
+			wake_up(&reply->wait_q);
+		}
+	};
 	rc = reply->rc;
 	qeth_put_reply(reply);
 	return rc;
@@ -2219,7 +2160,7 @@
 	return 0;
 }
 
-static inline struct sk_buff *
+static struct sk_buff *
 qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
 {
 	struct sk_buff* skb;
@@ -2238,7 +2179,7 @@
 	return skb;
 }
 
-static inline struct sk_buff *
+static struct sk_buff *
 qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
 		  struct qdio_buffer_element **__element, int *__offset,
 		  struct qeth_hdr **hdr)
@@ -2323,7 +2264,7 @@
 	return NULL;
 }
 
-static inline __be16
+static __be16
 qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct qeth_card *card;
@@ -2356,7 +2297,7 @@
 	return htons(ETH_P_802_2);
 }
 
-static inline void
+static void
 qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
 			 struct qeth_hdr *hdr)
 {
@@ -2410,7 +2351,7 @@
 	fake_llc->ethertype = ETH_P_IP;
 }
 
-static inline void
+static void
 qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
 			 struct qeth_hdr *hdr)
 {
@@ -2466,35 +2407,20 @@
 		qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
 }
 
-static inline __u16
+static inline void
 qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
 			struct qeth_hdr *hdr)
 {
-	unsigned short vlan_id = 0;
-#ifdef CONFIG_QETH_VLAN
-	struct vlan_hdr *vhdr;
-#endif
-
 	skb->pkt_type = PACKET_HOST;
 	skb->protocol = qeth_type_trans(skb, skb->dev);
 	if (card->options.checksum_type == NO_CHECKSUMMING)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
 		skb->ip_summed = CHECKSUM_NONE;
-#ifdef CONFIG_QETH_VLAN
-	if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) {
-		vhdr = (struct vlan_hdr *) skb->data;
-		skb->protocol =
-			__constant_htons(vhdr->h_vlan_encapsulated_proto);
-		vlan_id = hdr->hdr.l2.vlan_id;
-		skb_pull(skb, VLAN_HLEN);
-	}
-#endif
 	*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
-	return vlan_id;
 }
 
-static inline __u16
+static __u16
 qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
 		 struct qeth_hdr *hdr)
 {
@@ -2550,7 +2476,7 @@
 	return vlan_id;
 }
 
-static inline void
+static void
 qeth_process_inbound_buffer(struct qeth_card *card,
 			    struct qeth_qdio_buffer *buf, int index)
 {
@@ -2560,7 +2486,6 @@
 	int offset;
 	int rxrc;
 	__u16 vlan_tag = 0;
-	__u16 *vlan_addr;
 
 	/* get first element of current buffer */
 	element = (struct qdio_buffer_element *)&buf->buffer->element[0];
@@ -2571,7 +2496,7 @@
 				       &offset, &hdr))) {
 		skb->dev = card->dev;
 		if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
-			vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
+			qeth_layer2_rebuild_skb(card, skb, hdr);
 		else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
 			vlan_tag = qeth_rebuild_skb(card, skb, hdr);
 		else { /*in case of OSN*/
@@ -2603,7 +2528,7 @@
 	}
 }
 
-static inline struct qeth_buffer_pool_entry *
+static struct qeth_buffer_pool_entry *
 qeth_get_buffer_pool_entry(struct qeth_card *card)
 {
 	struct qeth_buffer_pool_entry *entry;
@@ -2618,7 +2543,7 @@
 	return NULL;
 }
 
-static inline void
+static void
 qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
 {
 	struct qeth_buffer_pool_entry *pool_entry;
@@ -2645,7 +2570,7 @@
 	buf->state = QETH_QDIO_BUF_EMPTY;
 }
 
-static inline void
+static void
 qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
 			 struct qeth_qdio_out_buffer *buf)
 {
@@ -2670,7 +2595,7 @@
 	atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
 }
 
-static inline void
+static void
 qeth_queue_input_buffer(struct qeth_card *card, int index)
 {
 	struct qeth_qdio_q *queue = card->qdio.in_q;
@@ -2774,7 +2699,7 @@
 			card->perf_stats.inbound_start_time;
 }
 
-static inline int
+static int
 qeth_handle_send_error(struct qeth_card *card,
 		       struct qeth_qdio_out_buffer *buffer,
 		       unsigned int qdio_err, unsigned int siga_err)
@@ -2896,7 +2821,7 @@
  * Switched to packing state if the number of used buffers on a queue
  * reaches a certain limit.
  */
-static inline void
+static void
 qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
 {
 	if (!queue->do_pack) {
@@ -2917,7 +2842,7 @@
  * In that case 1 is returned to inform the caller. If no buffer
  * has to be flushed, zero is returned.
  */
-static inline int
+static int
 qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
 {
 	struct qeth_qdio_out_buffer *buffer;
@@ -2952,7 +2877,7 @@
  * Checks if there is a packing buffer and prepares it to be flushed.
  * In that case returns 1, otherwise zero.
  */
-static inline int
+static int
 qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
 {
 	struct qeth_qdio_out_buffer *buffer;
@@ -2969,7 +2894,7 @@
 	return 0;
 }
 
-static inline void
+static void
 qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
 {
 	int index;
@@ -3669,7 +3594,7 @@
 	}
 }
 
-static inline int
+static int
 qeth_send_packet(struct qeth_card *, struct sk_buff *);
 
 static int
@@ -3834,7 +3759,7 @@
 	return 0;
 }
 
-static inline int
+static int
 qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
 {
 	int cast_type = RTN_UNSPEC;
@@ -3881,7 +3806,7 @@
 	return cast_type;
 }
 
-static inline int
+static int
 qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
 		        int ipv, int cast_type)
 {
@@ -3928,7 +3853,7 @@
 	}
 }
 
-static inline struct qeth_hdr *
+static struct qeth_hdr *
 __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
 {
 #ifdef CONFIG_QETH_VLAN
@@ -3957,24 +3882,33 @@
 		qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
 }
 
-static inline void
+static void
 __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
 {
 	if (orig_skb != new_skb)
 		dev_kfree_skb_any(new_skb);
 }
 
-static inline struct sk_buff *
+static struct sk_buff *
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
 		 struct qeth_hdr **hdr, int ipv)
 {
-	struct sk_buff *new_skb;
+	struct sk_buff *new_skb, *new_skb2;
 	
 	QETH_DBF_TEXT(trace, 6, "prepskb");
-
-        new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
-       	if (new_skb == NULL)
+	new_skb = skb;
+	new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+	if (!new_skb)
 		return NULL;
+	new_skb2 = qeth_realloc_headroom(card, new_skb,
+					 sizeof(struct qeth_hdr));
+	if (!new_skb2) {
+		__qeth_free_new_skb(skb, new_skb);
+		return NULL;
+	}
+	if (new_skb != skb)
+		__qeth_free_new_skb(new_skb2, new_skb);
+	new_skb = new_skb2;
 	*hdr = __qeth_prepare_skb(card, new_skb, ipv);
 	if (*hdr == NULL) {
 		__qeth_free_new_skb(skb, new_skb);
@@ -4006,7 +3940,7 @@
 	return ct | QETH_CAST_UNICAST;
 }
 
-static inline void
+static void
 qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
 			    struct sk_buff *skb)
 {
@@ -4043,7 +3977,7 @@
 	}
 }
 
-static inline void
+static void
 qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
 			struct sk_buff *skb, int cast_type)
 {
@@ -4134,7 +4068,7 @@
 	}
 }
 
-static inline void
+static void
 __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
 		   int is_tso, int *next_element_to_fill)
 {
@@ -4178,7 +4112,7 @@
 	*next_element_to_fill = element;
 }
 
-static inline int
+static int
 qeth_fill_buffer(struct qeth_qdio_out_q *queue,
 		 struct qeth_qdio_out_buffer *buf,
 		 struct sk_buff *skb)
@@ -4237,7 +4171,7 @@
 	return flush_cnt;
 }
 
-static inline int
+static int
 qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
 			 struct sk_buff *skb, struct qeth_hdr *hdr,
 			 int elements_needed,
@@ -4288,7 +4222,7 @@
 	return -EBUSY;
 }
 
-static inline int
+static int
 qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
 		    struct sk_buff *skb, struct qeth_hdr *hdr,
 		    int elements_needed, struct qeth_eddp_context *ctx)
@@ -4394,7 +4328,7 @@
 	return rc;
 }
 
-static inline int
+static int
 qeth_get_elements_no(struct qeth_card *card, void *hdr,
 		     struct sk_buff *skb, int elems)
 {
@@ -4415,7 +4349,7 @@
 }
 
 
-static inline int
+static int
 qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
 {
 	int ipv = 0;
@@ -4602,7 +4536,7 @@
 }
 
 
-static inline const char *
+static const char *
 qeth_arp_get_error_cause(int *rc)
 {
 	switch (*rc) {
@@ -4663,7 +4597,7 @@
 	return rc;
 }
 
-static inline void
+static void
 qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
 		               struct qeth_arp_query_data *qdata,
 			       int entry_size, int uentry_size)
@@ -4844,9 +4778,11 @@
 			   "(0x%x/%d)\n",
 			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
 			   tmp, tmp);
-		copy_to_user(udata, qinfo.udata, 4);
+		if (copy_to_user(udata, qinfo.udata, 4))
+			rc = -EFAULT;
 	} else {
-		copy_to_user(udata, qinfo.udata, qinfo.udata_len);
+		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+			rc = -EFAULT;
 	}
 	kfree(qinfo.udata);
 	return rc;
@@ -4992,8 +4928,10 @@
 	if (rc)
 		PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
 			   QETH_CARD_IFNAME(card), rc);
-	 else
-		copy_to_user(udata, qinfo.udata, qinfo.udata_len);
+	else {
+		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+			rc = -EFAULT;
+	}
 
 	kfree(ureq);
 	kfree(qinfo.udata);
@@ -5276,7 +5214,7 @@
 	spin_unlock_irqrestore(&card->vlanlock, flags);
 }
 
-static inline void
+static void
 qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
 		      unsigned short vid)
 {
@@ -5544,12 +5482,10 @@
 	qeth_add_multicast_ipv6(card);
 #endif
 out:
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
 		return;
-	if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_setadp_promisc_mode(card);
 }
 
 static int
@@ -5689,7 +5625,7 @@
 	spin_unlock_irqrestore(&card->ip_lock, flags);
 }
 
-static inline void
+static void
 qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
 {
 	struct qeth_ipaddr *ipm;
@@ -5775,7 +5711,7 @@
 }
 
 #ifdef CONFIG_QETH_IPV6
-static inline void
+static void
 qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
 {
 	struct qeth_ipaddr *ipm;
@@ -6086,7 +6022,7 @@
 
 	return rc;
 }
-static inline void
+static void
 qeth_fill_netmask(u8 *netmask, unsigned int len)
 {
 	int i,j;
@@ -6351,6 +6287,42 @@
 };
 
 static int
+qeth_hard_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+	struct qeth_card *card;
+	struct ethhdr *eth;
+
+	card = qeth_get_card_from_dev(skb->dev);
+	if (card->options.layer2)
+		goto haveheader;
+#ifdef CONFIG_QETH_IPV6
+	/* cause of the manipulated arp constructor and the ARP
+	   flag for OSAE devices we have some nasty exceptions */
+	if (card->info.type == QETH_CARD_TYPE_OSAE) {
+		if (!card->options.fake_ll) {
+			if ((skb->pkt_type==PACKET_OUTGOING) &&
+			    (skb->protocol==ETH_P_IPV6))
+				goto haveheader;
+			else
+				return 0;
+		} else {
+			if ((skb->pkt_type==PACKET_OUTGOING) &&
+			    (skb->protocol==ETH_P_IP))
+				return 0;
+			else
+				goto haveheader;
+		}
+	}
+#endif
+	if (!card->options.fake_ll)
+		return 0;
+haveheader:
+	eth = eth_hdr(skb);
+	memcpy(haddr, eth->h_source, ETH_ALEN);
+	return ETH_ALEN;
+}
+
+static int
 qeth_netdev_init(struct net_device *dev)
 {
 	struct qeth_card *card;
@@ -6388,7 +6360,10 @@
 	if (card->options.fake_ll &&
 		(qeth_get_netdev_flags(card) & IFF_NOARP))
 			dev->hard_header = qeth_fake_header;
-	dev->hard_header_parse = NULL;
+	if (dev->type == ARPHRD_IEEE802_TR)
+		dev->hard_header_parse = NULL;
+	else
+		dev->hard_header_parse = qeth_hard_header_parse;
 	dev->set_mac_address = qeth_layer2_set_mac_address;
 	dev->flags |= qeth_get_netdev_flags(card);
 	if ((card->options.fake_broadcast) ||
@@ -6651,7 +6626,7 @@
 	return rc;
 }
 
-static inline int
+static int
 qeth_setadapter_hstr(struct qeth_card *card)
 {
 	int rc;
@@ -6914,7 +6889,7 @@
 	return rc;
 }
 
-static inline int
+static int
 qeth_start_ipa_arp_processing(struct qeth_card *card)
 {
 	int rc;
@@ -7554,7 +7529,7 @@
 	wake_up(&card->wait_q);
 }
 
-static inline int
+static int
 qeth_threads_running(struct qeth_card *card, unsigned long threads)
 {
 	unsigned long flags;
@@ -8143,7 +8118,7 @@
 	spin_unlock_irqrestore(&card->ip_lock, flags);
 }
 
-static inline void
+static void
 qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
 {
 	int i, j;
@@ -8235,8 +8210,7 @@
 	}
 	if (!qeth_add_ip(card, ipaddr))
 		kfree(ipaddr);
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 	return rc;
 }
 
@@ -8264,8 +8238,7 @@
 		return;
 	if (!qeth_delete_ip(card, ipaddr))
 		kfree(ipaddr);
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 }
 
 /*
@@ -8308,8 +8281,7 @@
 	}
 	if (!qeth_add_ip(card, ipaddr))
 		kfree(ipaddr);
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 	return 0;
 }
 
@@ -8337,8 +8309,7 @@
 		return;
 	if (!qeth_delete_ip(card, ipaddr))
 		kfree(ipaddr);
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 }
 
 /**
@@ -8380,8 +8351,7 @@
 	default:
 		break;
 	}
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 out:
 	return NOTIFY_DONE;
 }
@@ -8433,8 +8403,7 @@
 	default:
 		break;
 	}
- 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-		schedule_work(&card->kernel_thread_starter);
+	qeth_set_ip_addr_list(card);
 out:
 	return NOTIFY_DONE;
 }
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 5836737..d518419 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -328,7 +328,7 @@
 static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
 		qeth_dev_bufcnt_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
 		    char *buf)
 {
@@ -368,7 +368,7 @@
 	return qeth_dev_route_show(card, &card->options.route4, buf);
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
 		enum qeth_prot_versions prot, const char *buf, size_t count)
 {
@@ -998,7 +998,7 @@
 	.store	= _store,						     \
 };
 
-int
+static int
 qeth_check_layer2(struct qeth_card *card)
 {
 	if (card->options.layer2)
@@ -1100,7 +1100,7 @@
 			qeth_dev_ipato_invert4_show,
 			qeth_dev_ipato_invert4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
 			enum qeth_prot_versions proto)
 {
@@ -1146,7 +1146,7 @@
 	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
 }
 
-static inline int
+static int
 qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
 		  u8 *addr, int *mask_bits)
 {
@@ -1178,7 +1178,7 @@
 	return 0;
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_ipato_add_store(const char *buf, size_t count,
 			 struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1223,7 +1223,7 @@
 			qeth_dev_ipato_add4_show,
 			qeth_dev_ipato_add4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_ipato_del_store(const char *buf, size_t count,
 			 struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1361,7 +1361,7 @@
 	.attrs = (struct attribute **)qeth_ipato_device_attrs,
 };
 
-static inline ssize_t
+static ssize_t
 qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
 			enum qeth_prot_versions proto)
 {
@@ -1407,7 +1407,7 @@
 	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
 }
 
-static inline int
+static int
 qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
 		 u8 *addr)
 {
@@ -1418,7 +1418,7 @@
 	return 0;
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_vipa_add_store(const char *buf, size_t count,
 			 struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1451,7 +1451,7 @@
 			qeth_dev_vipa_add4_show,
 			qeth_dev_vipa_add4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_vipa_del_store(const char *buf, size_t count,
 			 struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1542,7 +1542,7 @@
 	.attrs = (struct attribute **)qeth_vipa_device_attrs,
 };
 
-static inline ssize_t
+static ssize_t
 qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
 		       enum qeth_prot_versions proto)
 {
@@ -1588,7 +1588,7 @@
 	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
 }
 
-static inline int
+static int
 qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
 		 u8 *addr)
 {
@@ -1599,7 +1599,7 @@
 	return 0;
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_rxip_add_store(const char *buf, size_t count,
 			struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1632,7 +1632,7 @@
 			qeth_dev_rxip_add4_show,
 			qeth_dev_rxip_add4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_rxip_del_store(const char *buf, size_t count,
 			struct qeth_card *card, enum qeth_prot_versions proto)
 {
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index e088b5e..806bb1a 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -13,22 +13,18 @@
 #include <linux/errno.h>
 #include <linux/workqueue.h>
 #include <linux/time.h>
+#include <linux/device.h>
 #include <linux/kthread.h>
-
+#include <asm/etr.h>
 #include <asm/lowcore.h>
-
+#include <asm/cio.h>
+#include "cio/cio.h"
+#include "cio/chsc.h"
+#include "cio/css.h"
 #include "s390mach.h"
 
 static struct semaphore m_sem;
 
-extern int css_process_crw(int, int);
-extern int chsc_process_crw(void);
-extern int chp_process_crw(int, int);
-extern void css_reiterate_subchannels(void);
-
-extern struct workqueue_struct *slow_path_wq;
-extern struct work_struct slow_path_work;
-
 static NORET_TYPE void
 s390_handle_damage(char *msg)
 {
@@ -470,6 +466,19 @@
 			s390_handle_damage("unable to revalidate registers.");
 	}
 
+	if (mci->cd) {
+		/* Timing facility damage */
+		s390_handle_damage("TOD clock damaged");
+	}
+
+	if (mci->ed && mci->ec) {
+		/* External damage */
+		if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC))
+			etr_sync_check();
+		if (S390_lowcore.external_damage_code & (1U << ED_ETR_SWITCH))
+			etr_switch_to_local();
+	}
+
 	if (mci->se)
 		/* Storage error uncorrected */
 		s390_handle_damage("received storage error uncorrected "
@@ -508,7 +517,7 @@
 machine_check_init(void)
 {
 	init_MUTEX_LOCKED(&m_sem);
-	ctl_clear_bit(14, 25);	/* disable external damage MCH */
+	ctl_set_bit(14, 25);	/* enable external damage MCH */
 	ctl_set_bit(14, 27);    /* enable system recovery MCH */
 #ifdef CONFIG_MACHCHK_WARNING
 	ctl_set_bit(14, 24);	/* enable warning MCH */
@@ -529,7 +538,11 @@
 static int __init
 machine_check_crw_init (void)
 {
-	kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
+	struct task_struct *task;
+
+	task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
+	if (IS_ERR(task))
+		return PTR_ERR(task);
 	ctl_set_bit(14, 28);	/* enable channel report MCH */
 	return 0;
 }
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index 7abb42a..d3ca428 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -102,4 +102,7 @@
 	return ccode;
 }
 
+#define ED_ETR_SYNC	12	/* External damage ETR sync check */
+#define ED_ETR_SWITCH	13	/* External damage ETR switch to local */
+
 #endif /* __s390mach */
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 85093b7..39a8852 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -47,13 +47,12 @@
 static void zfcp_ns_gid_pn_handler(unsigned long);
 
 /* miscellaneous */
-static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
-static inline void zfcp_sg_list_free(struct zfcp_sg_list *);
-static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
-					      void __user *, size_t);
-static inline int zfcp_sg_list_copy_to_user(void __user *,
-					    struct zfcp_sg_list *, size_t);
-
+static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
+static void zfcp_sg_list_free(struct zfcp_sg_list *);
+static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
+				       void __user *, size_t);
+static int zfcp_sg_list_copy_to_user(void __user *,
+				     struct zfcp_sg_list *, size_t);
 static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long);
 
 #define ZFCP_CFDC_IOC_MAGIC                     0xDD
@@ -605,7 +604,7 @@
  * elements of the scatter-gather list. The maximum size of a single element
  * in the scatter-gather list is PAGE_SIZE.
  */
-static inline int
+static int
 zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
 {
 	struct scatterlist *sg;
@@ -652,7 +651,7 @@
  * Memory for each element in the scatter-gather list is freed.
  * Finally sg_list->sg is freed itself and sg_list->count is reset.
  */
-static inline void
+static void
 zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
 {
 	struct scatterlist *sg;
@@ -697,7 +696,7 @@
  * @size: number of bytes to be copied
  * Return: 0 on success, -EFAULT if copy_from_user fails.
  */
-static inline int
+static int
 zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
 			    void __user *user_buffer,
                             size_t size)
@@ -735,7 +734,7 @@
  * @size: number of bytes to be copied
  * Return: 0 on success, -EFAULT if copy_to_user fails
  */
-static inline int
+static int
 zfcp_sg_list_copy_to_user(void __user  *user_buffer,
 			  struct zfcp_sg_list *sg_list,
                           size_t size)
@@ -1799,7 +1798,7 @@
  * @code: reason code
  * @rc_table: table of reason codes and descriptions
  */
-static inline const char *
+static const char *
 zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table)
 {
 	const char *descr = "unknown reason code";
@@ -1847,7 +1846,7 @@
  * @rjt_par: reject parameter acc. to FC-PH/FC-FS
  * @rc_table: table of reason codes and descriptions
  */
-static inline void
+static void
 zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,
 		   const struct zfcp_rc_entry *rc_table)
 {
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 0aa3b1a..d8191d1 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -31,7 +31,7 @@
 
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_OTHER
 
-static inline int
+static int
 zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
 {
 	unsigned long long sec;
@@ -106,7 +106,7 @@
 	return len;
 }
 
-static inline int
+static int
 zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
 		     debug_entry_t * entry, char *out_buf)
 {
@@ -130,7 +130,7 @@
 	return len;
 }
 
-inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_adapter *adapter = fsf_req->adapter;
 	struct fsf_qtcb *qtcb = fsf_req->qtcb;
@@ -241,7 +241,7 @@
 	spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-inline void
+void
 zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
 			     struct fsf_status_read_buffer *status_buffer)
 {
@@ -295,7 +295,7 @@
 	spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-inline void
+void
 zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
 			unsigned int qdio_error, unsigned int siga_error,
 			int sbal_index, int sbal_count)
@@ -316,7 +316,7 @@
 	spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-static inline int
+static int
 zfcp_hba_dbf_view_response(char *out_buf,
 			   struct zfcp_hba_dbf_record_response *rec)
 {
@@ -403,7 +403,7 @@
 	return len;
 }
 
-static inline int
+static int
 zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
 {
 	int len = 0;
@@ -424,7 +424,7 @@
 	return len;
 }
 
-static inline int
+static int
 zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
 {
 	int len = 0;
@@ -469,7 +469,7 @@
 	return len;
 }
 
-struct debug_view zfcp_hba_dbf_view = {
+static struct debug_view zfcp_hba_dbf_view = {
 	"structured",
 	NULL,
 	&zfcp_dbf_view_header,
@@ -478,7 +478,7 @@
 	NULL
 };
 
-inline void
+void
 _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
 			      u32 s_id, u32 d_id, void *buffer, int buflen)
 {
@@ -519,7 +519,7 @@
 	spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
-inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
 	struct zfcp_port *port = ct->port;
@@ -531,7 +531,7 @@
 				      ct->req->length);
 }
 
-inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
 	struct zfcp_port *port = ct->port;
@@ -543,7 +543,7 @@
 				      ct->resp->length);
 }
 
-static inline void
+static void
 _zfcp_san_dbf_event_common_els(const char *tag, int level,
 			       struct zfcp_fsf_req *fsf_req, u32 s_id,
 			       u32 d_id, u8 ls_code, void *buffer, int buflen)
@@ -585,7 +585,7 @@
 	spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
-inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
@@ -597,7 +597,7 @@
 				       els->req->length);
 }
 
-inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
@@ -608,7 +608,7 @@
 				       els->resp->length);
 }
 
-inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_adapter *adapter = fsf_req->adapter;
 	struct fsf_status_read_buffer *status_buffer =
@@ -693,7 +693,7 @@
 	return len;
 }
 
-struct debug_view zfcp_san_dbf_view = {
+static struct debug_view zfcp_san_dbf_view = {
 	"structured",
 	NULL,
 	&zfcp_dbf_view_header,
@@ -702,7 +702,7 @@
 	NULL
 };
 
-static inline void
+static void
 _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
 			    struct zfcp_adapter *adapter,
 			    struct scsi_cmnd *scsi_cmnd,
@@ -786,7 +786,7 @@
 	spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
 }
 
-inline void
+void
 zfcp_scsi_dbf_event_result(const char *tag, int level,
 			   struct zfcp_adapter *adapter,
 			   struct scsi_cmnd *scsi_cmnd,
@@ -796,7 +796,7 @@
 			adapter, scsi_cmnd, fsf_req, 0);
 }
 
-inline void
+void
 zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
 			  struct scsi_cmnd *scsi_cmnd,
 			  struct zfcp_fsf_req *new_fsf_req,
@@ -806,7 +806,7 @@
 			adapter, scsi_cmnd, new_fsf_req, old_req_id);
 }
 
-inline void
+void
 zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
 			     struct scsi_cmnd *scsi_cmnd)
 {
@@ -884,7 +884,7 @@
 	return len;
 }
 
-struct debug_view zfcp_scsi_dbf_view = {
+static struct debug_view zfcp_scsi_dbf_view = {
 	"structured",
 	NULL,
 	&zfcp_dbf_view_header,
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index c88babc..88642de 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -200,7 +200,7 @@
  * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
-int
+static int
 zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
 {
 	int retval;
@@ -295,7 +295,7 @@
  * zfcp_erp_adisc - send ADISC ELS command
  * @port: port structure
  */
-int
+static int
 zfcp_erp_adisc(struct zfcp_port *port)
 {
 	struct zfcp_adapter *adapter = port->adapter;
@@ -380,7 +380,7 @@
  *
  * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered.
  */
-void
+static void
 zfcp_erp_adisc_handler(unsigned long data)
 {
 	struct zfcp_send_els *send_els;
@@ -3141,7 +3141,6 @@
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
 		if (result != ZFCP_ERP_SUCCEEDED) {
-			struct zfcp_port *port;
 			list_for_each_entry(port, &adapter->port_list_head, list)
 				if (port->rport &&
 				    !atomic_test_mask(ZFCP_STATUS_PORT_WKA,
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index b8794d7..cda0cc0 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -119,8 +119,8 @@
 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
 extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t);
 extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *);
-extern void set_host_byte(u32 *, char);
-extern void set_driver_byte(u32 *, char);
+extern void set_host_byte(int *, char);
+extern void set_driver_byte(int *, char);
 extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
 extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 067f151..4b3ae3f 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4563,7 +4563,7 @@
 /*
  * set qtcb pointer in fsf_req and initialize QTCB
  */
-static inline void
+static void
 zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req)
 {
 	if (likely(fsf_req->qtcb != NULL)) {
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index dbd9f48..1e12a78 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -21,22 +21,22 @@
 
 #include "zfcp_ext.h"
 
-static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
+static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
 static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get
 	(struct zfcp_qdio_queue *, int, int);
 static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp
 	(struct zfcp_fsf_req *, int, int);
-static inline volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain
+static volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain
 	(struct zfcp_fsf_req *, unsigned long);
-static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_next
+static volatile struct qdio_buffer_element *zfcp_qdio_sbale_next
 	(struct zfcp_fsf_req *, unsigned long);
-static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int);
+static int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int);
 static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *);
-static inline void zfcp_qdio_sbale_fill
+static void zfcp_qdio_sbale_fill
 	(struct zfcp_fsf_req *, unsigned long, void *, int);
-static inline int zfcp_qdio_sbals_from_segment
+static int zfcp_qdio_sbals_from_segment
 	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long);
-static inline int zfcp_qdio_sbals_from_buffer
+static int zfcp_qdio_sbals_from_buffer
 	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int);
 
 static qdio_handler_t zfcp_qdio_request_handler;
@@ -201,7 +201,7 @@
  * returns:	error flag
  *
  */
-static inline int
+static int
 zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
 			      unsigned int qdio_error, unsigned int siga_error,
 			      int first_element, int elements_processed)
@@ -462,7 +462,7 @@
  * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for
  *	a struct zfcp_fsf_req
  */
-inline volatile struct qdio_buffer_element *
+volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
 {
 	return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue,
@@ -484,7 +484,7 @@
  * zfcp_qdio_sbale_curr - return current SBALE on request_queue for
  *	a struct zfcp_fsf_req
  */
-inline volatile struct qdio_buffer_element *
+volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req)
 {
 	return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr,
@@ -499,7 +499,7 @@
  *
  * Note: We can assume at least one free SBAL in the request_queue when called.
  */
-static inline void
+static void
 zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
 {
 	int count = atomic_read(&fsf_req->adapter->request_queue.free_count);
@@ -517,7 +517,7 @@
  *
  * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req.
  */
-static inline volatile struct qdio_buffer_element *
+static volatile struct qdio_buffer_element *
 zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
 	volatile struct qdio_buffer_element *sbale;
@@ -554,7 +554,7 @@
 /**
  * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed
  */
-static inline volatile struct qdio_buffer_element *
+static volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
 	if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
@@ -569,7 +569,7 @@
  * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue
  *	with zero from
  */
-static inline int
+static int
 zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last)
 {
 	struct qdio_buffer **buf = queue->buffer;
@@ -603,7 +603,7 @@
  * zfcp_qdio_sbale_fill - set address and lenght in current SBALE
  *	on request_queue
  */
-static inline void
+static void
 zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
 		     void *addr, int length)
 {
@@ -624,7 +624,7 @@
  * Alignment and length of the segment determine how many SBALEs are needed
  * for the memory segment.
  */
-static inline int
+static int
 zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
 			     void *start_addr, unsigned long total_length)
 {
@@ -659,7 +659,7 @@
  * @sg_count: number of elements in scatter-gather list
  * @max_sbals: upper bound for number of SBALs to be used
  */
-inline int
+int
 zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                         struct scatterlist *sg,	int sg_count, int max_sbals)
 {
@@ -707,7 +707,7 @@
  * @length: length of buffer
  * @max_sbals: upper bound for number of SBALs to be used
  */
-static inline int
+static int
 zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
 			    void *buffer, unsigned long length, int max_sbals)
 {
@@ -728,7 +728,7 @@
  * @scsi_cmnd: either scatter-gather list or buffer contained herein is used
  *	to fill SBALs
  */
-inline int
+int
 zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req,
 			      unsigned long sbtype, struct scsi_cmnd *scsi_cmnd)
 {
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 452d96f..99db020 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -90,7 +90,7 @@
 	return fcp_sns_info_ptr;
 }
 
-fcp_dl_t *
+static fcp_dl_t *
 zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd)
 {
 	int additional_length = fcp_cmd->add_fcp_cdb_length << 2;
@@ -124,19 +124,19 @@
  * regarding the specified byte
  */
 static inline void
-set_byte(u32 * result, char status, char pos)
+set_byte(int *result, char status, char pos)
 {
 	*result |= status << (pos * 8);
 }
 
 void
-set_host_byte(u32 * result, char status)
+set_host_byte(int *result, char status)
 {
 	set_byte(result, status, 2);
 }
 
 void
-set_driver_byte(u32 * result, char status)
+set_driver_byte(int *result, char status)
 {
 	set_byte(result, status, 3);
 }
@@ -280,7 +280,7 @@
 	return retval;
 }
 
-void
+static void
 zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt)
 {
 	struct completion *wait = (struct completion *) scpnt->SCp.ptr;
@@ -324,7 +324,7 @@
  * returns:	0 - success, SCSI command enqueued
  *		!0 - failure
  */
-int
+static int
 zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 		       void (*done) (struct scsi_cmnd *))
 {
@@ -380,7 +380,7 @@
  * will handle late commands.  (Usually, the normal completion of late
  * commands is ignored with respect to the running abort operation.)
  */
-int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 {
  	struct Scsi_Host *scsi_host;
  	struct zfcp_adapter *adapter;
@@ -445,7 +445,7 @@
 	return retval;
 }
 
-int
+static int
 zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
 	int retval;
@@ -541,7 +541,7 @@
 /**
  * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset
  */
-int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
+static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
 	struct zfcp_unit *unit;
 	struct zfcp_adapter *adapter;
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 1e788e8..090743d 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -9,8 +9,14 @@
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <asm/ebcdic.h>
 
+/* Sigh, math-emu. Don't ask. */
+#include <asm/sfp-util.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
 struct sysinfo_1_1_1 {
 	char reserved_0[32];
 	char manufacturer[16];
@@ -198,7 +204,7 @@
 		 * if the higher order 8 bits are not zero. Printing
 		 * a floating point number in the kernel is a no-no,
 		 * always print the number as 32 bit unsigned integer.
-		 * The user-space needs to know about the stange
+		 * The user-space needs to know about the strange
 		 * encoding of the alternate cpu capability.
 		 */
 		len += sprintf(page + len, "Capability:           %u %u\n",
@@ -351,3 +357,58 @@
 
 __initcall(create_proc_sysinfo);
 
+/*
+ * CPU capability might have changed. Therefore recalculate loops_per_jiffy.
+ */
+void s390_adjust_jiffies(void)
+{
+	struct sysinfo_1_2_2 *info;
+	const unsigned int fmil = 0x4b189680;	/* 1e7 as 32-bit float. */
+	FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+	FP_DECL_EX;
+	unsigned int capability;
+
+	info = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!info)
+		return;
+
+	if (stsi(info, 1, 2, 2) != -ENOSYS) {
+		/*
+		 * Major sigh. The cpu capability encoding is "special".
+		 * If the first 9 bits of info->capability are 0 then it
+		 * is a 32 bit unsigned integer in the range 0 .. 2^23.
+		 * If the first 9 bits are != 0 then it is a 32 bit float.
+		 * In addition a lower value indicates a proportionally
+		 * higher cpu capacity. Bogomips are the other way round.
+		 * To get to a halfway suitable number we divide 1e7
+		 * by the cpu capability number. Yes, that means a floating
+		 * point division .. math-emu here we come :-)
+		 */
+		FP_UNPACK_SP(SA, &fmil);
+		if ((info->capability >> 23) == 0)
+			FP_FROM_INT_S(SB, info->capability, 32, int);
+		else
+			FP_UNPACK_SP(SB, &info->capability);
+		FP_DIV_S(SR, SA, SB);
+		FP_TO_INT_S(capability, SR, 32, 0);
+	} else
+		/*
+		 * Really old machine without stsi block for basic
+		 * cpu information. Report 42.0 bogomips.
+		 */
+		capability = 42;
+	loops_per_jiffy = capability * (500000/HZ);
+	free_page((unsigned long) info);
+}
+
+/*
+ * calibrate the delay loop
+ */
+void __init calibrate_delay(void)
+{
+	s390_adjust_jiffies();
+	/* Print the good old Bogomips line .. */
+	printk(KERN_DEBUG "Calibrating delay loop (skipped)... "
+	       "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ),
+	       (loops_per_jiffy/(5000/HZ)) % 100);
+}
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 99a259c..e1b44d6 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -6,7 +6,7 @@
    		     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                      Brad Strand <linux@3ware.com>
 
-   Copyright (C) 1999-2005 3ware Inc.
+   Copyright (C) 1999-2007 3ware Inc.
 
    Kernel compatiblity By: 	Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000	Andre Hedrick <andre@suse.com>
@@ -191,6 +191,9 @@
                  before shutting down card.
                  Change to new 'change_queue_depth' api.
                  Fix 'handled=1' ISR usage, remove bogus IRQ check.
+   1.26.02.002 - Free irq handler in __tw_shutdown().
+                 Turn on RCD bit for caching mode page.
+                 Serialize reset code.
 */
 
 #include <linux/module.h>
@@ -214,7 +217,7 @@
 #include "3w-xxxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "1.26.02.001"
+#define TW_DRIVER_VERSION "1.26.02.002"
 static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 static int tw_device_extension_count = 0;
 static int twe_major = -1;
@@ -226,7 +229,7 @@
 MODULE_VERSION(TW_DRIVER_VERSION);
 
 /* Function prototypes */
-static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
+static int tw_reset_device_extension(TW_Device_Extension *tw_dev);
 
 /* Functions */
 
@@ -984,24 +987,12 @@
 			/* Now wait for the command to complete */
 			timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
 
-			/* See if we reset while waiting for the ioctl to complete */
-			if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
-				clear_bit(TW_IN_RESET, &tw_dev->flags);
-				retval = -ERESTARTSYS;
-				goto out2;
-			}
-
 			/* We timed out, and didn't get an interrupt */
 			if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
 				/* Now we need to reset the board */
 				printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
 				retval = -EIO;
-				spin_lock_irqsave(tw_dev->host->host_lock, flags);
-				tw_dev->state[request_id] = TW_S_COMPLETED;
-				tw_state_request_finish(tw_dev, request_id);
-				tw_dev->posted_request_count--;
-				spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
-				if (tw_reset_device_extension(tw_dev, 1)) {
+				if (tw_reset_device_extension(tw_dev)) {
 					printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
 				}
 				goto out2;
@@ -1336,7 +1327,7 @@
 } /* End tw_unmap_scsi_data() */
 
 /* This function will reset a device extension */
-static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) 
+static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
 {
 	int i = 0;
 	struct scsi_cmnd *srb;
@@ -1382,15 +1373,10 @@
 		printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
 		return 1;
 	}
-	TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
 
-	/* Wake up any ioctl that was pending before the reset */
-	if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
-		clear_bit(TW_IN_RESET, &tw_dev->flags);
-	} else {
-		tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
-		wake_up(&tw_dev->ioctl_wqueue);
-	}
+	TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+	clear_bit(TW_IN_RESET, &tw_dev->flags);
+	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
 
 	return 0;
 } /* End tw_reset_device_extension() */
@@ -1437,14 +1423,18 @@
 		"WARNING: Command (0x%x) timed out, resetting card.\n",
 		SCpnt->cmnd[0]);
 
+	/* Make sure we are not issuing an ioctl or resetting from ioctl */
+	mutex_lock(&tw_dev->ioctl_lock);
+
 	/* Now reset the card and some of the device extension data */
-	if (tw_reset_device_extension(tw_dev, 0)) {
+	if (tw_reset_device_extension(tw_dev)) {
 		printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
 		goto out;
 	}
 
 	retval = SUCCESS;
 out:
+	mutex_unlock(&tw_dev->ioctl_lock);
 	return retval;
 } /* End tw_scsi_eh_reset() */
 
@@ -1660,9 +1650,9 @@
 	request_buffer[4] = 0x8;        /* caching page */
 	request_buffer[5] = 0xa;        /* page length */
 	if (*flags & 0x1)
-		request_buffer[6] = 0x4;        /* WCE on */
+		request_buffer[6] = 0x5;        /* WCE on, RCD on */
 	else
-		request_buffer[6] = 0x0;        /* WCE off */
+		request_buffer[6] = 0x1;        /* WCE off, RCD on */
 	tw_transfer_internal(tw_dev, request_id, request_buffer,
 			     sizeof(request_buffer));
 
@@ -2012,6 +2002,10 @@
 	int retval = 1;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
 
+	/* If we are resetting due to timed out ioctl, report as busy */
+	if (test_bit(TW_IN_RESET, &tw_dev->flags))
+		return SCSI_MLQUEUE_HOST_BUSY;
+
 	/* Save done function into Scsi_Cmnd struct */
 	SCpnt->scsi_done = done;
 		 
@@ -2100,6 +2094,10 @@
 
 	handled = 1;
 
+	/* If we are resetting, bail */
+	if (test_bit(TW_IN_RESET, &tw_dev->flags))
+		goto tw_interrupt_bail;
+
 	/* Check controller for errors */
 	if (tw_check_bits(status_reg_value)) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
@@ -2276,6 +2274,9 @@
 	/* Disable interrupts */
 	TW_DISABLE_INTERRUPTS(tw_dev);
 
+	/* Free up the IRQ */
+	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
 	printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no);
 
 	/* Tell the card we are shutting down */
@@ -2444,9 +2445,6 @@
 		twe_major = -1;
 	}
 
-	/* Free up the IRQ */
-	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
-
 	/* Shutdown the card */
 	__tw_shutdown(tw_dev);
 
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index bbd654a..0742e68 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -6,7 +6,7 @@
    		     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                      Brad Strand <linux@3ware.com>
 
-   Copyright (C) 1999-2005 3ware Inc.
+   Copyright (C) 1999-2007 3ware Inc.
 
    Kernel compatiblity By:	Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000	Andre Hedrick <andre@suse.com>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 60f5827..7869c34 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1303,7 +1303,7 @@
 
 config SCSI_SEAGATE
 	tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support"
-	depends on X86 && ISA && SCSI && BROKEN
+	depends on X86 && ISA && SCSI
 	---help---
 	  These are 8-bit SCSI controllers; the ST-01 is also supported by
 	  this driver.  It is explained in section 3.9 of the SCSI-HOWTO,
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 359e7dd..d2cf875 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -117,8 +117,8 @@
 	{ 0x9005, 0x0286, 0x9005, 0x029b, 0, 0, 22 }, /* AAR-2820SA (Intruder) */
 	{ 0x9005, 0x0286, 0x9005, 0x029c, 0, 0, 23 }, /* AAR-2620SA (Intruder) */
 	{ 0x9005, 0x0286, 0x9005, 0x029d, 0, 0, 24 }, /* AAR-2420SA (Intruder) */
-	{ 0x9005, 0x0286, 0x9005, 0x029e, 0, 0, 25 }, /* ICP9024R0 (Lancer) */
-	{ 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */
+	{ 0x9005, 0x0286, 0x9005, 0x029e, 0, 0, 25 }, /* ICP9024RO (Lancer) */
+	{ 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014RO (Lancer) */
 	{ 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */
 	{ 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */
 	{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */
@@ -137,15 +137,15 @@
 	{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
 	{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */
 	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */
-	{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005 */
 	{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */
 	{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */
 	{ 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */
 	{ 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */
-	{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
+	{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000 (BlackBird) */
 	{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
 	{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
-	{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800SAS (Hurricane44) */
+	{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800 (Hurricane44) */
 
 	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
 	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
@@ -193,8 +193,8 @@
 	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "AAR-2820SA      ", 1 }, /* AAR-2820SA (Intruder) */
 	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "AAR-2620SA      ", 1 }, /* AAR-2620SA (Intruder) */
 	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "AAR-2420SA      ", 1 }, /* AAR-2420SA (Intruder) */
-	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9024R0       ", 2 }, /* ICP9024R0 (Lancer) */
-	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9014R0       ", 1 }, /* ICP9014R0 (Lancer) */
+	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9024RO       ", 2 }, /* ICP9024RO (Lancer) */
+	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9014RO       ", 1 }, /* ICP9014RO (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9047MA       ", 1 }, /* ICP9047MA (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9087MA       ", 1 }, /* ICP9087MA (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP5445AU       ", 1 }, /* ICP5445AU (Hurricane44) */
@@ -212,14 +212,14 @@
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2026ZCR     ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2610SA      ", 1 }, /* SATA 6Ch (Bearcat) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2240S       ", 1 }, /* ASR-2240S (SabreExpress) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4005SAS     ", 1 }, /* ASR-4005SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4005        ", 1 }, /* ASR-4005 */
 	{ aac_rx_init, "ServeRAID","IBM     ", "ServeRAID 8i    ", 1 }, /* IBM 8i (AvonPark) */
 	{ aac_rkt_init, "ServeRAID","IBM     ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */
 	{ aac_rkt_init, "ServeRAID","IBM     ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000SAS     ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000        ", 1 }, /* ASR-4000 (BlackBird & AvonPark) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4800SAS     ", 1 }, /* ASR-4800SAS (Marauder-X) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4805SAS     ", 1 }, /* ASR-4805SAS (Marauder-E) */
-	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-3800SAS     ", 1 }, /* ASR-3800SAS (Hurricane44) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-3800        ", 1 }, /* ASR-3800 (Hurricane44) */
 
 	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 2b34435..306bec3 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -18215,6 +18215,7 @@
 }
 MODULE_LICENSE("Dual BSD/GPL");
 
+#ifdef CONFIG_PCI
 /* PCI Devices supported by this driver */
 static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
@@ -18232,4 +18233,4 @@
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
-
+#endif /* CONFIG_PCI */
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index d0b139c..4376840 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -749,7 +749,7 @@
 				if (!offset)
 					crypto_hash_update(
 							&tcp_conn->rx_hash,
-							&sg[i], 1);
+							&sg[i], sg[i].length);
 				else
 					partial_sg_digest_update(
 							&tcp_conn->rx_hash,
@@ -1777,13 +1777,13 @@
 	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
 						  CRYPTO_ALG_ASYNC);
 	tcp_conn->tx_hash.flags = 0;
-	if (!tcp_conn->tx_hash.tfm)
+	if (IS_ERR(tcp_conn->tx_hash.tfm))
 		goto free_tcp_conn;
 
 	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
 						  CRYPTO_ALG_ASYNC);
 	tcp_conn->rx_hash.flags = 0;
-	if (!tcp_conn->rx_hash.tfm)
+	if (IS_ERR(tcp_conn->rx_hash.tfm))
 		goto free_tx_tfm;
 
 	return cls_conn;
@@ -2044,13 +2044,11 @@
 		sk = tcp_conn->sock->sk;
 		if (sk->sk_family == PF_INET) {
 			inet = inet_sk(sk);
-			len = sprintf(buf, "%u.%u.%u.%u\n",
+			len = sprintf(buf, NIPQUAD_FMT "\n",
 				      NIPQUAD(inet->daddr));
 		} else {
 			np = inet6_sk(sk);
-			len = sprintf(buf,
-				"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-				NIP6(np->daddr));
+			len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
 		}
 		mutex_unlock(&conn->xmitmutex);
 		break;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index e11b23c..d37048c 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -260,7 +260,7 @@
 	}
 
 	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) {
-		int senselen;
+		uint16_t senselen;
 
 		if (datalen < 2) {
 invalid_datalen:
@@ -270,12 +270,12 @@
 			goto out;
 		}
 
-		senselen = (data[0] << 8) | data[1];
+		senselen = be16_to_cpu(*(uint16_t *)data);
 		if (datalen < senselen)
 			goto invalid_datalen;
 
 		memcpy(sc->sense_buffer, data + 2,
-		       min(senselen, SCSI_SENSE_BUFFERSIZE));
+		       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
 		debug_scsi("copied %d bytes of sense\n",
 			   min(senselen, SCSI_SENSE_BUFFERSIZE));
 	}
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 066292d..ec3bbbd 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -56,6 +56,9 @@
 
 	pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) *
 					 LPFC_MBUF_POOL_SIZE, GFP_KERNEL);
+	if (!pool->elements)
+		goto fail_free_lpfc_mbuf_pool;
+
 	pool->max_count = 0;
 	pool->current_count = 0;
 	for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) {
@@ -82,10 +85,11 @@
  fail_free_mbox_pool:
 	mempool_destroy(phba->mbox_mem_pool);
  fail_free_mbuf_pool:
-	while (--i)
+	while (i--)
 		pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
 						 pool->elements[i].phys);
 	kfree(pool->elements);
+ fail_free_lpfc_mbuf_pool:
 	pci_pool_destroy(phba->lpfc_mbuf_pool);
  fail_free_dma_buf_pool:
 	pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 046223b..b5bdd0d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -13,8 +13,8 @@
  * Version	: v00.00.03.05
  *
  * Authors:
- * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
- * 	Sumant Patro		<Sumant.Patro@lsil.com>
+ * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsi.com>
+ * 	Sumant Patro		<Sumant.Patro@lsi.com>
  *
  * List of supported controllers
  *
@@ -45,7 +45,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGASAS_VERSION);
-MODULE_AUTHOR("sreenivas.bagalkote@lsil.com");
+MODULE_AUTHOR("megaraidlinux@lsi.com");
 MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver");
 
 /*
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index d72df5d..e16fe36 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1629,7 +1629,6 @@
 	/* General socket configuration */
 	link->conf.Attributes	 = CONF_ENABLE_IRQ;
 	link->conf.IntType	 = INT_MEMORY_AND_IO;
-	link->conf.Present	 = PRESENT_OPTION;
 
 	ret = nsp_cs_config(link);
 
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index fb7acea..5b458d2 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -545,8 +545,6 @@
 	*/
 	if (shost->irq)
 		free_irq(shost->irq, shost);
-	if (shost->dma_channel != 0xff)
-		free_dma(shost->dma_channel);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 
@@ -895,7 +893,6 @@
 	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->conf.Present = PRESENT_OPTION;
 
 	return SYM53C500_config(link);
 } /* SYM53C500_attach */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 16af5b7..1548d42 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1341,7 +1341,7 @@
 	int host_status = DID_ERROR;
 	uint16_t comp_status = le16_to_cpu(sts->comp_status);
 	uint16_t state_flags = le16_to_cpu(sts->state_flags);
-	uint16_t residual_length = le32_to_cpu(sts->residual_length);
+	uint32_t residual_length = le32_to_cpu(sts->residual_length);
 	uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
 #if DEBUG_QLA1280_INTR
 	static char *reason[] = {
@@ -1413,8 +1413,10 @@
 			       "scsi: Underflow detected - retrying "
 			       "command.\n");
 			host_status = DID_ERROR;
-		} else
+		} else {
+			cp->resid = residual_length;
 			host_status = DID_OK;
+		}
 		break;
 
 	default:
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index c4fc40f..2c10130 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1602,6 +1602,7 @@
 
 #define CT_REJECT_RESPONSE	0x8001
 #define CT_ACCEPT_RESPONSE	0x8002
+#define CT_REASON_INVALID_COMMAND_CODE	0x01
 #define CT_REASON_CANNOT_PERFORM	0x09
 #define CT_EXPL_ALREADY_REGISTERED	0x10
 
@@ -2079,6 +2080,7 @@
 		uint32_t	msi_enabled		:1;
 		uint32_t	msix_enabled		:1;
 		uint32_t	disable_serdes		:1;
+		uint32_t	gpsc_supported		:1;
 	} flags;
 
 	atomic_t	loop_state;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 32ebeec..e4dd12f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -45,7 +45,6 @@
 extern int qla2x00_abort_isp(scsi_qla_host_t *);
 
 extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
-extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
 
 extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
 extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 97fbc62..ec5b2dd 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -127,8 +127,8 @@
 		    ha->host_no, routine, ms_pkt->entry_status));
 	} else {
 		if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
-			comp_status =
-			    ((struct ct_entry_24xx *)ms_pkt)->comp_status;
+			comp_status = le16_to_cpu(
+			    ((struct ct_entry_24xx *)ms_pkt)->comp_status);
 		else
 			comp_status = le16_to_cpu(ms_pkt->status);
 		switch (comp_status) {
@@ -143,6 +143,7 @@
 				DEBUG2_3(qla2x00_dump_buffer(
 				    (uint8_t *)&ct_rsp->header,
 				    sizeof(struct ct_rsp_hdr)));
+				rval = QLA_INVALID_COMMAND;
 			} else
 				rval = QLA_SUCCESS;
 			break;
@@ -1683,7 +1684,7 @@
 		memset(list[i].fabric_port_name, 0, WWN_SIZE);
 
 		/* Prepare common MS IOCB */
-		ms_pkt = qla2x00_prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
+		ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
 		    GFPN_ID_RSP_SIZE);
 
 		/* Prepare CT request */
@@ -1784,6 +1785,8 @@
 
 	if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
 		return QLA_FUNCTION_FAILED;
+	if (!ha->flags.gpsc_supported)
+		return QLA_FUNCTION_FAILED;
 
 	rval = qla2x00_mgmt_svr_login(ha);
 	if (rval)
@@ -1813,8 +1816,19 @@
 			/*EMPTY*/
 			DEBUG2_3(printk("scsi(%ld): GPSC issue IOCB "
 			    "failed (%d).\n", ha->host_no, rval));
-		} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
-		    "GPSC") != QLA_SUCCESS) {
+		} else if ((rval = qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
+		    "GPSC")) != QLA_SUCCESS) {
+			/* FM command unsupported? */
+			if (rval == QLA_INVALID_COMMAND &&
+			    ct_rsp->header.reason_code ==
+			    CT_REASON_INVALID_COMMAND_CODE) {
+				DEBUG2(printk("scsi(%ld): GPSC command "
+				    "unsupported, disabling query...\n",
+				    ha->host_no));
+				ha->flags.gpsc_supported = 0;
+				rval = QLA_FUNCTION_FAILED;
+				break;
+			}
 			rval = QLA_FUNCTION_FAILED;
 		} else {
 			/* Save portname */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a823f0b..b3dac26 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2103,40 +2103,7 @@
 	}
 }
 
-/*
- * qla2x00_update_fcport
- *	Updates device on list.
- *
- * Input:
- *	ha = adapter block pointer.
- *	fcport = port structure pointer.
- *
- * Return:
- *	0  - Success
- *  BIT_0 - error
- *
- * Context:
- *	Kernel context.
- */
-void
-qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
-{
-	fcport->ha = ha;
-	fcport->login_retry = 0;
-	fcport->port_login_retry_count = ha->port_down_retry_count *
-	    PORT_RETRY_TIME;
-	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
-	    PORT_RETRY_TIME);
-	fcport->flags &= ~FCF_LOGIN_NEEDED;
-
-	qla2x00_iidma_fcport(ha, fcport);
-
-	atomic_set(&fcport->state, FCS_ONLINE);
-
-	qla2x00_reg_remote_port(ha, fcport);
-}
-
-void
+static void
 qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
 {
 	struct fc_rport_identifiers rport_ids;
@@ -2179,6 +2146,39 @@
 }
 
 /*
+ * qla2x00_update_fcport
+ *	Updates device on list.
+ *
+ * Input:
+ *	ha = adapter block pointer.
+ *	fcport = port structure pointer.
+ *
+ * Return:
+ *	0  - Success
+ *  BIT_0 - error
+ *
+ * Context:
+ *	Kernel context.
+ */
+void
+qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+{
+	fcport->ha = ha;
+	fcport->login_retry = 0;
+	fcport->port_login_retry_count = ha->port_down_retry_count *
+	    PORT_RETRY_TIME;
+	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
+	    PORT_RETRY_TIME);
+	fcport->flags &= ~FCF_LOGIN_NEEDED;
+
+	qla2x00_iidma_fcport(ha, fcport);
+
+	atomic_set(&fcport->state, FCS_ONLINE);
+
+	qla2x00_reg_remote_port(ha, fcport);
+}
+
+/*
  * qla2x00_configure_fabric
  *      Setup SNS devices with loop ID's.
  *
@@ -3476,9 +3476,11 @@
 
 	/* Set host adapter parameters. */
 	ha->flags.disable_risc_code_load = 0;
-	ha->flags.enable_lip_reset = 1;
-	ha->flags.enable_lip_full_login = 1;
-	ha->flags.enable_target_reset = 1;
+	ha->flags.enable_lip_reset = 0;
+	ha->flags.enable_lip_full_login =
+	    le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
+	ha->flags.enable_target_reset =
+	    le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
 	ha->flags.enable_led_scheme = 0;
 	ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
 
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d3b6df4..39fd17b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -134,11 +134,11 @@
 		if (stat & HSR_RISC_PAUSED) {
 			hccr = RD_REG_WORD(&reg->hccr);
 			if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
-				qla_printk(KERN_INFO, ha,
-				    "Parity error -- HCCR=%x.\n", hccr);
+				qla_printk(KERN_INFO, ha, "Parity error -- "
+				    "HCCR=%x, Dumping firmware!\n", hccr);
 			else
-				qla_printk(KERN_INFO, ha,
-				    "RISC paused -- HCCR=%x.\n", hccr);
+				qla_printk(KERN_INFO, ha, "RISC paused -- "
+				    "HCCR=%x, Dumping firmware!\n", hccr);
 
 			/*
 			 * Issue a "HARD" reset in order for the RISC
@@ -147,6 +147,8 @@
 			 */
 			WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
 			RD_REG_WORD(&reg->hccr);
+
+			ha->isp_ops.fw_dump(ha, 1);
 			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
 			break;
 		} else if ((stat & HSR_RISC_INT) == 0)
@@ -475,6 +477,8 @@
 			set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
 		}
 		set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+
+		ha->flags.gpsc_supported = 1;
 		break;
 
 	case MBA_CHG_IN_CONNECTION:	/* Change in connection mode */
@@ -1440,8 +1444,7 @@
 
 			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
 			    "Dumping firmware!\n", hccr);
-			qla24xx_fw_dump(ha, 1);
-
+			ha->isp_ops.fw_dump(ha, 1);
 			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
 			break;
 		} else if ((stat & HSRX_RISC_INT) == 0)
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 4cde76c..077e578 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1339,9 +1339,9 @@
 
 	if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
 		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
-		mcp->mb[1] = BIT_0;
-		mcp->mb[2] = 0xff;
-		mcp->mb[3] = 0;
+		mcp->mb[1] = BIT_6;
+		mcp->mb[2] = 0;
+		mcp->mb[3] = ha->loop_reset_delay;
 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
 	} else {
 		mcp->mb[0] = MBC_LIP_RESET;
@@ -1823,8 +1823,8 @@
 	    ha->host_no));
 
 	mcp->mb[0] = MBC_LIP_FULL_LOGIN;
-	mcp->mb[1] = 0;
-	mcp->mb[2] = 0xff;
+	mcp->mb[1] = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? BIT_3: 0;
+	mcp->mb[2] = 0;
 	mcp->mb[3] = 0;
 	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
 	mcp->in_mb = MBX_0;
@@ -2486,7 +2486,7 @@
 		mcp->mb[4] = LSW(MSD(eft_dma));
 		mcp->mb[5] = MSW(MSD(eft_dma));
 		mcp->mb[6] = buffers;
-		mcp->mb[7] = buffers;
+		mcp->mb[7] = 0;
 		mcp->out_mb |= MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2;
 	}
 	mcp->tov = 30;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d03523d..d6445ae 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1037,48 +1037,49 @@
 static int
 qla2x00_loop_reset(scsi_qla_host_t *ha)
 {
-	int status = QLA_SUCCESS;
+	int ret;
 	struct fc_port *fcport;
 
-	if (ha->flags.enable_lip_reset) {
-		status = qla2x00_lip_reset(ha);
+	if (ha->flags.enable_lip_full_login) {
+		ret = qla2x00_full_login_lip(ha);
+		if (ret != QLA_SUCCESS) {
+			DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+			    "full_login_lip=%d.\n", __func__, ha->host_no,
+			    ret));
+		}
+		atomic_set(&ha->loop_state, LOOP_DOWN);
+		atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+		qla2x00_mark_all_devices_lost(ha, 0);
+		qla2x00_wait_for_loop_ready(ha);
 	}
 
-	if (status == QLA_SUCCESS && ha->flags.enable_target_reset) {
+	if (ha->flags.enable_lip_reset) {
+		ret = qla2x00_lip_reset(ha);
+		if (ret != QLA_SUCCESS) {
+			DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+			    "lip_reset=%d.\n", __func__, ha->host_no, ret));
+		}
+		qla2x00_wait_for_loop_ready(ha);
+	}
+
+	if (ha->flags.enable_target_reset) {
 		list_for_each_entry(fcport, &ha->fcports, list) {
 			if (fcport->port_type != FCT_TARGET)
 				continue;
 
-			status = qla2x00_device_reset(ha, fcport);
-			if (status != QLA_SUCCESS)
-				break;
+			ret = qla2x00_device_reset(ha, fcport);
+			if (ret != QLA_SUCCESS) {
+				DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+				    "target_reset=%d d_id=%x.\n", __func__,
+				    ha->host_no, ret, fcport->d_id.b24));
+			}
 		}
 	}
 
-	if (status == QLA_SUCCESS &&
-		((!ha->flags.enable_target_reset &&
-		  !ha->flags.enable_lip_reset) ||
-		ha->flags.enable_lip_full_login)) {
-
-		status = qla2x00_full_login_lip(ha);
-	}
-
 	/* Issue marker command only when we are going to start the I/O */
 	ha->marker_needed = 1;
 
-	if (status) {
-		/* Empty */
-		DEBUG2_3(printk("%s(%ld): **** FAILED ****\n",
-				__func__,
-				ha->host_no));
-	} else {
-		/* Empty */
-		DEBUG3(printk("%s(%ld): exiting normally.\n",
-				__func__,
-				ha->host_no));
-	}
-
-	return(status);
+	return QLA_SUCCESS;
 }
 
 /*
@@ -1413,7 +1414,9 @@
 
 	sht = &qla2x00_driver_template;
 	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
-	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
+	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
+	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432)
 		sht = &qla24xx_driver_template;
 	host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
 	if (host == NULL) {
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 1fa0bce..459e0d6 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k3"
+#define QLA2XXX_VERSION      "8.01.07-k4"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 4249e52..6f4cf2d 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -418,7 +418,6 @@
 	 * concurrently.
 	 */
 	struct mutex  mbox_sem;
-	wait_queue_head_t mailbox_wait_queue;
 
 	/* temporary mailbox status registers */
 	volatile uint8_t mbox_status_count;
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 2122967..e021eb5 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -76,4 +76,5 @@
 extern int ql4xextended_error_logging;
 extern int ql4xdiscoverywait;
 extern int ql4xdontresethba;
+extern int ql4_mod_unload;
 #endif /* _QLA4x_GBL_H */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index cc210f2..b907b06 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -958,25 +958,25 @@
 	return status;
 }
 
-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
 {
-#define QL4_LOCK_DRVR_WAIT	300
-#define QL4_LOCK_DRVR_SLEEP	100
+#define QL4_LOCK_DRVR_WAIT	30
+#define QL4_LOCK_DRVR_SLEEP	1
 
 	int drvr_wait = QL4_LOCK_DRVR_WAIT;
 	while (drvr_wait) {
-		if (ql4xxx_lock_drvr(a) == 0) {
-			msleep(QL4_LOCK_DRVR_SLEEP);
+		if (ql4xxx_lock_drvr(ha) == 0) {
+			ssleep(QL4_LOCK_DRVR_SLEEP);
 			if (drvr_wait) {
 				DEBUG2(printk("scsi%ld: %s: Waiting for "
-					      "Global Init Semaphore...n",
-					      a->host_no,
-					      __func__));
+					      "Global Init Semaphore(%d)...n",
+					      ha->host_no,
+					      __func__, drvr_wait));
 			}
 			drvr_wait -= QL4_LOCK_DRVR_SLEEP;
 		} else {
 			DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
-				      "acquired.n", a->host_no, __func__));
+				      "acquired.n", ha->host_no, __func__));
 			return QLA_SUCCESS;
 		}
 	}
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index ef975e0..35b9e36 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -433,7 +433,6 @@
 					readl(&ha->reg->mailbox[i]);
 
 			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
-			wake_up(&ha->mailbox_wait_queue);
 		}
 	} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
 		/* Immediately process the AENs that don't require much work.
@@ -686,7 +685,8 @@
 			       &ha->reg->ctrl_status);
 			readl(&ha->reg->ctrl_status);
 
-			set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+			if (!ql4_mod_unload)
+				set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
 
 			break;
 		} else if (intr_status & INTR_PENDING) {
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index b721dc5..7f28657 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -29,18 +29,30 @@
 	u_long wait_count;
 	uint32_t intr_status;
 	unsigned long flags = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	mutex_lock(&ha->mbox_sem);
-
-	/* Mailbox code active */
-	set_bit(AF_MBOX_COMMAND, &ha->flags);
 
 	/* Make sure that pointers are valid */
 	if (!mbx_cmd || !mbx_sts) {
 		DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
 			      "pointer\n", ha->host_no, __func__));
-		goto mbox_exit;
+		return status;
+	}
+	/* Mailbox code active */
+	wait_count = MBOX_TOV * 100;
+
+	while (wait_count--) {
+		mutex_lock(&ha->mbox_sem);
+		if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
+			set_bit(AF_MBOX_COMMAND, &ha->flags);
+			mutex_unlock(&ha->mbox_sem);
+			break;
+		}
+		mutex_unlock(&ha->mbox_sem);
+		if (!wait_count) {
+			DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
+				ha->host_no, __func__));
+			return status;
+		}
+		msleep(10);
 	}
 
 	/* To prevent overwriting mailbox registers for a command that has
@@ -73,8 +85,6 @@
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	/* Wait for completion */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&ha->mailbox_wait_queue, &wait);
 
 	/*
 	 * If we don't want status, don't wait for the mailbox command to
@@ -83,8 +93,6 @@
 	 */
 	if (outCount == 0) {
 		status = QLA_SUCCESS;
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&ha->mailbox_wait_queue, &wait);
 		goto mbox_exit;
 	}
 	/* Wait for command to complete */
@@ -108,8 +116,6 @@
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 		msleep(10);
 	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&ha->mailbox_wait_queue, &wait);
 
 	/* Check for mailbox timeout. */
 	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
@@ -155,9 +161,10 @@
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 mbox_exit:
+	mutex_lock(&ha->mbox_sem);
 	clear_bit(AF_MBOX_COMMAND, &ha->flags);
-	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
 	mutex_unlock(&ha->mbox_sem);
+	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
 
 	return status;
 }
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 9ef693c..81fb7bd 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -40,6 +40,8 @@
 		 "Option to enable extended error logging, "
 		 "Default is 0 - no logging, 1 - debug logging");
 
+int ql4_mod_unload = 0;
+
 /*
  * SCSI host template entry points
  */
@@ -422,6 +424,9 @@
 		goto qc_host_busy;
 	}
 
+	if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+		goto qc_host_busy;
+
 	spin_unlock_irq(ha->host->host_lock);
 
 	srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
@@ -707,16 +712,12 @@
 	return stat;
 }
 
-/**
- * qla4xxx_soft_reset - performs soft reset.
- * @ha: Pointer to host adapter structure.
- **/
-int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
 {
-	uint32_t max_wait_time;
-	unsigned long flags = 0;
-	int status = QLA_ERROR;
 	uint32_t ctrl_status;
+	unsigned long flags = 0;
+
+	DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -733,6 +734,20 @@
 	readl(&ha->reg->ctrl_status);
 
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+/**
+ * qla4xxx_soft_reset - performs soft reset.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+{
+	uint32_t max_wait_time;
+	unsigned long flags = 0;
+	int status = QLA_ERROR;
+	uint32_t ctrl_status;
+
+	qla4xxx_hw_reset(ha);
 
 	/* Wait until the Network Reset Intr bit is cleared */
 	max_wait_time = RESET_INTR_TOV;
@@ -966,10 +981,12 @@
 	struct scsi_qla_host *ha =
 		container_of(work, struct scsi_qla_host, dpc_work);
 	struct ddb_entry *ddb_entry, *dtemp;
+	int status = QLA_ERROR;
 
 	DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
-		"flags = 0x%08lx, dpc_flags = 0x%08lx\n",
-		ha->host_no, __func__, ha->flags, ha->dpc_flags));
+		"flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n",
+		ha->host_no, __func__, ha->flags, ha->dpc_flags,
+		readw(&ha->reg->ctrl_status)));
 
 	/* Initialization not yet finished. Don't do anything yet. */
 	if (!test_bit(AF_INIT_DONE, &ha->flags))
@@ -983,31 +1000,28 @@
 			test_bit(DPC_RESET_HA, &ha->dpc_flags))
 			qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
 
-		if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
+		if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
 			uint8_t wait_time = RESET_INTR_TOV;
-			unsigned long flags = 0;
 
-			qla4xxx_flush_active_srbs(ha);
-
-			spin_lock_irqsave(&ha->hardware_lock, flags);
 			while ((readw(&ha->reg->ctrl_status) &
 				(CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
 				if (--wait_time == 0)
 					break;
-
-				spin_unlock_irqrestore(&ha->hardware_lock,
-						       flags);
-
 				msleep(1000);
-
-				spin_lock_irqsave(&ha->hardware_lock, flags);
 			}
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
 			if (wait_time == 0)
 				DEBUG2(printk("scsi%ld: %s: SR|FSR "
 					      "bit not cleared-- resetting\n",
 					      ha->host_no, __func__));
+			qla4xxx_flush_active_srbs(ha);
+			if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
+				qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+				status = qla4xxx_initialize_adapter(ha,
+						PRESERVE_DDB_LIST);
+			}
+			clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+			if (status == QLA_SUCCESS)
+				qla4xxx_enable_intrs(ha);
 		}
 	}
 
@@ -1062,7 +1076,7 @@
 
 	/* Issue Soft Reset to put firmware in unknown state */
 	if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
-		qla4xxx_soft_reset(ha);
+		qla4xxx_hw_reset(ha);
 
 	/* Remove timer thread, if present */
 	if (ha->timer_active)
@@ -1198,7 +1212,6 @@
 	INIT_LIST_HEAD(&ha->free_srb_q);
 
 	mutex_init(&ha->mbox_sem);
-	init_waitqueue_head(&ha->mailbox_wait_queue);
 
 	spin_lock_init(&ha->hardware_lock);
 
@@ -1665,6 +1678,7 @@
 
 static void __exit qla4xxx_module_exit(void)
 {
+	ql4_mod_unload = 1;
 	pci_unregister_driver(&qla4xxx_pci_driver);
 	iscsi_unregister_transport(&qla4xxx_iscsi_transport);
 	kmem_cache_destroy(srb_cachep);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 454e19c..e5183a6 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION	"5.00.07-k"
+#define QLA4XXX_DRIVER_VERSION	"5.00.07-k1"
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 14e635a..96b7cbd 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -133,12 +133,10 @@
 /**
  * scsi_complete_async_scans - Wait for asynchronous scans to complete
  *
- * Asynchronous scans add themselves to the scanning_hosts list.  Once
- * that list is empty, we know that the scans are complete.  Rather than
- * waking up periodically to check the state of the list, we pretend to be
- * a scanning task by adding ourselves at the end of the list and going to
- * sleep.  When the task before us wakes us up, we take ourselves off the
- * list and return.
+ * When this function returns, any host which started scanning before
+ * this function was called will have finished its scan.  Hosts which
+ * started scanning after this function was called may or may not have
+ * finished.
  */
 int scsi_complete_async_scans(void)
 {
@@ -171,6 +169,11 @@
 
 	spin_lock(&async_scan_lock);
 	list_del(&data->list);
+	if (!list_empty(&scanning_hosts)) {
+		struct async_scan_data *next = list_entry(scanning_hosts.next,
+				struct async_scan_data, list);
+		complete(&next->prev_finished);
+	}
  done:
 	spin_unlock(&async_scan_lock);
 
@@ -739,6 +742,14 @@
 		sdev->no_uld_attach = 1;
 
 	switch (sdev->type = (inq_result[0] & 0x1f)) {
+	case TYPE_RBC:
+		/* RBC devices can return SCSI-3 compliance and yet
+		 * still not support REPORT LUNS, so make them act as
+		 * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
+		 * specifically set */
+		if ((*bflags & BLIST_REPORTLUN2) == 0)
+			*bflags |= BLIST_NOREPORTLUN;
+		/* fall through */
 	case TYPE_TAPE:
 	case TYPE_DISK:
 	case TYPE_PRINTER:
@@ -749,11 +760,17 @@
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
 	case TYPE_RAID:
-	case TYPE_RBC:
 		sdev->writeable = 1;
 		break;
-	case TYPE_WORM:
 	case TYPE_ROM:
+		/* MMC devices can return SCSI-3 compliance and yet
+		 * still not support REPORT LUNS, so make them act as
+		 * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
+		 * specifically set */
+		if ((*bflags & BLIST_REPORTLUN2) == 0)
+			*bflags |= BLIST_NOREPORTLUN;
+		/* fall through */
+	case TYPE_WORM:
 		sdev->writeable = 0;
 		break;
 	default:
@@ -1436,6 +1453,12 @@
 	struct device *parent = &shost->shost_gendev;
 	struct scsi_target *starget;
 
+	if (strncmp(scsi_scan_type, "none", 4) == 0)
+		return ERR_PTR(-ENODEV);
+
+	if (!shost->async_scan)
+		scsi_complete_async_scans();
+
 	starget = scsi_alloc_target(parent, channel, id);
 	if (!starget)
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 9c22f13..ce0d14a 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1416,7 +1416,7 @@
 {
 	int err;
 
-	printk(KERN_INFO "Loading iSCSI transport class v%s.",
+	printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
 		ISCSI_TRANSPORT_VERSION);
 
 	err = class_register(&iscsi_transport_class);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 3fded48..014d7fe 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -122,7 +122,7 @@
 			if (!sshdr)
 				sshdr = &sshdr_tmp;
 
-			if (scsi_normalize_sense(sense, sizeof(*sense),
+			if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE,
 						 sshdr)
 			    && sshdr->sense_key == UNIT_ATTENTION)
 				continue;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 978bfc1..b781a90 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1647,16 +1647,6 @@
 	if (error)
 		goto out_put;
 
-	class_device_initialize(&sdkp->cdev);
-	sdkp->cdev.dev = &sdp->sdev_gendev;
-	sdkp->cdev.class = &sd_disk_class;
-	strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
-
-	if (class_device_add(&sdkp->cdev))
-		goto out_put;
-
-	get_device(&sdp->sdev_gendev);
-
 	sdkp->device = sdp;
 	sdkp->driver = &sd_template;
 	sdkp->disk = gd;
@@ -1670,6 +1660,16 @@
 			sdp->timeout = SD_MOD_TIMEOUT;
 	}
 
+	class_device_initialize(&sdkp->cdev);
+	sdkp->cdev.dev = &sdp->sdev_gendev;
+	sdkp->cdev.class = &sd_disk_class;
+	strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
+
+	if (class_device_add(&sdkp->cdev))
+		goto out_put;
+
+	get_device(&sdp->sdev_gendev);
+
 	gd->major = sd_major((index & 0xf0) >> 4);
 	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
 	gd->minors = 16;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 5ffec27..ff62e97 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -114,6 +114,7 @@
 #define DPRINTK( when, msg... ) do { if ( (DEBUG & (when)) == (when) ) printk( msg ); } while (0)
 #else
 #define DPRINTK( when, msg... ) do { } while (0)
+#define DEBUG 0
 #endif
 #define DANY( msg... ) DPRINTK( 0xffff, msg );
 
@@ -523,7 +524,7 @@
 #ifdef ARBITRATE
 		" ARBITRATE"
 #endif
-#ifdef DEBUG
+#if DEBUG
 		" DEBUG"
 #endif
 #ifdef FAST
@@ -733,7 +734,7 @@
 	unsigned char *data = NULL;
 	struct scatterlist *buffer = NULL;
 	int clock, temp, nobuffs = 0, done = 0, len = 0;
-#ifdef DEBUG
+#if DEBUG
 	int transfered = 0, phase = 0, newphase;
 #endif
 	register unsigned char status_read;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index fae6e95..89e9b36 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -468,7 +468,7 @@
 	}
 
 	ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg);
-	if (ret != ENOSYS)
+	if (ret != -ENOSYS)
 		return ret;
 
 	/*
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index e016e09..488ec79 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -2816,15 +2816,18 @@
 
 		if (cmd_in == MTWEOF &&
 		    cmdstatp->have_sense &&
-		    (cmdstatp->flags & SENSE_EOM) &&
-		    (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
-		     cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
-		    undone == 0) {
-			ioctl_result = 0;	/* EOF written successfully at EOM */
-			if (fileno >= 0)
-				fileno++;
+		    (cmdstatp->flags & SENSE_EOM)) {
+			if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+			    cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
+				ioctl_result = 0;	/* EOF(s) written successfully at EOM */
+				STps->eof = ST_NOEOF;
+			} else {  /* Writing EOF(s) failed */
+				if (fileno >= 0)
+					fileno -= undone;
+				if (undone < arg)
+					STps->eof = ST_NOEOF;
+			}
 			STps->drv_file = fileno;
-			STps->eof = ST_NOEOF;
 		} else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
 			if (fileno >= 0)
 				STps->drv_file = fileno - undone;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 51f3c73..5261f0a 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2296,7 +2296,7 @@
 	local_irq_restore(flags);
 }
 
-static int serial8250_console_setup(struct console *co, char *options)
+static int __init serial8250_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 61db697..f69bd09 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -589,6 +589,8 @@
 	 */
 	if (co->index >= UART_NR)
 		co->index = 0;
+	if (!amba_ports[co->index])
+		return -ENODEV;
 	port = &amba_ports[co->index]->port;
 
 	if (options)
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 9a3b374..44639e7 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -661,6 +661,8 @@
 	if (co->index >= UART_NR)
 		co->index = 0;
 	uap = amba_ports[co->index];
+	if (!uap)
+		return -ENODEV;
 
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index ed7f720..881f886 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -689,9 +689,9 @@
 	struct atmel_uart_data *data = pdev->dev.platform_data;
 
 	port->iotype	= UPIO_MEM;
-	port->flags     = UPF_BOOT_AUTOCONF;
+	port->flags	= UPF_BOOT_AUTOCONF;
 	port->ops	= &atmel_pops;
-	port->fifosize  = 1;
+	port->fifosize	= 1;
 	port->line	= pdev->id;
 	port->dev	= &pdev->dev;
 
@@ -890,7 +890,6 @@
 	if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
 		enable_irq_wake(port->irq);
 	else {
-		disable_irq_wake(port->irq);
 		uart_suspend_port(&atmel_uart, port);
 		atmel_port->suspended = 1;
 	}
@@ -907,6 +906,8 @@
 		uart_resume_port(&atmel_uart, port);
 		atmel_port->suspended = 0;
 	}
+	else
+		disable_irq_wake(port->irq);
 
 	return 0;
 }
diff --git a/drivers/serial/atmel_serial.h b/drivers/serial/atmel_serial.h
index fe1763b..11b4436 100644
--- a/drivers/serial/atmel_serial.h
+++ b/drivers/serial/atmel_serial.h
@@ -106,7 +106,7 @@
 #define ATMEL_US_CSR		0x14			/* Channel Status Register */
 #define ATMEL_US_RHR		0x18			/* Receiver Holding Register */
 #define ATMEL_US_THR		0x1c			/* Transmitter Holding Register */
-#define 	ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [SAM9 only] */
+#define		ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [AT91SAM9261 only] */
 
 #define ATMEL_US_BRGR		0x20			/* Baud Rate Generator Register */
 #define		ATMEL_US_CD		(0xffff << 0)		/* Clock Divider */
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 9d11a75..3c4b6c2 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -789,7 +789,9 @@
 static int __init
 mpc52xx_console_init(void)
 {
+#if defined(CONFIG_PPC_MERGE)
 	mpc52xx_uart_of_enumerate();
+#endif
 	register_console(&mpc52xx_console);
 	return 0;
 }
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 6ed3f1d..8b41f9c 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1169,8 +1169,9 @@
 				spi->bits_per_word - 16 : spi->bits_per_word)
 			| SSCR0_SSE
 			| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
-	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4)
-			| (((spi->mode & SPI_CPOL) != 0) << 3);
+	chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
+	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
 
 	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
 	if (drv_data->ssp_type != PXA25x_SSP)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 270e621..6307428 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -366,7 +366,6 @@
 
 	class_device_initialize(&master->cdev);
 	master->cdev.class = &spi_master_class;
-	kobj_set_kset_s(&master->cdev, spi_master_class.subsys);
 	master->cdev.dev = get_device(dev);
 	spi_master_set_devdata(master, &master[1]);
 
@@ -466,14 +465,20 @@
  */
 struct spi_master *spi_busnum_to_master(u16 bus_num)
 {
-	char			name[9];
-	struct kobject		*bus;
+	struct class_device	*cdev;
+	struct spi_master	*master = NULL;
+	struct spi_master	*m;
 
-	snprintf(name, sizeof name, "spi%u", bus_num);
-	bus = kset_find_obj(&spi_master_class.subsys.kset, name);
-	if (bus)
-		return container_of(bus, struct spi_master, cdev.kobj);
-	return NULL;
+	down(&spi_master_class.sem);
+	list_for_each_entry(cdev, &spi_master_class.children, node) {
+		m = container_of(cdev, struct spi_master, cdev);
+		if (m->bus_num == bus_num) {
+			master = spi_master_get(m);
+			break;
+		}
+	}
+	up(&spi_master_class.sem);
+	return master;
 }
 EXPORT_SYMBOL_GPL(spi_busnum_to_master);
 
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 8ca0871..651379c 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -10,9 +10,6 @@
  *
 */
 
-
-//#define DEBUG
-
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
@@ -44,6 +41,9 @@
 	int			 len;
 	int			 count;
 
+	int			(*set_cs)(struct s3c2410_spi_info *spi,
+					  int cs, int pol);
+
 	/* data buffers */
 	const unsigned char	*tx;
 	unsigned char		*rx;
@@ -64,6 +64,11 @@
 	return spi_master_get_devdata(sdev->master);
 }
 
+static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
+{
+	s3c2410_gpio_setpin(spi->pin_cs, pol);
+}
+
 static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
 {
 	struct s3c24xx_spi *hw = to_hw(spi);
@@ -72,10 +77,7 @@
 
 	switch (value) {
 	case BITBANG_CS_INACTIVE:
-		if (hw->pdata->set_cs)
-			hw->pdata->set_cs(hw->pdata, value, cspol);
-		else
-			s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1);
+		hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol^1);
 		break;
 
 	case BITBANG_CS_ACTIVE:
@@ -96,14 +98,9 @@
 		/* write new configration */
 
 		writeb(spcon, hw->regs + S3C2410_SPCON);
-
-		if (hw->pdata->set_cs)
-			hw->pdata->set_cs(hw->pdata, value, cspol);
-		else
-			s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol);
+		hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol);
 
 		break;
-
 	}
 }
 
@@ -330,9 +327,12 @@
 	/* setup any gpio we can */
 
 	if (!hw->pdata->set_cs) {
+		hw->set_cs = s3c24xx_spi_gpiocs;
+
 		s3c2410_gpio_setpin(hw->pdata->pin_cs, 1);
 		s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT);
-	}
+	} else
+		hw->set_cs = hw->pdata->set_cs;
 
 	/* register our spi controller */
 
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f8324d8..3e66b2a 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -72,22 +72,6 @@
 
 	  If you are unsure about this, say N here.
 
-config USB_MULTITHREAD_PROBE
-	bool "USB Multi-threaded probe (EXPERIMENTAL)"
-	depends on USB && EXPERIMENTAL
-	default n
-	help
-	  Say Y here if you want the USB core to spawn a new thread for
-	  every USB device that is probed.  This can cause a small speedup
-	  in boot times on systems with a lot of different USB devices.
-
-	  This option should be safe to enable, but if any odd probing
-	  problems are found, please disable it, or dynamically turn it
-	  off in the /sys/module/usbcore/parameters/multithread_probe
-	  file
-
-	  When in doubt, say N.
-
 config USB_OTG
 	bool
 	depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 2651c2e..1988224 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -88,14 +88,7 @@
 static struct task_struct *khubd_task;
 
 /* multithreaded probe logic */
-static int multithread_probe =
-#ifdef CONFIG_USB_MULTITHREAD_PROBE
-	1;
-#else
-	0;
-#endif
-module_param(multithread_probe, bool, S_IRUGO);
-MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");
+static int multithread_probe = 0;
 
 /* cycle leds on hubs that aren't blinking for attention */
 static int blinkenlights = 0;
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 43ae696..3348b07 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -169,7 +169,7 @@
 static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct ochi_hcd *ohci = hcd_to_ohci(hcd);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 
 	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 258a5d0..aa6a620 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -7,7 +7,7 @@
 config USB_HID
 	tristate "USB Human Interface Device (full HID) support"
 	default y
-	depends on USB
+	depends on USB && INPUT
 	select HID
 	---help---
 	  Say Y here if you want full HID support to connect USB keyboards,
@@ -69,6 +69,14 @@
 	  Note: if you say N here, this device will still be supported, but without
 	  force feedback.
 
+config PANTHERLORD_FF
+	bool "PantherLord USB/PS2 2in1 Adapter support"
+	depends on HID_FF
+	select INPUT_FF_MEMLESS if USB_HID
+	help
+	  Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want
+	  to enable force feedback support for it.
+
 config THRUSTMASTER_FF
 	bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)"
 	depends on HID_FF && EXPERIMENTAL
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 1a24b5b..a06024e 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -17,6 +17,9 @@
 ifeq ($(CONFIG_LOGITECH_FF),y)
 	usbhid-objs	+= hid-lgff.o
 endif
+ifeq ($(CONFIG_PANTHERLORD_FF),y)
+	usbhid-objs	+= hid-plff.o
+endif
 ifeq ($(CONFIG_THRUSTMASTER_FF),y)
 	usbhid-objs	+= hid-tmff.o
 endif
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 89fa688..e07a304 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -35,6 +35,7 @@
 
 #include <linux/hid.h>
 #include <linux/hiddev.h>
+#include <linux/hid-debug.h>
 #include "usbhid.h"
 
 /*
@@ -56,11 +57,6 @@
 module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
 MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
 
-static int usbhid_pb_fnmode = 1;
-module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
-		"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
 /*
  * Input submission and I/O error handler.
  */
@@ -106,18 +102,18 @@
 
 	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
 		dev_dbg(&usbhid->intf->dev, "clear halt\n");
-		rc = usb_clear_halt(to_usb_device(hid->dev), usbhid->urbin->pipe);
+		rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe);
 		clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
 		hid_start_in(hid);
 	}
 
 	else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
 		dev_dbg(&usbhid->intf->dev, "resetting device\n");
-		rc = rc_lock = usb_lock_device_for_reset(to_usb_device(hid->dev), usbhid->intf);
+		rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
 		if (rc_lock >= 0) {
-			rc = usb_reset_composite_device(to_usb_device(hid->dev), usbhid->intf);
+			rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf);
 			if (rc_lock)
-				usb_unlock_device(to_usb_device(hid->dev));
+				usb_unlock_device(hid_to_usb_dev(hid));
 		}
 		clear_bit(HID_RESET_PENDING, &usbhid->iofl);
 	}
@@ -129,8 +125,8 @@
 		break;
 	default:
 		err("can't reset device, %s-%s/input%d, status %d",
-				to_usb_device(hid->dev)->bus->bus_name,
-				to_usb_device(hid->dev)->devpath,
+				hid_to_usb_dev(hid)->bus->bus_name,
+				hid_to_usb_dev(hid)->devpath,
 				usbhid->ifnum, rc);
 		/* FALLTHROUGH */
 	case -EHOSTUNREACH:
@@ -217,31 +213,14 @@
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
 		if (status != -EPERM) {
 			err("can't resubmit intr, %s-%s/input%d, status %d",
-					to_usb_device(hid->dev)->bus->bus_name,
-					to_usb_device(hid->dev)->devpath,
+					hid_to_usb_dev(hid)->bus->bus_name,
+					hid_to_usb_dev(hid)->devpath,
 					usbhid->ifnum, status);
 			hid_io_error(hid);
 		}
 	}
 }
 
-/*
- * Find a report field with a specified HID usage.
- */
-#if 0
-struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type)
-{
-	struct hid_report *report;
-	int i;
-
-	list_for_each_entry(report, &hid->report_enum[type].report_list, list)
-		for (i = 0; i < report->maxfield; i++)
-			if (report->field[i]->logical == wanted_usage)
-				return report->field[i];
-	return NULL;
-}
-#endif  /*  0  */
-
 static int hid_submit_out(struct hid_device *hid)
 {
 	struct hid_report *report;
@@ -251,7 +230,7 @@
 
 	hid_output_report(report, usbhid->outbuf);
 	usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-	usbhid->urbout->dev = to_usb_device(hid->dev);
+	usbhid->urbout->dev = hid_to_usb_dev(hid);
 
 	dbg("submitting out urb");
 
@@ -276,13 +255,13 @@
 	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 	if (dir == USB_DIR_OUT) {
 		hid_output_report(report, usbhid->ctrlbuf);
-		usbhid->urbctrl->pipe = usb_sndctrlpipe(to_usb_device(hid->dev), 0);
+		usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
 		usbhid->urbctrl->transfer_buffer_length = len;
 	} else {
 		int maxpacket, padlen;
 
-		usbhid->urbctrl->pipe = usb_rcvctrlpipe(to_usb_device(hid->dev), 0);
-		maxpacket = usb_maxpacket(to_usb_device(hid->dev), usbhid->urbctrl->pipe, 0);
+		usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
+		maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0);
 		if (maxpacket > 0) {
 			padlen = (len + maxpacket - 1) / maxpacket;
 			padlen *= maxpacket;
@@ -292,7 +271,7 @@
 			padlen = 0;
 		usbhid->urbctrl->transfer_buffer_length = padlen;
 	}
-	usbhid->urbctrl->dev = to_usb_device(hid->dev);
+	usbhid->urbctrl->dev = hid_to_usb_dev(hid);
 
 	usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
 	usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
@@ -506,7 +485,7 @@
 {
 	int result, retries = 4;
 
-	memset(buf,0,size);	// Make sure we parse really received data
+	memset(buf, 0, size);
 
 	do {
 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
@@ -533,18 +512,6 @@
 		usb_kill_urb(usbhid->urbin);
 }
 
-static int hidinput_open(struct input_dev *dev)
-{
-	struct hid_device *hid = dev->private;
-	return usbhid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
-	struct hid_device *hid = dev->private;
-	usbhid_close(hid);
-}
-
 #define USB_VENDOR_ID_PANJIT		0x134c
 
 #define USB_VENDOR_ID_TURBOX		0x062a
@@ -582,6 +549,7 @@
 }
 
 #define USB_VENDOR_ID_GTCO		0x078c
+#define USB_VENDOR_ID_GTCO_IPANEL_2     0x5543
 #define USB_DEVICE_ID_GTCO_90		0x0090
 #define USB_DEVICE_ID_GTCO_100		0x0100
 #define USB_DEVICE_ID_GTCO_101		0x0101
@@ -627,6 +595,8 @@
 #define USB_DEVICE_ID_GTCO_1004		0x1004
 #define USB_DEVICE_ID_GTCO_1005		0x1005
 #define USB_DEVICE_ID_GTCO_1006		0x1006
+#define USB_DEVICE_ID_GTCO_8		0x0008
+#define USB_DEVICE_ID_GTCO_d            0x000d
 
 #define USB_VENDOR_ID_WACOM		0x056a
 
@@ -772,6 +742,7 @@
 #define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
+#define USB_DEVICE_ID_APPLE_IR		0x8240
 
 #define USB_VENDOR_ID_CHERRY		0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
@@ -791,6 +762,12 @@
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER	0xc101
 
+#define USB_VENDOR_ID_IMATION		0x0718
+#define USB_DEVICE_ID_DISC_STAKKA	0xd000
+
+#define USB_VENDOR_ID_PANTHERLORD	0x0810
+#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK	0x0001
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -875,6 +852,9 @@
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
@@ -942,19 +922,21 @@
 
 	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
 
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE },
 
 	{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
@@ -965,6 +947,8 @@
 
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
 
+	{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+
 	{ 0, 0 }
 };
 
@@ -1060,6 +1044,11 @@
 	if (quirks & HID_QUIRK_IGNORE)
 		return NULL;
 
+	if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
+		(interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
+			return NULL;
+
+
 	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
 	    (!interface->desc.bNumEndpoints ||
 	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
@@ -1187,7 +1176,7 @@
 
 	hid->version = le16_to_cpu(hdesc->bcdHID);
 	hid->country = hdesc->bCountryCode;
-	hid->dev = &dev->dev;
+	hid->dev = &intf->dev;
 	usbhid->intf = intf;
 	usbhid->ifnum = interface->desc.bInterfaceNumber;
 
@@ -1231,16 +1220,12 @@
 	usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
 	usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 	hid->hidinput_input_event = usb_hidinput_input_event;
-	hid->hidinput_open = hidinput_open;
-	hid->hidinput_close = hidinput_close;
+	hid->hid_open = usbhid_open;
+	hid->hid_close = usbhid_close;
 #ifdef CONFIG_USB_HIDDEV
 	hid->hiddev_hid_event = hiddev_hid_event;
 	hid->hiddev_report_event = hiddev_report_event;
 #endif
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-	hid->pb_fnmode = usbhid_pb_fnmode;
-#endif
-
 	return hid;
 
 fail:
@@ -1282,7 +1267,7 @@
 	usb_free_urb(usbhid->urbctrl);
 	usb_free_urb(usbhid->urbout);
 
-	hid_free_buffers(to_usb_device(hid->dev), hid);
+	hid_free_buffers(hid_to_usb_dev(hid), hid);
 	hid_free_device(hid);
 }
 
@@ -1315,11 +1300,7 @@
 		return -ENODEV;
 	}
 
-	/* This only gets called when we are a single-input (most of the
-	 * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
-	 * only useful in this case, and not for multi-input quirks. */
-	if ((hid->claimed & HID_CLAIMED_INPUT) &&
-			!(hid->quirks & HID_QUIRK_MULTI_INPUT))
+	if ((hid->claimed & HID_CLAIMED_INPUT))
 		hid_ff_init(hid);
 
 	printk(KERN_INFO);
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index f8f660e..5d14505 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -33,6 +33,7 @@
 #include <linux/usb.h>
 
 #include <linux/hid.h>
+#include "usbhid.h"
 
 /*
  * This table contains pointers to initializers. To add support for new
@@ -57,6 +58,9 @@
 	{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
 	{ 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
 #endif
+#ifdef CONFIG_PANTHERLORD_FF
+	{ 0x810, 0x0001, hid_plff_init },
+#endif
 #ifdef CONFIG_THRUSTMASTER_FF
 	{ 0x44f, 0xb304, hid_tmff_init },
 #endif
@@ -70,8 +74,8 @@
 int hid_ff_init(struct hid_device* hid)
 {
 	struct hid_ff_initializer *init;
-	int vendor = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idVendor);
-	int product = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idProduct);
+	int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
+	int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);
 
 	for (init = inits; init->idVendor; init++)
 		if (init->idVendor == vendor && init->idProduct == product)
diff --git a/drivers/usb/input/hid-plff.c b/drivers/usb/input/hid-plff.c
new file mode 100644
index 0000000..76d2e6e
--- /dev/null
+++ b/drivers/usb/input/hid-plff.c
@@ -0,0 +1,129 @@
+/*
+ *  Force feedback support for PantherLord USB/PS2 2in1 Adapter devices
+ *
+ *  Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/* #define DEBUG */
+
+#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg)
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "usbhid.h"
+
+struct plff_device {
+	struct hid_report *report;
+};
+
+static int hid_plff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = dev->private;
+	struct plff_device *plff = data;
+	int left, right;
+
+	left = effect->u.rumble.strong_magnitude;
+	right = effect->u.rumble.weak_magnitude;
+	debug("called with 0x%04x 0x%04x", left, right);
+
+	left = left * 0x7f / 0xffff;
+	right = right * 0x7f / 0xffff;
+
+	plff->report->field[0]->value[2] = left;
+	plff->report->field[0]->value[3] = right;
+	debug("running with 0x%02x 0x%02x", left, right);
+	usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+
+	return 0;
+}
+
+int hid_plff_init(struct hid_device *hid)
+{
+	struct plff_device *plff;
+	struct hid_report *report;
+	struct hid_input *hidinput;
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct list_head *report_ptr = report_list;
+	struct input_dev *dev;
+	int error;
+
+	/* The device contains 2 output reports (one for each
+	   HID_QUIRK_MULTI_INPUT device), both containing 1 field, which
+	   contains 4 ff00.0002 usages and 4 16bit absolute values.
+
+	   The 2 input reports also contain a field which contains
+	   8 ff00.0001 usages and 8 boolean values. Their meaning is
+	   currently unknown. */
+
+	if (list_empty(report_list)) {
+		printk(KERN_ERR "hid-plff: no output reports found\n");
+		return -ENODEV;
+	}
+
+	list_for_each_entry(hidinput, &hid->inputs, list) {
+
+		report_ptr = report_ptr->next;
+
+		if (report_ptr == report_list) {
+			printk(KERN_ERR "hid-plff: required output report is missing\n");
+			return -ENODEV;
+		}
+
+		report = list_entry(report_ptr, struct hid_report, list);
+		if (report->maxfield < 1) {
+			printk(KERN_ERR "hid-plff: no fields in the report\n");
+			return -ENODEV;
+		}
+
+		if (report->field[0]->report_count < 4) {
+			printk(KERN_ERR "hid-plff: not enough values in the field\n");
+			return -ENODEV;
+		}
+
+		plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL);
+		if (!plff)
+			return -ENOMEM;
+
+		dev = hidinput->input;
+
+		set_bit(FF_RUMBLE, dev->ffbit);
+
+		error = input_ff_create_memless(dev, plff, hid_plff_play);
+		if (error) {
+			kfree(plff);
+			return error;
+		}
+
+		plff->report = report;
+		plff->report->field[0]->value[0] = 0x00;
+		plff->report->field[0]->value[1] = 0x00;
+		plff->report->field[0]->value[2] = 0x00;
+		plff->report->field[0]->value[3] = 0x00;
+		usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+	}
+
+	printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 "
+	       "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n");
+
+	return 0;
+}
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 114d6c9..a8b3d66 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -384,7 +384,7 @@
 	struct hiddev_list *list = file->private_data;
 	struct hiddev *hiddev = list->hiddev;
 	struct hid_device *hid = hiddev->hid;
-	struct usb_device *dev = to_usb_device(hid->dev);
+	struct usb_device *dev = hid_to_usb_dev(hid);
 	struct hiddev_collection_info cinfo;
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h
index 830107e..0023f96 100644
--- a/drivers/usb/input/usbhid.h
+++ b/drivers/usb/input/usbhid.h
@@ -80,5 +80,8 @@
 
 };
 
+#define	hid_to_usb_dev(hid_dev) \
+	container_of(hid_dev->dev->parent, struct usb_device, dev)
+
 #endif
 
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 7f3c57d..86e37a2 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -66,7 +66,7 @@
 
 	void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
 	int  (*get_pkt_len) (unsigned char *pkt, int len);
-	int  (*read_data)   (unsigned char *pkt, int *x, int *y, int *touch, int *press);
+	int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt);
 	int  (*init)        (struct usbtouch_usb *usbtouch);
 };
 
@@ -85,6 +85,9 @@
 	struct usbtouch_device_info *type;
 	char name[128];
 	char phys[64];
+
+	int x, y;
+	int touch, press;
 };
 
 
@@ -161,14 +164,14 @@
 #define EGALAX_PKT_TYPE_REPT		0x80
 #define EGALAX_PKT_TYPE_DIAG		0x0A
 
-static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
 		return 0;
 
-	*x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
-	*y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
-	*touch = pkt[0] & 0x01;
+	dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
+	dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
+	dev->touch = pkt[0] & 0x01;
 
 	return 1;
 }
@@ -195,11 +198,11 @@
  * PanJit Part
  */
 #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
-static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
-	*x = ((pkt[2] & 0x0F) << 8) | pkt[1];
-	*y = ((pkt[4] & 0x0F) << 8) | pkt[3];
-	*touch = pkt[0] & 0x01;
+	dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
+	dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3];
+	dev->touch = pkt[0] & 0x01;
 
 	return 1;
 }
@@ -215,11 +218,11 @@
 #define MTOUCHUSB_RESET                 7
 #define MTOUCHUSB_REQ_CTRLLR_ID         10
 
-static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
-	*x = (pkt[8] << 8) | pkt[7];
-	*y = (pkt[10] << 8) | pkt[9];
-	*touch = (pkt[2] & 0x40) ? 1 : 0;
+	dev->x = (pkt[8] << 8) | pkt[7];
+	dev->y = (pkt[10] << 8) | pkt[9];
+	dev->touch = (pkt[2] & 0x40) ? 1 : 0;
 
 	return 1;
 }
@@ -260,14 +263,32 @@
  * ITM Part
  */
 #ifdef CONFIG_USB_TOUCHSCREEN_ITM
-static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
-	*x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
-	*y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
-	*press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
-	*touch = ~pkt[7] & 0x20;
+	int touch;
+	/*
+	 * ITM devices report invalid x/y data if not touched.
+	 * if the screen was touched before but is not touched any more
+	 * report touch as 0 with the last valid x/y data once. then stop
+	 * reporting data until touched again.
+	 */
+	dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
 
-	return *touch;
+	touch = ~pkt[7] & 0x20;
+	if (!touch) {
+		if (dev->touch) {
+			dev->touch = 0;
+			return 1;
+		}
+
+		return 0;
+	}
+
+	dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
+	dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+	dev->touch = touch;
+
+	return 1;
 }
 #endif
 
@@ -276,7 +297,7 @@
  * eTurboTouch part
  */
 #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
-static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	unsigned int shift;
 
@@ -285,9 +306,9 @@
 		return 0;
 
 	shift = (6 - (pkt[0] & 0x03));
-	*x = ((pkt[3] << 7) | pkt[4]) >> shift;
-	*y = ((pkt[1] << 7) | pkt[2]) >> shift;
-	*touch = (pkt[0] & 0x10) ? 1 : 0;
+	dev->x = ((pkt[3] << 7) | pkt[4]) >> shift;
+	dev->y = ((pkt[1] << 7) | pkt[2]) >> shift;
+	dev->touch = (pkt[0] & 0x10) ? 1 : 0;
 
 	return 1;
 }
@@ -307,14 +328,14 @@
  * Gunze part
  */
 #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
-static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
 	if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
 		return 0;
 
-	*x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
-	*y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
-	*touch = pkt[0] & 0x20;
+	dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
+	dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
+	dev->touch = pkt[0] & 0x20;
 
 	return 1;
 }
@@ -383,11 +404,11 @@
 }
 
 
-static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
-	*x = ((pkt[2] & 0x03) << 8) | pkt[1];
-	*y = ((pkt[4] & 0x03) << 8) | pkt[3];
-	*touch = pkt[0] & 0x01;
+	dev->x = ((pkt[2] & 0x03) << 8) | pkt[1];
+	dev->y = ((pkt[4] & 0x03) << 8) | pkt[3];
+	dev->touch = pkt[0] & 0x01;
 
 	return 1;
 }
@@ -492,23 +513,22 @@
 static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
                                  unsigned char *pkt, int len)
 {
-	int x, y, touch, press;
 	struct usbtouch_device_info *type = usbtouch->type;
 
-	if (!type->read_data(pkt, &x, &y, &touch, &press))
+	if (!type->read_data(usbtouch, pkt))
 			return;
 
-	input_report_key(usbtouch->input, BTN_TOUCH, touch);
+	input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
 
 	if (swap_xy) {
-		input_report_abs(usbtouch->input, ABS_X, y);
-		input_report_abs(usbtouch->input, ABS_Y, x);
+		input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
+		input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
 	} else {
-		input_report_abs(usbtouch->input, ABS_X, x);
-		input_report_abs(usbtouch->input, ABS_Y, y);
+		input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
+		input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
 	}
 	if (type->max_press)
-		input_report_abs(usbtouch->input, ABS_PRESSURE, press);
+		input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
 	input_sync(usbtouch->input);
 }
 
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index f538013..896449f 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -898,7 +898,7 @@
 
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-	int ret;
+	int ret, embd_phy;
 	void *buf;
 	u16 rx_ctl;
 	struct asix_data *data = (struct asix_data *)&dev->data;
@@ -919,13 +919,15 @@
 			AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
 		goto out2;
 
+	/* 0x10 is the phy id of the embedded 10/100 ethernet phy */
+	embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
 	if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
-				1, 0, 0, buf)) < 0) {
+				embd_phy, 0, 0, buf)) < 0) {
 		dbg("Select PHY #1 failed: %d", ret);
 		goto out2;
 	}
 
-	if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD)) < 0)
+	if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0)
 		goto out2;
 
 	msleep(150);
@@ -933,8 +935,14 @@
 		goto out2;
 
 	msleep(150);
-	if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
-		goto out2;
+	if (embd_phy) {
+		if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0)
+			goto out2;
+	}
+	else {
+		if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0)
+			goto out2;
+	}
 
 	msleep(150);
 	rx_ctl = asix_read_rx_ctl(dev);
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index ea5f44d..a322a16 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -379,6 +379,7 @@
 {
 	int			retval;
 	struct net_device	*net = dev->net;
+	struct cdc_state	*info = (void *) &dev->data;
 	union {
 		void			*buf;
 		struct rndis_msg_hdr	*header;
@@ -397,7 +398,7 @@
 		return -ENOMEM;
 	retval = usbnet_generic_cdc_bind(dev, intf);
 	if (retval < 0)
-		goto done;
+		goto fail;
 
 	net->hard_header_len += sizeof (struct rndis_data_hdr);
 
@@ -412,10 +413,7 @@
 	if (unlikely(retval < 0)) {
 		/* it might not even be an RNDIS device!! */
 		dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
-fail:
-		usb_driver_release_interface(driver_of(intf),
-			((struct cdc_state *)&(dev->data))->data);
-		goto done;
+		goto fail_and_release;
 	}
 	dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size);
 	/* REVISIT:  peripheral "alignment" request is ignored ... */
@@ -431,7 +429,7 @@
 	retval = rndis_command(dev, u.header);
 	if (unlikely(retval < 0)) {
 		dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
-		goto fail;
+		goto fail_and_release;
 	}
 	tmp = le32_to_cpu(u.get_c->offset);
 	if (unlikely((tmp + 8) > (1024 - ETH_ALEN)
@@ -439,7 +437,7 @@
 		dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n",
 			tmp, le32_to_cpu(u.get_c->len));
 		retval = -EDOM;
-		goto fail;
+		goto fail_and_release;
 	}
 	memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN);
 
@@ -455,11 +453,18 @@
 	retval = rndis_command(dev, u.header);
 	if (unlikely(retval < 0)) {
 		dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
-		goto fail;
+		goto fail_and_release;
 	}
 
 	retval = 0;
-done:
+
+	kfree(u.buf);
+	return retval;
+
+fail_and_release:
+	usb_set_intfdata(info->data, NULL);
+	usb_driver_release_interface(driver_of(intf), info->data);
+fail:
 	kfree(u.buf);
 	return retval;
 }
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index e0eecda..670262a 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -284,7 +284,8 @@
 	u8 data[3], tmp;
 
 	data[0] = phy;
-	*(data + 1) = cpu_to_le16p(&reg);
+	data[1] = reg & 0xff;
+	data[2] = (reg >> 8) & 0xff;
 	tmp = indx | PHY_WRITE | PHY_GO;
 	i = 0;
 
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index c8999ae..2f4d303 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -170,7 +170,7 @@
 
 config USB_SERIAL_FUNSOFT
 	tristate "USB Fundamental Software Dongle Driver"
-	depends on USB_SERIAL && !(SPARC || SPARC64)
+	depends on USB_SERIAL
 	---help---
 	  Say Y here if you want to use the Fundamental Software dongle.
 
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index d3be9214..2bebd63 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -27,12 +27,12 @@
 static int funsoft_ioctl(struct usb_serial_port *port, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
-	struct termios t;
+	struct ktermios t;
 
 	dbg("%s - port %d, cmd 0x%04x", __FUNCTION__, port->number, cmd);
 
 	if (cmd == TCSETSF) {
-		if (user_termios_to_kernel_termios(&t, (void __user *)arg))
+		if (user_termios_to_kernel_termios(&t, (struct termios __user *)arg))
 			return -EFAULT;
 
 		dbg("%s - iflag:%x oflag:%x cflag:%x lflag:%x", __FUNCTION__,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5ca04e8..0fed43a 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -78,6 +78,7 @@
 #define OPTION_PRODUCT_FUSION2          0x6300
 #define OPTION_PRODUCT_COBRA            0x6500
 #define OPTION_PRODUCT_COBRA2           0x6600
+#define OPTION_PRODUCT_GTMAX36          0x6701
 #define HUAWEI_PRODUCT_E600             0x1001
 #define HUAWEI_PRODUCT_E220             0x1003
 #define AUDIOVOX_PRODUCT_AIRCARD        0x0112
@@ -90,6 +91,7 @@
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
 	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
@@ -104,6 +106,7 @@
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
 	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index cddef3e..b49f2a7 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -197,6 +197,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
+/* Reported by Manuel Osdoba <manuel.osdoba@tu-ilmenau.de> */
+UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452,
+		"Nokia",
+		"Nokia 6233",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_MAX_SECTORS_64 ),
+
 /* Reported by Alex Corcoles <alex@corcoles.net> */
 UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
 		"Nokia",
@@ -254,6 +261,18 @@
 		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
 #endif
 
+/*
+ * This virtual floppy is found in Sun equipment (x4600, x4200m2, etc.)
+ * Reported by Pete Zaitcev <zaitcev@redhat.com>
+ * This device chokes on both version of MODE SENSE which we have, so
+ * use_10_for_ms is not effective, and we use US_FL_NO_WP_DETECT.
+ */
+UNUSUAL_DEV(  0x046b, 0xff40, 0x0100, 0x0100,
+		"AMI",
+		"Virtual Floppy",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_NO_WP_DETECT),
+
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
 		"Kyocera",
diff --git a/fs/9p/error.c b/fs/9p/error.c
index ae91555..0d7fa4e 100644
--- a/fs/9p/error.c
+++ b/fs/9p/error.c
@@ -83,6 +83,7 @@
 
 	if (errno == 0) {
 		/* TODO: if error isn't found, add it dynamically */
+		errstr[len] = 0;
 		printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
 		       errstr);
 		errno = 1;
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 2750720..a9b6301 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/idr.h>
+#include <asm/semaphore.h>
 
 #include "debug.h"
 #include "v9fs.h"
@@ -84,6 +85,7 @@
 	new->iounit = 0;
 	new->rdir_pos = 0;
 	new->rdir_fcall = NULL;
+	init_MUTEX(&new->lock);
 	INIT_LIST_HEAD(&new->list);
 
 	return new;
@@ -102,11 +104,11 @@
 }
 
 /**
- * v9fs_fid_lookup - retrieve the right fid from a  particular dentry
+ * v9fs_fid_lookup - return a locked fid from a dentry
  * @dentry: dentry to look for fid in
- * @type: intent of lookup (operation or traversal)
  *
- * find a fid in the dentry
+ * find a fid in the dentry, obtain its semaphore and return a reference to it.
+ * code calling lookup is responsible for releasing lock
  *
  * TODO: only match fids that have the same uid as current user
  *
@@ -124,7 +126,68 @@
 
 	if (!return_fid) {
 		dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");
+		return_fid = ERR_PTR(-EBADF);
 	}
 
+	if(down_interruptible(&return_fid->lock))
+		return ERR_PTR(-EINTR);
+
 	return return_fid;
 }
+
+/**
+ * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it
+ * @dentry: dentry to look for fid in
+ *
+ * find a fid in the dentry and then clone to a new private fid
+ *
+ * TODO: only match fids that have the same uid as current user
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry)
+{
+	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
+	struct v9fs_fcall *fcall = NULL;
+	int fid, err;
+
+	base_fid = v9fs_fid_lookup(dentry);
+
+	if(IS_ERR(base_fid))
+		return base_fid;
+
+	if(base_fid) {  /* clone fid */
+		fid = v9fs_get_idpool(&v9ses->fidpool);
+		if (fid < 0) {
+			eprintk(KERN_WARNING, "newfid fails!\n");
+			new_fid = ERR_PTR(-ENOSPC);
+			goto Release_Fid;
+		}
+
+		err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
+		if (err < 0) {
+			dprintk(DEBUG_ERROR, "clone walk didn't work\n");
+			v9fs_put_idpool(fid, &v9ses->fidpool);
+			new_fid = ERR_PTR(err);
+			goto Free_Fcall;
+		}
+		new_fid = v9fs_fid_create(v9ses, fid);
+		if (new_fid == NULL) {
+			dprintk(DEBUG_ERROR, "out of memory\n");
+			new_fid = ERR_PTR(-ENOMEM);
+		}
+Free_Fcall:
+		kfree(fcall);
+	}
+
+Release_Fid:
+	up(&base_fid->lock);
+	return new_fid;
+}
+
+void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid)
+{
+	v9fs_t_clunk(v9ses, fid->fid);
+	v9fs_fid_destroy(fid);
+}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index aa974d6..48fc170 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -30,6 +30,8 @@
 	struct list_head list;	 /* list of fids associated with a dentry */
 	struct list_head active; /* XXX - debug */
 
+	struct semaphore lock;
+
 	u32 fid;
 	unsigned char fidopen;	  /* set when fid is opened */
 	unsigned char fidclunked; /* set when fid has already been clunked */
@@ -55,3 +57,6 @@
 void v9fs_fid_destroy(struct v9fs_fid *fid);
 struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid);
 int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry);
+struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry);
+void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid);
+
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 944273c..147ceef 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -132,8 +132,10 @@
 		v9fs_mux_poll_tasks[i].task = NULL;
 
 	v9fs_mux_wq = create_workqueue("v9fs");
-	if (!v9fs_mux_wq)
+	if (!v9fs_mux_wq) {
+		printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
 		return -ENOMEM;
+	}
 
 	return 0;
 }
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 0b96fae..d9b561b 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -457,14 +457,19 @@
 
 	v9fs_error_init();
 
-	printk(KERN_INFO "Installing v9fs 9P2000 file system support\n");
+	printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
 
 	ret = v9fs_mux_global_init();
-	if (!ret)
+	if (ret) {
+		printk(KERN_WARNING "v9fs: starting mux failed\n");
 		return ret;
+	}
 	ret = register_filesystem(&v9fs_fs_type);
-	if (!ret)
+	if (ret) {
+		printk(KERN_WARNING "v9fs: registering file system failed\n");
 		v9fs_mux_global_exit();
+	}
+
 	return ret;
 }
 
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index e86a071..9f17b0c 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -55,53 +55,22 @@
 	struct v9fs_fid *vfid;
 	struct v9fs_fcall *fcall = NULL;
 	int omode;
-	int fid = V9FS_NOFID;
 	int err;
 
 	dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
 
-	vfid = v9fs_fid_lookup(file->f_path.dentry);
-	if (!vfid) {
-		dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
-		return -EBADF;
-	}
+	vfid = v9fs_fid_clone(file->f_path.dentry);
+	if (IS_ERR(vfid))
+		return PTR_ERR(vfid);
 
-	fid = v9fs_get_idpool(&v9ses->fidpool);
-	if (fid < 0) {
-		eprintk(KERN_WARNING, "newfid fails!\n");
-		return -ENOSPC;
-	}
-
-	err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall);
-	if (err < 0) {
-		dprintk(DEBUG_ERROR, "rewalk didn't work\n");
-		if (fcall && fcall->id == RWALK)
-			goto clunk_fid;
-		else {
-			v9fs_put_idpool(fid, &v9ses->fidpool);
-			goto free_fcall;
-		}
-	}
-	kfree(fcall);
-
-	/* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
-	/* translate open mode appropriately */
 	omode = v9fs_uflags2omode(file->f_flags);
-	err = v9fs_t_open(v9ses, fid, omode, &fcall);
+	err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall);
 	if (err < 0) {
 		PRINT_FCALL_ERROR("open failed", fcall);
-		goto clunk_fid;
-	}
-
-	vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
-	if (vfid == NULL) {
-		dprintk(DEBUG_ERROR, "out of memory\n");
-		err = -ENOMEM;
-		goto clunk_fid;
+		goto Clunk_Fid;
 	}
 
 	file->private_data = vfid;
-	vfid->fid = fid;
 	vfid->fidopen = 1;
 	vfid->fidclunked = 0;
 	vfid->iounit = fcall->params.ropen.iounit;
@@ -112,10 +81,8 @@
 
 	return 0;
 
-clunk_fid:
-	v9fs_t_clunk(v9ses, fid);
-
-free_fcall:
+Clunk_Fid:
+	v9fs_fid_clunk(v9ses, vfid);
 	kfree(fcall);
 
 	return err;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 18f26cd..9109ba1 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -416,12 +416,8 @@
 	sb = file_inode->i_sb;
 	v9ses = v9fs_inode2v9ses(file_inode);
 	v9fid = v9fs_fid_lookup(file);
-
-	if (!v9fid) {
-		dprintk(DEBUG_ERROR,
-			"no v9fs_fid\n");
-		return -EBADF;
-	}
+	if(IS_ERR(v9fid))
+		return PTR_ERR(v9fid);
 
 	fid = v9fid->fid;
 	if (fid < 0) {
@@ -433,11 +429,13 @@
 	result = v9fs_t_remove(v9ses, fid, &fcall);
 	if (result < 0) {
 		PRINT_FCALL_ERROR("remove fails", fcall);
+		goto Error;
 	}
 
 	v9fs_put_idpool(fid, &v9ses->fidpool);
 	v9fs_fid_destroy(v9fid);
 
+Error:
 	kfree(fcall);
 	return result;
 }
@@ -473,9 +471,13 @@
 	inode = NULL;
 	vfid = NULL;
 	v9ses = v9fs_inode2v9ses(dir);
-	dfid = v9fs_fid_lookup(dentry->d_parent);
-	perm = unixmode2p9mode(v9ses, mode);
+	dfid = v9fs_fid_clone(dentry->d_parent);
+	if(IS_ERR(dfid)) {
+		err = PTR_ERR(dfid);
+		goto error;
+	}
 
+	perm = unixmode2p9mode(v9ses, mode);
 	if (nd && nd->flags & LOOKUP_OPEN)
 		flags = nd->intent.open.flags - 1;
 	else
@@ -485,9 +487,10 @@
 		perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
 
 	if (err)
-		goto error;
+		goto clunk_dfid;
 
 	vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
+	v9fs_fid_clunk(v9ses, dfid);
 	if (IS_ERR(vfid)) {
 		err = PTR_ERR(vfid);
 		vfid = NULL;
@@ -525,6 +528,9 @@
 
 	return 0;
 
+clunk_dfid:
+	v9fs_fid_clunk(v9ses, dfid);
+
 error:
 	if (vfid)
 		v9fs_fid_destroy(vfid);
@@ -551,7 +557,12 @@
 	inode = NULL;
 	vfid = NULL;
 	v9ses = v9fs_inode2v9ses(dir);
-	dfid = v9fs_fid_lookup(dentry->d_parent);
+	dfid = v9fs_fid_clone(dentry->d_parent);
+	if(IS_ERR(dfid)) {
+		err = PTR_ERR(dfid);
+		goto error;
+	}
+
 	perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
 
 	err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
@@ -559,37 +570,36 @@
 
 	if (err) {
 		dprintk(DEBUG_ERROR, "create error %d\n", err);
-		goto error;
-	}
-
-	err = v9fs_t_clunk(v9ses, fid);
-	if (err) {
-		dprintk(DEBUG_ERROR, "clunk error %d\n", err);
-		goto error;
+		goto clean_up_dfid;
 	}
 
 	vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
 	if (IS_ERR(vfid)) {
 		err = PTR_ERR(vfid);
 		vfid = NULL;
-		goto error;
+		goto clean_up_dfid;
 	}
 
+	v9fs_fid_clunk(v9ses, dfid);
 	inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		inode = NULL;
-		goto error;
+		goto clean_up_fids;
 	}
 
 	dentry->d_op = &v9fs_dentry_operations;
 	d_instantiate(dentry, inode);
 	return 0;
 
-error:
+clean_up_fids:
 	if (vfid)
 		v9fs_fid_destroy(vfid);
 
+clean_up_dfid:
+	v9fs_fid_clunk(v9ses, dfid);
+
+error:
 	return err;
 }
 
@@ -622,28 +632,23 @@
 	dentry->d_op = &v9fs_dentry_operations;
 	dirfid = v9fs_fid_lookup(dentry->d_parent);
 
-	if (!dirfid) {
-		dprintk(DEBUG_ERROR, "no dirfid\n");
-		return ERR_PTR(-EINVAL);
-	}
+	if(IS_ERR(dirfid))
+		return ERR_PTR(PTR_ERR(dirfid));
 
 	dirfidnum = dirfid->fid;
 
-	if (dirfidnum < 0) {
-		dprintk(DEBUG_ERROR, "no dirfid for inode %p, #%lu\n",
-			dir, dir->i_ino);
-		return ERR_PTR(-EBADF);
-	}
-
 	newfid = v9fs_get_idpool(&v9ses->fidpool);
 	if (newfid < 0) {
 		eprintk(KERN_WARNING, "newfid fails!\n");
-		return ERR_PTR(-ENOSPC);
+		result = -ENOSPC;
+		goto Release_Dirfid;
 	}
 
 	result = v9fs_t_walk(v9ses, dirfidnum, newfid,
 		(char *)dentry->d_name.name, &fcall);
 
+	up(&dirfid->lock);
+
 	if (result < 0) {
 		if (fcall && fcall->id == RWALK)
 			v9fs_t_clunk(v9ses, newfid);
@@ -701,8 +706,12 @@
 
 	return NULL;
 
-      FreeFcall:
+Release_Dirfid:
+	up(&dirfid->lock);
+
+FreeFcall:
 	kfree(fcall);
+
 	return ERR_PTR(result);
 }
 
@@ -746,10 +755,8 @@
 	struct inode *old_inode = old_dentry->d_inode;
 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
 	struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
-	struct v9fs_fid *olddirfid =
-	    v9fs_fid_lookup(old_dentry->d_parent);
-	struct v9fs_fid *newdirfid =
-	    v9fs_fid_lookup(new_dentry->d_parent);
+	struct v9fs_fid *olddirfid;
+	struct v9fs_fid *newdirfid;
 	struct v9fs_wstat wstat;
 	struct v9fs_fcall *fcall = NULL;
 	int fid = -1;
@@ -759,16 +766,26 @@
 
 	dprintk(DEBUG_VFS, "\n");
 
-	if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
-		dprintk(DEBUG_ERROR, "problem with arguments\n");
-		return -EBADF;
+	if(IS_ERR(oldfid))
+		return PTR_ERR(oldfid);
+
+	olddirfid = v9fs_fid_clone(old_dentry->d_parent);
+	if(IS_ERR(olddirfid)) {
+		retval = PTR_ERR(olddirfid);
+		goto Release_lock;
+	}
+
+	newdirfid = v9fs_fid_clone(new_dentry->d_parent);
+	if(IS_ERR(newdirfid)) {
+		retval = PTR_ERR(newdirfid);
+		goto Clunk_olddir;
 	}
 
 	/* 9P can only handle file rename in the same directory */
 	if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
 		dprintk(DEBUG_ERROR, "old dir and new dir are different\n");
-		retval = -EPERM;
-		goto FreeFcallnBail;
+		retval = -EXDEV;
+		goto Clunk_newdir;
 	}
 
 	fid = oldfid->fid;
@@ -779,7 +796,7 @@
 		dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
 			old_inode->i_ino);
 		retval = -EBADF;
-		goto FreeFcallnBail;
+		goto Clunk_newdir;
 	}
 
 	v9fs_blank_wstat(&wstat);
@@ -788,11 +805,20 @@
 
 	retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
 
-      FreeFcallnBail:
 	if (retval < 0)
 		PRINT_FCALL_ERROR("wstat error", fcall);
 
 	kfree(fcall);
+
+Clunk_newdir:
+	v9fs_fid_clunk(v9ses, newdirfid);
+
+Clunk_olddir:
+	v9fs_fid_clunk(v9ses, olddirfid);
+
+Release_lock:
+	up(&oldfid->lock);
+
 	return retval;
 }
 
@@ -810,15 +836,12 @@
 {
 	struct v9fs_fcall *fcall = NULL;
 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
+	struct v9fs_fid *fid = v9fs_fid_clone(dentry);
 	int err = -EPERM;
 
 	dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
-	if (!fid) {
-		dprintk(DEBUG_ERROR,
-			"couldn't find fid associated with dentry\n");
-		return -EBADF;
-	}
+	if(IS_ERR(fid))
+		return PTR_ERR(fid);
 
 	err = v9fs_t_stat(v9ses, fid->fid, &fcall);
 
@@ -831,6 +854,7 @@
 	}
 
 	kfree(fcall);
+	v9fs_fid_clunk(v9ses, fid);
 	return err;
 }
 
@@ -844,18 +868,14 @@
 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
+	struct v9fs_fid *fid = v9fs_fid_clone(dentry);
 	struct v9fs_fcall *fcall = NULL;
 	struct v9fs_wstat wstat;
 	int res = -EPERM;
 
 	dprintk(DEBUG_VFS, "\n");
-
-	if (!fid) {
-		dprintk(DEBUG_ERROR,
-			"Couldn't find fid associated with dentry\n");
-		return -EBADF;
-	}
+	if(IS_ERR(fid))
+		return PTR_ERR(fid);
 
 	v9fs_blank_wstat(&wstat);
 	if (iattr->ia_valid & ATTR_MODE)
@@ -887,6 +907,7 @@
 	if (res >= 0)
 		res = inode_setattr(dentry->d_inode, iattr);
 
+	v9fs_fid_clunk(v9ses, fid);
 	return res;
 }
 
@@ -987,18 +1008,15 @@
 
 	struct v9fs_fcall *fcall = NULL;
 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
+	struct v9fs_fid *fid = v9fs_fid_clone(dentry);
 
-	if (!fid) {
-		dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n");
-		retval = -EBADF;
-		goto FreeFcall;
-	}
+	if(IS_ERR(fid))
+		return PTR_ERR(fid);
 
 	if (!v9ses->extended) {
 		retval = -EBADF;
 		dprintk(DEBUG_ERROR, "not extended\n");
-		goto FreeFcall;
+		goto ClunkFid;
 	}
 
 	dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
@@ -1009,8 +1027,10 @@
 		goto FreeFcall;
 	}
 
-	if (!fcall)
-		return -EIO;
+	if (!fcall) {
+		retval = -EIO;
+		goto ClunkFid;
+	}
 
 	if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) {
 		retval = -EINVAL;
@@ -1028,9 +1048,12 @@
 		fcall->params.rstat.stat.extension.str, buffer);
 	retval = buflen;
 
-      FreeFcall:
+FreeFcall:
 	kfree(fcall);
 
+ClunkFid:
+	v9fs_fid_clunk(v9ses, fid);
+
 	return retval;
 }
 
@@ -1123,52 +1146,58 @@
 	int err;
 	u32 fid, perm;
 	struct v9fs_session_info *v9ses;
-	struct v9fs_fid *dfid, *vfid;
-	struct inode *inode;
+	struct v9fs_fid *dfid, *vfid = NULL;
+	struct inode *inode = NULL;
 
-	inode = NULL;
-	vfid = NULL;
 	v9ses = v9fs_inode2v9ses(dir);
-	dfid = v9fs_fid_lookup(dentry->d_parent);
-	perm = unixmode2p9mode(v9ses, mode);
-
 	if (!v9ses->extended) {
 		dprintk(DEBUG_ERROR, "not extended\n");
 		return -EPERM;
 	}
 
+	dfid = v9fs_fid_clone(dentry->d_parent);
+	if(IS_ERR(dfid)) {
+		err = PTR_ERR(dfid);
+		goto error;
+	}
+
+	perm = unixmode2p9mode(v9ses, mode);
+
 	err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
 		perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
 
 	if (err)
-		goto error;
+		goto clunk_dfid;
 
 	err = v9fs_t_clunk(v9ses, fid);
 	if (err)
-		goto error;
+		goto clunk_dfid;
 
 	vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
 	if (IS_ERR(vfid)) {
 		err = PTR_ERR(vfid);
 		vfid = NULL;
-		goto error;
+		goto clunk_dfid;
 	}
 
 	inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		inode = NULL;
-		goto error;
+		goto free_vfid;
 	}
 
 	dentry->d_op = &v9fs_dentry_operations;
 	d_instantiate(dentry, inode);
 	return 0;
 
-error:
-	if (vfid)
-		v9fs_fid_destroy(vfid);
+free_vfid:
+	v9fs_fid_destroy(vfid);
 
+clunk_dfid:
+	v9fs_fid_clunk(v9ses, dfid);
+
+error:
 	return err;
 
 }
@@ -1209,26 +1238,29 @@
 	      struct dentry *dentry)
 {
 	int retval;
+	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
 	struct v9fs_fid *oldfid;
 	char *name;
 
 	dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
 		old_dentry->d_name.name);
 
-	oldfid = v9fs_fid_lookup(old_dentry);
-	if (!oldfid) {
-		dprintk(DEBUG_ERROR, "can't find oldfid\n");
-		return -EPERM;
-	}
+	oldfid = v9fs_fid_clone(old_dentry);
+	if(IS_ERR(oldfid))
+		return PTR_ERR(oldfid);
 
 	name = __getname();
-	if (unlikely(!name))
-		return -ENOMEM;
+	if (unlikely(!name)) {
+		retval = -ENOMEM;
+		goto clunk_fid;
+	}
 
 	sprintf(name, "%d\n", oldfid->fid);
 	retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
 	__putname(name);
 
+clunk_fid:
+	v9fs_fid_clunk(v9ses, oldfid);
 	return retval;
 }
 
diff --git a/fs/aio.c b/fs/aio.c
index ee20fc4..55991e4 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -298,17 +298,23 @@
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
 
+	spin_lock_irq(&ctx->ctx_lock);
 	if (!ctx->reqs_active)
-		return;
+		goto out;
 
 	add_wait_queue(&ctx->wait, &wait);
 	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 	while (ctx->reqs_active) {
+		spin_unlock_irq(&ctx->ctx_lock);
 		schedule();
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		spin_lock_irq(&ctx->ctx_lock);
 	}
 	__set_task_state(tsk, TASK_RUNNING);
 	remove_wait_queue(&ctx->wait, &wait);
+
+out:
+	spin_unlock_irq(&ctx->ctx_lock);
 }
 
 /* wait_on_sync_kiocb:
@@ -424,7 +430,6 @@
 	ring = kmap_atomic(ctx->ring_info.ring_pages[0], KM_USER0);
 	if (ctx->reqs_active < aio_ring_avail(&ctx->ring_info, ring)) {
 		list_add(&req->ki_list, &ctx->active_reqs);
-		get_ioctx(ctx);
 		ctx->reqs_active++;
 		okay = 1;
 	}
@@ -536,8 +541,6 @@
 	spin_lock_irq(&ctx->ctx_lock);
 	ret = __aio_put_req(ctx, req);
 	spin_unlock_irq(&ctx->ctx_lock);
-	if (ret)
-		put_ioctx(ctx);
 	return ret;
 }
 
@@ -779,8 +782,7 @@
 		 */
 		iocb->ki_users++;       /* grab extra reference */
 		aio_run_iocb(iocb);
-		if (__aio_put_req(ctx, iocb))  /* drop extra ref */
-			put_ioctx(ctx);
+		__aio_put_req(ctx, iocb);
  	}
 	if (!list_empty(&ctx->run_list))
 		return 1;
@@ -997,14 +999,10 @@
 	/* everything turned out well, dispose of the aiocb. */
 	ret = __aio_put_req(ctx, iocb);
 
-	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-
 	if (waitqueue_active(&ctx->wait))
 		wake_up(&ctx->wait);
 
-	if (ret)
-		put_ioctx(ctx);
-
+	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
 	return ret;
 }
 
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 7cb2872..669dbe5 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -682,6 +682,15 @@
 			retval = PTR_ERR(interpreter);
 			if (IS_ERR(interpreter))
 				goto out_free_interp;
+
+			/*
+			 * If the binary is not readable then enforce
+			 * mm->dumpable = 0 regardless of the interpreter's
+			 * permissions.
+			 */
+			if (file_permission(interpreter, MAY_READ) < 0)
+				bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
 			retval = kernel_read(interpreter, 0, bprm->buf,
 					     BINPRM_BUF_SIZE);
 			if (retval != BINPRM_BUF_SIZE) {
@@ -1178,6 +1187,10 @@
  */
 static int maydump(struct vm_area_struct *vma)
 {
+	/* The vma can be set up to tell us the answer directly.  */
+	if (vma->vm_flags & VM_ALWAYSDUMP)
+		return 1;
+
 	/* Do not dump I/O mapped devices or special mappings */
 	if (vma->vm_flags & (VM_IO | VM_RESERVED))
 		return 0;
@@ -1424,6 +1437,32 @@
 	return sz;
 }
 
+static struct vm_area_struct *first_vma(struct task_struct *tsk,
+					struct vm_area_struct *gate_vma)
+{
+	struct vm_area_struct *ret = tsk->mm->mmap;
+
+	if (ret)
+		return ret;
+	return gate_vma;
+}
+/*
+ * Helper function for iterating across a vma list.  It ensures that the caller
+ * will visit `gate_vma' prior to terminating the search.
+ */
+static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
+					struct vm_area_struct *gate_vma)
+{
+	struct vm_area_struct *ret;
+
+	ret = this_vma->vm_next;
+	if (ret)
+		return ret;
+	if (this_vma == gate_vma)
+		return NULL;
+	return gate_vma;
+}
+
 /*
  * Actual dumper
  *
@@ -1439,7 +1478,7 @@
 	int segs;
 	size_t size = 0;
 	int i;
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *gate_vma;
 	struct elfhdr *elf = NULL;
 	loff_t offset = 0, dataoff, foffset;
 	unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1525,6 +1564,10 @@
 	segs += ELF_CORE_EXTRA_PHDRS;
 #endif
 
+	gate_vma = get_gate_vma(current);
+	if (gate_vma != NULL)
+		segs++;
+
 	/* Set up header */
 	fill_elf_header(elf, segs + 1);	/* including notes section */
 
@@ -1592,7 +1635,8 @@
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
 	/* Write program headers for segments dump */
-	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = first_vma(current, gate_vma); vma != NULL;
+			vma = next_vma(vma, gate_vma)) {
 		struct elf_phdr phdr;
 		size_t sz;
 
@@ -1641,7 +1685,8 @@
 	/* Align to page */
 	DUMP_SEEK(dataoff - foffset);
 
-	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = first_vma(current, gate_vma); vma != NULL;
+			vma = next_vma(vma, gate_vma)) {
 		unsigned long addr;
 
 		if (!maydump(vma))
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 6e6d456..a4d933a 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -234,6 +234,14 @@
 				goto error;
 			}
 
+			/*
+			 * If the binary is not readable then enforce
+			 * mm->dumpable = 0 regardless of the interpreter's
+			 * permissions.
+			 */
+			if (file_permission(interpreter, MAY_READ) < 0)
+				bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
 			retval = kernel_read(interpreter, 0, bprm->buf,
 					     BINPRM_BUF_SIZE);
 			if (retval < 0)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1715d6b..fc7028b6 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -129,6 +129,46 @@
 	return 0;
 }
 
+static int
+blkdev_get_blocks(struct inode *inode, sector_t iblock,
+		struct buffer_head *bh, int create)
+{
+	sector_t end_block = max_block(I_BDEV(inode));
+	unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
+
+	if ((iblock + max_blocks) > end_block) {
+		max_blocks = end_block - iblock;
+		if ((long)max_blocks <= 0) {
+			if (create)
+				return -EIO;	/* write fully beyond EOF */
+			/*
+			 * It is a read which is fully beyond EOF.  We return
+			 * a !buffer_mapped buffer
+			 */
+			max_blocks = 0;
+		}
+	}
+
+	bh->b_bdev = I_BDEV(inode);
+	bh->b_blocknr = iblock;
+	bh->b_size = max_blocks << inode->i_blkbits;
+	if (max_blocks)
+		set_buffer_mapped(bh);
+	return 0;
+}
+
+static ssize_t
+blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+			loff_t offset, unsigned long nr_segs)
+{
+	struct file *file = iocb->ki_filp;
+	struct inode *inode = file->f_mapping->host;
+
+	return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
+				iov, offset, nr_segs, blkdev_get_blocks, NULL);
+}
+
+#if 0
 static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error)
 {
 	struct kiocb *iocb = bio->bi_private;
@@ -146,7 +186,7 @@
 		iocb->ki_nbytes = -EIO;
 
 	if (atomic_dec_and_test(bio_count)) {
-		if (iocb->ki_nbytes < 0)
+		if ((long)iocb->ki_nbytes < 0)
 			aio_complete(iocb, iocb->ki_nbytes, 0);
 		else
 			aio_complete(iocb, iocb->ki_left, 0);
@@ -190,6 +230,12 @@
 	return pvec->page[pvec->idx++];
 }
 
+/* return a page back to pvec array */
+static void blk_unget_page(struct page *page, struct pvec *pvec)
+{
+	pvec->page[--pvec->idx] = page;
+}
+
 static ssize_t
 blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 		 loff_t pos, unsigned long nr_segs)
@@ -278,6 +324,8 @@
 				count = min(count, nbytes);
 				goto same_bio;
 			}
+		} else {
+			blk_unget_page(page, &pvec);
 		}
 
 		/* bio is ready, submit it */
@@ -315,6 +363,7 @@
 		return PTR_ERR(page);
 	goto completion;
 }
+#endif
 
 static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
 {
@@ -411,7 +460,7 @@
 	{
 		memset(bdev, 0, sizeof(*bdev));
 		mutex_init(&bdev->bd_mutex);
-		mutex_init(&bdev->bd_mount_mutex);
+		sema_init(&bdev->bd_mount_sem, 1);
 		INIT_LIST_HEAD(&bdev->bd_inodes);
 		INIT_LIST_HEAD(&bdev->bd_list);
 #ifdef CONFIG_SYSFS
diff --git a/fs/buffer.c b/fs/buffer.c
index 263f88e..1ad674f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -180,7 +180,7 @@
  * freeze_bdev  --  lock a filesystem and force it into a consistent state
  * @bdev:	blockdevice to lock
  *
- * This takes the block device bd_mount_mutex to make sure no new mounts
+ * This takes the block device bd_mount_sem to make sure no new mounts
  * happen on bdev until thaw_bdev() is called.
  * If a superblock is found on this device, we take the s_umount semaphore
  * on it to make sure nobody unmounts until the snapshot creation is done.
@@ -189,7 +189,7 @@
 {
 	struct super_block *sb;
 
-	mutex_lock(&bdev->bd_mount_mutex);
+	down(&bdev->bd_mount_sem);
 	sb = get_super(bdev);
 	if (sb && !(sb->s_flags & MS_RDONLY)) {
 		sb->s_frozen = SB_FREEZE_WRITE;
@@ -231,7 +231,7 @@
 		drop_super(sb);
 	}
 
-	mutex_unlock(&bdev->bd_mount_mutex);
+	up(&bdev->bd_mount_sem);
 }
 EXPORT_SYMBOL(thaw_bdev);
 
@@ -2834,7 +2834,7 @@
 	int ret = 0;
 
 	BUG_ON(!PageLocked(page));
-	if (PageDirty(page) || PageWriteback(page))
+	if (PageWriteback(page))
 		return 0;
 
 	if (mapping == NULL) {		/* can this still happen? */
@@ -2844,6 +2844,23 @@
 
 	spin_lock(&mapping->private_lock);
 	ret = drop_buffers(page, &buffers_to_free);
+
+	/*
+	 * If the filesystem writes its buffers by hand (eg ext3)
+	 * then we can have clean buffers against a dirty page.  We
+	 * clean the page here; otherwise the VM will never notice
+	 * that the filesystem did any IO at all.
+	 *
+	 * Also, during truncate, discard_buffer will have marked all
+	 * the page's buffers clean.  We discover that here and clean
+	 * the page also.
+	 *
+	 * private_lock must be held over this entire operation in order
+	 * to synchronise against __set_page_dirty_buffers and prevent the
+	 * dirty bit from being lost.
+	 */
+	if (ret)
+		cancel_dirty_page(page, PAGE_CACHE_SIZE);
 	spin_unlock(&mapping->private_lock);
 out:
 	if (buffers_to_free) {
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 3539d6e..85e3850 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,9 @@
+Version 1.47
+------------
+Fix oops in list_del during mount caused by unaligned string.
+Seek to SEEK_END forces check for update of file size for non-cached
+files.
+
 Version 1.46
 ------------
 Support deep tree mounts.  Better support OS/2, Win9x (DOS) time stamps.
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 96abeb7..6017c46 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -143,8 +143,8 @@
 		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
 		if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
 		   (ses->serverNOS == NULL)) {
-			buf += sprintf("\nentry for %s not fully displayed\n\t",
-					ses->serverName);
+			buf += sprintf(buf, "\nentry for %s not fully "
+					"displayed\n\t", ses->serverName);
 			
 		} else {
 			length =
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 10c9029..93ef099 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -511,7 +511,15 @@
 {
 	/* origin == SEEK_END => we must revalidate the cached file length */
 	if (origin == SEEK_END) {
-		int retval = cifs_revalidate(file->f_path.dentry);
+		int retval;
+
+		/* some applications poll for the file length in this strange
+		   way so we must seek to end on non-oplocked files by
+		   setting the revalidate time to zero */
+		if(file->f_path.dentry->d_inode)		
+			CIFS_I(file->f_path.dentry->d_inode)->time = 0;
+
+		retval = cifs_revalidate(file->f_path.dentry);
 		if (retval < 0)
 			return (loff_t)retval;
 	}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index a243f77..8aa66dc 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.46"
+#define CIFS_VERSION   "1.47"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8a49b2e..e9dcf5e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1146,7 +1146,7 @@
 	pgoff_t end;
 	pgoff_t index;
  	int range_whole = 0;
-	struct kvec iov[32];
+	struct kvec * iov;
 	int len;
 	int n_iov = 0;
 	pgoff_t next;
@@ -1171,15 +1171,21 @@
 	if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
 		if(cifs_sb->tcon->ses->server->secMode &
                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			if(!experimEnabled)
+			if(!experimEnabled) 
 				return generic_writepages(mapping, wbc);
 
+	iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
+	if(iov == NULL)
+		return generic_writepages(mapping, wbc);
+
+
 	/*
 	 * BB: Is this meaningful for a non-block-device file system?
 	 * If it is, we should test it again after we do I/O
 	 */
 	if (wbc->nonblocking && bdi_write_congested(bdi)) {
 		wbc->encountered_congestion = 1;
+		kfree(iov);
 		return 0;
 	}
 
@@ -1345,7 +1351,7 @@
 		mapping->writeback_index = index;
 
 	FreeXid(xid);
-
+	kfree(iov);
 	return rc;
 }
 
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index aedf683..19cc294 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -71,9 +71,7 @@
 {
 	struct cifsSesInfo *ret_buf;
 
-	ret_buf =
-	    (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
-					   GFP_KERNEL);
+	ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL);
 	if (ret_buf) {
 		write_lock(&GlobalSMBSeslock);
 		atomic_inc(&sesInfoAllocCount);
@@ -109,9 +107,7 @@
 tconInfoAlloc(void)
 {
 	struct cifsTconInfo *ret_buf;
-	ret_buf =
-	    (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
-					    GFP_KERNEL);
+	ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL);
 	if (ret_buf) {
 		write_lock(&GlobalSMBSeslock);
 		atomic_inc(&tconInfoAllocCount);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 99dfb53..782940b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -156,9 +156,9 @@
 		tmp_inode->i_atime = cnvrtDosUnixTm(
 				le16_to_cpu(pfindData->LastAccessDate),
 				le16_to_cpu(pfindData->LastAccessTime));
-                tmp_inode->i_ctime = cnvrtDosUnixTm(
-                                le16_to_cpu(pfindData->LastWriteDate),
-                                le16_to_cpu(pfindData->LastWriteTime));
+		tmp_inode->i_ctime = cnvrtDosUnixTm(
+				le16_to_cpu(pfindData->LastWriteDate),
+				le16_to_cpu(pfindData->LastWriteTime));
 		AdjustForTZ(cifs_sb->tcon, tmp_inode);
 		attr = le16_to_cpu(pfindData->Attributes);
 		allocation_size = le32_to_cpu(pfindData->AllocationSize);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index bbdda99..7584646 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -182,11 +182,14 @@
 	cFYI(1,("bleft %d",bleft));
 
 
-	/* word align, if bytes remaining is not even */
-	if(bleft % 2) {
-		bleft--;
-		data++;
-	}
+	/* SMB header is unaligned, so cifs servers word align start of
+	   Unicode strings */
+	data++;
+	bleft--; /* Windows servers do not always double null terminate
+		    their final Unicode string - in which case we
+		    now will not attempt to decode the byte of junk
+		    which follows it */
+		    
 	words_left = bleft / 2;
 
 	/* save off server operating system */
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index 7a1b2b9..1b1daf6 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -196,7 +196,7 @@
 	char c[28];
 	char d[28];
 	char *cd;
-	char ki[16][48];
+	char (*ki)[48];
 	char *pd1;
 	char l[32], r[32];
 	char *rl;
@@ -206,6 +206,12 @@
 	if(pk1 == NULL)
 		return;
 
+	ki = kmalloc(16*48, GFP_KERNEL);
+	if(ki == NULL) {
+		kfree(pk1);
+		return;
+	}
+
 	cd = pk1 + 56;
 	pd1= cd  + 56;
 	rl = pd1 + 64;
@@ -243,6 +249,7 @@
 		er = kmalloc(48+48+32+32+32, GFP_KERNEL);
 		if(er == NULL) {
 			kfree(pk1);
+			kfree(ki);
 			return;
 		}
 		erk = er+48;
@@ -290,6 +297,7 @@
 
 	permute(out, rl, perm6, 64);
 	kfree(pk1);
+	kfree(ki);
 }
 
 static void
diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig
index b5654a2..6fa7b0d 100644
--- a/fs/dlm/Kconfig
+++ b/fs/dlm/Kconfig
@@ -3,21 +3,21 @@
 
 config DLM
 	tristate "Distributed Lock Manager (DLM)"
-	depends on IPV6 || IPV6=n
+	depends on SYSFS && (IPV6 || IPV6=n)
 	select CONFIGFS_FS
 	select IP_SCTP if DLM_SCTP
 	help
-	A general purpose distributed lock manager for kernel or userspace
-	applications.
+	  A general purpose distributed lock manager for kernel or userspace
+	  applications.
 
 choice
 	prompt "Select DLM communications protocol"
 	depends on DLM
 	default DLM_TCP
 	help
-	The DLM Can use TCP or SCTP for it's network communications.
-	SCTP supports multi-homed operations whereas TCP doesn't.
-	However, SCTP seems to have stability problems at the moment.
+	  The DLM Can use TCP or SCTP for it's network communications.
+	  SCTP supports multi-homed operations whereas TCP doesn't.
+	  However, SCTP seems to have stability problems at the moment.
 
 config DLM_TCP
 	bool "TCP/IP"
@@ -31,8 +31,8 @@
 	bool "DLM debugging"
 	depends on DLM
 	help
-	Under the debugfs mount point, the name of each lockspace will
-	appear as a file in the "dlm" directory.  The output is the
-	list of resource and locks the local node knows about.
+	  Under the debugfs mount point, the name of each lockspace will
+	  appear as a file in the "dlm" directory.  The output is the
+	  list of resource and locks the local node knows about.
 
 endmenu
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 88553054..8665c88 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -54,6 +54,11 @@
 static void drop_node(struct config_group *, struct config_item *);
 static void release_node(struct config_item *);
 
+static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
+			    char *buf);
+static ssize_t store_cluster(struct config_item *i,
+			     struct configfs_attribute *a,
+			     const char *buf, size_t len);
 static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
 			 char *buf);
 static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
@@ -73,6 +78,101 @@
 static ssize_t node_weight_read(struct node *nd, char *buf);
 static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len);
 
+struct cluster {
+	struct config_group group;
+	unsigned int cl_tcp_port;
+	unsigned int cl_buffer_size;
+	unsigned int cl_rsbtbl_size;
+	unsigned int cl_lkbtbl_size;
+	unsigned int cl_dirtbl_size;
+	unsigned int cl_recover_timer;
+	unsigned int cl_toss_secs;
+	unsigned int cl_scan_secs;
+	unsigned int cl_log_debug;
+};
+
+enum {
+	CLUSTER_ATTR_TCP_PORT = 0,
+	CLUSTER_ATTR_BUFFER_SIZE,
+	CLUSTER_ATTR_RSBTBL_SIZE,
+	CLUSTER_ATTR_LKBTBL_SIZE,
+	CLUSTER_ATTR_DIRTBL_SIZE,
+	CLUSTER_ATTR_RECOVER_TIMER,
+	CLUSTER_ATTR_TOSS_SECS,
+	CLUSTER_ATTR_SCAN_SECS,
+	CLUSTER_ATTR_LOG_DEBUG,
+};
+
+struct cluster_attribute {
+	struct configfs_attribute attr;
+	ssize_t (*show)(struct cluster *, char *);
+	ssize_t (*store)(struct cluster *, const char *, size_t);
+};
+
+static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field,
+			   unsigned int *info_field, int check_zero,
+			   const char *buf, size_t len)
+{
+	unsigned int x;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	x = simple_strtoul(buf, NULL, 0);
+
+	if (check_zero && !x)
+		return -EINVAL;
+
+	*cl_field = x;
+	*info_field = x;
+
+	return len;
+}
+
+#define __CONFIGFS_ATTR(_name,_mode,_read,_write) {                           \
+	.attr   = { .ca_name = __stringify(_name),                            \
+		    .ca_mode = _mode,                                         \
+		    .ca_owner = THIS_MODULE },                                \
+	.show   = _read,                                                      \
+	.store  = _write,                                                     \
+}
+
+#define CLUSTER_ATTR(name, check_zero)                                        \
+static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len)  \
+{                                                                             \
+	return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
+			   check_zero, buf, len);                             \
+}                                                                             \
+static ssize_t name##_read(struct cluster *cl, char *buf)                     \
+{                                                                             \
+	return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
+}                                                                             \
+static struct cluster_attribute cluster_attr_##name =                         \
+__CONFIGFS_ATTR(name, 0644, name##_read, name##_write)
+
+CLUSTER_ATTR(tcp_port, 1);
+CLUSTER_ATTR(buffer_size, 1);
+CLUSTER_ATTR(rsbtbl_size, 1);
+CLUSTER_ATTR(lkbtbl_size, 1);
+CLUSTER_ATTR(dirtbl_size, 1);
+CLUSTER_ATTR(recover_timer, 1);
+CLUSTER_ATTR(toss_secs, 1);
+CLUSTER_ATTR(scan_secs, 1);
+CLUSTER_ATTR(log_debug, 0);
+
+static struct configfs_attribute *cluster_attrs[] = {
+	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
+	[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr,
+	[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr,
+	[CLUSTER_ATTR_LKBTBL_SIZE] = &cluster_attr_lkbtbl_size.attr,
+	[CLUSTER_ATTR_DIRTBL_SIZE] = &cluster_attr_dirtbl_size.attr,
+	[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr,
+	[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
+	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
+	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
+	NULL,
+};
+
 enum {
 	COMM_ATTR_NODEID = 0,
 	COMM_ATTR_LOCAL,
@@ -152,10 +252,6 @@
 	struct configfs_subsystem subsys;
 };
 
-struct cluster {
-	struct config_group group;
-};
-
 struct spaces {
 	struct config_group ss_group;
 };
@@ -197,6 +293,8 @@
 
 static struct configfs_item_operations cluster_ops = {
 	.release = release_cluster,
+	.show_attribute = show_cluster,
+	.store_attribute = store_cluster,
 };
 
 static struct configfs_group_operations spaces_ops = {
@@ -237,6 +335,7 @@
 
 static struct config_item_type cluster_type = {
 	.ct_item_ops = &cluster_ops,
+	.ct_attrs = cluster_attrs,
 	.ct_owner = THIS_MODULE,
 };
 
@@ -317,6 +416,16 @@
 	cl->group.default_groups[1] = &cms->cs_group;
 	cl->group.default_groups[2] = NULL;
 
+	cl->cl_tcp_port = dlm_config.ci_tcp_port;
+	cl->cl_buffer_size = dlm_config.ci_buffer_size;
+	cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size;
+	cl->cl_lkbtbl_size = dlm_config.ci_lkbtbl_size;
+	cl->cl_dirtbl_size = dlm_config.ci_dirtbl_size;
+	cl->cl_recover_timer = dlm_config.ci_recover_timer;
+	cl->cl_toss_secs = dlm_config.ci_toss_secs;
+	cl->cl_scan_secs = dlm_config.ci_scan_secs;
+	cl->cl_log_debug = dlm_config.ci_log_debug;
+
 	space_list = &sps->ss_group;
 	comm_list = &cms->cs_group;
 	return &cl->group;
@@ -509,6 +618,25 @@
  * Functions for user space to read/write attributes
  */
 
+static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
+			    char *buf)
+{
+	struct cluster *cl = to_cluster(i);
+	struct cluster_attribute *cla =
+			container_of(a, struct cluster_attribute, attr);
+	return cla->show ? cla->show(cl, buf) : 0;
+}
+
+static ssize_t store_cluster(struct config_item *i,
+			     struct configfs_attribute *a,
+			     const char *buf, size_t len)
+{
+	struct cluster *cl = to_cluster(i);
+	struct cluster_attribute *cla =
+		container_of(a, struct cluster_attribute, attr);
+	return cla->store ? cla->store(cl, buf, len) : -EINVAL;
+}
+
 static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
 			 char *buf)
 {
@@ -775,15 +903,17 @@
 #define DEFAULT_RECOVER_TIMER      5
 #define DEFAULT_TOSS_SECS         10
 #define DEFAULT_SCAN_SECS          5
+#define DEFAULT_LOG_DEBUG          0
 
 struct dlm_config_info dlm_config = {
-	.tcp_port = DEFAULT_TCP_PORT,
-	.buffer_size = DEFAULT_BUFFER_SIZE,
-	.rsbtbl_size = DEFAULT_RSBTBL_SIZE,
-	.lkbtbl_size = DEFAULT_LKBTBL_SIZE,
-	.dirtbl_size = DEFAULT_DIRTBL_SIZE,
-	.recover_timer = DEFAULT_RECOVER_TIMER,
-	.toss_secs = DEFAULT_TOSS_SECS,
-	.scan_secs = DEFAULT_SCAN_SECS
+	.ci_tcp_port = DEFAULT_TCP_PORT,
+	.ci_buffer_size = DEFAULT_BUFFER_SIZE,
+	.ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
+	.ci_lkbtbl_size = DEFAULT_LKBTBL_SIZE,
+	.ci_dirtbl_size = DEFAULT_DIRTBL_SIZE,
+	.ci_recover_timer = DEFAULT_RECOVER_TIMER,
+	.ci_toss_secs = DEFAULT_TOSS_SECS,
+	.ci_scan_secs = DEFAULT_SCAN_SECS,
+	.ci_log_debug = DEFAULT_LOG_DEBUG
 };
 
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 9da7839..1e97861 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -17,14 +17,15 @@
 #define DLM_MAX_ADDR_COUNT 3
 
 struct dlm_config_info {
-	int tcp_port;
-	int buffer_size;
-	int rsbtbl_size;
-	int lkbtbl_size;
-	int dirtbl_size;
-	int recover_timer;
-	int toss_secs;
-	int scan_secs;
+	int ci_tcp_port;
+	int ci_buffer_size;
+	int ci_rsbtbl_size;
+	int ci_lkbtbl_size;
+	int ci_dirtbl_size;
+	int ci_recover_timer;
+	int ci_toss_secs;
+	int ci_scan_secs;
+	int ci_log_debug;
 };
 
 extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 1ee8195..61d9320 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -41,6 +41,7 @@
 #include <asm/uaccess.h>
 
 #include <linux/dlm.h>
+#include "config.h"
 
 #define DLM_LOCKSPACE_LEN	64
 
@@ -69,12 +70,12 @@
 #define log_error(ls, fmt, args...) \
 	printk(KERN_ERR "dlm: %s: " fmt "\n", (ls)->ls_name , ##args)
 
-#define DLM_LOG_DEBUG
-#ifdef DLM_LOG_DEBUG
-#define log_debug(ls, fmt, args...) log_error(ls, fmt, ##args)
-#else
-#define log_debug(ls, fmt, args...)
-#endif
+#define log_debug(ls, fmt, args...) \
+do { \
+	if (dlm_config.ci_log_debug) \
+		printk(KERN_DEBUG "dlm: %s: " fmt "\n", \
+		       (ls)->ls_name , ##args); \
+} while (0)
 
 #define DLM_ASSERT(x, do) \
 { \
@@ -309,8 +310,8 @@
 
 /* dlm_header is first element of all structs sent between nodes */
 
-#define DLM_HEADER_MAJOR	0x00020000
-#define DLM_HEADER_MINOR	0x00000001
+#define DLM_HEADER_MAJOR	0x00030000
+#define DLM_HEADER_MINOR	0x00000000
 
 #define DLM_MSG			1
 #define DLM_RCOM		2
@@ -386,6 +387,8 @@
 	uint32_t		rc_type;	/* DLM_RCOM_ */
 	int			rc_result;	/* multi-purpose */
 	uint64_t		rc_id;		/* match reply with request */
+	uint64_t		rc_seq;		/* sender's ls_recover_seq */
+	uint64_t		rc_seq_reply;	/* remote ls_recover_seq */
 	char			rc_buf[0];
 };
 
@@ -523,6 +526,7 @@
 	spinlock_t		asts_spin;
 	struct list_head	locks;
 	spinlock_t		locks_spin;
+	struct list_head	unlocking;
 	wait_queue_head_t	wait;
 };
 
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 30878de..e725005 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -754,6 +754,11 @@
 	mutex_unlock(&ls->ls_waiters_mutex);
 }
 
+/* We clear the RESEND flag because we might be taking an lkb off the waiters
+   list as part of process_requestqueue (e.g. a lookup that has an optimized
+   request reply on the requestqueue) between dlm_recover_waiters_pre() which
+   set RESEND and dlm_recover_waiters_post() */
+
 static int _remove_from_waiters(struct dlm_lkb *lkb)
 {
 	int error = 0;
@@ -764,6 +769,7 @@
 		goto out;
 	}
 	lkb->lkb_wait_type = 0;
+	lkb->lkb_flags &= ~DLM_IFL_RESEND;
 	list_del(&lkb->lkb_wait_reply);
 	unhold_lkb(lkb);
  out:
@@ -810,7 +816,7 @@
 		list_for_each_entry_reverse(r, &ls->ls_rsbtbl[b].toss,
 					    res_hashchain) {
 			if (!time_after_eq(jiffies, r->res_toss_time +
-					   dlm_config.toss_secs * HZ))
+					   dlm_config.ci_toss_secs * HZ))
 				continue;
 			found = 1;
 			break;
@@ -2144,12 +2150,24 @@
 	if (lkb->lkb_astaddr)
 		ms->m_asts |= AST_COMP;
 
-	if (ms->m_type == DLM_MSG_REQUEST || ms->m_type == DLM_MSG_LOOKUP)
+	/* compare with switch in create_message; send_remove() doesn't
+	   use send_args() */
+
+	switch (ms->m_type) {
+	case DLM_MSG_REQUEST:
+	case DLM_MSG_LOOKUP:
 		memcpy(ms->m_extra, r->res_name, r->res_length);
-
-	else if (lkb->lkb_lvbptr)
+		break;
+	case DLM_MSG_CONVERT:
+	case DLM_MSG_UNLOCK:
+	case DLM_MSG_REQUEST_REPLY:
+	case DLM_MSG_CONVERT_REPLY:
+	case DLM_MSG_GRANT:
+		if (!lkb->lkb_lvbptr)
+			break;
 		memcpy(ms->m_extra, lkb->lkb_lvbptr, r->res_ls->ls_lvblen);
-
+		break;
+	}
 }
 
 static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype)
@@ -2418,8 +2436,12 @@
 
 	DLM_ASSERT(is_master_copy(lkb), dlm_print_lkb(lkb););
 
-	if (receive_lvb(ls, lkb, ms))
-		return -ENOMEM;
+	if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
+		/* lkb was just created so there won't be an lvb yet */
+		lkb->lkb_lvbptr = allocate_lvb(ls);
+		if (!lkb->lkb_lvbptr)
+			return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -3002,7 +3024,7 @@
 {
 	struct dlm_message *ms = (struct dlm_message *) hd;
 	struct dlm_ls *ls;
-	int error;
+	int error = 0;
 
 	if (!recovery)
 		dlm_message_in(ms);
@@ -3119,7 +3141,7 @@
  out:
 	dlm_put_lockspace(ls);
 	dlm_astd_wake();
-	return 0;
+	return error;
 }
 
 
@@ -3132,6 +3154,7 @@
 	if (middle_conversion(lkb)) {
 		hold_lkb(lkb);
 		ls->ls_stub_ms.m_result = -EINPROGRESS;
+		ls->ls_stub_ms.m_flags = lkb->lkb_flags;
 		_remove_from_waiters(lkb);
 		_receive_convert_reply(lkb, &ls->ls_stub_ms);
 
@@ -3205,6 +3228,7 @@
 		case DLM_MSG_UNLOCK:
 			hold_lkb(lkb);
 			ls->ls_stub_ms.m_result = -DLM_EUNLOCK;
+			ls->ls_stub_ms.m_flags = lkb->lkb_flags;
 			_remove_from_waiters(lkb);
 			_receive_unlock_reply(lkb, &ls->ls_stub_ms);
 			dlm_put_lkb(lkb);
@@ -3213,6 +3237,7 @@
 		case DLM_MSG_CANCEL:
 			hold_lkb(lkb);
 			ls->ls_stub_ms.m_result = -DLM_ECANCEL;
+			ls->ls_stub_ms.m_flags = lkb->lkb_flags;
 			_remove_from_waiters(lkb);
 			_receive_cancel_reply(lkb, &ls->ls_stub_ms);
 			dlm_put_lkb(lkb);
@@ -3571,6 +3596,14 @@
 	lock_rsb(r);
 
 	switch (error) {
+	case -EBADR:
+		/* There's a chance the new master received our lock before
+		   dlm_recover_master_reply(), this wouldn't happen if we did
+		   a barrier between recover_masters and recover_locks. */
+		log_debug(ls, "master copy not ready %x r %lx %s", lkb->lkb_id,
+			  (unsigned long)r, r->res_name);
+		dlm_send_rcom_lock(r, lkb);
+		goto out;
 	case -EEXIST:
 		log_debug(ls, "master copy exists %x", lkb->lkb_id);
 		/* fall through */
@@ -3585,7 +3618,7 @@
 	/* an ack for dlm_recover_locks() which waits for replies from
 	   all the locks it sends to new masters */
 	dlm_recovered_lock(r);
-
+ out:
 	unlock_rsb(r);
 	put_rsb(r);
 	dlm_put_lkb(lkb);
@@ -3610,7 +3643,7 @@
 	}
 
 	if (flags & DLM_LKF_VALBLK) {
-		ua->lksb.sb_lvbptr = kmalloc(DLM_USER_LVB_LEN, GFP_KERNEL);
+		ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL);
 		if (!ua->lksb.sb_lvbptr) {
 			kfree(ua);
 			__put_lkb(ls, lkb);
@@ -3679,7 +3712,7 @@
 	ua = (struct dlm_user_args *)lkb->lkb_astparam;
 
 	if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) {
-		ua->lksb.sb_lvbptr = kmalloc(DLM_USER_LVB_LEN, GFP_KERNEL);
+		ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL);
 		if (!ua->lksb.sb_lvbptr) {
 			error = -ENOMEM;
 			goto out_put;
@@ -3745,12 +3778,10 @@
 		goto out_put;
 
 	spin_lock(&ua->proc->locks_spin);
-	list_del_init(&lkb->lkb_ownqueue);
+	/* dlm_user_add_ast() may have already taken lkb off the proc list */
+	if (!list_empty(&lkb->lkb_ownqueue))
+		list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking);
 	spin_unlock(&ua->proc->locks_spin);
-
-	/* this removes the reference for the proc->locks list added by
-	   dlm_user_request */
-	unhold_lkb(lkb);
  out_put:
 	dlm_put_lkb(lkb);
  out:
@@ -3790,9 +3821,8 @@
 	/* this lkb was removed from the WAITING queue */
 	if (lkb->lkb_grmode == DLM_LOCK_IV) {
 		spin_lock(&ua->proc->locks_spin);
-		list_del_init(&lkb->lkb_ownqueue);
+		list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking);
 		spin_unlock(&ua->proc->locks_spin);
-		unhold_lkb(lkb);
 	}
  out_put:
 	dlm_put_lkb(lkb);
@@ -3853,11 +3883,6 @@
 	mutex_lock(&ls->ls_clear_proc_locks);
 
 	list_for_each_entry_safe(lkb, safe, &proc->locks, lkb_ownqueue) {
-		if (lkb->lkb_ast_type) {
-			list_del(&lkb->lkb_astqueue);
-			unhold_lkb(lkb);
-		}
-
 		list_del_init(&lkb->lkb_ownqueue);
 
 		if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) {
@@ -3874,6 +3899,20 @@
 
 		dlm_put_lkb(lkb);
 	}
+
+	/* in-progress unlocks */
+	list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) {
+		list_del_init(&lkb->lkb_ownqueue);
+		lkb->lkb_flags |= DLM_IFL_DEAD;
+		dlm_put_lkb(lkb);
+	}
+
+	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
+		list_del(&lkb->lkb_astqueue);
+		dlm_put_lkb(lkb);
+	}
+
 	mutex_unlock(&ls->ls_clear_proc_locks);
 	unlock_recovery(ls);
 }
+
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 59012b0..f40817b 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -236,7 +236,7 @@
 	while (!kthread_should_stop()) {
 		list_for_each_entry(ls, &lslist, ls_list)
 			dlm_scan_rsbs(ls);
-		schedule_timeout_interruptible(dlm_config.scan_secs * HZ);
+		schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
 	}
 	return 0;
 }
@@ -422,7 +422,7 @@
 	ls->ls_count = 0;
 	ls->ls_flags = 0;
 
-	size = dlm_config.rsbtbl_size;
+	size = dlm_config.ci_rsbtbl_size;
 	ls->ls_rsbtbl_size = size;
 
 	ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL);
@@ -434,7 +434,7 @@
 		rwlock_init(&ls->ls_rsbtbl[i].lock);
 	}
 
-	size = dlm_config.lkbtbl_size;
+	size = dlm_config.ci_lkbtbl_size;
 	ls->ls_lkbtbl_size = size;
 
 	ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL);
@@ -446,7 +446,7 @@
 		ls->ls_lkbtbl[i].counter = 1;
 	}
 
-	size = dlm_config.dirtbl_size;
+	size = dlm_config.ci_dirtbl_size;
 	ls->ls_dirtbl_size = size;
 
 	ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL);
@@ -489,7 +489,7 @@
 	mutex_init(&ls->ls_requestqueue_mutex);
 	mutex_init(&ls->ls_clear_proc_locks);
 
-	ls->ls_recover_buf = kmalloc(dlm_config.buffer_size, GFP_KERNEL);
+	ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
 	if (!ls->ls_recover_buf)
 		goto out_dirfree;
 
diff --git a/fs/dlm/lowcomms-sctp.c b/fs/dlm/lowcomms-sctp.c
index fe158d7..dc83a9d 100644
--- a/fs/dlm/lowcomms-sctp.c
+++ b/fs/dlm/lowcomms-sctp.c
@@ -72,6 +72,8 @@
 	struct list_head	writequeue; /* outgoing writequeue_entries */
 	spinlock_t		writequeue_lock;
 	int			nodeid;
+	struct work_struct      swork; /* Send workqueue */
+	struct work_struct      lwork; /* Locking workqueue */
 };
 
 static DEFINE_IDR(nodeinfo_idr);
@@ -96,6 +98,7 @@
 	atomic_t		waiting_requests;
 	struct cbuf		cb;
 	int                     eagain_flag;
+	struct work_struct      work; /* Send workqueue */
 };
 
 /* An entry waiting to be sent */
@@ -137,19 +140,23 @@
 static LIST_HEAD(write_nodes);
 static DEFINE_SPINLOCK(write_nodes_lock);
 
+
 /* Maximum number of incoming messages to process before
  * doing a schedule()
  */
 #define MAX_RX_MSG_COUNT 25
 
-/* Manage daemons */
-static struct task_struct *recv_task;
-static struct task_struct *send_task;
-static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_wait);
+/* Work queues */
+static struct workqueue_struct *recv_workqueue;
+static struct workqueue_struct *send_workqueue;
+static struct workqueue_struct *lock_workqueue;
 
 /* The SCTP connection */
 static struct connection sctp_con;
 
+static void process_send_sockets(struct work_struct *work);
+static void process_recv_sockets(struct work_struct *work);
+static void process_lock_request(struct work_struct *work);
 
 static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
 {
@@ -222,6 +229,8 @@
 	spin_lock_init(&ni->lock);
 	INIT_LIST_HEAD(&ni->writequeue);
 	spin_lock_init(&ni->writequeue_lock);
+	INIT_WORK(&ni->lwork, process_lock_request);
+	INIT_WORK(&ni->swork, process_send_sockets);
 	ni->nodeid = nodeid;
 
 	if (nodeid > max_nodeid)
@@ -249,11 +258,8 @@
 /* Data or notification available on socket */
 static void lowcomms_data_ready(struct sock *sk, int count_unused)
 {
-	atomic_inc(&sctp_con.waiting_requests);
 	if (test_and_set_bit(CF_READ_PENDING, &sctp_con.flags))
-		return;
-
-	wake_up_interruptible(&lowcomms_recv_wait);
+		queue_work(recv_workqueue, &sctp_con.work);
 }
 
 
@@ -361,10 +367,10 @@
 				spin_lock_bh(&write_nodes_lock);
 				list_add_tail(&ni->write_list, &write_nodes);
 				spin_unlock_bh(&write_nodes_lock);
+				queue_work(send_workqueue, &ni->swork);
 			}
 		}
 	}
-	wake_up_process(send_task);
 }
 
 /* Something happened to an association */
@@ -446,8 +452,8 @@
 				spin_lock_bh(&write_nodes_lock);
 				list_add_tail(&ni->write_list, &write_nodes);
 				spin_unlock_bh(&write_nodes_lock);
+				queue_work(send_workqueue, &ni->swork);
 			}
-			wake_up_process(send_task);
 		}
 		break;
 
@@ -580,8 +586,8 @@
 				spin_lock_bh(&write_nodes_lock);
 				list_add_tail(&ni->write_list, &write_nodes);
 				spin_unlock_bh(&write_nodes_lock);
+				queue_work(send_workqueue, &ni->swork);
 			}
-			wake_up_process(send_task);
 		}
 	}
 
@@ -590,6 +596,7 @@
 		return 0;
 
 	cbuf_add(&sctp_con.cb, ret);
+	// PJC: TODO: Add to node's workqueue....can we ??
 	ret = dlm_process_incoming_buffer(cpu_to_le32(sinfo->sinfo_ppid),
 					  page_address(sctp_con.rx_page),
 					  sctp_con.cb.base, sctp_con.cb.len,
@@ -635,7 +642,7 @@
 
 	if (result < 0)
 		log_print("Can't bind to port %d addr number %d",
-			  dlm_config.tcp_port, num);
+			  dlm_config.ci_tcp_port, num);
 
 	return result;
 }
@@ -711,7 +718,7 @@
 	/* Bind to all interfaces. */
 	for (i = 0; i < dlm_local_count; i++) {
 		memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr));
-		make_sockaddr(&localaddr, dlm_config.tcp_port, &addr_len);
+		make_sockaddr(&localaddr, dlm_config.ci_tcp_port, &addr_len);
 
 		result = add_bind_addr(&localaddr, addr_len, num);
 		if (result)
@@ -820,7 +827,8 @@
 		spin_lock_bh(&write_nodes_lock);
 		list_add_tail(&ni->write_list, &write_nodes);
 		spin_unlock_bh(&write_nodes_lock);
-		wake_up_process(send_task);
+
+		queue_work(send_workqueue, &ni->swork);
 	}
 	return;
 
@@ -863,7 +871,7 @@
 		return;
 	}
 
-	make_sockaddr(&rem_addr, dlm_config.tcp_port, &addrlen);
+	make_sockaddr(&rem_addr, dlm_config.ci_tcp_port, &addrlen);
 
 	outmessage.msg_name = &rem_addr;
 	outmessage.msg_namelen = addrlen;
@@ -1088,101 +1096,75 @@
 	return 0;
 }
 
-static int write_list_empty(void)
+// PJC: The work queue function for receiving.
+static void process_recv_sockets(struct work_struct *work)
 {
-	int status;
-
-	spin_lock_bh(&write_nodes_lock);
-	status = list_empty(&write_nodes);
-	spin_unlock_bh(&write_nodes_lock);
-
-	return status;
-}
-
-static int dlm_recvd(void *data)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	while (!kthread_should_stop()) {
+	if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) {
+		int ret;
 		int count = 0;
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&lowcomms_recv_wait, &wait);
-		if (!test_bit(CF_READ_PENDING, &sctp_con.flags))
-			cond_resched();
-		remove_wait_queue(&lowcomms_recv_wait, &wait);
-		set_current_state(TASK_RUNNING);
+		do {
+			ret = receive_from_sock();
 
-		if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) {
-			int ret;
-
-			do {
-				ret = receive_from_sock();
-
-				/* Don't starve out everyone else */
-				if (++count >= MAX_RX_MSG_COUNT) {
-					cond_resched();
-					count = 0;
-				}
-			} while (!kthread_should_stop() && ret >=0);
-		}
-		cond_resched();
+			/* Don't starve out everyone else */
+			if (++count >= MAX_RX_MSG_COUNT) {
+				cond_resched();
+				count = 0;
+			}
+		} while (!kthread_should_stop() && ret >=0);
 	}
-
-	return 0;
+	cond_resched();
 }
 
-static int dlm_sendd(void *data)
+// PJC: the work queue function for sending
+static void process_send_sockets(struct work_struct *work)
 {
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(sctp_con.sock->sk->sk_sleep, &wait);
-
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (write_list_empty())
-			cond_resched();
-		set_current_state(TASK_RUNNING);
-
-		if (sctp_con.eagain_flag) {
-			sctp_con.eagain_flag = 0;
-			refill_write_queue();
-		}
-		process_output_queue();
+	if (sctp_con.eagain_flag) {
+		sctp_con.eagain_flag = 0;
+		refill_write_queue();
 	}
+	process_output_queue();
+}
 
-	remove_wait_queue(sctp_con.sock->sk->sk_sleep, &wait);
-
-	return 0;
+// PJC: Process lock requests from a particular node.
+// TODO: can we optimise this out on UP ??
+static void process_lock_request(struct work_struct *work)
+{
 }
 
 static void daemons_stop(void)
 {
-	kthread_stop(recv_task);
-	kthread_stop(send_task);
+	destroy_workqueue(recv_workqueue);
+	destroy_workqueue(send_workqueue);
+	destroy_workqueue(lock_workqueue);
 }
 
 static int daemons_start(void)
 {
-	struct task_struct *p;
 	int error;
-
-	p = kthread_run(dlm_recvd, NULL, "dlm_recvd");
-	error = IS_ERR(p);
+	recv_workqueue = create_workqueue("dlm_recv");
+	error = IS_ERR(recv_workqueue);
 	if (error) {
-		log_print("can't start dlm_recvd %d", error);
+		log_print("can't start dlm_recv %d", error);
 		return error;
 	}
-	recv_task = p;
 
-	p = kthread_run(dlm_sendd, NULL, "dlm_sendd");
-	error = IS_ERR(p);
+	send_workqueue = create_singlethread_workqueue("dlm_send");
+	error = IS_ERR(send_workqueue);
 	if (error) {
-		log_print("can't start dlm_sendd %d", error);
-		kthread_stop(recv_task);
+		log_print("can't start dlm_send %d", error);
+		destroy_workqueue(recv_workqueue);
 		return error;
 	}
-	send_task = p;
+
+	lock_workqueue = create_workqueue("dlm_rlock");
+	error = IS_ERR(lock_workqueue);
+	if (error) {
+		log_print("can't start dlm_rlock %d", error);
+		destroy_workqueue(send_workqueue);
+		destroy_workqueue(recv_workqueue);
+		return error;
+	}
 
 	return 0;
 }
@@ -1194,6 +1176,8 @@
 {
 	int error;
 
+	INIT_WORK(&sctp_con.work, process_recv_sockets);
+
 	error = init_sock();
 	if (error)
 		goto fail_sock;
@@ -1224,4 +1208,3 @@
 	for (i = 0; i < dlm_local_count; i++)
 		kfree(dlm_local_addr[i]);
 }
-
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c
index 9be3a44..f1efd17 100644
--- a/fs/dlm/lowcomms-tcp.c
+++ b/fs/dlm/lowcomms-tcp.c
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -96,10 +96,7 @@
 struct connection {
 	struct socket *sock;	/* NULL if not connected */
 	uint32_t nodeid;	/* So we know who we are in the list */
-	struct rw_semaphore sock_sem; /* Stop connect races */
-	struct list_head read_list;   /* On this list when ready for reading */
-	struct list_head write_list;  /* On this list when ready for writing */
-	struct list_head state_list;  /* On this list when ready to connect */
+	struct mutex sock_mutex;
 	unsigned long flags;	/* bit 1,2 = We are on the read/write lists */
 #define CF_READ_PENDING 1
 #define CF_WRITE_PENDING 2
@@ -112,9 +109,10 @@
 	struct page *rx_page;
 	struct cbuf cb;
 	int retries;
-	atomic_t waiting_requests;
 #define MAX_CONNECT_RETRIES 3
 	struct connection *othercon;
+	struct work_struct rwork; /* Receive workqueue */
+	struct work_struct swork; /* Send workqueue */
 };
 #define sock2con(x) ((struct connection *)(x)->sk_user_data)
 
@@ -131,14 +129,9 @@
 
 static struct sockaddr_storage dlm_local_addr;
 
-/* Manage daemons */
-static struct task_struct *recv_task;
-static struct task_struct *send_task;
-
-static wait_queue_t lowcomms_send_waitq_head;
-static DECLARE_WAIT_QUEUE_HEAD(lowcomms_send_waitq);
-static wait_queue_t lowcomms_recv_waitq_head;
-static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_waitq);
+/* Work queues */
+static struct workqueue_struct *recv_workqueue;
+static struct workqueue_struct *send_workqueue;
 
 /* An array of pointers to connections, indexed by NODEID */
 static struct connection **connections;
@@ -146,17 +139,8 @@
 static struct kmem_cache *con_cache;
 static int conn_array_size;
 
-/* List of sockets that have reads pending */
-static LIST_HEAD(read_sockets);
-static DEFINE_SPINLOCK(read_sockets_lock);
-
-/* List of sockets which have writes pending */
-static LIST_HEAD(write_sockets);
-static DEFINE_SPINLOCK(write_sockets_lock);
-
-/* List of sockets which have connects pending */
-static LIST_HEAD(state_sockets);
-static DEFINE_SPINLOCK(state_sockets_lock);
+static void process_recv_sockets(struct work_struct *work);
+static void process_send_sockets(struct work_struct *work);
 
 static struct connection *nodeid2con(int nodeid, gfp_t allocation)
 {
@@ -186,9 +170,11 @@
 			goto finish;
 
 		con->nodeid = nodeid;
-		init_rwsem(&con->sock_sem);
+		mutex_init(&con->sock_mutex);
 		INIT_LIST_HEAD(&con->writequeue);
 		spin_lock_init(&con->writequeue_lock);
+		INIT_WORK(&con->swork, process_send_sockets);
+		INIT_WORK(&con->rwork, process_recv_sockets);
 
 		connections[nodeid] = con;
 	}
@@ -203,41 +189,22 @@
 {
 	struct connection *con = sock2con(sk);
 
-	atomic_inc(&con->waiting_requests);
-	if (test_and_set_bit(CF_READ_PENDING, &con->flags))
-		return;
-
-	spin_lock_bh(&read_sockets_lock);
-	list_add_tail(&con->read_list, &read_sockets);
-	spin_unlock_bh(&read_sockets_lock);
-
-	wake_up_interruptible(&lowcomms_recv_waitq);
+	if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+		queue_work(recv_workqueue, &con->rwork);
 }
 
 static void lowcomms_write_space(struct sock *sk)
 {
 	struct connection *con = sock2con(sk);
 
-	if (test_and_set_bit(CF_WRITE_PENDING, &con->flags))
-		return;
-
-	spin_lock_bh(&write_sockets_lock);
-	list_add_tail(&con->write_list, &write_sockets);
-	spin_unlock_bh(&write_sockets_lock);
-
-	wake_up_interruptible(&lowcomms_send_waitq);
+	if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+		queue_work(send_workqueue, &con->swork);
 }
 
 static inline void lowcomms_connect_sock(struct connection *con)
 {
-	if (test_and_set_bit(CF_CONNECT_PENDING, &con->flags))
-		return;
-
-	spin_lock_bh(&state_sockets_lock);
-	list_add_tail(&con->state_list, &state_sockets);
-	spin_unlock_bh(&state_sockets_lock);
-
-	wake_up_interruptible(&lowcomms_send_waitq);
+	if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags))
+		queue_work(send_workqueue, &con->swork);
 }
 
 static void lowcomms_state_change(struct sock *sk)
@@ -279,7 +246,7 @@
 /* Close a remote connection and tidy up */
 static void close_connection(struct connection *con, bool and_other)
 {
-	down_write(&con->sock_sem);
+	mutex_lock(&con->sock_mutex);
 
 	if (con->sock) {
 		sock_release(con->sock);
@@ -294,7 +261,7 @@
 		con->rx_page = NULL;
 	}
 	con->retries = 0;
-	up_write(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 }
 
 /* Data received from remote end */
@@ -308,10 +275,13 @@
 	int r;
 	int call_again_soon = 0;
 
-	down_read(&con->sock_sem);
+	mutex_lock(&con->sock_mutex);
 
-	if (con->sock == NULL)
-		goto out;
+	if (con->sock == NULL) {
+		ret = -EAGAIN;
+		goto out_close;
+	}
+
 	if (con->rx_page == NULL) {
 		/*
 		 * This doesn't need to be atomic, but I think it should
@@ -359,6 +329,9 @@
 
 	if (ret <= 0)
 		goto out_close;
+	if (ret == -EAGAIN)
+		goto out_resched;
+
 	if (ret == len)
 		call_again_soon = 1;
 	cbuf_add(&con->cb, ret);
@@ -381,24 +354,26 @@
 		con->rx_page = NULL;
 	}
 
-out:
 	if (call_again_soon)
 		goto out_resched;
-	up_read(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 	return 0;
 
 out_resched:
-	lowcomms_data_ready(con->sock->sk, 0);
-	up_read(&con->sock_sem);
-	cond_resched();
-	return 0;
+	if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+		queue_work(recv_workqueue, &con->rwork);
+	mutex_unlock(&con->sock_mutex);
+	return -EAGAIN;
 
 out_close:
-	up_read(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 	if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
 		close_connection(con, false);
 		/* Reconnect when there is something to send */
 	}
+	/* Don't return success if we really got EOF */
+	if (ret == 0)
+		ret = -EAGAIN;
 
 	return ret;
 }
@@ -412,6 +387,7 @@
 	int len;
 	int nodeid;
 	struct connection *newcon;
+	struct connection *addcon;
 
 	memset(&peeraddr, 0, sizeof(peeraddr));
 	result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM,
@@ -419,7 +395,7 @@
 	if (result < 0)
 		return -ENOMEM;
 
-	down_read(&con->sock_sem);
+	mutex_lock_nested(&con->sock_mutex, 0);
 
 	result = -ENOTCONN;
 	if (con->sock == NULL)
@@ -445,7 +421,7 @@
 	if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
 		printk("dlm: connect from non cluster node\n");
 		sock_release(newsock);
-		up_read(&con->sock_sem);
+		mutex_unlock(&con->sock_mutex);
 		return -1;
 	}
 
@@ -462,7 +438,7 @@
 		result = -ENOMEM;
 		goto accept_err;
 	}
-	down_write(&newcon->sock_sem);
+	mutex_lock_nested(&newcon->sock_mutex, 1);
 	if (newcon->sock) {
 		struct connection *othercon = newcon->othercon;
 
@@ -470,41 +446,45 @@
 			othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
 			if (!othercon) {
 				printk("dlm: failed to allocate incoming socket\n");
-				up_write(&newcon->sock_sem);
+				mutex_unlock(&newcon->sock_mutex);
 				result = -ENOMEM;
 				goto accept_err;
 			}
 			othercon->nodeid = nodeid;
 			othercon->rx_action = receive_from_sock;
-			init_rwsem(&othercon->sock_sem);
+			mutex_init(&othercon->sock_mutex);
+			INIT_WORK(&othercon->swork, process_send_sockets);
+			INIT_WORK(&othercon->rwork, process_recv_sockets);
 			set_bit(CF_IS_OTHERCON, &othercon->flags);
 			newcon->othercon = othercon;
 		}
 		othercon->sock = newsock;
 		newsock->sk->sk_user_data = othercon;
 		add_sock(newsock, othercon);
+		addcon = othercon;
 	}
 	else {
 		newsock->sk->sk_user_data = newcon;
 		newcon->rx_action = receive_from_sock;
 		add_sock(newsock, newcon);
-
+		addcon = newcon;
 	}
 
-	up_write(&newcon->sock_sem);
+	mutex_unlock(&newcon->sock_mutex);
 
 	/*
 	 * Add it to the active queue in case we got data
 	 * beween processing the accept adding the socket
 	 * to the read_sockets list
 	 */
-	lowcomms_data_ready(newsock->sk, 0);
-	up_read(&con->sock_sem);
+	if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
+		queue_work(recv_workqueue, &addcon->rwork);
+	mutex_unlock(&con->sock_mutex);
 
 	return 0;
 
 accept_err:
-	up_read(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 	sock_release(newsock);
 
 	if (result != -EAGAIN)
@@ -525,7 +505,7 @@
 		return;
 	}
 
-	down_write(&con->sock_sem);
+	mutex_lock(&con->sock_mutex);
 	if (con->retries++ > MAX_CONNECT_RETRIES)
 		goto out;
 
@@ -548,7 +528,7 @@
 	sock->sk->sk_user_data = con;
 	con->rx_action = receive_from_sock;
 
-	make_sockaddr(&saddr, dlm_config.tcp_port, &addr_len);
+	make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len);
 
 	add_sock(sock, con);
 
@@ -577,7 +557,7 @@
 		result = 0;
 	}
 out:
-	up_write(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 	return;
 }
 
@@ -616,10 +596,10 @@
 	con->sock = sock;
 
 	/* Bind to our port */
-	make_sockaddr(saddr, dlm_config.tcp_port, &addr_len);
+	make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
 	result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
 	if (result < 0) {
-		printk("dlm: Can't bind to port %d\n", dlm_config.tcp_port);
+		printk("dlm: Can't bind to port %d\n", dlm_config.ci_tcp_port);
 		sock_release(sock);
 		sock = NULL;
 		con->sock = NULL;
@@ -638,7 +618,7 @@
 
 	result = sock->ops->listen(sock, 5);
 	if (result < 0) {
-		printk("dlm: Can't listen on port %d\n", dlm_config.tcp_port);
+		printk("dlm: Can't listen on port %d\n", dlm_config.ci_tcp_port);
 		sock_release(sock);
 		sock = NULL;
 		goto create_out;
@@ -709,6 +689,7 @@
 	if (!con)
 		return NULL;
 
+	spin_lock(&con->writequeue_lock);
 	e = list_entry(con->writequeue.prev, struct writequeue_entry, list);
 	if ((&e->list == &con->writequeue) ||
 	    (PAGE_CACHE_SIZE - e->end < len)) {
@@ -747,6 +728,7 @@
 	struct connection *con = e->con;
 	int users;
 
+	spin_lock(&con->writequeue_lock);
 	users = --e->users;
 	if (users)
 		goto out;
@@ -754,12 +736,8 @@
 	kunmap(e->page);
 	spin_unlock(&con->writequeue_lock);
 
-	if (test_and_set_bit(CF_WRITE_PENDING, &con->flags) == 0) {
-		spin_lock_bh(&write_sockets_lock);
-		list_add_tail(&con->write_list, &write_sockets);
-		spin_unlock_bh(&write_sockets_lock);
-
-		wake_up_interruptible(&lowcomms_send_waitq);
+	if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
+		queue_work(send_workqueue, &con->swork);
 	}
 	return;
 
@@ -783,7 +761,7 @@
 	struct writequeue_entry *e;
 	int len, offset;
 
-	down_read(&con->sock_sem);
+	mutex_lock(&con->sock_mutex);
 	if (con->sock == NULL)
 		goto out_connect;
 
@@ -800,6 +778,7 @@
 		offset = e->offset;
 		BUG_ON(len == 0 && e->users == 0);
 		spin_unlock(&con->writequeue_lock);
+		kmap(e->page);
 
 		ret = 0;
 		if (len) {
@@ -828,18 +807,18 @@
 	}
 	spin_unlock(&con->writequeue_lock);
 out:
-	up_read(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 	return;
 
 send_error:
-	up_read(&con->sock_sem);
+	mutex_unlock(&con->sock_mutex);
 	close_connection(con, false);
 	lowcomms_connect_sock(con);
 	return;
 
 out_connect:
-	up_read(&con->sock_sem);
-	lowcomms_connect_sock(con);
+	mutex_unlock(&con->sock_mutex);
+	connect_to_sock(con);
 	return;
 }
 
@@ -872,7 +851,6 @@
 	if (con) {
 		clean_one_writequeue(con);
 		close_connection(con, true);
-		atomic_set(&con->waiting_requests, 0);
 	}
 	return 0;
 
@@ -880,102 +858,29 @@
 	return -1;
 }
 
-/* API send message call, may queue the request */
-/* N.B. This is the old interface - use the new one for new calls */
-int lowcomms_send_message(int nodeid, char *buf, int len, gfp_t allocation)
-{
-	struct writequeue_entry *e;
-	char *b;
-
-	e = dlm_lowcomms_get_buffer(nodeid, len, allocation, &b);
-	if (e) {
-		memcpy(b, buf, len);
-		dlm_lowcomms_commit_buffer(e);
-		return 0;
-	}
-	return -ENOBUFS;
-}
-
 /* Look for activity on active sockets */
-static void process_sockets(void)
+static void process_recv_sockets(struct work_struct *work)
 {
-	struct list_head *list;
-	struct list_head *temp;
-	int count = 0;
+	struct connection *con = container_of(work, struct connection, rwork);
+	int err;
 
-	spin_lock_bh(&read_sockets_lock);
-	list_for_each_safe(list, temp, &read_sockets) {
-
-		struct connection *con =
-			list_entry(list, struct connection, read_list);
-		list_del(&con->read_list);
-		clear_bit(CF_READ_PENDING, &con->flags);
-
-		spin_unlock_bh(&read_sockets_lock);
-
-		/* This can reach zero if we are processing requests
-		 * as they come in.
-		 */
-		if (atomic_read(&con->waiting_requests) == 0) {
-			spin_lock_bh(&read_sockets_lock);
-			continue;
-		}
-
-		do {
-			con->rx_action(con);
-
-			/* Don't starve out everyone else */
-			if (++count >= MAX_RX_MSG_COUNT) {
-				cond_resched();
-				count = 0;
-			}
-
-		} while (!atomic_dec_and_test(&con->waiting_requests) &&
-			 !kthread_should_stop());
-
-		spin_lock_bh(&read_sockets_lock);
-	}
-	spin_unlock_bh(&read_sockets_lock);
+	clear_bit(CF_READ_PENDING, &con->flags);
+	do {
+		err = con->rx_action(con);
+	} while (!err);
 }
 
-/* Try to send any messages that are pending
- */
-static void process_output_queue(void)
+
+static void process_send_sockets(struct work_struct *work)
 {
-	struct list_head *list;
-	struct list_head *temp;
+	struct connection *con = container_of(work, struct connection, swork);
 
-	spin_lock_bh(&write_sockets_lock);
-	list_for_each_safe(list, temp, &write_sockets) {
-		struct connection *con =
-			list_entry(list, struct connection, write_list);
-		clear_bit(CF_WRITE_PENDING, &con->flags);
-		list_del(&con->write_list);
-
-		spin_unlock_bh(&write_sockets_lock);
-		send_to_sock(con);
-		spin_lock_bh(&write_sockets_lock);
-	}
-	spin_unlock_bh(&write_sockets_lock);
-}
-
-static void process_state_queue(void)
-{
-	struct list_head *list;
-	struct list_head *temp;
-
-	spin_lock_bh(&state_sockets_lock);
-	list_for_each_safe(list, temp, &state_sockets) {
-		struct connection *con =
-			list_entry(list, struct connection, state_list);
-		list_del(&con->state_list);
-		clear_bit(CF_CONNECT_PENDING, &con->flags);
-		spin_unlock_bh(&state_sockets_lock);
-
+	if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
 		connect_to_sock(con);
-		spin_lock_bh(&state_sockets_lock);
 	}
-	spin_unlock_bh(&state_sockets_lock);
+
+	clear_bit(CF_WRITE_PENDING, &con->flags);
+	send_to_sock(con);
 }
 
 
@@ -992,109 +897,33 @@
 	}
 }
 
-static int read_list_empty(void)
+static void work_stop(void)
 {
-	int status;
-
-	spin_lock_bh(&read_sockets_lock);
-	status = list_empty(&read_sockets);
-	spin_unlock_bh(&read_sockets_lock);
-
-	return status;
+	destroy_workqueue(recv_workqueue);
+	destroy_workqueue(send_workqueue);
 }
 
-/* DLM Transport comms receive daemon */
-static int dlm_recvd(void *data)
+static int work_start(void)
 {
-	init_waitqueue_entry(&lowcomms_recv_waitq_head, current);
-	add_wait_queue(&lowcomms_recv_waitq, &lowcomms_recv_waitq_head);
-
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (read_list_empty())
-			cond_resched();
-		set_current_state(TASK_RUNNING);
-
-		process_sockets();
-	}
-
-	return 0;
-}
-
-static int write_and_state_lists_empty(void)
-{
-	int status;
-
-	spin_lock_bh(&write_sockets_lock);
-	status = list_empty(&write_sockets);
-	spin_unlock_bh(&write_sockets_lock);
-
-	spin_lock_bh(&state_sockets_lock);
-	if (list_empty(&state_sockets) == 0)
-		status = 0;
-	spin_unlock_bh(&state_sockets_lock);
-
-	return status;
-}
-
-/* DLM Transport send daemon */
-static int dlm_sendd(void *data)
-{
-	init_waitqueue_entry(&lowcomms_send_waitq_head, current);
-	add_wait_queue(&lowcomms_send_waitq, &lowcomms_send_waitq_head);
-
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (write_and_state_lists_empty())
-			cond_resched();
-		set_current_state(TASK_RUNNING);
-
-		process_state_queue();
-		process_output_queue();
-	}
-
-	return 0;
-}
-
-static void daemons_stop(void)
-{
-	kthread_stop(recv_task);
-	kthread_stop(send_task);
-}
-
-static int daemons_start(void)
-{
-	struct task_struct *p;
 	int error;
-
-	p = kthread_run(dlm_recvd, NULL, "dlm_recvd");
-	error = IS_ERR(p);
+	recv_workqueue = create_workqueue("dlm_recv");
+	error = IS_ERR(recv_workqueue);
 	if (error) {
-		log_print("can't start dlm_recvd %d", error);
+		log_print("can't start dlm_recv %d", error);
 		return error;
 	}
-	recv_task = p;
 
-	p = kthread_run(dlm_sendd, NULL, "dlm_sendd");
-	error = IS_ERR(p);
+	send_workqueue = create_singlethread_workqueue("dlm_send");
+	error = IS_ERR(send_workqueue);
 	if (error) {
-		log_print("can't start dlm_sendd %d", error);
-		kthread_stop(recv_task);
+		log_print("can't start dlm_send %d", error);
+		destroy_workqueue(recv_workqueue);
 		return error;
 	}
-	send_task = p;
 
 	return 0;
 }
 
-/*
- * Return the largest buffer size we can cope with.
- */
-int lowcomms_max_buffer_size(void)
-{
-	return PAGE_CACHE_SIZE;
-}
-
 void dlm_lowcomms_stop(void)
 {
 	int i;
@@ -1107,7 +936,7 @@
 			connections[i]->flags |= 0xFF;
 	}
 
-	daemons_stop();
+	work_stop();
 	clean_writequeues();
 
 	for (i = 0; i < conn_array_size; i++) {
@@ -1159,7 +988,7 @@
 	if (error)
 		goto fail_unlisten;
 
-	error = daemons_start();
+	error = work_start();
 	if (error)
 		goto fail_unlisten;
 
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c
index c9b1c3d..a5126e0 100644
--- a/fs/dlm/midcomms.c
+++ b/fs/dlm/midcomms.c
@@ -82,7 +82,7 @@
 		if (msglen < sizeof(struct dlm_header))
 			break;
 		err = -E2BIG;
-		if (msglen > dlm_config.buffer_size) {
+		if (msglen > dlm_config.ci_buffer_size) {
 			log_print("message size %d from %d too big, buf len %d",
 				  msglen, nodeid, len);
 			break;
@@ -103,7 +103,7 @@
 
 		if (msglen > sizeof(__tmp) &&
 		    msg == (struct dlm_header *) __tmp) {
-			msg = kmalloc(dlm_config.buffer_size, GFP_KERNEL);
+			msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
 			if (msg == NULL)
 				return ret;
 		}
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 4cc31be..6bfbd61 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -56,6 +56,10 @@
 
 	rc->rc_type = type;
 
+	spin_lock(&ls->ls_recover_lock);
+	rc->rc_seq = ls->ls_recover_seq;
+	spin_unlock(&ls->ls_recover_lock);
+
 	*mh_ret = mh;
 	*rc_ret = rc;
 	return 0;
@@ -78,8 +82,17 @@
 	rf->rf_lsflags = ls->ls_exflags;
 }
 
-static int check_config(struct dlm_ls *ls, struct rcom_config *rf, int nodeid)
+static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
 {
+	struct rcom_config *rf = (struct rcom_config *) rc->rc_buf;
+
+	if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) {
+		log_error(ls, "version mismatch: %x nodeid %d: %x",
+			  DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
+			  rc->rc_header.h_version);
+		return -EINVAL;
+	}
+
 	if (rf->rf_lvblen != ls->ls_lvblen ||
 	    rf->rf_lsflags != ls->ls_exflags) {
 		log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
@@ -125,7 +138,7 @@
 		goto out;
 
 	allow_sync_reply(ls, &rc->rc_id);
-	memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
+	memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
 
 	send_rcom(ls, mh, rc);
 
@@ -141,8 +154,7 @@
 		log_debug(ls, "remote node %d not ready", nodeid);
 		rc->rc_result = 0;
 	} else
-		error = check_config(ls, (struct rcom_config *) rc->rc_buf,
-				     nodeid);
+		error = check_config(ls, rc, nodeid);
 	/* the caller looks at rc_result for the remote recovery status */
  out:
 	return error;
@@ -159,6 +171,7 @@
 	if (error)
 		return;
 	rc->rc_id = rc_in->rc_id;
+	rc->rc_seq_reply = rc_in->rc_seq;
 	rc->rc_result = dlm_recover_status(ls);
 	make_config(ls, (struct rcom_config *) rc->rc_buf);
 
@@ -200,7 +213,7 @@
 	if (nodeid == dlm_our_nodeid()) {
 		dlm_copy_master_names(ls, last_name, last_len,
 		                      ls->ls_recover_buf + len,
-		                      dlm_config.buffer_size - len, nodeid);
+		                      dlm_config.ci_buffer_size - len, nodeid);
 		goto out;
 	}
 
@@ -210,7 +223,7 @@
 	memcpy(rc->rc_buf, last_name, last_len);
 
 	allow_sync_reply(ls, &rc->rc_id);
-	memset(ls->ls_recover_buf, 0, dlm_config.buffer_size);
+	memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
 
 	send_rcom(ls, mh, rc);
 
@@ -224,30 +237,17 @@
 {
 	struct dlm_rcom *rc;
 	struct dlm_mhandle *mh;
-	int error, inlen, outlen;
-	int nodeid = rc_in->rc_header.h_nodeid;
-	uint32_t status = dlm_recover_status(ls);
-
-	/*
-	 * We can't run dlm_dir_rebuild_send (which uses ls_nodes) while
-	 * dlm_recoverd is running ls_nodes_reconfig (which changes ls_nodes).
-	 * It could only happen in rare cases where we get a late NAMES
-	 * message from a previous instance of recovery.
-	 */
-
-	if (!(status & DLM_RS_NODES)) {
-		log_debug(ls, "ignoring RCOM_NAMES from %u", nodeid);
-		return;
-	}
+	int error, inlen, outlen, nodeid;
 
 	nodeid = rc_in->rc_header.h_nodeid;
 	inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
-	outlen = dlm_config.buffer_size - sizeof(struct dlm_rcom);
+	outlen = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom);
 
 	error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh);
 	if (error)
 		return;
 	rc->rc_id = rc_in->rc_id;
+	rc->rc_seq_reply = rc_in->rc_seq;
 
 	dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen,
 			      nodeid);
@@ -294,6 +294,7 @@
 		ret_nodeid = error;
 	rc->rc_result = ret_nodeid;
 	rc->rc_id = rc_in->rc_id;
+	rc->rc_seq_reply = rc_in->rc_seq;
 
 	send_rcom(ls, mh, rc);
 }
@@ -375,20 +376,13 @@
 
 	memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock));
 	rc->rc_id = rc_in->rc_id;
+	rc->rc_seq_reply = rc_in->rc_seq;
 
 	send_rcom(ls, mh, rc);
 }
 
 static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 {
-	uint32_t status = dlm_recover_status(ls);
-
-	if (!(status & DLM_RS_DIR)) {
-		log_debug(ls, "ignoring RCOM_LOCK_REPLY from %u",
-			  rc_in->rc_header.h_nodeid);
-		return;
-	}
-
 	dlm_recover_process_copy(ls, rc_in);
 }
 
@@ -415,6 +409,7 @@
 
 	rc->rc_type = DLM_RCOM_STATUS_REPLY;
 	rc->rc_id = rc_in->rc_id;
+	rc->rc_seq_reply = rc_in->rc_seq;
 	rc->rc_result = -ESRCH;
 
 	rf = (struct rcom_config *) rc->rc_buf;
@@ -426,6 +421,31 @@
 	return 0;
 }
 
+static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
+{
+	uint64_t seq;
+	int rv = 0;
+
+	switch (rc->rc_type) {
+	case DLM_RCOM_STATUS_REPLY:
+	case DLM_RCOM_NAMES_REPLY:
+	case DLM_RCOM_LOOKUP_REPLY:
+	case DLM_RCOM_LOCK_REPLY:
+		spin_lock(&ls->ls_recover_lock);
+		seq = ls->ls_recover_seq;
+		spin_unlock(&ls->ls_recover_lock);
+		if (rc->rc_seq_reply != seq) {
+			log_debug(ls, "ignoring old reply %x from %d "
+				      "seq_reply %llx expect %llx",
+				      rc->rc_type, rc->rc_header.h_nodeid,
+				      (unsigned long long)rc->rc_seq_reply,
+				      (unsigned long long)seq);
+			rv = 1;
+		}
+	}
+	return rv;
+}
+
 /* Called by dlm_recvd; corresponds to dlm_receive_message() but special
    recovery-only comms are sent through here. */
 
@@ -449,11 +469,14 @@
 	}
 
 	if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
-		log_error(ls, "ignoring recovery message %x from %d",
+		log_debug(ls, "ignoring recovery message %x from %d",
 			  rc->rc_type, nodeid);
 		goto out;
 	}
 
+	if (is_old_reply(ls, rc))
+		goto out;
+
 	if (nodeid != rc->rc_header.h_nodeid) {
 		log_error(ls, "bad rcom nodeid %d from %d",
 			  rc->rc_header.h_nodeid, nodeid);
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index cf9f683..c2cc769 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -44,7 +44,7 @@
 static void dlm_wait_timer_fn(unsigned long data)
 {
 	struct dlm_ls *ls = (struct dlm_ls *) data;
-	mod_timer(&ls->ls_timer, jiffies + (dlm_config.recover_timer * HZ));
+	mod_timer(&ls->ls_timer, jiffies + (dlm_config.ci_recover_timer * HZ));
 	wake_up(&ls->ls_wait_general);
 }
 
@@ -55,7 +55,7 @@
 	init_timer(&ls->ls_timer);
 	ls->ls_timer.function = dlm_wait_timer_fn;
 	ls->ls_timer.data = (long) ls;
-	ls->ls_timer.expires = jiffies + (dlm_config.recover_timer * HZ);
+	ls->ls_timer.expires = jiffies + (dlm_config.ci_recover_timer * HZ);
 	add_timer(&ls->ls_timer);
 
 	wait_event(ls->ls_wait_general, testfn(ls) || dlm_recovery_stopped(ls));
@@ -397,7 +397,9 @@
 
 		if (dlm_no_directory(ls))
 			count += recover_master_static(r);
-		else if (!is_master(r) && dlm_is_removed(ls, r->res_nodeid)) {
+		else if (!is_master(r) &&
+			 (dlm_is_removed(ls, r->res_nodeid) ||
+			  rsb_flag(r, RSB_NEW_MASTER))) {
 			recover_master(r);
 			count++;
 		}
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 650536aa..3cb636d 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -77,7 +77,7 @@
 
 	error = dlm_recover_members(ls, rv, &neg);
 	if (error) {
-		log_error(ls, "recover_members failed %d", error);
+		log_debug(ls, "recover_members failed %d", error);
 		goto fail;
 	}
 	start = jiffies;
@@ -89,7 +89,7 @@
 
 	error = dlm_recover_directory(ls);
 	if (error) {
-		log_error(ls, "recover_directory failed %d", error);
+		log_debug(ls, "recover_directory failed %d", error);
 		goto fail;
 	}
 
@@ -99,7 +99,7 @@
 
 	error = dlm_recover_directory_wait(ls);
 	if (error) {
-		log_error(ls, "recover_directory_wait failed %d", error);
+		log_debug(ls, "recover_directory_wait failed %d", error);
 		goto fail;
 	}
 
@@ -129,7 +129,7 @@
 
 		error = dlm_recover_masters(ls);
 		if (error) {
-			log_error(ls, "recover_masters failed %d", error);
+			log_debug(ls, "recover_masters failed %d", error);
 			goto fail;
 		}
 
@@ -139,13 +139,13 @@
 
 		error = dlm_recover_locks(ls);
 		if (error) {
-			log_error(ls, "recover_locks failed %d", error);
+			log_debug(ls, "recover_locks failed %d", error);
 			goto fail;
 		}
 
 		error = dlm_recover_locks_wait(ls);
 		if (error) {
-			log_error(ls, "recover_locks_wait failed %d", error);
+			log_debug(ls, "recover_locks_wait failed %d", error);
 			goto fail;
 		}
 
@@ -166,7 +166,7 @@
 
 		error = dlm_recover_locks_wait(ls);
 		if (error) {
-			log_error(ls, "recover_locks_wait failed %d", error);
+			log_debug(ls, "recover_locks_wait failed %d", error);
 			goto fail;
 		}
 	}
@@ -184,7 +184,7 @@
 	dlm_set_recover_status(ls, DLM_RS_DONE);
 	error = dlm_recover_done_wait(ls);
 	if (error) {
-		log_error(ls, "recover_done_wait failed %d", error);
+		log_debug(ls, "recover_done_wait failed %d", error);
 		goto fail;
 	}
 
@@ -192,19 +192,19 @@
 
 	error = enable_locking(ls, rv->seq);
 	if (error) {
-		log_error(ls, "enable_locking failed %d", error);
+		log_debug(ls, "enable_locking failed %d", error);
 		goto fail;
 	}
 
 	error = dlm_process_requestqueue(ls);
 	if (error) {
-		log_error(ls, "process_requestqueue failed %d", error);
+		log_debug(ls, "process_requestqueue failed %d", error);
 		goto fail;
 	}
 
 	error = dlm_recover_waiters_post(ls);
 	if (error) {
-		log_error(ls, "recover_waiters_post failed %d", error);
+		log_debug(ls, "recover_waiters_post failed %d", error);
 		goto fail;
 	}
 
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index c37e93e..d378b7f 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -180,6 +180,14 @@
 	    ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue))
 		remove_ownqueue = 1;
 
+	/* unlocks or cancels of waiting requests need to be removed from the
+	   proc's unlocking list, again there must be a better way...  */
+
+	if (ua->lksb.sb_status == -DLM_EUNLOCK ||
+	    (ua->lksb.sb_status == -DLM_ECANCEL &&
+	     lkb->lkb_grmode == DLM_LOCK_IV))
+		remove_ownqueue = 1;
+
 	/* We want to copy the lvb to userspace when the completion
 	   ast is read if the status is 0, the lock has an lvb and
 	   lvb_ops says we should.  We could probably have set_lvb_lock()
@@ -523,6 +531,7 @@
 	proc->lockspace = ls->ls_local_handle;
 	INIT_LIST_HEAD(&proc->asts);
 	INIT_LIST_HEAD(&proc->locks);
+	INIT_LIST_HEAD(&proc->unlocking);
 	spin_lock_init(&proc->asts_spin);
 	spin_lock_init(&proc->locks_spin);
 	init_waitqueue_head(&proc->wait);
diff --git a/fs/dlm/util.c b/fs/dlm/util.c
index 767197d..963889c 100644
--- a/fs/dlm/util.c
+++ b/fs/dlm/util.c
@@ -134,6 +134,8 @@
 	rc->rc_type		= cpu_to_le32(rc->rc_type);
 	rc->rc_result		= cpu_to_le32(rc->rc_result);
 	rc->rc_id		= cpu_to_le64(rc->rc_id);
+	rc->rc_seq		= cpu_to_le64(rc->rc_seq);
+	rc->rc_seq_reply	= cpu_to_le64(rc->rc_seq_reply);
 
 	if (type == DLM_RCOM_LOCK)
 		rcom_lock_out((struct rcom_lock *) rc->rc_buf);
@@ -151,6 +153,8 @@
 	rc->rc_type		= le32_to_cpu(rc->rc_type);
 	rc->rc_result		= le32_to_cpu(rc->rc_result);
 	rc->rc_id		= le64_to_cpu(rc->rc_id);
+	rc->rc_seq		= le64_to_cpu(rc->rc_seq);
+	rc->rc_seq_reply	= le64_to_cpu(rc->rc_seq_reply);
 
 	if (rc->rc_type == DLM_RCOM_LOCK)
 		rcom_lock_in((struct rcom_lock *) rc->rc_buf);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index c403b66..a4b142a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -251,8 +251,19 @@
 		WARN_ON(inode->i_state & I_WILL_FREE);
 
 	if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) {
+		struct address_space *mapping = inode->i_mapping;
+		int ret;
+
 		list_move(&inode->i_list, &inode->i_sb->s_dirty);
-		return 0;
+
+		/*
+		 * Even if we don't actually write the inode itself here,
+		 * we can at least start some of the data writeout..
+		 */
+		spin_unlock(&inode_lock);
+		ret = do_writepages(mapping, wbc);
+		spin_lock(&inode_lock);
+		return ret;
 	}
 
 	/*
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 8c58bd4..1794305 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -193,8 +193,12 @@
 
 static void fuse_ctl_kill_sb(struct super_block *sb)
 {
+	struct fuse_conn *fc;
+
 	mutex_lock(&fuse_mutex);
 	fuse_control_sb = NULL;
+	list_for_each_entry(fc, &fuse_conn_list, entry)
+		fc->ctl_ndents = 0;
 	mutex_unlock(&fuse_mutex);
 
 	kill_litter_super(sb);
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index 6a2ffa2..de8e64c 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -4,44 +4,43 @@
 	select FS_POSIX_ACL
 	select CRC32
 	help
-	A cluster filesystem.
+	  A cluster filesystem.
 
-	Allows a cluster of computers to simultaneously use a block device
-	that is shared between them (with FC, iSCSI, NBD, etc...).  GFS reads
-	and writes to the block device like a local filesystem, but also uses
-	a lock module to allow the computers coordinate their I/O so
-	filesystem consistency is maintained.  One of the nifty features of
-	GFS is perfect consistency -- changes made to the filesystem on one
-	machine show up immediately on all other machines in the cluster.
+	  Allows a cluster of computers to simultaneously use a block device
+	  that is shared between them (with FC, iSCSI, NBD, etc...).  GFS reads
+	  and writes to the block device like a local filesystem, but also uses
+	  a lock module to allow the computers coordinate their I/O so
+	  filesystem consistency is maintained.  One of the nifty features of
+	  GFS is perfect consistency -- changes made to the filesystem on one
+	  machine show up immediately on all other machines in the cluster.
 
-	To use the GFS2 filesystem, you will need to enable one or more of
-	the below locking modules. Documentation and utilities for GFS2 can
-	be found here: http://sources.redhat.com/cluster
+	  To use the GFS2 filesystem, you will need to enable one or more of
+	  the below locking modules. Documentation and utilities for GFS2 can
+	  be found here: http://sources.redhat.com/cluster
 
 config GFS2_FS_LOCKING_NOLOCK
 	tristate "GFS2 \"nolock\" locking module"
 	depends on GFS2_FS
 	help
-	Single node locking module for GFS2.
+	  Single node locking module for GFS2.
 
-	Use this module if you want to use GFS2 on a single node without
-	its clustering features. You can still take advantage of the
-	large file support, and upgrade to running a full cluster later on
-	if required.
+	  Use this module if you want to use GFS2 on a single node without
+	  its clustering features. You can still take advantage of the
+	  large file support, and upgrade to running a full cluster later on
+	  if required.
 
-	If you will only be using GFS2 in cluster mode, you do not need this
-	module.
+	  If you will only be using GFS2 in cluster mode, you do not need this
+	  module.
 
 config GFS2_FS_LOCKING_DLM
 	tristate "GFS2 DLM locking module"
-	depends on GFS2_FS && NET && INET && (IPV6 || IPV6=n)
+	depends on GFS2_FS && SYSFS && NET && INET && (IPV6 || IPV6=n)
 	select IP_SCTP if DLM_SCTP
 	select CONFIGFS_FS
 	select DLM
 	help
-	Multiple node locking module for GFS2
+	  Multiple node locking module for GFS2
 
-	Most users of GFS2 will require this module. It provides the locking
-	interface between GFS2 and the DLM, which is required to use GFS2
-	in a cluster environment.
-
+	  Most users of GFS2 will require this module. It provides the locking
+	  interface between GFS2 and the DLM, which is required to use GFS2
+	  in a cluster environment.
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 8240c1f..113f6c9 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -773,7 +773,7 @@
 			gfs2_free_data(ip, bstart, blen);
 	}
 
-	ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 
 	gfs2_dinode_out(ip, dibh->b_data);
 
@@ -848,7 +848,7 @@
 	}
 
 	ip->i_di.di_size = size;
-	ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (error)
@@ -963,7 +963,7 @@
 
 	if (gfs2_is_stuffed(ip)) {
 		ip->i_di.di_size = size;
-		ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -975,7 +975,7 @@
 
 		if (!error) {
 			ip->i_di.di_size = size;
-			ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 			ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
 			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 			gfs2_dinode_out(ip, dibh->b_data);
@@ -1048,7 +1048,7 @@
 			ip->i_num.no_addr;
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 	}
-	ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 	ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 0fdcb77..c93ca8f 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -131,7 +131,7 @@
 	memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
 	if (ip->i_di.di_size < offset + size)
 		ip->i_di.di_size = offset + size;
-	ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 	gfs2_dinode_out(ip, dibh->b_data);
 
 	brelse(dibh);
@@ -229,7 +229,7 @@
 
 	if (ip->i_di.di_size < offset + copied)
 		ip->i_di.di_size = offset + copied;
-	ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
@@ -1198,12 +1198,11 @@
  */
 
 static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
-			   void *opaque, gfs2_filldir_t filldir,
+			   void *opaque, filldir_t filldir,
 			   const struct gfs2_dirent **darr, u32 entries,
 			   int *copied)
 {
 	const struct gfs2_dirent *dent, *dent_next;
-	struct gfs2_inum_host inum;
 	u64 off, off_next;
 	unsigned int x, y;
 	int run = 0;
@@ -1240,11 +1239,9 @@
 			*offset = off;
 		}
 
-		gfs2_inum_in(&inum, (char *)&dent->de_inum);
-
 		error = filldir(opaque, (const char *)(dent + 1),
 				be16_to_cpu(dent->de_name_len),
-				off, &inum,
+				off, be64_to_cpu(dent->de_inum.no_addr),
 				be16_to_cpu(dent->de_type));
 		if (error)
 			return 1;
@@ -1262,8 +1259,8 @@
 }
 
 static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
-			      gfs2_filldir_t filldir, int *copied,
-			      unsigned *depth, u64 leaf_no)
+			      filldir_t filldir, int *copied, unsigned *depth,
+			      u64 leaf_no)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct buffer_head *bh;
@@ -1343,7 +1340,7 @@
  */
 
 static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
-		      gfs2_filldir_t filldir)
+		      filldir_t filldir)
 {
 	struct gfs2_inode *dip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -1402,7 +1399,7 @@
 }
 
 int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
-		  gfs2_filldir_t filldir)
+		  filldir_t filldir)
 {
 	struct gfs2_inode *dip = GFS2_I(inode);
 	struct dirent_gather g;
@@ -1568,7 +1565,7 @@
 				break;
 			gfs2_trans_add_bh(ip->i_gl, bh, 1);
 			ip->i_di.di_entries++;
-			ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 			gfs2_dinode_out(ip, bh->b_data);
 			brelse(bh);
 			error = 0;
@@ -1654,7 +1651,7 @@
 		gfs2_consist_inode(dip);
 	gfs2_trans_add_bh(dip->i_gl, bh, 1);
 	dip->i_di.di_entries--;
-	dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds();
+	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
 	gfs2_dinode_out(dip, bh->b_data);
 	brelse(bh);
 	mark_inode_dirty(&dip->i_inode);
@@ -1702,7 +1699,7 @@
 		gfs2_trans_add_bh(dip->i_gl, bh, 1);
 	}
 
-	dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds();
+	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
 	gfs2_dinode_out(dip, bh->b_data);
 	brelse(bh);
 	return 0;
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index b21b336..48fe890 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,30 +16,13 @@
 struct gfs2_inode;
 struct gfs2_inum;
 
-/**
- * gfs2_filldir_t - Report a directory entry to the caller of gfs2_dir_read()
- * @opaque: opaque data used by the function
- * @name: the name of the directory entry
- * @length: the length of the name
- * @offset: the entry's offset in the directory
- * @inum: the inode number the entry points to
- * @type: the type of inode the entry points to
- *
- * Returns: 0 on success, 1 if buffer full
- */
-
-typedef int (*gfs2_filldir_t) (void *opaque,
-			      const char *name, unsigned int length,
-			      u64 offset,
-			      struct gfs2_inum_host *inum, unsigned int type);
-
 int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
 		    struct gfs2_inum_host *inum, unsigned int *type);
 int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
 		 const struct gfs2_inum_host *inum, unsigned int type);
 int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
-int gfs2_dir_read(struct inode *inode, u64 * offset, void *opaque,
-		  gfs2_filldir_t filldir);
+int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
+		  filldir_t filldir);
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
 		   struct gfs2_inum_host *new_inum, unsigned int new_type);
 
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index ebebbdc..0c83c7f 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -301,7 +301,7 @@
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (!error) {
-		ip->i_inode.i_ctime.tv_sec = get_seconds();
+		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -718,7 +718,7 @@
 					    (er->er_mode & S_IFMT));
 			ip->i_inode.i_mode = er->er_mode;
 		}
-		ip->i_inode.i_ctime.tv_sec = get_seconds();
+		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -853,7 +853,7 @@
 			(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
 		ip->i_inode.i_mode = er->er_mode;
 	}
-	ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
 	brelse(dibh);
@@ -1134,7 +1134,7 @@
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (!error) {
-		ip->i_inode.i_ctime.tv_sec = get_seconds();
+		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 4381469..6618c11 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -19,6 +19,8 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/list.h>
 #include <linux/lm_interface.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -33,11 +35,6 @@
 #include "super.h"
 #include "util.h"
 
-struct greedy {
-	struct gfs2_holder gr_gh;
-	struct delayed_work gr_work;
-};
-
 struct gfs2_gl_hash_bucket {
         struct hlist_head hb_list;
 };
@@ -47,6 +44,9 @@
 static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
 static int dump_glock(struct gfs2_glock *gl);
 static int dump_inode(struct gfs2_inode *ip);
+static void gfs2_glock_xmote_th(struct gfs2_holder *gh);
+static void gfs2_glock_drop_th(struct gfs2_glock *gl);
+static DECLARE_RWSEM(gfs2_umount_flush_sem);
 
 #define GFS2_GL_HASH_SHIFT      15
 #define GFS2_GL_HASH_SIZE       (1 << GFS2_GL_HASH_SHIFT)
@@ -213,30 +213,6 @@
 }
 
 /**
- * queue_empty - check to see if a glock's queue is empty
- * @gl: the glock
- * @head: the head of the queue to check
- *
- * This function protects the list in the event that a process already
- * has a holder on the list and is adding a second holder for itself.
- * The glmutex lock is what generally prevents processes from working
- * on the same glock at once, but the special case of adding a second
- * holder for yourself ("recursive" locking) doesn't involve locking
- * glmutex, making the spin lock necessary.
- *
- * Returns: 1 if the queue is empty
- */
-
-static inline int queue_empty(struct gfs2_glock *gl, struct list_head *head)
-{
-	int empty;
-	spin_lock(&gl->gl_spin);
-	empty = list_empty(head);
-	spin_unlock(&gl->gl_spin);
-	return empty;
-}
-
-/**
  * search_bucket() - Find struct gfs2_glock by lock number
  * @bucket: the bucket to search
  * @name: The lock name
@@ -395,11 +371,6 @@
 	gh->gh_flags = flags;
 	gh->gh_error = 0;
 	gh->gh_iflags = 0;
-	init_completion(&gh->gh_wait);
-
-	if (gh->gh_state == LM_ST_EXCLUSIVE)
-		gh->gh_flags |= GL_LOCAL_EXCL;
-
 	gfs2_glock_hold(gl);
 }
 
@@ -417,9 +388,6 @@
 {
 	gh->gh_state = state;
 	gh->gh_flags = flags;
-	if (gh->gh_state == LM_ST_EXCLUSIVE)
-		gh->gh_flags |= GL_LOCAL_EXCL;
-
 	gh->gh_iflags &= 1 << HIF_ALLOCED;
 	gh->gh_ip = (unsigned long)__builtin_return_address(0);
 }
@@ -479,6 +447,29 @@
 	kfree(gh);
 }
 
+static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh)
+{
+	if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) {
+		gfs2_holder_put(gh);
+		return;
+	}
+	clear_bit(HIF_WAIT, &gh->gh_iflags);
+	smp_mb();
+	wake_up_bit(&gh->gh_iflags, HIF_WAIT);
+}
+
+static int holder_wait(void *word)
+{
+        schedule();
+        return 0;
+}
+
+static void wait_on_holder(struct gfs2_holder *gh)
+{
+	might_sleep();
+	wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
+}
+
 /**
  * rq_mutex - process a mutex request in the queue
  * @gh: the glock holder
@@ -493,7 +484,9 @@
 	list_del_init(&gh->gh_list);
 	/*  gh->gh_error never examined.  */
 	set_bit(GLF_LOCK, &gl->gl_flags);
-	complete(&gh->gh_wait);
+	clear_bit(HIF_WAIT, &gh->gh_iflags);
+	smp_mb();
+	wake_up_bit(&gh->gh_iflags, HIF_WAIT);
 
 	return 1;
 }
@@ -511,7 +504,6 @@
 {
 	struct gfs2_glock *gl = gh->gh_gl;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
-	const struct gfs2_glock_operations *glops = gl->gl_ops;
 
 	if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
 		if (list_empty(&gl->gl_holders)) {
@@ -526,7 +518,7 @@
 				gfs2_reclaim_glock(sdp);
 			}
 
-			glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags);
+			gfs2_glock_xmote_th(gh);
 			spin_lock(&gl->gl_spin);
 		}
 		return 1;
@@ -537,11 +529,11 @@
 		set_bit(GLF_LOCK, &gl->gl_flags);
 	} else {
 		struct gfs2_holder *next_gh;
-		if (gh->gh_flags & GL_LOCAL_EXCL)
+		if (gh->gh_state == LM_ST_EXCLUSIVE)
 			return 1;
 		next_gh = list_entry(gl->gl_holders.next, struct gfs2_holder,
 				     gh_list);
-		if (next_gh->gh_flags & GL_LOCAL_EXCL)
+		if (next_gh->gh_state == LM_ST_EXCLUSIVE)
 			 return 1;
 	}
 
@@ -549,7 +541,7 @@
 	gh->gh_error = 0;
 	set_bit(HIF_HOLDER, &gh->gh_iflags);
 
-	complete(&gh->gh_wait);
+	gfs2_holder_dispose_or_wake(gh);
 
 	return 0;
 }
@@ -564,7 +556,6 @@
 static int rq_demote(struct gfs2_holder *gh)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	const struct gfs2_glock_operations *glops = gl->gl_ops;
 
 	if (!list_empty(&gl->gl_holders))
 		return 1;
@@ -573,10 +564,7 @@
 		list_del_init(&gh->gh_list);
 		gh->gh_error = 0;
 		spin_unlock(&gl->gl_spin);
-		if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
-			gfs2_holder_put(gh);
-		else
-			complete(&gh->gh_wait);
+		gfs2_holder_dispose_or_wake(gh);
 		spin_lock(&gl->gl_spin);
 	} else {
 		gl->gl_req_gh = gh;
@@ -585,9 +573,9 @@
 
 		if (gh->gh_state == LM_ST_UNLOCKED ||
 		    gl->gl_state != LM_ST_EXCLUSIVE)
-			glops->go_drop_th(gl);
+			gfs2_glock_drop_th(gl);
 		else
-			glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags);
+			gfs2_glock_xmote_th(gh);
 
 		spin_lock(&gl->gl_spin);
 	}
@@ -596,30 +584,6 @@
 }
 
 /**
- * rq_greedy - process a queued request to drop greedy status
- * @gh: the glock holder
- *
- * Returns: 1 if the queue is blocked
- */
-
-static int rq_greedy(struct gfs2_holder *gh)
-{
-	struct gfs2_glock *gl = gh->gh_gl;
-
-	list_del_init(&gh->gh_list);
-	/*  gh->gh_error never examined.  */
-	clear_bit(GLF_GREEDY, &gl->gl_flags);
-	spin_unlock(&gl->gl_spin);
-
-	gfs2_holder_uninit(gh);
-	kfree(container_of(gh, struct greedy, gr_gh));
-
-	spin_lock(&gl->gl_spin);
-
-	return 0;
-}
-
-/**
  * run_queue - process holder structures on a glock
  * @gl: the glock
  *
@@ -649,8 +613,6 @@
 
 			if (test_bit(HIF_DEMOTE, &gh->gh_iflags))
 				blocked = rq_demote(gh);
-			else if (test_bit(HIF_GREEDY, &gh->gh_iflags))
-				blocked = rq_greedy(gh);
 			else
 				gfs2_assert_warn(gl->gl_sbd, 0);
 
@@ -684,6 +646,8 @@
 
 	gfs2_holder_init(gl, 0, 0, &gh);
 	set_bit(HIF_MUTEX, &gh.gh_iflags);
+	if (test_and_set_bit(HIF_WAIT, &gh.gh_iflags))
+		BUG();
 
 	spin_lock(&gl->gl_spin);
 	if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
@@ -691,11 +655,13 @@
 	} else {
 		gl->gl_owner = current;
 		gl->gl_ip = (unsigned long)__builtin_return_address(0);
-		complete(&gh.gh_wait);
+		clear_bit(HIF_WAIT, &gh.gh_iflags);
+		smp_mb();
+		wake_up_bit(&gh.gh_iflags, HIF_WAIT);
 	}
 	spin_unlock(&gl->gl_spin);
 
-	wait_for_completion(&gh.gh_wait);
+	wait_on_holder(&gh);
 	gfs2_holder_uninit(&gh);
 }
 
@@ -774,6 +740,7 @@
 			return;
 		set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
 		set_bit(HIF_DEALLOC, &new_gh->gh_iflags);
+		set_bit(HIF_WAIT, &new_gh->gh_iflags);
 
 		goto restart;
 	}
@@ -825,7 +792,7 @@
 	int op_done = 1;
 
 	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
-	gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
 	gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC));
 
 	state_change(gl, ret & LM_OUT_ST_MASK);
@@ -908,12 +875,8 @@
 
 	gfs2_glock_put(gl);
 
-	if (gh) {
-		if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
-			gfs2_holder_put(gh);
-		else
-			complete(&gh->gh_wait);
-	}
+	if (gh)
+		gfs2_holder_dispose_or_wake(gh);
 }
 
 /**
@@ -924,23 +887,26 @@
  *
  */
 
-void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags)
+void gfs2_glock_xmote_th(struct gfs2_holder *gh)
 {
+	struct gfs2_glock *gl = gh->gh_gl;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
+	int flags = gh->gh_flags;
+	unsigned state = gh->gh_state;
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 	int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB |
 				 LM_FLAG_NOEXP | LM_FLAG_ANY |
 				 LM_FLAG_PRIORITY);
 	unsigned int lck_ret;
 
+	if (glops->go_xmote_th)
+		glops->go_xmote_th(gl);
+
 	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
-	gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
 	gfs2_assert_warn(sdp, state != LM_ST_UNLOCKED);
 	gfs2_assert_warn(sdp, state != gl->gl_state);
 
-	if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync)
-		glops->go_sync(gl);
-
 	gfs2_glock_hold(gl);
 	gl->gl_req_bh = xmote_bh;
 
@@ -971,10 +937,8 @@
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 	struct gfs2_holder *gh = gl->gl_req_gh;
 
-	clear_bit(GLF_PREFETCH, &gl->gl_flags);
-
 	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
-	gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
 	gfs2_assert_warn(sdp, !ret);
 
 	state_change(gl, LM_ST_UNLOCKED);
@@ -1001,12 +965,8 @@
 
 	gfs2_glock_put(gl);
 
-	if (gh) {
-		if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
-			gfs2_holder_put(gh);
-		else
-			complete(&gh->gh_wait);
-	}
+	if (gh)
+		gfs2_holder_dispose_or_wake(gh);
 }
 
 /**
@@ -1015,18 +975,18 @@
  *
  */
 
-void gfs2_glock_drop_th(struct gfs2_glock *gl)
+static void gfs2_glock_drop_th(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 	unsigned int ret;
 
-	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
-	gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
-	gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
+	if (glops->go_drop_th)
+		glops->go_drop_th(gl);
 
-	if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync)
-		glops->go_sync(gl);
+	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+	gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
 
 	gfs2_glock_hold(gl);
 	gl->gl_req_bh = drop_bh;
@@ -1107,8 +1067,7 @@
 	if (gh->gh_flags & LM_FLAG_PRIORITY)
 		do_cancels(gh);
 
-	wait_for_completion(&gh->gh_wait);
-
+	wait_on_holder(gh);
 	if (gh->gh_error)
 		return gh->gh_error;
 
@@ -1164,6 +1123,8 @@
 	struct gfs2_holder *existing;
 
 	BUG_ON(!gh->gh_owner);
+	if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
+		BUG();
 
 	existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner);
 	if (existing) {
@@ -1227,8 +1188,6 @@
 		}
 	}
 
-	clear_bit(GLF_PREFETCH, &gl->gl_flags);
-
 	return error;
 }
 
@@ -1321,98 +1280,6 @@
 }
 
 /**
- * gfs2_glock_prefetch - Try to prefetch a glock
- * @gl: the glock
- * @state: the state to prefetch in
- * @flags: flags passed to go_xmote_th()
- *
- */
-
-static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state,
-				int flags)
-{
-	const struct gfs2_glock_operations *glops = gl->gl_ops;
-
-	spin_lock(&gl->gl_spin);
-
-	if (test_bit(GLF_LOCK, &gl->gl_flags) || !list_empty(&gl->gl_holders) ||
-	    !list_empty(&gl->gl_waiters1) || !list_empty(&gl->gl_waiters2) ||
-	    !list_empty(&gl->gl_waiters3) ||
-	    relaxed_state_ok(gl->gl_state, state, flags)) {
-		spin_unlock(&gl->gl_spin);
-		return;
-	}
-
-	set_bit(GLF_PREFETCH, &gl->gl_flags);
-	set_bit(GLF_LOCK, &gl->gl_flags);
-	spin_unlock(&gl->gl_spin);
-
-	glops->go_xmote_th(gl, state, flags);
-}
-
-static void greedy_work(struct work_struct *work)
-{
-	struct greedy *gr = container_of(work, struct greedy, gr_work.work);
-	struct gfs2_holder *gh = &gr->gr_gh;
-	struct gfs2_glock *gl = gh->gh_gl;
-	const struct gfs2_glock_operations *glops = gl->gl_ops;
-
-	clear_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
-
-	if (glops->go_greedy)
-		glops->go_greedy(gl);
-
-	spin_lock(&gl->gl_spin);
-
-	if (list_empty(&gl->gl_waiters2)) {
-		clear_bit(GLF_GREEDY, &gl->gl_flags);
-		spin_unlock(&gl->gl_spin);
-		gfs2_holder_uninit(gh);
-		kfree(gr);
-	} else {
-		gfs2_glock_hold(gl);
-		list_add_tail(&gh->gh_list, &gl->gl_waiters2);
-		run_queue(gl);
-		spin_unlock(&gl->gl_spin);
-		gfs2_glock_put(gl);
-	}
-}
-
-/**
- * gfs2_glock_be_greedy -
- * @gl:
- * @time:
- *
- * Returns: 0 if go_greedy will be called, 1 otherwise
- */
-
-int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time)
-{
-	struct greedy *gr;
-	struct gfs2_holder *gh;
-
-	if (!time || gl->gl_sbd->sd_args.ar_localcaching ||
-	    test_and_set_bit(GLF_GREEDY, &gl->gl_flags))
-		return 1;
-
-	gr = kmalloc(sizeof(struct greedy), GFP_KERNEL);
-	if (!gr) {
-		clear_bit(GLF_GREEDY, &gl->gl_flags);
-		return 1;
-	}
-	gh = &gr->gr_gh;
-
-	gfs2_holder_init(gl, 0, 0, gh);
-	set_bit(HIF_GREEDY, &gh->gh_iflags);
-	INIT_DELAYED_WORK(&gr->gr_work, greedy_work);
-
-	set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
-	schedule_delayed_work(&gr->gr_work, time);
-
-	return 0;
-}
-
-/**
  * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it
  * @gh: the holder structure
  *
@@ -1470,10 +1337,7 @@
 		return 1;
 	if (a->ln_number < b->ln_number)
 		return -1;
-	if (gh_a->gh_state == LM_ST_SHARED && gh_b->gh_state == LM_ST_EXCLUSIVE)
-		return 1;
-	if (!(gh_a->gh_flags & GL_LOCAL_EXCL) && (gh_b->gh_flags & GL_LOCAL_EXCL))
-		return 1;
+	BUG_ON(gh_a->gh_gl->gl_ops->go_type == gh_b->gh_gl->gl_ops->go_type);
 	return 0;
 }
 
@@ -1618,34 +1482,6 @@
 }
 
 /**
- * gfs2_glock_prefetch_num - prefetch a glock based on lock number
- * @sdp: the filesystem
- * @number: the lock number
- * @glops: the glock operations for the type of glock
- * @state: the state to acquire the glock in
- * @flags: modifier flags for the aquisition
- *
- * Returns: errno
- */
-
-void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number,
-			     const struct gfs2_glock_operations *glops,
-			     unsigned int state, int flags)
-{
-	struct gfs2_glock *gl;
-	int error;
-
-	if (atomic_read(&sdp->sd_reclaim_count) <
-	    gfs2_tune_get(sdp, gt_reclaim_limit)) {
-		error = gfs2_glock_get(sdp, number, glops, CREATE, &gl);
-		if (!error) {
-			gfs2_glock_prefetch(gl, state, flags);
-			gfs2_glock_put(gl);
-		}
-	}
-}
-
-/**
  * gfs2_lvb_hold - attach a LVB from a glock
  * @gl: The glock in question
  *
@@ -1703,8 +1539,6 @@
 	if (!gl)
 		return;
 
-	if (gl->gl_ops->go_callback)
-		gl->gl_ops->go_callback(gl, state);
 	handle_callback(gl, state);
 
 	spin_lock(&gl->gl_spin);
@@ -1746,12 +1580,14 @@
 		struct lm_async_cb *async = data;
 		struct gfs2_glock *gl;
 
+		down_read(&gfs2_umount_flush_sem);
 		gl = gfs2_glock_find(sdp, &async->lc_name);
 		if (gfs2_assert_warn(sdp, gl))
 			return;
 		if (!gfs2_assert_warn(sdp, gl->gl_req_bh))
 			gl->gl_req_bh(gl, async->lc_ret);
 		gfs2_glock_put(gl);
+		up_read(&gfs2_umount_flush_sem);
 		return;
 	}
 
@@ -1781,15 +1617,11 @@
 
 static int demote_ok(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 	int demote = 1;
 
 	if (test_bit(GLF_STICKY, &gl->gl_flags))
 		demote = 0;
-	else if (test_bit(GLF_PREFETCH, &gl->gl_flags))
-		demote = time_after_eq(jiffies, gl->gl_stamp +
-				    gfs2_tune_get(sdp, gt_prefetch_secs) * HZ);
 	else if (glops->go_demote_ok)
 		demote = glops->go_demote_ok(gl);
 
@@ -1845,7 +1677,7 @@
 	atomic_inc(&sdp->sd_reclaimed);
 
 	if (gfs2_glmutex_trylock(gl)) {
-		if (queue_empty(gl, &gl->gl_holders) &&
+		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
 			handle_callback(gl, LM_ST_UNLOCKED);
 		gfs2_glmutex_unlock(gl);
@@ -1909,7 +1741,7 @@
 		return;
 
 	if (gfs2_glmutex_trylock(gl)) {
-		if (queue_empty(gl, &gl->gl_holders) &&
+		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
 			goto out_schedule;
 		gfs2_glmutex_unlock(gl);
@@ -1958,7 +1790,7 @@
 	}
 
 	if (gfs2_glmutex_trylock(gl)) {
-		if (queue_empty(gl, &gl->gl_holders) &&
+		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED)
 			handle_callback(gl, LM_ST_UNLOCKED);
 		gfs2_glmutex_unlock(gl);
@@ -2000,7 +1832,9 @@
 			t = jiffies;
 		}
 
+		down_write(&gfs2_umount_flush_sem);
 		invalidate_inodes(sdp->sd_vfs);
+		up_write(&gfs2_umount_flush_sem);
 		msleep(10);
 	}
 }
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index fb39108..f50e40c 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -20,7 +20,6 @@
 #define LM_FLAG_ANY		0x00000008
 #define LM_FLAG_PRIORITY	0x00000010 */
 
-#define GL_LOCAL_EXCL		0x00000020
 #define GL_ASYNC		0x00000040
 #define GL_EXACT		0x00000080
 #define GL_SKIP			0x00000100
@@ -83,17 +82,11 @@
 void gfs2_holder_reinit(unsigned int state, unsigned flags,
 			struct gfs2_holder *gh);
 void gfs2_holder_uninit(struct gfs2_holder *gh);
-
-void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags);
-void gfs2_glock_drop_th(struct gfs2_glock *gl);
-
 int gfs2_glock_nq(struct gfs2_holder *gh);
 int gfs2_glock_poll(struct gfs2_holder *gh);
 int gfs2_glock_wait(struct gfs2_holder *gh);
 void gfs2_glock_dq(struct gfs2_holder *gh);
 
-int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time);
-
 void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
 int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
 		      u64 number, const struct gfs2_glock_operations *glops,
@@ -103,10 +96,6 @@
 void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
 void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
 
-void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number,
-			     const struct gfs2_glock_operations *glops,
-			     unsigned int state, int flags);
-
 /**
  * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
  * @gl: the glock
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index b068d10..c4b0391 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -117,12 +117,14 @@
 
 static void meta_go_sync(struct gfs2_glock *gl)
 {
+	if (gl->gl_state != LM_ST_EXCLUSIVE)
+		return;
+
 	if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
 		gfs2_log_flush(gl->gl_sbd, gl);
 		gfs2_meta_sync(gl);
 		gfs2_ail_empty_gl(gl);
 	}
-
 }
 
 /**
@@ -142,6 +144,37 @@
 }
 
 /**
+ * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
+ * @gl: the glock protecting the inode
+ *
+ */
+
+static void inode_go_sync(struct gfs2_glock *gl)
+{
+	struct gfs2_inode *ip = gl->gl_object;
+
+	if (ip && !S_ISREG(ip->i_inode.i_mode))
+		ip = NULL;
+
+	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
+		gfs2_log_flush(gl->gl_sbd, gl);
+		if (ip)
+			filemap_fdatawrite(ip->i_inode.i_mapping);
+		gfs2_meta_sync(gl);
+		if (ip) {
+			struct address_space *mapping = ip->i_inode.i_mapping;
+			int error = filemap_fdatawait(mapping);
+			if (error == -ENOSPC)
+				set_bit(AS_ENOSPC, &mapping->flags);
+			else if (error)
+				set_bit(AS_EIO, &mapping->flags);
+		}
+		clear_bit(GLF_DIRTY, &gl->gl_flags);
+		gfs2_ail_empty_gl(gl);
+	}
+}
+
+/**
  * inode_go_xmote_th - promote/demote a glock
  * @gl: the glock
  * @state: the requested state
@@ -149,12 +182,12 @@
  *
  */
 
-static void inode_go_xmote_th(struct gfs2_glock *gl, unsigned int state,
-			      int flags)
+static void inode_go_xmote_th(struct gfs2_glock *gl)
 {
 	if (gl->gl_state != LM_ST_UNLOCKED)
 		gfs2_pte_inval(gl);
-	gfs2_glock_xmote_th(gl, state, flags);
+	if (gl->gl_state == LM_ST_EXCLUSIVE)
+		inode_go_sync(gl);
 }
 
 /**
@@ -189,38 +222,8 @@
 static void inode_go_drop_th(struct gfs2_glock *gl)
 {
 	gfs2_pte_inval(gl);
-	gfs2_glock_drop_th(gl);
-}
-
-/**
- * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
- * @gl: the glock protecting the inode
- *
- */
-
-static void inode_go_sync(struct gfs2_glock *gl)
-{
-	struct gfs2_inode *ip = gl->gl_object;
-
-	if (ip && !S_ISREG(ip->i_inode.i_mode))
-		ip = NULL;
-
-	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
-		gfs2_log_flush(gl->gl_sbd, gl);
-		if (ip)
-			filemap_fdatawrite(ip->i_inode.i_mapping);
-		gfs2_meta_sync(gl);
-		if (ip) {
-			struct address_space *mapping = ip->i_inode.i_mapping;
-			int error = filemap_fdatawait(mapping);
-			if (error == -ENOSPC)
-				set_bit(AS_ENOSPC, &mapping->flags);
-			else if (error)
-				set_bit(AS_EIO, &mapping->flags);
-		}
-		clear_bit(GLF_DIRTY, &gl->gl_flags);
-		gfs2_ail_empty_gl(gl);
-	}
+	if (gl->gl_state == LM_ST_EXCLUSIVE)
+		inode_go_sync(gl);
 }
 
 /**
@@ -295,7 +298,7 @@
 
 	if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) &&
 	    (gl->gl_state == LM_ST_EXCLUSIVE) &&
-	    (gh->gh_flags & GL_LOCAL_EXCL))
+	    (gh->gh_state == LM_ST_EXCLUSIVE))
 		error = gfs2_truncatei_resume(ip);
 
 	return error;
@@ -319,39 +322,6 @@
 }
 
 /**
- * inode_greedy -
- * @gl: the glock
- *
- */
-
-static void inode_greedy(struct gfs2_glock *gl)
-{
-	struct gfs2_sbd *sdp = gl->gl_sbd;
-	struct gfs2_inode *ip = gl->gl_object;
-	unsigned int quantum = gfs2_tune_get(sdp, gt_greedy_quantum);
-	unsigned int max = gfs2_tune_get(sdp, gt_greedy_max);
-	unsigned int new_time;
-
-	spin_lock(&ip->i_spin);
-
-	if (time_after(ip->i_last_pfault + quantum, jiffies)) {
-		new_time = ip->i_greedy + quantum;
-		if (new_time > max)
-			new_time = max;
-	} else {
-		new_time = ip->i_greedy - quantum;
-		if (!new_time || new_time > max)
-			new_time = 1;
-	}
-
-	ip->i_greedy = new_time;
-
-	spin_unlock(&ip->i_spin);
-
-	iput(&ip->i_inode);
-}
-
-/**
  * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
  * @gl: the glock
  *
@@ -398,8 +368,7 @@
  *
  */
 
-static void trans_go_xmote_th(struct gfs2_glock *gl, unsigned int state,
-			      int flags)
+static void trans_go_xmote_th(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 
@@ -408,8 +377,6 @@
 		gfs2_meta_syncfs(sdp);
 		gfs2_log_shutdown(sdp);
 	}
-
-	gfs2_glock_xmote_th(gl, state, flags);
 }
 
 /**
@@ -461,8 +428,6 @@
 		gfs2_meta_syncfs(sdp);
 		gfs2_log_shutdown(sdp);
 	}
-
-	gfs2_glock_drop_th(gl);
 }
 
 /**
@@ -478,8 +443,8 @@
 }
 
 const struct gfs2_glock_operations gfs2_meta_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
+	.go_xmote_th = meta_go_sync,
+	.go_drop_th = meta_go_sync,
 	.go_type = LM_TYPE_META,
 };
 
@@ -487,19 +452,14 @@
 	.go_xmote_th = inode_go_xmote_th,
 	.go_xmote_bh = inode_go_xmote_bh,
 	.go_drop_th = inode_go_drop_th,
-	.go_sync = inode_go_sync,
 	.go_inval = inode_go_inval,
 	.go_demote_ok = inode_go_demote_ok,
 	.go_lock = inode_go_lock,
 	.go_unlock = inode_go_unlock,
-	.go_greedy = inode_greedy,
 	.go_type = LM_TYPE_INODE,
 };
 
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
-	.go_sync = meta_go_sync,
 	.go_inval = meta_go_inval,
 	.go_demote_ok = rgrp_go_demote_ok,
 	.go_lock = rgrp_go_lock,
@@ -515,33 +475,23 @@
 };
 
 const struct gfs2_glock_operations gfs2_iopen_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
 	.go_type = LM_TYPE_IOPEN,
 };
 
 const struct gfs2_glock_operations gfs2_flock_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
 	.go_type = LM_TYPE_FLOCK,
 };
 
 const struct gfs2_glock_operations gfs2_nondisk_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
 	.go_type = LM_TYPE_NONDISK,
 };
 
 const struct gfs2_glock_operations gfs2_quota_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
 	.go_demote_ok = quota_go_demote_ok,
 	.go_type = LM_TYPE_QUOTA,
 };
 
 const struct gfs2_glock_operations gfs2_journal_glops = {
-	.go_xmote_th = gfs2_glock_xmote_th,
-	.go_drop_th = gfs2_glock_drop_th,
 	.go_type = LM_TYPE_JOURNAL,
 };
 
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 734421e..12c80fd 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -101,17 +101,14 @@
 };
 
 struct gfs2_glock_operations {
-	void (*go_xmote_th) (struct gfs2_glock *gl, unsigned int state, int flags);
+	void (*go_xmote_th) (struct gfs2_glock *gl);
 	void (*go_xmote_bh) (struct gfs2_glock *gl);
 	void (*go_drop_th) (struct gfs2_glock *gl);
 	void (*go_drop_bh) (struct gfs2_glock *gl);
-	void (*go_sync) (struct gfs2_glock *gl);
 	void (*go_inval) (struct gfs2_glock *gl, int flags);
 	int (*go_demote_ok) (struct gfs2_glock *gl);
 	int (*go_lock) (struct gfs2_holder *gh);
 	void (*go_unlock) (struct gfs2_holder *gh);
-	void (*go_callback) (struct gfs2_glock *gl, unsigned int state);
-	void (*go_greedy) (struct gfs2_glock *gl);
 	const int go_type;
 };
 
@@ -120,7 +117,6 @@
 	HIF_MUTEX		= 0,
 	HIF_PROMOTE		= 1,
 	HIF_DEMOTE		= 2,
-	HIF_GREEDY		= 3,
 
 	/* States */
 	HIF_ALLOCED		= 4,
@@ -128,6 +124,7 @@
 	HIF_HOLDER		= 6,
 	HIF_FIRST		= 7,
 	HIF_ABORTED		= 9,
+	HIF_WAIT		= 10,
 };
 
 struct gfs2_holder {
@@ -140,17 +137,14 @@
 
 	int gh_error;
 	unsigned long gh_iflags;
-	struct completion gh_wait;
 	unsigned long gh_ip;
 };
 
 enum {
 	GLF_LOCK		= 1,
 	GLF_STICKY		= 2,
-	GLF_PREFETCH		= 3,
 	GLF_DIRTY		= 5,
 	GLF_SKIP_WAITERS2	= 6,
-	GLF_GREEDY		= 7,
 };
 
 struct gfs2_glock {
@@ -167,7 +161,7 @@
 	unsigned long gl_ip;
 	struct list_head gl_holders;
 	struct list_head gl_waiters1;	/* HIF_MUTEX */
-	struct list_head gl_waiters2;	/* HIF_DEMOTE, HIF_GREEDY */
+	struct list_head gl_waiters2;	/* HIF_DEMOTE */
 	struct list_head gl_waiters3;	/* HIF_PROMOTE */
 
 	const struct gfs2_glock_operations *gl_ops;
@@ -236,7 +230,6 @@
 
 	spinlock_t i_spin;
 	struct rw_semaphore i_rw_mutex;
-	unsigned int i_greedy;
 	unsigned long i_last_pfault;
 
 	struct buffer_head *i_cache[GFS2_MAX_META_HEIGHT];
@@ -418,17 +411,12 @@
 	unsigned int gt_atime_quantum; /* Min secs between atime updates */
 	unsigned int gt_new_files_jdata;
 	unsigned int gt_new_files_directio;
-	unsigned int gt_max_atomic_write; /* Split big writes into this size */
 	unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
 	unsigned int gt_lockdump_size;
 	unsigned int gt_stall_secs; /* Detects trouble! */
 	unsigned int gt_complain_secs;
 	unsigned int gt_reclaim_limit; /* Max num of glocks in reclaim list */
 	unsigned int gt_entries_per_readdir;
-	unsigned int gt_prefetch_secs; /* Usage window for prefetched glocks */
-	unsigned int gt_greedy_default;
-	unsigned int gt_greedy_quantum;
-	unsigned int gt_greedy_max;
 	unsigned int gt_statfs_quantum;
 	unsigned int gt_statfs_slow;
 };
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index d122074c..0d6831a 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -287,10 +287,8 @@
  *
  * Returns: errno
  */
-
 int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
 {
-	struct gfs2_sbd *sdp = ip->i_inode.i_sb->s_fs_info;
 	struct buffer_head *dibh;
 	u32 nlink;
 	int error;
@@ -315,42 +313,34 @@
 	else
 		drop_nlink(&ip->i_inode);
 
-	ip->i_inode.i_ctime.tv_sec = get_seconds();
+	ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
 	brelse(dibh);
 	mark_inode_dirty(&ip->i_inode);
 
-	if (ip->i_inode.i_nlink == 0) {
-		struct gfs2_rgrpd *rgd;
-		struct gfs2_holder ri_gh, rg_gh;
-
-		error = gfs2_rindex_hold(sdp, &ri_gh);
-		if (error)
-			goto out;
-		error = -EIO;
-		rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
-		if (!rgd)
-			goto out_norgrp;
-		error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh);
-		if (error)
-			goto out_norgrp;
-
+	if (ip->i_inode.i_nlink == 0)
 		gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */
-		gfs2_glock_dq_uninit(&rg_gh);
-out_norgrp:
-		gfs2_glock_dq_uninit(&ri_gh);
-	}
-out:
+
 	return error;
 }
 
 struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
 {
 	struct qstr qstr;
+	struct inode *inode;
 	gfs2_str2qstr(&qstr, name);
-	return gfs2_lookupi(dip, &qstr, 1, NULL);
+	inode = gfs2_lookupi(dip, &qstr, 1, NULL);
+	/* gfs2_lookupi has inconsistent callers: vfs
+	 * related routines expect NULL for no entry found,
+	 * gfs2_lookup_simple callers expect ENOENT
+	 * and do not check for NULL.
+	 */
+	if (inode == NULL)
+		return ERR_PTR(-ENOENT);
+	else
+		return inode;
 }
 
 
@@ -361,8 +351,10 @@
  * @is_root: If 1, ignore the caller's permissions
  * @i_gh: An uninitialized holder for the new inode glock
  *
- * There will always be a vnode (Linux VFS inode) for the d_gh inode unless
- * @is_root is true.
+ * This can be called via the VFS filldir function when NFS is doing
+ * a readdirplus and the inode which its intending to stat isn't
+ * already in cache. In this case we must not take the directory glock
+ * again, since the readdir call will have already taken that lock.
  *
  * Returns: errno
  */
@@ -375,8 +367,9 @@
 	struct gfs2_holder d_gh;
 	struct gfs2_inum_host inum;
 	unsigned int type;
-	int error = 0;
+	int error;
 	struct inode *inode = NULL;
+	int unlock = 0;
 
 	if (!name->len || name->len > GFS2_FNAMESIZE)
 		return ERR_PTR(-ENAMETOOLONG);
@@ -388,9 +381,12 @@
 		return dir;
 	}
 
-	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
-	if (error)
-		return ERR_PTR(error);
+	if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) {
+		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+		if (error)
+			return ERR_PTR(error);
+		unlock = 1;
+	}
 
 	if (!is_root) {
 		error = permission(dir, MAY_EXEC, NULL);
@@ -405,10 +401,11 @@
 	inode = gfs2_inode_lookup(sb, &inum, type);
 
 out:
-	gfs2_glock_dq_uninit(&d_gh);
+	if (unlock)
+		gfs2_glock_dq_uninit(&d_gh);
 	if (error == -ENOENT)
 		return NULL;
-	return inode;
+	return inode ? inode : ERR_PTR(error);
 }
 
 static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
diff --git a/fs/gfs2/lm.c b/fs/gfs2/lm.c
index effe4a3..e30673d 100644
--- a/fs/gfs2/lm.c
+++ b/fs/gfs2/lm.c
@@ -104,15 +104,9 @@
 	vprintk(fmt, args);
 	va_end(args);
 
-	fs_err(sdp, "about to withdraw from the cluster\n");
+	fs_err(sdp, "about to withdraw this file system\n");
 	BUG_ON(sdp->sd_args.ar_debug);
 
-
-	fs_err(sdp, "waiting for outstanding I/O\n");
-
-	/* FIXME: suspend dm device so oustanding bio's complete
-	   and all further io requests fail */
-
 	fs_err(sdp, "telling LM to withdraw\n");
 	gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
 	fs_err(sdp, "withdrawn\n");
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
index 33af707..a87c7bf 100644
--- a/fs/gfs2/locking/dlm/lock_dlm.h
+++ b/fs/gfs2/locking/dlm/lock_dlm.h
@@ -36,7 +36,7 @@
 
 #define GDLM_STRNAME_BYTES	24
 #define GDLM_LVB_SIZE		32
-#define GDLM_DROP_COUNT		50000
+#define GDLM_DROP_COUNT		200000
 #define GDLM_DROP_PERIOD	60
 #define GDLM_NAME_LEN		128
 
diff --git a/fs/gfs2/locking/dlm/main.c b/fs/gfs2/locking/dlm/main.c
index 2194b1d..a0e7eda 100644
--- a/fs/gfs2/locking/dlm/main.c
+++ b/fs/gfs2/locking/dlm/main.c
@@ -11,9 +11,6 @@
 
 #include "lock_dlm.h"
 
-extern int gdlm_drop_count;
-extern int gdlm_drop_period;
-
 extern struct lm_lockops gdlm_ops;
 
 static int __init init_lock_dlm(void)
@@ -40,9 +37,6 @@
 		return error;
 	}
 
-	gdlm_drop_count = GDLM_DROP_COUNT;
-	gdlm_drop_period = GDLM_DROP_PERIOD;
-
 	printk(KERN_INFO
 	       "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__);
 	return 0;
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index cdd1694..1d8faa3 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -9,8 +9,6 @@
 
 #include "lock_dlm.h"
 
-int gdlm_drop_count;
-int gdlm_drop_period;
 const struct lm_lockops gdlm_ops;
 
 
@@ -24,8 +22,8 @@
 	if (!ls)
 		return NULL;
 
-	ls->drop_locks_count = gdlm_drop_count;
-	ls->drop_locks_period = gdlm_drop_period;
+	ls->drop_locks_count = GDLM_DROP_COUNT;
+	ls->drop_locks_period = GDLM_DROP_PERIOD;
 	ls->fscb = cb;
 	ls->sdp = sdp;
 	ls->fsflags = flags;
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
index 29ae06f..4746b88 100644
--- a/fs/gfs2/locking/dlm/sysfs.c
+++ b/fs/gfs2/locking/dlm/sysfs.c
@@ -116,6 +116,17 @@
 	return sprintf(buf, "%d\n", ls->recover_jid_status);
 }
 
+static ssize_t drop_count_show(struct gdlm_ls *ls, char *buf)
+{
+	return sprintf(buf, "%d\n", ls->drop_locks_count);
+}
+
+static ssize_t drop_count_store(struct gdlm_ls *ls, const char *buf, size_t len)
+{
+	ls->drop_locks_count = simple_strtol(buf, NULL, 0);
+	return len;
+}
+
 struct gdlm_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct gdlm_ls *, char *);
@@ -135,6 +146,7 @@
 GDLM_ATTR(recover,        0644, recover_show,        recover_store);
 GDLM_ATTR(recover_done,   0444, recover_done_show,   NULL);
 GDLM_ATTR(recover_status, 0444, recover_status_show, NULL);
+GDLM_ATTR(drop_count,     0644, drop_count_show,     drop_count_store);
 
 static struct attribute *gdlm_attrs[] = {
 	&gdlm_attr_proto_name.attr,
@@ -147,6 +159,7 @@
 	&gdlm_attr_recover.attr,
 	&gdlm_attr_recover_done.attr,
 	&gdlm_attr_recover_status.attr,
+	&gdlm_attr_drop_count.attr,
 	NULL,
 };
 
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 4d7f94d..16bb4b4 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -69,13 +69,16 @@
 	struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
 	struct gfs2_trans *tr;
 
-	if (!list_empty(&bd->bd_list_tr))
+	gfs2_log_lock(sdp);
+	if (!list_empty(&bd->bd_list_tr)) {
+		gfs2_log_unlock(sdp);
 		return;
-
+	}
 	tr = current->journal_info;
 	tr->tr_touched = 1;
 	tr->tr_num_buf++;
 	list_add(&bd->bd_list_tr, &tr->tr_list_buf);
+	gfs2_log_unlock(sdp);
 
 	if (!list_empty(&le->le_list))
 		return;
@@ -84,7 +87,6 @@
 
 	gfs2_meta_check(sdp, bd->bd_bh);
 	gfs2_pin(sdp, bd->bd_bh);
-
 	gfs2_log_lock(sdp);
 	sdp->sd_log_num_buf++;
 	list_add(&le->le_list, &sdp->sd_log_le_buf);
@@ -98,11 +100,13 @@
 	struct list_head *head = &tr->tr_list_buf;
 	struct gfs2_bufdata *bd;
 
+	gfs2_log_lock(sdp);
 	while (!list_empty(head)) {
 		bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
 		list_del_init(&bd->bd_list_tr);
 		tr->tr_num_buf--;
 	}
+	gfs2_log_unlock(sdp);
 	gfs2_assert_warn(sdp, !tr->tr_num_buf);
 }
 
@@ -462,13 +466,17 @@
 	struct address_space *mapping = bd->bd_bh->b_page->mapping;
 	struct gfs2_inode *ip = GFS2_I(mapping->host);
 
+	gfs2_log_lock(sdp);
 	tr->tr_touched = 1;
 	if (list_empty(&bd->bd_list_tr) &&
 	    (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
 		tr->tr_num_buf++;
 		list_add(&bd->bd_list_tr, &tr->tr_list_buf);
+		gfs2_log_unlock(sdp);
 		gfs2_pin(sdp, bd->bd_bh);
 		tr->tr_num_buf_new++;
+	} else {
+		gfs2_log_unlock(sdp);
 	}
 	gfs2_trans_add_gl(bd->bd_gl);
 	gfs2_log_lock(sdp);
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index d8d69a7..56e3359 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -16,6 +16,7 @@
 #include <linux/pagevec.h>
 #include <linux/mpage.h>
 #include <linux/fs.h>
+#include <linux/writeback.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
 
@@ -157,6 +158,32 @@
 }
 
 /**
+ * gfs2_writepages - Write a bunch of dirty pages back to disk
+ * @mapping: The mapping to write
+ * @wbc: Write-back control
+ *
+ * For journaled files and/or ordered writes this just falls back to the
+ * kernel's default writepages path for now. We will probably want to change
+ * that eventually (i.e. when we look at allocate on flush).
+ *
+ * For the data=writeback case though we can already ignore buffer heads
+ * and write whole extents at once. This is a big reduction in the
+ * number of I/O requests we send and the bmap calls we make in this case.
+ */
+static int gfs2_writepages(struct address_space *mapping,
+			   struct writeback_control *wbc)
+{
+	struct inode *inode = mapping->host;
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+
+	if (sdp->sd_args.ar_data == GFS2_DATA_WRITEBACK && !gfs2_is_jdata(ip))
+		return mpage_writepages(mapping, wbc, gfs2_get_block_noalloc);
+
+	return generic_writepages(mapping, wbc);
+}
+
+/**
  * stuffed_readpage - Fill in a Linux page with stuffed file data
  * @ip: the inode
  * @page: the page
@@ -256,7 +283,7 @@
  *    the page lock and the glock) and return having done no I/O. Its
  *    obviously not something we'd want to do on too regular a basis.
  *    Any I/O we ignore at this time will be done via readpage later.
- * 2. We have to handle stuffed files here too.
+ * 2. We don't handle stuffed files here we let readpage do the honours.
  * 3. mpage_readpages() does most of the heavy lifting in the common case.
  * 4. gfs2_get_block() is relied upon to set BH_Boundary in the right places.
  * 5. We use LM_FLAG_TRY_1CB here, effectively we then have lock-ahead as
@@ -269,8 +296,7 @@
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct gfs2_holder gh;
-	unsigned page_idx;
-	int ret;
+	int ret = 0;
 	int do_unlock = 0;
 
 	if (likely(file != &gfs2_internal_file_sentinel)) {
@@ -289,29 +315,8 @@
 			goto out_unlock;
 	}
 skip_lock:
-	if (gfs2_is_stuffed(ip)) {
-		struct pagevec lru_pvec;
-		pagevec_init(&lru_pvec, 0);
-		for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-			struct page *page = list_entry(pages->prev, struct page, lru);
-			prefetchw(&page->flags);
-			list_del(&page->lru);
-			if (!add_to_page_cache(page, mapping,
-					       page->index, GFP_KERNEL)) {
-				ret = stuffed_readpage(ip, page);
-				unlock_page(page);
-				if (!pagevec_add(&lru_pvec, page))
-					 __pagevec_lru_add(&lru_pvec);
-			} else {
-				page_cache_release(page);
-			}
-		}
-		pagevec_lru_add(&lru_pvec);
-		ret = 0;
-	} else {
-		/* What we really want to do .... */
+	if (!gfs2_is_stuffed(ip))
 		ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block);
-	}
 
 	if (do_unlock) {
 		gfs2_glock_dq_m(1, &gh);
@@ -356,8 +361,10 @@
 	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh);
 	error = gfs2_glock_nq_atime(&ip->i_gh);
 	if (unlikely(error)) {
-		if (error == GLR_TRYFAILED)
+		if (error == GLR_TRYFAILED) {
+			unlock_page(page);
 			error = AOP_TRUNCATED_PAGE;
+		}
 		goto out_uninit;
 	}
 
@@ -594,6 +601,36 @@
 	return;
 }
 
+/**
+ * gfs2_ok_for_dio - check that dio is valid on this file
+ * @ip: The inode
+ * @rw: READ or WRITE
+ * @offset: The offset at which we are reading or writing
+ *
+ * Returns: 0 (to ignore the i/o request and thus fall back to buffered i/o)
+ *          1 (to accept the i/o request)
+ */
+static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset)
+{
+	/*
+	 * Should we return an error here? I can't see that O_DIRECT for
+	 * a journaled file makes any sense. For now we'll silently fall
+	 * back to buffered I/O, likewise we do the same for stuffed
+	 * files since they are (a) small and (b) unaligned.
+	 */
+	if (gfs2_is_jdata(ip))
+		return 0;
+
+	if (gfs2_is_stuffed(ip))
+		return 0;
+
+	if (offset > i_size_read(&ip->i_inode))
+		return 0;
+	return 1;
+}
+
+
+
 static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
 			      const struct iovec *iov, loff_t offset,
 			      unsigned long nr_segs)
@@ -604,42 +641,28 @@
 	struct gfs2_holder gh;
 	int rv;
 
-	if (rw == READ)
-		mutex_lock(&inode->i_mutex);
 	/*
-	 * Shared lock, even if its a write, since we do no allocation
-	 * on this path. All we need change is atime.
+	 * Deferred lock, even if its a write, since we do no allocation
+	 * on this path. All we need change is atime, and this lock mode
+	 * ensures that other nodes have flushed their buffered read caches
+	 * (i.e. their page cache entries for this inode). We do not,
+	 * unfortunately have the option of only flushing a range like
+	 * the VFS does.
 	 */
-	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
+	gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh);
 	rv = gfs2_glock_nq_atime(&gh);
 	if (rv)
-		goto out;
+		return rv;
+	rv = gfs2_ok_for_dio(ip, rw, offset);
+	if (rv != 1)
+		goto out; /* dio not valid, fall back to buffered i/o */
 
-	if (offset > i_size_read(inode))
-		goto out;
-
-	/*
-	 * Should we return an error here? I can't see that O_DIRECT for
-	 * a journaled file makes any sense. For now we'll silently fall
-	 * back to buffered I/O, likewise we do the same for stuffed
-	 * files since they are (a) small and (b) unaligned.
-	 */
-	if (gfs2_is_jdata(ip))
-		goto out;
-
-	if (gfs2_is_stuffed(ip))
-		goto out;
-
-	rv = blockdev_direct_IO_own_locking(rw, iocb, inode,
-					    inode->i_sb->s_bdev,
-					    iov, offset, nr_segs,
-					    gfs2_get_block_direct, NULL);
+	rv = blockdev_direct_IO_no_locking(rw, iocb, inode, inode->i_sb->s_bdev,
+					   iov, offset, nr_segs,
+					   gfs2_get_block_direct, NULL);
 out:
 	gfs2_glock_dq_m(1, &gh);
 	gfs2_holder_uninit(&gh);
-	if (rw == READ)
-		mutex_unlock(&inode->i_mutex);
-
 	return rv;
 }
 
@@ -763,6 +786,7 @@
 
 const struct address_space_operations gfs2_file_aops = {
 	.writepage = gfs2_writepage,
+	.writepages = gfs2_writepages,
 	.readpage = gfs2_readpage,
 	.readpages = gfs2_readpages,
 	.sync_page = block_sync_page,
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index d355899..9187eb1 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -46,6 +46,7 @@
 	struct gfs2_inum_host inum;
 	unsigned int type;
 	int error;
+	int had_lock=0;
 
 	if (inode && is_bad_inode(inode))
 		goto invalid;
@@ -53,9 +54,12 @@
 	if (sdp->sd_args.ar_localcaching)
 		goto valid;
 
-	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
-	if (error)
-		goto fail;
+	had_lock = gfs2_glock_is_locked_by_me(dip->i_gl);
+	if (!had_lock) {
+		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+		if (error)
+			goto fail;
+	} 
 
 	error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type);
 	switch (error) {
@@ -82,13 +86,15 @@
 	}
 
 valid_gunlock:
-	gfs2_glock_dq_uninit(&d_gh);
+	if (!had_lock)
+		gfs2_glock_dq_uninit(&d_gh);
 valid:
 	dput(parent);
 	return 1;
 
 invalid_gunlock:
-	gfs2_glock_dq_uninit(&d_gh);
+	if (!had_lock)
+		gfs2_glock_dq_uninit(&d_gh);
 invalid:
 	if (inode && S_ISDIR(inode->i_mode)) {
 		if (have_submounts(dentry))
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index b4e7b87..4855e8c 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -22,6 +22,7 @@
 #include "glock.h"
 #include "glops.h"
 #include "inode.h"
+#include "ops_dentry.h"
 #include "ops_export.h"
 #include "rgrp.h"
 #include "util.h"
@@ -112,13 +113,12 @@
 	char *name;
 };
 
-static int get_name_filldir(void *opaque, const char *name, unsigned int length,
-			    u64 offset, struct gfs2_inum_host *inum,
-			    unsigned int type)
+static int get_name_filldir(void *opaque, const char *name, int length,
+			    loff_t offset, u64 inum, unsigned int type)
 {
-	struct get_name_filldir *gnfd = (struct get_name_filldir *)opaque;
+	struct get_name_filldir *gnfd = opaque;
 
-	if (!gfs2_inum_equal(inum, &gnfd->inum))
+	if (inum != gnfd->inum.no_addr)
 		return 0;
 
 	memcpy(gnfd->name, name, length);
@@ -189,6 +189,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
+	dentry->d_op = &gfs2_dops;
 	return dentry;
 }
 
@@ -215,8 +216,7 @@
 	}
 
 	error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
-				  LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL,
-				  &i_gh);
+				  LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
 	if (error)
 		return ERR_PTR(error);
 
@@ -269,6 +269,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
+	dentry->d_op = &gfs2_dops;
 	return dentry;
 
 fail_rgd:
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index faa07e4..c996aa7 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -43,15 +43,6 @@
 #include "util.h"
 #include "eaops.h"
 
-/* For regular, non-NFS */
-struct filldir_reg {
-	struct gfs2_sbd *fdr_sbd;
-	int fdr_prefetch;
-
-	filldir_t fdr_filldir;
-	void *fdr_opaque;
-};
-
 /*
  * Most fields left uninitialised to catch anybody who tries to
  * use them. f_flags set to prevent file_accessed() from touching
@@ -128,41 +119,6 @@
 }
 
 /**
- * filldir_func - Report a directory entry to the caller of gfs2_dir_read()
- * @opaque: opaque data used by the function
- * @name: the name of the directory entry
- * @length: the length of the name
- * @offset: the entry's offset in the directory
- * @inum: the inode number the entry points to
- * @type: the type of inode the entry points to
- *
- * Returns: 0 on success, 1 if buffer full
- */
-
-static int filldir_func(void *opaque, const char *name, unsigned int length,
-			u64 offset, struct gfs2_inum_host *inum,
-			unsigned int type)
-{
-	struct filldir_reg *fdr = (struct filldir_reg *)opaque;
-	struct gfs2_sbd *sdp = fdr->fdr_sbd;
-	int error;
-
-	error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset,
-				 inum->no_addr, type);
-	if (error)
-		return 1;
-
-	if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) {
-		gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_inode_glops,
-				       LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY);
-		gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_iopen_glops,
-				       LM_ST_SHARED, LM_FLAG_TRY);
-	}
-
-	return 0;
-}
-
-/**
  * gfs2_readdir - Read directory entries from a directory
  * @file: The directory to read from
  * @dirent: Buffer for dirents
@@ -175,16 +131,10 @@
 {
 	struct inode *dir = file->f_mapping->host;
 	struct gfs2_inode *dip = GFS2_I(dir);
-	struct filldir_reg fdr;
 	struct gfs2_holder d_gh;
 	u64 offset = file->f_pos;
 	int error;
 
-	fdr.fdr_sbd = GFS2_SB(dir);
-	fdr.fdr_prefetch = 1;
-	fdr.fdr_filldir = filldir;
-	fdr.fdr_opaque = dirent;
-
 	gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
 	error = gfs2_glock_nq_atime(&d_gh);
 	if (error) {
@@ -192,7 +142,7 @@
 		return error;
 	}
 
-	error = gfs2_dir_read(dir, &offset, &fdr, filldir_func);
+	error = gfs2_dir_read(dir, &offset, dirent, filldir);
 
 	gfs2_glock_dq_uninit(&d_gh);
 
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index d14e139..ee80b8a 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -867,9 +867,9 @@
 		error = -EBUSY;
 		goto error;
 	}
-	mutex_lock(&sb->s_bdev->bd_mount_mutex);
+	down(&sb->s_bdev->bd_mount_sem);
 	new = sget(fs_type, test_bdev_super, set_bdev_super, sb->s_bdev);
-	mutex_unlock(&sb->s_bdev->bd_mount_mutex);
+	up(&sb->s_bdev->bd_mount_sem);
 	if (IS_ERR(new)) {
 		error = PTR_ERR(new);
 		goto error;
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 636dda4..f40a848 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -264,13 +264,23 @@
 	struct gfs2_inode *dip = GFS2_I(dir);
 	struct gfs2_sbd *sdp = GFS2_SB(dir);
 	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-	struct gfs2_holder ghs[2];
+	struct gfs2_holder ghs[3];
+	struct gfs2_rgrpd *rgd;
+	struct gfs2_holder ri_gh;
 	int error;
 
-	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
-	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
+	error = gfs2_rindex_hold(sdp, &ri_gh);
+	if (error)
+		return error;
 
-	error = gfs2_glock_nq_m(2, ghs);
+	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
+	gfs2_holder_init(ip->i_gl,  LM_ST_EXCLUSIVE, 0, ghs + 1);
+
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
+
+
+	error = gfs2_glock_nq_m(3, ghs);
 	if (error)
 		goto out;
 
@@ -291,10 +301,12 @@
 out_end_trans:
 	gfs2_trans_end(sdp);
 out_gunlock:
-	gfs2_glock_dq_m(2, ghs);
+	gfs2_glock_dq_m(3, ghs);
 out:
 	gfs2_holder_uninit(ghs);
 	gfs2_holder_uninit(ghs + 1);
+	gfs2_holder_uninit(ghs + 2);
+	gfs2_glock_dq_uninit(&ri_gh);
 	return error;
 }
 
@@ -449,13 +461,22 @@
 	struct gfs2_inode *dip = GFS2_I(dir);
 	struct gfs2_sbd *sdp = GFS2_SB(dir);
 	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-	struct gfs2_holder ghs[2];
+	struct gfs2_holder ghs[3];
+	struct gfs2_rgrpd *rgd;
+	struct gfs2_holder ri_gh;
 	int error;
 
+
+	error = gfs2_rindex_hold(sdp, &ri_gh);
+	if (error)
+		return error;
 	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
 	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
 
-	error = gfs2_glock_nq_m(2, ghs);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
+
+	error = gfs2_glock_nq_m(3, ghs);
 	if (error)
 		goto out;
 
@@ -483,10 +504,12 @@
 	gfs2_trans_end(sdp);
 
 out_gunlock:
-	gfs2_glock_dq_m(2, ghs);
+	gfs2_glock_dq_m(3, ghs);
 out:
 	gfs2_holder_uninit(ghs);
 	gfs2_holder_uninit(ghs + 1);
+	gfs2_holder_uninit(ghs + 2);
+	gfs2_glock_dq_uninit(&ri_gh);
 	return error;
 }
 
@@ -547,7 +570,8 @@
 	struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
 	struct gfs2_inode *nip = NULL;
 	struct gfs2_sbd *sdp = GFS2_SB(odir);
-	struct gfs2_holder ghs[4], r_gh;
+	struct gfs2_holder ghs[5], r_gh;
+	struct gfs2_rgrpd *nrgd;
 	unsigned int num_gh;
 	int dir_rename = 0;
 	int alloc_required;
@@ -587,6 +611,13 @@
 	if (nip) {
 		gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
 		num_gh++;
+		/* grab the resource lock for unlink flag twiddling 
+		 * this is the case of the target file already existing
+		 * so we unlink before doing the rename
+		 */
+		nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr);
+		if (nrgd)
+			gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
 	}
 
 	error = gfs2_glock_nq_m(num_gh, ghs);
@@ -684,12 +715,12 @@
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
 					 al->al_rgd->rd_ri.ri_length +
 					 4 * RES_DINODE + 4 * RES_LEAF +
-					 RES_STATFS + RES_QUOTA, 0);
+					 RES_STATFS + RES_QUOTA + 4, 0);
 		if (error)
 			goto out_ipreserv;
 	} else {
 		error = gfs2_trans_begin(sdp, 4 * RES_DINODE +
-					 5 * RES_LEAF, 0);
+					 5 * RES_LEAF + 4, 0);
 		if (error)
 			goto out_gunlock;
 	}
@@ -728,7 +759,7 @@
 		error = gfs2_meta_inode_buffer(ip, &dibh);
 		if (error)
 			goto out_end_trans;
-		ip->i_inode.i_ctime.tv_sec = get_seconds();
+		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -1018,7 +1049,7 @@
 	}
 
 	generic_fillattr(inode, stat);
-	if (unlock);
+	if (unlock)
 		gfs2_glock_dq_uninit(&gh);
 
 	return 0;
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 7685b46..47369d0 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -173,6 +173,9 @@
 	struct gfs2_sbd *sdp = sb->s_fs_info;
 	int error;
 
+	if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
+		return;
+
 	for (;;) {
 		error = gfs2_freeze_fs(sdp);
 		if (!error)
@@ -426,6 +429,12 @@
 	}
 
 	error = gfs2_dinode_dealloc(ip);
+	/*
+	 * Must do this before unlock to avoid trying to write back
+	 * potentially dirty data now that inode no longer exists
+	 * on disk.
+	 */
+	truncate_inode_pages(&inode->i_data, 0);
 
 out_unlock:
 	gfs2_glock_dq(&ip->i_iopen_gh);
@@ -443,14 +452,12 @@
 
 static struct inode *gfs2_alloc_inode(struct super_block *sb)
 {
-	struct gfs2_sbd *sdp = sb->s_fs_info;
 	struct gfs2_inode *ip;
 
 	ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL);
 	if (ip) {
 		ip->i_flags = 0;
 		ip->i_gl = NULL;
-		ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default);
 		ip->i_last_pfault = jiffies;
 	}
 	return &ip->i_inode;
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index 45a5f11..14b380f 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -28,34 +28,13 @@
 #include "trans.h"
 #include "util.h"
 
-static void pfault_be_greedy(struct gfs2_inode *ip)
-{
-	unsigned int time;
-
-	spin_lock(&ip->i_spin);
-	time = ip->i_greedy;
-	ip->i_last_pfault = jiffies;
-	spin_unlock(&ip->i_spin);
-
-	igrab(&ip->i_inode);
-	if (gfs2_glock_be_greedy(ip->i_gl, time))
-		iput(&ip->i_inode);
-}
-
 static struct page *gfs2_private_nopage(struct vm_area_struct *area,
 					unsigned long address, int *type)
 {
 	struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host);
-	struct page *result;
 
 	set_bit(GIF_PAGED, &ip->i_flags);
-
-	result = filemap_nopage(area, address, type);
-
-	if (result && result != NOPAGE_OOM)
-		pfault_be_greedy(ip);
-
-	return result;
+	return filemap_nopage(area, address, type);
 }
 
 static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
@@ -167,7 +146,6 @@
 		set_page_dirty(result);
 	}
 
-	pfault_be_greedy(ip);
 out:
 	gfs2_glock_dq_uninit(&i_gh);
 
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 43a24f2..70f424f 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -71,17 +71,12 @@
 	gt->gt_atime_quantum = 3600;
 	gt->gt_new_files_jdata = 0;
 	gt->gt_new_files_directio = 0;
-	gt->gt_max_atomic_write = 4 << 20;
 	gt->gt_max_readahead = 1 << 18;
 	gt->gt_lockdump_size = 131072;
 	gt->gt_stall_secs = 600;
 	gt->gt_complain_secs = 10;
 	gt->gt_reclaim_limit = 5000;
 	gt->gt_entries_per_readdir = 32;
-	gt->gt_prefetch_secs = 10;
-	gt->gt_greedy_default = HZ / 10;
-	gt->gt_greedy_quantum = HZ / 40;
-	gt->gt_greedy_max = HZ / 4;
 	gt->gt_statfs_quantum = 30;
 	gt->gt_statfs_slow = 0;
 }
@@ -359,8 +354,7 @@
 	mutex_lock(&sdp->sd_jindex_mutex);
 
 	for (;;) {
-		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED,
-					   GL_LOCAL_EXCL, ji_gh);
+		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh);
 		if (error)
 			break;
 
@@ -529,8 +523,7 @@
 	struct gfs2_log_header_host head;
 	int error;
 
-	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED,
-				   GL_LOCAL_EXCL, &t_gh);
+	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh);
 	if (error)
 		return error;
 
@@ -583,9 +576,8 @@
 	gfs2_quota_sync(sdp);
 	gfs2_statfs_sync(sdp);
 
-	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED,
-				GL_LOCAL_EXCL | GL_NOCACHE,
-				&t_gh);
+	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
+				   &t_gh);
 	if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
 		return error;
 
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 983eaf1..d01f9f0 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -436,17 +436,12 @@
 TUNE_ATTR(max_readahead, 0);
 TUNE_ATTR(complain_secs, 0);
 TUNE_ATTR(reclaim_limit, 0);
-TUNE_ATTR(prefetch_secs, 0);
 TUNE_ATTR(statfs_slow, 0);
 TUNE_ATTR(new_files_jdata, 0);
 TUNE_ATTR(new_files_directio, 0);
 TUNE_ATTR(quota_simul_sync, 1);
 TUNE_ATTR(quota_cache_secs, 1);
-TUNE_ATTR(max_atomic_write, 1);
 TUNE_ATTR(stall_secs, 1);
-TUNE_ATTR(greedy_default, 1);
-TUNE_ATTR(greedy_quantum, 1);
-TUNE_ATTR(greedy_max, 1);
 TUNE_ATTR(statfs_quantum, 1);
 TUNE_ATTR_DAEMON(scand_secs, scand_process);
 TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
@@ -465,15 +460,10 @@
 	&tune_attr_max_readahead.attr,
 	&tune_attr_complain_secs.attr,
 	&tune_attr_reclaim_limit.attr,
-	&tune_attr_prefetch_secs.attr,
 	&tune_attr_statfs_slow.attr,
 	&tune_attr_quota_simul_sync.attr,
 	&tune_attr_quota_cache_secs.attr,
-	&tune_attr_max_atomic_write.attr,
 	&tune_attr_stall_secs.attr,
-	&tune_attr_greedy_default.attr,
-	&tune_attr_greedy_quantum.attr,
-	&tune_attr_greedy_max.attr,
 	&tune_attr_statfs_quantum.attr,
 	&tune_attr_scand_secs.attr,
 	&tune_attr_recoverd_secs.attr,
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index cca3fb6..70543b1 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -76,7 +76,7 @@
 extern int unlink_file(const char *file);
 extern int do_mkdir(const char *file, int mode);
 extern int do_rmdir(const char *file);
-extern int do_mknod(const char *file, int mode, int dev);
+extern int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor);
 extern int link_file(const char *from, const char *to);
 extern int do_readlink(char *file, char *buf, int size);
 extern int rename_file(char *from, char *to);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 1e6fc37..69a376f 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -755,7 +755,7 @@
 		goto out_put;
 
 	init_special_inode(inode, mode, dev);
-	err = do_mknod(name, mode, dev);
+	err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
 	if(err)
 		goto out_free;
 
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 23b7cee..1ed5ea3 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -295,11 +295,11 @@
 	return(0);
 }
 
-int do_mknod(const char *file, int mode, int dev)
+int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
 {
 	int err;
 
-	err = mknod(file, mode, dev);
+	err = mknod(file, mode, makedev(major, minor));
 	if(err) return(-errno);
 	return(0);
 }
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index 077258b..5a95fbd 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -17,6 +17,7 @@
  *
  */
 #include <linux/slab.h>
+#include <linux/err.h>
 #include <linux/blkdev.h>
 #include <linux/jffs.h>
 #include "jffs_fm.h"
@@ -104,7 +105,7 @@
 
 	mtd = get_mtd_device(NULL, unit);
 
-	if (!mtd) {
+	if (IS_ERR(mtd)) {
 		kfree(fmc);
 		DJM(no_jffs_fmcontrol--);
 		return NULL;
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 72b4fc1..4189e4a 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -178,8 +178,8 @@
 	while (ref2) {
 		uint32_t totlen = ref_totlen(c, jeb, ref2);
 
-		if (ref2->flash_offset < jeb->offset ||
-				ref2->flash_offset > jeb->offset + c->sector_size) {
+		if (ref_offset(ref2) < jeb->offset ||
+				ref_offset(ref2) > jeb->offset + c->sector_size) {
 			JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
 				ref_offset(ref2), jeb->offset);
 			goto error;
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 3daf3bc..f89c85d 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -13,6 +13,7 @@
 #ifndef _JFFS2_DEBUG_H_
 #define _JFFS2_DEBUG_H_
 
+#include <linux/sched.h>
 
 #ifndef CONFIG_JFFS2_FS_DEBUG
 #define CONFIG_JFFS2_FS_DEBUG 0
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 7bc1a42..abb90c0 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -502,12 +502,11 @@
 	if (ret)
 		return ret;
 
-	c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
+	c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
 	if (!c->inocache_list) {
 		ret = -ENOMEM;
 		goto out_wbuf;
 	}
-	memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
 
 	jffs2_init_xattr_subsystem(c);
 
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index daff334..3a3cf22 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -838,6 +838,8 @@
 
 		for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
 
+			cond_resched();
+
 			/* We only care about obsolete ones */
 			if (!(ref_obsolete(raw)))
 				continue;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 0ddfd70..4178b4b5 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -294,23 +294,21 @@
 
 static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
 {
-	struct rb_node *node = root->rb_node;
+	struct rb_node *node = rb_first(root);
 
 	if (!node)
 		return NULL;
-	while(node->rb_left)
-		node = node->rb_left;
+
 	return rb_entry(node, struct jffs2_node_frag, rb);
 }
 
 static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
 {
-	struct rb_node *node = root->rb_node;
+	struct rb_node *node = rb_last(root);
 
 	if (!node)
 		return NULL;
-	while(node->rb_right)
-		node = node->rb_right;
+
 	return rb_entry(node, struct jffs2_node_frag, rb);
 }
 
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 266423b..58a0b91 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -944,13 +944,12 @@
 int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
 {
 	struct jffs2_raw_inode n;
-	struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
+	struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL);
 	int ret;
 
 	if (!f)
 		return -ENOMEM;
 
-	memset(f, 0, sizeof(*f));
 	init_MUTEX_LOCKED(&f->sem);
 	f->inocache = ic;
 
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index e241346..3af746e 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -128,17 +128,19 @@
 	}
 
 	if (jffs2_sum_active()) {
-		s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
+		s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
 		if (!s) {
+			kfree(flashbuf);
 			JFFS2_WARNING("Can't allocate memory for summary\n");
 			return -ENOMEM;
 		}
-		memset(s, 0, sizeof(struct jffs2_summary));
 	}
 
 	for (i=0; i<c->nr_blocks; i++) {
 		struct jffs2_eraseblock *jeb = &c->blocks[i];
 
+		cond_resched();
+
 		/* reset summary info for next eraseblock scan */
 		jffs2_sum_reset_collected(s);
 
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index e52cef5..2526596 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -26,15 +26,13 @@
 
 int jffs2_sum_init(struct jffs2_sb_info *c)
 {
-	c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
+	c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
 
 	if (!c->summary) {
 		JFFS2_WARNING("Can't allocate memory for summary information!\n");
 		return -ENOMEM;
 	}
 
-	memset(c->summary, 0, sizeof(struct jffs2_summary));
-
 	c->summary->sum_buf = vmalloc(c->sector_size);
 
 	if (!c->summary->sum_buf) {
@@ -398,6 +396,8 @@
 	for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
 		dbg_summary("processing summary index %d\n", i);
 
+		cond_resched();
+
 		/* Make sure there's a spare ref for dirty space */
 		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
 		if (err)
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 7deb782..08a0e6c 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
+#include <linux/err.h>
 #include <linux/mount.h>
 #include <linux/jffs2.h>
 #include <linux/pagemap.h>
@@ -184,9 +185,9 @@
 	struct mtd_info *mtd;
 
 	mtd = get_mtd_device(NULL, mtdnr);
-	if (!mtd) {
+	if (IS_ERR(mtd)) {
 		D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
-		return -EINVAL;
+		return PTR_ERR(mtd);
 	}
 
 	return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
@@ -221,7 +222,7 @@
 			D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
 			for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
 				mtd = get_mtd_device(NULL, mtdnr);
-				if (mtd) {
+				if (!IS_ERR(mtd)) {
 					if (!strcmp(mtd->name, dev_name+4))
 						return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
 					put_mtd_device(mtd);
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index fc211b6..b90d5aa 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -51,7 +51,7 @@
 	 */
 
 	if (!p) {
-		printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n");
+		printk(KERN_ERR "jffs2_follow_link(): can't find symlink target\n");
 		p = ERR_PTR(-EIO);
 	}
 	D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target));
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 7070730..9c99859 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -969,8 +969,7 @@
 	int oobsize = c->mtd->oobsize;
 	struct mtd_oob_ops ops;
 
-	ops.len = NR_OOB_SCAN_PAGES * oobsize;
-	ops.ooblen = oobsize;
+	ops.ooblen = NR_OOB_SCAN_PAGES * oobsize;
 	ops.oobbuf = c->oobbuf;
 	ops.ooboffs = 0;
 	ops.datbuf = NULL;
@@ -983,10 +982,10 @@
 		return ret;
 	}
 
-	if (ops.retlen < ops.len) {
+	if (ops.oobretlen < ops.ooblen) {
 		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
 			  "returned short read (%zd bytes not %d) for block "
-			  "at %08x\n", ops.retlen, ops.len, jeb->offset));
+			  "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset));
 		return -EIO;
 	}
 
@@ -1005,7 +1004,7 @@
 	}
 
 	/* we know, we are aligned :) */
-	for (page = oobsize; page < ops.len; page += sizeof(long)) {
+	for (page = oobsize; page < ops.ooblen; page += sizeof(long)) {
 		long dat = *(long *)(&ops.oobbuf[page]);
 		if(dat != -1)
 			return 1;
@@ -1033,7 +1032,6 @@
 		return 2;
 	}
 
-	ops.len = oobsize;
 	ops.ooblen = oobsize;
 	ops.oobbuf = c->oobbuf;
 	ops.ooboffs = 0;
@@ -1048,10 +1046,10 @@
 		return ret;
 	}
 
-	if (ops.retlen < ops.len) {
+	if (ops.oobretlen < ops.ooblen) {
 		D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
 			    "Read OOB return short read (%zd bytes not %d) "
-			    "for block at %08x\n", ops.retlen, ops.len,
+			    "for block at %08x\n", ops.oobretlen, ops.ooblen,
 			    jeb->offset));
 		return -EIO;
 	}
@@ -1090,8 +1088,7 @@
 	n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
 	n.totlen = cpu_to_je32(8);
 
-	ops.len = c->fsdata_len;
-	ops.ooblen = c->fsdata_len;;
+	ops.ooblen = c->fsdata_len;
 	ops.oobbuf = (uint8_t *)&n;
 	ops.ooboffs = c->fsdata_pos;
 	ops.datbuf = NULL;
@@ -1105,10 +1102,10 @@
 			  jeb->offset, ret));
 		return ret;
 	}
-	if (ops.retlen != ops.len) {
+	if (ops.oobretlen != ops.ooblen) {
 		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
 			  "Short write for block at %08x: %zd not %d\n",
-			  jeb->offset, ops.retlen, ops.len));
+			  jeb->offset, ops.oobretlen, ops.ooblen));
 		return -EIO;
 	}
 	return 0;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 4da09ce..4bb3f18 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -399,8 +399,6 @@
 {
 	/* must be called under down_write(xattr_sem) */
 	if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
-		uint32_t xid = xd->xid, version = xd->version;
-
 		unload_xattr_datum(c, xd);
 		xd->flags |= JFFS2_XFLAGS_DEAD;
 		if (xd->node == (void *)xd) {
@@ -411,7 +409,8 @@
 		}
 		spin_unlock(&c->erase_completion_lock);
 
-		dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version);
+		dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n",
+			  xd->xid, xd->version);
 	}
 }
 
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 0627077..f4d45d4 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -176,7 +176,7 @@
 	lock_kernel();
 	lockd_up(0); /* note: this cannot fail as lockd is already running */
 
-	dprintk("lockd: reclaiming locks for host %s", host->h_name);
+	dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
 
 restart:
 	nsmstate = host->h_nsmstate;
@@ -206,7 +206,7 @@
 
 	host->h_reclaiming = 0;
 	up_write(&host->h_rwsem);
-	dprintk("NLM: done reclaiming locks for host %s", host->h_name);
+	dprintk("NLM: done reclaiming locks for host %s\n", host->h_name);
 
 	/* Now, wake up all processes that sleep on a blocked lock */
 	list_for_each_entry(block, &nlm_blocked, b_list) {
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index dee3d6c..d9ba8cb 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -532,7 +532,7 @@
 
 	lock_kernel();
 
-	res = nfs_revalidate_mapping(inode, filp->f_mapping);
+	res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping);
 	if (res < 0) {
 		unlock_kernel();
 		return res;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 0dd6be3..9e4a2b7 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -315,14 +315,13 @@
 
 static int nfs_release_page(struct page *page, gfp_t gfp)
 {
-	/*
-	 * Avoid deadlock on nfs_wait_on_request().
-	 */
-	if (!(gfp & __GFP_FS))
-		return 0;
-	/* Hack... Force nfs_wb_page() to write out the page */
-	SetPageDirty(page);
-	return !nfs_wb_page(page->mapping->host, page);
+	/* If PagePrivate() is set, then the page is not freeable */
+	return 0;
+}
+
+static int nfs_launder_page(struct page *page)
+{
+	return nfs_wb_page(page->mapping->host, page);
 }
 
 const struct address_space_operations nfs_file_aops = {
@@ -338,6 +337,7 @@
 #ifdef CONFIG_NFS_DIRECTIO
 	.direct_IO = nfs_direct_IO,
 #endif
+	.launder_page = nfs_launder_page,
 };
 
 static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
@@ -434,8 +434,9 @@
 			BUG();
 	}
 	if (res < 0)
-		printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
-				__FUNCTION__);
+		dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager"
+			" - error %d!\n",
+				__FUNCTION__, res);
 	return res;
 }
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 63e4702..d834982 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -665,49 +665,86 @@
 	return __nfs_revalidate_inode(server, inode);
 }
 
+static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	
+	if (mapping->nrpages != 0) {
+		int ret = invalidate_inode_pages2(mapping);
+		if (ret < 0)
+			return ret;
+	}
+	spin_lock(&inode->i_lock);
+	nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
+	if (S_ISDIR(inode->i_mode)) {
+		memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
+		/* This ensures we revalidate child dentries */
+		nfsi->cache_change_attribute = jiffies;
+	}
+	spin_unlock(&inode->i_lock);
+	nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
+	dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
+			inode->i_sb->s_id, (long long)NFS_FILEID(inode));
+	return 0;
+}
+
+static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
+{
+	int ret = 0;
+
+	mutex_lock(&inode->i_mutex);
+	if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_DATA) {
+		ret = nfs_sync_mapping(mapping);
+		if (ret == 0)
+			ret = nfs_invalidate_mapping_nolock(inode, mapping);
+	}
+	mutex_unlock(&inode->i_mutex);
+	return ret;
+}
+
+/**
+ * nfs_revalidate_mapping_nolock - Revalidate the pagecache
+ * @inode - pointer to host inode
+ * @mapping - pointer to mapping
+ */
+int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int ret = 0;
+
+	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
+			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
+		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		if (ret < 0)
+			goto out;
+	}
+	if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
+		ret = nfs_invalidate_mapping_nolock(inode, mapping);
+out:
+	return ret;
+}
+
 /**
  * nfs_revalidate_mapping - Revalidate the pagecache
  * @inode - pointer to host inode
  * @mapping - pointer to mapping
+ *
+ * This version of the function will take the inode->i_mutex and attempt to
+ * flush out all dirty data if it needs to invalidate the page cache.
  */
 int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int ret = 0;
 
-	if (NFS_STALE(inode))
-		ret = -ESTALE;
 	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
-			|| nfs_attribute_timeout(inode))
+			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
 		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-	if (ret < 0)
-		goto out;
-
-	if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
-		if (mapping->nrpages != 0) {
-			if (S_ISREG(inode->i_mode)) {
-				ret = nfs_sync_mapping(mapping);
-				if (ret < 0)
-					goto out;
-			}
-			ret = invalidate_inode_pages2(mapping);
-			if (ret < 0)
-				goto out;
-		}
-		spin_lock(&inode->i_lock);
-		nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
-		if (S_ISDIR(inode->i_mode)) {
-			memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
-			/* This ensures we revalidate child dentries */
-			nfsi->cache_change_attribute = jiffies;
-		}
-		spin_unlock(&inode->i_lock);
-
-		nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
-		dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
-				inode->i_sb->s_id,
-				(long long)NFS_FILEID(inode));
+		if (ret < 0)
+			goto out;
 	}
+	if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
+		ret = nfs_invalidate_mapping(inode, mapping);
 out:
 	return ret;
 }
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 6c68611..525c136 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -50,7 +50,9 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct page *page;
-	void *err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
+	void *err;
+
+	err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
 	if (err)
 		goto read_failed;
 	page = read_cache_page(&inode->i_data, 0,
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 248dd92..49c310b 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -35,7 +35,6 @@
 #include <linux/lockd/bind.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
-#define NFSD_PARANOIA 1
 
 typedef struct auth_domain	svc_client;
 typedef struct svc_export	svc_export;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 277df40..e695660 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -990,15 +990,16 @@
 }
 
 int
-nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
-		     int namlen, loff_t offset, ino_t ino, unsigned int d_type)
+nfs3svc_encode_entry(void *cd, const char *name,
+		     int namlen, loff_t offset, u64 ino, unsigned int d_type)
 {
 	return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
 }
 
 int
-nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
-			  int namlen, loff_t offset, ino_t ino, unsigned int d_type)
+nfs3svc_encode_entry_plus(void *cd, const char *name,
+			  int namlen, loff_t offset, u64 ino,
+			  unsigned int d_type)
 {
 	return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
 }
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fea4636..18aa944 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1880,9 +1880,10 @@
 }
 
 static int
-nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
-		    loff_t offset, ino_t ino, unsigned int d_type)
+nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+		    loff_t offset, u64 ino, unsigned int d_type)
 {
+	struct readdir_cd *ccd = ccdv;
 	struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
 	int buflen;
 	__be32 *p = cd->buffer;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index b06bf9f..c59d6fb 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -24,8 +24,6 @@
 #include <linux/nfsd/nfsd.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_FH
-#define NFSD_PARANOIA 1
-/* #define NFSD_DEBUG_VERBOSE 1 */
 
 
 static int nfsd_nr_verified;
@@ -230,13 +228,12 @@
 				error = nfserrno(PTR_ERR(dentry));
 			goto out;
 		}
-#ifdef NFSD_PARANOIA
+
 		if (S_ISDIR(dentry->d_inode->i_mode) &&
 		    (dentry->d_flags & DCACHE_DISCONNECTED)) {
 			printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
 			       dentry->d_parent->d_name.name, dentry->d_name.name);
 		}
-#endif
 
 		fhp->fh_dentry = dentry;
 		fhp->fh_export = exp;
@@ -267,12 +264,13 @@
 	/* Finally, check access permissions. */
 	error = nfsd_permission(exp, dentry, access);
 
-#ifdef NFSD_PARANOIA_EXTREME
 	if (error) {
-		printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
-		       dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
+		dprintk("fh_verify: %s/%s permission failure, "
+			"acc=%x, error=%d\n",
+			dentry->d_parent->d_name.name,
+			dentry->d_name.name,
+			access, ntohl(error));
 	}
-#endif
 out:
 	if (exp && !IS_ERR(exp))
 		exp_put(exp);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 0aaccb0..fbf5d51 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -72,7 +72,7 @@
 	.pg_prog		= NFS_ACL_PROGRAM,
 	.pg_nvers		= NFSD_ACL_NRVERS,
 	.pg_vers		= nfsd_acl_versions,
-	.pg_name		= "nfsd",
+	.pg_name		= "nfsacl",
 	.pg_class		= "nfsd",
 	.pg_stats		= &nfsd_acl_svcstats,
 	.pg_authenticate	= &svc_set_client,
@@ -118,16 +118,16 @@
 	switch(change) {
 	case NFSD_SET:
 		nfsd_versions[vers] = nfsd_version[vers];
-		break;
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 		if (vers < NFSD_ACL_NRVERS)
-			nfsd_acl_version[vers] = nfsd_acl_version[vers];
+			nfsd_acl_versions[vers] = nfsd_acl_version[vers];
 #endif
+		break;
 	case NFSD_CLEAR:
 		nfsd_versions[vers] = NULL;
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 		if (vers < NFSD_ACL_NRVERS)
-			nfsd_acl_version[vers] = NULL;
+			nfsd_acl_versions[vers] = NULL;
 #endif
 		break;
 	case NFSD_TEST:
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index f5243f9..6555c50 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -462,9 +462,10 @@
 }
 
 int
-nfssvc_encode_entry(struct readdir_cd *ccd, const char *name,
-		    int namlen, loff_t offset, ino_t ino, unsigned int d_type)
+nfssvc_encode_entry(void *ccdv, const char *name,
+		    int namlen, loff_t offset, u64 ino, unsigned int d_type)
 {
+	struct readdir_cd *ccd = ccdv;
 	struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common);
 	__be32	*p = cd->buffer;
 	int	buflen, slen;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7a79c23..8283236 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -59,7 +59,6 @@
 #include <asm/uaccess.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_FILEOP
-#define NFSD_PARANOIA
 
 
 /* We must ignore files (but only files) which might have mandatory
@@ -822,7 +821,8 @@
 		rqstp->rq_res.page_len = size;
 	} else if (page != pp[-1]) {
 		get_page(page);
-		put_page(*pp);
+		if (*pp)
+			put_page(*pp);
 		*pp = page;
 		rqstp->rq_resused++;
 		rqstp->rq_res.page_len += size;
@@ -1244,7 +1244,6 @@
 	__be32		err;
 	int		host_err;
 	__u32		v_mtime=0, v_atime=0;
-	int		v_mode=0;
 
 	err = nfserr_perm;
 	if (!flen)
@@ -1281,16 +1280,11 @@
 		goto out;
 
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
-		/* while the verifier would fit in mtime+atime,
-		 * solaris7 gets confused (bugid 4218508) if these have
-		 * the high bit set, so we use the mode as well
+		/* solaris7 gets confused (bugid 4218508) if these have
+		 * the high bit set, so just clear the high bits.
 		 */
 		v_mtime = verifier[0]&0x7fffffff;
 		v_atime = verifier[1]&0x7fffffff;
-		v_mode  = S_IFREG
-			| ((verifier[0]&0x80000000) >> (32-7)) /* u+x */
-			| ((verifier[1]&0x80000000) >> (32-9)) /* u+r */
-			;
 	}
 	
 	if (dchild->d_inode) {
@@ -1318,7 +1312,6 @@
 		case NFS3_CREATE_EXCLUSIVE:
 			if (   dchild->d_inode->i_mtime.tv_sec == v_mtime
 			    && dchild->d_inode->i_atime.tv_sec == v_atime
-			    && dchild->d_inode->i_mode  == v_mode
 			    && dchild->d_inode->i_size  == 0 )
 				break;
 			 /* fallthru */
@@ -1340,26 +1333,22 @@
 	}
 
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
-		/* Cram the verifier into atime/mtime/mode */
+		/* Cram the verifier into atime/mtime */
 		iap->ia_valid = ATTR_MTIME|ATTR_ATIME
-			| ATTR_MTIME_SET|ATTR_ATIME_SET
-			| ATTR_MODE;
+			| ATTR_MTIME_SET|ATTR_ATIME_SET;
 		/* XXX someone who knows this better please fix it for nsec */ 
 		iap->ia_mtime.tv_sec = v_mtime;
 		iap->ia_atime.tv_sec = v_atime;
 		iap->ia_mtime.tv_nsec = 0;
 		iap->ia_atime.tv_nsec = 0;
-		iap->ia_mode  = v_mode;
 	}
 
 	/* Set file attributes.
-	 * Mode has already been set but we might need to reset it
-	 * for CREATE_EXCLUSIVE
 	 * Irix appears to send along the gid when it tries to
 	 * implement setgid directories via NFS. Clear out all that cruft.
 	 */
  set_attr:
-	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
+	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
  		__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
 		if (err2)
 			err = err2;
@@ -1726,7 +1715,7 @@
  */
 __be32
 nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, 
-	     struct readdir_cd *cdp, encode_dent_fn func)
+	     struct readdir_cd *cdp, filldir_t func)
 {
 	__be32		err;
 	int 		host_err;
@@ -1751,7 +1740,7 @@
 
 	do {
 		cdp->err = nfserr_eof; /* will be cleared on successful read */
-		host_err = vfs_readdir(file, (filldir_t) func, cdp);
+		host_err = vfs_readdir(file, func, cdp);
 	} while (host_err >=0 && cdp->err == nfs_ok);
 	if (host_err)
 		err = nfserrno(host_err);
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 35cc4b1..af4ef80 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -17,6 +17,13 @@
 	  happen is unclear however so it is worth waiting until someone hits
 	  the problem.
 
+2.1.28 - Fix a deadlock.
+
+	- Fix deadlock in fs/ntfs/inode.c::ntfs_put_inode().  Thanks to Sergey
+	  Vlasov for the report and detailed analysis of the deadlock.  The fix
+	  involved getting rid of ntfs_put_inode() altogether and hence NTFS no
+	  longer has a ->put_inode super operation.
+
 2.1.27 - Various bug fixes and cleanups.
 
 	- Fix two compiler warnings on Alpha.  Thanks to Andrew Morton for
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index e27b4ea..8255083 100644
--- a/fs/ntfs/Makefile
+++ b/fs/ntfs/Makefile
@@ -6,7 +6,7 @@
 	     index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
 	     unistr.o upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.27\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.28\"
 
 ifeq ($(CONFIG_NTFS_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 7b2c8f4..629e7ab 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -92,10 +92,12 @@
 			ofs = 0;
 			if (file_ofs < init_size)
 				ofs = init_size - file_ofs;
+			local_irq_save(flags);
 			kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
 			memset(kaddr + bh_offset(bh) + ofs, 0,
 					bh->b_size - ofs);
 			kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+			local_irq_restore(flags);
 			flush_dcache_page(page);
 		}
 	} else {
@@ -143,11 +145,13 @@
 		recs = PAGE_CACHE_SIZE / rec_size;
 		/* Should have been verified before we got here... */
 		BUG_ON(!recs);
+		local_irq_save(flags);
 		kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
 		for (i = 0; i < recs; i++)
 			post_read_mst_fixup((NTFS_RECORD*)(kaddr +
 					i * rec_size), rec_size);
 		kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+		local_irq_restore(flags);
 		flush_dcache_page(page);
 		if (likely(page_uptodate && !PageError(page)))
 			SetPageUptodate(page);
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 8296c29..74f99a6 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1,7 +1,7 @@
 /**
  * dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2005 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  * Copyright (c) 2002 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -1249,16 +1249,12 @@
 	/* Get the offset into the index allocation attribute. */
 	ia_pos = (s64)fpos - vol->mft_record_size;
 	ia_mapping = vdir->i_mapping;
-	bmp_vi = ndir->itype.index.bmp_ino;
-	if (unlikely(!bmp_vi)) {
-		ntfs_debug("Inode 0x%lx, regetting index bitmap.", vdir->i_ino);
-		bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
-		if (IS_ERR(bmp_vi)) {
-			ntfs_error(sb, "Failed to get bitmap attribute.");
-			err = PTR_ERR(bmp_vi);
-			goto err_out;
-		}
-		ndir->itype.index.bmp_ino = bmp_vi;
+	ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino);
+	bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
+	if (IS_ERR(bmp_vi)) {
+		ntfs_error(sb, "Failed to get bitmap attribute.");
+		err = PTR_ERR(bmp_vi);
+		goto err_out;
 	}
 	bmp_mapping = bmp_vi->i_mapping;
 	/* Get the starting bitmap bit position and sanity check it. */
@@ -1266,7 +1262,7 @@
 	if (unlikely(bmp_pos >> 3 >= i_size_read(bmp_vi))) {
 		ntfs_error(sb, "Current index allocation position exceeds "
 				"index bitmap size.");
-		goto err_out;
+		goto iput_err_out;
 	}
 	/* Get the starting bit position in the current bitmap page. */
 	cur_bmp_pos = bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1);
@@ -1282,7 +1278,7 @@
 		ntfs_error(sb, "Reading index bitmap failed.");
 		err = PTR_ERR(bmp_page);
 		bmp_page = NULL;
-		goto err_out;
+		goto iput_err_out;
 	}
 	bmp = (u8*)page_address(bmp_page);
 	/* Find next index block in use. */
@@ -1429,6 +1425,7 @@
 			/* @ia_page is already unlocked in this case. */
 			ntfs_unmap_page(ia_page);
 			ntfs_unmap_page(bmp_page);
+			iput(bmp_vi);
 			goto abort;
 		}
 	}
@@ -1439,6 +1436,7 @@
 		ntfs_unmap_page(ia_page);
 	}
 	ntfs_unmap_page(bmp_page);
+	iput(bmp_vi);
 EOD:
 	/* We are finished, set fpos to EOD. */
 	fpos = i_size + vol->mft_record_size;
@@ -1455,8 +1453,11 @@
 	filp->f_pos = fpos;
 	return 0;
 err_out:
-	if (bmp_page)
+	if (bmp_page) {
 		ntfs_unmap_page(bmp_page);
+iput_err_out:
+		iput(bmp_vi);
+	}
 	if (ia_page) {
 		unlock_page(ia_page);
 		ntfs_unmap_page(ia_page);
@@ -1529,14 +1530,22 @@
 static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
 		int datasync)
 {
-	struct inode *vi = dentry->d_inode;
-	ntfs_inode *ni = NTFS_I(vi);
+	struct inode *bmp_vi, *vi = dentry->d_inode;
 	int err, ret;
+	ntfs_attr na;
 
 	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
 	BUG_ON(!S_ISDIR(vi->i_mode));
-	if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino)
-		write_inode_now(ni->itype.index.bmp_ino, !datasync);
+	/* If the bitmap attribute inode is in memory sync it, too. */
+	na.mft_no = vi->i_ino;
+	na.type = AT_BITMAP;
+	na.name = I30;
+	na.name_len = 4;
+	bmp_vi = ilookup5(vi->i_sb, vi->i_ino, (test_t)ntfs_test_inode, &na);
+	if (bmp_vi) {
+ 		write_inode_now(bmp_vi, !datasync);
+		iput(bmp_vi);
+	}
 	ret = ntfs_write_inode(vi, 1);
 	write_inode_now(vi, !datasync);
 	err = sync_blockdev(vi->i_sb->s_bdev);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 2479898..f8bf8da 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1,7 +1,7 @@
 /**
  * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2006 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
@@ -95,7 +95,7 @@
  * If initializing the normal file/directory inode, set @na->type to AT_UNUSED.
  * In that case, @na->name and @na->name_len should be set to NULL and 0,
  * respectively. Although that is not strictly necessary as
- * ntfs_read_inode_locked() will fill them in later.
+ * ntfs_read_locked_inode() will fill them in later.
  *
  * Return 0 on success and -errno on error.
  *
@@ -171,8 +171,8 @@
 struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no)
 {
 	struct inode *vi;
-	ntfs_attr na;
 	int err;
+	ntfs_attr na;
 
 	na.mft_no = mft_no;
 	na.type = AT_UNUSED;
@@ -229,8 +229,8 @@
 		ntfschar *name, u32 name_len)
 {
 	struct inode *vi;
-	ntfs_attr na;
 	int err;
+	ntfs_attr na;
 
 	/* Make sure no one calls ntfs_attr_iget() for indices. */
 	BUG_ON(type == AT_INDEX_ALLOCATION);
@@ -287,8 +287,8 @@
 		u32 name_len)
 {
 	struct inode *vi;
-	ntfs_attr na;
 	int err;
+	ntfs_attr na;
 
 	na.mft_no = base_vi->i_ino;
 	na.type = AT_INDEX_ALLOCATION;
@@ -402,7 +402,6 @@
 	ntfs_init_runlist(&ni->attr_list_rl);
 	lockdep_set_class(&ni->attr_list_rl.lock,
 				&attr_list_rl_lock_class);
-	ni->itype.index.bmp_ino = NULL;
 	ni->itype.index.block_size = 0;
 	ni->itype.index.vcn_size = 0;
 	ni->itype.index.collation_rule = 0;
@@ -546,6 +545,7 @@
 {
 	ntfs_volume *vol = NTFS_SB(vi->i_sb);
 	ntfs_inode *ni;
+	struct inode *bvi;
 	MFT_RECORD *m;
 	ATTR_RECORD *a;
 	STANDARD_INFORMATION *si;
@@ -780,7 +780,6 @@
 	 */
 	if (S_ISDIR(vi->i_mode)) {
 		loff_t bvi_size;
-		struct inode *bvi;
 		ntfs_inode *bni;
 		INDEX_ROOT *ir;
 		u8 *ir_end, *index_end;
@@ -985,13 +984,12 @@
 			err = PTR_ERR(bvi);
 			goto unm_err_out;
 		}
-		ni->itype.index.bmp_ino = bvi;
 		bni = NTFS_I(bvi);
 		if (NInoCompressed(bni) || NInoEncrypted(bni) ||
 				NInoSparse(bni)) {
 			ntfs_error(vi->i_sb, "$BITMAP attribute is compressed "
 					"and/or encrypted and/or sparse.");
-			goto unm_err_out;
+			goto iput_unm_err_out;
 		}
 		/* Consistency check bitmap size vs. index allocation size. */
 		bvi_size = i_size_read(bvi);
@@ -1000,8 +998,10 @@
 			ntfs_error(vi->i_sb, "Index bitmap too small (0x%llx) "
 					"for index allocation (0x%llx).",
 					bvi_size << 3, vi->i_size);
-			goto unm_err_out;
+			goto iput_unm_err_out;
 		}
+		/* No longer need the bitmap attribute inode. */
+		iput(bvi);
 skip_large_dir_stuff:
 		/* Setup the operations for this inode. */
 		vi->i_op = &ntfs_dir_inode_ops;
@@ -1176,7 +1176,8 @@
 		vi->i_blocks = ni->allocated_size >> 9;
 	ntfs_debug("Done.");
 	return 0;
-
+iput_unm_err_out:
+	iput(bvi);
 unm_err_out:
 	if (!err)
 		err = -EIO;
@@ -1697,7 +1698,7 @@
 				vi->i_size);
 		goto iput_unm_err_out;
 	}
-	ni->itype.index.bmp_ino = bvi;
+	iput(bvi);
 skip_large_index_stuff:
 	/* Setup the operations for this index inode. */
 	vi->i_op = NULL;
@@ -1714,7 +1715,6 @@
 
 	ntfs_debug("Done.");
 	return 0;
-
 iput_unm_err_out:
 	iput(bvi);
 unm_err_out:
@@ -2191,37 +2191,6 @@
 	return -1;
 }
 
-/**
- * ntfs_put_inode - handler for when the inode reference count is decremented
- * @vi:		vfs inode
- *
- * The VFS calls ntfs_put_inode() every time the inode reference count (i_count)
- * is about to be decremented (but before the decrement itself.
- *
- * If the inode @vi is a directory with two references, one of which is being
- * dropped, we need to put the attribute inode for the directory index bitmap,
- * if it is present, otherwise the directory inode would remain pinned for
- * ever.
- */
-void ntfs_put_inode(struct inode *vi)
-{
-	if (S_ISDIR(vi->i_mode) && atomic_read(&vi->i_count) == 2) {
-		ntfs_inode *ni = NTFS_I(vi);
-		if (NInoIndexAllocPresent(ni)) {
-			struct inode *bvi = NULL;
-			mutex_lock(&vi->i_mutex);
-			if (atomic_read(&vi->i_count) == 2) {
-				bvi = ni->itype.index.bmp_ino;
-				if (bvi)
-					ni->itype.index.bmp_ino = NULL;
-			}
-			mutex_unlock(&vi->i_mutex);
-			if (bvi)
-				iput(bvi);
-		}
-	}
-}
-
 static void __ntfs_clear_inode(ntfs_inode *ni)
 {
 	/* Free all alocated memory. */
@@ -2287,18 +2256,6 @@
 {
 	ntfs_inode *ni = NTFS_I(vi);
 
-	/*
-	 * If the inode @vi is an index inode we need to put the attribute
-	 * inode for the index bitmap, if it is present, otherwise the index
-	 * inode would disappear and the attribute inode for the index bitmap
-	 * would no longer be referenced from anywhere and thus it would remain
-	 * pinned for ever.
-	 */
-	if (NInoAttr(ni) && (ni->type == AT_INDEX_ALLOCATION) &&
-			NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino) {
-		iput(ni->itype.index.bmp_ino);
-		ni->itype.index.bmp_ino = NULL;
-	}
 #ifdef NTFS_RW
 	if (NInoDirty(ni)) {
 		bool was_bad = (is_bad_inode(vi));
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index f088291..117eaf8 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -2,7 +2,7 @@
  * inode.h - Defines for inode structures NTFS Linux kernel driver. Part of
  *	     the Linux-NTFS project.
  *
- * Copyright (c) 2001-2005 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  * Copyright (c) 2002 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -101,8 +101,6 @@
 	runlist attr_list_rl;	/* Run list for the attribute list value. */
 	union {
 		struct { /* It is a directory, $MFT, or an index inode. */
-			struct inode *bmp_ino;	/* Attribute inode for the
-						   index $BITMAP. */
 			u32 block_size;		/* Size of an index block. */
 			u32 vcn_size;		/* Size of a vcn in this
 						   index. */
@@ -300,8 +298,6 @@
 
 extern int ntfs_read_inode_mount(struct inode *vi);
 
-extern void ntfs_put_inode(struct inode *vi);
-
 extern int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt);
 
 #ifdef NTFS_RW
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 03a391a..babf94d 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -1,7 +1,7 @@
 /*
  * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2006 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  * Copyright (c) 2001,2002 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -2702,9 +2702,6 @@
 static struct super_operations ntfs_sops = {
 	.alloc_inode	= ntfs_alloc_big_inode,	  /* VFS: Allocate new inode. */
 	.destroy_inode	= ntfs_destroy_big_inode, /* VFS: Deallocate inode. */
-	.put_inode	= ntfs_put_inode,	  /* VFS: Called just before
-						     the inode reference count
-						     is decreased. */
 #ifdef NTFS_RW
 	//.dirty_inode	= NULL,			/* VFS: Called from
 	//					   __mark_inode_dirty(). */
@@ -3261,7 +3258,7 @@
 }
 
 MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>");
-MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2006 Anton Altaparmakov");
+MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2007 Anton Altaparmakov");
 MODULE_VERSION(NTFS_VERSION);
 MODULE_LICENSE("GPL");
 #ifdef DEBUG
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 06be6e7..56e1fef 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -60,14 +60,11 @@
 
 	inode = ocfs2_iget(OCFS2_SB(sb), handle->ih_blkno, 0);
 
-	if (IS_ERR(inode)) {
-		mlog_errno(PTR_ERR(inode));
+	if (IS_ERR(inode))
 		return (void *)inode;
-	}
 
 	if (handle->ih_generation != inode->i_generation) {
 		iput(inode);
-		mlog_errno(-ESTALE);
 		return ERR_PTR(-ESTALE);
 	}
 
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index e4d9149..28ab56f 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -146,7 +146,6 @@
 	if (is_bad_inode(inode)) {
 		iput(inode);
 		inode = ERR_PTR(-ESTALE);
-		mlog_errno(PTR_ERR(inode));
 		goto bail;
 	}
 
@@ -155,8 +154,7 @@
 		mlog(0, "returning inode with number %llu\n",
 		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
 		mlog_exit_ptr(inode);
-	} else
-		mlog_errno(PTR_ERR(inode));
+	}
 
 	return inode;
 }
@@ -247,7 +245,7 @@
 	 * today.  change if needed. */
 	if (!OCFS2_IS_VALID_DINODE(fe) ||
 	    !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
-		mlog(ML_ERROR, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "
+		mlog(0, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "
 		     "signature = %.*s, flags = 0x%x\n",
 		     inode->i_ino,
 		     (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
@@ -478,11 +476,8 @@
 	    S_ISBLK(le16_to_cpu(fe->i_mode)))
     		inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
 
-	if (ocfs2_populate_inode(inode, fe, 0) < 0) {
-		mlog(ML_ERROR, "populate failed! i_blkno=%llu, i_ino=%lu\n",
-		     (unsigned long long)fe->i_blkno, inode->i_ino);
+	if (ocfs2_populate_inode(inode, fe, 0) < 0)
 		goto bail;
-	}
 
 	BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
 
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index e121636..d026b4f 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -306,8 +306,8 @@
  * for the dinode, one for the new block. */
 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
 
-/* file update (nlink, etc) + dir entry block */
-#define OCFS2_LINK_CREDITS  (OCFS2_INODE_UPDATE_CREDITS + 1)
+/* file update (nlink, etc) + directory mtime/ctime + dir entry block */
+#define OCFS2_LINK_CREDITS  (2*OCFS2_INODE_UPDATE_CREDITS + 1)
 
 /* inode + dir inode (if we unlink a dir), + dir entry block + orphan
  * dir inode link */
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 9637039..f3d7803 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -932,14 +932,15 @@
 		goto leave;
 	}
 
-	if (S_ISDIR(inode->i_mode)) {
+	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	if (S_ISDIR(inode->i_mode))
 		drop_nlink(dir);
-		status = ocfs2_mark_inode_dirty(handle, dir,
-						parent_node_bh);
-		if (status < 0) {
-			mlog_errno(status);
+
+	status = ocfs2_mark_inode_dirty(handle, dir, parent_node_bh);
+	if (status < 0) {
+		mlog_errno(status);
+		if (S_ISDIR(inode->i_mode))
 			inc_nlink(dir);
-		}
 	}
 
 leave:
@@ -1068,6 +1069,7 @@
 	char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
 	struct buffer_head *orphan_entry_bh = NULL;
 	struct buffer_head *newfe_bh = NULL;
+	struct buffer_head *old_inode_bh = NULL;
 	struct buffer_head *insert_entry_bh = NULL;
 	struct ocfs2_super *osb = NULL;
 	u64 newfe_blkno;
@@ -1079,7 +1081,7 @@
 	struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above
 	struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
 						    // this is the 1st dirent bh
-	nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
+	nlink_t old_dir_nlink = old_dir->i_nlink;
 
 	/* At some point it might be nice to break this function up a
 	 * bit. */
@@ -1139,12 +1141,11 @@
 	}
 
 	/*
-	 * Though we don't require an inode meta data update if
-	 * old_inode is not a directory, we lock anyway here to ensure
-	 * the vote thread on other nodes won't have to concurrently
-	 * downconvert the inode and the dentry locks.
+	 * Aside from allowing a meta data update, the locking here
+	 * also ensures that the vote thread on other nodes won't have
+	 * to concurrently downconvert the inode and the dentry locks.
 	 */
-	status = ocfs2_meta_lock(old_inode, NULL, 1);
+	status = ocfs2_meta_lock(old_inode, &old_inode_bh, 1);
 	if (status < 0) {
 		if (status != -ENOENT)
 			mlog_errno(status);
@@ -1355,6 +1356,7 @@
 
 	old_inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(old_inode);
+	ocfs2_mark_inode_dirty(handle, old_inode, old_inode_bh);
 
 	/* now that the name has been added to new_dir, remove the old name */
 	status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh);
@@ -1384,27 +1386,22 @@
 		}
 	}
 	mark_inode_dirty(old_dir);
-	if (new_inode)
+	ocfs2_mark_inode_dirty(handle, old_dir, old_dir_bh);
+	if (new_inode) {
 		mark_inode_dirty(new_inode);
+		ocfs2_mark_inode_dirty(handle, new_inode, newfe_bh);
+	}
 
-	if (old_dir != new_dir)
-		if (new_dir_nlink != new_dir->i_nlink) {
-			if (!new_dir_bh) {
-				mlog(ML_ERROR, "need to change nlink for new "
-				     "dir %llu from %d to %d but bh is NULL\n",
-				     (unsigned long long)OCFS2_I(new_dir)->ip_blkno,
-				     (int)new_dir_nlink, new_dir->i_nlink);
-			} else {
-				struct ocfs2_dinode *fe;
-				status = ocfs2_journal_access(handle,
-							      new_dir,
-							      new_dir_bh,
-							      OCFS2_JOURNAL_ACCESS_WRITE);
-				fe = (struct ocfs2_dinode *) new_dir_bh->b_data;
-				fe->i_links_count = cpu_to_le16(new_dir->i_nlink);
-				status = ocfs2_journal_dirty(handle, new_dir_bh);
-			}
-		}
+	if (old_dir != new_dir) {
+		/* Keep the same times on both directories.*/
+		new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime;
+
+		/*
+		 * This will also pick up the i_nlink change from the
+		 * block above.
+		 */
+		ocfs2_mark_inode_dirty(handle, new_dir, new_dir_bh);
+	}
 
 	if (old_dir_nlink != old_dir->i_nlink) {
 		if (!old_dir_bh) {
@@ -1455,6 +1452,8 @@
 		iput(new_inode);
 	if (newfe_bh)
 		brelse(newfe_bh);
+	if (old_inode_bh)
+		brelse(old_inode_bh);
 	if (old_dir_bh)
 		brelse(old_dir_bh);
 	if (new_dir_bh)
@@ -1826,6 +1825,13 @@
 		     (le16_to_cpu(de->rec_len) >= rec_len)) ||
 		    (le16_to_cpu(de->rec_len) >=
 		     (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
+			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+			retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
+			if (retval < 0) {
+				mlog_errno(retval);
+				goto bail;
+			}
+
 			status = ocfs2_journal_access(handle, dir, insert_bh,
 						      OCFS2_JOURNAL_ACCESS_WRITE);
 			/* By now the buffer is marked for journaling */
@@ -1848,7 +1854,6 @@
 			de->name_len = namelen;
 			memcpy(de->name, name, namelen);
 
-			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			dir->i_version++;
 			status = ocfs2_journal_dirty(handle, insert_bh);
 			retval = 0;
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index b5c6856..e61e218 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -85,7 +85,7 @@
 #define OCFS2_CLEAR_INCOMPAT_FEATURE(sb,mask)			\
 	OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
 
-#define OCFS2_FEATURE_COMPAT_SUPP	0
+#define OCFS2_FEATURE_COMPAT_SUPP	OCFS2_FEATURE_COMPAT_BACKUP_SB
 #define OCFS2_FEATURE_INCOMPAT_SUPP	OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT
 #define OCFS2_FEATURE_RO_COMPAT_SUPP	0
 
@@ -110,6 +110,20 @@
 #define OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC	0x0010
 
 /*
+ * backup superblock flag is used to indicate that this volume
+ * has backup superblocks.
+ */
+#define OCFS2_FEATURE_COMPAT_BACKUP_SB		0x0001
+
+/* The byte offset of the first backup block will be 1G.
+ * The following will be 4G, 16G, 64G, 256G and 1T.
+ */
+#define OCFS2_BACKUP_SB_START			1 << 30
+
+/* the max backup superblock nums */
+#define OCFS2_MAX_BACKUP_SUPERBLOCKS	6
+
+/*
  * Flags on ocfs2_dinode.i_flags
  */
 #define OCFS2_VALID_FL		(0x00000001)	/* Inode is valid */
@@ -566,6 +580,20 @@
 
 	return size / sizeof(struct ocfs2_truncate_rec);
 }
+
+static inline u64 ocfs2_backup_super_blkno(struct super_block *sb, int index)
+{
+	u64 offset = OCFS2_BACKUP_SB_START;
+
+	if (index >= 0 && index < OCFS2_MAX_BACKUP_SUPERBLOCKS) {
+		offset <<= (2 * index);
+		offset >>= sb->s_blocksize_bits;
+		return offset;
+	}
+
+	return 0;
+
+}
 #else
 static inline int ocfs2_fast_symlink_chars(int blocksize)
 {
@@ -631,6 +659,19 @@
 
 	return size / sizeof(struct ocfs2_truncate_rec);
 }
+
+static inline uint64_t ocfs2_backup_super_blkno(int blocksize, int index)
+{
+	uint64_t offset = OCFS2_BACKUP_SB_START;
+
+	if (index >= 0 && index < OCFS2_MAX_BACKUP_SUPERBLOCKS) {
+		offset <<= (2 * index);
+		offset /= blocksize;
+		return offset;
+	}
+
+	return 0;
+}
 #endif  /* __KERNEL__ */
 
 
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 957d687..03b0191 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -158,8 +158,7 @@
 	}
 
 	status = vfs_follow_link(nd, link);
-	if (status && status != -ENOENT)
-		mlog_errno(status);
+
 bail:
 	if (page) {
 		kunmap(page);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 77a57b5..1a979ea 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -371,9 +371,11 @@
 
 	if (task) {
 		task_lock(task);
-		ns = task->nsproxy->mnt_ns;
-		if (ns)
-			get_mnt_ns(ns);
+		if (task->nsproxy) {
+			ns = task->nsproxy->mnt_ns;
+			if (ns)
+				get_mnt_ns(ns);
+		}
 		task_unlock(task);
 		put_task_struct(task);
 	}
@@ -2326,13 +2328,23 @@
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
-	struct task_struct *leader = get_proc_task(inode);
+	struct task_struct *leader = NULL;
 	struct task_struct *task;
 	int retval = -ENOENT;
 	ino_t ino;
 	int tid;
 	unsigned long pos = filp->f_pos;  /* avoiding "long long" filp->f_pos */
 
+	task = get_proc_task(inode);
+	if (!task)
+		goto out_no_task;
+	rcu_read_lock();
+	if (pid_alive(task)) {
+		leader = task->group_leader;
+		get_task_struct(leader);
+	}
+	rcu_read_unlock();
+	put_task_struct(task);
 	if (!leader)
 		goto out_no_task;
 	retval = 0;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 92ea774..b37ce33 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -47,7 +47,6 @@
 #include <linux/vmalloc.h>
 #include <linux/crash_dump.h>
 #include <linux/pid_namespace.h>
-#include <linux/compile.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -254,12 +253,7 @@
 {
 	int len;
 
-	/* FIXED STRING! Don't touch! */
-	len = snprintf(page, PAGE_SIZE,
-		"%s version %s"
-		" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
-		" (" LINUX_COMPILER ")"
-		" %s\n",
+	len = snprintf(page, PAGE_SIZE, linux_proc_banner,
 		utsname()->sysname,
 		utsname()->release,
 		utsname()->version);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 99b6f32..5109f1d 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -48,6 +48,11 @@
 	}
 
 	mutex_lock(&inode->i_mutex);
+
+	mutex_lock(&(REISERFS_I(inode)->i_mmap));
+	if (REISERFS_I(inode)->i_flags & i_ever_mapped)
+		REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+
 	reiserfs_write_lock(inode->i_sb);
 	/* freeing preallocation only involves relogging blocks that
 	 * are already in the current transaction.  preallocation gets
@@ -100,11 +105,24 @@
 		err = reiserfs_truncate_file(inode, 0);
 	}
       out:
+	mutex_unlock(&(REISERFS_I(inode)->i_mmap));
 	mutex_unlock(&inode->i_mutex);
 	reiserfs_write_unlock(inode->i_sb);
 	return err;
 }
 
+static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct inode *inode;
+
+	inode = file->f_path.dentry->d_inode;
+	mutex_lock(&(REISERFS_I(inode)->i_mmap));
+	REISERFS_I(inode)->i_flags |= i_ever_mapped;
+	mutex_unlock(&(REISERFS_I(inode)->i_mmap));
+
+	return generic_file_mmap(file, vma);
+}
+
 static void reiserfs_vfs_truncate_file(struct inode *inode)
 {
 	reiserfs_truncate_file(inode, 1);
@@ -1527,7 +1545,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = reiserfs_compat_ioctl,
 #endif
-	.mmap = generic_file_mmap,
+	.mmap = reiserfs_file_mmap,
 	.open = generic_file_open,
 	.release = reiserfs_file_release,
 	.fsync = reiserfs_sync_file,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index f3d1c4a..9fcbfe3 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1125,6 +1125,7 @@
 	REISERFS_I(inode)->i_prealloc_count = 0;
 	REISERFS_I(inode)->i_trans_id = 0;
 	REISERFS_I(inode)->i_jl = NULL;
+	mutex_init(&(REISERFS_I(inode)->i_mmap));
 	reiserfs_init_acl_access(inode);
 	reiserfs_init_acl_default(inode);
 	reiserfs_init_xattr_rwsem(inode);
@@ -1832,6 +1833,7 @@
 	REISERFS_I(inode)->i_attrs =
 	    REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
 	sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
+	mutex_init(&(REISERFS_I(inode)->i_mmap));
 	reiserfs_init_acl_access(inode);
 	reiserfs_init_acl_default(inode);
 	reiserfs_init_xattr_rwsem(inode);
diff --git a/fs/super.c b/fs/super.c
index f961e03..3e7458c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -753,9 +753,9 @@
 	 * will protect the lockfs code from trying to start a snapshot
 	 * while we are mounting
 	 */
-	mutex_lock(&bdev->bd_mount_mutex);
+	down(&bdev->bd_mount_sem);
 	s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
-	mutex_unlock(&bdev->bd_mount_mutex);
+	up(&bdev->bd_mount_sem);
 	if (IS_ERR(s))
 		goto error_s;
 
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 2e0021e..638f4c5 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -227,24 +227,27 @@
  * We can come here from ufs_writepage or ufs_prepare_write,
  * locked_page is argument of these functions, so we already lock it.
  */
-static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
+static void ufs_change_blocknr(struct inode *inode, unsigned int beg,
 			       unsigned int count, unsigned int oldb,
 			       unsigned int newb, struct page *locked_page)
 {
-	unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-	struct address_space *mapping = inode->i_mapping;
-	pgoff_t index, cur_index = locked_page->index;
-	unsigned int i, j;
+	const unsigned mask = (1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1;
+	struct address_space * const mapping = inode->i_mapping;
+	pgoff_t index, cur_index;
+	unsigned end, pos, j;
 	struct page *page;
 	struct buffer_head *head, *bh;
 
 	UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
 	      inode->i_ino, count, oldb, newb);
 
+	BUG_ON(!locked_page);
 	BUG_ON(!PageLocked(locked_page));
 
-	for (i = 0; i < count; i += blk_per_page) {
-		index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	cur_index = locked_page->index;
+
+	for (end = count + beg; beg < end; beg = (beg | mask) + 1) {
+		index = beg >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
 
 		if (likely(cur_index != index)) {
 			page = ufs_get_locked_page(mapping, index);
@@ -253,21 +256,32 @@
 		} else
 			page = locked_page;
 
-		j = i;
 		head = page_buffers(page);
 		bh = head;
+		pos = beg & mask;
+		for (j = 0; j < pos; ++j)
+			bh = bh->b_this_page;
+		j = 0;
 		do {
-			if (likely(bh->b_blocknr == j + oldb && j < count)) {
-				unmap_underlying_metadata(bh->b_bdev,
-							  bh->b_blocknr);
-				bh->b_blocknr = newb + j++;
-				mark_buffer_dirty(bh);
+			if (buffer_mapped(bh)) {
+				pos = bh->b_blocknr - oldb;
+				if (pos < count) {
+					UFSD(" change from %llu to %llu\n",
+					     (unsigned long long)pos + oldb,
+					     (unsigned long long)pos + newb);
+					bh->b_blocknr = newb + pos;
+					unmap_underlying_metadata(bh->b_bdev,
+								  bh->b_blocknr);
+					mark_buffer_dirty(bh);
+					++j;
+				}
 			}
 
 			bh = bh->b_this_page;
 		} while (bh != head);
 
-		set_page_dirty(page);
+		if (j)
+			set_page_dirty(page);
 
 		if (likely(cur_index != index))
 			ufs_put_locked_page(page);
@@ -415,14 +429,14 @@
 	}
 	result = ufs_alloc_fragments (inode, cgno, goal, request, err);
 	if (result) {
+		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
+				locked_page != NULL);
 		ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
 				   result, locked_page);
 
 		*p = cpu_to_fs32(sb, result);
 		*err = 0;
 		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
-		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
-				locked_page != NULL);
 		unlock_super(sb);
 		if (newcount < request)
 			ufs_free_fragments (inode, result + newcount, request - newcount);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 2fbab0a..4295ca9 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -242,7 +242,8 @@
 			goal = tmp + uspi->s_fpb;
 		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
 					 goal, required + blockoff,
-					 err, locked_page);
+					 err,
+					 phys != NULL ? locked_page : NULL);
 	}
 	/*
 	 * We will extend last allocated block
@@ -250,7 +251,7 @@
 	else if (lastblock == block) {
 		tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
 					fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff),
-					err, locked_page);
+					err, phys != NULL ? locked_page : NULL);
 	} else /* (lastblock > block) */ {
 	/*
 	 * We will allocate new block before last allocated block
@@ -261,7 +262,8 @@
 				goal = tmp + uspi->s_fpb;
 		}
 		tmp = ufs_new_fragments(inode, p, fragment - blockoff,
-					goal, uspi->s_fpb, err, locked_page);
+					goal, uspi->s_fpb, err,
+					phys != NULL ? locked_page : NULL);
 	}
 	if (!tmp) {
 		if ((!blockoff && *p) || 
@@ -438,9 +440,11 @@
 	 * it much more readable:
 	 */
 #define GET_INODE_DATABLOCK(x) \
-	ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page)
+	ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\
+			  bh_result->b_page)
 #define GET_INODE_PTR(x) \
-	ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, NULL)
+	ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\
+			  bh_result->b_page)
 #define GET_INDIRECT_DATABLOCK(x) \
 	ufs_inode_getblock(inode, bh, x, fragment,	\
 			  &err, &phys, &new, bh_result->b_page)
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index ea11d04..0437b0a 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -109,10 +109,10 @@
 	tmp = fs32_to_cpu(sb, *p);
 	if (!tmp )
 		ufs_panic (sb, "ufs_trunc_direct", "internal error");
+	frag2 -= frag1;
 	frag1 = ufs_fragnum (frag1);
-	frag2 = ufs_fragnum (frag2);
 
-	ufs_free_fragments (inode, tmp + frag1, frag2 - frag1);
+	ufs_free_fragments(inode, tmp + frag1, frag2);
 	mark_inode_dirty(inode);
 	frag_to_free = tmp + frag1;
 
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index 57e09f5..75a1aff 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -41,9 +41,9 @@
 #define dma_map_single(dev, va, size, dir)	virt_to_phys(va)
 #define dma_map_page(dev, page, off, size, dir)	(page_to_pa(page) + off)
 
-#define dma_unmap_single(dev, addr, size, dir)	do { } while (0)
-#define dma_unmap_page(dev, addr, size, dir)	do { } while (0)
-#define dma_unmap_sg(dev, sg, nents, dir)	do { } while (0)
+#define dma_unmap_single(dev, addr, size, dir)	((void)0)
+#define dma_unmap_page(dev, addr, size, dir)	((void)0)
+#define dma_unmap_sg(dev, sg, nents, dir)	((void)0)
 
 #define dma_mapping_error(addr)  (0)
 
@@ -55,12 +55,14 @@
 
 int dma_set_mask(struct device *dev, u64 mask);
 
-#define dma_sync_single_for_cpu(dev, addr, size, dir)	  do { } while (0)
-#define dma_sync_single_for_device(dev, addr, size, dir)  do { } while (0)
-#define dma_sync_single_range(dev, addr, off, size, dir)  do { } while (0)
-#define dma_sync_sg_for_cpu(dev, sg, nents, dir)	  do { } while (0)
-#define dma_sync_sg_for_device(dev, sg, nents, dir)	  do { } while (0)
-#define dma_cache_sync(dev, va, size, dir)		  do { } while (0)
+#define dma_sync_single_for_cpu(dev, addr, size, dir)	  ((void)0)
+#define dma_sync_single_for_device(dev, addr, size, dir)  ((void)0)
+#define dma_sync_single_range(dev, addr, off, size, dir)  ((void)0)
+#define dma_sync_sg_for_cpu(dev, sg, nents, dir)	  ((void)0)
+#define dma_sync_sg_for_device(dev, sg, nents, dir)	  ((void)0)
+#define dma_cache_sync(dev, va, size, dir)		  ((void)0)
+#define dma_sync_single_range_for_cpu(dev, addr, offset, size, dir)	((void)0)
+#define dma_sync_single_range_for_device(dev, addr, offset, size, dir)	((void)0)
 
 #define dma_get_cache_alignment()			  L1_CACHE_BYTES
 
diff --git a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h
index c78c04a..db16741 100644
--- a/include/asm-alpha/posix_types.h
+++ b/include/asm-alpha/posix_types.h
@@ -49,7 +49,7 @@
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 #define	__FD_ISSET(d, set)	(((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
 #define	__FD_ZERO(set)	\
-  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
 
 #else /* __GNUC__ */
 
diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
index 84313d1..e58a427 100644
--- a/include/asm-alpha/unistd.h
+++ b/include/asm-alpha/unistd.h
@@ -342,9 +342,14 @@
 #define __NR_io_cancel			402
 #define __NR_exit_group			405
 #define __NR_lookup_dcookie		406
-#define __NR_sys_epoll_create		407
-#define __NR_sys_epoll_ctl		408
-#define __NR_sys_epoll_wait		409
+#define __NR_epoll_create		407
+#define __NR_epoll_ctl			408
+#define __NR_epoll_wait			409
+/* Feb 2007: These three sys_epoll defines shouldn't be here but culling
+ * them would break userspace apps ... we'll kill them off in 2010 :) */
+#define __NR_sys_epoll_create		__NR_epoll_create
+#define __NR_sys_epoll_ctl		__NR_epoll_ctl
+#define __NR_sys_epoll_wait		__NR_epoll_wait
 #define __NR_remap_file_pages		410
 #define __NR_set_tid_address		411
 #define __NR_restart_syscall		412
diff --git a/include/asm-arm/arch-at91rm9200/at91_ecc.h b/include/asm-arm/arch-at91rm9200/at91_ecc.h
index fddf256..5c564ed 100644
--- a/include/asm-arm/arch-at91rm9200/at91_ecc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_ecc.h
@@ -14,7 +14,7 @@
 #define AT91_ECC_H
 
 #define AT91_ECC_CR		(AT91_ECC + 0x00)	/* Control register */
-#define		AT91_ECC_RST		(1 << 0) 		/* Reset parity */
+#define		AT91_ECC_RST		(1 << 0)		/* Reset parity */
 
 #define AT91_ECC_MR		(AT91_ECC + 0x04)	/* Mode register */
 #define		AT91_ECC_PAGESIZE	(3 << 0)		/* Page Size */
@@ -23,16 +23,16 @@
 #define			AT91_ECC_PAGESIZE_2112		(2)
 #define			AT91_ECC_PAGESIZE_4224		(3)
 
-#define AT91_ECC_SR		(AT91_ECC + 0x08) 	/* Status register */
+#define AT91_ECC_SR		(AT91_ECC + 0x08)	/* Status register */
 #define		AT91_ECC_RECERR		(1 << 0)		/* Recoverable Error */
 #define		AT91_ECC_ECCERR		(1 << 1)		/* ECC Single Bit Error */
 #define		AT91_ECC_MULERR		(1 << 2)		/* Multiple Errors */
 
-#define AT91_ECC_PR		(AT91_ECC + 0x0c) 	/* Parity register */
+#define AT91_ECC_PR		(AT91_ECC + 0x0c)	/* Parity register */
 #define		AT91_ECC_BITADDR	(0xf << 0)		/* Bit Error Address */
 #define		AT91_ECC_WORDADDR	(0xfff << 4)		/* Word Error Address */
 
-#define AT91_ECC_NPR		(AT91_ECC + 0x10) 	/* NParity register */
+#define AT91_ECC_NPR		(AT91_ECC + 0x10)	/* NParity register */
 #define		AT91_ECC_NPARITY	(0xffff << 0)		/* NParity */
 
 #endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pmc.h b/include/asm-arm/arch-at91rm9200/at91_pmc.h
index de8c3da..c3b489d 100644
--- a/include/asm-arm/arch-at91rm9200/at91_pmc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_pmc.h
@@ -61,7 +61,7 @@
 #define			AT91_PMC_CSS_PLLA		(2 << 0)
 #define			AT91_PMC_CSS_PLLB		(3 << 0)
 #define		AT91_PMC_PRES		(7 <<  2)		/* Master Clock Prescaler */
-#define 		AT91_PMC_PRES_1			(0 << 2)
+#define			AT91_PMC_PRES_1			(0 << 2)
 #define			AT91_PMC_PRES_2			(1 << 2)
 #define			AT91_PMC_PRES_4			(2 << 2)
 #define			AT91_PMC_PRES_8			(3 << 2)
diff --git a/include/asm-arm/arch-at91rm9200/at91_rstc.h b/include/asm-arm/arch-at91rm9200/at91_rstc.h
index ccdc52d..237d3c4 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rstc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_rstc.h
@@ -17,7 +17,7 @@
 #define		AT91_RSTC_PROCRST	(1 << 0)		/* Processor Reset */
 #define		AT91_RSTC_PERRST	(1 << 2)		/* Peripheral Reset */
 #define		AT91_RSTC_EXTRST	(1 << 3)		/* External Reset */
-#define		AT01_RSTC_KEY		(0xff << 24)		/* KEY Password */
+#define		AT91_RSTC_KEY		(0xff << 24)		/* KEY Password */
 
 #define AT91_RSTC_SR		(AT91_RSTC + 0x04)	/* Reset Controller Status Register */
 #define		AT91_RSTC_URSTS		(1 << 0)		/* User Reset Status */
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtc.h b/include/asm-arm/arch-at91rm9200/at91_rtc.h
index 6e5065d..095fe08 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rtc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_rtc.h
@@ -21,21 +21,21 @@
 #define		AT91_RTC_UPDCAL		(1 <<  1)		/* Update Request Calendar Register */
 #define		AT91_RTC_TIMEVSEL	(3 <<  8)		/* Time Event Selection */
 #define			AT91_RTC_TIMEVSEL_MINUTE	(0 << 8)
-#define 		AT91_RTC_TIMEVSEL_HOUR		(1 << 8)
-#define 		AT91_RTC_TIMEVSEL_DAY24		(2 << 8)
-#define 		AT91_RTC_TIMEVSEL_DAY12		(3 << 8)
+#define			AT91_RTC_TIMEVSEL_HOUR		(1 << 8)
+#define			AT91_RTC_TIMEVSEL_DAY24		(2 << 8)
+#define			AT91_RTC_TIMEVSEL_DAY12		(3 << 8)
 #define		AT91_RTC_CALEVSEL	(3 << 16)		/* Calendar Event Selection */
-#define 		AT91_RTC_CALEVSEL_WEEK		(0 << 16)
-#define 		AT91_RTC_CALEVSEL_MONTH		(1 << 16)
-#define 		AT91_RTC_CALEVSEL_YEAR		(2 << 16)
+#define			AT91_RTC_CALEVSEL_WEEK		(0 << 16)
+#define			AT91_RTC_CALEVSEL_MONTH		(1 << 16)
+#define			AT91_RTC_CALEVSEL_YEAR		(2 << 16)
 
 #define	AT91_RTC_MR		(AT91_RTC + 0x04)	/* Mode Register */
-#define 	AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */
+#define			AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */
 
 #define	AT91_RTC_TIMR		(AT91_RTC + 0x08)	/* Time Register */
 #define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */
 #define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */
-#define		AT91_RTC_HOUR 		(0x3f << 16)		/* Current Hour */
+#define		AT91_RTC_HOUR		(0x3f << 16)		/* Current Hour */
 #define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
 
 #define	AT91_RTC_CALR		(AT91_RTC + 0x0c)	/* Calendar Register */
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h
index 4d51177..c569b6a 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200.h
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200.h
@@ -274,7 +274,7 @@
 #define AT91_PD19_TPK7		(1 << 19)	/* B: ETM Trace Packet Port 7 */
 #define AT91_PD20_NPCS3		(1 << 20)	/* A: SPI Peripheral Chip Select 3 */
 #define AT91_PD20_TPK8		(1 << 20)	/* B: ETM Trace Packet Port 8 */
-#define AT91_PD21_RTS0		(1 << 21)  	/* A: USART Ready To Send 0 */
+#define AT91_PD21_RTS0		(1 << 21)	/* A: USART Ready To Send 0 */
 #define AT91_PD21_TPK9		(1 << 21)	/* B: ETM Trace Packet Port 9 */
 #define AT91_PD22_RTS1		(1 << 22)	/* A: USART Ready To Send 1 */
 #define AT91_PD22_TPK10		(1 << 22)	/* B: ETM Trace Packet Port 10 */
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
index 746d9737..78f6b49 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+++ b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
@@ -58,7 +58,7 @@
 #define		AT91_MATRIX_RCB1		(1 << 1)	/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
 
 #define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x11C)	/* EBI Chip Select Assignment Register */
-#define		AT91_MATRIX_CS1A		(1 << 1)	 /* Chip Select 1 Assignment */
+#define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
 #define			AT91_MATRIX_CS1A_SMC		(0 << 1)
 #define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
 #define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
index 270a5dc..ec88efa 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+++ b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
@@ -15,7 +15,7 @@
 
 #define AT91_MATRIX_MCFG	(AT91_MATRIX + 0x00)	/* Master Configuration Register */
 #define		AT91_MATRIX_RCB0	(1 << 0)		/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define		AT01_MATRIX_RCB1	(1 << 1)		/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+#define		AT91_MATRIX_RCB1	(1 << 1)		/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
 
 #define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x04)	/* Slave Configuration Register 0 */
 #define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x08)	/* Slave Configuration Register 1 */
@@ -43,8 +43,8 @@
 
 #define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x30)	/* EBI Chip Select Assignment Register */
 #define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
-#define 		AT91_MATRIX_CS1A_SMC		(0 << 1)
-#define 		AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
+#define			AT91_MATRIX_CS1A_SMC		(0 << 1)
+#define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1)
 #define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
 #define			AT91_MATRIX_CS3A_SMC		(0 << 3)
 #define			AT91_MATRIX_CS3A_SMC_SMARTMEDIA	(1 << 3)
diff --git a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
index 7d94968..972e753 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+++ b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
@@ -33,14 +33,14 @@
 #define			AT91_SDRAMC_NC_9	(1 << 0)
 #define			AT91_SDRAMC_NC_10	(2 << 0)
 #define			AT91_SDRAMC_NC_11	(3 << 0)
-#define 	AT91_SDRAMC_NR		(3 << 2)		/* Number of Row Bits */
+#define		AT91_SDRAMC_NR		(3 << 2)		/* Number of Row Bits */
 #define			AT91_SDRAMC_NR_11	(0 << 2)
 #define			AT91_SDRAMC_NR_12	(1 << 2)
 #define			AT91_SDRAMC_NR_13	(2 << 2)
-#define 	AT91_SDRAMC_NB		(1 << 4)		/* Number of Banks */
+#define		AT91_SDRAMC_NB		(1 << 4)		/* Number of Banks */
 #define			AT91_SDRAMC_NB_2	(0 << 4)
-#define 		AT91_SDRAMC_NB_4	(1 << 4)
-#define 	AT91_SDRAMC_CAS		(3 << 5)		/* CAS Latency */
+#define			AT91_SDRAMC_NB_4	(1 << 4)
+#define		AT91_SDRAMC_CAS		(3 << 5)		/* CAS Latency */
 #define			AT91_SDRAMC_CAS_1	(1 << 5)
 #define			AT91_SDRAMC_CAS_2	(2 << 5)
 #define			AT91_SDRAMC_CAS_3	(3 << 5)
@@ -110,10 +110,10 @@
 #define AT91_SMC_MODE(n)	(AT91_SMC + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
 #define		AT91_SMC_READMODE	(1 <<  0)			/* Read Mode */
 #define		AT91_SMC_WRITEMODE	(1 <<  1)			/* Write Mode */
-#define		AT91_SMC_EXNWMODE	(3 <<  5)			/* NWAIT Mode */
-#define			AT91_SMC_EXNWMODE_DISABLE	(0 << 5)
-#define			AT91_SMC_EXNWMODE_FROZEN	(2 << 5)
-#define			AT91_SMC_EXNWMODE_READY		(3 << 5)
+#define		AT91_SMC_EXNWMODE	(3 <<  4)			/* NWAIT Mode */
+#define			AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
+#define			AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
+#define			AT91_SMC_EXNWMODE_READY		(3 << 4)
 #define		AT91_SMC_BAT		(1 <<  8)			/* Byte Access Type */
 #define			AT91_SMC_BAT_SELECT		(0 << 8)
 #define			AT91_SMC_BAT_WRITE		(1 << 8)
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index b2893e3..eae9169 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -52,10 +52,10 @@
 /* general configuration options */
 
 #define S3C2410_GPIO_LEAVE   (0xFFFFFFFF)
-#define S3C2410_GPIO_INPUT   (0xFFFFFFF0)
+#define S3C2410_GPIO_INPUT   (0xFFFFFFF0)	/* not available on A */
 #define S3C2410_GPIO_OUTPUT  (0xFFFFFFF1)
 #define S3C2410_GPIO_IRQ     (0xFFFFFFF2)	/* not available for all */
-#define S3C2410_GPIO_SFN2    (0xFFFFFFF2)	/* not available on A */
+#define S3C2410_GPIO_SFN2    (0xFFFFFFF2)	/* bank A => addr/cs/nand */
 #define S3C2410_GPIO_SFN3    (0xFFFFFFF3)	/* not available on A */
 
 /* register address for the GPIO registers.
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
index 375dca5..e4d8234 100644
--- a/include/asm-arm/arch-s3c2410/regs-mem.h
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h
@@ -133,10 +133,10 @@
 #define S3C2410_BANKCON_SDRAM		(0x3 << 15)
 
 /* next bits only for EDO DRAM in 6,7 */
-#define S3C2400_BANKCON_EDO_Trdc1      (0x00 << 4)
-#define S3C2400_BANKCON_EDO_Trdc2      (0x01 << 4)
-#define S3C2400_BANKCON_EDO_Trdc3      (0x02 << 4)
-#define S3C2400_BANKCON_EDO_Trdc4      (0x03 << 4)
+#define S3C2400_BANKCON_EDO_Trcd1      (0x00 << 4)
+#define S3C2400_BANKCON_EDO_Trcd2      (0x01 << 4)
+#define S3C2400_BANKCON_EDO_Trcd3      (0x02 << 4)
+#define S3C2400_BANKCON_EDO_Trcd4      (0x03 << 4)
 
 /* CAS pulse width */
 #define S3C2400_BANKCON_EDO_PULSE1     (0x00 << 3)
@@ -153,9 +153,9 @@
 #define S3C2400_BANKCON_EDO_SCANb11    (0x03 << 0)
 
 /* next bits only for SDRAM in 6,7 */
-#define S3C2410_BANKCON_Trdc2		(0x00 << 2)
-#define S3C2410_BANKCON_Trdc3		(0x01 << 2)
-#define S3C2410_BANKCON_Trdc4		(0x02 << 2)
+#define S3C2410_BANKCON_Trcd2		(0x00 << 2)
+#define S3C2410_BANKCON_Trcd3		(0x01 << 2)
+#define S3C2410_BANKCON_Trcd4		(0x02 << 2)
 
 /* control column address select */
 #define S3C2410_BANKCON_SCANb8		(0x00 << 0)
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 6af4e6b..f31cda5 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -35,6 +35,9 @@
 	 */
 	__u32 fpinst;
 	__u32 fpinst2;
+#ifdef CONFIG_SMP
+	__u32 cpu;
+#endif
 };
 
 union vfp_state {
diff --git a/include/asm-frv/Kbuild b/include/asm-frv/Kbuild
index c68e168..966a983 100644
--- a/include/asm-frv/Kbuild
+++ b/include/asm-frv/Kbuild
@@ -1 +1,7 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+
+unifdef-y += termios.h
+unifdef-y += ptrace.h
+unifdef-y += page.h
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index 134cc0c..213d92f 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -76,8 +76,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
 #define WANT_PAGE_VIRTUAL	1
 #endif
@@ -85,4 +83,6 @@
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _ASM_PAGE_H */
diff --git a/include/asm-frv/ptrace.h b/include/asm-frv/ptrace.h
index 9a2241b..cf69340 100644
--- a/include/asm-frv/ptrace.h
+++ b/include/asm-frv/ptrace.h
@@ -12,9 +12,11 @@
 #define _ASM_PTRACE_H
 
 #include <asm/registers.h>
+#ifdef __KERNEL__
 #include <asm/irq_regs.h>
 
 #define in_syscall(regs) (((regs)->tbr & TBR_TT) == TBR_TT_TRAP0)
+#endif
 
 
 #define PT_PSR		0
@@ -60,6 +62,7 @@
 #define PTRACE_GETFDPIC_EXEC	0	/* [addr] request the executable loadmap */
 #define PTRACE_GETFDPIC_INTERP	1	/* [addr] request the interpreter loadmap */
 
+#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 /*
@@ -74,6 +77,7 @@
 extern unsigned long user_stack(const struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
+#endif
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_PTRACE_H */
diff --git a/include/asm-frv/termios.h b/include/asm-frv/termios.h
index b4a664e..8840cf9 100644
--- a/include/asm-frv/termios.h
+++ b/include/asm-frv/termios.h
@@ -69,6 +69,8 @@
 #define N_SYNC_PPP	14
 #define N_HCI		15  /* Bluetooth HCI UART */
 
+#ifdef __KERNEL__
 #include <asm-generic/termios.h>
+#endif
 
 #endif /* _ASM_TERMIOS_H */
diff --git a/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h
index 9202fd0..62fb361 100644
--- a/include/asm-generic/libata-portmap.h
+++ b/include/asm-generic/libata-portmap.h
@@ -3,10 +3,10 @@
 
 #define ATA_PRIMARY_CMD		0x1F0
 #define ATA_PRIMARY_CTL		0x3F6
-#define ATA_PRIMARY_IRQ		14
+#define ATA_PRIMARY_IRQ(dev)	14
 
 #define ATA_SECONDARY_CMD	0x170
 #define ATA_SECONDARY_CTL	0x376
-#define ATA_SECONDARY_IRQ	15
+#define ATA_SECONDARY_IRQ(dev)	15
 
 #endif
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index 45d21a0..369035d 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -143,11 +143,8 @@
 # define VDSO_PRELINK		0
 #endif
 
-#define VDSO_COMPAT_SYM(x) \
-		(VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
-
 #define VDSO_SYM(x) \
-		(VDSO_BASE + (unsigned long)(x) - VDSO_PRELINK)
+		(VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
 
 #define VDSO_HIGH_EHDR		((const struct elfhdr *) VDSO_HIGH_BASE)
 #define VDSO_EHDR		((const struct elfhdr *) VDSO_COMPAT_BASE)
@@ -156,10 +153,12 @@
 
 #define VDSO_ENTRY		VDSO_SYM(&__kernel_vsyscall)
 
+#ifndef CONFIG_COMPAT_VDSO
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
                                        int executable_stack);
+#endif
 
 extern unsigned int vdso_enabled;
 
@@ -169,50 +168,6 @@
 		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE);	\
 } while (0)
 
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents.  Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS		(VDSO_HIGH_EHDR->e_phnum)
-#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
-do {									      \
-	const struct elf_phdr *const vsyscall_phdrs =			      \
-		(const struct elf_phdr *) (VDSO_HIGH_BASE		      \
-					   + VDSO_HIGH_EHDR->e_phoff);    \
-	int i;								      \
-	Elf32_Off ofs = 0;						      \
-	for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) {		      \
-		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
-		if (phdr.p_type == PT_LOAD) {				      \
-			BUG_ON(ofs != 0);				      \
-			ofs = phdr.p_offset = offset;			      \
-			phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);	      \
-			phdr.p_filesz = phdr.p_memsz;			      \
-			offset += phdr.p_filesz;			      \
-		}							      \
-		else							      \
-			phdr.p_offset += ofs;				      \
-		phdr.p_paddr = 0; /* match other core phdrs */		      \
-		DUMP_WRITE(&phdr, sizeof(phdr));			      \
-	}								      \
-} while (0)
-#define ELF_CORE_WRITE_EXTRA_DATA					      \
-do {									      \
-	const struct elf_phdr *const vsyscall_phdrs =			      \
-		(const struct elf_phdr *) (VDSO_HIGH_BASE		      \
-					   + VDSO_HIGH_EHDR->e_phoff);    \
-	int i;								      \
-	for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) {		      \
-		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
-			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
-				   PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));    \
-	}								      \
-} while (0)
-
 #endif
 
 #endif
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 02428cb..3e9f610 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -23,6 +23,8 @@
 extern unsigned long __FIXADDR_TOP;
 #else
 #define __FIXADDR_TOP  0xfffff000
+#define FIXADDR_USER_START	__fix_to_virt(FIX_VDSO)
+#define FIXADDR_USER_END	__fix_to_virt(FIX_VDSO - 1)
 #endif
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index fd3f64a..7b19f45 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -143,7 +143,9 @@
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#ifndef CONFIG_COMPAT_VDSO
 #define __HAVE_ARCH_GATE_AREA 1
+#endif
 #endif /* __KERNEL__ */
 
 #endif /* _I386_PAGE_H */
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index a52d654..359f10b 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -743,6 +743,7 @@
 extern int sysenter_setup(void);
 
 extern int init_gdt(int cpu, struct task_struct *idle);
+extern void cpu_set_gdt(int);
 extern void secondary_cpu_init(void);
 
 #endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-ia64/checksum.h b/include/asm-ia64/checksum.h
index 2b78582..97af155 100644
--- a/include/asm-ia64/checksum.h
+++ b/include/asm-ia64/checksum.h
@@ -72,8 +72,8 @@
 
 #define _HAVE_ARCH_IPV6_CSUM	1
 struct in6_addr;
-extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
-	struct in6_addr *daddr, __u32 len, unsigned short proto,
-	unsigned int csum);
+extern __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+	const struct in6_addr *daddr, __u32 len, unsigned short proto,
+	__wsum csum);
 
 #endif /* _ASM_IA64_CHECKSUM_H */
diff --git a/include/asm-ia64/dma.h b/include/asm-ia64/dma.h
index dad3a73..4d97f60 100644
--- a/include/asm-ia64/dma.h
+++ b/include/asm-ia64/dma.h
@@ -19,4 +19,6 @@
 
 #define free_dma(x)
 
+void dma_mark_clean(void *addr, size_t size);
+
 #endif /* _ASM_IA64_DMA_H */
diff --git a/include/asm-ia64/esi.h b/include/asm-ia64/esi.h
index 84aac0e..40991c6 100644
--- a/include/asm-ia64/esi.h
+++ b/include/asm-ia64/esi.h
@@ -19,7 +19,6 @@
 	ESI_PROC_REENTRANT	/* MP-safe and reentrant */
 };
 
-extern int ia64_esi_init (void);
 extern struct ia64_sal_retval esi_call_phys (void *, u64 *);
 extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *,
 			 enum esi_proc_type,
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index c8df759..6dd476b 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -51,12 +51,13 @@
 
 #define IGNORE_PFN0	1	/* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
 
+extern int register_active_ranges(u64 start, u64 end, void *arg);
+
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 # define LARGE_GAP	0x40000000 /* Use virtual mem map if hole is > than this */
   extern unsigned long vmalloc_end;
   extern struct page *vmem_map;
   extern int find_largest_hole (u64 start, u64 end, void *arg);
-  extern int register_active_ranges (u64 start, u64 end, void *arg);
   extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
   extern int vmemmap_find_next_valid_pfn(int, int);
 #else
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index 556f53f..5160233 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -167,4 +167,10 @@
 
 #define pcibios_scan_all_fns(a, b)	0
 
+#define HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return channel ? 15 : 14;
+}
+
 #endif /* _ASM_IA64_PCI_H */
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
index 393e04c..560c287 100644
--- a/include/asm-ia64/pgalloc.h
+++ b/include/asm-ia64/pgalloc.h
@@ -137,7 +137,8 @@
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
 					 unsigned long addr)
 {
-	return virt_to_page(pgtable_quicklist_alloc());
+	void *pg = pgtable_quicklist_alloc();
+	return pg ? virt_to_page(pg) : NULL;
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
diff --git a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h
index adb6227..1788556 100644
--- a/include/asm-ia64/posix_types.h
+++ b/include/asm-ia64/posix_types.h
@@ -54,7 +54,7 @@
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 #define	__FD_ISSET(d, set)	(((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
 #define	__FD_ZERO(set)	\
-  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
 
 #  else /* !__GNUC__ */
 
diff --git a/include/asm-ia64/swiotlb.h b/include/asm-ia64/swiotlb.h
new file mode 100644
index 0000000..452c162
--- /dev/null
+++ b/include/asm-ia64/swiotlb.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_SWIOTLB_H
+#define _ASM_SWIOTLB_H 1
+
+#include <asm/machvec.h>
+
+#define SWIOTLB_ARCH_NEED_LATE_INIT
+#define SWIOTLB_ARCH_NEED_ALLOC
+
+#endif /* _ASM_SWIOTLB_H */
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 9b505b2..9169859 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -84,6 +84,7 @@
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SYSCALL_TRACE	3	/* syscall trace active */
 #define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */
+#define TIF_SINGLESTEP		5	/* restore singlestep on return to user mode */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 #define TIF_MCA_INIT		18	/* this task is processing MCA or INIT */
@@ -92,7 +93,8 @@
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
-#define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
+#define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 53c5c0e..a9e1fa4 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -291,11 +291,13 @@
 #define __NR_sync_file_range		1300
 #define __NR_tee			1301
 #define __NR_vmsplice			1302
+/* 1303 reserved for move_pages */
+#define __NR_getcpu			1304
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls			279 /* length of syscall table */
+#define NR_syscalls			281 /* length of syscall table */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index e4c9f08..6a4cf20 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -7,6 +7,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <asm/segment.h>
 
 #define VERIFY_READ	0
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index 8e321f5..c7c945b 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -243,6 +243,10 @@
 extern void add_memory_region(phys_t start, phys_t size, long type);
 
 extern void prom_init(void);
+extern void prom_free_prom_memory(void);
+
+extern void free_init_pages(const char *what,
+			    unsigned long begin, unsigned long end);
 
 /*
  * Initial kernel command line, usually setup by prom_init()
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index 24cdcc6..20a81e1 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -159,7 +159,8 @@
 #endif
 	"	.set	pop"
 	: "=r" (sum)
-	: "0" (daddr), "r"(saddr),
+	: "0" ((__force unsigned long)daddr),
+	  "r" ((__force unsigned long)saddr),
 #ifdef __MIPSEL__
 	  "r" ((proto + len) << 8),
 #else
diff --git a/include/asm-mips/ddb5xxx/ddb5477.h b/include/asm-mips/ddb5xxx/ddb5477.h
index c5af4b7..6cf177c 100644
--- a/include/asm-mips/ddb5xxx/ddb5477.h
+++ b/include/asm-mips/ddb5xxx/ddb5477.h
@@ -17,6 +17,7 @@
 #ifndef __ASM_DDB5XXX_DDB5477_H
 #define __ASM_DDB5XXX_DDB5477_H
 
+#include <irq.h>
 
 /*
  * This contains macros that are specific to DDB5477 or renamed from
@@ -251,14 +252,10 @@
  */
 
 #define	NUM_CPU_IRQ		8
-#define	NUM_I8259_IRQ		16
 #define	NUM_VRC5477_IRQ		32
 
-#define	DDB_IRQ_BASE		0
-
-#define	I8259_IRQ_BASE		DDB_IRQ_BASE
-#define	VRC5477_IRQ_BASE	(I8259_IRQ_BASE + NUM_I8259_IRQ)
-#define	CPU_IRQ_BASE		(VRC5477_IRQ_BASE + NUM_VRC5477_IRQ)
+#define	CPU_IRQ_BASE		MIPS_CPU_IRQ_BASE
+#define	VRC5477_IRQ_BASE	(CPU_IRQ_BASE + NUM_CPU_IRQ)
 
 /*
  * vrc5477 irq defs
@@ -300,22 +297,22 @@
 /*
  * i2859 irq assignment
  */
-#define I8259_IRQ_RESERVED_0	(0 + I8259_IRQ_BASE)
-#define I8259_IRQ_KEYBOARD	(1 + I8259_IRQ_BASE)	/* M1543 default */
-#define I8259_IRQ_CASCADE	(2 + I8259_IRQ_BASE)
-#define I8259_IRQ_UART_B	(3 + I8259_IRQ_BASE)	/* M1543 default, may conflict with RTC according to schematic diagram  */
-#define I8259_IRQ_UART_A	(4 + I8259_IRQ_BASE)	/* M1543 default */
-#define I8259_IRQ_PARALLEL	(5 + I8259_IRQ_BASE)	/* M1543 default */
-#define I8259_IRQ_RESERVED_6	(6 + I8259_IRQ_BASE)
-#define I8259_IRQ_RESERVED_7	(7 + I8259_IRQ_BASE)
-#define I8259_IRQ_RTC		(8 + I8259_IRQ_BASE)	/* who set this? */
-#define I8259_IRQ_USB		(9 + I8259_IRQ_BASE)	/* ddb_setup */
-#define I8259_IRQ_PMU		(10 + I8259_IRQ_BASE)	/* ddb_setup */
-#define I8259_IRQ_RESERVED_11	(11 + I8259_IRQ_BASE)
-#define I8259_IRQ_RESERVED_12	(12 + I8259_IRQ_BASE)	/* m1543_irq_setup */
-#define I8259_IRQ_RESERVED_13	(13 + I8259_IRQ_BASE)
-#define I8259_IRQ_HDC1		(14 + I8259_IRQ_BASE)	/* default and ddb_setup */
-#define I8259_IRQ_HDC2		(15 + I8259_IRQ_BASE)	/* default */
+#define I8259_IRQ_RESERVED_0	(0 + I8259A_IRQ_BASE)
+#define I8259_IRQ_KEYBOARD	(1 + I8259A_IRQ_BASE)	/* M1543 default */
+#define I8259_IRQ_CASCADE	(2 + I8259A_IRQ_BASE)
+#define I8259_IRQ_UART_B	(3 + I8259A_IRQ_BASE)	/* M1543 default, may conflict with RTC according to schematic diagram  */
+#define I8259_IRQ_UART_A	(4 + I8259A_IRQ_BASE)	/* M1543 default */
+#define I8259_IRQ_PARALLEL	(5 + I8259A_IRQ_BASE)	/* M1543 default */
+#define I8259_IRQ_RESERVED_6	(6 + I8259A_IRQ_BASE)
+#define I8259_IRQ_RESERVED_7	(7 + I8259A_IRQ_BASE)
+#define I8259_IRQ_RTC		(8 + I8259A_IRQ_BASE)	/* who set this? */
+#define I8259_IRQ_USB		(9 + I8259A_IRQ_BASE)	/* ddb_setup */
+#define I8259_IRQ_PMU		(10 + I8259A_IRQ_BASE)	/* ddb_setup */
+#define I8259_IRQ_RESERVED_11	(11 + I8259A_IRQ_BASE)
+#define I8259_IRQ_RESERVED_12	(12 + I8259A_IRQ_BASE)	/* m1543_irq_setup */
+#define I8259_IRQ_RESERVED_13	(13 + I8259A_IRQ_BASE)
+#define I8259_IRQ_HDC1		(14 + I8259A_IRQ_BASE)	/* default and ddb_setup */
+#define I8259_IRQ_HDC2		(15 + I8259A_IRQ_BASE)	/* default */
 
 
 /*
diff --git a/include/asm-mips/dec/interrupts.h b/include/asm-mips/dec/interrupts.h
index 273e4d6..e10d341 100644
--- a/include/asm-mips/dec/interrupts.h
+++ b/include/asm-mips/dec/interrupts.h
@@ -14,6 +14,7 @@
 #ifndef __ASM_DEC_INTERRUPTS_H
 #define __ASM_DEC_INTERRUPTS_H
 
+#include <irq.h>
 #include <asm/mipsregs.h>
 
 
@@ -87,7 +88,7 @@
 #define DEC_CPU_INR_SW1		1	/* software #1 */
 #define DEC_CPU_INR_SW0		0	/* software #0 */
 
-#define DEC_CPU_IRQ_BASE	0	/* first IRQ assigned to CPU */
+#define DEC_CPU_IRQ_BASE	MIPS_CPU_IRQ_BASE	/* first IRQ assigned to CPU */
 
 #define DEC_CPU_IRQ_NR(n)	((n) + DEC_CPU_IRQ_BASE)
 #define DEC_CPU_IRQ_MASK(n)	(1 << ((n) + CAUSEB_IP))
diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h
index 23f789c..e06ef07 100644
--- a/include/asm-mips/dma.h
+++ b/include/asm-mips/dma.h
@@ -91,6 +91,7 @@
 #else
 #define MAX_DMA_ADDRESS		(PAGE_OFFSET + 0x01000000)
 #endif
+#define MAX_DMA_PFN		PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS))
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
diff --git a/include/asm-mips/emma2rh/emma2rh.h b/include/asm-mips/emma2rh/emma2rh.h
index 4fb8df7..6a1af0a 100644
--- a/include/asm-mips/emma2rh/emma2rh.h
+++ b/include/asm-mips/emma2rh/emma2rh.h
@@ -24,6 +24,8 @@
 #ifndef __ASM_EMMA2RH_EMMA2RH_H
 #define __ASM_EMMA2RH_EMMA2RH_H
 
+#include <irq.h>
+
 /*
  * EMMA2RH registers
  */
@@ -104,7 +106,8 @@
 #define NUM_EMMA2RH_IRQ		96
 
 #define CPU_EMMA2RH_CASCADE	2
-#define EMMA2RH_IRQ_BASE	0
+#define CPU_IRQ_BASE		MIPS_CPU_IRQ_BASE
+#define EMMA2RH_IRQ_BASE	(CPU_IRQ_BASE + NUM_CPU_IRQ)
 
 /*
  * emma2rh irq defs
diff --git a/include/asm-mips/emma2rh/markeins.h b/include/asm-mips/emma2rh/markeins.h
index 8fa7667..973b062 100644
--- a/include/asm-mips/emma2rh/markeins.h
+++ b/include/asm-mips/emma2rh/markeins.h
@@ -33,7 +33,6 @@
 
 #define EMMA2RH_SW_IRQ_BASE	(EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ)
 #define EMMA2RH_GPIO_IRQ_BASE	(EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW)
-#define CPU_IRQ_BASE		(EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO)
 
 #define EMMA2RH_SW_IRQ_INT0	(0+EMMA2RH_SW_IRQ_BASE)
 #define EMMA2RH_SW_IRQ_INT1	(1+EMMA2RH_SW_IRQ_BASE)
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index 0fe0294..5007315 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -157,7 +157,7 @@
  * processors.
  */
 ASMMACRO(mtc0_tlbw_hazard,
-	nop
+	nop; nop
 	)
 ASMMACRO(tlbw_use_hazard,
 	nop; nop; nop
diff --git a/include/asm-mips/i8259.h b/include/asm-mips/i8259.h
index 4df8d8b..e88a016 100644
--- a/include/asm-mips/i8259.h
+++ b/include/asm-mips/i8259.h
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
+#include <irq.h>
 
 /* i8259A PIC registers */
 #define PIC_MASTER_CMD		0x20
@@ -42,8 +43,6 @@
 
 extern void init_i8259_irqs(void);
 
-#define I8259A_IRQ_BASE	0
-
 /*
  * Do the traditional i8259 interrupt polling thing.  This is for the few
  * cases where no better interrupt acknowledge method is available and we
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index d77b657..67f0810 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -115,7 +115,7 @@
  */
 static inline unsigned long virt_to_phys(volatile const void *address)
 {
-	return (unsigned long)address - PAGE_OFFSET;
+	return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
 }
 
 /*
@@ -132,7 +132,7 @@
  */
 static inline void * phys_to_virt(unsigned long address)
 {
-	return (void *)(address + PAGE_OFFSET);
+	return (void *)(address + PAGE_OFFSET - PHYS_OFFSET);
 }
 
 /*
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 386da82..91803ba 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -18,7 +18,7 @@
 #ifdef CONFIG_I8259
 static inline int irq_canonicalize(int irq)
 {
-	return ((irq == 2) ? 9 : irq);
+	return ((irq == I8259A_IRQ_BASE + 2) ? I8259A_IRQ_BASE + 9 : irq);
 }
 #else
 #define irq_canonicalize(irq) (irq)	/* Sane hardware, sane code ... */
diff --git a/include/asm-mips/irq_cpu.h b/include/asm-mips/irq_cpu.h
index ed3d1e3..ef6a07c 100644
--- a/include/asm-mips/irq_cpu.h
+++ b/include/asm-mips/irq_cpu.h
@@ -13,8 +13,8 @@
 #ifndef _ASM_IRQ_CPU_H
 #define _ASM_IRQ_CPU_H
 
-extern void mips_cpu_irq_init(int irq_base);
-extern void rm7k_cpu_irq_init(int irq_base);
-extern void rm9k_cpu_irq_init(int irq_base);
+extern void mips_cpu_irq_init(void);
+extern void rm7k_cpu_irq_init(void);
+extern void rm9k_cpu_irq_init(void);
 
 #endif /* _ASM_IRQ_CPU_H */
diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h
index 46bf5de..af3b07d 100644
--- a/include/asm-mips/irqflags.h
+++ b/include/asm-mips/irqflags.h
@@ -15,6 +15,27 @@
 
 #include <asm/hazards.h>
 
+/*
+ * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs,
+ * at the cost of branch and call overhead on each local_irq_restore()
+ */
+
+#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
+
+extern void smtc_ipi_replay(void);
+
+#define irq_restore_epilog(flags)				\
+do {								\
+	if (!(flags & 0x0400))					\
+		smtc_ipi_replay();				\
+} while (0)
+
+#else
+
+#define irq_restore_epilog(ignore) do { } while (0)
+
+#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
+
 __asm__ (
 	"	.macro	raw_local_irq_enable				\n"
 	"	.set	push						\n"
@@ -193,6 +214,7 @@
 		: "=r" (__tmp1)						\
 		: "0" (flags)						\
 		: "memory");						\
+	irq_restore_epilog(flags);					\
 } while(0)
 
 static inline int raw_irqs_disabled_flags(unsigned long flags)
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 582acd8..58fca8a 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -39,6 +39,7 @@
 #ifndef _LANGUAGE_ASSEMBLY
 
 #include <linux/delay.h>
+#include <linux/types.h>
 #include <asm/io.h>
 
 /* cpu pipeline flush */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 00b0fc6..24a8d51 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -12,6 +12,8 @@
 #ifndef __ASM_COBALT_H
 #define __ASM_COBALT_H
 
+#include <irq.h>
+
 /*
  * i8259 legacy interrupts used on Cobalt:
  *
@@ -25,7 +27,7 @@
 /*
  * CPU IRQs  are 16 ... 23
  */
-#define COBALT_CPU_IRQ		16
+#define COBALT_CPU_IRQ		MIPS_CPU_IRQ_BASE
 
 #define COBALT_GALILEO_IRQ	(COBALT_CPU_IRQ + 2)
 #define COBALT_SCC_IRQ          (COBALT_CPU_IRQ + 3)	/* pre-production has 85C30 */
diff --git a/include/asm-mips/mach-emma2rh/irq.h b/include/asm-mips/mach-emma2rh/irq.h
index bce6424..5439eb8 100644
--- a/include/asm-mips/mach-emma2rh/irq.h
+++ b/include/asm-mips/mach-emma2rh/irq.h
@@ -10,4 +10,6 @@
 
 #define NR_IRQS	256
 
+#include_next <irq.h>
+
 #endif /* __ASM_MACH_EMMA2RH_IRQ_H */
diff --git a/include/asm-mips/mach-generic/irq.h b/include/asm-mips/mach-generic/irq.h
index 500e10f..70d9a25 100644
--- a/include/asm-mips/mach-generic/irq.h
+++ b/include/asm-mips/mach-generic/irq.h
@@ -8,6 +8,38 @@
 #ifndef __ASM_MACH_GENERIC_IRQ_H
 #define __ASM_MACH_GENERIC_IRQ_H
 
+#ifndef NR_IRQS
 #define NR_IRQS	128
+#endif
+
+#ifdef CONFIG_I8259
+#ifndef I8259A_IRQ_BASE
+#define I8259A_IRQ_BASE	0
+#endif
+#endif
+
+#ifdef CONFIG_IRQ_CPU
+
+#ifndef MIPS_CPU_IRQ_BASE
+#ifdef CONFIG_I8259
+#define MIPS_CPU_IRQ_BASE 16
+#else
+#define MIPS_CPU_IRQ_BASE 0
+#endif /* CONFIG_I8259 */
+#endif
+
+#ifdef CONFIG_IRQ_CPU_RM7K
+#ifndef RM7K_CPU_IRQ_BASE
+#define RM7K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+8)
+#endif
+#endif
+
+#ifdef CONFIG_IRQ_CPU_RM9K
+#ifndef RM9K_CPU_IRQ_BASE
+#define RM9K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+12)
+#endif
+#endif
+
+#endif /* CONFIG_IRQ_CPU */
 
 #endif /* __ASM_MACH_GENERIC_IRQ_H */
diff --git a/include/asm-mips/mach-mips/irq.h b/include/asm-mips/mach-mips/irq.h
index e994b0c..9b9da26 100644
--- a/include/asm-mips/mach-mips/irq.h
+++ b/include/asm-mips/mach-mips/irq.h
@@ -4,4 +4,6 @@
 
 #define NR_IRQS	256
 
+#include_next <irq.h>
+
 #endif /* __ASM_MACH_MIPS_IRQ_H */
diff --git a/include/asm-mips/mach-vr41xx/irq.h b/include/asm-mips/mach-vr41xx/irq.h
new file mode 100644
index 0000000..8488122
--- /dev/null
+++ b/include/asm-mips/mach-vr41xx/irq.h
@@ -0,0 +1,11 @@
+#ifndef __ASM_MACH_VR41XX_IRQ_H
+#define __ASM_MACH_VR41XX_IRQ_H
+
+#include <asm/vr41xx/irq.h> /* for MIPS_CPU_IRQ_BASE */
+#ifdef CONFIG_NEC_CMBVR4133
+#include <asm/vr41xx/cmbvr4133.h> /* for I8259A_IRQ_BASE */
+#endif
+
+#include_next <irq.h>
+
+#endif /* __ASM_MACH_VR41XX_IRQ_H */
diff --git a/include/asm-mips/mips-boards/atlasint.h b/include/asm-mips/mips-boards/atlasint.h
index b15e4ea..76add42 100644
--- a/include/asm-mips/mips-boards/atlasint.h
+++ b/include/asm-mips/mips-boards/atlasint.h
@@ -26,10 +26,12 @@
 #ifndef _MIPS_ATLASINT_H
 #define _MIPS_ATLASINT_H
 
+#include <irq.h>
+
 /*
  * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
  */
-#define MIPSCPU_INT_BASE	0
+#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
 
 /* CPU interrupt offsets */
 #define MIPSCPU_INT_SW0		0
diff --git a/include/asm-mips/mips-boards/maltaint.h b/include/asm-mips/mips-boards/maltaint.h
index da6cc2f..9180d64 100644
--- a/include/asm-mips/mips-boards/maltaint.h
+++ b/include/asm-mips/mips-boards/maltaint.h
@@ -25,6 +25,8 @@
 #ifndef _MIPS_MALTAINT_H
 #define _MIPS_MALTAINT_H
 
+#include <irq.h>
+
 /*
  * Interrupts 0..15 are used for Malta ISA compatible interrupts
  */
@@ -33,7 +35,7 @@
 /*
  * Interrupts 16..23 are used for Malta CPU interrupts (nonEIC mode)
  */
-#define MIPSCPU_INT_BASE	16
+#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
 
 /* CPU interrupt offsets */
 #define MIPSCPU_INT_SW0		0
diff --git a/include/asm-mips/mips-boards/prom.h b/include/asm-mips/mips-boards/prom.h
index 4168c7f..7bf6f5f 100644
--- a/include/asm-mips/mips-boards/prom.h
+++ b/include/asm-mips/mips-boards/prom.h
@@ -33,7 +33,6 @@
 extern void prom_init_cmdline(void);
 extern void prom_meminit(void);
 extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
-extern unsigned long prom_free_prom_memory (void);
 extern void mips_display_message(const char *str);
 extern void mips_display_word(unsigned int num);
 extern int get_ethernet_addr(char *ethernet_addr);
diff --git a/include/asm-mips/mips-boards/seadint.h b/include/asm-mips/mips-boards/seadint.h
index 365c2a3..4f6a393 100644
--- a/include/asm-mips/mips-boards/seadint.h
+++ b/include/asm-mips/mips-boards/seadint.h
@@ -20,10 +20,12 @@
 #ifndef _MIPS_SEADINT_H
 #define _MIPS_SEADINT_H
 
+#include <irq.h>
+
 /*
  * Interrupts 0..7 are used for SEAD CPU interrupts
  */
-#define MIPSCPU_INT_BASE	0
+#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
 
 #define MIPSCPU_INT_UART0	2
 #define MIPSCPU_INT_UART1	3
diff --git a/include/asm-mips/mips-boards/simint.h b/include/asm-mips/mips-boards/simint.h
index 4952e0b..54f2fe6 100644
--- a/include/asm-mips/mips-boards/simint.h
+++ b/include/asm-mips/mips-boards/simint.h
@@ -17,10 +17,11 @@
 #ifndef _MIPS_SIMINT_H
 #define _MIPS_SIMINT_H
 
+#include <irq.h>
 
 #define SIM_INT_BASE		0
 #define MIPSCPU_INT_MB0		2
-#define MIPSCPU_INT_BASE	16
+#define MIPSCPU_INT_BASE	MIPS_CPU_IRQ_BASE
 #define MIPS_CPU_TIMER_IRQ	7
 
 
diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
index 3e9468f..294bca1 100644
--- a/include/asm-mips/mipsmtregs.h
+++ b/include/asm-mips/mipsmtregs.h
@@ -165,8 +165,6 @@
 
 #ifndef __ASSEMBLY__
 
-extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
-
 static inline unsigned int dvpe(void)
 {
 	int res = 0;
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 2f9e1a9..d3fbd83 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,6 +34,20 @@
 
 #ifndef __ASSEMBLY__
 
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET		0UL
+#endif
+
+/*
+ * It's normally defined only for FLATMEM config but it's
+ * used in our early mem init code for all memory models.
+ * So always define it.
+ */
+#define ARCH_PFN_OFFSET		PFN_UP(PHYS_OFFSET)
+
 #include <linux/pfn.h>
 #include <asm/io.h>
 
@@ -132,20 +146,23 @@
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
+/*
+ * __pa()/__va() should be used only during mem init.
+ */
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
 #define __pa_page_offset(x)	((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
 #else
 #define __pa_page_offset(x)	PAGE_OFFSET
 #endif
-#define __pa(x)			((unsigned long)(x) - __pa_page_offset(x))
-#define __pa_symbol(x)		__pa(RELOC_HIDE((unsigned long)(x),0))
-#define __va(x)			((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define __pa(x)		((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
+#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x),0))
 
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)		((pfn) < max_mapnr)
+#define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
 
 #elif defined(CONFIG_SPARSEMEM)
 
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index f2e1325..3fcfd79 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -69,16 +69,6 @@
 #define ZERO_PAGE(vaddr) \
 	(virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))))
 
-#define __HAVE_ARCH_MOVE_PTE
-#define move_pte(pte, prot, old_addr, new_addr)				\
-({									\
- 	pte_t newpte = (pte);						\
-	if (pte_present(pte) && pfn_valid(pte_pfn(pte)) &&		\
-			pte_page(pte) == ZERO_PAGE(old_addr))		\
-		newpte = mk_pte(ZERO_PAGE(new_addr), (prot));		\
-	newpte;								\
-})
-
 extern void paging_init(void);
 
 /*
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h
index 76cd51c..59162f7 100644
--- a/include/asm-mips/rtlx.h
+++ b/include/asm-mips/rtlx.h
@@ -6,9 +6,10 @@
 #ifndef __ASM_RTLX_H
 #define __ASM_RTLX_H_
 
+#include <irq.h>
+
 #define LX_NODE_BASE 10
 
-#define MIPSCPU_INT_BASE       16
 #define MIPS_CPU_RTLX_IRQ 0
 
 #define RTLX_VERSION 2
diff --git a/include/asm-mips/sections.h b/include/asm-mips/sections.h
index f701627..b7e3726 100644
--- a/include/asm-mips/sections.h
+++ b/include/asm-mips/sections.h
@@ -3,6 +3,4 @@
 
 #include <asm-generic/sections.h>
 
-extern char _fdata;
-
 #endif /* _ASM_SECTIONS_H */
diff --git a/include/asm-mips/sgi/ip22.h b/include/asm-mips/sgi/ip22.h
index bbfc05c..6592f3b 100644
--- a/include/asm-mips/sgi/ip22.h
+++ b/include/asm-mips/sgi/ip22.h
@@ -21,15 +21,16 @@
  * HAL2 driver). This will prevent many complications, trust me ;-)
  */
 
+#include <irq.h>
 #include <asm/sgi/ioc.h>
 
 #define SGINT_EISA	0	/* 16 EISA irq levels (Indigo2) */
-#define SGINT_CPU	16	/* MIPS CPU define 8 interrupt sources */
-#define SGINT_LOCAL0	24	/* 8 local0 irq levels */
-#define SGINT_LOCAL1	32	/* 8 local1 irq levels */
-#define SGINT_LOCAL2	40	/* 8 local2 vectored irq levels */
-#define SGINT_LOCAL3	48	/* 8 local3 vectored irq levels */
-#define SGINT_END	56	/* End of 'spaces' */
+#define SGINT_CPU	MIPS_CPU_IRQ_BASE	/* MIPS CPU define 8 interrupt sources */
+#define SGINT_LOCAL0	(SGINT_CPU+8)	/* 8 local0 irq levels */
+#define SGINT_LOCAL1	(SGINT_CPU+16)	/* 8 local1 irq levels */
+#define SGINT_LOCAL2	(SGINT_CPU+24)	/* 8 local2 vectored irq levels */
+#define SGINT_LOCAL3	(SGINT_CPU+32)	/* 8 local3 vectored irq levels */
+#define SGINT_END	(SGINT_CPU+40)	/* End of 'spaces' */
 
 /*
  * Individual interrupt definitions for the Indy and Indigo2
diff --git a/include/asm-mips/smtc_ipi.h b/include/asm-mips/smtc_ipi.h
index f22c3e2..55f3419 100644
--- a/include/asm-mips/smtc_ipi.h
+++ b/include/asm-mips/smtc_ipi.h
@@ -44,9 +44,6 @@
 	int depth;
 };
 
-extern struct smtc_ipi_q IPIQ[NR_CPUS];
-extern struct smtc_ipi_q freeIPIq;
-
 static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
 {
 	long flags;
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index e475c45..fbcda82 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -118,6 +118,7 @@
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -129,6 +130,7 @@
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE		(1<<TIF_FREEZE)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		(0x0000ffef & ~_TIF_SECCOMP)
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 1cdd4ee..c12ebc5 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -488,7 +488,8 @@
 })
 
 /*
- * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space.
+ * __copy_from_user: - Copy a block of data from user space, with less checking.
+ * @to:   Destination address, in kernel space.
  * @from: Source address, in user space.
  * @n:    Number of bytes to copy.
  *
diff --git a/include/asm-mips/vr41xx/cmbvr4133.h b/include/asm-mips/vr41xx/cmbvr4133.h
index 9490ade..4230003 100644
--- a/include/asm-mips/vr41xx/cmbvr4133.h
+++ b/include/asm-mips/vr41xx/cmbvr4133.h
@@ -35,8 +35,8 @@
 #define CMBVR41XX_INTD_IRQ		GIU_IRQ(CMBVR41XX_INTD_PIN)
 #define CMBVR41XX_INTE_IRQ		GIU_IRQ(CMBVR41XX_INTE_PIN)
 
-#define I8259_IRQ_BASE			72
-#define I8259_IRQ(x)			(I8259_IRQ_BASE + (x))
+#define I8259A_IRQ_BASE			72
+#define I8259_IRQ(x)			(I8259A_IRQ_BASE + (x))
 #define TIMER_IRQ			I8259_IRQ(0)
 #define KEYBOARD_IRQ			I8259_IRQ(1)
 #define I8259_SLAVE_IRQ			I8259_IRQ(2)
@@ -52,6 +52,5 @@
 #define AUX_IRQ				I8259_IRQ(12)
 #define IDE_PRIMARY_IRQ			I8259_IRQ(14)
 #define IDE_SECONDARY_IRQ		I8259_IRQ(15)
-#define I8259_IRQ_LAST			IDE_SECONDARY_IRQ
 
 #endif /* __NEC_CMBVR4133_H */
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index 53283e2..f038e33 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -207,7 +207,8 @@
 
 /*
  * Atomically test *v and decrement if it is greater than 0.
- * The function returns the old value of *v minus 1.
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
  */
 static __inline__ int atomic_dec_if_positive(atomic_t *v)
 {
@@ -216,14 +217,15 @@
 	__asm__ __volatile__(
 	LWSYNC_ON_SMP
 "1:	lwarx	%0,0,%1		# atomic_dec_if_positive\n\
-	addic.	%0,%0,-1\n\
+	cmpwi	%0,1\n\
+	addi	%0,%0,-1\n\
 	blt-	2f\n"
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1\n\
 	bne-	1b"
 	ISYNC_ON_SMP
 	"\n\
-2:"	: "=&r" (t)
+2:"	: "=&b" (t)
 	: "r" (&v->counter)
 	: "cc", "memory");
 
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index 7095688..f6fa394 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -11,10 +11,31 @@
 #define BUG_OPCODE .long 0x00b00b00  /* For asm */
 #define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */
 
-#ifndef __ASSEMBLY__
-
 #ifdef CONFIG_BUG
 
+#ifdef __ASSEMBLY__
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+.macro EMIT_BUG_ENTRY addr,file,line,flags
+	 .section __bug_table,"a"
+5001:	 PPC_LONG \addr, 5002f
+	 .short \line, \flags
+	 .org 5001b+BUG_ENTRY_SIZE
+	 .previous
+	 .section .rodata,"a"
+5002:	 .asciz "\file"
+	 .previous
+.endm
+#else
+ .macro EMIT_BUG_ENTRY addr,file,line,flags
+	 .section __bug_table,"a"
+5001:	 PPC_LONG \addr
+	 .short \flags
+	 .org 5001b+BUG_ENTRY_SIZE
+	 .previous
+.endm
+#endif /* verbose */
+
+#else /* !__ASSEMBLY__ */
 /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
    sizeof(struct bug_entry), respectively */
 #ifdef CONFIG_DEBUG_BUGVERBOSE
@@ -91,8 +112,8 @@
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG_ON
 #define HAVE_ARCH_WARN_ON
-#endif /* CONFIG_BUG */
 #endif /* __ASSEMBLY __ */
+#endif /* CONFIG_BUG */
 
 #include <asm-generic/bug.h>
 
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index 7c7de87..a19a6f1 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -37,9 +37,9 @@
  */
 
 #define __dma_alloc_coherent(gfp, size, handle)	NULL
-#define __dma_free_coherent(size, addr)		do { } while (0)
-#define __dma_sync(addr, size, rw)		do { } while (0)
-#define __dma_sync_page(pg, off, sz, rw)	do { } while (0)
+#define __dma_free_coherent(size, addr)		((void)0)
+#define __dma_sync(addr, size, rw)		((void)0)
+#define __dma_sync_page(pg, off, sz, rw)	((void)0)
 
 #endif /* ! CONFIG_NOT_COHERENT_CACHE */
 
@@ -251,7 +251,7 @@
 }
 
 /* We do nothing. */
-#define dma_unmap_single(dev, addr, size, dir)	do { } while (0)
+#define dma_unmap_single(dev, addr, size, dir)	((void)0)
 
 static inline dma_addr_t
 dma_map_page(struct device *dev, struct page *page,
@@ -266,7 +266,7 @@
 }
 
 /* We do nothing. */
-#define dma_unmap_page(dev, handle, size, dir)	do { } while (0)
+#define dma_unmap_page(dev, handle, size, dir)	((void)0)
 
 static inline int
 dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
@@ -286,7 +286,7 @@
 }
 
 /* We don't do anything here. */
-#define dma_unmap_sg(dev, sg, nents, dir)	do { } while (0)
+#define dma_unmap_sg(dev, sg, nents, dir)	((void)0)
 
 #endif /* CONFIG_PPC64 */
 
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 257d1ce..7a50073 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -252,8 +252,6 @@
 	unsigned long	tb_total;	/* total wall time (mftb) of calls. */
 	unsigned long	purr_total;	/* total cpu time (PURR) of calls. */
 };
-void update_hcall_stats(unsigned long opcode, unsigned long tb_delta,
-			unsigned long purr_delta);
 #define HCALL_STAT_ARRAY_SIZE	((MAX_HCALL_OPCODE >> 2) + 1)
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h
new file mode 100644
index 0000000..4d85180
--- /dev/null
+++ b/include/asm-powerpc/libata-portmap.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_POWERPC_LIBATA_PORTMAP_H
+#define __ASM_POWERPC_LIBATA_PORTMAP_H
+
+#define ATA_PRIMARY_CMD	0x1F0
+#define ATA_PRIMARY_CTL	0x3F6
+#define ATA_PRIMARY_IRQ(dev)	pci_get_legacy_ide_irq(dev, 0)
+
+#define ATA_SECONDARY_CMD	0x170
+#define ATA_SECONDARY_CTL	0x376
+#define ATA_SECONDARY_IRQ(dev)	pci_get_legacy_ide_irq(dev, 1)
+
+#endif
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
index 4a28a85..4560d72 100644
--- a/include/asm-powerpc/mpc52xx.h
+++ b/include/asm-powerpc/mpc52xx.h
@@ -244,6 +244,7 @@
 extern void __iomem * mpc52xx_find_and_map(const char *);
 extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node);
 extern void mpc52xx_setup_cpu(void);
+extern void mpc52xx_declare_of_platform_devices(void);
 
 extern void mpc52xx_init_irq(void);
 extern unsigned int mpc52xx_get_irq(void);
diff --git a/include/asm-powerpc/posix_types.h b/include/asm-powerpc/posix_types.h
index c639107..2f2288f 100644
--- a/include/asm-powerpc/posix_types.h
+++ b/include/asm-powerpc/posix_types.h
@@ -60,7 +60,7 @@
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 #define	__FD_ISSET(d, set)	(((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
 #define	__FD_ZERO(set)	\
-  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
 
 #else /* __GNUC__ */
 
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index 356a0b1..296f4f1 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -6,6 +6,34 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
+#define PSW32_MASK_PER		0x40000000UL
+#define PSW32_MASK_DAT		0x04000000UL
+#define PSW32_MASK_IO		0x02000000UL
+#define PSW32_MASK_EXT		0x01000000UL
+#define PSW32_MASK_KEY		0x00F00000UL
+#define PSW32_MASK_MCHECK	0x00040000UL
+#define PSW32_MASK_WAIT		0x00020000UL
+#define PSW32_MASK_PSTATE	0x00010000UL
+#define PSW32_MASK_ASC		0x0000C000UL
+#define PSW32_MASK_CC		0x00003000UL
+#define PSW32_MASK_PM		0x00000f00UL
+
+#define PSW32_ADDR_AMODE31	0x80000000UL
+#define PSW32_ADDR_INSN		0x7FFFFFFFUL
+
+#define PSW32_BASE_BITS		0x00080000UL
+
+#define PSW32_ASC_PRIMARY	0x00000000UL
+#define PSW32_ASC_ACCREG	0x00004000UL
+#define PSW32_ASC_SECONDARY	0x00008000UL
+#define PSW32_ASC_HOME		0x0000C000UL
+
+#define PSW32_MASK_MERGE(CURRENT,NEW) \
+	(((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
+	 ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
+
+extern long psw32_user_bits;
+
 #define COMPAT_USER_HZ	100
 
 typedef u32		compat_size_t;
diff --git a/include/asm-s390/etr.h b/include/asm-s390/etr.h
new file mode 100644
index 0000000..b498f19
--- /dev/null
+++ b/include/asm-s390/etr.h
@@ -0,0 +1,219 @@
+/*
+ *  include/asm-s390/etr.h
+ *
+ *  Copyright IBM Corp. 2006
+ *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+#ifndef __S390_ETR_H
+#define __S390_ETR_H
+
+/* ETR attachment control register */
+struct etr_eacr {
+	unsigned int e0		: 1;	/* port 0 stepping control */
+	unsigned int e1		: 1;	/* port 1 stepping control */
+	unsigned int _pad0	: 5;	/* must be 00100 */
+	unsigned int dp		: 1;	/* data port control */
+	unsigned int p0		: 1;	/* port 0 change recognition control */
+	unsigned int p1		: 1;	/* port 1 change recognition control */
+	unsigned int _pad1	: 3;	/* must be 000 */
+	unsigned int ea		: 1;	/* ETR alert control */
+	unsigned int es		: 1;	/* ETR sync check control */
+	unsigned int sl		: 1;	/* switch to local control */
+} __attribute__ ((packed));
+
+/* Port state returned by steai */
+enum etr_psc {
+	etr_psc_operational = 0,
+	etr_psc_semi_operational = 1,
+	etr_psc_protocol_error =  4,
+	etr_psc_no_symbols = 8,
+	etr_psc_no_signal = 12,
+	etr_psc_pps_mode = 13
+};
+
+/* Logical port state returned by stetr */
+enum etr_lpsc {
+	etr_lpsc_operational_step = 0,
+	etr_lpsc_operational_alt = 1,
+	etr_lpsc_semi_operational = 2,
+	etr_lpsc_protocol_error =  4,
+	etr_lpsc_no_symbol_sync = 8,
+	etr_lpsc_no_signal = 12,
+	etr_lpsc_pps_mode = 13
+};
+
+/* ETR status words */
+struct etr_esw {
+	struct etr_eacr eacr;		/* attachment control register */
+	unsigned int y		: 1;	/* stepping mode */
+	unsigned int _pad0	: 5;	/* must be 00000 */
+	unsigned int p		: 1;	/* stepping port number */
+	unsigned int q		: 1;	/* data port number */
+	unsigned int psc0	: 4;	/* port 0 state code */
+	unsigned int psc1	: 4;	/* port 1 state code */
+} __attribute__ ((packed));
+
+/* Second level data register status word */
+struct etr_slsw {
+	unsigned int vv1	: 1;	/* copy of validity bit data frame 1 */
+	unsigned int vv2	: 1;	/* copy of validity bit data frame 2 */
+	unsigned int vv3	: 1;	/* copy of validity bit data frame 3 */
+	unsigned int vv4	: 1;	/* copy of validity bit data frame 4 */
+	unsigned int _pad0	: 19;	/* must by all zeroes */
+	unsigned int n		: 1;	/* EAF port number */
+	unsigned int v1		: 1;	/* validity bit ETR data frame 1 */
+	unsigned int v2		: 1;	/* validity bit ETR data frame 2 */
+	unsigned int v3		: 1;	/* validity bit ETR data frame 3 */
+	unsigned int v4		: 1;	/* validity bit ETR data frame 4 */
+	unsigned int _pad1	: 4;	/* must be 0000 */
+} __attribute__ ((packed));
+
+/* ETR data frames */
+struct etr_edf1 {
+	unsigned int u		: 1;	/* untuned bit */
+	unsigned int _pad0	: 1;	/* must be 0 */
+	unsigned int r		: 1;	/* service request bit */
+	unsigned int _pad1	: 4;	/* must be 0000 */
+	unsigned int a		: 1;	/* time adjustment bit */
+	unsigned int net_id	: 8;	/* ETR network id */
+	unsigned int etr_id	: 8;	/* id of ETR which sends data frames */
+	unsigned int etr_pn	: 8;	/* port number of ETR output port */
+} __attribute__ ((packed));
+
+struct etr_edf2 {
+	unsigned int etv	: 32;	/* Upper 32 bits of TOD. */
+} __attribute__ ((packed));
+
+struct etr_edf3 {
+	unsigned int rc		: 8;	/* failure reason code */
+	unsigned int _pad0	: 3;	/* must be 000 */
+	unsigned int c		: 1;	/* ETR coupled bit */
+	unsigned int tc		: 4;	/* ETR type code */
+	unsigned int blto	: 8;	/* biased local time offset */
+					/* (blto - 128) * 15 = minutes */
+	unsigned int buo	: 8;	/* biased utc offset */
+					/* (buo - 128) = leap seconds */
+} __attribute__ ((packed));
+
+struct etr_edf4 {
+	unsigned int ed		: 8;	/* ETS device dependent data */
+	unsigned int _pad0	: 1;	/* must be 0 */
+	unsigned int buc	: 5;	/* biased ut1 correction */
+					/* (buc - 16) * 0.1 seconds */
+	unsigned int em		: 6;	/* ETS error magnitude */
+	unsigned int dc		: 6;	/* ETS drift code */
+	unsigned int sc		: 6;	/* ETS steering code */
+} __attribute__ ((packed));
+
+/*
+ * ETR attachment information block, two formats
+ * format 1 has 4 reserved words with a size of 64 bytes
+ * format 2 has 16 reserved words with a size of 96 bytes
+ */
+struct etr_aib {
+	struct etr_esw esw;
+	struct etr_slsw slsw;
+	unsigned long long tsp;
+	struct etr_edf1 edf1;
+	struct etr_edf2 edf2;
+	struct etr_edf3 edf3;
+	struct etr_edf4 edf4;
+	unsigned int reserved[16];
+} __attribute__ ((packed,aligned(8)));
+
+/* ETR interruption parameter */
+struct etr_interruption_parameter {
+	unsigned int _pad0	: 8;
+	unsigned int pc0	: 1;	/* port 0 state change */
+	unsigned int pc1	: 1;	/* port 1 state change */
+	unsigned int _pad1	: 3;
+	unsigned int eai	: 1;	/* ETR alert indication */
+	unsigned int _pad2	: 18;
+} __attribute__ ((packed));
+
+/* Query TOD offset result */
+struct etr_ptff_qto {
+	unsigned long long physical_clock;
+	unsigned long long tod_offset;
+	unsigned long long logical_tod_offset;
+	unsigned long long tod_epoch_difference;
+} __attribute__ ((packed));
+
+/* Inline assembly helper functions */
+static inline int etr_setr(struct etr_eacr *ctrl)
+{
+	int rc = -ENOSYS;
+
+	asm volatile(
+		"	.insn	s,0xb2160000,0(%2)\n"
+		"0:	la	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (rc) : "m" (*ctrl), "a" (ctrl));
+	return rc;
+}
+
+/* Stores a format 1 aib with 64 bytes */
+static inline int etr_stetr(struct etr_aib *aib)
+{
+	int rc = -ENOSYS;
+
+	asm volatile(
+		"	.insn	s,0xb2170000,0(%2)\n"
+		"0:	la	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (rc) : "m" (*aib), "a" (aib));
+	return rc;
+}
+
+/* Stores a format 2 aib with 96 bytes for specified port */
+static inline int etr_steai(struct etr_aib *aib, unsigned int func)
+{
+	register unsigned int reg0 asm("0") = func;
+	int rc = -ENOSYS;
+
+	asm volatile(
+		"	.insn	s,0xb2b30000,0(%2)\n"
+		"0:	la	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (rc) : "m" (*aib), "a" (aib), "d" (reg0));
+	return rc;
+}
+
+/* Function codes for the steai instruction. */
+#define ETR_STEAI_STEPPING_PORT		0x10
+#define ETR_STEAI_ALTERNATE_PORT	0x11
+#define ETR_STEAI_PORT_0		0x12
+#define ETR_STEAI_PORT_1		0x13
+
+static inline int etr_ptff(void *ptff_block, unsigned int func)
+{
+	register unsigned int reg0 asm("0") = func;
+	register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
+	int rc = -ENOSYS;
+
+	asm volatile(
+		"	.word	0x0104\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (rc), "=m" (ptff_block)
+		: "d" (reg0), "d" (reg1), "m" (ptff_block) : "cc");
+	return rc;
+}
+
+/* Function codes for the ptff instruction. */
+#define ETR_PTFF_QAF	0x00	/* query available functions */
+#define ETR_PTFF_QTO	0x01	/* query tod offset */
+#define ETR_PTFF_QSI	0x02	/* query steering information */
+#define ETR_PTFF_ATO	0x40	/* adjust tod offset */
+#define ETR_PTFF_STO	0x41	/* set tod offset */
+#define ETR_PTFF_SFS	0x42	/* set fine steering rate */
+#define ETR_PTFF_SGS	0x43	/* set gross steering rate */
+
+/* Functions needed by the machine check handler */
+extern void etr_switch_to_local(void);
+extern void etr_sync_check(void);
+
+#endif /* __S390_ETR_H */
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
index 5e261e1..5c5d02d 100644
--- a/include/asm-s390/futex.h
+++ b/include/asm-s390/futex.h
@@ -4,8 +4,8 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 
 static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 {
@@ -21,7 +21,9 @@
 	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
+	pagefault_disable();
 	ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval);
+	pagefault_enable();
 
 	if (!ret) {
 		switch (cmp) {
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index c2f6a87..31beb18 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -32,6 +32,6 @@
 
 #define HARDIRQ_BITS	8
 
-extern void account_ticks(void);
+extern void account_ticks(u64 time);
 
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index efb7de9..a4c2d55 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -28,11 +28,7 @@
 {
 	unsigned long real_address;
 	asm volatile(
-#ifndef __s390x__
 		 "	lra	%0,0(%1)\n"
-#else /* __s390x__ */
-		 "	lrag	%0,0(%1)\n"
-#endif /* __s390x__ */
 		 "	jz	0f\n"
 		 "	la	%0,0\n"
                  "0:"
diff --git a/include/asm-s390/kdebug.h b/include/asm-s390/kdebug.h
index 40cc680..1b50f89 100644
--- a/include/asm-s390/kdebug.h
+++ b/include/asm-s390/kdebug.h
@@ -26,7 +26,6 @@
 extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head s390die_chain;
 
-
 enum die_val {
 	DIE_OOPS = 1,
 	DIE_BPT,
@@ -56,4 +55,6 @@
 	return atomic_notifier_call_chain(&s390die_chain, val, &args);
 }
 
+extern void die(const char *, struct pt_regs *, long);
+
 #endif
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index 74f7389..4a31d0a 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -220,7 +220,8 @@
 	__u32        kernel_asce;              /* 0xc4c */
 	__u32        user_asce;                /* 0xc50 */
 	__u32        panic_stack;              /* 0xc54 */
-	__u8         pad10[0xc60-0xc58];       /* 0xc58 */
+	__u32	     user_exec_asce;	       /* 0xc58 */
+	__u8	     pad10[0xc60-0xc5c];       /* 0xc5c */
 	/* entry.S sensitive area start */
 	struct       cpuinfo_S390 cpu_data;    /* 0xc60 */
 	__u32        ipl_device;               /* 0xc7c */
@@ -310,7 +311,8 @@
 	__u64        kernel_asce;              /* 0xd58 */
 	__u64        user_asce;                /* 0xd60 */
 	__u64        panic_stack;              /* 0xd68 */
-	__u8         pad10[0xd80-0xd70];       /* 0xd70 */
+	__u64	     user_exec_asce;	       /* 0xd70 */
+	__u8	     pad10[0xd80-0xd78];       /* 0xd78 */
 	/* entry.S sensitive area start */
 	struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
 	__u32        ipl_device;               /* 0xdb8 */
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index bcf24a8..1d21da2 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -9,6 +9,7 @@
 #ifndef __S390_MMU_CONTEXT_H
 #define __S390_MMU_CONTEXT_H
 
+#include <asm/pgalloc.h>
 /*
  * get a new mmu context.. S390 don't know about contexts.
  */
@@ -16,29 +17,44 @@
 
 #define destroy_context(mm)             do { } while (0)
 
+#ifndef __s390x__
+#define LCTL_OPCODE "lctl"
+#define PGTABLE_BITS (_SEGMENT_TABLE|USER_STD_MASK)
+#else
+#define LCTL_OPCODE "lctlg"
+#define PGTABLE_BITS (_REGION_TABLE|USER_STD_MASK)
+#endif
+
 static inline void enter_lazy_tlb(struct mm_struct *mm,
                                   struct task_struct *tsk)
 {
 }
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-                             struct task_struct *tsk)
+			     struct task_struct *tsk)
 {
-        if (prev != next) {
-#ifndef __s390x__
-	        S390_lowcore.user_asce = (__pa(next->pgd)&PAGE_MASK) |
-                      (_SEGMENT_TABLE|USER_STD_MASK);
-                /* Load home space page table origin. */
-                asm volatile("lctl  13,13,%0"
-			     : : "m" (S390_lowcore.user_asce) );
-#else /* __s390x__ */
-                S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
-			(_REGION_TABLE|USER_STD_MASK);
-		/* Load home space page table origin. */
-		asm volatile("lctlg  13,13,%0"
-			     : : "m" (S390_lowcore.user_asce) );
-#endif /* __s390x__ */
-        }
+	pgd_t *shadow_pgd = get_shadow_pgd(next->pgd);
+
+	if (prev != next) {
+		S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
+					 PGTABLE_BITS;
+		if (shadow_pgd) {
+			/* Load primary/secondary space page table origin. */
+			S390_lowcore.user_exec_asce =
+				(__pa(shadow_pgd) & PAGE_MASK) | PGTABLE_BITS;
+			asm volatile(LCTL_OPCODE" 1,1,%0\n"
+				     LCTL_OPCODE" 7,7,%1"
+				     : : "m" (S390_lowcore.user_exec_asce),
+					 "m" (S390_lowcore.user_asce) );
+		} else if (switch_amode) {
+			/* Load primary space page table origin. */
+			asm volatile(LCTL_OPCODE" 1,1,%0"
+				     : : "m" (S390_lowcore.user_asce) );
+		} else
+			/* Load home space page table origin. */
+			asm volatile(LCTL_OPCODE" 13,13,%0"
+				     : : "m" (S390_lowcore.user_asce) );
+	}
 	cpu_set(smp_processor_id(), next->cpu_vm_mask);
 }
 
@@ -51,4 +67,4 @@
 	set_fs(current->thread.mm_segment);
 }
 
-#endif
+#endif /* __S390_MMU_CONTEXT_H */
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 0707a7e..56c8a6c 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -47,6 +47,17 @@
 
 	if (!pgd)
 		return NULL;
+	if (s390_noexec) {
+		pgd_t *shadow_pgd = (pgd_t *)
+			__get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER);
+		struct page *page = virt_to_page(pgd);
+
+		if (!shadow_pgd) {
+			free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
+			return NULL;
+		}
+		page->lru.next = (void *) shadow_pgd;
+	}
 	for (i = 0; i < PTRS_PER_PGD; i++)
 #ifndef __s390x__
 		pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE));
@@ -58,6 +69,10 @@
 
 static inline void pgd_free(pgd_t *pgd)
 {
+	pgd_t *shadow_pgd = get_shadow_pgd(pgd);
+
+	if (shadow_pgd)
+		free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER);
 	free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
 }
 
@@ -71,6 +86,7 @@
 #define pmd_free(x)                     do { } while (0)
 #define __pmd_free_tlb(tlb,x)		do { } while (0)
 #define pgd_populate(mm, pmd, pte)      BUG()
+#define pgd_populate_kernel(mm, pmd, pte)	BUG()
 #else /* __s390x__ */
 static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
@@ -79,6 +95,17 @@
 
 	if (!pmd)
 		return NULL;
+	if (s390_noexec) {
+		pmd_t *shadow_pmd = (pmd_t *)
+			__get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER);
+		struct page *page = virt_to_page(pmd);
+
+		if (!shadow_pmd) {
+			free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
+			return NULL;
+		}
+		page->lru.next = (void *) shadow_pmd;
+	}
 	for (i=0; i < PTRS_PER_PMD; i++)
 		pmd_clear(pmd + i);
 	return pmd;
@@ -86,6 +113,10 @@
 
 static inline void pmd_free (pmd_t *pmd)
 {
+	pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+
+	if (shadow_pmd)
+		free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER);
 	free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
 }
 
@@ -95,11 +126,22 @@
 		pmd_free(pmd);			\
 	 } while (0)
 
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+static inline void
+pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
 {
 	pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd);
 }
 
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+{
+	pgd_t *shadow_pgd = get_shadow_pgd(pgd);
+	pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+
+	if (shadow_pgd && shadow_pmd)
+		pgd_populate_kernel(mm, shadow_pgd, shadow_pmd);
+	pgd_populate_kernel(mm, pgd, pmd);
+}
+
 #endif /* __s390x__ */
 
 static inline void 
@@ -119,7 +161,13 @@
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
 {
-	pmd_populate_kernel(mm, pmd, (pte_t *)page_to_phys(page));
+	pte_t *pte = (pte_t *)page_to_phys(page);
+	pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+	pte_t *shadow_pte = get_shadow_pte(pte);
+
+	pmd_populate_kernel(mm, pmd, pte);
+	if (shadow_pmd && shadow_pte)
+		pmd_populate_kernel(mm, shadow_pmd, shadow_pte);
 }
 
 /*
@@ -133,6 +181,17 @@
 
 	if (!pte)
 		return NULL;
+	if (s390_noexec) {
+		pte_t *shadow_pte = (pte_t *)
+			__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+		struct page *page = virt_to_page(pte);
+
+		if (!shadow_pte) {
+			free_page((unsigned long) pte);
+			return NULL;
+		}
+		page->lru.next = (void *) shadow_pte;
+	}
 	for (i=0; i < PTRS_PER_PTE; i++) {
 		pte_clear(mm, vmaddr, pte + i);
 		vmaddr += PAGE_SIZE;
@@ -151,14 +210,30 @@
 
 static inline void pte_free_kernel(pte_t *pte)
 {
-        free_page((unsigned long) pte);
+	pte_t *shadow_pte = get_shadow_pte(pte);
+
+	if (shadow_pte)
+		free_page((unsigned long) shadow_pte);
+	free_page((unsigned long) pte);
 }
 
 static inline void pte_free(struct page *pte)
 {
-        __free_page(pte);
+	struct page *shadow_page = get_shadow_page(pte);
+
+	if (shadow_page)
+		__free_page(shadow_page);
+	__free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte) tlb_remove_page(tlb,pte)
+#define __pte_free_tlb(tlb, pte)					\
+({									\
+	struct mmu_gather *__tlb = (tlb);				\
+	struct page *__pte = (pte);					\
+	struct page *shadow_page = get_shadow_page(__pte);		\
+	if (shadow_page)						\
+		tlb_remove_page(__tlb, shadow_page);			\
+	tlb_remove_page(__tlb, __pte);					\
+})
 
 #endif /* _S390_PGALLOC_H */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index ae61aca..13c1654 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -40,6 +40,7 @@
 
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
 extern void paging_init(void);
+extern void vmem_map_init(void);
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
@@ -223,6 +224,8 @@
 #define _PAGE_TYPE_FILE		0x601	/* bit 0x002 is used for offset !! */
 #define _PAGE_TYPE_RO		0x200
 #define _PAGE_TYPE_RW		0x000
+#define _PAGE_TYPE_EX_RO	0x202
+#define _PAGE_TYPE_EX_RW	0x002
 
 /*
  * PTE type bits are rather complicated. handle_pte_fault uses pte_present,
@@ -243,11 +246,13 @@
  * _PAGE_TYPE_FILE	11?1   ->   11?1
  * _PAGE_TYPE_RO	0100   ->   1100
  * _PAGE_TYPE_RW	0000   ->   1000
+ * _PAGE_TYPE_EX_RO	0110   ->   1110
+ * _PAGE_TYPE_EX_RW	0010   ->   1010
  *
- * pte_none is true for bits combinations 1000, 1100
+ * pte_none is true for bits combinations 1000, 1010, 1100, 1110
  * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001
  * pte_file is true for bits combinations 1101, 1111
- * swap pte is 1011 and 0001, 0011, 0101, 0111, 1010 and 1110 are invalid.
+ * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
  */
 
 #ifndef __s390x__
@@ -312,33 +317,100 @@
 #define PAGE_NONE	__pgprot(_PAGE_TYPE_NONE)
 #define PAGE_RO		__pgprot(_PAGE_TYPE_RO)
 #define PAGE_RW		__pgprot(_PAGE_TYPE_RW)
+#define PAGE_EX_RO	__pgprot(_PAGE_TYPE_EX_RO)
+#define PAGE_EX_RW	__pgprot(_PAGE_TYPE_EX_RW)
 
 #define PAGE_KERNEL	PAGE_RW
 #define PAGE_COPY	PAGE_RO
 
 /*
- * The S390 can't do page protection for execute, and considers that the
- * same are read. Also, write permissions imply read permissions. This is
- * the closest we can get..
+ * Dependent on the EXEC_PROTECT option s390 can do execute protection.
+ * Write permission always implies read permission. In theory with a
+ * primary/secondary page table execute only can be implemented but
+ * it would cost an additional bit in the pte to distinguish all the
+ * different pte types. To avoid that execute permission currently
+ * implies read permission as well.
  */
          /*xwr*/
 #define __P000	PAGE_NONE
 #define __P001	PAGE_RO
 #define __P010	PAGE_RO
 #define __P011	PAGE_RO
-#define __P100	PAGE_RO
-#define __P101	PAGE_RO
-#define __P110	PAGE_RO
-#define __P111	PAGE_RO
+#define __P100	PAGE_EX_RO
+#define __P101	PAGE_EX_RO
+#define __P110	PAGE_EX_RO
+#define __P111	PAGE_EX_RO
 
 #define __S000	PAGE_NONE
 #define __S001	PAGE_RO
 #define __S010	PAGE_RW
 #define __S011	PAGE_RW
-#define __S100	PAGE_RO
-#define __S101	PAGE_RO
-#define __S110	PAGE_RW
-#define __S111	PAGE_RW
+#define __S100	PAGE_EX_RO
+#define __S101	PAGE_EX_RO
+#define __S110	PAGE_EX_RW
+#define __S111	PAGE_EX_RW
+
+#ifndef __s390x__
+# define PMD_SHADOW_SHIFT	1
+# define PGD_SHADOW_SHIFT	1
+#else /* __s390x__ */
+# define PMD_SHADOW_SHIFT	2
+# define PGD_SHADOW_SHIFT	2
+#endif /* __s390x__ */
+
+static inline struct page *get_shadow_page(struct page *page)
+{
+	if (s390_noexec && !list_empty(&page->lru))
+		return virt_to_page(page->lru.next);
+	return NULL;
+}
+
+static inline pte_t *get_shadow_pte(pte_t *ptep)
+{
+	unsigned long pteptr = (unsigned long) (ptep);
+
+	if (s390_noexec) {
+		unsigned long offset = pteptr & (PAGE_SIZE - 1);
+		void *addr = (void *) (pteptr ^ offset);
+		struct page *page = virt_to_page(addr);
+		if (!list_empty(&page->lru))
+			return (pte_t *) ((unsigned long) page->lru.next |
+								offset);
+	}
+	return NULL;
+}
+
+static inline pmd_t *get_shadow_pmd(pmd_t *pmdp)
+{
+	unsigned long pmdptr = (unsigned long) (pmdp);
+
+	if (s390_noexec) {
+		unsigned long offset = pmdptr &
+				((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1);
+		void *addr = (void *) (pmdptr ^ offset);
+		struct page *page = virt_to_page(addr);
+		if (!list_empty(&page->lru))
+			return (pmd_t *) ((unsigned long) page->lru.next |
+								offset);
+	}
+	return NULL;
+}
+
+static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
+{
+	unsigned long pgdptr = (unsigned long) (pgdp);
+
+	if (s390_noexec) {
+		unsigned long offset = pgdptr &
+				((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1);
+		void *addr = (void *) (pgdptr ^ offset);
+		struct page *page = virt_to_page(addr);
+		if (!list_empty(&page->lru))
+			return (pgd_t *) ((unsigned long) page->lru.next |
+								offset);
+	}
+	return NULL;
+}
 
 /*
  * Certain architectures need to do special things when PTEs
@@ -347,7 +419,16 @@
  */
 static inline void set_pte(pte_t *pteptr, pte_t pteval)
 {
+	pte_t *shadow_pte = get_shadow_pte(pteptr);
+
 	*pteptr = pteval;
+	if (shadow_pte) {
+		if (!(pte_val(pteval) & _PAGE_INVALID) &&
+		    (pte_val(pteval) & _PAGE_SWX))
+			pte_val(*shadow_pte) = pte_val(pteval) | _PAGE_RO;
+		else
+			pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
+	}
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
@@ -465,7 +546,7 @@
 
 static inline void pgd_clear(pgd_t * pgdp)      { }
 
-static inline void pmd_clear(pmd_t * pmdp)
+static inline void pmd_clear_kernel(pmd_t * pmdp)
 {
 	pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
 	pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
@@ -473,24 +554,55 @@
 	pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
 }
 
+static inline void pmd_clear(pmd_t * pmdp)
+{
+	pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
+
+	pmd_clear_kernel(pmdp);
+	if (shadow_pmd)
+		pmd_clear_kernel(shadow_pmd);
+}
+
 #else /* __s390x__ */
 
-static inline void pgd_clear(pgd_t * pgdp)
+static inline void pgd_clear_kernel(pgd_t * pgdp)
 {
 	pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
 }
 
-static inline void pmd_clear(pmd_t * pmdp)
+static inline void pgd_clear(pgd_t * pgdp)
+{
+	pgd_t *shadow_pgd = get_shadow_pgd(pgdp);
+
+	pgd_clear_kernel(pgdp);
+	if (shadow_pgd)
+		pgd_clear_kernel(shadow_pgd);
+}
+
+static inline void pmd_clear_kernel(pmd_t * pmdp)
 {
 	pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
 	pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
 }
 
+static inline void pmd_clear(pmd_t * pmdp)
+{
+	pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
+
+	pmd_clear_kernel(pmdp);
+	if (shadow_pmd)
+		pmd_clear_kernel(shadow_pmd);
+}
+
 #endif /* __s390x__ */
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
+	pte_t *shadow_pte = get_shadow_pte(ptep);
+
 	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	if (shadow_pte)
+		pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
 }
 
 /*
@@ -608,8 +720,11 @@
 		 unsigned long address, pte_t *ptep)
 {
 	pte_t pte = *ptep;
+	pte_t *shadow_pte = get_shadow_pte(ptep);
 
 	__ptep_ipte(address, ptep);
+	if (shadow_pte)
+		__ptep_ipte(address, shadow_pte);
 	return pte;
 }
 
diff --git a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h
index b94c988..397d93f 100644
--- a/include/asm-s390/posix_types.h
+++ b/include/asm-s390/posix_types.h
@@ -104,7 +104,7 @@
 
 #undef  __FD_ZERO
 #define __FD_ZERO(fdsetp) \
-	((void) memset ((__ptr_t) (fdsetp), 0, sizeof (__kernel_fd_set)))
+	((void) memset ((void *) (fdsetp), 0, sizeof (__kernel_fd_set)))
 
 #endif     /* __KERNEL__ */
 
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index cbbedc6..4c1b739 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -50,6 +50,7 @@
         unsigned long pgtable_cache_sz;
 };
 
+extern void s390_adjust_jiffies(void);
 extern void print_cpu_info(struct cpuinfo_S390 *);
 
 /* Lazy FPU handling on uni-processor */
@@ -144,7 +145,8 @@
 #ifndef __s390x__
 
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        regs->psw.mask  = PSW_USER_BITS;                        \
+	set_fs(USER_DS);					\
+	regs->psw.mask	= psw_user_bits;			\
         regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
         regs->gprs[15]  = new_stackp ;                          \
 } while (0)
@@ -152,13 +154,15 @@
 #else /* __s390x__ */
 
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        regs->psw.mask  = PSW_USER_BITS;                        \
+	set_fs(USER_DS);					\
+	regs->psw.mask	= psw_user_bits;			\
         regs->psw.addr  = new_psw;                              \
         regs->gprs[15]  = new_stackp;                           \
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {          \
-	regs->psw.mask  = PSW_USER32_BITS;			\
+	set_fs(USER_DS);					\
+	regs->psw.mask	= psw_user32_bits;			\
         regs->psw.addr  = new_psw;                              \
         regs->gprs[15]  = new_stackp;                           \
 } while (0)
@@ -201,9 +205,8 @@
 static inline void cpu_relax(void)
 {
 	if (MACHINE_HAS_DIAG44)
-		asm volatile("diag 0,0,68" : : : "memory");
-	else
-		barrier();
+		asm volatile("diag 0,0,68");
+	barrier();
 }
 
 /*
@@ -328,6 +331,18 @@
 }
 
 /*
+ * Basic Machine Check/Program Check Handler.
+ */
+
+extern void s390_base_mcck_handler(void);
+extern void s390_base_pgm_handler(void);
+extern void s390_base_ext_handler(void);
+
+extern void (*s390_base_mcck_handler_fn)(void);
+extern void (*s390_base_pgm_handler_fn)(void);
+extern void (*s390_base_ext_handler_fn)(void);
+
+/*
  * CPU idle notifier chain.
  */
 #define CPU_IDLE	0
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 7b768c5..fa6ca87 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -266,17 +266,12 @@
 #define PSW_ASC_SECONDARY	0x0000800000000000UL
 #define PSW_ASC_HOME		0x0000C00000000000UL
 
-#define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
-			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
-			 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
+extern long psw_user32_bits;
 
 #endif /* __s390x__ */
 
-#define PSW_KERNEL_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
-			 PSW_MASK_MCHECK | PSW_DEFAULT_KEY)
-#define PSW_USER_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
-			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
-			 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
+extern long psw_kernel_bits;
+extern long psw_user_bits;
 
 /* This macro merges a NEW PSW mask specified by the user into
    the currently active PSW mask CURRENT, modifying only those
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h
index 532e65a..f584f4a 100644
--- a/include/asm-s390/reset.h
+++ b/include/asm-s390/reset.h
@@ -18,7 +18,4 @@
 extern void register_reset_call(struct reset_call *reset);
 extern void unregister_reset_call(struct reset_call *reset);
 extern void s390_reset_system(void);
-extern void (*s390_reset_mcck_handler)(void);
-extern void (*s390_reset_pgm_handler)(void);
-
 #endif /* _ASM_S390_RESET_H */
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
new file mode 100644
index 0000000..468b970
--- /dev/null
+++ b/include/asm-s390/sclp.h
@@ -0,0 +1,39 @@
+/*
+ *  include/asm-s390/sclp.h
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_SCLP_H
+#define _ASM_S390_SCLP_H
+
+#include <linux/types.h>
+
+struct sccb_header {
+	u16	length;
+	u8	function_code;
+	u8	control_mask[3];
+	u16	response_code;
+} __attribute__((packed));
+
+#define LOADPARM_LEN 8
+
+struct sclp_readinfo_sccb {
+	struct	sccb_header header;	/* 0-7 */
+	u16	rnmax;			/* 8-9 */
+	u8	rnsize;			/* 10 */
+	u8	_reserved0[24 - 11];	/* 11-23 */
+	u8	loadparm[LOADPARM_LEN];	/* 24-31 */
+	u8	_reserved1[91 - 32];	/* 32-90 */
+	u8	flags;			/* 91 */
+	u8	_reserved2[100 - 92];	/* 92-99 */
+	u32	rnsize2;		/* 100-103 */
+	u64	rnmax2;			/* 104-111 */
+	u8	_reserved3[4096 - 112];	/* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+extern struct sclp_readinfo_sccb s390_readinfo_sccb;
+extern void sclp_readinfo_early(void);
+
+#endif /* _ASM_S390_SCLP_H */
diff --git a/include/asm-s390/sections.h b/include/asm-s390/sections.h
index 3a0b8ff..1c5a2c4 100644
--- a/include/asm-s390/sections.h
+++ b/include/asm-s390/sections.h
@@ -3,4 +3,6 @@
 
 #include <asm-generic/sections.h>
 
+extern char _eshared[];
+
 #endif
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
index 9574fe8..3388bb5 100644
--- a/include/asm-s390/setup.h
+++ b/include/asm-s390/setup.h
@@ -42,6 +42,18 @@
 
 extern struct mem_chunk memory_chunk[];
 
+#ifdef CONFIG_S390_SWITCH_AMODE
+extern unsigned int switch_amode;
+#else
+#define switch_amode	(0)
+#endif
+
+#ifdef CONFIG_S390_EXEC_PROTECT
+extern unsigned int s390_noexec;
+#else
+#define s390_noexec	(0)
+#endif
+
 /*
  * Machine features detected in head.S
  */
@@ -74,6 +86,9 @@
 extern unsigned int console_devno;
 extern unsigned int console_irq;
 
+extern char vmhalt_cmd[];
+extern char vmpoff_cmd[];
+
 #define CONSOLE_IS_UNDEFINED	(console_mode == 0)
 #define CONSOLE_IS_SCLP		(console_mode == 1)
 #define CONSOLE_IS_3215		(console_mode == 2)
@@ -141,13 +156,19 @@
 extern u32 ipl_flags;
 extern u16 ipl_devno;
 
-void do_reipl(void);
+extern void do_reipl(void);
+extern void ipl_save_parameters(void);
 
 enum {
 	IPL_DEVNO_VALID	= 1,
 	IPL_PARMBLOCK_VALID = 2,
+	IPL_NSS_VALID = 4,
 };
 
+#define NSS_NAME_SIZE	8
+
+extern char kernel_nss_name[];
+
 #define IPL_PARMBLOCK_START	((struct ipl_parameter_block *) \
 				 IPL_PARMBLOCK_ORIGIN)
 #define IPL_PARMBLOCK_SIZE	(IPL_PARMBLOCK_START->hdr.len)
diff --git a/arch/s390/math-emu/sfp-util.h b/include/asm-s390/sfp-util.h
similarity index 90%
rename from arch/s390/math-emu/sfp-util.h
rename to include/asm-s390/sfp-util.h
index 5b6ca45..8cabcd2 100644
--- a/arch/s390/math-emu/sfp-util.h
+++ b/include/asm-s390/sfp-util.h
@@ -52,12 +52,12 @@
 })
 
 #define udiv_qrnnd(q, r, n1, n0, d)			\
-  do { unsigned long __r;				\
+  do { unsigned int __r;				\
     (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));		\
     (r) = __r;						\
   } while (0)
-extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long,
-				   unsigned long , unsigned long);
+extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
+				   unsigned int , unsigned int);
 
 #define UDIV_NEEDS_NORMALIZATION 0
 
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 7097c96..b957e4c 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -31,6 +31,10 @@
 	__u16      cpu;
 } sigp_info;
 
+extern void machine_restart_smp(char *);
+extern void machine_halt_smp(void);
+extern void machine_power_off_smp(void);
+
 extern void smp_setup_cpu_possible_map(void);
 extern int smp_call_function_on(void (*func) (void *info), void *info,
 				int nonatomic, int wait, int cpu);
@@ -106,7 +110,7 @@
 static inline void smp_send_stop(void)
 {
 	/* Disable all interrupts/machine checks */
-	__load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
+	__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
 }
 
 #define smp_cpu_not_running(cpu)	1
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index bd0b05a..bbe137c 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -373,8 +373,8 @@
 	__load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
 }
 
-#define local_mcck_enable()  __set_psw_mask(PSW_KERNEL_BITS)
-#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK)
+#define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
+#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
 
 #ifdef CONFIG_SMP
 
diff --git a/include/asm-s390/tape390.h b/include/asm-s390/tape390.h
index f1d66ba..884fba4 100644
--- a/include/asm-s390/tape390.h
+++ b/include/asm-s390/tape390.h
@@ -1,11 +1,11 @@
 /*************************************************************************
  *
  * tape390.h
- *         enables user programs to display messages on the tape device
+ *	   enables user programs to display messages and control encryption
+ *	   on s390 tape devices
  *
- *  S390 and zSeries version
- *         Copyright (C) 2001 IBM Corporation
- *         Author(s): Despina Papadopoulou <despina_p@de.ibm.com>
+ *	   Copyright IBM Corp. 2001,2006
+ *	   Author(s): Michael Holzheu <holzheu@de.ibm.com>
  *
  *************************************************************************/
 
@@ -36,4 +36,68 @@
         char message2[8];
 } display_struct;
 
+/*
+ * Tape encryption support
+ */
+
+struct tape390_crypt_info {
+	char capability;
+	char status;
+	char medium_status;
+} __attribute__ ((packed));
+
+
+/* Macros for "capable" field */
+#define TAPE390_CRYPT_SUPPORTED_MASK 0x01
+#define TAPE390_CRYPT_SUPPORTED(x) \
+	((x.capability & TAPE390_CRYPT_SUPPORTED_MASK))
+
+/* Macros for "status" field */
+#define TAPE390_CRYPT_ON_MASK 0x01
+#define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK))
+
+/* Macros for "medium status" field */
+#define TAPE390_MEDIUM_LOADED_MASK 0x01
+#define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02
+#define TAPE390_MEDIUM_ENCRYPTED(x) \
+	(((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK))
+#define TAPE390_MEDIUM_LOADED(x) \
+	(((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK))
+
+/*
+ * The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption.
+ * The "encryption_capable" and "tape_status" fields are ignored for this ioctl!
+ */
+#define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info)
+
+/*
+ * The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state.
+ */
+#define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info)
+
+/* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */
+#define TAPE390_KEKL_TYPE_NONE 0
+#define TAPE390_KEKL_TYPE_LABEL 1
+#define TAPE390_KEKL_TYPE_HASH 2
+
+struct tape390_kekl {
+	unsigned char type;
+	unsigned char type_on_tape;
+	char label[65];
+} __attribute__ ((packed));
+
+struct tape390_kekl_pair {
+	struct tape390_kekl kekl[2];
+} __attribute__ ((packed));
+
+/*
+ * The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels.
+ */
+#define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair)
+
+/*
+ * The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels.
+ */
+#define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair)
+
 #endif 
diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h
index 30e5cbe..adb3486 100644
--- a/include/asm-s390/timer.h
+++ b/include/asm-s390/timer.h
@@ -45,6 +45,9 @@
 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
 extern int del_virt_timer(struct vtimer_list *timer);
 
+extern void init_cpu_vtimer(void);
+extern void vtime_init(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_S390_TIMER_H */
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index 4df4a41..98229db 100644
--- a/include/asm-s390/timex.h
+++ b/include/asm-s390/timex.h
@@ -11,6 +11,41 @@
 #ifndef _ASM_S390_TIMEX_H
 #define _ASM_S390_TIMEX_H
 
+/* Inline functions for clock register access. */
+static inline int set_clock(__u64 time)
+{
+	int cc;
+
+	asm volatile(
+		"   sck   0(%2)\n"
+		"   ipm   %0\n"
+		"   srl   %0,28\n"
+		: "=d" (cc) : "m" (time), "a" (&time) : "cc");
+	return cc;
+}
+
+static inline int store_clock(__u64 *time)
+{
+	int cc;
+
+	asm volatile(
+		"   stck  0(%2)\n"
+		"   ipm   %0\n"
+		"   srl   %0,28\n"
+		: "=d" (cc), "=m" (*time) : "a" (time) : "cc");
+	return cc;
+}
+
+static inline void set_clock_comparator(__u64 time)
+{
+	asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time));
+}
+
+static inline void store_clock_comparator(__u64 *time)
+{
+	asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time));
+}
+
 #define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
 
 typedef unsigned long long cycles_t;
@@ -27,9 +62,24 @@
 	return clk;
 }
 
+static inline void get_clock_extended(void *dest)
+{
+	typedef struct { unsigned long long clk[2]; } __clock_t;
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+	asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc");
+#else /* __GNUC__ */
+	asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest))
+				   : "a" ((__clock_t *)dest) : "cc");
+#endif /* __GNUC__ */
+}
+
 static inline cycles_t get_cycles(void)
 {
 	return (cycles_t) get_clock() >> 2;
 }
 
+int get_sync_clock(unsigned long long *clock);
+void init_cpu_timer(void);
+
 #endif
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index fa4dc91..66793f5 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -3,6 +3,7 @@
 
 #include <linux/mm.h>
 #include <asm/processor.h>
+#include <asm/pgalloc.h>
 
 /*
  * TLB flushing:
@@ -102,6 +103,14 @@
 	if (unlikely(cpus_empty(mm->cpu_vm_mask)))
 		return;
 	if (MACHINE_HAS_IDTE) {
+		pgd_t *shadow_pgd = get_shadow_pgd(mm->pgd);
+
+		if (shadow_pgd) {
+			asm volatile(
+				"	.insn	rrf,0xb98e0000,0,%0,%1,0"
+				: : "a" (2048),
+				"a" (__pa(shadow_pgd) & PAGE_MASK) : "cc" );
+		}
 		asm volatile(
 			"	.insn	rrf,0xb98e0000,0,%0,%1,0"
 			: : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc");
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index 73ac4e8..0235970 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -90,6 +90,8 @@
 extern struct uaccess_ops uaccess;
 extern struct uaccess_ops uaccess_std;
 extern struct uaccess_ops uaccess_mvcos;
+extern struct uaccess_ops uaccess_mvcos_switch;
+extern struct uaccess_ops uaccess_pt;
 
 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
 {
diff --git a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
index 267e631..34518ea 100644
--- a/include/asm-sparc/checksum.h
+++ b/include/asm-sparc/checksum.h
@@ -151,7 +151,7 @@
 			     "xnor\t%%g0, %0, %0"
 			     : "=r" (sum), "=&r" (iph)
 			     : "r" (ihl), "1" (iph)
-			     : "g2", "g3", "g4", "cc");
+			     : "g2", "g3", "g4", "cc", "memory");
 	return sum;
 }
 
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 188f726..e57ff13 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -408,6 +408,15 @@
 
 #include <asm-generic/pgtable-nopud.h>
 
+#ifdef CONFIG_HIGHMEM
+/* Clear a kernel PTE and flush it from the TLB */
+#define kpte_clear_flush(ptep, vaddr)					\
+do {									\
+	pte_clear(&init_mm, vaddr, ptep);				\
+	__flush_tlb_one(vaddr);						\
+} while (0)
+#endif
+
 #endif
 #endif
 
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 5b535ea..8da9609 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -7,7 +7,13 @@
 
 #include <asm/alternative.h>
 
-#define ADDR (*(volatile long *) addr)
+#if __GNUC__ < 4 || __GNUC_MINOR__ < 1
+/* Technically wrong, but this avoids compilation errors on some gcc
+   versions. */
+#define ADDR "=m" (*(volatile long *) addr)
+#else
+#define ADDR "+m" (*(volatile long *) addr)
+#endif
 
 /**
  * set_bit - Atomically set a bit in memory
@@ -23,7 +29,7 @@
 {
 	__asm__ __volatile__( LOCK_PREFIX
 		"btsl %1,%0"
-		:"+m" (ADDR)
+		:ADDR
 		:"dIr" (nr) : "memory");
 }
 
@@ -40,7 +46,7 @@
 {
 	__asm__ volatile(
 		"btsl %1,%0"
-		:"+m" (ADDR)
+		:ADDR
 		:"dIr" (nr) : "memory");
 }
 
@@ -58,7 +64,7 @@
 {
 	__asm__ __volatile__( LOCK_PREFIX
 		"btrl %1,%0"
-		:"+m" (ADDR)
+		:ADDR
 		:"dIr" (nr));
 }
 
@@ -66,7 +72,7 @@
 {
 	__asm__ __volatile__(
 		"btrl %1,%0"
-		:"+m" (ADDR)
+		:ADDR
 		:"dIr" (nr));
 }
 
@@ -86,7 +92,7 @@
 {
 	__asm__ __volatile__(
 		"btcl %1,%0"
-		:"+m" (ADDR)
+		:ADDR
 		:"dIr" (nr));
 }
 
@@ -103,7 +109,7 @@
 {
 	__asm__ __volatile__( LOCK_PREFIX
 		"btcl %1,%0"
-		:"+m" (ADDR)
+		:ADDR
 		:"dIr" (nr));
 }
 
@@ -121,7 +127,7 @@
 
 	__asm__ __volatile__( LOCK_PREFIX
 		"btsl %2,%1\n\tsbbl %0,%0"
-		:"=r" (oldbit),"+m" (ADDR)
+		:"=r" (oldbit),ADDR
 		:"dIr" (nr) : "memory");
 	return oldbit;
 }
@@ -141,7 +147,7 @@
 
 	__asm__(
 		"btsl %2,%1\n\tsbbl %0,%0"
-		:"=r" (oldbit),"+m" (ADDR)
+		:"=r" (oldbit),ADDR
 		:"dIr" (nr));
 	return oldbit;
 }
@@ -160,7 +166,7 @@
 
 	__asm__ __volatile__( LOCK_PREFIX
 		"btrl %2,%1\n\tsbbl %0,%0"
-		:"=r" (oldbit),"+m" (ADDR)
+		:"=r" (oldbit),ADDR
 		:"dIr" (nr) : "memory");
 	return oldbit;
 }
@@ -180,7 +186,7 @@
 
 	__asm__(
 		"btrl %2,%1\n\tsbbl %0,%0"
-		:"=r" (oldbit),"+m" (ADDR)
+		:"=r" (oldbit),ADDR
 		:"dIr" (nr));
 	return oldbit;
 }
@@ -192,7 +198,7 @@
 
 	__asm__ __volatile__(
 		"btcl %2,%1\n\tsbbl %0,%0"
-		:"=r" (oldbit),"+m" (ADDR)
+		:"=r" (oldbit),ADDR
 		:"dIr" (nr) : "memory");
 	return oldbit;
 }
@@ -211,7 +217,7 @@
 
 	__asm__ __volatile__( LOCK_PREFIX
 		"btcl %2,%1\n\tsbbl %0,%0"
-		:"=r" (oldbit),"+m" (ADDR)
+		:"=r" (oldbit),ADDR
 		:"dIr" (nr) : "memory");
 	return oldbit;
 }
@@ -237,7 +243,7 @@
 	__asm__ __volatile__(
 		"btl %2,%1\n\tsbbl %0,%0"
 		:"=r" (oldbit)
-		:"m" (ADDR),"dIr" (nr));
+		:"m" (*(volatile long *)addr),"dIr" (nr));
 	return oldbit;
 }
 
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index be9ec68..49dbab0 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -63,6 +63,9 @@
 	return (dma_addr == bad_dma_address);
 }
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
 extern void *dma_alloc_coherent(struct device *dev, size_t size,
 				dma_addr_t *dma_handle, gfp_t gfp);
 extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
index ba94ab3..ab913ff 100644
--- a/include/asm-x86_64/swiotlb.h
+++ b/include/asm-x86_64/swiotlb.h
@@ -1,6 +1,5 @@
 #ifndef _ASM_SWIOTLB_H
-#define _ASM_SWTIOLB_H 1
-
+#define _ASM_SWIOTLB_H 1
 
 #include <asm/dma-mapping.h>
 
@@ -45,6 +44,7 @@
 extern int swiotlb_force;
 
 #ifdef CONFIG_SWIOTLB
+#define SWIOTLB_ARCH_NEED_ALLOC
 extern int swiotlb;
 #else
 #define swiotlb 0
@@ -52,4 +52,6 @@
 
 extern void pci_swiotlb_init(void);
 
-#endif /* _ASM_SWTIOLB_H */
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+#endif /* _ASM_SWIOTLB_H */
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index d5dbc87..c0eac51 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -157,7 +157,7 @@
 	  case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\
 	  case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\
 	  case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\
-	  case 8: __put_user_asm(x,ptr,retval,"q","","ir",-EFAULT); break;\
+	  case 8: __put_user_asm(x,ptr,retval,"q","","Zr",-EFAULT); break;\
 	  default: __put_user_bad();					\
 	}								\
 } while (0)
diff --git a/include/asm-xtensa/posix_types.h b/include/asm-xtensa/posix_types.h
index 3470b44..4ad77dd 100644
--- a/include/asm-xtensa/posix_types.h
+++ b/include/asm-xtensa/posix_types.h
@@ -60,7 +60,7 @@
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 #define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
 #define	__FD_ZERO(set)	\
-  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
 
 #else /* __GNUC__ */
 
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 862e483c..157db77 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -69,7 +69,6 @@
 header-y += i2c-dev.h
 header-y += i8k.h
 header-y += icmp.h
-header-y += if_addr.h
 header-y += if_arcnet.h
 header-y += if_arp.h
 header-y += if_bonding.h
@@ -79,7 +78,6 @@
 header-y += if.h
 header-y += if_hippi.h
 header-y += if_infiniband.h
-header-y += if_link.h
 header-y += if_packet.h
 header-y += if_plip.h
 header-y += if_ppp.h
@@ -129,7 +127,6 @@
 header-y += ppdev.h
 header-y += prctl.h
 header-y += ps2esdi.h
-header-y += qic117.h
 header-y += qnxtypes.h
 header-y += quotaio_v1.h
 header-y += quotaio_v2.h
@@ -214,6 +211,7 @@
 unifdef-y += i2c.h
 unifdef-y += i2o-dev.h
 unifdef-y += icmpv6.h
+unifdef-y += if_addr.h
 unifdef-y += if_bridge.h
 unifdef-y += if_ec.h
 unifdef-y += if_eql.h
@@ -221,6 +219,7 @@
 unifdef-y += if_fddi.h
 unifdef-y += if_frad.h
 unifdef-y += if_ltalk.h
+unifdef-y += if_link.h
 unifdef-y += if_pppox.h
 unifdef-y += if_shaper.h
 unifdef-y += if_tr.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 2b0c955..91f1f23 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -47,6 +47,7 @@
 	ACPI_IRQ_MODEL_PIC = 0,
 	ACPI_IRQ_MODEL_IOAPIC,
 	ACPI_IRQ_MODEL_IOSAPIC,
+	ACPI_IRQ_MODEL_PLATFORM,
 	ACPI_IRQ_MODEL_COUNT
 };
 
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 5d1eabc..638165f 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -31,9 +31,8 @@
 	return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
 }
 
-/*
+/**
  * rol32 - rotate a 32-bit value left
- *
  * @word: value to rotate
  * @shift: bits to roll
  */
@@ -42,9 +41,8 @@
 	return (word << shift) | (word >> (32 - shift));
 }
 
-/*
+/**
  * ror32 - rotate a 32-bit value right
- *
  * @word: value to rotate
  * @shift: bits to roll
  */
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index f309b00..1e29b13 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -6,6 +6,10 @@
 #include <linux/kdev_t.h>
 #include <linux/list.h>
 
+struct file_operations;
+struct inode;
+struct module;
+
 struct cdev {
 	struct kobject kobj;
 	struct module *owner;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index df1c918..f8ebd7c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -301,7 +301,7 @@
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
 					struct resource *data_resource);
 extern unsigned long efi_get_time(void);
-extern int __init efi_set_rtc_mmss(unsigned long nowtime);
+extern int efi_set_rtc_mmss(unsigned long nowtime);
 extern int is_available_memory(efi_memory_desc_t * md);
 extern struct efi_memory_map memmap;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 186da81..1410e53 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -426,6 +426,7 @@
 	/* migrate the contents of a page to the specified target */
 	int (*migratepage) (struct address_space *,
 			struct page *, struct page *);
+	int (*launder_page) (struct page *);
 };
 
 struct backing_dev_info;
@@ -458,7 +459,7 @@
 	struct inode *		bd_inode;	/* will die */
 	int			bd_openers;
 	struct mutex		bd_mutex;	/* open/close mutex */
-	struct mutex		bd_mount_mutex;	/* mount mutex */
+	struct semaphore	bd_mount_sem;
 	struct list_head	bd_inodes;
 	void *			bd_holder;
 	int			bd_holders;
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index 2b54eac..818c6af 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -60,13 +60,15 @@
 #define TAG_MASK		0xf8
 #endif /* __KERNEL__ */
 
+#include <linux/types.h>
+
 /*
  * Command Header sizes for IOCTL commands
  */
 
-#define HDIO_DRIVE_CMD_HDR_SIZE		(4 * sizeof(u8))
-#define HDIO_DRIVE_HOB_HDR_SIZE		(8 * sizeof(u8))
-#define HDIO_DRIVE_TASK_HDR_SIZE	(8 * sizeof(u8))
+#define HDIO_DRIVE_CMD_HDR_SIZE		(4 * sizeof(__u8))
+#define HDIO_DRIVE_HOB_HDR_SIZE		(8 * sizeof(__u8))
+#define HDIO_DRIVE_TASK_HDR_SIZE	(8 * sizeof(__u8))
 
 #define IDE_DRIVE_TASK_INVALID		-1
 #define IDE_DRIVE_TASK_NO_DATA		0
diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h
index f04d6d7..50d568e 100644
--- a/include/linux/hid-debug.h
+++ b/include/linux/hid-debug.h
@@ -1,10 +1,8 @@
+#ifndef __HID_DEBUG_H
+#define __HID_DEBUG_H
+
 /*
- * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
- *
- *  (c) 1999 Andreas Gal		<gal@cs.uni-magdeburg.de>
- *  (c) 2000-2001 Vojtech Pavlik	<vojtech@ucw.cz>
- *
- *  Some debug stuff for the HID parser.
+ *  Copyright (c) 2007	Jiri Kosina
  */
 
 /*
@@ -22,736 +20,26 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
-#include <linux/input.h>
+#ifdef CONFIG_HID_DEBUG
 
-struct hid_usage_entry {
-	unsigned  page;
-	unsigned  usage;
-	char     *description;
-};
+void hid_dump_input(struct hid_usage *, __s32);
+void hid_dump_device(struct hid_device *);
+void hid_dump_field(struct hid_field *, int);
+void hid_resolv_usage(unsigned);
+void hid_resolv_event(__u8, __u16);
 
-static const struct hid_usage_entry hid_usage_table[] = {
-  {  0,      0, "Undefined" },
-  {  1,      0, "GenericDesktop" },
-    {0, 0x01, "Pointer"},
-    {0, 0x02, "Mouse"},
-    {0, 0x04, "Joystick"},
-    {0, 0x05, "GamePad"},
-    {0, 0x06, "Keyboard"},
-    {0, 0x07, "Keypad"},
-    {0, 0x08, "MultiAxis"},
-      {0, 0x30, "X"},
-      {0, 0x31, "Y"},
-      {0, 0x32, "Z"},
-      {0, 0x33, "Rx"},
-      {0, 0x34, "Ry"},
-      {0, 0x35, "Rz"},
-      {0, 0x36, "Slider"},
-      {0, 0x37, "Dial"},
-      {0, 0x38, "Wheel"},
-      {0, 0x39, "HatSwitch"},
-    {0, 0x3a, "CountedBuffer"},
-      {0, 0x3b, "ByteCount"},
-      {0, 0x3c, "MotionWakeup"},
-      {0, 0x3d, "Start"},
-      {0, 0x3e, "Select"},
-      {0, 0x40, "Vx"},
-      {0, 0x41, "Vy"},
-      {0, 0x42, "Vz"},
-      {0, 0x43, "Vbrx"},
-      {0, 0x44, "Vbry"},
-      {0, 0x45, "Vbrz"},
-      {0, 0x46, "Vno"},
-    {0, 0x80, "SystemControl"},
-      {0, 0x81, "SystemPowerDown"},
-      {0, 0x82, "SystemSleep"},
-      {0, 0x83, "SystemWakeUp"},
-      {0, 0x84, "SystemContextMenu"},
-      {0, 0x85, "SystemMainMenu"},
-      {0, 0x86, "SystemAppMenu"},
-      {0, 0x87, "SystemMenuHelp"},
-      {0, 0x88, "SystemMenuExit"},
-      {0, 0x89, "SystemMenuSelect"},
-      {0, 0x8a, "SystemMenuRight"},
-      {0, 0x8b, "SystemMenuLeft"},
-      {0, 0x8c, "SystemMenuUp"},
-      {0, 0x8d, "SystemMenuDown"},
-      {0, 0x90, "D-PadUp"},
-      {0, 0x91, "D-PadDown"},
-      {0, 0x92, "D-PadRight"},
-      {0, 0x93, "D-PadLeft"},
-  {  2, 0, "Simulation" },
-      {0, 0xb0, "Aileron"},
-      {0, 0xb1, "AileronTrim"},
-      {0, 0xb2, "Anti-Torque"},
-      {0, 0xb3, "Autopilot"},
-      {0, 0xb4, "Chaff"},
-      {0, 0xb5, "Collective"},
-      {0, 0xb6, "DiveBrake"},
-      {0, 0xb7, "ElectronicCountermeasures"},
-      {0, 0xb8, "Elevator"},
-      {0, 0xb9, "ElevatorTrim"},
-      {0, 0xba, "Rudder"},
-      {0, 0xbb, "Throttle"},
-      {0, 0xbc, "FlightCommunications"},
-      {0, 0xbd, "FlareRelease"},
-      {0, 0xbe, "LandingGear"},
-      {0, 0xbf, "ToeBrake"},
-  {  7, 0, "Keyboard" },
-  {  8, 0, "LED" },
-      {0, 0x01, "NumLock"},
-      {0, 0x02, "CapsLock"},
-      {0, 0x03, "ScrollLock"},
-      {0, 0x04, "Compose"},
-      {0, 0x05, "Kana"},
-      {0, 0x4b, "GenericIndicator"},
-  {  9, 0, "Button" },
-  { 10, 0, "Ordinal" },
-  { 12, 0, "Consumer" },
-      {0, 0x238, "HorizontalWheel"},
-  { 13, 0, "Digitizers" },
-    {0, 0x01, "Digitizer"},
-    {0, 0x02, "Pen"},
-    {0, 0x03, "LightPen"},
-    {0, 0x04, "TouchScreen"},
-    {0, 0x05, "TouchPad"},
-    {0, 0x20, "Stylus"},
-    {0, 0x21, "Puck"},
-    {0, 0x22, "Finger"},
-    {0, 0x30, "TipPressure"},
-    {0, 0x31, "BarrelPressure"},
-    {0, 0x32, "InRange"},
-    {0, 0x33, "Touch"},
-    {0, 0x34, "UnTouch"},
-    {0, 0x35, "Tap"},
-    {0, 0x39, "TabletFunctionKey"},
-    {0, 0x3a, "ProgramChangeKey"},
-    {0, 0x3c, "Invert"},
-    {0, 0x42, "TipSwitch"},
-    {0, 0x43, "SecondaryTipSwitch"},
-    {0, 0x44, "BarrelSwitch"},
-    {0, 0x45, "Eraser"},
-    {0, 0x46, "TabletPick"},
-  { 15, 0, "PhysicalInterfaceDevice" },
-    {0, 0x00, "Undefined"},
-    {0, 0x01, "Physical_Interface_Device"},
-      {0, 0x20, "Normal"},
-    {0, 0x21, "Set_Effect_Report"},
-      {0, 0x22, "Effect_Block_Index"},
-      {0, 0x23, "Parameter_Block_Offset"},
-      {0, 0x24, "ROM_Flag"},
-      {0, 0x25, "Effect_Type"},
-        {0, 0x26, "ET_Constant_Force"},
-        {0, 0x27, "ET_Ramp"},
-        {0, 0x28, "ET_Custom_Force_Data"},
-        {0, 0x30, "ET_Square"},
-        {0, 0x31, "ET_Sine"},
-        {0, 0x32, "ET_Triangle"},
-        {0, 0x33, "ET_Sawtooth_Up"},
-        {0, 0x34, "ET_Sawtooth_Down"},
-        {0, 0x40, "ET_Spring"},
-        {0, 0x41, "ET_Damper"},
-        {0, 0x42, "ET_Inertia"},
-        {0, 0x43, "ET_Friction"},
-      {0, 0x50, "Duration"},
-      {0, 0x51, "Sample_Period"},
-      {0, 0x52, "Gain"},
-      {0, 0x53, "Trigger_Button"},
-      {0, 0x54, "Trigger_Repeat_Interval"},
-      {0, 0x55, "Axes_Enable"},
-        {0, 0x56, "Direction_Enable"},
-      {0, 0x57, "Direction"},
-      {0, 0x58, "Type_Specific_Block_Offset"},
-        {0, 0x59, "Block_Type"},
-        {0, 0x5A, "Set_Envelope_Report"},
-          {0, 0x5B, "Attack_Level"},
-          {0, 0x5C, "Attack_Time"},
-          {0, 0x5D, "Fade_Level"},
-          {0, 0x5E, "Fade_Time"},
-        {0, 0x5F, "Set_Condition_Report"},
-        {0, 0x60, "CP_Offset"},
-        {0, 0x61, "Positive_Coefficient"},
-        {0, 0x62, "Negative_Coefficient"},
-        {0, 0x63, "Positive_Saturation"},
-        {0, 0x64, "Negative_Saturation"},
-        {0, 0x65, "Dead_Band"},
-      {0, 0x66, "Download_Force_Sample"},
-      {0, 0x67, "Isoch_Custom_Force_Enable"},
-      {0, 0x68, "Custom_Force_Data_Report"},
-        {0, 0x69, "Custom_Force_Data"},
-        {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
-      {0, 0x6B, "Set_Custom_Force_Report"},
-        {0, 0x6C, "Custom_Force_Data_Offset"},
-        {0, 0x6D, "Sample_Count"},
-      {0, 0x6E, "Set_Periodic_Report"},
-        {0, 0x6F, "Offset"},
-        {0, 0x70, "Magnitude"},
-        {0, 0x71, "Phase"},
-        {0, 0x72, "Period"},
-      {0, 0x73, "Set_Constant_Force_Report"},
-        {0, 0x74, "Set_Ramp_Force_Report"},
-        {0, 0x75, "Ramp_Start"},
-        {0, 0x76, "Ramp_End"},
-      {0, 0x77, "Effect_Operation_Report"},
-        {0, 0x78, "Effect_Operation"},
-          {0, 0x79, "Op_Effect_Start"},
-          {0, 0x7A, "Op_Effect_Start_Solo"},
-          {0, 0x7B, "Op_Effect_Stop"},
-          {0, 0x7C, "Loop_Count"},
-      {0, 0x7D, "Device_Gain_Report"},
-        {0, 0x7E, "Device_Gain"},
-    {0, 0x7F, "PID_Pool_Report"},
-      {0, 0x80, "RAM_Pool_Size"},
-      {0, 0x81, "ROM_Pool_Size"},
-      {0, 0x82, "ROM_Effect_Block_Count"},
-      {0, 0x83, "Simultaneous_Effects_Max"},
-      {0, 0x84, "Pool_Alignment"},
-    {0, 0x85, "PID_Pool_Move_Report"},
-      {0, 0x86, "Move_Source"},
-      {0, 0x87, "Move_Destination"},
-      {0, 0x88, "Move_Length"},
-    {0, 0x89, "PID_Block_Load_Report"},
-      {0, 0x8B, "Block_Load_Status"},
-      {0, 0x8C, "Block_Load_Success"},
-      {0, 0x8D, "Block_Load_Full"},
-      {0, 0x8E, "Block_Load_Error"},
-      {0, 0x8F, "Block_Handle"},
-      {0, 0x90, "PID_Block_Free_Report"},
-      {0, 0x91, "Type_Specific_Block_Handle"},
-    {0, 0x92, "PID_State_Report"},
-      {0, 0x94, "Effect_Playing"},
-      {0, 0x95, "PID_Device_Control_Report"},
-        {0, 0x96, "PID_Device_Control"},
-        {0, 0x97, "DC_Enable_Actuators"},
-        {0, 0x98, "DC_Disable_Actuators"},
-        {0, 0x99, "DC_Stop_All_Effects"},
-        {0, 0x9A, "DC_Device_Reset"},
-        {0, 0x9B, "DC_Device_Pause"},
-        {0, 0x9C, "DC_Device_Continue"},
-      {0, 0x9F, "Device_Paused"},
-      {0, 0xA0, "Actuators_Enabled"},
-      {0, 0xA4, "Safety_Switch"},
-      {0, 0xA5, "Actuator_Override_Switch"},
-      {0, 0xA6, "Actuator_Power"},
-    {0, 0xA7, "Start_Delay"},
-    {0, 0xA8, "Parameter_Block_Size"},
-    {0, 0xA9, "Device_Managed_Pool"},
-    {0, 0xAA, "Shared_Parameter_Blocks"},
-    {0, 0xAB, "Create_New_Effect_Report"},
-    {0, 0xAC, "RAM_Pool_Available"},
-  { 0x84, 0, "Power Device" },
-    { 0x84, 0x02, "PresentStatus" },
-    { 0x84, 0x03, "ChangeStatus" },
-    { 0x84, 0x04, "UPS" },
-    { 0x84, 0x05, "PowerSupply" },
-    { 0x84, 0x10, "BatterySystem" },
-    { 0x84, 0x11, "BatterySystemID" },
-    { 0x84, 0x12, "Battery" },
-    { 0x84, 0x13, "BatteryID" },
-    { 0x84, 0x14, "Charger" },
-    { 0x84, 0x15, "ChargerID" },
-    { 0x84, 0x16, "PowerConverter" },
-    { 0x84, 0x17, "PowerConverterID" },
-    { 0x84, 0x18, "OutletSystem" },
-    { 0x84, 0x19, "OutletSystemID" },
-    { 0x84, 0x1a, "Input" },
-    { 0x84, 0x1b, "InputID" },
-    { 0x84, 0x1c, "Output" },
-    { 0x84, 0x1d, "OutputID" },
-    { 0x84, 0x1e, "Flow" },
-    { 0x84, 0x1f, "FlowID" },
-    { 0x84, 0x20, "Outlet" },
-    { 0x84, 0x21, "OutletID" },
-    { 0x84, 0x22, "Gang" },
-    { 0x84, 0x24, "PowerSummary" },
-    { 0x84, 0x25, "PowerSummaryID" },
-    { 0x84, 0x30, "Voltage" },
-    { 0x84, 0x31, "Current" },
-    { 0x84, 0x32, "Frequency" },
-    { 0x84, 0x33, "ApparentPower" },
-    { 0x84, 0x35, "PercentLoad" },
-    { 0x84, 0x40, "ConfigVoltage" },
-    { 0x84, 0x41, "ConfigCurrent" },
-    { 0x84, 0x43, "ConfigApparentPower" },
-    { 0x84, 0x53, "LowVoltageTransfer" },
-    { 0x84, 0x54, "HighVoltageTransfer" },
-    { 0x84, 0x56, "DelayBeforeStartup" },
-    { 0x84, 0x57, "DelayBeforeShutdown" },
-    { 0x84, 0x58, "Test" },
-    { 0x84, 0x5a, "AudibleAlarmControl" },
-    { 0x84, 0x60, "Present" },
-    { 0x84, 0x61, "Good" },
-    { 0x84, 0x62, "InternalFailure" },
-    { 0x84, 0x65, "Overload" },
-    { 0x84, 0x66, "OverCharged" },
-    { 0x84, 0x67, "OverTemperature" },
-    { 0x84, 0x68, "ShutdownRequested" },
-    { 0x84, 0x69, "ShutdownImminent" },
-    { 0x84, 0x6b, "SwitchOn/Off" },
-    { 0x84, 0x6c, "Switchable" },
-    { 0x84, 0x6d, "Used" },
-    { 0x84, 0x6e, "Boost" },
-    { 0x84, 0x73, "CommunicationLost" },
-    { 0x84, 0xfd, "iManufacturer" },
-    { 0x84, 0xfe, "iProduct" },
-    { 0x84, 0xff, "iSerialNumber" },
-  { 0x85, 0, "Battery System" },
-    { 0x85, 0x01, "SMBBatteryMode" },
-    { 0x85, 0x02, "SMBBatteryStatus" },
-    { 0x85, 0x03, "SMBAlarmWarning" },
-    { 0x85, 0x04, "SMBChargerMode" },
-    { 0x85, 0x05, "SMBChargerStatus" },
-    { 0x85, 0x06, "SMBChargerSpecInfo" },
-    { 0x85, 0x07, "SMBSelectorState" },
-    { 0x85, 0x08, "SMBSelectorPresets" },
-    { 0x85, 0x09, "SMBSelectorInfo" },
-    { 0x85, 0x29, "RemainingCapacityLimit" },
-    { 0x85, 0x2c, "CapacityMode" },
-    { 0x85, 0x42, "BelowRemainingCapacityLimit" },
-    { 0x85, 0x44, "Charging" },
-    { 0x85, 0x45, "Discharging" },
-    { 0x85, 0x4b, "NeedReplacement" },
-    { 0x85, 0x66, "RemainingCapacity" },
-    { 0x85, 0x68, "RunTimeToEmpty" },
-    { 0x85, 0x6a, "AverageTimeToFull" },
-    { 0x85, 0x83, "DesignCapacity" },
-    { 0x85, 0x85, "ManufacturerDate" },
-    { 0x85, 0x89, "iDeviceChemistry" },
-    { 0x85, 0x8b, "Rechargable" },
-    { 0x85, 0x8f, "iOEMInformation" },
-    { 0x85, 0x8d, "CapacityGranularity1" },
-    { 0x85, 0xd0, "ACPresent" },
-  /* pages 0xff00 to 0xffff are vendor-specific */
-  { 0xffff, 0, "Vendor-specific-FF" },
-  { 0, 0, NULL }
-};
+#else
 
-static void resolv_usage_page(unsigned page) {
-	const struct hid_usage_entry *p;
+#define hid_dump_input(a,b)     do { } while (0)
+#define hid_dump_device(c)      do { } while (0)
+#define hid_dump_field(a,b)     do { } while (0)
+#define hid_resolv_usage(a)         do { } while (0)
+#define hid_resolv_event(a,b)       do { } while (0)
 
-	for (p = hid_usage_table; p->description; p++)
-		if (p->page == page) {
-			printk("%s", p->description);
-			return;
-		}
-	printk("%04x", page);
-}
-
-static void resolv_usage(unsigned usage) {
-	const struct hid_usage_entry *p;
-
-	resolv_usage_page(usage >> 16);
-	printk(".");
-	for (p = hid_usage_table; p->description; p++)
-		if (p->page == (usage >> 16)) {
-			for(++p; p->description && p->usage != 0; p++)
-				if (p->usage == (usage & 0xffff)) {
-					printk("%s", p->description);
-					return;
-				}
-			break;
-		}
-	printk("%04x", usage & 0xffff);
-}
-
-__inline__ static void tab(int n) {
-	while (n--) printk(" ");
-}
-
-static void hid_dump_field(struct hid_field *field, int n) {
-	int j;
-
-	if (field->physical) {
-		tab(n);
-		printk("Physical(");
-		resolv_usage(field->physical); printk(")\n");
-	}
-	if (field->logical) {
-		tab(n);
-		printk("Logical(");
-		resolv_usage(field->logical); printk(")\n");
-	}
-	tab(n); printk("Usage(%d)\n", field->maxusage);
-	for (j = 0; j < field->maxusage; j++) {
-		tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
-	}
-	if (field->logical_minimum != field->logical_maximum) {
-		tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
-		tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
-	}
-	if (field->physical_minimum != field->physical_maximum) {
-		tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
-		tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
-	}
-	if (field->unit_exponent) {
-		tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
-	}
-	if (field->unit) {
-		char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
-		char *units[5][8] = {
-			{ "None", "None", "None", "None", "None", "None", "None", "None" },
-			{ "None", "Centimeter", "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
-			{ "None", "Radians",    "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
-			{ "None", "Inch",       "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
-			{ "None", "Degrees",    "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
-		};
-
-		int i;
-		int sys;
-                __u32 data = field->unit;
-
-		/* First nibble tells us which system we're in. */
-		sys = data & 0xf;
-		data >>= 4;
-
-		if(sys > 4) {
-			tab(n); printk("Unit(Invalid)\n");
-		}
-		else {
-			int earlier_unit = 0;
-
-			tab(n); printk("Unit(%s : ", systems[sys]);
-
-			for (i=1 ; i<sizeof(__u32)*2 ; i++) {
-				char nibble = data & 0xf;
-				data >>= 4;
-				if (nibble != 0) {
-					if(earlier_unit++ > 0)
-						printk("*");
-					printk("%s", units[sys][i]);
-					if(nibble != 1) {
-						/* This is a _signed_ nibble(!) */
-
-						int val = nibble & 0x7;
-						if(nibble & 0x08)
-							val = -((0x7 & ~val) +1);
-						printk("^%d", val);
-					}
-				}
-			}
-			printk(")\n");
-		}
-	}
-	tab(n); printk("Report Size(%u)\n", field->report_size);
-	tab(n); printk("Report Count(%u)\n", field->report_count);
-	tab(n); printk("Report Offset(%u)\n", field->report_offset);
-
-	tab(n); printk("Flags( ");
-	j = field->flags;
-	printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
-	printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
-	printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
-	printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
-	printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
-	printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
-	printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
-	printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
-	printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
-	printk(")\n");
-}
-
-static void __attribute__((unused)) hid_dump_device(struct hid_device *device) {
-	struct hid_report_enum *report_enum;
-	struct hid_report *report;
-	struct list_head *list;
-	unsigned i,k;
-	static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
-
-	for (i = 0; i < HID_REPORT_TYPES; i++) {
-		report_enum = device->report_enum + i;
-		list = report_enum->report_list.next;
-		while (list != &report_enum->report_list) {
-			report = (struct hid_report *) list;
-			tab(2);
-			printk("%s", table[i]);
-			if (report->id)
-				printk("(%d)", report->id);
-			printk("[%s]", table[report->type]);
-			printk("\n");
-			for (k = 0; k < report->maxfield; k++) {
-				tab(4);
-				printk("Field(%d)\n", k);
-				hid_dump_field(report->field[k], 6);
-			}
-			list = list->next;
-		}
-	}
-}
-
-static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s32 value) {
-	printk("hid-debug: input ");
-	resolv_usage(usage->hid);
-	printk(" = %d\n", value);
-}
+#endif /* CONFIG_HID_DEBUG */
 
 
-static char *events[EV_MAX + 1] = {
-	[EV_SYN] = "Sync",			[EV_KEY] = "Key",
-	[EV_REL] = "Relative",			[EV_ABS] = "Absolute",
-	[EV_MSC] = "Misc",			[EV_LED] = "LED",
-	[EV_SND] = "Sound",			[EV_REP] = "Repeat",
-	[EV_FF] = "ForceFeedback",		[EV_PWR] = "Power",
-	[EV_FF_STATUS] = "ForceFeedbackStatus",
-};
+#endif
 
-static char *syncs[2] = {
-	[SYN_REPORT] = "Report",		[SYN_CONFIG] = "Config",
-};
-static char *keys[KEY_MAX + 1] = {
-	[KEY_RESERVED] = "Reserved",		[KEY_ESC] = "Esc",
-	[KEY_1] = "1",				[KEY_2] = "2",
-	[KEY_3] = "3",				[KEY_4] = "4",
-	[KEY_5] = "5",				[KEY_6] = "6",
-	[KEY_7] = "7",				[KEY_8] = "8",
-	[KEY_9] = "9",				[KEY_0] = "0",
-	[KEY_MINUS] = "Minus",			[KEY_EQUAL] = "Equal",
-	[KEY_BACKSPACE] = "Backspace",		[KEY_TAB] = "Tab",
-	[KEY_Q] = "Q",				[KEY_W] = "W",
-	[KEY_E] = "E",				[KEY_R] = "R",
-	[KEY_T] = "T",				[KEY_Y] = "Y",
-	[KEY_U] = "U",				[KEY_I] = "I",
-	[KEY_O] = "O",				[KEY_P] = "P",
-	[KEY_LEFTBRACE] = "LeftBrace",		[KEY_RIGHTBRACE] = "RightBrace",
-	[KEY_ENTER] = "Enter",			[KEY_LEFTCTRL] = "LeftControl",
-	[KEY_A] = "A",				[KEY_S] = "S",
-	[KEY_D] = "D",				[KEY_F] = "F",
-	[KEY_G] = "G",				[KEY_H] = "H",
-	[KEY_J] = "J",				[KEY_K] = "K",
-	[KEY_L] = "L",				[KEY_SEMICOLON] = "Semicolon",
-	[KEY_APOSTROPHE] = "Apostrophe",	[KEY_GRAVE] = "Grave",
-	[KEY_LEFTSHIFT] = "LeftShift",		[KEY_BACKSLASH] = "BackSlash",
-	[KEY_Z] = "Z",				[KEY_X] = "X",
-	[KEY_C] = "C",				[KEY_V] = "V",
-	[KEY_B] = "B",				[KEY_N] = "N",
-	[KEY_M] = "M",				[KEY_COMMA] = "Comma",
-	[KEY_DOT] = "Dot",			[KEY_SLASH] = "Slash",
-	[KEY_RIGHTSHIFT] = "RightShift",	[KEY_KPASTERISK] = "KPAsterisk",
-	[KEY_LEFTALT] = "LeftAlt",		[KEY_SPACE] = "Space",
-	[KEY_CAPSLOCK] = "CapsLock",		[KEY_F1] = "F1",
-	[KEY_F2] = "F2",			[KEY_F3] = "F3",
-	[KEY_F4] = "F4",			[KEY_F5] = "F5",
-	[KEY_F6] = "F6",			[KEY_F7] = "F7",
-	[KEY_F8] = "F8",			[KEY_F9] = "F9",
-	[KEY_F10] = "F10",			[KEY_NUMLOCK] = "NumLock",
-	[KEY_SCROLLLOCK] = "ScrollLock",	[KEY_KP7] = "KP7",
-	[KEY_KP8] = "KP8",			[KEY_KP9] = "KP9",
-	[KEY_KPMINUS] = "KPMinus",		[KEY_KP4] = "KP4",
-	[KEY_KP5] = "KP5",			[KEY_KP6] = "KP6",
-	[KEY_KPPLUS] = "KPPlus",		[KEY_KP1] = "KP1",
-	[KEY_KP2] = "KP2",			[KEY_KP3] = "KP3",
-	[KEY_KP0] = "KP0",			[KEY_KPDOT] = "KPDot",
-	[KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
-	[KEY_F11] = "F11",			[KEY_F12] = "F12",
-	[KEY_RO] = "RO",			[KEY_KATAKANA] = "Katakana",
-	[KEY_HIRAGANA] = "HIRAGANA",		[KEY_HENKAN] = "Henkan",
-	[KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
-	[KEY_KPJPCOMMA] = "KPJpComma",		[KEY_KPENTER] = "KPEnter",
-	[KEY_RIGHTCTRL] = "RightCtrl",		[KEY_KPSLASH] = "KPSlash",
-	[KEY_SYSRQ] = "SysRq",			[KEY_RIGHTALT] = "RightAlt",
-	[KEY_LINEFEED] = "LineFeed",		[KEY_HOME] = "Home",
-	[KEY_UP] = "Up",			[KEY_PAGEUP] = "PageUp",
-	[KEY_LEFT] = "Left",			[KEY_RIGHT] = "Right",
-	[KEY_END] = "End",			[KEY_DOWN] = "Down",
-	[KEY_PAGEDOWN] = "PageDown",		[KEY_INSERT] = "Insert",
-	[KEY_DELETE] = "Delete",		[KEY_MACRO] = "Macro",
-	[KEY_MUTE] = "Mute",			[KEY_VOLUMEDOWN] = "VolumeDown",
-	[KEY_VOLUMEUP] = "VolumeUp",		[KEY_POWER] = "Power",
-	[KEY_KPEQUAL] = "KPEqual",		[KEY_KPPLUSMINUS] = "KPPlusMinus",
-	[KEY_PAUSE] = "Pause",			[KEY_KPCOMMA] = "KPComma",
-	[KEY_HANGUEL] = "Hangeul",		[KEY_HANJA] = "Hanja",
-	[KEY_YEN] = "Yen",			[KEY_LEFTMETA] = "LeftMeta",
-	[KEY_RIGHTMETA] = "RightMeta",		[KEY_COMPOSE] = "Compose",
-	[KEY_STOP] = "Stop",			[KEY_AGAIN] = "Again",
-	[KEY_PROPS] = "Props",			[KEY_UNDO] = "Undo",
-	[KEY_FRONT] = "Front",			[KEY_COPY] = "Copy",
-	[KEY_OPEN] = "Open",			[KEY_PASTE] = "Paste",
-	[KEY_FIND] = "Find",			[KEY_CUT] = "Cut",
-	[KEY_HELP] = "Help",			[KEY_MENU] = "Menu",
-	[KEY_CALC] = "Calc",			[KEY_SETUP] = "Setup",
-	[KEY_SLEEP] = "Sleep",			[KEY_WAKEUP] = "WakeUp",
-	[KEY_FILE] = "File",			[KEY_SENDFILE] = "SendFile",
-	[KEY_DELETEFILE] = "DeleteFile",	[KEY_XFER] = "X-fer",
-	[KEY_PROG1] = "Prog1",			[KEY_PROG2] = "Prog2",
-	[KEY_WWW] = "WWW",			[KEY_MSDOS] = "MSDOS",
-	[KEY_COFFEE] = "Coffee",		[KEY_DIRECTION] = "Direction",
-	[KEY_CYCLEWINDOWS] = "CycleWindows",	[KEY_MAIL] = "Mail",
-	[KEY_BOOKMARKS] = "Bookmarks",		[KEY_COMPUTER] = "Computer",
-	[KEY_BACK] = "Back",			[KEY_FORWARD] = "Forward",
-	[KEY_CLOSECD] = "CloseCD",		[KEY_EJECTCD] = "EjectCD",
-	[KEY_EJECTCLOSECD] = "EjectCloseCD",	[KEY_NEXTSONG] = "NextSong",
-	[KEY_PLAYPAUSE] = "PlayPause",		[KEY_PREVIOUSSONG] = "PreviousSong",
-	[KEY_STOPCD] = "StopCD",		[KEY_RECORD] = "Record",
-	[KEY_REWIND] = "Rewind",		[KEY_PHONE] = "Phone",
-	[KEY_ISO] = "ISOKey",			[KEY_CONFIG] = "Config",
-	[KEY_HOMEPAGE] = "HomePage",		[KEY_REFRESH] = "Refresh",
-	[KEY_EXIT] = "Exit",			[KEY_MOVE] = "Move",
-	[KEY_EDIT] = "Edit",			[KEY_SCROLLUP] = "ScrollUp",
-	[KEY_SCROLLDOWN] = "ScrollDown",	[KEY_KPLEFTPAREN] = "KPLeftParenthesis",
-	[KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
-	[KEY_REDO] = "Redo",			[KEY_F13] = "F13",
-	[KEY_F14] = "F14",			[KEY_F15] = "F15",
-	[KEY_F16] = "F16",			[KEY_F17] = "F17",
-	[KEY_F18] = "F18",			[KEY_F19] = "F19",
-	[KEY_F20] = "F20",			[KEY_F21] = "F21",
-	[KEY_F22] = "F22",			[KEY_F23] = "F23",
-	[KEY_F24] = "F24",			[KEY_PLAYCD] = "PlayCD",
-	[KEY_PAUSECD] = "PauseCD",		[KEY_PROG3] = "Prog3",
-	[KEY_PROG4] = "Prog4",			[KEY_SUSPEND] = "Suspend",
-	[KEY_CLOSE] = "Close",			[KEY_PLAY] = "Play",
-	[KEY_FASTFORWARD] = "FastForward",	[KEY_BASSBOOST] = "BassBoost",
-	[KEY_PRINT] = "Print",			[KEY_HP] = "HP",
-	[KEY_CAMERA] = "Camera",		[KEY_SOUND] = "Sound",
-	[KEY_QUESTION] = "Question",		[KEY_EMAIL] = "Email",
-	[KEY_CHAT] = "Chat",			[KEY_SEARCH] = "Search",
-	[KEY_CONNECT] = "Connect",		[KEY_FINANCE] = "Finance",
-	[KEY_SPORT] = "Sport",			[KEY_SHOP] = "Shop",
-	[KEY_ALTERASE] = "AlternateErase",	[KEY_CANCEL] = "Cancel",
-	[KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
-	[KEY_MEDIA] = "Media",			[KEY_UNKNOWN] = "Unknown",
-	[BTN_0] = "Btn0",			[BTN_1] = "Btn1",
-	[BTN_2] = "Btn2",			[BTN_3] = "Btn3",
-	[BTN_4] = "Btn4",			[BTN_5] = "Btn5",
-	[BTN_6] = "Btn6",			[BTN_7] = "Btn7",
-	[BTN_8] = "Btn8",			[BTN_9] = "Btn9",
-	[BTN_LEFT] = "LeftBtn",			[BTN_RIGHT] = "RightBtn",
-	[BTN_MIDDLE] = "MiddleBtn",		[BTN_SIDE] = "SideBtn",
-	[BTN_EXTRA] = "ExtraBtn",		[BTN_FORWARD] = "ForwardBtn",
-	[BTN_BACK] = "BackBtn",			[BTN_TASK] = "TaskBtn",
-	[BTN_TRIGGER] = "Trigger",		[BTN_THUMB] = "ThumbBtn",
-	[BTN_THUMB2] = "ThumbBtn2",		[BTN_TOP] = "TopBtn",
-	[BTN_TOP2] = "TopBtn2",			[BTN_PINKIE] = "PinkieBtn",
-	[BTN_BASE] = "BaseBtn",			[BTN_BASE2] = "BaseBtn2",
-	[BTN_BASE3] = "BaseBtn3",		[BTN_BASE4] = "BaseBtn4",
-	[BTN_BASE5] = "BaseBtn5",		[BTN_BASE6] = "BaseBtn6",
-	[BTN_DEAD] = "BtnDead",			[BTN_A] = "BtnA",
-	[BTN_B] = "BtnB",			[BTN_C] = "BtnC",
-	[BTN_X] = "BtnX",			[BTN_Y] = "BtnY",
-	[BTN_Z] = "BtnZ",			[BTN_TL] = "BtnTL",
-	[BTN_TR] = "BtnTR",			[BTN_TL2] = "BtnTL2",
-	[BTN_TR2] = "BtnTR2",			[BTN_SELECT] = "BtnSelect",
-	[BTN_START] = "BtnStart",		[BTN_MODE] = "BtnMode",
-	[BTN_THUMBL] = "BtnThumbL",		[BTN_THUMBR] = "BtnThumbR",
-	[BTN_TOOL_PEN] = "ToolPen",		[BTN_TOOL_RUBBER] = "ToolRubber",
-	[BTN_TOOL_BRUSH] = "ToolBrush",		[BTN_TOOL_PENCIL] = "ToolPencil",
-	[BTN_TOOL_AIRBRUSH] = "ToolAirbrush",	[BTN_TOOL_FINGER] = "ToolFinger",
-	[BTN_TOOL_MOUSE] = "ToolMouse",		[BTN_TOOL_LENS] = "ToolLens",
-	[BTN_TOUCH] = "Touch",			[BTN_STYLUS] = "Stylus",
-	[BTN_STYLUS2] = "Stylus2",		[BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
-	[BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
-	[BTN_GEAR_UP] = "Gear up",		[KEY_OK] = "Ok",
-	[KEY_SELECT] = "Select",		[KEY_GOTO] = "Goto",
-	[KEY_CLEAR] = "Clear",			[KEY_POWER2] = "Power2",
-	[KEY_OPTION] = "Option",		[KEY_INFO] = "Info",
-	[KEY_TIME] = "Time",			[KEY_VENDOR] = "Vendor",
-	[KEY_ARCHIVE] = "Archive",		[KEY_PROGRAM] = "Program",
-	[KEY_CHANNEL] = "Channel",		[KEY_FAVORITES] = "Favorites",
-	[KEY_EPG] = "EPG",			[KEY_PVR] = "PVR",
-	[KEY_MHP] = "MHP",			[KEY_LANGUAGE] = "Language",
-	[KEY_TITLE] = "Title",			[KEY_SUBTITLE] = "Subtitle",
-	[KEY_ANGLE] = "Angle",			[KEY_ZOOM] = "Zoom",
-	[KEY_MODE] = "Mode",			[KEY_KEYBOARD] = "Keyboard",
-	[KEY_SCREEN] = "Screen",		[KEY_PC] = "PC",
-	[KEY_TV] = "TV",			[KEY_TV2] = "TV2",
-	[KEY_VCR] = "VCR",			[KEY_VCR2] = "VCR2",
-	[KEY_SAT] = "Sat",			[KEY_SAT2] = "Sat2",
-	[KEY_CD] = "CD",			[KEY_TAPE] = "Tape",
-	[KEY_RADIO] = "Radio",			[KEY_TUNER] = "Tuner",
-	[KEY_PLAYER] = "Player",		[KEY_TEXT] = "Text",
-	[KEY_DVD] = "DVD",			[KEY_AUX] = "Aux",
-	[KEY_MP3] = "MP3",			[KEY_AUDIO] = "Audio",
-	[KEY_VIDEO] = "Video",			[KEY_DIRECTORY] = "Directory",
-	[KEY_LIST] = "List",			[KEY_MEMO] = "Memo",
-	[KEY_CALENDAR] = "Calendar",		[KEY_RED] = "Red",
-	[KEY_GREEN] = "Green",			[KEY_YELLOW] = "Yellow",
-	[KEY_BLUE] = "Blue",			[KEY_CHANNELUP] = "ChannelUp",
-	[KEY_CHANNELDOWN] = "ChannelDown",	[KEY_FIRST] = "First",
-	[KEY_LAST] = "Last",			[KEY_AB] = "AB",
-	[KEY_NEXT] = "Next",			[KEY_RESTART] = "Restart",
-	[KEY_SLOW] = "Slow",			[KEY_SHUFFLE] = "Shuffle",
-	[KEY_BREAK] = "Break",			[KEY_PREVIOUS] = "Previous",
-	[KEY_DIGITS] = "Digits",		[KEY_TEEN] = "TEEN",
-	[KEY_TWEN] = "TWEN",			[KEY_DEL_EOL] = "DeleteEOL",
-	[KEY_DEL_EOS] = "DeleteEOS",		[KEY_INS_LINE] = "InsertLine",
-	[KEY_DEL_LINE] = "DeleteLine",
-	[KEY_SEND] = "Send",			[KEY_REPLY] = "Reply",
-	[KEY_FORWARDMAIL] = "ForwardMail",	[KEY_SAVE] = "Save",
-	[KEY_DOCUMENTS] = "Documents",
-	[KEY_FN] = "Fn",			[KEY_FN_ESC] = "Fn+ESC",
-	[KEY_FN_1] = "Fn+1",			[KEY_FN_2] = "Fn+2",
-	[KEY_FN_B] = "Fn+B",			[KEY_FN_D] = "Fn+D",
-	[KEY_FN_E] = "Fn+E",			[KEY_FN_F] = "Fn+F",
-	[KEY_FN_S] = "Fn+S",
-	[KEY_FN_F1] = "Fn+F1",			[KEY_FN_F2] = "Fn+F2",
-	[KEY_FN_F3] = "Fn+F3",			[KEY_FN_F4] = "Fn+F4",
-	[KEY_FN_F5] = "Fn+F5",			[KEY_FN_F6] = "Fn+F6",
-	[KEY_FN_F7] = "Fn+F7",			[KEY_FN_F8] = "Fn+F8",
-	[KEY_FN_F9] = "Fn+F9",			[KEY_FN_F10] = "Fn+F10",
-	[KEY_FN_F11] = "Fn+F11",		[KEY_FN_F12] = "Fn+F12",
-	[KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
-	[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
-	[KEY_KBDILLUMUP] = "KbdIlluminationUp",
-	[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
-};
-
-static char *relatives[REL_MAX + 1] = {
-	[REL_X] = "X",			[REL_Y] = "Y",
-	[REL_Z] = "Z",			[REL_HWHEEL] = "HWheel",
-	[REL_DIAL] = "Dial",		[REL_WHEEL] = "Wheel",
-	[REL_MISC] = "Misc",
-};
-
-static char *absolutes[ABS_MAX + 1] = {
-	[ABS_X] = "X",			[ABS_Y] = "Y",
-	[ABS_Z] = "Z",			[ABS_RX] = "Rx",
-	[ABS_RY] = "Ry",		[ABS_RZ] = "Rz",
-	[ABS_THROTTLE] = "Throttle",	[ABS_RUDDER] = "Rudder",
-	[ABS_WHEEL] = "Wheel",		[ABS_GAS] = "Gas",
-	[ABS_BRAKE] = "Brake",		[ABS_HAT0X] = "Hat0X",
-	[ABS_HAT0Y] = "Hat0Y",		[ABS_HAT1X] = "Hat1X",
-	[ABS_HAT1Y] = "Hat1Y",		[ABS_HAT2X] = "Hat2X",
-	[ABS_HAT2Y] = "Hat2Y",		[ABS_HAT3X] = "Hat3X",
-	[ABS_HAT3Y] = "Hat 3Y",		[ABS_PRESSURE] = "Pressure",
-	[ABS_DISTANCE] = "Distance",	[ABS_TILT_X] = "XTilt",
-	[ABS_TILT_Y] = "YTilt",		[ABS_TOOL_WIDTH] = "Tool Width",
-	[ABS_VOLUME] = "Volume",	[ABS_MISC] = "Misc",
-};
-
-static char *misc[MSC_MAX + 1] = {
-	[MSC_SERIAL] = "Serial",	[MSC_PULSELED] = "Pulseled",
-	[MSC_GESTURE] = "Gesture",	[MSC_RAW] = "RawData"
-};
-
-static char *leds[LED_MAX + 1] = {
-	[LED_NUML] = "NumLock",		[LED_CAPSL] = "CapsLock",
-	[LED_SCROLLL] = "ScrollLock",	[LED_COMPOSE] = "Compose",
-	[LED_KANA] = "Kana",		[LED_SLEEP] = "Sleep",
-	[LED_SUSPEND] = "Suspend",	[LED_MUTE] = "Mute",
-	[LED_MISC] = "Misc",
-};
-
-static char *repeats[REP_MAX + 1] = {
-	[REP_DELAY] = "Delay",		[REP_PERIOD] = "Period"
-};
-
-static char *sounds[SND_MAX + 1] = {
-	[SND_CLICK] = "Click",		[SND_BELL] = "Bell",
-	[SND_TONE] = "Tone"
-};
-
-static char **names[EV_MAX + 1] = {
-	[EV_SYN] = syncs,			[EV_KEY] = keys,
-	[EV_REL] = relatives,			[EV_ABS] = absolutes,
-	[EV_MSC] = misc,			[EV_LED] = leds,
-	[EV_SND] = sounds,			[EV_REP] = repeats,
-};
-
-static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) {
-
-	printk("%s.%s", events[type] ? events[type] : "?",
-		names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
-}
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 770120a..93173fe 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -264,6 +264,8 @@
 #define HID_QUIRK_INVERT_HWHEEL			0x00004000
 #define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00008000
 #define HID_QUIRK_BAD_RELATIVE_KEYS		0x00010000
+#define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00020000
+#define HID_QUIRK_IGNORE_MOUSE			0x00040000
 
 /*
  * This is the global environment of the parser. This information is
@@ -430,15 +432,14 @@
 
 	/* device-specific function pointers */
 	int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
-	int (*hidinput_open) (struct input_dev *);
-	void (*hidinput_close) (struct input_dev *);
+	int (*hid_open) (struct hid_device *);
+	void (*hid_close) (struct hid_device *);
 
 	/* hiddev event handler */
 	void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
 				  struct hid_usage *, __s32);
 	void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-	unsigned int  pb_fnmode;
 	unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
 	unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
 #endif
@@ -472,16 +473,6 @@
 	struct hid_class_descriptor desc[1];
 } __attribute__ ((packed));
 
-#ifdef DEBUG
-#include "hid-debug.h"
-#else
-#define hid_dump_input(a,b)	do { } while (0)
-#define hid_dump_device(c)	do { } while (0)
-#define hid_dump_field(a,b)	do { } while (0)
-#define resolv_usage(a)		do { } while (0)
-#define resolv_event(a,b)	do { } while (0)
-#endif
-
 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
 /* We ignore a few input applications that are not widely used */
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
@@ -504,6 +495,7 @@
 int hid_ff_init(struct hid_device *hid);
 
 int hid_lgff_init(struct hid_device *hid);
+int hid_plff_init(struct hid_device *hid);
 int hid_tmff_init(struct hid_device *hid);
 int hid_zpff_init(struct hid_device *hid);
 #ifdef CONFIG_HID_PID
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index c2519df..a0b23dd 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -24,12 +24,13 @@
 #define MAX_I2O_CONTROLLERS	32
 
 #include <linux/ioctl.h>
+#include <linux/types.h>
 
 /*
  * I2O Control IOCTLs and structures
  */
 #define I2O_MAGIC_NUMBER	'i'
-#define I2OGETIOPS		_IOR(I2O_MAGIC_NUMBER,0,u8[MAX_I2O_CONTROLLERS])
+#define I2OGETIOPS		_IOR(I2O_MAGIC_NUMBER,0,__u8[MAX_I2O_CONTROLLERS])
 #define I2OHRTGET		_IOWR(I2O_MAGIC_NUMBER,1,struct i2o_cmd_hrtlct)
 #define I2OLCTGET		_IOWR(I2O_MAGIC_NUMBER,2,struct i2o_cmd_hrtlct)
 #define I2OPARMSET		_IOWR(I2O_MAGIC_NUMBER,3,struct i2o_cmd_psetget)
@@ -37,7 +38,7 @@
 #define I2OSWDL 		_IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
 #define I2OSWUL 		_IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
 #define I2OSWDEL		_IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
-#define I2OVALIDATE		_IOR(I2O_MAGIC_NUMBER,8,u32)
+#define I2OVALIDATE		_IOR(I2O_MAGIC_NUMBER,8,__u32)
 #define I2OHTML 		_IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
 #define I2OEVTREG		_IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
 #define I2OEVTGET		_IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 8de079b..660b501 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -1,6 +1,8 @@
 #ifndef _IF_TUNNEL_H_
 #define _IF_TUNNEL_H_
 
+#include <linux/types.h>
+
 #define SIOCGETTUNNEL   (SIOCDEVPRIVATE + 0)
 #define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)
 #define SIOCDELTUNNEL   (SIOCDEVPRIVATE + 2)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index b0c4a05..63fb18d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -17,6 +17,9 @@
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
+extern const char linux_banner[];
+extern const char linux_proc_banner[];
+
 #define INT_MAX		((int)(~0U>>1))
 #define INT_MIN		(-INT_MAX - 1)
 #define UINT_MAX	(~0U)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index bc8b461..1be148f 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -46,6 +46,7 @@
 	KVM_EXIT_HLT              = 5,
 	KVM_EXIT_MMIO             = 6,
 	KVM_EXIT_IRQ_WINDOW_OPEN  = 7,
+	KVM_EXIT_SHUTDOWN         = 8,
 };
 
 /* for KVM_RUN */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index ab27548..91bb8ce 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -177,6 +177,7 @@
 					      * Register FIS clearing BSY */
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
 	ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15), /* ignore SIMPLEX */
 
 	/* The following flag belongs to ap->pflags but is kept in
 	 * ap->flags because it's referenced in many LLDs and will be
@@ -612,11 +613,11 @@
 	void (*dev_select)(struct ata_port *ap, unsigned int device);
 
 	void (*phy_reset) (struct ata_port *ap); /* obsolete */
-	void (*set_mode) (struct ata_port *ap);
+	int  (*set_mode) (struct ata_port *ap, struct ata_device **r_failed_dev);
 
 	void (*post_set_mode) (struct ata_port *ap);
 
-	int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+	int  (*check_atapi_dma) (struct ata_queued_cmd *qc);
 
 	void (*bmdma_setup) (struct ata_queued_cmd *qc);
 	void (*bmdma_start) (struct ata_queued_cmd *qc);
@@ -1053,6 +1054,8 @@
 /**
  *	ata_busy_wait - Wait for a port status register
  *	@ap: Port to wait for.
+ *	@bits: bits that must be clear
+ *	@max: number of 10uS waits to perform
  *
  *	Waits up to max*10 microseconds for the selected bits in the port's
  *	status register to be cleared.
@@ -1143,12 +1146,15 @@
 
 static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
 {
+	qc->dma_dir = DMA_NONE;
 	qc->__sg = NULL;
 	qc->flags = 0;
 	qc->cursect = qc->cursg = qc->cursg_ofs = 0;
 	qc->nsect = 0;
 	qc->nbytes = qc->curbytes = 0;
+	qc->n_elem = 0;
 	qc->err_mask = 0;
+	qc->pad_len = 0;
 
 	ata_tf_init(qc->dev, &qc->tf);
 
diff --git a/include/linux/list.h b/include/linux/list.h
index a9c9028..611059d 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -227,13 +227,13 @@
 	INIT_LIST_HEAD(old);
 }
 
-/*
+/**
  * list_replace_rcu - replace old entry by new one
  * @old : the element to be replaced
  * @new : the new element to insert
  *
- * The old entry will be replaced with the new entry atomically.
- * Note: 'old' should not be empty.
+ * The @old entry will be replaced with the @new entry atomically.
+ * Note: @old should not be empty.
  */
 static inline void list_replace_rcu(struct list_head *old,
 				struct list_head *new)
@@ -680,12 +680,12 @@
 	}
 }
 
-/*
+/**
  * hlist_replace_rcu - replace old entry by new one
  * @old : the element to be replaced
  * @new : the new element to insert
  *
- * The old entry will be replaced with the new entry atomically.
+ * The @old entry will be replaced with the @new entry atomically.
  */
 static inline void hlist_replace_rcu(struct hlist_node *old,
 					struct hlist_node *new)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a17b147..2d2c08d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -168,6 +168,7 @@
 #define VM_NONLINEAR	0x00800000	/* Is non-linear (remap_file_pages) */
 #define VM_MAPPED_COPY	0x01000000	/* T if mapped copy of data (nommu mmap) */
 #define VM_INSERTPAGE	0x02000000	/* The vma has had "vm_insert_page()" done on it */
+#define VM_ALWAYSDUMP	0x04000000	/* Always include in core dumps */
 
 #ifndef VM_STACK_DEFAULT_FLAGS		/* arch can override this */
 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
@@ -978,7 +979,8 @@
 #endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 extern void set_dma_reserve(unsigned long new_dma_reserve);
-extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
+extern void memmap_init_zone(unsigned long, int, unsigned long,
+				unsigned long, enum memmap_context);
 extern void setup_per_zone_pages_min(void);
 extern void mem_init(void);
 extern void show_mem(void);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d0e6a54..e45712a 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -71,6 +71,7 @@
 #define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
 #define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
 #define MMC_STATE_HIGHSPEED	(1<<5)		/* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR	(1<<6)		/* card uses block-addressing */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
@@ -87,6 +88,7 @@
 #define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
 #define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
+#define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
@@ -94,6 +96,7 @@
 #define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
+#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
 
 #define mmc_card_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		((c)->dev.bus_id)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index c15ae19..913e575 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -92,8 +92,10 @@
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
 	unsigned short		max_hw_segs;	/* see blk_queue_max_hw_segments */
 	unsigned short		max_phys_segs;	/* see blk_queue_max_phys_segments */
-	unsigned short		max_sectors;	/* see blk_queue_max_sectors */
 	unsigned short		unused;
+	unsigned int		max_req_size;	/* maximum number of bytes in one req */
+	unsigned int		max_blk_size;	/* maximum size of one mmc block */
+	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
 
 	/* private data */
 	struct mmc_ios		ios;		/* current io bus settings */
@@ -106,8 +108,9 @@
 	struct list_head	cards;		/* devices attached to this host */
 
 	wait_queue_head_t	wq;
-	spinlock_t		lock;		/* card_busy lock */
-	struct mmc_card		*card_busy;	/* the MMC card claiming host */
+	spinlock_t		lock;		/* claimed lock */
+	unsigned int		claimed:1;	/* host exclusively claimed */
+
 	struct mmc_card		*card_selected;	/* the selected MMC card */
 
 	struct delayed_work	detect;
@@ -126,6 +129,7 @@
 }
 
 #define mmc_dev(x)	((x)->parent)
+#define mmc_classdev(x)	(&(x)->class_dev)
 #define mmc_hostname(x)	((x)->class_dev.bus_id)
 
 extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index a3594df..cdc54be 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -42,7 +42,8 @@
 #define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
 #define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
 #define MMC_RSP_R3	(MMC_RSP_PRESENT)
-#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC)
+#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
 
 #define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 2dce60c..c90b676 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -79,9 +79,12 @@
 #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
 
 /* SD commands                           type  argument     response */
-  /* class 8 */
+  /* class 0 */
 /* This is basically the same command as for MMC with some quirks. */
 #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
 #define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
 
   /* Application commands */
@@ -115,6 +118,14 @@
  */
 
 /*
+ * SD_SEND_IF_COND argument format:
+ *
+ *	[31:12] Reserved (0)
+ *	[11:8] Host Voltage Supply Flags
+ *	[7:0] Check Pattern (0xAA)
+ */
+
+/*
   MMC status in R1
   Type
   	e : error bit
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e339a73..b262f47 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -450,9 +450,13 @@
 void wakeup_kswapd(struct zone *zone, int order);
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
 		int classzone_idx, int alloc_flags);
-
+enum memmap_context {
+	MEMMAP_EARLY,
+	MEMMAP_HOTPLUG,
+};
 extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
-				     unsigned long size);
+				     unsigned long size,
+				     enum memmap_context context);
 
 #ifdef CONFIG_HAVE_MEMORY_PRESENT
 void memory_present(int nid, unsigned long start, unsigned long end);
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index 72fc68c..9a6e2f9 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -24,7 +24,6 @@
 	struct mtd_info *mtd;
 	struct mutex lock;
 	int devnum;
-	int blksize;
 	unsigned long size;
 	int readonly;
 	void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
@@ -36,6 +35,8 @@
 	char *name;
 	int major;
 	int part_bits;
+	int blksize;
+	int blkshift;
 
 	/* Access functions */
 	int (*readsect)(struct mtd_blktrans_dev *dev,
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 94a443d..d644e57 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -23,7 +23,7 @@
 
 #define MTD_CHAR_MAJOR 90
 #define MTD_BLOCK_MAJOR 31
-#define MAX_MTD_DEVICES 16
+#define MAX_MTD_DEVICES 32
 
 #define MTD_ERASE_PENDING      	0x01
 #define MTD_ERASING		0x02
@@ -75,15 +75,12 @@
  * struct mtd_oob_ops - oob operation operands
  * @mode:	operation mode
  *
- * @len:	number of bytes to write/read. When a data buffer is given
- *		(datbuf != NULL) this is the number of data bytes. When
- *		no data buffer is available this is the number of oob bytes.
+ * @len:	number of data bytes to write/read
  *
- * @retlen:	number of bytes written/read. When a data buffer is given
- *		(datbuf != NULL) this is the number of data bytes. When
- *		no data buffer is available this is the number of oob bytes.
+ * @retlen:	number of data bytes written/read
  *
- * @ooblen:	number of oob bytes per page
+ * @ooblen:	number of oob bytes to write/read
+ * @oobretlen:	number of oob bytes written/read
  * @ooboffs:	offset of oob data in the oob area (only relevant when
  *		mode = MTD_OOB_PLACE)
  * @datbuf:	data buffer - if NULL only oob data are read/written
@@ -94,6 +91,7 @@
 	size_t		len;
 	size_t		retlen;
 	size_t		ooblen;
+	size_t		oobretlen;
 	uint32_t	ooboffs;
 	uint8_t		*datbuf;
 	uint8_t		*oobbuf;
@@ -202,11 +200,20 @@
 
 	/* ECC status information */
 	struct mtd_ecc_stats ecc_stats;
+	/* Subpage shift (NAND) */
+	int subpage_sft;
 
 	void *priv;
 
 	struct module *owner;
 	int usecount;
+
+	/* If the driver is something smart, like UBI, it may need to maintain
+	 * its own reference counting. The below functions are only for driver.
+	 * The driver may register its callbacks. These callbacks are not
+	 * supposed to be called by MTD users */
+	int (*get_device) (struct mtd_info *mtd);
+	void (*put_device) (struct mtd_info *mtd);
 };
 
 
@@ -216,6 +223,7 @@
 extern int del_mtd_device (struct mtd_info *mtd);
 
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
+extern struct mtd_info *get_mtd_device_nm(const char *name);
 
 extern void put_mtd_device(struct mtd_info *mtd);
 
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8b3ef41..2071b02 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -166,6 +166,9 @@
  * for all large page devices, as they do not support
  * autoincrement.*/
 #define NAND_NO_READRDY		0x00000100
+/* Chip does not allow subpage writes */
+#define NAND_NO_SUBPAGE_WRITE	0x00000200
+
 
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS \
@@ -193,6 +196,9 @@
 /* Nand scan has allocated controller struct */
 #define NAND_CONTROLLER_ALLOC	0x80000000
 
+/* Cell info constants */
+#define NAND_CI_CHIPNR_MSK	0x03
+#define NAND_CI_CELLTYPE_MSK	0x0C
 
 /*
  * nand_state_t - chip states
@@ -286,9 +292,7 @@
  * struct nand_buffers - buffer structure for read/write
  * @ecccalc:	buffer for calculated ecc
  * @ecccode:	buffer for ecc read from flash
- * @oobwbuf:	buffer for write oob data
  * @databuf:	buffer for data - dynamically sized
- * @oobrbuf:	buffer to read oob data
  *
  * Do not change the order of buffers. databuf and oobrbuf must be in
  * consecutive order.
@@ -296,9 +300,7 @@
 struct nand_buffers {
 	uint8_t	ecccalc[NAND_MAX_OOBSIZE];
 	uint8_t	ecccode[NAND_MAX_OOBSIZE];
-	uint8_t	oobwbuf[NAND_MAX_OOBSIZE];
-	uint8_t databuf[NAND_MAX_PAGESIZE];
-	uint8_t	oobrbuf[NAND_MAX_OOBSIZE];
+	uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
 };
 
 /**
@@ -345,6 +347,7 @@
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
  * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
+ * @subpagesize:	[INTERN] holds the subpagesize
  * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
@@ -392,6 +395,8 @@
 	unsigned long	chipsize;
 	int		pagemask;
 	int		pagebuf;
+	int		subpagesize;
+	uint8_t		cellinfo;
 	int		badblockpos;
 
 	nand_state_t	state;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 6f045b5..f775a7a 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -13,6 +13,7 @@
 #define __LINUX_MTD_ONENAND_H
 
 #include <linux/spinlock.h>
+#include <linux/completion.h>
 #include <linux/mtd/onenand_regs.h>
 #include <linux/mtd/bbm.h>
 
@@ -33,7 +34,6 @@
 	FL_WRITING,
 	FL_ERASING,
 	FL_SYNCING,
-	FL_UNLOCKING,
 	FL_LOCKING,
 	FL_RESETING,
 	FL_OTPING,
@@ -88,6 +88,7 @@
  *			operation is in progress
  * @state:		[INTERN] the current state of the OneNAND device
  * @page_buf:		data buffer
+ * @subpagesize:	[INTERN] holds the subpagesize
  * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
  * @bbm:		[REPLACEABLE] pointer to Bad Block Management
  * @priv:		[OPTIONAL] pointer to private chip date
@@ -120,11 +121,15 @@
 	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	int (*scan_bbt)(struct mtd_info *mtd);
 
+	struct completion	complete;
+	int			irq;
+
 	spinlock_t		chip_lock;
 	wait_queue_head_t	wq;
 	onenand_state_t		state;
 	unsigned char		*page_buf;
 
+	int			subpagesize;
 	struct nand_ecclayout	*ecclayout;
 
 	void			*bbm;
@@ -138,6 +143,7 @@
 #define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
 #define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
 #define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
+#define ONENAND_SET_PREV_BUFFERRAM(this)	(this->bufferram_index ^= 1)
 
 #define ONENAND_GET_SYS_CFG1(this)					\
 	(this->read_word(this->base + ONENAND_REG_SYS_CFG1))
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index 9e409fe..e31c8f5 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -179,6 +179,7 @@
  * ECC Status Reigser FF00h (R)
  */
 #define ONENAND_ECC_1BIT		(1 << 0)
+#define ONENAND_ECC_1BIT_ALL		(0x5555)
 #define ONENAND_ECC_2BIT		(1 << 1)
 #define ONENAND_ECC_2BIT_ALL		(0xAAAA)
 
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index 8c66151..6f8d2d4 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -10,7 +10,6 @@
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
-#include <linux/qic117.h>
 
 /*
  * Structures and definitions for mag tape io control commands
@@ -116,32 +115,6 @@
 #define MT_ISFTAPE_UNKNOWN	0x800000 /* obsolete */
 #define MT_ISFTAPE_FLAG	0x800000
 
-struct mt_tape_info {
-	long t_type;		/* device type id (mt_type) */
-	char *t_name;		/* descriptive name */
-};
-
-#define MT_TAPE_INFO	{ \
-	{MT_ISUNKNOWN,		"Unknown type of tape device"}, \
-	{MT_ISQIC02,		"Generic QIC-02 tape streamer"}, \
-	{MT_ISWT5150,		"Wangtek 5150, QIC-150"}, \
-	{MT_ISARCHIVE_5945L2,	"Archive 5945L-2"}, \
-	{MT_ISCMSJ500,		"CMS Jumbo 500"}, \
-	{MT_ISTDC3610,		"Tandberg TDC 3610, QIC-24"}, \
-	{MT_ISARCHIVE_VP60I,	"Archive VP60i, QIC-02"}, \
-	{MT_ISARCHIVE_2150L,	"Archive Viper 2150L"}, \
-	{MT_ISARCHIVE_2060L,	"Archive Viper 2060L"}, \
-	{MT_ISARCHIVESC499,	"Archive SC-499 QIC-36 controller"}, \
-	{MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \
-	{MT_ISWT5099EEN24,	"Wangtek 5099-een24, 60MB"}, \
-	{MT_ISTEAC_MT2ST,	"Teac MT-2ST 155mb data cassette drive"}, \
-	{MT_ISEVEREX_FT40A,	"Everex FT40A, QIC-40"}, \
-	{MT_ISONSTREAM_SC,      "OnStream SC-, DI-, DP-, or USB tape drive"}, \
-	{MT_ISSCSI1,		"Generic SCSI-1 tape"}, \
-	{MT_ISSCSI2,		"Generic SCSI-2 tape"}, \
-	{0, NULL} \
-}
-
 
 /* structure for MTIOCPOS - mag tape get position command */
 
@@ -150,130 +123,11 @@
 };
 
 
-/*  structure for MTIOCVOLINFO, query information about the volume
- *  currently positioned at (zftape)
- */
-struct mtvolinfo {
-	unsigned int mt_volno;   /* vol-number */
-	unsigned int mt_blksz;   /* blocksize used when recording */
-	unsigned int mt_rawsize; /* raw tape space consumed, in kb */
-	unsigned int mt_size;    /* volume size after decompression, in kb */
-	unsigned int mt_cmpr:1;  /* this volume has been compressed */
-};
-
-/* raw access to a floppy drive, read and write an arbitrary segment.
- * For ftape/zftape to support formatting etc.
- */
-#define MT_FT_RD_SINGLE  0
-#define MT_FT_RD_AHEAD   1
-#define MT_FT_WR_ASYNC   0 /* start tape only when all buffers are full     */
-#define MT_FT_WR_MULTI   1 /* start tape, continue until buffers are empty  */
-#define MT_FT_WR_SINGLE  2 /* write a single segment and stop afterwards    */
-#define MT_FT_WR_DELETE  3 /* write deleted data marks, one segment at time */
-
-struct mtftseg
-{            
-	unsigned mt_segno;   /* the segment to read or write */
-	unsigned mt_mode;    /* modes for read/write (sync/async etc.) */
-	int      mt_result;  /* result of r/w request, not of the ioctl */
-	void    __user *mt_data;    /* User space buffer: must be 29kb */
-};
-
-/* get tape capacity (ftape/zftape)
- */
-struct mttapesize {
-	unsigned long mt_capacity; /* entire, uncompressed capacity 
-				    * of a cartridge
-				    */
-	unsigned long mt_used;     /* what has been used so far, raw 
-				    * uncompressed amount
-				    */
-};
-
-/*  possible values of the ftfmt_op field
- */
-#define FTFMT_SET_PARMS		1 /* set software parms */
-#define FTFMT_GET_PARMS		2 /* get software parms */
-#define FTFMT_FORMAT_TRACK	3 /* start formatting a tape track   */
-#define FTFMT_STATUS		4 /* monitor formatting a tape track */
-#define FTFMT_VERIFY		5 /* verify the given segment        */
-
-struct ftfmtparms {
-	unsigned char  ft_qicstd;   /* QIC-40/QIC-80/QIC-3010/QIC-3020 */
-	unsigned char  ft_fmtcode;  /* Refer to the QIC specs */
-	unsigned char  ft_fhm;      /* floppy head max */
-	unsigned char  ft_ftm;      /* floppy track max */
-	unsigned short ft_spt;      /* segments per track */
-	unsigned short ft_tpc;      /* tracks per cartridge */
-};
-
-struct ftfmttrack {
-	unsigned int  ft_track;   /* track to format */
-	unsigned char ft_gap3;    /* size of gap3, for FORMAT_TRK */
-};
-
-struct ftfmtstatus {
-	unsigned int  ft_segment;  /* segment currently being formatted */
-};
-
-struct ftfmtverify {
-	unsigned int  ft_segment;   /* segment to verify */
-	unsigned long ft_bsm;       /* bsm as result of VERIFY cmd */
-};
-
-struct mtftformat {
-	unsigned int fmt_op;      /* operation to perform */
-	union fmt_arg {
-		struct ftfmtparms  fmt_parms;  /* format parameters */
-		struct ftfmttrack  fmt_track;  /* ctrl while formatting */
-		struct ftfmtstatus fmt_status;
-		struct ftfmtverify fmt_verify; /* for verifying */ 
-	} fmt_arg;
-};
-
-struct mtftcmd {
-	unsigned int ft_wait_before; /* timeout to wait for drive to get ready 
-				      * before command is sent. Milliseconds
-				      */
-	qic117_cmd_t ft_cmd;         /* command to send */
-	unsigned char ft_parm_cnt;   /* zero: no parm is sent. */
-	unsigned char ft_parms[3];   /* parameter(s) to send to
-				      * the drive. The parms are nibbles
-				      * driver sends cmd + 2 step pulses */
-	unsigned int ft_result_bits; /* if non zero, number of bits
-				      *	returned by the tape drive
-				      */
-	unsigned int ft_result;      /* the result returned by the tape drive*/
-	unsigned int ft_wait_after;  /* timeout to wait for drive to get ready
-				      * after command is sent. 0: don't wait */
-	int ft_status;	             /* status returned by ready wait
-				      * undefined if timeout was 0.
-				      */
-	int ft_error;                /* error code if error status was set by 
-				      * command
-				      */
-};
-
 /* mag tape io control commands */
 #define	MTIOCTOP	_IOW('m', 1, struct mtop)	/* do a mag tape op */
 #define	MTIOCGET	_IOR('m', 2, struct mtget)	/* get tape status */
 #define	MTIOCPOS	_IOR('m', 3, struct mtpos)	/* get tape position */
 
-/* The next two are used by the QIC-02 driver for runtime reconfiguration.
- * See tpqic02.h for struct mtconfiginfo.
- */
-#define	MTIOCGETCONFIG	_IOR('m', 4, struct mtconfiginfo) /* get tape config */
-#define	MTIOCSETCONFIG	_IOW('m', 5, struct mtconfiginfo) /* set tape config */
-
-/* the next six are used by the floppy ftape drivers and its frontends
- * sorry, but MTIOCTOP commands are write only.
- */
-#define	MTIOCRDFTSEG    _IOWR('m', 6, struct mtftseg)  /* read a segment */
-#define	MTIOCWRFTSEG    _IOWR('m', 7, struct mtftseg)   /* write a segment */
-#define MTIOCVOLINFO	_IOR('m',  8, struct mtvolinfo) /* info about volume */
-#define MTIOCGETSIZE    _IOR('m',  9, struct mttapesize)/* get cartridge size*/
-#define MTIOCFTFORMAT   _IOWR('m', 10, struct mtftformat) /* format ftape */
-#define MTIOCFTCMD	_IOWR('m', 11, struct mtftcmd) /* send QIC-117 cmd */
 
 /* Generic Mag Tape (device independent) status macros for examining
  * mt_gstat -- HP-UX compatible.
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index a7544af..b81bc2a 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -105,7 +105,7 @@
 extern void __mutex_init(struct mutex *lock, const char *name,
 			 struct lock_class_key *key);
 
-/***
+/**
  * mutex_is_locked - is the mutex locked
  * @lock: the mutex to be queried
  *
diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h
index 6b01ba2..2f4e98b 100644
--- a/include/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/linux/netfilter/nf_conntrack_tcp.h
@@ -25,7 +25,7 @@
 #define IP_CT_TCP_FLAG_SACK_PERM		0x02
 
 /* This sender sent FIN first */
-#define IP_CT_TCP_FLAG_CLOSE_INIT		0x03
+#define IP_CT_TCP_FLAG_CLOSE_INIT		0x04
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 0be2354..24c8786 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -190,6 +190,7 @@
 
 /* The argument to ARPT_SO_ADD_COUNTERS. */
 #define arpt_counters_info xt_counters_info
+#define arpt_counters xt_counters
 
 /* The argument to ARPT_SO_GET_ENTRIES. */
 struct arpt_get_entries
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 4f06dad..98d566c 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -28,7 +28,7 @@
 #include <linux/netfilter/x_tables.h>
 
 #define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
-#define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
 #define ipt_match xt_match
 #define ipt_target xt_target
 #define ipt_table xt_table
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0496306..c5d4084 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -308,6 +308,7 @@
 extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
+extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern void nfs_begin_attr_update(struct inode *);
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 0727774..4b7c4b5 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -52,8 +52,6 @@
 struct readdir_cd {
 	__be32			err;	/* 0, nfserr, or nfserr_eof */
 };
-typedef int		(*encode_dent_fn)(struct readdir_cd *, const char *,
-						int, loff_t, ino_t, unsigned int);
 typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
 
 extern struct svc_program	nfsd_program;
@@ -117,7 +115,7 @@
 int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
 				unsigned long size);
 __be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
-			     loff_t *, struct readdir_cd *, encode_dent_fn);
+			     loff_t *, struct readdir_cd *, filldir_t);
 __be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
 				struct kstatfs *);
 
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index f3b51d6..d9c6c38 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -217,11 +217,7 @@
 static __inline__ struct svc_fh *
 fh_copy(struct svc_fh *dst, struct svc_fh *src)
 {
-	if (src->fh_dentry || src->fh_locked) {
-		struct dentry *dentry = src->fh_dentry;
-		printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name);
-	}
+	WARN_ON(src->fh_dentry || src->fh_locked);
 			
 	*dst = *src;
 	return dst;
@@ -300,10 +296,8 @@
 	dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
 			SVCFH_fmt(fhp), fhp->fh_locked);
 
-	if (!fhp->fh_dentry) {
-		printk(KERN_ERR "fh_lock: fh not verified!\n");
-		return;
-	}
+	BUG_ON(!dentry);
+
 	if (fhp->fh_locked) {
 		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -328,8 +322,7 @@
 static inline void
 fh_unlock(struct svc_fh *fhp)
 {
-	if (!fhp->fh_dentry)
-		printk(KERN_ERR "fh_unlock: fh not verified!\n");
+	BUG_ON(!fhp->fh_dentry);
 
 	if (fhp->fh_locked) {
 		fill_post_wcc(fhp);
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index 877192d..67885d5 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -165,8 +165,8 @@
 int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *, struct nfsd_statfsres *);
 int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *, struct nfsd_readdirres *);
 
-int nfssvc_encode_entry(struct readdir_cd *, const char *name,
-				int namlen, loff_t offset, ino_t ino, unsigned int);
+int nfssvc_encode_entry(void *, const char *name,
+			int namlen, loff_t offset, u64 ino, unsigned int);
 
 int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
 
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 7996386..89d9d60 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -331,11 +331,11 @@
 				struct nfsd3_attrstat *);
 int nfs3svc_release_fhandle2(struct svc_rqst *, __be32 *,
 				struct nfsd3_fhandle_pair *);
-int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
-				int namlen, loff_t offset, ino_t ino,
+int nfs3svc_encode_entry(void *, const char *name,
+				int namlen, loff_t offset, u64 ino,
 				unsigned int);
-int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
-				int namlen, loff_t offset, ino_t ino,
+int nfs3svc_encode_entry_plus(void *, const char *name,
+				int namlen, loff_t offset, u64 ino,
 				unsigned int);
 /* Helper functions for NFSv3 ACL code */
 __be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p,
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f7a416c..ccd706f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -735,9 +735,11 @@
 #define PCI_DEVICE_ID_TI_TVP4020	0x3d07
 #define PCI_DEVICE_ID_TI_4450		0x8011
 #define PCI_DEVICE_ID_TI_XX21_XX11	0x8031
+#define PCI_DEVICE_ID_TI_XX21_XX11_FM	0x8033
 #define PCI_DEVICE_ID_TI_XX21_XX11_SD	0x8034
 #define PCI_DEVICE_ID_TI_X515		0x8036
 #define PCI_DEVICE_ID_TI_XX12		0x8039
+#define PCI_DEVICE_ID_TI_XX12_FM	0x803b
 #define PCI_DEVICE_ID_TI_1130		0xac12
 #define PCI_DEVICE_ID_TI_1031		0xac13
 #define PCI_DEVICE_ID_TI_1131		0xac15
@@ -765,6 +767,7 @@
 #define PCI_DEVICE_ID_TI_1510		0xac56
 #define PCI_DEVICE_ID_TI_X620		0xac8d
 #define PCI_DEVICE_ID_TI_X420		0xac8e
+#define PCI_DEVICE_ID_TI_XX20_FM	0xac8f
 
 #define PCI_VENDOR_ID_SONY		0x104d
 
@@ -1277,13 +1280,13 @@
 #define PCI_DEVICE_ID_VIA_3296_0	0x0296
 #define PCI_DEVICE_ID_VIA_8363_0	0x0305
 #define PCI_DEVICE_ID_VIA_P4M800CE	0x0314
-#define PCI_DEVICE_ID_VIA_K8M890CE	0x0336
+#define PCI_DEVICE_ID_VIA_P4M890	0x0327
+#define PCI_DEVICE_ID_VIA_VT3336	0x0336
 #define PCI_DEVICE_ID_VIA_8371_0	0x0391
 #define PCI_DEVICE_ID_VIA_8501_0	0x0501
 #define PCI_DEVICE_ID_VIA_82C561	0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1	0x0571
 #define PCI_DEVICE_ID_VIA_82C576	0x0576
-#define PCI_DEVICE_ID_VIA_SATA_EIDE	0x0581
 #define PCI_DEVICE_ID_VIA_82C586_0	0x0586
 #define PCI_DEVICE_ID_VIA_82C596	0x0596
 #define PCI_DEVICE_ID_VIA_82C597_0	0x0597
@@ -1326,6 +1329,8 @@
 #define PCI_DEVICE_ID_VIA_8237		0x3227
 #define PCI_DEVICE_ID_VIA_8251		0x3287
 #define PCI_DEVICE_ID_VIA_8237A		0x3337
+#define PCI_DEVICE_ID_VIA_8237S		0x3372
+#define PCI_DEVICE_ID_VIA_SATA_EIDE	0x5324
 #define PCI_DEVICE_ID_VIA_8231		0x8231
 #define PCI_DEVICE_ID_VIA_8231_4	0x8235
 #define PCI_DEVICE_ID_VIA_8365_1	0x8305
@@ -1969,6 +1974,7 @@
 #define PCI_DEVICE_ID_TOPIC_TP560	0x0000
 
 #define PCI_VENDOR_ID_ENE		0x1524
+#define PCI_DEVICE_ID_ENE_CB712_SD	0x0550
 #define PCI_DEVICE_ID_ENE_1211		0x1211
 #define PCI_DEVICE_ID_ENE_1225		0x1225
 #define PCI_DEVICE_ID_ENE_1410		0x1410
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index d2a9d41..2833806 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -39,7 +39,7 @@
 
 static inline struct task_struct *child_reaper(struct task_struct *tsk)
 {
-	return tsk->nsproxy->pid_ns->child_reaper;
+	return init_pid_ns.child_reaper;
 }
 
 #endif /* _LINUX_PID_NS_H */
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 5670b34..eec48f5 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -15,6 +15,7 @@
 #define CPU_PROFILING	1
 #define SCHED_PROFILING	2
 #define SLEEP_PROFILING	3
+#define KVM_PROFILING	4
 
 struct proc_dir_entry;
 struct pt_regs;
diff --git a/include/linux/qic117.h b/include/linux/qic117.h
deleted file mode 100644
index 07b537e..0000000
--- a/include/linux/qic117.h
+++ /dev/null
@@ -1,290 +0,0 @@
-#ifndef _QIC117_H
-#define _QIC117_H
-
-/*
- *      Copyright (C) 1993-1996 Bas Laarhoven,
- *                (C) 1997      Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING.  If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/include/linux/qic117.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:32 $
- *
- *      This file contains QIC-117 spec. related definitions for the
- *      QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- *
- *      These data were taken from the Quarter-Inch Cartridge
- *      Drive Standards, Inc. document titled:
- *      `Common Command Set Interface Specification for Flexible
- *       Disk Controller Based Minicartridge Tape Drives'
- *       document QIC-117 Revision J, 28 Aug 96.
- *      For more information, contact:
- *       Quarter-Inch Cartridge Drive Standards, Inc.
- *       311 East Carrillo Street
- *       Santa Barbara, California 93101
- *       Telephone (805) 963-3853
- *       Fax       (805) 962-1541
- *       WWW       http://www.qic.org
- *
- *      Current QIC standard revisions (of interest) are:
- *       QIC-40-MC,   Rev. M,  2 Sep 92.
- *       QIC-80-MC,   Rev. N, 20 Mar 96.
- *       QIC-80-MC,   Rev. K, 15 Dec 94.
- *       QIC-113,     Rev. G, 15 Jun 95.
- *       QIC-117,     Rev. J, 28 Aug 96.
- *       QIC-122,     Rev. B,  6 Mar 91.
- *       QIC-130,     Rev. C,  2 Sep 92.
- *       QIC-3010-MC, Rev. F, 14 Jun 95.
- *       QIC-3020-MC, Rev. G, 31 Aug 95.
- *       QIC-CRF3,    Rev. B, 15 Jun 95.
- * */
-
-/*
- *      QIC-117 common command set rev. J.
- *      These commands are sent to the tape unit
- *      as number of pulses over the step line.
- */
-
-typedef enum {
-	QIC_NO_COMMAND                  = 0,
-	QIC_RESET 			= 1,
-	QIC_REPORT_NEXT_BIT		= 2,
-	QIC_PAUSE 			= 3,
-	QIC_MICRO_STEP_PAUSE		= 4,
-	QIC_ALTERNATE_TIMEOUT		= 5,
-	QIC_REPORT_DRIVE_STATUS		= 6,
-	QIC_REPORT_ERROR_CODE		= 7,
-	QIC_REPORT_DRIVE_CONFIGURATION	= 8,
-	QIC_REPORT_ROM_VERSION		= 9,
-	QIC_LOGICAL_FORWARD		= 10,
-	QIC_PHYSICAL_REVERSE		= 11,
-	QIC_PHYSICAL_FORWARD		= 12,
-	QIC_SEEK_HEAD_TO_TRACK		= 13,
-	QIC_SEEK_LOAD_POINT		= 14,
-	QIC_ENTER_FORMAT_MODE		= 15,
-	QIC_WRITE_REFERENCE_BURST	= 16,
-	QIC_ENTER_VERIFY_MODE		= 17,
-	QIC_STOP_TAPE			= 18,
-/* commands 19-20: reserved */
-	QIC_MICRO_STEP_HEAD_UP		= 21,
-	QIC_MICRO_STEP_HEAD_DOWN	= 22,
-	QIC_SOFT_SELECT			= 23,
-	QIC_SOFT_DESELECT		= 24,
-	QIC_SKIP_REVERSE		= 25,
-	QIC_SKIP_FORWARD		= 26,
-	QIC_SELECT_RATE			= 27,
-/* command 27, in ccs2: Select Rate or Format */
-	QIC_ENTER_DIAGNOSTIC_1		= 28,
-	QIC_ENTER_DIAGNOSTIC_2		= 29,
-	QIC_ENTER_PRIMARY_MODE		= 30,
-/* command 31: vendor unique */
-	QIC_REPORT_VENDOR_ID		= 32,
-	QIC_REPORT_TAPE_STATUS		= 33,
-	QIC_SKIP_EXTENDED_REVERSE	= 34,
-	QIC_SKIP_EXTENDED_FORWARD	= 35,
-	QIC_CALIBRATE_TAPE_LENGTH	= 36,
-	QIC_REPORT_FORMAT_SEGMENTS	= 37,
-	QIC_SET_FORMAT_SEGMENTS		= 38,
-/* commands 39-45: reserved */
-	QIC_PHANTOM_SELECT		= 46,
-	QIC_PHANTOM_DESELECT		= 47
-} qic117_cmd_t;
-
-typedef enum {
-	discretional = 0, required, ccs1, ccs2
-} qic_compatibility;
-
-typedef enum {
-	unused, mode, motion, report
-} command_types;
-
-struct qic117_command_table {
-	char *name;
-	__u8 mask;
-	__u8 state;
-	__u8 cmd_type;
-	__u8 non_intr;
-	__u8 level;
-};
-
-#define QIC117_COMMANDS {\
-/* command                           mask  state cmd_type           */\
-/* |    name                         |     |     |       non_intr   */\
-/* |    |                            |     |     |       |  level   */\
-/* 0*/ {NULL,                        0x00, 0x00, mode,   0, discretional},\
-/* 1*/ {"soft reset",                0x00, 0x00, motion, 1, required},\
-/* 2*/ {"report next bit",           0x00, 0x00, report, 0, required},\
-/* 3*/ {"pause",                     0x36, 0x24, motion, 1, required},\
-/* 4*/ {"micro step pause",          0x36, 0x24, motion, 1, required},\
-/* 5*/ {"alternate command timeout", 0x00, 0x00, mode,   0, required},\
-/* 6*/ {"report drive status",       0x00, 0x00, report, 0, required},\
-/* 7*/ {"report error code",         0x01, 0x01, report, 0, required},\
-/* 8*/ {"report drive configuration",0x00, 0x00, report, 0, required},\
-/* 9*/ {"report rom version",        0x00, 0x00, report, 0, required},\
-/*10*/ {"logical forward",           0x37, 0x25, motion, 0, required},\
-/*11*/ {"physical reverse",          0x17, 0x05, motion, 0, required},\
-/*12*/ {"physical forward",          0x17, 0x05, motion, 0, required},\
-/*13*/ {"seek head to track",        0x37, 0x25, motion, 0, required},\
-/*14*/ {"seek load point",           0x17, 0x05, motion, 1, required},\
-/*15*/ {"enter format mode",         0x1f, 0x05, mode,   0, required},\
-/*16*/ {"write reference burst",     0x1f, 0x05, motion, 1, required},\
-/*17*/ {"enter verify mode",         0x37, 0x25, mode,   0, required},\
-/*18*/ {"stop tape",                 0x00, 0x00, motion, 1, required},\
-/*19*/ {"reserved (19)",             0x00, 0x00, unused, 0, discretional},\
-/*20*/ {"reserved (20)",             0x00, 0x00, unused, 0, discretional},\
-/*21*/ {"micro step head up",        0x02, 0x00, motion, 0, required},\
-/*22*/ {"micro step head down",      0x02, 0x00, motion, 0, required},\
-/*23*/ {"soft select",               0x00, 0x00, mode,   0, discretional},\
-/*24*/ {"soft deselect",             0x00, 0x00, mode,   0, discretional},\
-/*25*/ {"skip segments reverse",     0x36, 0x24, motion, 1, required},\
-/*26*/ {"skip segments forward",     0x36, 0x24, motion, 1, required},\
-/*27*/ {"select rate or format",     0x03, 0x01, mode,   0, required /* [ccs2] */},\
-/*28*/ {"enter diag mode 1",         0x00, 0x00, mode,   0, discretional},\
-/*29*/ {"enter diag mode 2",         0x00, 0x00, mode,   0, discretional},\
-/*30*/ {"enter primary mode",        0x00, 0x00, mode,   0, required},\
-/*31*/ {"vendor unique (31)",        0x00, 0x00, unused, 0, discretional},\
-/*32*/ {"report vendor id",          0x00, 0x00, report, 0, required},\
-/*33*/ {"report tape status",        0x04, 0x04, report, 0, ccs1},\
-/*34*/ {"skip extended reverse",     0x36, 0x24, motion, 1, ccs1},\
-/*35*/ {"skip extended forward",     0x36, 0x24, motion, 1, ccs1},\
-/*36*/ {"calibrate tape length",     0x17, 0x05, motion, 1, ccs2},\
-/*37*/ {"report format segments",    0x17, 0x05, report, 0, ccs2},\
-/*38*/ {"set format segments",       0x17, 0x05, mode,   0, ccs2},\
-/*39*/ {"reserved (39)",             0x00, 0x00, unused, 0, discretional},\
-/*40*/ {"vendor unique (40)",        0x00, 0x00, unused, 0, discretional},\
-/*41*/ {"vendor unique (41)",        0x00, 0x00, unused, 0, discretional},\
-/*42*/ {"vendor unique (42)",        0x00, 0x00, unused, 0, discretional},\
-/*43*/ {"vendor unique (43)",        0x00, 0x00, unused, 0, discretional},\
-/*44*/ {"vendor unique (44)",        0x00, 0x00, unused, 0, discretional},\
-/*45*/ {"vendor unique (45)",        0x00, 0x00, unused, 0, discretional},\
-/*46*/ {"phantom select",            0x00, 0x00, mode,   0, discretional},\
-/*47*/ {"phantom deselect",          0x00, 0x00, mode,   0, discretional},\
-}
-
-/*
- *      Status bits returned by QIC_REPORT_DRIVE_STATUS
- */
-
-#define QIC_STATUS_READY	0x01	/* Drive is ready or idle. */
-#define QIC_STATUS_ERROR	0x02	/* Error detected, must read
-					   error code to clear this */
-#define QIC_STATUS_CARTRIDGE_PRESENT 0x04	/* Tape is present */
-#define QIC_STATUS_WRITE_PROTECT 0x08	/* Tape is write protected */
-#define QIC_STATUS_NEW_CARTRIDGE 0x10	/* New cartridge inserted, must
-					   read error status to clear. */
-#define QIC_STATUS_REFERENCED	0x20	/* Cartridge appears to have been
-					   formatted. */
-#define QIC_STATUS_AT_BOT	0x40	/* Cartridge is at physical
-					   beginning of tape. */
-#define QIC_STATUS_AT_EOT	0x80	/* Cartridge is at physical end
-					   of tape. */
-/*
- *      Status bits returned by QIC_REPORT_DRIVE_CONFIGURATION
- */
-
-#define QIC_CONFIG_RATE_MASK	0x18
-#define QIC_CONFIG_RATE_SHIFT	3
-#define QIC_CONFIG_RATE_250	0
-#define QIC_CONFIG_RATE_500	2
-#define QIC_CONFIG_RATE_1000	3
-#define QIC_CONFIG_RATE_2000	1
-#define QIC_CONFIG_RATE_4000    0       /* since QIC-117 Rev. J */
-
-#define QIC_CONFIG_LONG		0x40	/* Extra Length Tape Detected */
-#define QIC_CONFIG_80		0x80	/* QIC-80 detected. */
-
-/*
- *      Status bits returned by QIC_REPORT_TAPE_STATUS
- */
-
-#define QIC_TAPE_STD_MASK       0x0f
-#define QIC_TAPE_QIC40  	0x01
-#define QIC_TAPE_QIC80  	0x02
-#define QIC_TAPE_QIC3020  	0x03
-#define QIC_TAPE_QIC3010  	0x04
-
-#define QIC_TAPE_LEN_MASK	0x70
-#define QIC_TAPE_205FT		0x10
-#define QIC_TAPE_307FT		0x20
-#define QIC_TAPE_VARIABLE	0x30
-#define QIC_TAPE_1100FT		0x40
-#define QIC_TAPE_FLEX		0x60
-
-#define QIC_TAPE_WIDE		0x80
-
-/* Define a value (in feet) slightly higher than 
- * the possible maximum tape length.
- */
-#define QIC_TOP_TAPE_LEN	1500
-
-/*
- *      Errors: List of error codes, and their severity.
- */
-
-typedef struct {
-	char *message;		/* Text describing the error. */
-	unsigned int fatal:1;	/* Non-zero if the error is fatal. */
-} ftape_error;
-
-#define QIC117_ERRORS {\
-  /* 0*/ { "No error", 0, },\
-  /* 1*/ { "Command Received while Drive Not Ready", 0, },\
-  /* 2*/ { "Cartridge Not Present or Removed", 1, },\
-  /* 3*/ { "Motor Speed Error (not within 1%)", 1, },\
-  /* 4*/ { "Motor Speed Fault (jammed, or gross speed error", 1, },\
-  /* 5*/ { "Cartridge Write Protected", 1, },\
-  /* 6*/ { "Undefined or Reserved Command Code", 1, },\
-  /* 7*/ { "Illegal Track Address Specified for Seek", 1, },\
-  /* 8*/ { "Illegal Command in Report Subcontext", 0, },\
-  /* 9*/ { "Illegal Entry into a Diagnostic Mode", 1, },\
-  /*10*/ { "Broken Tape Detected (based on hole sensor)", 1, },\
-  /*11*/ { "Warning--Read Gain Setting Error", 1, },\
-  /*12*/ { "Command Received While Error Status Pending (obs)", 1, },\
-  /*13*/ { "Command Received While New Cartridge Pending", 1, },\
-  /*14*/ { "Command Illegal or Undefined in Primary Mode", 1, },\
-  /*15*/ { "Command Illegal or Undefined in Format Mode", 1, },\
-  /*16*/ { "Command Illegal or Undefined in Verify Mode", 1, },\
-  /*17*/ { "Logical Forward Not at Logical BOT or no Format Segments in Format Mode", 1, },\
-  /*18*/ { "Logical EOT Before All Segments generated", 1, },\
-  /*19*/ { "Command Illegal When Cartridge Not Referenced", 1, },\
-  /*20*/ { "Self-Diagnostic Failed (cannot be cleared)", 1, },\
-  /*21*/ { "Warning EEPROM Not Initialized, Defaults Set", 1, },\
-  /*22*/ { "EEPROM Corrupted or Hardware Failure", 1, },\
-  /*23*/ { "Motion Time-out Error", 1, },\
-  /*24*/ { "Data Segment Too Long -- Logical Forward or Pause", 1, },\
-  /*25*/ { "Transmit Overrun (obs)", 1, },\
-  /*26*/ { "Power On Reset Occurred", 0, },\
-  /*27*/ { "Software Reset Occurred", 0, },\
-  /*28*/ { "Diagnostic Mode 1 Error", 1, },\
-  /*29*/ { "Diagnostic Mode 2 Error", 1, },\
-  /*30*/ { "Command Received During Non-Interruptible Process", 1, },\
-  /*31*/ { "Rate or Format Selection Error", 1, },\
-  /*32*/ { "Illegal Command While in High Speed Mode", 1, },\
-  /*33*/ { "Illegal Seek Segment Value", 1, },\
-  /*34*/ { "Invalid Media", 1, },\
-  /*35*/ { "Head Positioning Failure", 1, },\
-  /*36*/ { "Write Reference Burst Failure", 1, },\
-  /*37*/ { "Prom Code Missing", 1, },\
-  /*38*/ { "Invalid Format", 1, },\
-  /*39*/ { "EOT/BOT System Failure", 1, },\
-  /*40*/ { "Prom A Checksum Error", 1, },\
-  /*41*/ { "Drive Wakeup Reset Occurred", 1, },\
-  /*42*/ { "Prom B Checksum Error", 1, },\
-  /*43*/ { "Illegal Entry into Format Mode", 1, },\
-}
-
-#endif				/* _QIC117_H */
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index 866a1e2..fbaeda7 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -94,7 +94,7 @@
 			struct page *page, int rw);
 extern void md_do_sync(mddev_t *mddev);
 extern void md_new_event(mddev_t *mddev);
-
+extern void md_allow_write(mddev_t *mddev);
 
 #endif /* CONFIG_MD */
 #endif 
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index 5b3b297..ce3663f 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -25,6 +25,7 @@
 	i_link_saved_truncate_mask = 0x0020,
 	i_has_xattr_dir = 0x0040,
 	i_data_log = 0x0080,
+	i_ever_mapped = 0x0100
 } reiserfs_inode_flags;
 
 struct reiserfs_inode_info {
@@ -52,6 +53,7 @@
 	 ** flushed */
 	unsigned long i_trans_id;
 	struct reiserfs_journal_list *i_jl;
+	struct mutex i_mmap;
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
 	struct posix_acl *i_acl_access;
 	struct posix_acl *i_acl_default;
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index b0090e9..382bb79 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -16,7 +16,7 @@
 #include <linux/plist.h>
 #include <linux/spinlock_types.h>
 
-/*
+/**
  * The rt_mutex structure
  *
  * @wait_lock:	spinlock to protect the structure
@@ -71,7 +71,7 @@
 #define DEFINE_RT_MUTEX(mutexname) \
 	struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)
 
-/***
+/**
  * rt_mutex_is_locked - is the mutex locked
  * @lock: the mutex to be queried
  *
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 97c7616..8b6ce60 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -250,7 +250,6 @@
 				int flags, const struct rpc_call_ops *ops,
 				void *data);
 void		rpc_put_task(struct rpc_task *);
-void		rpc_release_task(struct rpc_task *);
 void		rpc_exit_task(struct rpc_task *);
 void		rpc_release_calldata(const struct rpc_call_ops *, void *);
 void		rpc_killall_tasks(struct rpc_clnt *);
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 965d6c2..64f3d60 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -144,8 +144,11 @@
  *
  * Each request/reply pair can have at most one "payload", plus two pages,
  * one for the request, and one for the reply.
+ * We using ->sendfile to return read data, we might need one extra page
+ * if the request is not page-aligned.  So add another '1'.
  */
-#define RPCSVC_MAXPAGES		((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2)
+#define RPCSVC_MAXPAGES		((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE \
+				+ 2 + 1)
 
 static inline u32 svc_getnl(struct kvec *iov)
 {
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index dfb8052..3deb0a6 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -17,7 +17,7 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/scatterlist.h>
+#include <linux/kthread.h>
 
 /* Host registers (relative to pci base address): */
 enum {
@@ -62,11 +62,10 @@
 
 
 #define TIFM_IRQ_ENABLE           0x80000000
-#define TIFM_IRQ_SOCKMASK         0x00000001
-#define TIFM_IRQ_CARDMASK         0x00000100
-#define TIFM_IRQ_FIFOMASK         0x00010000
+#define TIFM_IRQ_SOCKMASK(x)      (x)
+#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
+#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
 #define TIFM_IRQ_SETALL           0xffffffff
-#define TIFM_IRQ_SETALLSOCK       0x0000000f
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
@@ -89,10 +88,9 @@
 	char __iomem            *addr;
 	spinlock_t              lock;
 	tifm_media_id           media_id;
-	char                    wq_name[KOBJ_NAME_LEN];
-	struct workqueue_struct *wq;
+	unsigned int            socket_id;
 
-	unsigned int            (*signal_irq)(struct tifm_dev *sock,
+	void                    (*signal_irq)(struct tifm_dev *sock,
 					      unsigned int sock_irq_status);
 
 	struct tifm_driver      *drv;
@@ -103,24 +101,23 @@
 	tifm_media_id        *id_table;
 	int                  (*probe)(struct tifm_dev *dev);
 	void                 (*remove)(struct tifm_dev *dev);
+	int                  (*suspend)(struct tifm_dev *dev,
+                                        pm_message_t state);
+	int                  (*resume)(struct tifm_dev *dev);
 
 	struct device_driver driver;
 };
 
 struct tifm_adapter {
 	char __iomem            *addr;
-	unsigned int            irq_status;
-	unsigned int            insert_mask;
-	unsigned int            remove_mask;
 	spinlock_t              lock;
+	unsigned int            irq_status;
+	unsigned int            socket_change_set;
+	wait_queue_head_t       change_set_notify;
 	unsigned int            id;
-	unsigned int            max_sockets;
-	char                    wq_name[KOBJ_NAME_LEN];
-	unsigned int            inhibit_new_cards;
-	struct workqueue_struct *wq;
-	struct work_struct      media_inserter;
-	struct work_struct      media_remover;
+	unsigned int            num_sockets;
 	struct tifm_dev         **sockets;
+	struct task_struct      *media_switcher;
 	struct class_device     cdev;
 	struct device           *dev;
 
@@ -130,9 +127,9 @@
 struct tifm_adapter *tifm_alloc_adapter(void);
 void tifm_free_device(struct device *dev);
 void tifm_free_adapter(struct tifm_adapter *fm);
-int tifm_add_adapter(struct tifm_adapter *fm);
+int tifm_add_adapter(struct tifm_adapter *fm, int (*mediathreadfn)(void *data));
 void tifm_remove_adapter(struct tifm_adapter *fm);
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id);
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
 int tifm_register_driver(struct tifm_driver *drv);
 void tifm_unregister_driver(struct tifm_driver *drv);
 void tifm_eject(struct tifm_dev *sock);
diff --git a/include/linux/timer.h b/include/linux/timer.h
index eeef664..fb5edaa 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -41,7 +41,7 @@
 	init_timer(timer);
 }
 
-/***
+/**
  * timer_pending - is a timer pending?
  * @timer: the timer in question
  *
@@ -63,7 +63,7 @@
 
 extern unsigned long next_timer_interrupt(void);
 
-/***
+/**
  * add_timer - start a timer
  * @timer: the timer to be added
  *
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5cb380a..d94e268 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -662,6 +662,15 @@
 #define V4L2_STD_ATSC_8_VSB     ((v4l2_std_id)0x01000000)
 #define V4L2_STD_ATSC_16_VSB    ((v4l2_std_id)0x02000000)
 
+/* FIXME:
+   Although std_id is 64 bits, there is an issue on PPC32 architecture that
+   makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding
+   this value to 32 bits.
+   As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide),
+   it should work fine. However, if needed to add more than two standards,
+   v4l2-common.c should be fixed.
+ */
+
 /* some merged standards */
 #define V4L2_STD_MN	(V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
 #define V4L2_STD_B	(V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index e6af381..e02d85f 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -218,7 +218,7 @@
 #define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
 
 #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
-#define WLAN_GET_SEQ_SEQ(seq)  ((seq) & IEEE80211_SCTL_SEQ)
+#define WLAN_GET_SEQ_SEQ(seq)  (((seq) & IEEE80211_SCTL_SEQ) >> 4)
 
 /* Authentication algorithms */
 #define WLAN_AUTH_OPEN 0
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 16aa96a..f13ddc2 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -38,5 +38,5 @@
 
 extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
 
-extern int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok);
+extern int inet6_csk_xmit(struct sk_buff *skb, int ipfragok);
 #endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index bf16d98..133cf30 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -37,8 +37,7 @@
  * (i.e. things that depend on the address family)
  */
 struct inet_connection_sock_af_ops {
-	int	    (*queue_xmit)(struct sk_buff *skb, struct sock *sk,
-				  int ipfragok);
+	int	    (*queue_xmit)(struct sk_buff *skb, int ipfragok);
 	void	    (*send_check)(struct sock *sk, int len,
 				  struct sk_buff *skb);
 	int	    (*rebuild_header)(struct sock *sk);
diff --git a/include/net/ip.h b/include/net/ip.h
index 053f02b..e79c3e3 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -97,7 +97,7 @@
 extern int		ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 extern int		ip_do_nat(struct sk_buff *skb);
 extern void		ip_send_check(struct iphdr *ip);
-extern int		ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok);
+extern int		ip_queue_xmit(struct sk_buff *skb, int ipfragok);
 extern void		ip_init(void);
 extern int		ip_append_data(struct sock *sk,
 				       int getfrag(void *from, char *to, int offset, int len,
diff --git a/include/net/netfilter/nf_conntrack_compat.h b/include/net/netfilter/nf_conntrack_compat.h
index b9ce5c8..6f84c1f 100644
--- a/include/net/netfilter/nf_conntrack_compat.h
+++ b/include/net/netfilter/nf_conntrack_compat.h
@@ -6,6 +6,7 @@
 #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/socket.h>
 
 #ifdef CONFIG_IP_NF_CONNTRACK_MARK
 static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 3269ed1..73cb994 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -134,6 +134,7 @@
 sctp_state_fn_t sctp_sf_discard_chunk;
 sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
 sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
+sctp_state_fn_t sctp_sf_do_5_2_3_initack;
 sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
 sctp_state_fn_t sctp_sf_unk_chunk;
 sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
diff --git a/include/rdma/ib_user_mad.h b/include/rdma/ib_user_mad.h
index 44537aa..d66b15e 100644
--- a/include/rdma/ib_user_mad.h
+++ b/include/rdma/ib_user_mad.h
@@ -98,7 +98,7 @@
  */
 struct ib_user_mad {
 	struct ib_user_mad_hdr hdr;
-	__u8	data[0];
+	__u64	data[0];
 };
 
 /**
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 0bfa332..765589f 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -45,6 +45,7 @@
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/kref.h>
 
 #include <asm/atomic.h>
 #include <asm/scatterlist.h>
@@ -419,8 +420,8 @@
 	enum ib_wc_opcode	opcode;
 	u32			vendor_err;
 	u32			byte_len;
+	struct ib_qp	       *qp;
 	__be32			imm_data;
-	u32			qp_num;
 	u32			src_qp;
 	int			wc_flags;
 	u16			pkey_index;
diff --git a/include/sound/core.h b/include/sound/core.h
index a994bea..521f036 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -132,8 +132,10 @@
 	int shutdown;			/* this card is going down */
 	int free_on_last_close;		/* free in context of file_release */
 	wait_queue_head_t shutdown_sleep;
-	struct device *parent;
-	struct device *dev;
+	struct device *dev;		/* device assigned to this card */
+#ifndef CONFIG_SYSFS_DEPRECATED
+	struct device *card_dev;	/* cardX object for sysfs */
+#endif
 
 #ifdef CONFIG_PM
 	unsigned int power_state;	/* power state */
@@ -191,6 +193,16 @@
 	struct device *dev;		/* device for sysfs */
 };
 
+/* return a device pointer linked to each sound device as a parent */
+static inline struct device *snd_card_get_device_link(struct snd_card *card)
+{
+#ifdef CONFIG_SYSFS_DEPRECATED
+	return card ? card->dev : NULL;
+#else
+	return card ? card->card_dev : NULL;
+#endif
+}
+
 /* sound.c */
 
 extern int snd_major;
@@ -257,7 +269,7 @@
 int snd_card_file_remove(struct snd_card *card, struct file *file);
 
 #ifndef snd_card_set_dev
-#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr))
+#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
 #endif
 
 /* device.c */
diff --git a/include/sound/version.h b/include/sound/version.h
index 2949b9b..20f7bab 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
 #define CONFIG_SND_VERSION "1.0.14rc1"
-#define CONFIG_SND_DATE " (Wed Dec 20 08:11:48 2006 UTC)"
+#define CONFIG_SND_DATE " (Tue Jan 09 09:56:17 2007 UTC)"
diff --git a/init/Makefile b/init/Makefile
index 9cd871c..633a268 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -15,6 +15,14 @@
 
 # dependencies on generated files need to be listed explicitly
 
-$(obj)/main.o: include/linux/compile.h
 $(obj)/version.o: include/linux/compile.h
 
+# compile.h changes depending on hostname, generation number, etc,
+# so we regenerate it always.
+# mkcompile_h will make sure to only update the
+# actual file if its content has changed.
+
+include/linux/compile.h: FORCE
+	@echo '  CHK     $@'
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
+	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(CFLAGS)"
diff --git a/init/main.c b/init/main.c
index bc27d72..8b4a7d7 100644
--- a/init/main.c
+++ b/init/main.c
@@ -50,9 +50,7 @@
 #include <linux/buffer_head.h>
 #include <linux/debug_locks.h>
 #include <linux/lockdep.h>
-#include <linux/utsrelease.h>
 #include <linux/pid_namespace.h>
-#include <linux/compile.h>
 #include <linux/device.h>
 
 #include <asm/io.h>
@@ -482,12 +480,6 @@
 {
 }
 
-static const char linux_banner[] =
-	"Linux version " UTS_RELEASE
-	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
-	" (" LINUX_COMPILER ")"
-	" " UTS_VERSION "\n";
-
 asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
@@ -703,7 +695,7 @@
 	do_initcalls();
 }
 
-static void do_pre_smp_initcalls(void)
+static void __init do_pre_smp_initcalls(void)
 {
 	extern int spawn_ksoftirqd(void);
 #ifdef CONFIG_SMP
diff --git a/init/version.c b/init/version.c
index 9d96d36..6c01ec1 100644
--- a/init/version.c
+++ b/init/version.c
@@ -33,3 +33,13 @@
 	},
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
+
+/* FIXED STRINGS! Don't touch! */
+const char linux_banner[] =
+	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+const char linux_proc_banner[] =
+	"%s version %s"
+	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+	" (" LINUX_COMPILER ") %s\n";
diff --git a/ipc/shm.c b/ipc/shm.c
index 6d16bb6..f8e10a2 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -279,7 +279,7 @@
 	if (size < SHMMIN || size > ns->shm_ctlmax)
 		return -EINVAL;
 
-	if (ns->shm_tot + numpages >= ns->shm_ctlall)
+	if (ns->shm_tot + numpages > ns->shm_ctlall)
 		return -ENOSPC;
 
 	shp = ipc_rcu_alloc(sizeof(*shp));
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 241064a..7406fe6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -204,7 +204,7 @@
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 /* Requires cpu_add_remove_lock to be held */
-static int __devinit _cpu_up(unsigned int cpu)
+static int __cpuinit _cpu_up(unsigned int cpu)
 {
 	int ret;
 	void *hcpu = (void *)(long)cpu;
@@ -239,7 +239,7 @@
 	return ret;
 }
 
-int __devinit cpu_up(unsigned int cpu)
+int __cpuinit cpu_up(unsigned int cpu)
 {
 	int err = 0;
 
diff --git a/kernel/exit.c b/kernel/exit.c
index 3540172..fec12eb 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -938,8 +938,8 @@
 
 	tsk->exit_code = code;
 	proc_exit_connector(tsk);
-	exit_notify(tsk);
 	exit_task_namespaces(tsk);
+	exit_notify(tsk);
 #ifdef CONFIG_NUMA
 	mpol_free(tsk->mempolicy);
 	tsk->mempolicy = NULL;
diff --git a/kernel/fork.c b/kernel/fork.c
index fc723e5..d57118d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1313,7 +1313,7 @@
 	return regs;
 }
 
-struct task_struct * __devinit fork_idle(int cpu)
+struct task_struct * __cpuinit fork_idle(int cpu)
 {
 	struct task_struct *task;
 	struct pt_regs regs;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index b385878..8b961ad 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -315,6 +315,9 @@
 			/* Undo nested disables: */
 			desc->depth = 1;
 	}
+	/* Reset broken irq detection when installing new handler */
+	desc->irq_count = 0;
+	desc->irqs_unhandled = 0;
 	spin_unlock_irqrestore(&desc->lock, flags);
 
 	new->irq = irq;
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 543ea2e..9d8c79b 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -176,7 +176,7 @@
 
 int noirqdebug __read_mostly;
 
-int __init noirqdebug_setup(char *str)
+int noirqdebug_setup(char *str)
 {
 	noirqdebug = 1;
 	printk(KERN_INFO "IRQ lockup detection disabled\n");
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 17ec4af..6fcf8dd 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -87,6 +87,12 @@
 	int ngarbage;
 };
 
+enum kprobe_slot_state {
+	SLOT_CLEAN = 0,
+	SLOT_DIRTY = 1,
+	SLOT_USED = 2,
+};
+
 static struct hlist_head kprobe_insn_pages;
 static int kprobe_garbage_slots;
 static int collect_garbage_slots(void);
@@ -130,8 +136,8 @@
 		if (kip->nused < INSNS_PER_PAGE) {
 			int i;
 			for (i = 0; i < INSNS_PER_PAGE; i++) {
-				if (!kip->slot_used[i]) {
-					kip->slot_used[i] = 1;
+				if (kip->slot_used[i] == SLOT_CLEAN) {
+					kip->slot_used[i] = SLOT_USED;
 					kip->nused++;
 					return kip->insns + (i * MAX_INSN_SIZE);
 				}
@@ -163,8 +169,8 @@
 	}
 	INIT_HLIST_NODE(&kip->hlist);
 	hlist_add_head(&kip->hlist, &kprobe_insn_pages);
-	memset(kip->slot_used, 0, INSNS_PER_PAGE);
-	kip->slot_used[0] = 1;
+	memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
+	kip->slot_used[0] = SLOT_USED;
 	kip->nused = 1;
 	kip->ngarbage = 0;
 	return kip->insns;
@@ -173,7 +179,7 @@
 /* Return 1 if all garbages are collected, otherwise 0. */
 static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
 {
-	kip->slot_used[idx] = 0;
+	kip->slot_used[idx] = SLOT_CLEAN;
 	kip->nused--;
 	if (kip->nused == 0) {
 		/*
@@ -212,7 +218,7 @@
 			continue;
 		kip->ngarbage = 0;	/* we will collect all garbages */
 		for (i = 0; i < INSNS_PER_PAGE; i++) {
-			if (kip->slot_used[i] == -1 &&
+			if (kip->slot_used[i] == SLOT_DIRTY &&
 			    collect_one_slot(kip, i))
 				break;
 		}
@@ -232,7 +238,7 @@
 		    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
 			int i = (slot - kip->insns) / MAX_INSN_SIZE;
 			if (dirty) {
-				kip->slot_used[i] = -1;
+				kip->slot_used[i] = SLOT_DIRTY;
 				kip->ngarbage++;
 			} else {
 				collect_one_slot(kip, i);
diff --git a/kernel/pid.c b/kernel/pid.c
index 2efe9d8..78f2aee 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -197,7 +197,7 @@
 	hlist_del_rcu(&pid->pid_chain);
 	spin_unlock_irqrestore(&pidmap_lock, flags);
 
-	free_pidmap(current->nsproxy->pid_ns, pid->nr);
+	free_pidmap(&init_pid_ns, pid->nr);
 	call_rcu(&pid->rcu, delayed_put_pid);
 }
 
diff --git a/kernel/profile.c b/kernel/profile.c
index 11550b2..d6579d5 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -40,7 +40,10 @@
 
 static atomic_t *prof_buffer;
 static unsigned long prof_len, prof_shift;
+
 int prof_on __read_mostly;
+EXPORT_SYMBOL_GPL(prof_on);
+
 static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -52,6 +55,7 @@
 {
 	static char __initdata schedstr[] = "schedule";
 	static char __initdata sleepstr[] = "sleep";
+	static char __initdata kvmstr[] = "kvm";
 	int par;
 
 	if (!strncmp(str, sleepstr, strlen(sleepstr))) {
@@ -72,6 +76,15 @@
 		printk(KERN_INFO
 			"kernel schedule profiling enabled (shift: %ld)\n",
 			prof_shift);
+	} else if (!strncmp(str, kvmstr, strlen(kvmstr))) {
+		prof_on = KVM_PROFILING;
+		if (str[strlen(kvmstr)] == ',')
+			str += strlen(kvmstr) + 1;
+		if (get_option(&str, &par))
+			prof_shift = par;
+		printk(KERN_INFO
+			"kernel KVM profiling enabled (shift: %ld)\n",
+			prof_shift);
 	} else if (get_option(&str, &par)) {
 		prof_shift = par;
 		prof_on = CPU_PROFILING;
@@ -387,6 +400,8 @@
 }
 #endif /* !CONFIG_SMP */
 
+EXPORT_SYMBOL_GPL(profile_hits);
+
 void profile_tick(int type)
 {
 	struct pt_regs *regs = get_irq_regs();
diff --git a/kernel/sched.c b/kernel/sched.c
index 3df33da..cca93cc 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6865,7 +6865,7 @@
 
 	lock_cpu_hotplug();
 	arch_init_sched_domains(&cpu_online_map);
-	cpus_andnot(non_isolated_cpus, cpu_online_map, cpu_isolated_map);
+	cpus_andnot(non_isolated_cpus, cpu_possible_map, cpu_isolated_map);
 	if (cpus_empty(non_isolated_cpus))
 		cpu_set(smp_processor_id(), non_isolated_cpus);
 	unlock_cpu_hotplug();
diff --git a/kernel/sys.c b/kernel/sys.c
index c7675c1..6e2101d 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -323,11 +323,18 @@
 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
 		unsigned long val, void *v)
 {
-	int ret;
+	int ret = NOTIFY_DONE;
 
-	down_read(&nh->rwsem);
-	ret = notifier_call_chain(&nh->head, val, v);
-	up_read(&nh->rwsem);
+	/*
+	 * We check the head outside the lock, but if this access is
+	 * racy then it does not matter what the result of the test
+	 * is, we re-check the list after having taken the lock anyway:
+	 */
+	if (rcu_dereference(nh->head)) {
+		down_read(&nh->rwsem);
+		ret = notifier_call_chain(&nh->head, val, v);
+		up_read(&nh->rwsem);
+	}
 	return ret;
 }
 
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1062578..50a4380 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -1,7 +1,7 @@
 /*
  * Dynamic DMA mapping support.
  *
- * This implementation is for IA-64 and EM64T platforms that do not support
+ * This implementation is a fallback for platforms that do not support
  * I/O TLBs (aka DMA address translation hardware).
  * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com>
  * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com>
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/scatterlist.h>
+#include <asm/swiotlb.h>
 
 #include <linux/init.h>
 #include <linux/bootmem.h>
@@ -35,8 +36,10 @@
 #define OFFSET(val,align) ((unsigned long)	\
 	                   ( (val) & ( (align) - 1)))
 
+#ifndef SG_ENT_VIRT_ADDRESS
 #define SG_ENT_VIRT_ADDRESS(sg)	(page_address((sg)->page) + (sg)->offset)
-#define SG_ENT_PHYS_ADDRESS(SG)	virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
+#define SG_ENT_PHYS_ADDRESS(sg)	virt_to_bus(SG_ENT_VIRT_ADDRESS(sg))
+#endif
 
 /*
  * Maximum allowable number of contiguous slabs to map,
@@ -101,13 +104,25 @@
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
  */
-static unsigned char **io_tlb_orig_addr;
+#ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T
+typedef char *io_tlb_addr_t;
+#define swiotlb_orig_addr_null(buffer) (!(buffer))
+#define ptr_to_io_tlb_addr(ptr) (ptr)
+#define page_to_io_tlb_addr(pg, off) (page_address(pg) + (off))
+#define sg_to_io_tlb_addr(sg) SG_ENT_VIRT_ADDRESS(sg)
+#endif
+static io_tlb_addr_t *io_tlb_orig_addr;
 
 /*
  * Protect the above data structures in the map and unmap calls
  */
 static DEFINE_SPINLOCK(io_tlb_lock);
 
+#ifdef SWIOTLB_EXTRA_VARIABLES
+SWIOTLB_EXTRA_VARIABLES;
+#endif
+
+#ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES
 static int __init
 setup_io_tlb_npages(char *str)
 {
@@ -122,30 +137,50 @@
 		swiotlb_force = 1;
 	return 1;
 }
+#endif
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+#ifndef swiotlb_adjust_size
+#define swiotlb_adjust_size(size) ((void)0)
+#endif
+
+#ifndef swiotlb_adjust_seg
+#define swiotlb_adjust_seg(start, size) ((void)0)
+#endif
+
+#ifndef swiotlb_print_info
+#define swiotlb_print_info(bytes) \
+	printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " \
+	       "0x%lx\n", bytes >> 20, \
+	       virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end))
+#endif
+
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data
  * structures for the software IO TLB used to implement the DMA API.
  */
-void
-swiotlb_init_with_default_size (size_t default_size)
+void __init
+swiotlb_init_with_default_size(size_t default_size)
 {
-	unsigned long i;
+	unsigned long i, bytes;
 
 	if (!io_tlb_nslabs) {
 		io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
 		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
 	}
+	swiotlb_adjust_size(io_tlb_nslabs);
+	swiotlb_adjust_size(io_tlb_overflow);
+
+	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
 	/*
 	 * Get IO TLB memory from the low pages
 	 */
-	io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+	io_tlb_start = alloc_bootmem_low_pages(bytes);
 	if (!io_tlb_start)
 		panic("Cannot allocate SWIOTLB buffer");
-	io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
+	io_tlb_end = io_tlb_start + bytes;
 
 	/*
 	 * Allocate and initialize the free list array.  This array is used
@@ -153,34 +188,45 @@
 	 * between io_tlb_start and io_tlb_end.
 	 */
 	io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
-	for (i = 0; i < io_tlb_nslabs; i++)
+	for (i = 0; i < io_tlb_nslabs; i++) {
+		if ( !(i % IO_TLB_SEGSIZE) )
+			swiotlb_adjust_seg(io_tlb_start + (i << IO_TLB_SHIFT),
+				IO_TLB_SEGSIZE << IO_TLB_SHIFT);
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
+ 	}
 	io_tlb_index = 0;
-	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
+	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(io_tlb_addr_t));
 
 	/*
 	 * Get the overflow emergency buffer
 	 */
 	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
-	printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
-	       virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
-}
+	if (!io_tlb_overflow_buffer)
+		panic("Cannot allocate SWIOTLB overflow buffer!\n");
+	swiotlb_adjust_seg(io_tlb_overflow_buffer, io_tlb_overflow);
 
-void
-swiotlb_init (void)
+	swiotlb_print_info(bytes);
+}
+#ifndef __swiotlb_init_with_default_size
+#define __swiotlb_init_with_default_size swiotlb_init_with_default_size
+#endif
+
+void __init
+swiotlb_init(void)
 {
-	swiotlb_init_with_default_size(64 * (1<<20));	/* default to 64MB */
+	__swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */
 }
 
+#ifdef SWIOTLB_ARCH_NEED_LATE_INIT
 /*
  * Systems with larger DMA zones (those that don't support ISA) can
  * initialize the swiotlb later using the slab allocator if needed.
  * This should be just like above, but with some error catching.
  */
 int
-swiotlb_late_init_with_default_size (size_t default_size)
+swiotlb_late_init_with_default_size(size_t default_size)
 {
-	unsigned long i, req_nslabs = io_tlb_nslabs;
+	unsigned long i, bytes, req_nslabs = io_tlb_nslabs;
 	unsigned int order;
 
 	if (!io_tlb_nslabs) {
@@ -191,8 +237,9 @@
 	/*
 	 * Get IO TLB memory from the low pages
 	 */
-	order = get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+	order = get_order(io_tlb_nslabs << IO_TLB_SHIFT);
 	io_tlb_nslabs = SLABS_PER_PAGE << order;
+	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
 	while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
 		io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
@@ -205,13 +252,14 @@
 	if (!io_tlb_start)
 		goto cleanup1;
 
-	if (order != get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT))) {
+	if (order != get_order(bytes)) {
 		printk(KERN_WARNING "Warning: only able to allocate %ld MB "
 		       "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
 		io_tlb_nslabs = SLABS_PER_PAGE << order;
+		bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 	}
-	io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
-	memset(io_tlb_start, 0, io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+	io_tlb_end = io_tlb_start + bytes;
+	memset(io_tlb_start, 0, bytes);
 
 	/*
 	 * Allocate and initialize the free list array.  This array is used
@@ -227,12 +275,12 @@
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
 
-	io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
-	                           get_order(io_tlb_nslabs * sizeof(char *)));
+	io_tlb_orig_addr = (io_tlb_addr_t *)__get_free_pages(GFP_KERNEL,
+	                           get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t)));
 	if (!io_tlb_orig_addr)
 		goto cleanup3;
 
-	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
+	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(io_tlb_addr_t));
 
 	/*
 	 * Get the overflow emergency buffer
@@ -242,29 +290,29 @@
 	if (!io_tlb_overflow_buffer)
 		goto cleanup4;
 
-	printk(KERN_INFO "Placing %ldMB software IO TLB between 0x%lx - "
-	       "0x%lx\n", (io_tlb_nslabs * (1 << IO_TLB_SHIFT)) >> 20,
-	       virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
+	swiotlb_print_info(bytes);
 
 	return 0;
 
 cleanup4:
-	free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs *
-	                                                      sizeof(char *)));
+	free_pages((unsigned long)io_tlb_orig_addr,
+		   get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t)));
 	io_tlb_orig_addr = NULL;
 cleanup3:
-	free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
-	                                                 sizeof(int)));
+	free_pages((unsigned long)io_tlb_list,
+		   get_order(io_tlb_nslabs * sizeof(int)));
 	io_tlb_list = NULL;
-	io_tlb_end = NULL;
 cleanup2:
+	io_tlb_end = NULL;
 	free_pages((unsigned long)io_tlb_start, order);
 	io_tlb_start = NULL;
 cleanup1:
 	io_tlb_nslabs = req_nslabs;
 	return -ENOMEM;
 }
+#endif
 
+#ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING
 static inline int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
@@ -275,11 +323,35 @@
 	return (addr & ~mask) != 0;
 }
 
+static inline int range_needs_mapping(const void *ptr, size_t size)
+{
+	return swiotlb_force;
+}
+
+static inline int order_needs_mapping(unsigned int order)
+{
+	return 0;
+}
+#endif
+
+static void
+__sync_single(io_tlb_addr_t buffer, char *dma_addr, size_t size, int dir)
+{
+#ifndef SWIOTLB_ARCH_HAS_SYNC_SINGLE
+	if (dir == DMA_TO_DEVICE)
+		memcpy(dma_addr, buffer, size);
+	else
+		memcpy(buffer, dma_addr, size);
+#else
+	__swiotlb_arch_sync_single(buffer, dma_addr, size, dir);
+#endif
+}
+
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
-map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir)
 {
 	unsigned long flags;
 	char *dma_addr;
@@ -352,7 +424,7 @@
 	 */
 	io_tlb_orig_addr[index] = buffer;
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-		memcpy(dma_addr, buffer, size);
+		__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
 
 	return dma_addr;
 }
@@ -366,17 +438,18 @@
 	unsigned long flags;
 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	char *buffer = io_tlb_orig_addr[index];
+	io_tlb_addr_t buffer = io_tlb_orig_addr[index];
 
 	/*
 	 * First, sync the memory before unmapping the entry
 	 */
-	if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
+	if (!swiotlb_orig_addr_null(buffer)
+	    && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
 		/*
 		 * bounce... copy the data back into the original buffer * and
 		 * delete the bounce buffer.
 		 */
-		memcpy(buffer, dma_addr, size);
+		__sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
 
 	/*
 	 * Return the buffer to the free list by setting the corresponding
@@ -409,18 +482,18 @@
 	    int dir, int target)
 {
 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	char *buffer = io_tlb_orig_addr[index];
+	io_tlb_addr_t buffer = io_tlb_orig_addr[index];
 
 	switch (target) {
 	case SYNC_FOR_CPU:
 		if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-			memcpy(buffer, dma_addr, size);
+			__sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
 		else
 			BUG_ON(dir != DMA_TO_DEVICE);
 		break;
 	case SYNC_FOR_DEVICE:
 		if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-			memcpy(dma_addr, buffer, size);
+			__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
 		else
 			BUG_ON(dir != DMA_FROM_DEVICE);
 		break;
@@ -429,11 +502,13 @@
 	}
 }
 
+#ifdef SWIOTLB_ARCH_NEED_ALLOC
+
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 		       dma_addr_t *dma_handle, gfp_t flags)
 {
-	unsigned long dev_addr;
+	dma_addr_t dev_addr;
 	void *ret;
 	int order = get_order(size);
 
@@ -444,8 +519,11 @@
 	 */
 	flags |= GFP_DMA;
 
-	ret = (void *)__get_free_pages(flags, order);
-	if (ret && address_needs_mapping(hwdev, virt_to_phys(ret))) {
+	if (!order_needs_mapping(order))
+		ret = (void *)__get_free_pages(flags, order);
+	else
+		ret = NULL;
+	if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) {
 		/*
 		 * The allocated memory isn't reachable by the device.
 		 * Fall back on swiotlb_map_single().
@@ -465,22 +543,24 @@
 		if (swiotlb_dma_mapping_error(handle))
 			return NULL;
 
-		ret = phys_to_virt(handle);
+		ret = bus_to_virt(handle);
 	}
 
 	memset(ret, 0, size);
-	dev_addr = virt_to_phys(ret);
+	dev_addr = virt_to_bus(ret);
 
 	/* Confirm address can be DMA'd by device */
 	if (address_needs_mapping(hwdev, dev_addr)) {
-		printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016lx\n",
-		       (unsigned long long)*hwdev->dma_mask, dev_addr);
+		printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+		       (unsigned long long)*hwdev->dma_mask,
+		       (unsigned long long)dev_addr);
 		panic("swiotlb_alloc_coherent: allocated memory is out of "
 		      "range for device");
 	}
 	*dma_handle = dev_addr;
 	return ret;
 }
+EXPORT_SYMBOL(swiotlb_alloc_coherent);
 
 void
 swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
@@ -493,6 +573,9 @@
 		/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
 		swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE);
 }
+EXPORT_SYMBOL(swiotlb_free_coherent);
+
+#endif
 
 static void
 swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
@@ -504,7 +587,7 @@
 	 * When the mapping is small enough return a static buffer to limit
 	 * the damage, or panic when the transfer is too big.
 	 */
-	printk(KERN_ERR "DMA: Out of SW-IOMMU space for %lu bytes at "
+	printk(KERN_ERR "DMA: Out of SW-IOMMU space for %zu bytes at "
 	       "device %s\n", size, dev ? dev->bus_id : "?");
 
 	if (size > io_tlb_overflow && do_panic) {
@@ -525,7 +608,7 @@
 dma_addr_t
 swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
 {
-	unsigned long dev_addr = virt_to_phys(ptr);
+	dma_addr_t dev_addr = virt_to_bus(ptr);
 	void *map;
 
 	BUG_ON(dir == DMA_NONE);
@@ -534,19 +617,20 @@
 	 * we can safely return the device addr and not worry about bounce
 	 * buffering it.
 	 */
-	if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force)
+	if (!range_needs_mapping(ptr, size)
+	    && !address_needs_mapping(hwdev, dev_addr))
 		return dev_addr;
 
 	/*
 	 * Oh well, have to allocate and map a bounce buffer.
 	 */
-	map = map_single(hwdev, ptr, size, dir);
+	map = map_single(hwdev, ptr_to_io_tlb_addr(ptr), size, dir);
 	if (!map) {
 		swiotlb_full(hwdev, size, dir, 1);
 		map = io_tlb_overflow_buffer;
 	}
 
-	dev_addr = virt_to_phys(map);
+	dev_addr = virt_to_bus(map);
 
 	/*
 	 * Ensure that the address returned is DMA'ble
@@ -558,25 +642,6 @@
 }
 
 /*
- * Since DMA is i-cache coherent, any (complete) pages that were written via
- * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
- * flush them when they get mapped into an executable vm-area.
- */
-static void
-mark_clean(void *addr, size_t size)
-{
-	unsigned long pg_addr, end;
-
-	pg_addr = PAGE_ALIGN((unsigned long) addr);
-	end = (unsigned long) addr + size;
-	while (pg_addr + PAGE_SIZE <= end) {
-		struct page *page = virt_to_page(pg_addr);
-		set_bit(PG_arch_1, &page->flags);
-		pg_addr += PAGE_SIZE;
-	}
-}
-
-/*
  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
  * match what was provided for in a previous swiotlb_map_single call.  All
  * other usages are undefined.
@@ -588,13 +653,13 @@
 swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
 		     int dir)
 {
-	char *dma_addr = phys_to_virt(dev_addr);
+	char *dma_addr = bus_to_virt(dev_addr);
 
 	BUG_ON(dir == DMA_NONE);
 	if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
 		unmap_single(hwdev, dma_addr, size, dir);
 	else if (dir == DMA_FROM_DEVICE)
-		mark_clean(dma_addr, size);
+		dma_mark_clean(dma_addr, size);
 }
 
 /*
@@ -611,13 +676,13 @@
 swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 		    size_t size, int dir, int target)
 {
-	char *dma_addr = phys_to_virt(dev_addr);
+	char *dma_addr = bus_to_virt(dev_addr);
 
 	BUG_ON(dir == DMA_NONE);
 	if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
 		sync_single(hwdev, dma_addr, size, dir, target);
 	else if (dir == DMA_FROM_DEVICE)
-		mark_clean(dma_addr, size);
+		dma_mark_clean(dma_addr, size);
 }
 
 void
@@ -642,13 +707,13 @@
 			  unsigned long offset, size_t size,
 			  int dir, int target)
 {
-	char *dma_addr = phys_to_virt(dev_addr) + offset;
+	char *dma_addr = bus_to_virt(dev_addr) + offset;
 
 	BUG_ON(dir == DMA_NONE);
 	if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
 		sync_single(hwdev, dma_addr, size, dir, target);
 	else if (dir == DMA_FROM_DEVICE)
-		mark_clean(dma_addr, size);
+		dma_mark_clean(dma_addr, size);
 }
 
 void
@@ -687,18 +752,16 @@
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
 	       int dir)
 {
-	void *addr;
-	unsigned long dev_addr;
+	dma_addr_t dev_addr;
 	int i;
 
 	BUG_ON(dir == DMA_NONE);
 
 	for (i = 0; i < nelems; i++, sg++) {
-		addr = SG_ENT_VIRT_ADDRESS(sg);
-		dev_addr = virt_to_phys(addr);
-		if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
-			void *map = map_single(hwdev, addr, sg->length, dir);
-			sg->dma_address = virt_to_bus(map);
+		dev_addr = SG_ENT_PHYS_ADDRESS(sg);
+		if (range_needs_mapping(SG_ENT_VIRT_ADDRESS(sg), sg->length)
+		    || address_needs_mapping(hwdev, dev_addr)) {
+			void *map = map_single(hwdev, sg_to_io_tlb_addr(sg), sg->length, dir);
 			if (!map) {
 				/* Don't panic here, we expect map_sg users
 				   to do proper error handling. */
@@ -707,6 +770,7 @@
 				sg[0].dma_length = 0;
 				return 0;
 			}
+			sg->dma_address = virt_to_bus(map);
 		} else
 			sg->dma_address = dev_addr;
 		sg->dma_length = sg->length;
@@ -728,9 +792,10 @@
 
 	for (i = 0; i < nelems; i++, sg++)
 		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-			unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir);
+			unmap_single(hwdev, bus_to_virt(sg->dma_address),
+				     sg->dma_length, dir);
 		else if (dir == DMA_FROM_DEVICE)
-			mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
 
 /*
@@ -750,8 +815,10 @@
 
 	for (i = 0; i < nelems; i++, sg++)
 		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-			sync_single(hwdev, (void *) sg->dma_address,
+			sync_single(hwdev, bus_to_virt(sg->dma_address),
 				    sg->dma_length, dir, target);
+		else if (dir == DMA_FROM_DEVICE)
+			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
 
 void
@@ -768,10 +835,48 @@
 	swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE);
 }
 
+#ifdef SWIOTLB_ARCH_NEED_MAP_PAGE
+
+dma_addr_t
+swiotlb_map_page(struct device *hwdev, struct page *page,
+		 unsigned long offset, size_t size,
+		 enum dma_data_direction direction)
+{
+	dma_addr_t dev_addr;
+	char *map;
+
+	dev_addr = page_to_bus(page) + offset;
+	if (address_needs_mapping(hwdev, dev_addr)) {
+		map = map_single(hwdev, page_to_io_tlb_addr(page, offset), size, direction);
+		if (!map) {
+			swiotlb_full(hwdev, size, direction, 1);
+			map = io_tlb_overflow_buffer;
+		}
+		dev_addr = virt_to_bus(map);
+	}
+
+	return dev_addr;
+}
+
+void
+swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
+		   size_t size, enum dma_data_direction direction)
+{
+	char *dma_addr = bus_to_virt(dev_addr);
+
+	BUG_ON(direction == DMA_NONE);
+	if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
+		unmap_single(hwdev, dma_addr, size, direction);
+	else if (direction == DMA_FROM_DEVICE)
+		dma_mark_clean(dma_addr, size);
+}
+
+#endif
+
 int
 swiotlb_dma_mapping_error(dma_addr_t dma_addr)
 {
-	return (dma_addr == virt_to_phys(io_tlb_overflow_buffer));
+	return (dma_addr == virt_to_bus(io_tlb_overflow_buffer));
 }
 
 /*
@@ -780,10 +885,13 @@
  * during bus mastering, then you would pass 0x00ffffff as the mask to
  * this function.
  */
+#ifndef __swiotlb_dma_supported
+#define __swiotlb_dma_supported(hwdev, mask) (virt_to_bus(io_tlb_end - 1) <= (mask))
+#endif
 int
-swiotlb_dma_supported (struct device *hwdev, u64 mask)
+swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return (virt_to_phys (io_tlb_end) - 1) <= mask;
+	return __swiotlb_dma_supported(hwdev, mask);
 }
 
 EXPORT_SYMBOL(swiotlb_init);
@@ -798,6 +906,4 @@
 EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
 EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
-EXPORT_SYMBOL(swiotlb_alloc_coherent);
-EXPORT_SYMBOL(swiotlb_free_coherent);
 EXPORT_SYMBOL(swiotlb_dma_supported);
diff --git a/mm/bounce.c b/mm/bounce.c
index e4b62d2..643efbe 100644
--- a/mm/bounce.c
+++ b/mm/bounce.c
@@ -237,6 +237,8 @@
 	if (!bio)
 		return;
 
+	blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE);
+
 	/*
 	 * at least one page was bounced, fill in possible non-highmem
 	 * pages
@@ -291,8 +293,6 @@
 		pool = isa_page_pool;
 	}
 
-	blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE);
-
 	/*
 	 * slow path
 	 */
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 45b3553..9dd9fbb 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -183,7 +183,7 @@
 		address = vma->vm_start +
 			((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
 		BUG_ON(address < vma->vm_start || address >= vma->vm_end);
-		page = ZERO_PAGE(address);
+		page = ZERO_PAGE(0);
 		pte = page_check_address(page, mm, address, &ptl);
 		if (pte) {
 			/* Nuke the page table entry. */
@@ -246,7 +246,7 @@
 		__xip_unmap(mapping, pgoff);
 	} else {
 		/* not shared and writable, use ZERO_PAGE() */
-		page = ZERO_PAGE(address);
+		page = ZERO_PAGE(0);
 	}
 
 out:
diff --git a/mm/memory.c b/mm/memory.c
index af227d2..ef09f0a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2606,8 +2606,15 @@
 	gate_vma.vm_mm = NULL;
 	gate_vma.vm_start = FIXADDR_USER_START;
 	gate_vma.vm_end = FIXADDR_USER_END;
-	gate_vma.vm_page_prot = PAGE_READONLY;
-	gate_vma.vm_flags = 0;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	gate_vma.vm_flags |= VM_ALWAYSDUMP;
 	return 0;
 }
 __initcall(gate_vma_init);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 0c055a09..8427912 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -67,11 +67,13 @@
 	zone_type = zone - pgdat->node_zones;
 	if (!populated_zone(zone)) {
 		int ret = 0;
-		ret = init_currently_empty_zone(zone, phys_start_pfn, nr_pages);
+		ret = init_currently_empty_zone(zone, phys_start_pfn,
+						nr_pages, MEMMAP_HOTPLUG);
 		if (ret < 0)
 			return ret;
 	}
-	memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn);
+	memmap_init_zone(nr_pages, nid, zone_type,
+			 phys_start_pfn, MEMMAP_HOTPLUG);
 	return 0;
 }
 
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index da94639..c2aec0e 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -884,6 +884,10 @@
 	err = get_nodes(&nodes, nmask, maxnode);
 	if (err)
 		return err;
+#ifdef CONFIG_CPUSETS
+	/* Restrict the nodes to the allowed nodes in the cpuset */
+	nodes_and(nodes, nodes, current->mems_allowed);
+#endif
 	return do_mbind(start, len, mode, &nodes, flags);
 }
 
diff --git a/mm/mmap.c b/mm/mmap.c
index 9717337..cc3a208 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1477,6 +1477,7 @@
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct rlimit *rlim = current->signal->rlim;
+	unsigned long new_start;
 
 	/* address space limit tests */
 	if (!may_expand_vm(mm, grow))
@@ -1496,6 +1497,12 @@
 			return -ENOMEM;
 	}
 
+	/* Check to ensure the stack will not grow into a hugetlb-only region */
+	new_start = (vma->vm_flags & VM_GROWSUP) ? vma->vm_start :
+			vma->vm_end - size;
+	if (is_hugepage_only_range(vma->vm_mm, new_start, size))
+		return -EFAULT;
+
 	/*
 	 * Overcommit..  This must be the final test, as it will
 	 * update security statistics.
diff --git a/mm/mremap.c b/mm/mremap.c
index 9c769fa..5d4bd4f 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -105,7 +105,6 @@
 		if (pte_none(*old_pte))
 			continue;
 		pte = ptep_clear_flush(vma, old_addr, old_pte);
-		/* ZERO_PAGE can be dependant on virtual addr */
 		pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
 		set_pte_at(mm, new_addr, new_pte, pte);
 	}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 1d2fc89..be0efbd 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -133,11 +133,9 @@
 
 #ifdef CONFIG_HIGHMEM
 	/*
-	 * If this mapping can only allocate from low memory,
-	 * we exclude high memory from our count.
+	 * We always exclude high memory from our count.
 	 */
-	if (mapping && !(mapping_gfp_mask(mapping) & __GFP_HIGHMEM))
-		available_memory -= totalhigh_pages;
+	available_memory -= totalhigh_pages;
 #endif
 
 
@@ -526,28 +524,25 @@
 };
 
 /*
- * If the machine has a large highmem:lowmem ratio then scale back the default
- * dirty memory thresholds: allowing too much dirty highmem pins an excessive
- * number of buffer_heads.
+ * Called early on to tune the page writeback dirty limits.
+ *
+ * We used to scale dirty pages according to how total memory
+ * related to pages that could be allocated for buffers (by
+ * comparing nr_free_buffer_pages() to vm_total_pages.
+ *
+ * However, that was when we used "dirty_ratio" to scale with
+ * all memory, and we don't do that any more. "dirty_ratio"
+ * is now applied to total non-HIGHPAGE memory (by subtracting
+ * totalhigh_pages from vm_total_pages), and as such we can't
+ * get into the old insane situation any more where we had
+ * large amounts of dirty pages compared to a small amount of
+ * non-HIGHMEM memory.
+ *
+ * But we might still want to scale the dirty_ratio by how
+ * much memory the box has..
  */
 void __init page_writeback_init(void)
 {
-	long buffer_pages = nr_free_buffer_pages();
-	long correction;
-
-	correction = (100 * 4 * buffer_pages) / vm_total_pages;
-
-	if (correction < 100) {
-		dirty_background_ratio *= correction;
-		dirty_background_ratio /= 100;
-		vm_dirty_ratio *= correction;
-		vm_dirty_ratio /= 100;
-
-		if (dirty_background_ratio <= 0)
-			dirty_background_ratio = 1;
-		if (vm_dirty_ratio <= 0)
-			vm_dirty_ratio = 1;
-	}
 	mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
 	writeback_set_ratelimit();
 	register_cpu_notifier(&ratelimit_nb);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a49f96b..2c606cc 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -989,8 +989,7 @@
 		      int classzone_idx, int alloc_flags)
 {
 	/* free_pages my go negative - that's OK */
-	unsigned long min = mark;
-	long free_pages = z->free_pages - (1 << order) + 1;
+	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
 	int o;
 
 	if (alloc_flags & ALLOC_HIGH)
@@ -1956,17 +1955,24 @@
  * done. Non-atomic initialization, single-pass.
  */
 void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
-		unsigned long start_pfn)
+		unsigned long start_pfn, enum memmap_context context)
 {
 	struct page *page;
 	unsigned long end_pfn = start_pfn + size;
 	unsigned long pfn;
 
 	for (pfn = start_pfn; pfn < end_pfn; pfn++) {
-		if (!early_pfn_valid(pfn))
-			continue;
-		if (!early_pfn_in_nid(pfn, nid))
-			continue;
+		/*
+		 * There can be holes in boot-time mem_map[]s
+		 * handed to this function.  They do not
+		 * exist on hotplugged memory.
+		 */
+		if (context == MEMMAP_EARLY) {
+			if (!early_pfn_valid(pfn))
+				continue;
+			if (!early_pfn_in_nid(pfn, nid))
+				continue;
+		}
 		page = pfn_to_page(pfn);
 		set_page_links(page, zone, nid, pfn);
 		init_page_count(page);
@@ -1993,7 +1999,7 @@
 
 #ifndef __HAVE_ARCH_MEMMAP_INIT
 #define memmap_init(size, nid, zone, start_pfn) \
-	memmap_init_zone((size), (nid), (zone), (start_pfn))
+	memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
 #endif
 
 static int __cpuinit zone_batchsize(struct zone *zone)
@@ -2239,7 +2245,8 @@
 
 __meminit int init_currently_empty_zone(struct zone *zone,
 					unsigned long zone_start_pfn,
-					unsigned long size)
+					unsigned long size,
+					enum memmap_context context)
 {
 	struct pglist_data *pgdat = zone->zone_pgdat;
 	int ret;
@@ -2683,7 +2690,8 @@
 		if (!size)
 			continue;
 
-		ret = init_currently_empty_zone(zone, zone_start_pfn, size);
+		ret = init_currently_empty_zone(zone, zone_start_pfn,
+						size, MEMMAP_EARLY);
 		BUG_ON(ret);
 		zone_start_pfn += size;
 	}
diff --git a/mm/truncate.c b/mm/truncate.c
index ecdfdcc..5df947d 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -51,15 +51,22 @@
 		do_invalidatepage(page, partial);
 }
 
+/*
+ * This cancels just the dirty bit on the kernel page itself, it
+ * does NOT actually remove dirty bits on any mmap's that may be
+ * around. It also leaves the page tagged dirty, so any sync
+ * activity will still find it on the dirty lists, and in particular,
+ * clear_page_dirty_for_io() will still look at the dirty bits in
+ * the VM.
+ *
+ * Doing this should *normally* only ever be done when a page
+ * is truncated, and is not actually mapped anywhere at all. However,
+ * fs/buffer.c does this when it notices that somebody has cleaned
+ * out all the buffers on a page without actually doing it through
+ * the VM. Can you say "ext3 is horribly ugly"? Tought you could.
+ */
 void cancel_dirty_page(struct page *page, unsigned int account_size)
 {
-	/* If we're cancelling the page, it had better not be mapped any more */
-	if (page_mapped(page)) {
-		static unsigned int warncount;
-
-		WARN_ON(++warncount < 5);
-	}
-		
 	if (TestClearPageDirty(page)) {
 		struct address_space *mapping = page->mapping;
 		if (mapping && mapping_cap_account_dirty(mapping)) {
@@ -341,6 +348,15 @@
 	return 0;
 }
 
+static int do_launder_page(struct address_space *mapping, struct page *page)
+{
+	if (!PageDirty(page))
+		return 0;
+	if (page->mapping != mapping || mapping->a_ops->launder_page == NULL)
+		return 0;
+	return mapping->a_ops->launder_page(page);
+}
+
 /**
  * invalidate_inode_pages2_range - remove range of pages from an address_space
  * @mapping: the address_space
@@ -405,14 +421,14 @@
 					  PAGE_CACHE_SIZE, 0);
 				}
 			}
-			if (!invalidate_complete_page2(mapping, page))
+			ret = do_launder_page(mapping, page);
+			if (ret == 0 && !invalidate_complete_page2(mapping, page))
 				ret = -EIO;
 			unlock_page(page);
 		}
 		pagevec_release(&pvec);
 		cond_resched();
 	}
-	WARN_ON_ONCE(ret);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index be04e9f..ab166b4 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -196,6 +196,9 @@
 
 	switch (CAPIMSG_SUBCOMMAND(skb->data)) {
 	case CAPI_CONF:
+		if (skb->len < CAPI_MSG_BASELEN + 10)
+			break;
+
 		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
 		info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
 
@@ -226,6 +229,9 @@
 			break;
 
 		case CAPI_FUNCTION_GET_PROFILE:
+			if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
+				break;
+
 			controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
 			msgnum = CAPIMSG_MSGID(skb->data);
 
@@ -246,17 +252,26 @@
 			break;
 
 		case CAPI_FUNCTION_GET_MANUFACTURER:
+			if (skb->len < CAPI_MSG_BASELEN + 15)
+				break;
+
 			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
 
 			if (!info && ctrl) {
+				int len = min_t(uint, CAPI_MANUFACTURER_LEN,
+						skb->data[CAPI_MSG_BASELEN + 14]);
+
+				memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
 				strncpy(ctrl->manu,
-					skb->data + CAPI_MSG_BASELEN + 15,
-					skb->data[CAPI_MSG_BASELEN + 14]);
+					skb->data + CAPI_MSG_BASELEN + 15, len);
 			}
 
 			break;
 
 		case CAPI_FUNCTION_GET_VERSION:
+			if (skb->len < CAPI_MSG_BASELEN + 32)
+				break;
+
 			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
 
 			if (!info && ctrl) {
@@ -269,13 +284,18 @@
 			break;
 
 		case CAPI_FUNCTION_GET_SERIAL_NUMBER:
+			if (skb->len < CAPI_MSG_BASELEN + 17)
+				break;
+
 			controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
 
 			if (!info && ctrl) {
+				int len = min_t(uint, CAPI_SERIAL_LEN,
+						skb->data[CAPI_MSG_BASELEN + 16]);
+
 				memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
 				strncpy(ctrl->serial,
-					skb->data + CAPI_MSG_BASELEN + 17,
-					skb->data[CAPI_MSG_BASELEN + 16]);
+					skb->data + CAPI_MSG_BASELEN + 17, len);
 			}
 
 			break;
@@ -284,14 +304,18 @@
 		break;
 
 	case CAPI_IND:
+		if (skb->len < CAPI_MSG_BASELEN + 6)
+			break;
+
 		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
 
 		if (func == CAPI_FUNCTION_LOOPBACK) {
+			int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
+						skb->data[CAPI_MSG_BASELEN + 5]);
 			appl = CAPIMSG_APPID(skb->data);
 			msgnum = CAPIMSG_MSGID(skb->data);
 			cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
-						skb->data + CAPI_MSG_BASELEN + 6,
-						skb->data[CAPI_MSG_BASELEN + 5]);
+						skb->data + CAPI_MSG_BASELEN + 6, len);
 		}
 
 		break;
@@ -309,6 +333,9 @@
 
 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
 
+	if (skb->len < CAPI_MSG_BASELEN)
+		return;
+
 	if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
 		cmtp_recv_interopmsg(session, skb);
 		return;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index d4c9356..801d687 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -242,7 +242,7 @@
 	struct hci_conn *conn = container_of(work, struct hci_conn, work);
 	int i;
 
-	if (device_register(&conn->dev) < 0) {
+	if (device_add(&conn->dev) < 0) {
 		BT_ERR("Failed to register connection device");
 		return;
 	}
@@ -272,6 +272,8 @@
 
 	dev_set_drvdata(&conn->dev, conn);
 
+	device_initialize(&conn->dev);
+
 	INIT_WORK(&conn->work, add_conn);
 
 	schedule_work(&conn->work);
@@ -287,6 +289,9 @@
 {
 	BT_DBG("conn %p", conn);
 
+	if (!device_is_registered(&conn->dev))
+		return;
+
 	INIT_WORK(&conn->work, del_conn);
 
 	schedule_work(&conn->work);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 29a8fa4..f8c25d5 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -585,6 +585,12 @@
 		goto done;
 	}
 
+	if (la->l2_psm > 0 && btohs(la->l2_psm) < 0x1001 &&
+				!capable(CAP_NET_BIND_SERVICE)) {
+		err = -EACCES;
+		goto done;
+	}
+		
 	write_lock_bh(&l2cap_sk_list.lock);
 
 	if (la->l2_psm && __l2cap_get_sock_by_addr(la->l2_psm, &la->l2_bdaddr)) {
@@ -2150,8 +2156,8 @@
 
 		str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n",
 				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
-				sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu,
-				pi->omtu, pi->link_mode);
+				sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid,
+				pi->imtu, pi->omtu, pi->link_mode);
 	}
 
 	read_unlock_bh(&l2cap_sk_list.lock);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 544d65b..cb7e855 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -557,7 +557,6 @@
 	struct sock *sk = sock->sk;
 	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
 	struct sk_buff *skb;
-	int err;
 	int sent = 0;
 
 	if (msg->msg_flags & MSG_OOB)
@@ -572,6 +571,7 @@
 
 	while (len) {
 		size_t size = min_t(size_t, len, d->mtu);
+		int err;
 		
 		skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
 				msg->msg_flags & MSG_DONTWAIT, &err);
@@ -582,13 +582,16 @@
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 		if (err) {
 			kfree_skb(skb);
-			sent = err;
+			if (sent == 0)
+				sent = err;
 			break;
 		}
 
 		err = rfcomm_dlc_send(d, skb);
 		if (err < 0) {
 			kfree_skb(skb);
+			if (sent == 0)
+				sent = err;
 			break;
 		}
 
@@ -598,7 +601,7 @@
 
 	release_sock(sk);
 
-	return sent ? sent : err;
+	return sent;
 }
 
 static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index e0e0d09..eb2b524 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -697,9 +697,13 @@
 
 	BT_DBG("tty %p", tty);
 
+	if (!dev || !dev->dlc)
+		return 0;
+
 	room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
 	if (room < 0)
 		room = 0;
+
 	return room;
 }
 
@@ -915,12 +919,14 @@
 static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
-	struct rfcomm_dlc *dlc = dev->dlc;
 
 	BT_DBG("tty %p dev %p", tty, dev);
 
-	if (!skb_queue_empty(&dlc->tx_queue))
-		return dlc->mtu;
+	if (!dev || !dev->dlc)
+		return 0;
+
+	if (!skb_queue_empty(&dev->dlc->tx_queue))
+		return dev->dlc->mtu;
 
 	return 0;
 }
@@ -928,11 +934,12 @@
 static void rfcomm_tty_flush_buffer(struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
-	if (!dev)
-		return;
 
 	BT_DBG("tty %p dev %p", tty, dev);
 
+	if (!dev || !dev->dlc)
+		return;
+
 	skb_queue_purge(&dev->dlc->tx_queue);
 
 	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
@@ -952,11 +959,12 @@
 static void rfcomm_tty_hangup(struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
-	if (!dev)
-		return;
 
 	BT_DBG("tty %p dev %p", tty, dev);
 
+	if (!dev)
+		return;
+
 	rfcomm_tty_flush_buffer(tty);
 
 	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
diff --git a/net/core/flow.c b/net/core/flow.c
index d137f97..5d25697 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -231,22 +231,16 @@
 
 		err = resolver(key, family, dir, &obj, &obj_ref);
 
-		if (fle) {
-			if (err) {
-				/* Force security policy check on next lookup */
-				*head = fle->next;
-				flow_entry_kill(cpu, fle);
-			} else {
-				fle->genid = atomic_read(&flow_cache_genid);
+		if (fle && !err) {
+			fle->genid = atomic_read(&flow_cache_genid);
 
-				if (fle->object)
-					atomic_dec(fle->object_ref);
+			if (fle->object)
+				atomic_dec(fle->object_ref);
 
-				fle->object = obj;
-				fle->object_ref = obj_ref;
-				if (obj)
-					atomic_inc(fle->object_ref);
-			}
+			fle->object = obj;
+			fle->object_ref = obj_ref;
+			if (obj)
+				atomic_inc(fle->object_ref);
 		}
 		local_bh_enable();
 
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 8245696..3435542 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -124,7 +124,7 @@
 		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
 
 		memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-		err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
+		err = icsk->icsk_af_ops->queue_xmit(skb, 0);
 		return net_xmit_eval(err);
 	}
 	return -ENOBUFS;
@@ -396,7 +396,7 @@
 						      code);
 		if (skb != NULL) {
 			memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-			err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0);
+			err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0);
 			return net_xmit_eval(err);
 		}
 	}
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index fc6f3c0..ed083ab 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -1145,16 +1145,23 @@
 	init_timer(&dn_db->timer);
 
 	dn_db->uptime = jiffies;
+
+	dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
+	if (!dn_db->neigh_parms) {
+		dev->dn_ptr = NULL;
+		kfree(dn_db);
+		return NULL;
+	}
+
 	if (dn_db->parms.up) {
 		if (dn_db->parms.up(dev) < 0) {
+			neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
 			dev->dn_ptr = NULL;
 			kfree(dn_db);
 			return NULL;
 		}
 	}
 
-	dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
-
 	dn_dev_sysctl_register(dev, &dn_db->parms);
 
 	dn_dev_set_timer(dev);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 1144900..8640096 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -305,7 +305,7 @@
 		sk->sk_reuse = 1;
 
 	inet = inet_sk(sk);
-	inet->is_icsk = INET_PROTOSW_ICSK & answer_flags;
+	inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
 
 	if (SOCK_RAW == sock->type) {
 		inet->num = protocol;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 25c8a42..480ace9 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -174,9 +174,10 @@
 	ip_mc_init_dev(in_dev);
 	if (dev->flags & IFF_UP)
 		ip_mc_up(in_dev);
-out:
+
 	/* we can receive as soon as ip_ptr is set -- do this last */
 	rcu_assign_pointer(dev->ip_ptr, in_dev);
+out:
 	return in_dev;
 out_kfree:
 	kfree(in_dev);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index cfb249c..1e589b9 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1989,6 +1989,10 @@
 	unsigned cindex = iter->index;
 	struct tnode *p;
 
+	/* A single entry routing table */
+	if (!tn)
+		return NULL;
+
 	pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
 		 iter->tnode, iter->index, iter->depth);
 rescan:
@@ -2037,11 +2041,18 @@
 	if(!iter)
 		return NULL;
 
-	if (n && IS_TNODE(n)) {
-		iter->tnode = (struct tnode *) n;
-		iter->trie = t;
-		iter->index = 0;
-		iter->depth = 1;
+	if (n) {
+		if (IS_TNODE(n)) {
+			iter->tnode = (struct tnode *) n;
+			iter->trie = t;
+			iter->index = 0;
+			iter->depth = 1;
+		} else {
+			iter->tnode = NULL;
+			iter->trie  = t;
+			iter->index = 0;
+			iter->depth = 0;
+		}
 		return n;
 	}
 	return NULL;
@@ -2279,16 +2290,17 @@
 	if (v == SEQ_START_TOKEN)
 		return 0;
 
+	if (!NODE_PARENT(n)) {
+		if (iter->trie == trie_local)
+			seq_puts(seq, "<local>:\n");
+		else
+			seq_puts(seq, "<main>:\n");
+	}
+
 	if (IS_TNODE(n)) {
 		struct tnode *tn = (struct tnode *) n;
 		__be32 prf = htonl(MASK_PFX(tn->key, tn->pos));
 
-		if (!NODE_PARENT(n)) {
-			if (iter->trie == trie_local)
-				seq_puts(seq, "<local>:\n");
-			else
-				seq_puts(seq, "<main>:\n");
-		} 
 		seq_indent(seq, iter->depth-1);
 		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",
 			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children, 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f071f84..a0f2008 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -281,8 +281,9 @@
 			    !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
 
-int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
+int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
 {
+	struct sock *sk = skb->sk;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ip_options *opt = inet->opt;
 	struct rtable *rt;
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 15e741a..16d177b 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -4,6 +4,14 @@
 
 # objects for the standalone - connection tracking / NAT
 ip_conntrack-objs	:= ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
+# objects for l3 independent conntrack
+nf_conntrack_ipv4-objs  :=  nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
+ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
+ifeq ($(CONFIG_PROC_FS),y)
+nf_conntrack_ipv4-objs	+= nf_conntrack_l3proto_ipv4_compat.o
+endif
+endif
+
 ip_nat-objs	:= ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
 nf_nat-objs	:= nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
 ifneq ($(CONFIG_NF_NAT),)
@@ -20,6 +28,8 @@
 
 # connection tracking
 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
+
 obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
 obj-$(CONFIG_NF_NAT) += nf_nat.o
 
@@ -106,13 +116,3 @@
 
 obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
 
-# objects for l3 independent conntrack
-nf_conntrack_ipv4-objs  :=  nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
-ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
-ifeq ($(CONFIG_PROC_FS),y)
-nf_conntrack_ipv4-objs	+= nf_conntrack_l3proto_ipv4_compat.o
-endif
-endif
-
-# l3 independent conntrack
-obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 5fcf91d..7f70b08 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -374,9 +374,11 @@
 		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
 		    	goto nfattr_failure;
 
+#ifdef CONFIG_IP_NF_CONNTRACK_MARK
 		if ((events & IPCT_MARK || ct->mark)
 		    && ctnetlink_dump_mark(skb, ct) < 0)
 		    	goto nfattr_failure;
+#endif
 
 		if (events & IPCT_COUNTER_FILLING &&
 		    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
@@ -959,7 +961,7 @@
 	if (cda[CTA_PROTOINFO-1]) {
 		err = ctnetlink_change_protoinfo(ct, cda);
 		if (err < 0)
-			return err;
+			goto err;
 	}
 
 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index 3a26d63..11c588a 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -283,10 +283,16 @@
 {
 	int s = *shift;
 
-	for (; dptr <= limit && *dptr != '@'; dptr++)
+	/* Search for @, but stop at the end of the line.
+	 * We are inside a sip: URI, so we don't need to worry about
+	 * continuation lines. */
+	while (dptr <= limit &&
+	       *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
 		(*shift)++;
+		dptr++;
+	}
 
-	if (*dptr == '@') {
+	if (dptr <= limit && *dptr == '@') {
 		dptr++;
 		(*shift)++;
 	} else
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 0ae45b7..5df4fca 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -72,9 +72,9 @@
 		DEBUGP("we are PAC->PNS\n");
 		/* build tuple for PNS->PAC */
 		t.src.l3num = AF_INET;
-		t.src.u3.ip = master->tuplehash[exp->dir].tuple.src.u3.ip;
+		t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
 		t.src.u.gre.key = nat_pptp_info->pns_call_id;
-		t.dst.u3.ip = master->tuplehash[exp->dir].tuple.dst.u3.ip;
+		t.dst.u3.ip = master->tuplehash[!exp->dir].tuple.dst.u3.ip;
 		t.dst.u.gre.key = nat_pptp_info->pac_call_id;
 		t.dst.protonum = IPPROTO_GRE;
 	}
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 730a7a4..00d6dea 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -123,7 +123,7 @@
 
 	nat = nfct_nat(ct);
 	if (!nat)
-		return NF_DROP;
+		return NF_ACCEPT;
 
 	switch (ctinfo) {
 	case IP_CT_RELATED:
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c701f6a..c26076f 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1011,10 +1011,11 @@
 			for (j = 0; j < i; j++){
 				if (after(ntohl(sp[j].start_seq),
 					  ntohl(sp[j+1].start_seq))){
-					sp[j].start_seq = htonl(tp->recv_sack_cache[j+1].start_seq);
-					sp[j].end_seq = htonl(tp->recv_sack_cache[j+1].end_seq);
-					sp[j+1].start_seq = htonl(tp->recv_sack_cache[j].start_seq);
-					sp[j+1].end_seq = htonl(tp->recv_sack_cache[j].end_seq);
+					struct tcp_sack_block_wire tmp;
+
+					tmp = sp[j];
+					sp[j] = sp[j+1];
+					sp[j+1] = tmp;
 				}
 
 			}
@@ -4420,9 +4421,11 @@
 			 * But, this leaves one open to an easy denial of
 		 	 * service attack, and SYN cookies can't defend
 			 * against this problem. So, we drop the data
-			 * in the interest of security over speed.
+			 * in the interest of security over speed unless
+			 * it's still in use.
 			 */
-			goto discard;
+			kfree_skb(skb);
+			return 0;
 		}
 		goto discard;
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index bf7a224..12de90a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -648,7 +648,7 @@
 				   TCPOLEN_TIMESTAMP);
 		rep.opt[1] = htonl(tcp_time_stamp);
 		rep.opt[2] = htonl(ts);
-		arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED;
+		arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
 	}
 
 	/* Swap the send and the receive. */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 32c1a97..975f447 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -467,6 +467,7 @@
 
 	th = (struct tcphdr *) skb_push(skb, tcp_header_size);
 	skb->h.th = th;
+	skb_set_owner_w(skb, sk);
 
 	/* Build TCP header and checksum it. */
 	th->source		= inet->sport;
@@ -540,7 +541,7 @@
 	if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
 		TCP_INC_STATS(TCP_MIB_OUTSEGS);
 
-	err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
+	err = icsk->icsk_af_ops->queue_xmit(skb, 0);
 	if (likely(err <= 0))
 		return err;
 
@@ -1650,7 +1651,8 @@
 
 		memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
 
-		skb->ip_summed = next_skb->ip_summed;
+		if (next_skb->ip_summed == CHECKSUM_PARTIAL)
+			skb->ip_summed = CHECKSUM_PARTIAL;
 
 		if (skb->ip_summed != CHECKSUM_PARTIAL)
 			skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size);
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index f230eee..41c1578 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -30,7 +30,7 @@
 
 #include <net/tcp.h>
 
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
 MODULE_DESCRIPTION("TCP cwnd snooper");
 MODULE_LICENSE("GPL");
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 171e5b5..e385469 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -341,6 +341,7 @@
 static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
 {
 	struct inet6_dev *ndev;
+	struct in6_addr maddr;
 
 	ASSERT_RTNL();
 
@@ -425,6 +426,11 @@
 #endif
 	/* protected by rtnl_lock */
 	rcu_assign_pointer(dev->ip6_ptr, ndev);
+
+	/* Join all-node multicast group */
+	ipv6_addr_all_nodes(&maddr);
+	ipv6_dev_mc_inc(dev, &maddr);
+
 	return ndev;
 }
 
@@ -3387,7 +3393,7 @@
 #ifdef CONFIG_IPV6_ROUTER_PREF
 	array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
 	array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
-#ifdef CONFIV_IPV6_ROUTE_INFO
+#ifdef CONFIG_IPV6_ROUTE_INFO
 	array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
 #endif
 #endif
@@ -3892,7 +3898,7 @@
 			.proc_handler	=	&proc_dointvec_jiffies,
 			.strategy	=	&sysctl_jiffies,
 		},
-#ifdef CONFIV_IPV6_ROUTE_INFO
+#ifdef CONFIG_IPV6_ROUTE_INFO
 		{
 			.ctl_name	=	NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,
 			.procname	=	"accept_ra_rt_info_max_plen",
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e5cd83b..0e0e426 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -171,7 +171,7 @@
 		sk->sk_reuse = 1;
 
 	inet = inet_sk(sk);
-	inet->is_icsk = INET_PROTOSW_ICSK & answer_flags;
+	inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
 
 	if (SOCK_RAW == sock->type) {
 		inet->num = protocol;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index c700302..116f94a 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -139,8 +139,9 @@
 
 EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
 
-int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
+int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
 {
+	struct sock *sk = skb->sk;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct flowi fl;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a1c231a..882cde4 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2258,8 +2258,6 @@
 
 void ipv6_mc_init_dev(struct inet6_dev *idev)
 {
-	struct in6_addr maddr;
-
 	write_lock_bh(&idev->lock);
 	rwlock_init(&idev->mc_lock);
 	idev->mc_gq_running = 0;
@@ -2275,10 +2273,6 @@
 	idev->mc_maxdelay = IGMP6_UNSOLICITED_IVAL;
 	idev->mc_v1_seen = 0;
 	write_unlock_bh(&idev->lock);
-
-	/* Add all-nodes address. */
-	ipv6_addr_all_nodes(&maddr);
-	ipv6_dev_mc_inc(idev->dev, &maddr);
 }
 
 /*
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 6a9f616..39bb658 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1413,6 +1413,13 @@
  		return;
  	}
 
+	if (!ipv6_addr_equal(&skb->nh.ipv6h->daddr, target) &&
+	    !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+		ND_PRINTK2(KERN_WARNING
+			"ICMPv6 Redirect: target address is not link-local.\n");
+		return;
+	}
+
 	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr,
 			dev->ifindex);
 
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 37e5fca..d9c1540 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -835,6 +835,8 @@
 		s->nfct_reasm = skb;
 
 		s2 = s->next;
+		s->next = NULL;
+
 		NF_HOOK_THRESH(PF_INET6, hooknum, s, in, out, okfn,
 			       NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
 		s = s2;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8c3d568..5f0043c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2017,6 +2017,7 @@
 	       + nla_total_size(4) /* RTA_IIF */
 	       + nla_total_size(4) /* RTA_OIF */
 	       + nla_total_size(4) /* RTA_PRIORITY */
+	       + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
 	       + nla_total_size(sizeof(struct rta_cacheinfo));
 }
 
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index cd10e44..80107d4 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -165,7 +165,7 @@
 
 config NF_CONNTRACK_H323
 	tristate "H.323 protocol support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && NF_CONNTRACK
+	depends on EXPERIMENTAL && NF_CONNTRACK && (IPV6 || IPV6=n)
 	help
 	  H.323 is a VoIP signalling protocol from ITU-T. As one of the most
 	  important VoIP protocols, it is widely used by voice hardware and
@@ -628,7 +628,7 @@
 
 config NETFILTER_XT_MATCH_HASHLIMIT
 	tristate '"hashlimit" match support'
-	depends on NETFILTER_XTABLES
+	depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
 	help
 	  This option adds a `hashlimit' match.
 
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index a5b234e..2a48efd 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -89,6 +89,7 @@
 
 	exp->expectfn             = NULL;
 	exp->flags                = NF_CT_EXPECT_PERMANENT;
+	exp->helper               = NULL;
 
 	nf_conntrack_expect_related(exp);
 	nf_conntrack_expect_put(exp);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index bd1d2de..c64f029 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -389,9 +389,11 @@
 		    && ctnetlink_dump_helpinfo(skb, ct) < 0)
 		    	goto nfattr_failure;
 
+#ifdef CONFIG_NF_CONNTRACK_MARK
 		if ((events & IPCT_MARK || ct->mark)
 		    && ctnetlink_dump_mark(skb, ct) < 0)
 		    	goto nfattr_failure;
+#endif
 
 		if (events & IPCT_COUNTER_FILLING &&
 		    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
@@ -981,7 +983,7 @@
 	if (cda[CTA_PROTOINFO-1]) {
 		err = ctnetlink_change_protoinfo(ct, cda);
 		if (err < 0)
-			return err;
+			goto err;
 	}
 
 #if defined(CONFIG_NF_CONNTRACK_MARK)
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index f0ff00e..c59df3b 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -113,7 +113,7 @@
 
 	rcu_read_lock();
 	nf_nat_pptp_expectfn = rcu_dereference(nf_nat_pptp_hook_expectfn);
-	if (nf_nat_pptp_expectfn && ct->status & IPS_NAT_MASK)
+	if (nf_nat_pptp_expectfn && ct->master->status & IPS_NAT_MASK)
 		nf_nat_pptp_expectfn(ct, exp);
 	else {
 		struct nf_conntrack_tuple inv_t;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index eb2a241..9dec115 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -303,10 +303,16 @@
 {
 	int s = *shift;
 
-	for (; dptr <= limit && *dptr != '@'; dptr++)
+	/* Search for @, but stop at the end of the line.
+	 * We are inside a sip: URI, so we don't need to worry about
+	 * continuation lines. */
+	while (dptr <= limit &&
+	       *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
 		(*shift)++;
+		dptr++;
+	}
 
-	if (*dptr == '@') {
+	if (dptr <= limit && *dptr == '@') {
 		dptr++;
 		(*shift)++;
 	} else
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index d93cb09..5e32dfa 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -52,6 +52,8 @@
 {
 	const struct xt_connbytes_info *sinfo = matchinfo;
 	u_int64_t what = 0;	/* initialize to make gcc happy */
+	u_int64_t bytes = 0;
+	u_int64_t pkts = 0;
 	const struct ip_conntrack_counter *counters;
 
 	if (!(counters = nf_ct_get_counters(skb)))
@@ -89,29 +91,22 @@
 	case XT_CONNBYTES_AVGPKT:
 		switch (sinfo->direction) {
 		case XT_CONNBYTES_DIR_ORIGINAL:
-			what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
-					counters[IP_CT_DIR_ORIGINAL].packets);
+			bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
+			pkts  = counters[IP_CT_DIR_ORIGINAL].packets;
 			break;
 		case XT_CONNBYTES_DIR_REPLY:
-			what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
-					counters[IP_CT_DIR_REPLY].packets);
+			bytes = counters[IP_CT_DIR_REPLY].bytes;
+			pkts  = counters[IP_CT_DIR_REPLY].packets;
 			break;
 		case XT_CONNBYTES_DIR_BOTH:
-			{
-				u_int64_t bytes;
-				u_int64_t pkts;
-				bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
-					counters[IP_CT_DIR_REPLY].bytes;
-				pkts = counters[IP_CT_DIR_ORIGINAL].packets+
-					counters[IP_CT_DIR_REPLY].packets;
-
-				/* FIXME_THEORETICAL: what to do if sum
-				 * overflows ? */
-
-				what = div64_64(bytes, pkts);
-			}
+			bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
+				counters[IP_CT_DIR_REPLY].bytes;
+			pkts  = counters[IP_CT_DIR_ORIGINAL].packets +
+				counters[IP_CT_DIR_REPLY].packets;
 			break;
 		}
+		if (pkts != 0)
+			what = div64_64(bytes, pkts);
 		break;
 	}
 
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 4afc75f..73e0ff4 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -130,12 +130,12 @@
 
 	nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
 		if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
-			if (iter > CIPSO_V4_TAG_MAXCNT)
+			if (iter >= CIPSO_V4_TAG_MAXCNT)
 				return -EINVAL;
 			doi_def->tags[iter++] = nla_get_u8(nla);
 		}
-	if (iter < CIPSO_V4_TAG_MAXCNT)
-		doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
+	while (iter < CIPSO_V4_TAG_MAXCNT)
+		doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
 
 	return 0;
 }
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index da73e8a..6dc01bd 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -359,6 +359,10 @@
 	if (dev == NULL)
 		goto out_unlock;
 	
+	err = -ENETDOWN;
+	if (!(dev->flags & IFF_UP))
+		goto out_unlock;
+
 	/*
 	 *	You may not queue a frame bigger than the mtu. This is the lowest level
 	 *	raw protocol and you must do your own fragmentation at this level.
@@ -407,10 +411,6 @@
 	if (err)
 		goto out_free;
 
-	err = -ENETDOWN;
-	if (!(dev->flags & IFF_UP))
-		goto out_free;
-
 	/*
 	 *	Now send it
 	 */
@@ -428,24 +428,18 @@
 }
 #endif
 
-static inline int run_filter(struct sk_buff *skb, struct sock *sk,
-							unsigned *snaplen)
+static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
+				      unsigned int res)
 {
 	struct sk_filter *filter;
-	int err = 0;
 
 	rcu_read_lock_bh();
 	filter = rcu_dereference(sk->sk_filter);
-	if (filter != NULL) {
-		err = sk_run_filter(skb, filter->insns, filter->len);
-		if (!err)
-			err = -EPERM;
-		else if (*snaplen > err)
-			*snaplen = err;
-	}
+	if (filter != NULL)
+		res = sk_run_filter(skb, filter->insns, filter->len);
 	rcu_read_unlock_bh();
 
-	return err;
+	return res;
 }
 
 /*
@@ -467,7 +461,7 @@
 	struct packet_sock *po;
 	u8 * skb_head = skb->data;
 	int skb_len = skb->len;
-	unsigned snaplen;
+	unsigned int snaplen, res;
 
 	if (skb->pkt_type == PACKET_LOOPBACK)
 		goto drop;
@@ -495,8 +489,11 @@
 
 	snaplen = skb->len;
 
-	if (run_filter(skb, sk, &snaplen) < 0)
+	res = run_filter(skb, sk, snaplen);
+	if (!res)
 		goto drop_n_restore;
+	if (snaplen > res)
+		snaplen = res;
 
 	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
 	    (unsigned)sk->sk_rcvbuf)
@@ -568,7 +565,7 @@
 	struct tpacket_hdr *h;
 	u8 * skb_head = skb->data;
 	int skb_len = skb->len;
-	unsigned snaplen;
+	unsigned int snaplen, res;
 	unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER;
 	unsigned short macoff, netoff;
 	struct sk_buff *copy_skb = NULL;
@@ -592,8 +589,11 @@
 
 	snaplen = skb->len;
 
-	if (run_filter(skb, sk, &snaplen) < 0)
+	res = run_filter(skb, sk, snaplen);
+	if (!res)
 		goto drop_n_restore;
+	if (snaplen > res)
+		snaplen = res;
 
 	if (sk->sk_type == SOCK_DGRAM) {
 		macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
@@ -738,6 +738,10 @@
 	if (sock->type == SOCK_RAW)
 		reserve = dev->hard_header_len;
 
+	err = -ENETDOWN;
+	if (!(dev->flags & IFF_UP))
+		goto out_unlock;
+
 	err = -EMSGSIZE;
 	if (len > dev->mtu+reserve)
 		goto out_unlock;
@@ -770,10 +774,6 @@
 	skb->dev = dev;
 	skb->priority = sk->sk_priority;
 
-	err = -ENETDOWN;
-	if (!(dev->flags & IFF_UP))
-		goto out_free;
-
 	/*
 	 *	Now send it
 	 */
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index a960806..01e6913 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -55,7 +55,8 @@
 	struct ipt_target *target;
 	int ret = 0;
 
-	target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision);
+	target = xt_request_find_target(AF_INET, t->u.user.name,
+					t->u.user.revision);
 	if (!target)
 		return -ENOENT;
 
@@ -63,9 +64,10 @@
 
 	ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
 			      table, hook, 0, 0);
-	if (ret)
+	if (ret) {
+		module_put(t->u.kernel.target->me);
 		return ret;
-
+	}
 	if (t->u.kernel.target->checkentry
 	    && !t->u.kernel.target->checkentry(table, NULL,
 		    			       t->u.kernel.target, t->data,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 225f39b..0ef4812 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -804,7 +804,7 @@
 			  NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
 
 	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
-	return ip_queue_xmit(skb, skb->sk, ipfragok);
+	return ip_queue_xmit(skb, ipfragok);
 }
 
 static struct sctp_af sctp_ipv4_specific;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index f0bbe36..0b1ddb1 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -124,8 +124,8 @@
 	padlen = len % 4;
 	err.length  = htons(len);
 	len += padlen;
-	sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
-	chunk->subh.err_hdr = sctp_addto_chunk(chunk, paylen, payload);
+	chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
+	sctp_addto_chunk(chunk, paylen, payload);
 }
 
 /* 3.3.2 Initiation (INIT) (1)
@@ -1562,7 +1562,7 @@
 	if (*errp) {
 		report.num_missing = htonl(1);
 		report.type = paramtype;
-		sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM,
+		sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
 				&report, sizeof(report));
 	}
 
@@ -1775,7 +1775,9 @@
 
 	/* Verify stream values are non-zero. */
 	if ((0 == peer_init->init_hdr.num_outbound_streams) ||
-	    (0 == peer_init->init_hdr.num_inbound_streams)) {
+	    (0 == peer_init->init_hdr.num_inbound_streams) ||
+	    (0 == peer_init->init_hdr.init_tag) ||
+	    (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
 
 		sctp_process_inv_mandatory(asoc, chunk, errp);
 		return 0;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 7bbc615..6db77d1 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -217,7 +217,7 @@
 
 		asoc->peer.sack_needed = 0;
 
-		error = sctp_outq_tail(&asoc->outqueue, sack);
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack));
 
 		/* Stop the SACK timer.  */
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -621,7 +621,13 @@
 	/* The receiver of the HEARTBEAT ACK should also perform an
 	 * RTT measurement for that destination transport address
 	 * using the time value carried in the HEARTBEAT ACK chunk.
+	 * If the transport's rto_pending variable has been cleared,
+	 * it was most likely due to a retransmit.  However, we want
+	 * to re-enable it to properly update the rto.
 	 */
+	if (t->rto_pending == 0)
+		t->rto_pending = 1;
+
 	hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
 	sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at));
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index aa51d19..fbbc9e6 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -440,7 +440,6 @@
 {
 	struct sctp_chunk *chunk = arg;
 	sctp_init_chunk_t *initchunk;
-	__u32 init_tag;
 	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
 	sctp_error_t error;
@@ -462,24 +461,6 @@
 	/* Grab the INIT header.  */
 	chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
 
-	init_tag = ntohl(chunk->subh.init_hdr->init_tag);
-
-	/* Verification Tag: 3.3.3
-	 *   If the value of the Initiate Tag in a received INIT ACK
-	 *   chunk is found to be 0, the receiver MUST treat it as an
-	 *   error and close the association by transmitting an ABORT.
-	 */
-	if (!init_tag) {
-		struct sctp_chunk *reply = sctp_make_abort(asoc, chunk, 0);
-		if (!reply)
-			goto nomem;
-
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
-		return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM,
-					      ECONNREFUSED, asoc,
-					      chunk->transport);
-	}
-
 	/* Verify the INIT chunk before processing it. */
 	err_chunk = NULL;
 	if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -550,9 +531,6 @@
 			SCTP_CHUNK(err_chunk));
 
 	return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-	return SCTP_DISPOSITION_NOMEM;
 }
 
 /*
@@ -1553,6 +1531,28 @@
 }
 
 
+/*
+ * Unexpected INIT-ACK handler.
+ *
+ * Section 5.2.3
+ * If an INIT ACK received by an endpoint in any state other than the
+ * COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk.
+ * An unexpected INIT ACK usually indicates the processing of an old or
+ * duplicated INIT chunk.
+*/
+sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
+					    const struct sctp_association *asoc,
+					    const sctp_subtype_t type,
+					    void *arg, sctp_cmd_seq_t *commands)
+{
+	/* Per the above section, we'll discard the chunk if we have an
+	 * endpoint.  If this is an OOTB INIT-ACK, treat it as such.
+	 */
+        if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
+		return sctp_sf_ootb(ep, asoc, type, arg, commands);
+	else
+		return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+}
 
 /* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A')
  *
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 733dd87..5f6cc7a 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -152,7 +152,7 @@
 	/* SCTP_STATE_EMPTY */ \
 	TYPE_SCTP_FUNC(sctp_sf_ootb), \
 	/* SCTP_STATE_CLOSED */ \
-	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	TYPE_SCTP_FUNC(sctp_sf_do_5_2_3_initack), \
 	/* SCTP_STATE_COOKIE_WAIT */ \
 	TYPE_SCTP_FUNC(sctp_sf_do_5_1C_ack), \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index aba528b..16c9fbc 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -490,16 +490,14 @@
 
 	/* Set up the call info struct and execute the task */
 	status = task->tk_status;
-	if (status != 0) {
-		rpc_release_task(task);
+	if (status != 0)
 		goto out;
-	}
 	atomic_inc(&task->tk_count);
 	status = rpc_execute(task);
 	if (status == 0)
 		status = task->tk_status;
-	rpc_put_task(task);
 out:
+	rpc_put_task(task);
 	rpc_restore_sigmask(&oldset);
 	return status;
 }
@@ -537,7 +535,7 @@
 	if (status == 0)
 		rpc_execute(task);
 	else
-		rpc_release_task(task);
+		rpc_put_task(task);
 
 	rpc_restore_sigmask(&oldset);		
 	return status;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 79bc4cd..fc083f0 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -42,6 +42,7 @@
 static void			__rpc_default_timer(struct rpc_task *task);
 static void			rpciod_killall(void);
 static void			rpc_async_schedule(struct work_struct *);
+static void			 rpc_release_task(struct rpc_task *task);
 
 /*
  * RPC tasks sit here while waiting for conditions to improve.
@@ -896,7 +897,7 @@
 }
 EXPORT_SYMBOL(rpc_put_task);
 
-void rpc_release_task(struct rpc_task *task)
+static void rpc_release_task(struct rpc_task *task)
 {
 #ifdef RPC_DEBUG
 	BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index f3001f3..4c16112 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -26,7 +26,6 @@
 #include <linux/sunrpc/clnt.h>
 
 #define RPCDBG_FACILITY	RPCDBG_SVCDSP
-#define RPC_PARANOIA 1
 
 /*
  * Mode for mapping cpus to pools.
@@ -872,15 +871,15 @@
 	return 0;
 
 err_short_len:
-#ifdef RPC_PARANOIA
-	printk("svc: short len %Zd, dropping request\n", argv->iov_len);
-#endif
+	if (net_ratelimit())
+		printk("svc: short len %Zd, dropping request\n", argv->iov_len);
+
 	goto dropit;			/* drop request */
 
 err_bad_dir:
-#ifdef RPC_PARANOIA
-	printk("svc: bad direction %d, dropping request\n", dir);
-#endif
+	if (net_ratelimit())
+		printk("svc: bad direction %d, dropping request\n", dir);
+
 	serv->sv_stats->rpcbadfmt++;
 	goto dropit;			/* drop request */
 
@@ -909,9 +908,10 @@
 	goto sendit;
 
 err_bad_vers:
-#ifdef RPC_PARANOIA
-	printk("svc: unknown version (%d)\n", vers);
-#endif
+	if (net_ratelimit())
+		printk("svc: unknown version (%d for prog %d, %s)\n",
+		       vers, prog, progp->pg_name);
+
 	serv->sv_stats->rpcbadfmt++;
 	svc_putnl(resv, RPC_PROG_MISMATCH);
 	svc_putnl(resv, progp->pg_lovers);
@@ -919,17 +919,17 @@
 	goto sendit;
 
 err_bad_proc:
-#ifdef RPC_PARANOIA
-	printk("svc: unknown procedure (%d)\n", proc);
-#endif
+	if (net_ratelimit())
+		printk("svc: unknown procedure (%d)\n", proc);
+
 	serv->sv_stats->rpcbadfmt++;
 	svc_putnl(resv, RPC_PROC_UNAVAIL);
 	goto sendit;
 
 err_garbage:
-#ifdef RPC_PARANOIA
-	printk("svc: failed to decode args\n");
-#endif
+	if (net_ratelimit())
+		printk("svc: failed to decode args\n");
+
 	rpc_stat = rpc_garbage_args;
 err_bad:
 	serv->sv_stats->rpcbadfmt++;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 99f54fb..ff1f8bf 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1062,15 +1062,19 @@
 			 *  bit set in the fragment length header.
 			 *  But apparently no known nfs clients send fragmented
 			 *  records. */
-			printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx (non-terminal)\n",
-			       (unsigned long) svsk->sk_reclen);
+			if (net_ratelimit())
+				printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+				       " (non-terminal)\n",
+				       (unsigned long) svsk->sk_reclen);
 			goto err_delete;
 		}
 		svsk->sk_reclen &= 0x7fffffff;
 		dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
 		if (svsk->sk_reclen > serv->sv_max_mesg) {
-			printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx (large)\n",
-			       (unsigned long) svsk->sk_reclen);
+			if (net_ratelimit())
+				printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+				       " (large)\n",
+				       (unsigned long) svsk->sk_reclen);
 			goto err_delete;
 		}
 	}
@@ -1278,6 +1282,8 @@
 				schedule_timeout_uninterruptible(msecs_to_jiffies(500));
 			rqstp->rq_pages[i] = p;
 		}
+	rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */
+	BUG_ON(pages >= RPCSVC_MAXPAGES);
 
 	/* Make arg->head point to first page and arg->pages point to rest */
 	arg = &rqstp->rq_arg;
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 47b68a3..328d80f 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -56,6 +56,7 @@
 			sk_add_backlog(sk, skb);
 		}
 		bh_unlock_sock(sk);
+		sock_put(sk);
 		return queued;
 	}
 
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 9f42b9c..27f5cc7 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -254,7 +254,7 @@
 	 *	They want reverse charging, we won't accept it.
 	 */
 	if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
-		SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
+		SOCK_DEBUG(sk, "X.25: rejecting reverse charging request\n");
 		return -1;
 	}
 
@@ -262,29 +262,29 @@
 
 	if (theirs.throughput) {
 		if (theirs.throughput < ours->throughput) {
-			SOCK_DEBUG(sk, "X.25: throughput negotiated down");
+			SOCK_DEBUG(sk, "X.25: throughput negotiated down\n");
 			new->throughput = theirs.throughput;
 		}
 	}
 
 	if (theirs.pacsize_in && theirs.pacsize_out) {
 		if (theirs.pacsize_in < ours->pacsize_in) {
-			SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down");
+			SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down\n");
 			new->pacsize_in = theirs.pacsize_in;
 		}
 		if (theirs.pacsize_out < ours->pacsize_out) {
-			SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down");
+			SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down\n");
 			new->pacsize_out = theirs.pacsize_out;
 		}
 	}
 
 	if (theirs.winsize_in && theirs.winsize_out) {
 		if (theirs.winsize_in < ours->winsize_in) {
-			SOCK_DEBUG(sk, "X.25: window size inwards negotiated down");
+			SOCK_DEBUG(sk, "X.25: window size inwards negotiated down\n");
 			new->winsize_in = theirs.winsize_in;
 		}
 		if (theirs.winsize_out < ours->winsize_out) {
-			SOCK_DEBUG(sk, "X.25: window size outwards negotiated down");
+			SOCK_DEBUG(sk, "X.25: window size outwards negotiated down\n");
 			new->winsize_out = theirs.winsize_out;
 		}
 	}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index bebd40e..b7e537f 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -650,19 +650,18 @@
 	struct xfrm_policy *pol;
 	struct xfrm_policy *delpol;
 	struct hlist_head *chain;
-	struct hlist_node *entry, *newpos, *last;
+	struct hlist_node *entry, *newpos;
 	struct dst_entry *gc_list;
 
 	write_lock_bh(&xfrm_policy_lock);
 	chain = policy_hash_bysel(&policy->selector, policy->family, dir);
 	delpol = NULL;
 	newpos = NULL;
-	last = NULL;
 	hlist_for_each_entry(pol, entry, chain, bydst) {
-		if (!delpol &&
-		    pol->type == policy->type &&
+		if (pol->type == policy->type &&
 		    !selector_cmp(&pol->selector, &policy->selector) &&
-		    xfrm_sec_ctx_match(pol->security, policy->security)) {
+		    xfrm_sec_ctx_match(pol->security, policy->security) &&
+		    !WARN_ON(delpol)) {
 			if (excl) {
 				write_unlock_bh(&xfrm_policy_lock);
 				return -EEXIST;
@@ -671,17 +670,12 @@
 			if (policy->priority > pol->priority)
 				continue;
 		} else if (policy->priority >= pol->priority) {
-			last = &pol->bydst;
+			newpos = &pol->bydst;
 			continue;
 		}
-		if (!newpos)
-			newpos = &pol->bydst;
 		if (delpol)
 			break;
-		last = &pol->bydst;
 	}
-	if (!newpos)
-		newpos = last;
 	if (newpos)
 		hlist_add_after(newpos, &policy->bydst);
 	else
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index f01f8c0..96926eb 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -1,7 +1,7 @@
 ####
 # kbuild: Generic definitions
 
-# Convinient variables
+# Convenient constants
 comma   := ,
 squote  := '
 empty   :=
@@ -56,40 +56,46 @@
 # gcc support functions
 # See documentation in Documentation/kbuild/makefiles.txt
 
-# output directory for tests below
-TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+# checker-shell
+# Usage: option = $(call checker-shell, $(CC)...-o $$OUT, option-ok, otherwise)
+# Exit code chooses option. $$OUT is safe location for needless output.
+define checker-shell
+  $(shell set -e; \
+    DIR=$(KBUILD_EXTMOD); \
+    cd $${DIR:-$(objtree)}; \
+    OUT=$$PWD/.$$$$.null; \
+    \
+    ln -s /dev/null $$OUT; \
+    if $(1) >/dev/null 2>&1; \
+      then echo "$(2)"; \
+      else echo "$(3)"; \
+    fi; \
+    rm -f $$OUT)
+endef
 
 # as-option
 # Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
-
-as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
-	     -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
-	     else echo "$(2)"; fi ;)
+as-option = $(call checker-shell, \
+   $(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o $$OUT, $(1), $(2))
 
 # as-instr
 # Usage: cflags-y += $(call as-instr, instr, option1, option2)
-
-as-instr = $(shell if echo -e "$(1)" | \
-		      $(CC) $(AFLAGS) -c -xassembler - \
-			    -o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \
-		   then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \
-		   else echo "$(3)"; fi)
+as-instr = $(call checker-shell, \
+   printf "$(1)" | $(CC) $(AFLAGS) -c -xassembler -o $$OUT -, $(2), $(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
-
-cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
-             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+cc-option = $(call checker-shell, \
+   $(CC) $(CFLAGS) $(if $(3),$(3),$(1)) -S -xc /dev/null -o $$OUT, $(1), $(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn, -march=winchip-c6)
-cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
-                > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
+cc-option-yn = $(call cc-option, "y", "n", $(1))
 
 # cc-option-align
 # Prefix align with either -falign or -malign
 cc-option-align = $(subst -functions=0,,\
-	$(call cc-option,-falign-functions=0,-malign-functions=0))
+   $(call cc-option,-falign-functions=0,-malign-functions=0))
 
 # cc-version
 # Usage gcc-ver := $(call cc-version, $(CC))
@@ -97,35 +103,42 @@
 
 # cc-ifversion
 # Usage:  EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
-cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
-                       echo $(3); fi;)
+cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
 
 # ld-option
 # Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
-ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
-			     -o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \
-             then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \
-             else echo "$(2)"; fi)
+ld-option = $(call checker-shell, \
+   $(CC) $(1) -nostdlib -xc /dev/null -o $$OUT, $(1), $(2))
 
-###
+######
+
 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
 # Usage:
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
-# Prefix -I with $(srctree) if it is not an absolute path
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
-# Find all -I options and call addtree
-flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
+# Prefix -I with $(srctree) if it is not an absolute path,
+# add original to the end
+addtree = $(if \
+	$(filter-out -I/%, $(1)), $(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
 
-# If quiet is set, only print short version of command
+# Find all -I options and call addtree
+flags = $(foreach o,$($(1)), \
+	$(if $(filter -I%,$(o)), $(call addtree, $(o)), $(o)))
+
+# echo command.
+# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
+echo-cmd = $(if $($(quiet)cmd_$(1)), \
+	echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
+
+# printing commands
 cmd = @$(echo-cmd) $(cmd_$(1))
 
-# Add $(obj)/ for paths that is not absolute
-objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
+# Add $(obj)/ for paths that are not absolute
+objectify = $(foreach o,$(1), $(if $(filter /%,$(o)), $(o), $(obj)/$(o)))
 
 ###
-# if_changed      - execute command if any prerequisite is newer than 
+# if_changed      - execute command if any prerequisite is newer than
 #                   target, or command line has changed
 # if_changed_dep  - as if_changed, but uses fixdep to reveal dependencies
 #                   including used config symbols
@@ -133,16 +146,12 @@
 # See Documentation/kbuild/makefiles.txt for more info
 
 ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments has same arguments. Result in empty string if equal
+# Check if both arguments has same arguments. Result is empty string, if equal.
 # User may override this check using make KBUILD_NOCMDDEP=1
 arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
                     $(filter-out $(cmd_$@),   $(cmd_$(1))) )
 endif
 
-# echo command. Short version is $(quiet) equals quiet, otherwise full command
-echo-cmd = $(if $($(quiet)cmd_$(1)), \
-	echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
-
 # >'< substitution is for echo to work,
 # >$< substitution to preserve $ when reloading .cmd file
 # note: when using inline perl scripts [perl -e '...$$t=1;...']
@@ -153,15 +162,15 @@
 # PHONY targets skipped in both cases.
 any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
 
-# Execute command if command has changed or prerequisitei(s) are updated
+# Execute command if command has changed or prerequisite(s) are updated.
 #
 if_changed = $(if $(strip $(any-prereq) $(arg-check)),                       \
 	@set -e;                                                             \
 	$(echo-cmd) $(cmd_$(1));                                             \
 	echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
 
-# execute the command and also postprocess generated .d dependencies
-# file
+# Execute the command and also postprocess generated .d dependencies file.
+#
 if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ),                  \
 	@set -e;                                                             \
 	$(echo-cmd) $(cmd_$(1));                                             \
@@ -169,9 +178,10 @@
 	rm -f $(depfile);                                                    \
 	mv -f $(dot-target).tmp $(dot-target).cmd)
 
+# Will check if $(cmd_foo) changed, or any of the prerequisites changed,
+# and if so will execute $(rule_foo).
 # Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
+#
 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),                 \
 	@set -e;                                                             \
 	$(rule_$(1)))
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 4241e0d..f7b6705 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -109,7 +109,7 @@
 quiet_cmd_gen		  = GEN     $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
       cmd_gen		  = \
 FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@)			\
-STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z. A-Z_`;			\
+STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z.- A-Z__`;			\
 (echo "/* File autogenerated by 'make headers_install' */" ;		\
 echo "\#ifndef $$STUBDEF" ;						\
 echo "\#define $$STUBDEF" ;						\
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 4c723fd..43f75d6 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
-# Copyright (c) 2006           Sam Ravnborg <sam@ravnborg.org>
+# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
 #
 # Released under the terms of the GNU GPL
 #
@@ -17,15 +17,15 @@
 Usage:
 $0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
 	-o <file>      Create gzipped initramfs file named <file> using
-	               gen_init_cpio and gzip
+		       gen_init_cpio and gzip
 	-u <uid>       User ID to map to user ID 0 (root).
-	               <uid> is only meaningful if <cpio_source>
-	               is a directory.
+		       <uid> is only meaningful if <cpio_source>
+		       is a directory.
 	-g <gid>       Group ID to map to group ID 0 (root).
-	               <gid> is only meaningful if <cpio_source>
-	               is a directory.
+		       <gid> is only meaningful if <cpio_source>
+		       is a directory.
 	<cpio_source>  File list or directory for cpio archive.
-	               If <cpio_source> is a .cpio file it will be used
+		       If <cpio_source> is a .cpio file it will be used
 		       as direct input to initramfs.
 	-d             Output the default cpio list.
 
@@ -36,6 +36,12 @@
 EOF
 }
 
+# awk style field access
+# $1 - field number; rest is argument string
+field() {
+	shift $1 ; echo $1
+}
+
 list_default_initramfs() {
 	# echo usr/kinit/kinit
 	:
@@ -119,22 +125,17 @@
 			str="${ftype} ${name} ${location} ${str}"
 			;;
 		"nod")
-			local dev_type=
-			local maj=$(LC_ALL=C ls -l "${location}" | \
-					gawk '{sub(/,/, "", $5); print $5}')
-			local min=$(LC_ALL=C ls -l "${location}" | \
-					gawk '{print $6}')
+			local dev=`LC_ALL=C ls -l "${location}"`
+			local maj=`field 5 ${dev}`
+			local min=`field 6 ${dev}`
+			maj=${maj%,}
 
-			if [ -b "${location}" ]; then
-				dev_type="b"
-			else
-				dev_type="c"
-			fi
-			str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
+			[ -b "${location}" ] && dev="b" || dev="c"
+
+			str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
 			;;
 		"slink")
-			local target=$(LC_ALL=C ls -l "${location}" | \
-					gawk '{print $11}')
+			local target=`field 11 $(LC_ALL=C ls -l "${location}")`
 			str="${ftype} ${name} ${target} ${str}"
 			;;
 		*)
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index a8ffc32..c0ae0a7 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -917,7 +917,7 @@
 }
 
 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
-	: Parent(parent, name), menu(0)
+	: Parent(parent, name), menu(0), sym(0)
 {
 	if (name) {
 		configSettings->beginGroup(name);
@@ -925,8 +925,6 @@
 		configSettings->endGroup();
 		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
 	}
-
-	has_dbg_info = 0;
 }
 
 void ConfigInfoView::saveSettings(void)
@@ -955,13 +953,11 @@
 	if (menu == m)
 		return;
 	menu = m;
-	if (!menu) {
-		has_dbg_info = 0;
+	sym = NULL;
+	if (!menu)
 		clear();
-	} else {
-		has_dbg_info = 1;
+	else
 		menuInfo();
-       }
 }
 
 void ConfigInfoView::setSource(const QString& name)
@@ -996,9 +992,6 @@
 {
 	QString str;
 
-	if (!has_dbg_info)
-		return;
-
 	str += "<big>Symbol: <b>";
 	str += print_filter(sym->name);
 	str += "</b></big><br><br>value: ";
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index a397edb..6fc1c5f 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -273,8 +273,6 @@
 	struct symbol *sym;
 	struct menu *menu;
 	bool _showDebug;
-
-	int has_dbg_info;
 };
 
 class ConfigSearchWindow : public QDialog {
diff --git a/scripts/makelst b/scripts/makelst
index 34bd723..4fc80f2 100755
--- a/scripts/makelst
+++ b/scripts/makelst
@@ -1,31 +1,31 @@
-#!/bin/bash
+#!/bin/sh
 # A script to dump mixed source code & assembly
 # with correct relocations from System.map
-# Requires the following lines in Rules.make.
-# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 
-#            William Stearns <wstearns@pobox.com>
+# Requires the following lines in makefile:
 #%.lst: %.c
 #	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
-#	$(TOPDIR)/scripts/makelst $*.o $(TOPDIR)/System.map $(OBJDUMP)
+#	$(srctree)/scripts/makelst $*.o $(objtree)/System.map $(OBJDUMP)
 #
-#    Copyright (C) 2000 IBM Corporation
-#    Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 
+# Copyright (C) 2000 IBM Corporation
+# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+#            William Stearns <wstearns@pobox.com>
 #
 
-t1=`$3 --syms $1 | grep .text | grep " F " | head -n 1`
+# awk style field access
+field() {
+  shift $1 ; echo $1
+}
+
+t1=`$3 --syms $1 | grep .text | grep -m1 " F "`
 if [ -n "$t1" ]; then
-  t2=`echo $t1 | gawk '{ print $6 }'`
+  t2=`field 6 $t1`
   if [ ! -r $2 ]; then
     echo "No System.map" >&2
-    t7=0
   else
     t3=`grep $t2 $2`
-    t4=`echo $t3 | gawk '{ print $1 }'`
-    t5=`echo $t1 | gawk '{ print $1 }'`
-    t6=`echo $t4 - $t5 | tr a-f A-F`
-    t7=`( echo  ibase=16 ; echo $t6 ) | bc`
+    t4=`field 1 $t3`
+    t5=`field 1 $t1`
+    t6=`printf "%lu" $((0x$t4 - 0x$t5))`
   fi
-else
-  t7=0
 fi
-$3 -r --source --adjust-vma=$t7 $1
+$3 -r --source --adjust-vma=${t6:-0} $1
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 15ab5d0..2aa4762 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -582,9 +582,19 @@
  *   tosec   = .init.text | .exit.text | .init.data
  *   fromsec = .data
  *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
+ *
+ * Pattern 3:
+ *   Some symbols belong to init section but still it is ok to reference
+ *   these from non-init sections as these symbols don't have any memory
+ *   allocated for them and symbol address and value are same. So even
+ *   if init section is freed, its ok to reference those symbols.
+ *   For ex. symbols marking the init section boundaries.
+ *   This pattern is identified by
+ *   refsymname = __init_begin, _sinittext, _einittext
  **/
 static int secref_whitelist(const char *modname, const char *tosec,
-			    const char *fromsec, const char *atsym)
+			    const char *fromsec, const char *atsym,
+			    const char *refsymname)
 {
 	int f1 = 1, f2 = 1;
 	const char **s;
@@ -595,6 +605,14 @@
 		"_ops",
 		"_probe",
 		"_probe_one",
+		"_console",
+		NULL
+	};
+
+	const char *pat3refsym[] = {
+		"__init_begin",
+		"_sinittext",
+		"_einittext",
 		NULL
 	};
 
@@ -628,6 +646,11 @@
 		if ((strcmp(fromsec, ".pci_fixup") == 0) &&
 		    (strcmp(tosec, ".init.text") == 0))
 		return 1;
+
+		/* Check for pattern 3 */
+		for (s = pat3refsym; *s; s++)
+			if (strcmp(refsymname, *s) == 0)
+				return 1;
 	}
 	return 0;
 }
@@ -737,7 +760,7 @@
 	/* check whitelist - we may ignore it */
 	if (before &&
 	    secref_whitelist(modname, secname, fromsec,
-			     elf->strtab + before->st_name))
+			     elf->strtab + before->st_name, refsymname))
 		return;
 
 	if (before && after) {
diff --git a/security/keys/key.c b/security/keys/key.c
index ac9326c..700400d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -188,6 +188,7 @@
 
 	spin_lock(&key_serial_lock);
 
+attempt_insertion:
 	parent = NULL;
 	p = &key_serial_tree.rb_node;
 
@@ -202,39 +203,33 @@
 		else
 			goto serial_exists;
 	}
-	goto insert_here;
+
+	/* we've found a suitable hole - arrange for this key to occupy it */
+	rb_link_node(&key->serial_node, parent, p);
+	rb_insert_color(&key->serial_node, &key_serial_tree);
+
+	spin_unlock(&key_serial_lock);
+	return;
 
 	/* we found a key with the proposed serial number - walk the tree from
 	 * that point looking for the next unused serial number */
 serial_exists:
 	for (;;) {
 		key->serial++;
-		if (key->serial < 2)
-			key->serial = 2;
-
-		if (!rb_parent(parent))
-			p = &key_serial_tree.rb_node;
-		else if (rb_parent(parent)->rb_left == parent)
-			p = &(rb_parent(parent)->rb_left);
-		else
-			p = &(rb_parent(parent)->rb_right);
+		if (key->serial < 3) {
+			key->serial = 3;
+			goto attempt_insertion;
+		}
 
 		parent = rb_next(parent);
 		if (!parent)
-			break;
+			goto attempt_insertion;
 
 		xkey = rb_entry(parent, struct key, serial_node);
 		if (key->serial < xkey->serial)
-			goto insert_here;
+			goto attempt_insertion;
 	}
 
-	/* we've found a suitable hole - arrange for this key to occupy it */
-insert_here:
-	rb_link_node(&key->serial_node, parent, p);
-	rb_insert_color(&key->serial_node, &key_serial_tree);
-
-	spin_unlock(&key_serial_lock);
-
 } /* end key_alloc_serial() */
 
 /*****************************************************************************/
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 161eb57..31929e3 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -37,6 +37,11 @@
 int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
 			struct avc_audit_data *ad, u8 proto);
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
+
+static inline void selinux_xfrm_notify_policyload(void)
+{
+	atomic_inc(&flow_cache_genid);
+}
 #else
 static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
 			struct avc_audit_data *ad)
@@ -55,6 +60,10 @@
 	*sid = SECSID_NULL;
 	return 0;
 }
+
+static inline void selinux_xfrm_notify_policyload(void)
+{
+}
 #endif
 
 static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 372eaad..ca9154d 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1299,6 +1299,7 @@
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
 		selinux_netlbl_cache_invalidate();
+		selinux_xfrm_notify_policyload();
 		return 0;
 	}
 
@@ -1354,6 +1355,7 @@
 	avc_ss_reset(seqno);
 	selnl_notify_policyload(seqno);
 	selinux_netlbl_cache_invalidate();
+	selinux_xfrm_notify_policyload();
 
 	return 0;
 
@@ -1853,6 +1855,7 @@
 	if (!rc) {
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
+		selinux_xfrm_notify_policyload();
 	}
 	return rc;
 }
@@ -2491,9 +2494,9 @@
 
 	rc = netlbl_socket_setattr(sock, &secattr);
 	if (rc == 0) {
-		spin_lock(&sksec->nlbl_lock);
+		spin_lock_bh(&sksec->nlbl_lock);
 		sksec->nlbl_state = NLBL_LABELED;
-		spin_unlock(&sksec->nlbl_lock);
+		spin_unlock_bh(&sksec->nlbl_lock);
 	}
 
 netlbl_socket_setsid_return:
diff --git a/sound/core/init.c b/sound/core/init.c
index 6152a75..a4cc6b1 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -361,8 +361,10 @@
 		snd_printk(KERN_WARNING "unable to free card info\n");
 		/* Not fatal error */
 	}
-	if (card->dev)
-		device_unregister(card->dev);
+#ifndef CONFIG_SYSFS_DEPRECATED
+	if (card->card_dev)
+		device_unregister(card->card_dev);
+#endif
 	kfree(card);
 	return 0;
 }
@@ -497,12 +499,14 @@
 	int err;
 
 	snd_assert(card != NULL, return -EINVAL);
-	if (!card->dev) {
-		card->dev = device_create(sound_class, card->parent, 0,
-					  "card%i", card->number);
-		if (IS_ERR(card->dev))
-			card->dev = NULL;
+#ifndef CONFIG_SYSFS_DEPRECATED
+	if (!card->card_dev) {
+		card->card_dev = device_create(sound_class, card->dev, 0,
+					       "card%i", card->number);
+		if (IS_ERR(card->card_dev))
+			card->card_dev = NULL;
 	}
+#endif
 	if ((err = snd_device_register_all(card)) < 0)
 		return err;
 	mutex_lock(&snd_card_mutex);
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 2827420..82a61c6 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -238,7 +238,7 @@
 {
 	int minor;
 	struct snd_minor *preg;
-	struct device *device = NULL;
+	struct device *device = snd_card_get_device_link(card);
 
 	snd_assert(name, return -EINVAL);
 	preg = kmalloc(sizeof *preg, GFP_KERNEL);
@@ -263,8 +263,6 @@
 		return minor;
 	}
 	snd_minors[minor] = preg;
-	if (card)
-		device = card->dev;
 	preg->dev = device_create(sound_class, device, MKDEV(major, minor),
 				  "%s", name);
 	if (preg->dev)
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index b2fc40a..4566df4 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -106,7 +106,7 @@
 	int cidx = SNDRV_MINOR_OSS_CARD(minor);
 	int track2 = -1;
 	int register1 = -1, register2 = -1;
-	struct device *carddev = NULL;
+	struct device *carddev = snd_card_get_device_link(card);
 
 	if (card && card->number >= 8)
 		return 0; /* ignore silently */
@@ -134,8 +134,6 @@
 		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
 		break;
 	}
-	if (card)
-		carddev = card->dev;
 	register1 = register_sound_special_device(f_ops, minor, carddev);
 	if (register1 != minor)
 		goto __end;
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 71c58df..70face7 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2198,7 +2198,8 @@
 		val = inb(cm->iobase + args->reg);
 	else
 		val = snd_cmipci_read(cm, args->reg);
-	change = (val & args->mask) != (ucontrol->value.integer.value[0] ? args->mask : 0);
+	change = (val & args->mask) != (ucontrol->value.integer.value[0] ? 
+			args->mask_on : (args->mask & ~args->mask_on));
 	if (change) {
 		val &= ~args->mask;
 		if (ucontrol->value.integer.value[0])
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index e31f0f1..91f5bff 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -213,7 +213,7 @@
 	sent = bytes = 0;
 	spin_lock_irqsave(&chip->lock, flags);
 	chip->midi_full = 0;
-	if (chip->midi_out && !snd_rawmidi_transmit_empty(chip->midi_out)) {
+	if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
 		bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
 						  MIDI_OUT_BUFFER_SIZE - 1);
 		DE_MID(("Try to send %d bytes...\n", bytes));
@@ -264,9 +264,11 @@
 		}
 	} else {
 		if (chip->tinuse) {
-			del_timer(&chip->timer);
 			chip->tinuse = 0;
+			spin_unlock_irq(&chip->lock);
+			del_timer_sync(&chip->timer);
 			DE_MID(("Timer removed\n"));
+			return;
 		}
 	}
 	spin_unlock_irq(&chip->lock);
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 97e9af1..1589d2f 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -485,8 +485,9 @@
 			return "Front Aux";
 		return "Aux";
 	case AC_JACK_MIC_IN:
-		if (node->pin_caps &
-		    (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT))
+		if (pinctl &&
+		    (node->pin_caps &
+		     (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT)))
 			*pinctl |= AC_PINCTL_VREF_80;
 		if ((location & 0x0f) == AC_JACK_LOC_FRONT)
 			return "Front Mic";
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 9fd34f8..1a7e821 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -83,6 +83,7 @@
 			 "{Intel, ICH7},"
 			 "{Intel, ESB2},"
 			 "{Intel, ICH8},"
+			 "{Intel, ICH9},"
 			 "{ATI, SB450},"
 			 "{ATI, SB600},"
 			 "{ATI, RS600},"
@@ -1711,6 +1712,8 @@
 	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
 	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
 	{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
+	{ 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+	{ 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
 	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
 	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
 	{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
@@ -1718,9 +1721,14 @@
 	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
 	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
 	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
-	{ 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */
-	{ 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */
-	{ 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 03f0 */
+	{ 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
+	{ 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
+	{ 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+	{ 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+	{ 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+	{ 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+	{ 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+	{ 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 3d7f36f..19bdcc7 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2471,7 +2471,13 @@
 		fp->nr_rates = nr_rates;
 		fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
 		for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
-			unsigned int rate = fp->rate_table[r] = combine_triple(&fmt[idx]);
+			unsigned int rate = combine_triple(&fmt[idx]);
+			/* C-Media CM6501 mislabels its 96 kHz altsetting */
+			if (rate == 48000 && nr_rates == 1 &&
+			    chip->usb_id == USB_ID(0x0d8c, 0x0201) &&
+			    fp->altsetting == 5 && fp->maxpacksize == 392)
+				rate = 96000;
+			fp->rate_table[r] = rate;
 			if (rate < fp->rate_min)
 				fp->rate_min = rate;
 			else if (rate > fp->rate_max)
@@ -3280,6 +3286,7 @@
 
 static int snd_usb_audio_free(struct snd_usb_audio *chip)
 {
+	usb_chip[chip->index] = NULL;
 	kfree(chip);
 	return 0;
 }
@@ -3541,7 +3548,6 @@
 		list_for_each(p, &chip->mixer_list) {
 			snd_usb_mixer_disconnect(p);
 		}
-		usb_chip[chip->index] = NULL;
 		mutex_unlock(&register_mutex);
 		snd_card_free_when_closed(card);
 	} else {
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index e74eb1b..7b3bf35 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1526,7 +1526,7 @@
 		namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
 		if (! namelist[i]) {
 			snd_printk(KERN_ERR "cannot malloc\n");
-			while (--i > 0)
+			while (i--)
 				kfree(namelist[i]);
 			kfree(namelist);
 			kfree(cval);
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 367f8a3..0a352e4 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -322,7 +322,7 @@
 		usX2Y_error_urb_status(usX2Y, subs, urb);
 		return;
 	}
-	if (likely(urb->start_frame == usX2Y->wait_iso_frame))
+	if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
 		subs->completed_urb = urb;
 	else {
 		usX2Y_error_sequence(usX2Y, subs, urb);
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 8f3e35e..a5e7bcd 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -243,7 +243,7 @@
 		usX2Y_error_urb_status(usX2Y, subs, urb);
 		return;
 	}
-	if (likely(urb->start_frame == usX2Y->wait_iso_frame))
+	if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
 		subs->completed_urb = urb;
 	else {
 		usX2Y_error_sequence(usX2Y, subs, urb);