Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog: (33 commits)
  [WATCHDOG] remove experimental on iTCO_wdt.c
  [WATCHDOG] Atmel AT91RM9200 rename.
  [WATCHDOG] includes for sample watchdog program.
  [WATCHDOG] watchdog/iTCO_wdt: fix bug related to gcc uninit warning
  [WATCHDOG] add ich8 support to iTCO_wdt.c (patch 2)
  [WATCHDOG] add ich8 support to iTCO_wdt.c
  [WATCHDOG] ioremap balanced with iounmap for drivers/char/watchdog/s3c2410_wdt.c
  [WATCHDOG] w83697hf/hg WDT driver - Kconfig patch
  [WATCHDOG] w83697hf/hg WDT driver - autodetect patch
  [WATCHDOG] w83697hf/hg WDT driver - patch 16
  [WATCHDOG] w83697hf/hg WDT driver - patch 15
  [WATCHDOG] w83697hf/hg WDT driver - patch 14
  [WATCHDOG] w83697hf/hg WDT driver - patch 13
  [WATCHDOG] w83697hf/hg WDT driver - patch 12
  [WATCHDOG] w83697hf/hg WDT driver - patch 11
  [WATCHDOG] w83697hf/hg WDT driver - patch 10
  [WATCHDOG] w83697hf/hg WDT driver - patch 9
  [WATCHDOG] w83697hf/hg WDT driver - patch 8
  [WATCHDOG] w83697hf/hg WDT driver - patch 7
  [WATCHDOG] w83697hf/hg WDT driver - patch 6
  ...
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index d6f3dd1..8d51c14 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -395,6 +395,26 @@
 
 
 
+Managing bug reports
+--------------------
+
+One of the best ways to put into practice your hacking skills is by fixing
+bugs reported by other people. Not only you will help to make the kernel
+more stable, you'll learn to fix real world problems and you will improve
+your skills, and other developers will be aware of your presence. Fixing
+bugs is one of the best ways to get merits among other developers, because
+not many people like wasting time fixing other people's bugs.
+
+To work in the already reported bug reports, go to http://bugzilla.kernel.org.
+If you want to be advised of the future bug reports, you can subscribe to the
+bugme-new mailing list (only new bug reports are mailed here) or to the
+bugme-janitor mailing list (every change in the bugzilla is mailed here)
+
+	http://lists.osdl.org/mailman/listinfo/bugme-new
+	http://lists.osdl.org/mailman/listinfo/bugme-janitors
+
+
+
 Mailing lists
 -------------
 
diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt
index c70306a..5c34910 100644
--- a/Documentation/MSI-HOWTO.txt
+++ b/Documentation/MSI-HOWTO.txt
@@ -470,7 +470,68 @@
 ERR:          0
 MIS:          0
 
-6. FAQ
+6. MSI quirks
+
+Several PCI chipsets or devices are known to not support MSI.
+The PCI stack provides 3 possible levels of MSI disabling:
+* on a single device
+* on all devices behind a specific bridge
+* globally
+
+6.1. Disabling MSI on a single device
+
+Under some circumstances, it might be required to disable MSI on a
+single device, It may be achived by either not calling pci_enable_msi()
+or all, or setting the pci_dev->no_msi flag before (most of the time
+in a quirk).
+
+6.2. Disabling MSI below a bridge
+
+The vast majority of MSI quirks are required by PCI bridges not
+being able to route MSI between busses. In this case, MSI have to be
+disabled on all devices behind this bridge. It is achieves by setting
+the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge
+subordinate bus. There is no need to set the same flag on bridges that
+are below the broken brigde. When pci_enable_msi() is called to enable
+MSI on a device, pci_msi_supported() takes care of checking the NO_MSI
+flag in all parent busses of the device.
+
+Some bridges actually support dynamic MSI support enabling/disabling
+by changing some bits in their PCI configuration space (especially
+the Hypertransport chipsets such as the nVidia nForce and Serverworks
+HT2000). It may then be required to update the NO_MSI flag on the
+corresponding devices in the sysfs hierarchy. To enable MSI support
+on device "0000:00:0e", do:
+
+	echo 1 > /sys/bus/pci/devices/0000:00:0e/msi_bus
+
+To disable MSI support, echo 0 instead of 1. Note that it should be
+used with caution since changing this value might break interrupts.
+
+6.3. Disabling MSI globally
+
+Some extreme cases may require to disable MSI globally on the system.
+For now, the only known case is a Serverworks PCI-X chipsets (MSI are
+not supported on several busses that are not all connected to the
+chipset in the Linux PCI hierarchy). In the vast majority of other
+cases, disabling only behind a specific bridge is enough.
+
+For debugging purpose, the user may also pass pci=nomsi on the kernel
+command-line to explicitly disable MSI globally. But, once the appro-
+priate quirks are added to the kernel, this option should not be
+required anymore.
+
+6.4. Finding why MSI cannot be enabled on a device
+
+Assuming that MSI are not enabled on a device, you should look at
+dmesg to find messages that quirks may output when disabling MSI
+on some devices, some bridges or even globally.
+Then, lspci -t gives the list of bridges above a device. Reading
+/sys/bus/pci/devices/0000:00:0e/msi_bus will tell you whether MSI
+are enabled (1) or disabled (0). In 0 is found in a single bridge
+msi_bus file above the device, MSI cannot be enabled.
+
+7. FAQ
 
 Q1. Are there any limitations on using the MSI?
 
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index bc107cb..4868c34 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -46,7 +46,7 @@
              maxcpus=2 will only boot 2. You can choose to bring the
              other cpus later online, read FAQ's for more info.
 
-additional_cpus*=n	Use this to limit hotpluggable cpus. This option sets
+additional_cpus=n (*)	Use this to limit hotpluggable cpus. This option sets
   			cpu_possible_map = cpu_present_map + additional_cpus
 
 (*) Option valid only for following architectures
@@ -101,15 +101,15 @@
 
 Never use anything other than cpumask_t to represent bitmap of CPUs.
 
-#include <linux/cpumask.h>
+	#include <linux/cpumask.h>
 
-for_each_possible_cpu     - Iterate over cpu_possible_map
-for_each_online_cpu       - Iterate over cpu_online_map
-for_each_present_cpu      - Iterate over cpu_present_map
-for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
+	for_each_possible_cpu     - Iterate over cpu_possible_map
+	for_each_online_cpu       - Iterate over cpu_online_map
+	for_each_present_cpu      - Iterate over cpu_present_map
+	for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
 
-#include <linux/cpu.h>
-lock_cpu_hotplug() and unlock_cpu_hotplug():
+	#include <linux/cpu.h>
+	lock_cpu_hotplug() and unlock_cpu_hotplug():
 
 The above calls are used to inhibit cpu hotplug operations. While holding the
 cpucontrol mutex, cpu_online_map will not change. If you merely need to avoid
@@ -120,7 +120,7 @@
 
 CPU Hotplug - Frequently Asked Questions.
 
-Q: How to i enable my kernel to support CPU hotplug?
+Q: How to enable my kernel to support CPU hotplug?
 A: When doing make defconfig, Enable CPU hotplug support
 
    "Processor type and Features" -> Support for Hotpluggable CPUs
@@ -141,39 +141,39 @@
 Check if sysfs is mounted, using the "mount" command. You should notice
 an entry as shown below in the output.
 
-....
-none on /sys type sysfs (rw)
-....
+	....
+	none on /sys type sysfs (rw)
+	....
 
-if this is not mounted, do the following.
+If this is not mounted, do the following.
 
-#mkdir /sysfs
-#mount -t sysfs sys /sys
+	 #mkdir /sysfs
+	#mount -t sysfs sys /sys
 
-now you should see entries for all present cpu, the following is an example
+Now you should see entries for all present cpu, the following is an example
 in a 8-way system.
 
-#pwd
-#/sys/devices/system/cpu
-#ls -l
-total 0
-drwxr-xr-x  10 root root 0 Sep 19 07:44 .
-drwxr-xr-x  13 root root 0 Sep 19 07:45 ..
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu0
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu1
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu2
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu3
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu4
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu5
-drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu6
-drwxr-xr-x   3 root root 0 Sep 19 07:48 cpu7
+	#pwd
+	#/sys/devices/system/cpu
+	#ls -l
+	total 0
+	drwxr-xr-x  10 root root 0 Sep 19 07:44 .
+	drwxr-xr-x  13 root root 0 Sep 19 07:45 ..
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu0
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu1
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu2
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu3
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu4
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu5
+	drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu6
+	drwxr-xr-x   3 root root 0 Sep 19 07:48 cpu7
 
 Under each directory you would find an "online" file which is the control
 file to logically online/offline a processor.
 
 Q: Does hot-add/hot-remove refer to physical add/remove of cpus?
 A: The usage of hot-add/remove may not be very consistently used in the code.
-CONFIG_CPU_HOTPLUG enables logical online/offline capability in the kernel.
+CONFIG_HOTPLUG_CPU enables logical online/offline capability in the kernel.
 To support physical addition/removal, one would need some BIOS hooks and
 the platform should have something like an attention button in PCI hotplug.
 CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs.
@@ -181,17 +181,17 @@
 Q: How do i logically offline a CPU?
 A: Do the following.
 
-#echo 0 > /sys/devices/system/cpu/cpuX/online
+	#echo 0 > /sys/devices/system/cpu/cpuX/online
 
-once the logical offline is successful, check
+Once the logical offline is successful, check
 
-#cat /proc/interrupts
+	#cat /proc/interrupts
 
-you should now not see the CPU that you removed. Also online file will report
+You should now not see the CPU that you removed. Also online file will report
 the state as 0 when a cpu if offline and 1 when its online.
 
-#To display the current cpu state.
-#cat /sys/devices/system/cpu/cpuX/online
+	#To display the current cpu state.
+	#cat /sys/devices/system/cpu/cpuX/online
 
 Q: Why cant i remove CPU0 on some systems?
 A: Some architectures may have some special dependency on a certain CPU.
@@ -234,8 +234,8 @@
    departure, how to i arrange for proper notification?
 A: This is what you would need in your kernel code to receive notifications.
 
-    #include <linux/cpu.h>
-    static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb,
+	#include <linux/cpu.h>
+	static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb,
 					    unsigned long action, void *hcpu)
 	{
 		unsigned int cpu = (unsigned long)hcpu;
@@ -279,10 +279,10 @@
 A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
    If you need to perform some action for each cpu already in the system, then
 
-  for_each_online_cpu(i) {
+	for_each_online_cpu(i) {
 		foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i);
-		foobar_cpu_callback(&foobar-cpu_notifier, CPU_ONLINE, i);
-  }
+		foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i);
+	}
 
 Q: If i would like to develop cpu hotplug support for a new architecture,
    what do i need at a minimum?
@@ -307,38 +307,38 @@
    work specific to this cpu is in progress.
 A: First switch the current thread context to preferred cpu
 
-   int my_func_on_cpu(int cpu)
-   {
-       cpumask_t saved_mask, new_mask = CPU_MASK_NONE;
-       int curr_cpu, err = 0;
+	int my_func_on_cpu(int cpu)
+	{
+		cpumask_t saved_mask, new_mask = CPU_MASK_NONE;
+		int curr_cpu, err = 0;
 
-       saved_mask = current->cpus_allowed;
-       cpu_set(cpu, new_mask);
-       err = set_cpus_allowed(current, new_mask);
+		saved_mask = current->cpus_allowed;
+		cpu_set(cpu, new_mask);
+		err = set_cpus_allowed(current, new_mask);
 
-       if (err)
-           return err;
+		if (err)
+			return err;
 
-       /*
-        * If we got scheduled out just after the return from
-        * set_cpus_allowed() before running the work, this ensures
-        * we stay locked.
-        */
-       curr_cpu = get_cpu();
+		/*
+		 * If we got scheduled out just after the return from
+		 * set_cpus_allowed() before running the work, this ensures
+		 * we stay locked.
+		 */
+		curr_cpu = get_cpu();
 
-       if (curr_cpu != cpu) {
-	   err = -EAGAIN;
-           goto ret;
-       } else {
-       	   /*
-	    * Do work : But cant sleep, since get_cpu() disables preempt
-	    */
-       }
-    ret:
-    	put_cpu();
-	set_cpus_allowed(current, saved_mask);
-	return err;
-    }
+		if (curr_cpu != cpu) {
+			err = -EAGAIN;
+			goto ret;
+		} else {
+			/*
+			 * Do work : But cant sleep, since get_cpu() disables preempt
+			 */
+		}
+		ret:
+			put_cpu();
+			set_cpus_allowed(current, saved_mask);
+			return err;
+		}
 
 
 Q: How do we determine how many CPUs are available for hotplug.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 24f3c63..1ac3c74 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -255,7 +255,7 @@
 
 
 What:	PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
-When:	Oktober 2008
+When:	October 2008
 Why:	The stacking of class devices makes these values misleading and
 	inconsistent.
 	Class devices should not carry any of these properties, and bus
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 3c384c0..4dc28cc 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -34,6 +34,8 @@
 	- info, mount options and specifications for the Ext2 filesystem.
 ext3.txt
 	- info, mount options and specifications for the Ext3 filesystem.
+ext4.txt
+	- info, mount options and specifications for the Ext4 filesystem.
 files.txt
 	- info on file management in the Linux kernel.
 fuse.txt
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
new file mode 100644
index 0000000..6a4adca
--- /dev/null
+++ b/Documentation/filesystems/ext4.txt
@@ -0,0 +1,236 @@
+
+Ext4 Filesystem
+===============
+
+This is a development version of the ext4 filesystem, an advanced level
+of the ext3 filesystem which incorporates scalability and reliability
+enhancements for supporting large filesystems (64 bit) in keeping with
+increasing disk capacities and state-of-the-art feature requirements.
+
+Mailing list: linux-ext4@vger.kernel.org
+
+
+1. Quick usage instructions:
+===========================
+
+  - Grab updated e2fsprogs from
+    ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs-interim/
+    This is a patchset on top of e2fsprogs-1.39, which can be found at
+    ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/
+
+  - It's still mke2fs -j /dev/hda1
+
+  - mount /dev/hda1 /wherever -t ext4dev
+
+  - To enable extents,
+
+	mount /dev/hda1 /wherever -t ext4dev -o extents
+
+  - The filesystem is compatible with the ext3 driver until you add a file
+    which has extents (ie: `mount -o extents', then create a file).
+
+    NOTE: The "extents" mount flag is temporary.  It will soon go away and
+    extents will be enabled by the "-o extents" flag to mke2fs or tune2fs
+
+  - When comparing performance with other filesystems, remember that
+    ext3/4 by default offers higher data integrity guarantees than most.  So
+    when comparing with a metadata-only journalling filesystem, use `mount -o
+    data=writeback'.  And you might as well use `mount -o nobh' too along
+    with it.  Making the journal larger than the mke2fs default often helps
+    performance with metadata-intensive workloads.
+
+2. Features
+===========
+
+2.1 Currently available
+
+* ability to use filesystems > 16TB
+* extent format reduces metadata overhead (RAM, IO for access, transactions)
+* extent format more robust in face of on-disk corruption due to magics,
+* internal redunancy in tree
+
+2.1 Previously available, soon to be enabled by default by "mkefs.ext4":
+
+* dir_index and resize inode will be on by default
+* large inodes will be used by default for fast EAs, nsec timestamps, etc
+
+2.2 Candidate features for future inclusion
+
+There are several under discussion, whether they all make it in is
+partly a function of how much time everyone has to work on them:
+
+* improved file allocation (multi-block alloc, delayed alloc; basically done)
+* fix 32000 subdirectory limit (patch exists, needs some e2fsck work)
+* nsec timestamps for mtime, atime, ctime, create time (patch exists,
+  needs some e2fsck work)
+* inode version field on disk (NFSv4, Lustre; prototype exists)
+* reduced mke2fs/e2fsck time via uninitialized groups (prototype exists)
+* journal checksumming for robustness, performance (prototype exists)
+* persistent file preallocation (e.g for streaming media, databases)
+
+Features like metadata checksumming have been discussed and planned for
+a bit but no patches exist yet so I'm not sure they're in the near-term
+roadmap.
+
+The big performance win will come with mballoc and delalloc.  CFS has
+been using mballoc for a few years already with Lustre, and IBM + Bull
+did a lot of benchmarking on it.  The reason it isn't in the first set of
+patches is partly a manageability issue, and partly because it doesn't
+directly affect the on-disk format (outside of much better allocation)
+so it isn't critical to get into the first round of changes.  I believe
+Alex is working on a new set of patches right now.
+
+3. Options
+==========
+
+When mounting an ext4 filesystem, the following option are accepted:
+(*) == default
+
+extents			ext4 will use extents to address file data.  The
+			file system will no longer be mountable by ext3.
+
+journal=update		Update the ext4 file system's journal to the current
+			format.
+
+journal=inum		When a journal already exists, this option is ignored.
+			Otherwise, it specifies the number of the inode which
+			will represent the ext4 file system's journal file.
+
+journal_dev=devnum	When the external journal device's major/minor numbers
+			have changed, this option allows the user to specify
+			the new journal location.  The journal device is
+			identified through its new major/minor numbers encoded
+			in devnum.
+
+noload			Don't load the journal on mounting.
+
+data=journal		All data are committed into the journal prior to being
+			written into the main file system.
+
+data=ordered	(*)	All data are forced directly out to the main file
+			system prior to its metadata being committed to the
+			journal.
+
+data=writeback		Data ordering is not preserved, data may be written
+			into the main file system after its metadata has been
+			committed to the journal.
+
+commit=nrsec	(*)	Ext4 can be told to sync all its data and metadata
+			every 'nrsec' seconds. The default value is 5 seconds.
+			This means that if you lose your power, you will lose
+			as much as the latest 5 seconds of work (your
+			filesystem will not be damaged though, thanks to the
+			journaling).  This default value (or any low value)
+			will hurt performance, but it's good for data-safety.
+			Setting it to 0 will have the same effect as leaving
+			it at the default (5 seconds).
+			Setting it to very large values will improve
+			performance.
+
+barrier=1		This enables/disables barriers.  barrier=0 disables
+			it, barrier=1 enables it.
+
+orlov		(*)	This enables the new Orlov block allocator. It is
+			enabled by default.
+
+oldalloc		This disables the Orlov block allocator and enables
+			the old block allocator.  Orlov should have better
+			performance - we'd like to get some feedback if it's
+			the contrary for you.
+
+user_xattr		Enables Extended User Attributes.  Additionally, you
+			need to have extended attribute support enabled in the
+			kernel configuration (CONFIG_EXT4_FS_XATTR).  See the
+			attr(5) manual page and http://acl.bestbits.at/ to
+			learn more about extended attributes.
+
+nouser_xattr		Disables Extended User Attributes.
+
+acl			Enables POSIX Access Control Lists support.
+			Additionally, you need to have ACL support enabled in
+			the kernel configuration (CONFIG_EXT4_FS_POSIX_ACL).
+			See the acl(5) manual page and http://acl.bestbits.at/
+			for more information.
+
+noacl			This option disables POSIX Access Control List
+			support.
+
+reservation
+
+noreservation
+
+bsddf		(*)	Make 'df' act like BSD.
+minixdf			Make 'df' act like Minix.
+
+check=none		Don't do extra checking of bitmaps on mount.
+nocheck
+
+debug			Extra debugging information is sent to syslog.
+
+errors=remount-ro(*)	Remount the filesystem read-only on an error.
+errors=continue		Keep going on a filesystem error.
+errors=panic		Panic and halt the machine if an error occurs.
+
+grpid			Give objects the same group ID as their creator.
+bsdgroups
+
+nogrpid		(*)	New objects have the group ID of their creator.
+sysvgroups
+
+resgid=n		The group ID which may use the reserved blocks.
+
+resuid=n		The user ID which may use the reserved blocks.
+
+sb=n			Use alternate superblock at this location.
+
+quota
+noquota
+grpquota
+usrquota
+
+bh		(*)	ext4 associates buffer heads to data pages to
+nobh			(a) cache disk block mapping information
+			(b) link pages into transaction to provide
+			    ordering guarantees.
+			"bh" option forces use of buffer heads.
+			"nobh" option tries to avoid associating buffer
+			heads (supported only for "writeback" mode).
+
+
+Data Mode
+---------
+There are 3 different data modes:
+
+* writeback mode
+In data=writeback mode, ext4 does not journal data at all.  This mode provides
+a similar level of journaling as that of XFS, JFS, and ReiserFS in its default
+mode - metadata journaling.  A crash+recovery can cause incorrect data to
+appear in files which were written shortly before the crash.  This mode will
+typically provide the best ext4 performance.
+
+* ordered mode
+In data=ordered mode, ext4 only officially journals metadata, but it logically
+groups metadata and data blocks into a single unit called a transaction.  When
+it's time to write the new metadata out to disk, the associated data blocks
+are written first.  In general, this mode performs slightly slower than
+writeback but significantly faster than journal mode.
+
+* journal mode
+data=journal mode provides full data and metadata journaling.  All new data is
+written to the journal first, and then to its final location.
+In the event of a crash, the journal can be replayed, bringing both data and
+metadata into a consistent state.  This mode is the slowest except when data
+needs to be read from and written to disk at the same time where it
+outperforms all others modes.
+
+References
+==========
+
+kernel source:	<file:fs/ext4/>
+		<file:fs/jbd2/>
+
+programs:	http://e2fsprogs.sourceforge.net/
+		http://ext2resize.sourceforge.net
+
+useful links:	http://fedoraproject.org/wiki/ext3-devel
+		http://www.bullopensource.org/ext4/
diff --git a/Documentation/hwmon/adm9240 b/Documentation/hwmon/adm9240
index 35f618f..2c6f1fe 100644
--- a/Documentation/hwmon/adm9240
+++ b/Documentation/hwmon/adm9240
@@ -24,7 +24,7 @@
     Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>,
     Michiel Rook <michiel@grendelproject.nl>,
-    Grant Coady <gcoady@gmail.com> with guidance
+    Grant Coady <gcoady.lk@gmail.com> with guidance
         from Jean Delvare <khali@linux-fr.org>
 
 Interface
diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f
index 28c5b7d..2ca69df 100644
--- a/Documentation/hwmon/f71805f
+++ b/Documentation/hwmon/f71805f
@@ -17,7 +17,7 @@
 providing additional documentation.
 
 Thanks to Chris Lin from Jetway for providing wiring schematics and
-anwsering technical questions.
+answering technical questions.
 
 
 Description
diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp
index bab445a..30d123b 100644
--- a/Documentation/hwmon/k8temp
+++ b/Documentation/hwmon/k8temp
@@ -2,7 +2,7 @@
 ====================
 
 Supported chips:
-  * AMD K8 CPU
+  * AMD Athlon64/FX or Opteron CPUs
     Prefix: 'k8temp'
     Addresses scanned: PCI space
     Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
@@ -13,10 +13,13 @@
 Description
 -----------
 
-This driver permits reading temperature sensor(s) embedded inside AMD K8 CPUs.
-Official documentation says that it works from revision F of K8 core, but
-in fact it seems to be implemented for all revisions of K8 except the first
-two revisions (SH-B0 and SH-B3).
+This driver permits reading temperature sensor(s) embedded inside AMD K8
+family CPUs (Athlon64/FX, Opteron). Official documentation says that it works
+from revision F of K8 core, but in fact it seems to be implemented for all
+revisions of K8 except the first two revisions (SH-B0 and SH-B3).
+
+Please note that you will need at least lm-sensors 2.10.1 for proper userspace
+support.
 
 There can be up to four temperature sensors inside single CPU. The driver
 will auto-detect the sensors and will display only temperatures from
diff --git a/Documentation/hwmon/smsc47m1 b/Documentation/hwmon/smsc47m1
index c15bbe6..04a1112 100644
--- a/Documentation/hwmon/smsc47m1
+++ b/Documentation/hwmon/smsc47m1
@@ -2,12 +2,14 @@
 ======================
 
 Supported chips:
-  * SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192
+  * SMSC LPC47B27x, LPC47M112, LPC47M10x, LPC47M13x, LPC47M14x,
+    LPC47M15x and LPC47M192
     Addresses scanned: none, address read from Super I/O config space
     Prefix: 'smsc47m1'
     Datasheets:
         http://www.smsc.com/main/datasheets/47b27x.pdf
         http://www.smsc.com/main/datasheets/47m10x.pdf
+        http://www.smsc.com/main/datasheets/47m112.pdf
         http://www.smsc.com/main/tools/discontinued/47m13x.pdf
         http://www.smsc.com/main/datasheets/47m14x.pdf
         http://www.smsc.com/main/tools/discontinued/47m15x.pdf
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index fae3b78..caa610a 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -26,7 +26,7 @@
 Temperatures are measured in degrees Celsius and measurement resolution is 1
 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
 the temperature gets higher than high limit; it stays on until the temperature
-falls below the Hysteresis value.
+falls below the hysteresis value.
 
 Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
 triggered if the rotation speed has dropped below a programmable limit. Fan
@@ -67,9 +67,9 @@
 
 If the temperature is in the range defined by:
 
-pwm[1-4]_target    - set target temperature, unit millidegree Celcius
+pwm[1-4]_target    - set target temperature, unit millidegree Celsius
 		     (range 0 - 127000)
-pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (range 0 - 15000)
+pwm[1-4]_tolerance - tolerance, unit millidegree Celsius (range 0 - 15000)
 
 there are no changes to fan speed. Once the temperature leaves the interval,
 fan speed increases (temp is higher) or decreases if lower than desired.
diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt
index 71aa403..e50595b 100644
--- a/Documentation/ibm-acpi.txt
+++ b/Documentation/ibm-acpi.txt
@@ -30,9 +30,10 @@
 	- ACPI sounds
 	- temperature sensors
 	- Experimental: embedded controller register dump
-	- Experimental: LCD brightness control
-	- Experimental: volume control
+	- LCD brightness control
+	- Volume control
 	- Experimental: fan speed, fan enable/disable
+	- Experimental: WAN enable and disable
 
 A compatibility table by model and feature is maintained on the web
 site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -52,40 +53,7 @@
 
 If you are compiling this driver as included in the Linux kernel
 sources, simply enable the CONFIG_ACPI_IBM option (Power Management /
-ACPI / IBM ThinkPad Laptop Extras). The rest of this section describes
-how to install this driver when downloaded from the web site.
-
-First, you need to get a kernel with ACPI support up and running.
-Please refer to http://acpi.sourceforge.net/ for help with this
-step. How successful you will be depends a lot on you ThinkPad model,
-the kernel you are using and any additional patches applied. The
-kernel provided with your distribution may not be good enough. I
-needed to compile a 2.6.7 kernel with the 20040715 ACPI patch to get
-ACPI working reliably on my ThinkPad X40. Old ThinkPad models may not
-be supported at all.
-
-Assuming you have the basic ACPI support working (e.g. you can see the
-/proc/acpi directory), follow the following steps to install this
-driver:
-
-	- unpack the archive:
-
-		tar xzvf ibm-acpi-x.y.tar.gz; cd ibm-acpi-x.y
-
-	- compile the driver:
-
-		make
-
-	- install the module in your kernel modules directory:
-
-		make install
-
-	- load the module:
-
-		modprobe ibm_acpi
-
-After loading the module, check the "dmesg" output for any error messages.
-
+ACPI / IBM ThinkPad Laptop Extras).
 
 Features
 --------
@@ -523,13 +491,8 @@
 with this, do send me your results (including some complete dumps with
 a description of the conditions when they were taken.)
 
-EXPERIMENTAL: LCD brightness control -- /proc/acpi/ibm/brightness
------------------------------------------------------------------
-
-This feature is marked EXPERIMENTAL because the implementation
-directly accesses hardware registers and may not work as expected. USE
-WITH CAUTION! To use this feature, you need to supply the
-experimental=1 parameter when loading the module.
+LCD brightness control -- /proc/acpi/ibm/brightness
+---------------------------------------------------
 
 This feature allows software control of the LCD brightness on ThinkPad
 models which don't have a hardware brightness slider. The available
@@ -542,13 +505,8 @@
 The <level> number range is 0 to 7, although not all of them may be
 distinct. The current brightness level is shown in the file.
 
-EXPERIMENTAL: Volume control -- /proc/acpi/ibm/volume
------------------------------------------------------
-
-This feature is marked EXPERIMENTAL because the implementation
-directly accesses hardware registers and may not work as expected. USE
-WITH CAUTION! To use this feature, you need to supply the
-experimental=1 parameter when loading the module.
+Volume control -- /proc/acpi/ibm/volume
+---------------------------------------
 
 This feature allows volume control on ThinkPad models which don't have
 a hardware volume knob. The available commands are:
@@ -611,6 +569,23 @@
 
 	echo 'level <level>' > /proc/acpi/ibm/thermal
 
+EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
+---------------------------------------
+
+This feature is marked EXPERIMENTAL because the implementation
+directly accesses hardware registers and may not work as expected. USE
+WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module.
+
+This feature shows the presence and current state of a WAN (Sierra
+Wireless EV-DO) device. If WAN is installed, the following commands can
+be used:
+
+	echo enable > /proc/acpi/ibm/wan
+	echo disable > /proc/acpi/ibm/wan
+
+It was tested on a Lenovo Thinkpad X60. It should probably work on other
+Thinkpad models which come with this module installed.
 
 Multiple Commands, Module Parameters
 ------------------------------------
diff --git a/Documentation/input/xpad.txt b/Documentation/input/xpad.txt
index b9111a7..5427bdf 100644
--- a/Documentation/input/xpad.txt
+++ b/Documentation/input/xpad.txt
@@ -3,20 +3,37 @@
 This is the very first release of a driver for X-Box gamepads.
 Basically, this was hacked away in just a few hours, so don't expect
 miracles.
+
 In particular, there is currently NO support for the rumble pack.
 You won't find many ff-aware linux applications anyway.
 
 
-0. Status
----------
+0. Notes
+--------
 
-For now, this driver has only been tested on just one Linux-Box.
-This one is running a 2.4.18 kernel with usb-uhci on an amd athlon 600.
+Driver updated for kernel 2.6.17.11. (Based on a patch for 2.6.11.4.)
 
-The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) reports
-8 axes and 10 buttons.
+The number of buttons/axes reported varies based on 3 things:
+- if you are using a known controller
+- if you are using a known dance pad
+- if using an unknown device (one not listed below), what you set in the
+  module configuration for "Map D-PAD to buttons rather than axes for unknown
+  pads" (module option dpad_to_buttons)
 
-Alls 8 axes work, though they all have the same range (-32768..32767)
+If you set dpad_to_buttons to 0 and you are using an unknown device (one
+not listed below), the driver will map the directional pad to axes (X/Y),
+if you said N it will map the d-pad to buttons, which is needed for dance
+style games to function correctly.  The default is Y.
+
+dpad_to_buttons has no effect for known pads.
+
+0.1 Normal Controllers
+----------------------
+With a normal controller, the directional pad is mapped to its own X/Y axes.
+The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) will report 8
+axes and 10 buttons.
+
+All 8 axes work, though they all have the same range (-32768..32767)
 and the zero-setting is not correct for the triggers (I don't know if that
 is some limitation of jstest, since the input device setup should be fine. I
 didn't have a look at jstest itself yet).
@@ -30,16 +47,50 @@
 play first person shooters with a pad. Your mileage may vary.
 
 
+0.2 Xbox Dance Pads
+-------------------
+When using a known dance pad, jstest will report 6 axes and 14 buttons.
+
+For dance style pads (like the redoctane pad) several changes
+have been made.  The old driver would map the d-pad to axes, resulting
+in the driver being unable to report when the user was pressing both
+left+right or up+down, making DDR style games unplayable.
+
+Known dance pads automatically map the d-pad to buttons and will work
+correctly out of the box.
+
+If your dance pad is recognized by the driver but is using axes instead
+of buttons, see section 0.3 - Unknown Controllers
+
+I've tested this with Stepmania, and it works quite well.
+
+
+0.3 Unkown Controllers
+----------------------
+If you have an unkown xbox controller, it should work just fine with
+the default settings.
+
+HOWEVER if you have an unknown dance pad not listed below, it will not
+work UNLESS you set "dpad_to_buttons" to 1 in the module configuration.
+
+PLEASE if you have an unkown controller, email Dom <binary1230@yahoo.com> with
+a dump from /proc/bus/usb and a description of the pad (manufacturer, country,
+whether it is a dance pad or normal controller) so that we can add your pad
+to the list of supported devices, ensuring that it will work out of the
+box in the future.
+
+
 1. USB adapter
 --------------
 
 Before you can actually use the driver, you need to get yourself an
-adapter cable to connect the X-Box controller to your Linux-Box.
+adapter cable to connect the X-Box controller to your Linux-Box. You
+can buy these online fairly cheap, or build your own.
 
-Such a cable is pretty easy to build. The Controller itself is a USB compound
-device (a hub with three ports for two expansion slots and the controller
-device) with the only difference in a nonstandard connector (5 pins vs. 4 on
-standard USB connector).
+Such a cable is pretty easy to build. The Controller itself is a USB
+compound device (a hub with three ports for two expansion slots and
+the controller device) with the only difference in a nonstandard connector
+(5 pins vs. 4 on standard USB connector).
 
 You just need to solder a USB connector onto the cable and keep the
 yellow wire unconnected. The other pins have the same order on both
@@ -51,36 +102,36 @@
 you can still use the controller with your X-Box, if you have one ;)
 
 
-2. driver installation
+2. Driver Installation
 ----------------------
 
 Once you have the adapter cable and the controller is connected, you need
 to load your USB subsystem and should cat /proc/bus/usb/devices.
 There should be an entry like the one at the end [4].
 
-Currently (as of version 0.0.4), the following three devices are included:
+Currently (as of version 0.0.6), the following devices are included:
  original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202
+ smaller  Microsoft XBOX controller (US), vendor=0x045e, product=0x0289
  original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285
  InterAct PowerPad Pro (Germany), vendor=0x05fd, product=0x107a
+ RedOctane Xbox Dance Pad (US), vendor=0x0c12, product=0x8809
 
-If you have another controller that is not listed above and is not recognized
-by the driver, please drop me a line with the appropriate info (that is, include
-the name, vendor and product ID, as well as the country where you bought it;
-sending the whole dump out of /proc/bus/usb/devices along would be even better).
+The driver should work with xbox pads not listed above as well, however
+you will need to do something extra for dance pads to work.
 
-In theory, the driver should work with other controllers than mine
-(InterAct PowerPad pro, bought in Germany) just fine, but I cannot test this
-for I only have this one controller.
+If you have a controller not listed above, see 0.3 - Unknown Controllers
 
 If you compiled and installed the driver, test the functionality:
 > modprobe xpad
 > modprobe joydev
 > jstest /dev/js0
 
-There should be a single line showing 18 inputs (8 axes, 10 buttons), and
-it's values should change if you move the sticks and push the buttons.
+If you're using a normal controller, there should be a single line showing
+18 inputs (8 axes, 10 buttons), and its values should change if you move
+the sticks and push the buttons.  If you're using a dance pad, it should
+show 20 inputs (6 axes, 14 buttons).
 
-It works? Voila, your done ;)
+It works? Voila, you're done ;)
 
 
 3. Thanks
@@ -111,6 +162,22 @@
 E:  Ad=81(I) Atr=03(Int.) MxPS=  32 Ivl= 10ms
 E:  Ad=02(O) Atr=03(Int.) MxPS=  32 Ivl= 10ms
 
+5. /proc/bus/usb/devices - dump from Redoctane Xbox Dance Pad (US):
+
+T:  Bus=01 Lev=02 Prnt=09 Port=00 Cnt=01 Dev#= 10 Spd=12  MxCh= 0
+D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+P:  Vendor=0c12 ProdID=8809 Rev= 0.01
+S:  Product=XBOX DDR
+C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=xpad
+E:  Ad=82(I) Atr=03(Int.) MxPS=  32 Ivl=4ms
+E:  Ad=02(O) Atr=03(Int.) MxPS=  32 Ivl=4ms
+
 -- 
 Marko Friedemann <mfr@bmx-chemnitz.de>
 2002-07-16
+ - original doc
+
+Dominic Cerquetti <binary1230@yahoo.com>
+2005-03-19
+ - added stuff for dance pads, new d-pad->axes mappings
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ff571f9..dd00fd5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1231,6 +1231,11 @@
 				machine check when some devices' config space
 				is read. But various workarounds are disabled
 				and some IOMMU drivers will not work.
+		bfsort		Sort PCI devices into breadth-first order.
+				This sorting is done to get a device
+				order compatible with older (<= 2.4) kernels.
+		nobfsort	Don't sort PCI devices into breadth-first order.
+
 	pcmv=		[HW,PCMCIA] BadgePAD 4
 
 	pd.		[PARIDE]
diff --git a/Documentation/lockdep-design.txt b/Documentation/lockdep-design.txt
index dab123d..4887730 100644
--- a/Documentation/lockdep-design.txt
+++ b/Documentation/lockdep-design.txt
@@ -50,10 +50,10 @@
 softirq-read respectively, and the character displayed in each
 indicates:
 
-   '.'	 acquired while irqs enabled
+   '.'  acquired while irqs disabled
    '+'  acquired in irq context
-   '-'  acquired in process context with irqs disabled
-   '?'  read-acquired both with irqs enabled and in irq context
+   '-'  acquired with irqs enabled
+   '?' read acquired in irq context with irqs enabled.
 
 Unused mutexes cannot be part of the cause of an error.
 
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 994355b..7f790f6 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1898,7 +1898,7 @@
 	smp_wmb();
 	<A:modify v=2>	<C:busy>
 			<C:queue v=2>
-	p = &b;		q = p;
+	p = &v;		q = p;
 			<D:request p>
 	<B:modify p=&v>	<D:commit p=&v>
 		  	<D:read p>
diff --git a/Documentation/mips/time.README b/Documentation/mips/time.README
index 69ddc5c..e1304b6 100644
--- a/Documentation/mips/time.README
+++ b/Documentation/mips/time.README
@@ -63,7 +63,7 @@
   a) board_time_init - a function pointer.  Invoked at the beginnig of
      time_init().  It is optional.
 	1. (optional) set up RTC routines
-	2. (optional) calibrate and set the mips_counter_frequency
+	2. (optional) calibrate and set the mips_hpt_frequency
 
   b) plat_timer_setup - a function pointer.  Invoked at the end of time_init()
 	1. (optional) over-ride any decisions made in time_init()
@@ -72,7 +72,7 @@
 
   c) (optional) board-specific RTC routines.
 
-  d) (optional) mips_counter_frequency - It must be definied if the board
+  d) (optional) mips_hpt_frequency - It must be definied if the board
      is using CPU counter for timer interrupt or it is using fixed rate
      gettimeoffset().
 
@@ -104,7 +104,7 @@
      or use an exnternal timer?
 
      In order to use CPU counter register as the timer interrupt source, you
-     must know the counter speed (mips_counter_frequency).  It is usually the
+     must know the counter speed (mips_hpt_frequency).  It is usually the
      same as the CPU speed or an integral divisor of it.
 
   d) decide on whether you want to use high-level or low-level timer
@@ -121,8 +121,8 @@
   if needed.
 
   board_time_init() -
-  	a) (optional) set up RTC routines, 
-        b) (optional) calibrate and set the mips_counter_frequency
+  	a) (optional) set up RTC routines,
+        b) (optional) calibrate and set the mips_hpt_frequency
  	    (only needed if you intended to use fixed_rate_gettimeoffset
  	     or use cpu counter as timer interrupt source)
 
diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO
index 59d1166..d684a6a 100644
--- a/Documentation/s390/CommonIO
+++ b/Documentation/s390/CommonIO
@@ -66,7 +66,7 @@
 
   When a device is un-ignored, device recognition and sensing is performed and 
   the device driver will be notified if possible, so the device will become
-  available to the system.
+  available to the system. Note that un-ignoring is performed asynchronously.
 
   You can also add ranges of devices to be ignored by piping to 
   /proc/cio_ignore; "add <device range>, <device range>, ..." will ignore the
diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt
index d80e573..32a96cc 100644
--- a/Documentation/s390/cds.txt
+++ b/Documentation/s390/cds.txt
@@ -174,14 +174,10 @@
 
 This routine returns the characteristics for the device specified.
 
-The function is meant to be called with an irq handler in place; that is,
+The function is meant to be called with the device already enabled; that is,
 at earliest during set_online() processing.
 
-While the request is processed synchronously, the device interrupt
-handler is called for final ending status. In case of error situations the
-interrupt handler may recover appropriately. The device irq handler can
-recognize the corresponding interrupts by the interruption parameter be
-0x00524443. The ccw_device must not be locked prior to calling read_dev_chars().
+The ccw_device must not be locked prior to calling read_dev_chars().
 
 The function may be called enabled or disabled.
 
@@ -410,26 +406,7 @@
 
 Usage Notes :
 
-Prior to call ccw_device_start() the device driver must assure disabled state,
-i.e. the I/O mask value in the PSW must be disabled. This can be accomplished
-by calling local_save_flags( flags). The current PSW flags are preserved and
-can be restored by local_irq_restore( flags) at a later time.
-
-If the device driver violates this rule while running in a uni-processor
-environment an interrupt might be presented prior to the ccw_device_start()
-routine returning to the device driver main path. In this case we will end in a
-deadlock situation as the interrupt handler will try to obtain the irq
-lock the device driver still owns (see below) !
-
-The driver must assure to hold the device specific lock. This can be
-accomplished by
-
-(i)  spin_lock(get_ccwdev_lock(cdev)), or
-(ii) spin_lock_irqsave(get_ccwdev_lock(cdev), flags)
-
-Option (i) should be used if the calling routine is running disabled for
-I/O interrupts (see above) already. Option (ii) obtains the device gate und
-puts the CPU into I/O disabled state by preserving the current PSW flags.
+ccw_device_start() must be called disabled and with the ccw device lock held.
 
 The device driver is allowed to issue the next ccw_device_start() call from
 within its interrupt handler already. It is not required to schedule a
@@ -488,7 +465,7 @@
 
 cdev - ccw_device the resume operation is requested for
 
-The resume_IO() function returns:
+The ccw_device_resume() function returns:
 
         0  - suspended channel program is resumed
 -EBUSY     - status pending
@@ -507,6 +484,8 @@
 a halt subchannel (HSCH) I/O command. For those purposes the ccw_device_halt()
 command is provided.
 
+ccw_device_halt() must be called disabled and with the ccw device lock held.
+
 int ccw_device_halt(struct ccw_device *cdev,
                     unsigned long intparm);
 
@@ -517,7 +496,7 @@
 
 The ccw_device_halt() function returns :
 
-      0 - successful completion or request successfully initiated
+      0 - request successfully initiated
 -EBUSY  - the device is currently busy, or status pending.
 -ENODEV - cdev invalid.
 -EINVAL - The device is not operational or the ccw device is not online.
@@ -533,6 +512,23 @@
 read to a network device (with or without PCI flag) a ccw_device_halt()
 is required to end the pending operation.
 
+ccw_device_clear() - Terminage I/O Request Processing
+
+In order to terminate all I/O processing at the subchannel, the clear subchannel
+(CSCH) command is used. It can be issued via ccw_device_clear().
+
+ccw_device_clear() must be called disabled and with the ccw device lock held.
+
+int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm);
+
+cdev:	 ccw_device the clear operation is requested for
+intparm: interruption parameter (see ccw_device_halt())
+
+The ccw_device_clear() function returns:
+
+      0 - request successfully initiated
+-ENODEV - cdev invalid
+-EINVAL - The device is not operational or the ccw device is not online.
 
 Miscellaneous Support Routines
 
diff --git a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt
index 62c0823..77bf450 100644
--- a/Documentation/s390/driver-model.txt
+++ b/Documentation/s390/driver-model.txt
@@ -239,6 +239,9 @@
 
 type - The physical type of the channel path.
 
+shared - Whether the channel path is shared.
+
+cmg - The channel measurement group.
 
 3. System devices
 -----------------
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index d9e5960..5eb9275 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,4 +1,49 @@
 
+1 Release Date    : Mon Oct 02 11:21:32 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.03.05
+3 Older Version   : 00.00.03.04
+
+i.	PCI_DEVICE macro used
+
+	Convert the pci_device_id-table of the megaraid_sas-driver to the PCI_DEVICE-macro, to safe some lines.
+
+		- Henrik Kretzschmar <henne@nachtwindheim.de>
+ii.	All compiler warnings removed
+iii.	megasas_ctrl_info struct reverted to 3.02 release
+iv.	Default value of megasas_dbg_lvl set to 0
+v.	Removing in megasas_exit the sysfs entry created for megasas_dbg_lvl
+vi.	In megasas_teardown_frame_pool(), cmd->frame was passed instead of
+	cmd->sense to pci_pool_free. Fixed. Bug was pointed out by
+	Eric Sesterhenn
+
+1 Release Date    : Wed Sep 13 14:22:51 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.03.04
+3 Older Version   : 00.00.03.03
+
+i.	Added Reboot notify
+ii.	Reduced by 1 max cmds sent to FW from Driver to make the reply_q_sz same
+	as Max Cmds FW can support
+
+1 Release Date    : Tue Aug 22 16:33:14 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.03.03
+3 Older Version   : 00.00.03.02
+
+i.	Send stop adapter to FW & Dump pending FW cmds before declaring adapter dead.
+	New varible added to set dbg level.
+ii.	Disable interrupt made as fn pointer as they are different for 1068 / 1078
+iii.	Frame count optimization. Main frame can contain 2 SGE for 64 bit SGLs and
+	3 SGE for 32 bit SGL
+iv.	Tasklet added for cmd completion
+v.	If FW in operational state before firing INIT, now we send RESET Flag to FW instead of just READY. This is used to do soft reset.
+vi.	megasas_ctrl_prop structure updated (based on FW struct)
+vii.	Added print : FW now in Ready State during initialization
+
+1 Release Date    : Sun Aug 06 22:49:52 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.03.02
+3 Older Version   : 00.00.03.01
+
+i.	Added FW tranistion state for Hotplug scenario
+
 1 Release Date    : Sun May 14 22:49:52 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
 2 Current Version : 00.00.03.01
 3 Older Version   : 00.00.02.04
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 89bf8c2..0bc7f1e 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -86,7 +86,7 @@
 core_pattern:
 
 core_pattern is used to specify a core dumpfile pattern name.
-. max length 64 characters; default value is "core"
+. max length 128 characters; default value is "core"
 . core_pattern is used as a pattern template for the output filename;
   certain string patterns (beginning with '%') are substituted with
   their actual values.
@@ -105,6 +105,9 @@
 	%h	hostname
 	%e	executable filename
 	%<OTHER> both are dropped
+. If the first character of the pattern is a '|', the kernel will treat
+  the rest of the pattern as a command to run.  The core dump will be
+  written to the standard input of that program instead of to a file.
 
 ==============================================================
 
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 126e59d9..8755b3e 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -51,7 +51,7 @@
  50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
  51 -> WinFast DTV2000 H                                   [107d:665e]
  52 -> Geniatech DVB-S                                     [14f1:0084]
- 53 -> Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T  [0070:1404]
+ 53 -> Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T  [0070:1404,0070:1400,0070:1401,0070:1402]
  54 -> Norwood Micro TV Tuner
  55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM  [c180:c980]
  56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
diff --git a/MAINTAINERS b/MAINTAINERS
index 17becb9..d708702 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -641,7 +641,7 @@
 P:	Muli Ben-Yehuda
 M:	muli@il.ibm.com
 P:	Jon D. Mason
-M:	jdmason@us.ibm.com
+M:	jdmason@kudzu.us
 L:	linux-kernel@vger.kernel.org
 L:	discuss@x86-64.org
 S:	Maintained
@@ -905,7 +905,8 @@
 M:	teigland@redhat.com
 L:	cluster-devel@redhat.com
 W:	http://sources.redhat.com/cluster/
-T:	git kernel.org:/pub/scm/linux/kernel/git/steve/gfs-2.6.git
+T:	git kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git
+T:	git kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw.git
 S:	Supported
 
 DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
@@ -1188,7 +1189,8 @@
 M:	swhiteho@redhat.com
 L:	cluster-devel@redhat.com
 W:	http://sources.redhat.com/cluster/
-T:	git kernel.org:/pub/scm/linux/kernel/git/steve/gfs-2.6.git
+T:	git kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git
+T:	git kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw.git
 S:	Supported
 
 GIGASET ISDN DRIVERS
@@ -1666,6 +1668,12 @@
 L:	ext2-devel@lists.sourceforge.net
 S:	Maintained
 
+K8TEMP HARDWARE MONITORING DRIVER
+P:	Rudolf Marek
+M:	r.marek@assembler.cz
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 KCONFIG
 P:	Roman Zippel
 M:	zippel@linux-m68k.org
@@ -1996,6 +2004,13 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+MSI LAPTOP SUPPORT
+P:	Lennart Poettering
+M:	mzxreary@0pointer.de
+L:	https://tango.0pointer.de/mailman/listinfo/s270-linux
+W:	http://0pointer.de/lennart/tchibo.html
+S:	Maintained
+
 MTRR AND SIMILAR SUPPORT [i386]
 P:	Richard Gooch
 M:	rgooch@atnf.csiro.au
@@ -2003,8 +2018,11 @@
 W:	http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html
 S:	Maintained
 
-MULTIMEDIA CARD (MMC) SUBSYSTEM
-S:	Orphan
+MULTIMEDIA CARD (MMC) AND SECURE DIGITAL (SD) SUBSYSTEM
+P:	Pierre Ossman
+M:	drzeus-mmc@drzeus.cx
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
 
 MULTISOUND SOUND DRIVER
 P:	Andrew Veliath
@@ -2040,11 +2058,13 @@
 P:	James Morris
 P:	Harald Welte
 P:	Jozsef Kadlecsik
-M:	coreteam@netfilter.org
+P:	Patrick McHardy
+M:	kaber@trash.net
+L:	netfilter-devel@lists.netfilter.org
+L:	netfilter@lists.netfilter.org
+L:	coreteam@netfilter.org
 W:	http://www.netfilter.org/
 W:	http://www.iptables.org/
-L:	netfilter@lists.netfilter.org
-L:	netfilter-devel@lists.netfilter.org
 S:	Supported
 
 NETLABEL
@@ -2261,6 +2281,17 @@
 T:	cvs cvs.parisc-linux.org:/var/cvs/linux-2.6
 S:	Maintained
 
+PC87360 HARDWARE MONITORING DRIVER
+P:	Jim Cromie
+M:	jim.cromie@gmail.com
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
+PC8736x GPIO DRIVER
+P:	Jim Cromie
+M:	jim.cromie@gmail.com
+S:	Maintained
+
 PCI ERROR RECOVERY
 P:	Linas Vepstas
 M:	linas@austin.ibm.com
@@ -2284,8 +2315,8 @@
 S:	Supported
 
 PCI HOTPLUG CORE
-P:	Greg Kroah-Hartman
-M:	gregkh@suse.de
+P: 	Kristen Carlson Accardi
+M:	kristen.c.accardi@intel.com
 S:	Supported
 
 PCI HOTPLUG COMPAQ DRIVER
@@ -2592,10 +2623,19 @@
 S: Supported
 
 SCx200 CPU SUPPORT
-P:	Christer Weinigel
-M:	christer@weinigel.se
-W:	http://www.weinigel.se
-S:	Supported
+P:	Jim Cromie
+M:	jim.cromie@gmail.com
+S:	Odd Fixes
+
+SCx200 GPIO DRIVER
+P:	Jim Cromie
+M:	jim.cromie@gmail.com
+S:	Maintained
+
+SCx200 HRT CLOCKSOURCE DRIVER
+P:	Jim Cromie
+M:	jim.cromie@gmail.com
+S:	Maintained
 
 SECURITY CONTACT
 P:	Security Officers
@@ -2760,14 +2800,7 @@
 UltraSPARC (sparc64):
 P:	David S. Miller
 M:	davem@davemloft.net
-P:	Eddie C. Dost
-M:	ecd@brainaid.de
-P:	Jakub Jelinek
-M:	jj@sunsite.ms.mff.cuni.cz
-P:	Anton Blanchard
-M:	anton@samba.org
 L:	sparclinux@vger.kernel.org
-L:	ultralinux@vger.kernel.org
 T:	git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
 S:	Maintained
 
diff --git a/Makefile b/Makefile
index adb2c74..389ff0c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 18
-EXTRAVERSION =
+SUBLEVEL = 19
+EXTRAVERSION =-rc2
 NAME=Avast! A bilge rat!
 
 # *DOCUMENTATION*
@@ -499,6 +499,7 @@
 
 ifdef CONFIG_UNWIND_INFO
 CFLAGS		+= -fasynchronous-unwind-tables
+LDFLAGS_vmlinux	+= --eh-frame-hdr
 endif
 
 ifdef CONFIG_DEBUG_INFO
@@ -741,6 +742,9 @@
 
 # vmlinux image - including updated kernel symbols
 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
+ifdef CONFIG_HEADERS_CHECK
+	$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
+endif
 	$(call if_changed_rule,vmlinux__)
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
 	$(Q)rm -f .old_version
@@ -932,7 +936,7 @@
 
 PHONY += headers_install
 headers_install: include/linux/version.h scripts_basic FORCE
-	@if [ ! -r include/asm-$(ARCH)/Kbuild ]; then \
+	@if [ ! -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
 	  echo '*** Error: Headers not exportable for this architecture ($(ARCH))'; \
 	  exit 1 ; fi
 	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
@@ -1316,7 +1320,8 @@
 	    $(all-sources) | xargs $1 -a \
 		-I __initdata,__exitdata,__acquires,__releases \
 		-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
-		--extra=+f --c-kinds=+px; \
+		--extra=+f --c-kinds=+px \
+		--regex-asm='/ENTRY\(([^)]*)\).*/\1/'; \
 	    $(all-kconfigs) | xargs $1 -a \
 		--langdef=kconfig \
 		--language-force=kconfig \
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 8b02420..e9762a3 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -6,40 +6,13 @@
  */
 
 #include <linux/module.h>
-#include <linux/string.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/socket.h>
-#include <linux/syscalls.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/pci.h>
-#include <linux/screen_info.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/io.h>
 #include <asm/console.h>
-#include <asm/hwrpb.h>
 #include <asm/uaccess.h>
-#include <asm/processor.h>
 #include <asm/checksum.h>
-#include <linux/interrupt.h>
 #include <asm/fpu.h>
-#include <asm/irq.h>
 #include <asm/machvec.h>
-#include <asm/pgalloc.h>
-#include <asm/semaphore.h>
-#include <asm/tlbflush.h>
-#include <asm/cacheflush.h>
-#include <asm/vga.h>
 
-#include <asm/unistd.h>
-
-extern struct hwrpb_struct *hwrpb;
-extern spinlock_t rtc_lock;
+#include <linux/syscalls.h>
 
 /* these are C runtime functions with special calling conventions: */
 extern void __divl (void);
@@ -52,14 +25,9 @@
 extern void __remqu (void);
 
 EXPORT_SYMBOL(alpha_mv);
-EXPORT_SYMBOL(screen_info);
-EXPORT_SYMBOL(perf_irq);
 EXPORT_SYMBOL(callback_getenv);
 EXPORT_SYMBOL(callback_setenv);
 EXPORT_SYMBOL(callback_save_env);
-#ifdef CONFIG_ALPHA_GENERIC
-EXPORT_SYMBOL(alpha_using_srm);
-#endif /* CONFIG_ALPHA_GENERIC */
 
 /* platform dependent support */
 EXPORT_SYMBOL(strcat);
@@ -77,47 +45,14 @@
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
 
-EXPORT_SYMBOL(__direct_map_base);
-EXPORT_SYMBOL(__direct_map_size);
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_map_page);
-EXPORT_SYMBOL(pci_unmap_single);
-EXPORT_SYMBOL(pci_unmap_page);
-EXPORT_SYMBOL(pci_map_sg);
-EXPORT_SYMBOL(pci_unmap_sg);
-EXPORT_SYMBOL(pci_dma_supported);
-EXPORT_SYMBOL(pci_dac_dma_supported);
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-EXPORT_SYMBOL(alpha_gendev_to_pci);
-#endif
-EXPORT_SYMBOL(dma_set_mask);
-
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_elf_thread);
-EXPORT_SYMBOL(dump_elf_task);
-EXPORT_SYMBOL(dump_elf_task_fp);
-EXPORT_SYMBOL(hwrpb);
-EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(alpha_read_fp_reg);
 EXPORT_SYMBOL(alpha_read_fp_reg_s);
 EXPORT_SYMBOL(alpha_write_fp_reg);
 EXPORT_SYMBOL(alpha_write_fp_reg_s);
 
-/* In-kernel system calls.  */
+/* entry.S */
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_dup);
-EXPORT_SYMBOL(sys_exit);
-EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_lseek);
 EXPORT_SYMBOL(kernel_execve);
-EXPORT_SYMBOL(sys_setsid);
-EXPORT_SYMBOL(sys_wait4);
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_tcpudp_magic);
@@ -134,10 +69,6 @@
 EXPORT_SYMBOL(alpha_fp_emul);
 #endif
 
-#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
-EXPORT_SYMBOL(__min_ipl);
-#endif
-
 /*
  * The following are specially called from the uaccess assembly stubs.
  */
@@ -160,27 +91,10 @@
  */
 
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(flush_tlb_mm);
-EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(flush_tlb_page);
-EXPORT_SYMBOL(smp_imb);
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(smp_num_cpus);
-EXPORT_SYMBOL(smp_call_function);
-EXPORT_SYMBOL(smp_call_function_on_cpu);
 EXPORT_SYMBOL(_atomic_dec_and_lock);
 #endif /* CONFIG_SMP */
 
 /*
- * NUMA specific symbols
- */
-#ifdef CONFIG_DISCONTIGMEM
-EXPORT_SYMBOL(node_data);
-#endif /* CONFIG_DISCONTIGMEM */
-
-EXPORT_SYMBOL(rtc_lock);
-
-/*
  * The following are special because they're not called
  * explicitly (the C compiler or assembler generates them in
  * response to division operations).  Fortunately, their
@@ -200,8 +114,3 @@
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memchr);
-
-#ifdef CONFIG_ALPHA_IRONGATE
-EXPORT_SYMBOL(irongate_ioremap);
-EXPORT_SYMBOL(irongate_iounmap);
-#endif
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
index a27ba12..ca46b2c 100644
--- a/arch/alpha/kernel/core_apecs.c
+++ b/arch/alpha/kernel/core_apecs.c
@@ -387,8 +387,7 @@
 }
 
 void
-apecs_machine_check(unsigned long vector, unsigned long la_ptr,
-		    struct pt_regs * regs)
+apecs_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	struct el_common *mchk_header;
 	struct el_apecs_procdata *mchk_procdata;
@@ -412,7 +411,7 @@
 	wrmces(0x7);		/* reset machine check pending flag */
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "APECS",
+	process_mcheck_info(vector, la_ptr, "APECS",
 			    (mcheck_expected(0)
 			     && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
 }
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index fd56306..1d6ee6c 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -1192,8 +1192,7 @@
 }
 
 void
-cia_machine_check(unsigned long vector, unsigned long la_ptr,
-		  struct pt_regs * regs)
+cia_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	int expected;
 
@@ -1208,5 +1207,5 @@
 	expected = mcheck_expected(0);
 	if (!expected && vector == 0x660)
 		expected = cia_decode_mchk(la_ptr);
-	process_mcheck_info(vector, la_ptr, regs, "CIA", expected);
+	process_mcheck_info(vector, la_ptr, "CIA", expected);
 }
diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
index 138d497..e4a0bcf 100644
--- a/arch/alpha/kernel/core_irongate.c
+++ b/arch/alpha/kernel/core_irongate.c
@@ -404,6 +404,7 @@
 #endif
 	return (void __iomem *)vaddr;
 }
+EXPORT_SYMBOL(irongate_ioremap);
 
 void
 irongate_iounmap(volatile void __iomem *xaddr)
@@ -414,3 +415,4 @@
 	if (addr)
 		return vfree((void *)(PAGE_MASK & addr)); 
 }
+EXPORT_SYMBOL(irongate_iounmap);
diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c
index 6a5a914..4843f6e 100644
--- a/arch/alpha/kernel/core_lca.c
+++ b/arch/alpha/kernel/core_lca.c
@@ -19,6 +19,7 @@
 #include <linux/tty.h>
 
 #include <asm/ptrace.h>
+#include <asm/irq_regs.h>
 #include <asm/smp.h>
 
 #include "proto.h"
@@ -386,8 +387,7 @@
 }
 
 void
-lca_machine_check(unsigned long vector, unsigned long la_ptr,
-		  struct pt_regs *regs)
+lca_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	const char * reason;
 	union el_lca el;
@@ -397,7 +397,7 @@
 	wrmces(rdmces());	/* reset machine check pending flag */
 
 	printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n",
-	       vector, regs->pc, (unsigned int) el.c->code);
+	       vector, get_irq_regs()->pc, (unsigned int) el.c->code);
 
 	/*
 	 * The first quadword after the common header always seems to
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
index 28849c8..8d01907 100644
--- a/arch/alpha/kernel/core_mcpcia.c
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -572,8 +572,7 @@
 }
 
 void
-mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
-		     struct pt_regs * regs)
+mcpcia_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	struct el_common *mchk_header;
 	struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
@@ -610,7 +609,7 @@
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "MCPCIA", expected != 0);
+	process_mcheck_info(vector, la_ptr, "MCPCIA", expected != 0);
 	if (!expected && vector != 0x620 && vector != 0x630) {
 		mcpcia_print_uncorrectable(mchk_logout);
 		mcpcia_print_system_area(la_ptr);
diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c
index 277674a..c5a271d 100644
--- a/arch/alpha/kernel/core_polaris.c
+++ b/arch/alpha/kernel/core_polaris.c
@@ -187,8 +187,7 @@
 }
 
 void
-polaris_machine_check(unsigned long vector, unsigned long la_ptr,
-		      struct pt_regs * regs)
+polaris_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	/* Clear the error before any reporting.  */
 	mb();
@@ -198,6 +197,6 @@
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "POLARIS",
+	process_mcheck_info(vector, la_ptr, "POLARIS",
 			    mcheck_expected(0));
 }
diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
index ecce09e..f5ca525 100644
--- a/arch/alpha/kernel/core_t2.c
+++ b/arch/alpha/kernel/core_t2.c
@@ -551,8 +551,7 @@
  * Hence all the taken/expected/any_expected/last_taken stuff...
  */
 void
-t2_machine_check(unsigned long vector, unsigned long la_ptr,
-		 struct pt_regs * regs)
+t2_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	int cpu = smp_processor_id();
 #ifdef CONFIG_VERBOSE_MCHECK
@@ -618,5 +617,5 @@
 	}
 #endif
 
-	process_mcheck_info(vector, la_ptr, regs, "T2", mcheck_expected(cpu));
+	process_mcheck_info(vector, la_ptr, "T2", mcheck_expected(cpu));
 }
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index 8aa305b..ce623c6 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -443,8 +443,7 @@
 }
 
 void
-tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
-		      struct pt_regs * regs)
+tsunami_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	/* Clear error before any reporting.  */
 	mb();
@@ -454,6 +453,6 @@
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "TSUNAMI",
+	process_mcheck_info(vector, la_ptr, "TSUNAMI",
 			    mcheck_expected(smp_processor_id()));
 }
diff --git a/arch/alpha/kernel/core_wildfire.c b/arch/alpha/kernel/core_wildfire.c
index 2b767a1..7e07244 100644
--- a/arch/alpha/kernel/core_wildfire.c
+++ b/arch/alpha/kernel/core_wildfire.c
@@ -322,8 +322,7 @@
 }
 
 void
-wildfire_machine_check(unsigned long vector, unsigned long la_ptr,
-		       struct pt_regs * regs)
+wildfire_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	mb();
 	mb();  /* magic */
@@ -332,7 +331,7 @@
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "WILDFIRE",
+	process_mcheck_info(vector, la_ptr, "WILDFIRE",
 			    mcheck_expected(smp_processor_id()));
 }
 
diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c
index 64f59f2..69b5f4e 100644
--- a/arch/alpha/kernel/err_ev6.c
+++ b/arch/alpha/kernel/err_ev6.c
@@ -11,6 +11,7 @@
 #include <linux/sched.h>
 
 #include <asm/io.h>
+#include <asm/irq_regs.h>
 #include <asm/hwrpb.h>
 #include <asm/smp.h>
 #include <asm/err_common.h>
@@ -229,7 +230,7 @@
 }
 
 void
-ev6_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
+ev6_machine_check(u64 vector, u64 la_ptr)
 {
 	struct el_common *mchk_header = (struct el_common *)la_ptr;
 
@@ -260,7 +261,7 @@
 		       (unsigned int)vector, (int)smp_processor_id());
 		
 		ev6_process_logout_frame(mchk_header, 1);
-		dik_show_regs(regs, NULL);
+		dik_show_regs(get_irq_regs(), NULL);
 
 		err_print_prefix = saved_err_prefix;
 	}
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
index fed6b3d..95463ab 100644
--- a/arch/alpha/kernel/err_ev7.c
+++ b/arch/alpha/kernel/err_ev7.c
@@ -118,7 +118,7 @@
 }
 
 void
-ev7_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
+ev7_machine_check(u64 vector, u64 la_ptr)
 {
 	struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
 	char *saved_err_prefix = err_print_prefix;
diff --git a/arch/alpha/kernel/err_impl.h b/arch/alpha/kernel/err_impl.h
index 64e9b73..3c12258 100644
--- a/arch/alpha/kernel/err_impl.h
+++ b/arch/alpha/kernel/err_impl.h
@@ -60,26 +60,26 @@
 ev7_collect_logout_frame_subpackets(struct el_subpacket *,
 				    struct ev7_lf_subpackets *);
 extern void ev7_register_error_handlers(void);
-extern void ev7_machine_check(u64, u64, struct pt_regs *);
+extern void ev7_machine_check(u64, u64);
 
 /*
  * err_ev6.c
  */
 extern void ev6_register_error_handlers(void);
 extern int ev6_process_logout_frame(struct el_common *, int);
-extern void ev6_machine_check(u64, u64, struct pt_regs *);
+extern void ev6_machine_check(u64, u64);
 
 /*
  * err_marvel.c
  */
-extern void marvel_machine_check(u64, u64, struct pt_regs *);
+extern void marvel_machine_check(u64, u64);
 extern void marvel_register_error_handlers(void);
 
 /*
  * err_titan.c
  */
 extern int titan_process_logout_frame(struct el_common *, int);
-extern void titan_machine_check(u64, u64, struct pt_regs *);
+extern void titan_machine_check(u64, u64);
 extern void titan_register_error_handlers(void);
 extern int privateer_process_logout_frame(struct el_common *, int);
-extern void privateer_machine_check(u64, u64, struct pt_regs *);
+extern void privateer_machine_check(u64, u64);
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c
index 70b38b1..f2956ac 100644
--- a/arch/alpha/kernel/err_marvel.c
+++ b/arch/alpha/kernel/err_marvel.c
@@ -1042,7 +1042,7 @@
 }
 
 void
-marvel_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
+marvel_machine_check(u64 vector, u64 la_ptr)
 {
 	struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
 	int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
@@ -1077,7 +1077,7 @@
 
 	default:
 		/* Don't know it - pass it up.  */
-		ev7_machine_check(vector, la_ptr, regs);
+		ev7_machine_check(vector, la_ptr);
 		return;
 	}	
 
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
index 7e6720d..febe71c 100644
--- a/arch/alpha/kernel/err_titan.c
+++ b/arch/alpha/kernel/err_titan.c
@@ -379,7 +379,7 @@
 }
 
 void
-titan_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
+titan_machine_check(u64 vector, u64 la_ptr)
 {
 	struct el_common *mchk_header = (struct el_common *)la_ptr;
 	struct el_TITAN_sysdata_mcheck *tmchk =
@@ -408,7 +408,7 @@
 	 * Only handle system errors here 
 	 */
 	if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
-		ev6_machine_check(vector, la_ptr, regs);
+		ev6_machine_check(vector, la_ptr);
 		return;
 	}
 
@@ -442,7 +442,7 @@
 #ifdef CONFIG_VERBOSE_MCHECK
 		titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
 		if (alpha_verbose_mcheck)
-			dik_show_regs(regs, NULL);
+			dik_show_regs(get_irq_regs(), NULL);
 #endif /* CONFIG_VERBOSE_MCHECK */
 
 		err_print_prefix = saved_err_prefix;
@@ -452,7 +452,7 @@
 		 * machine checks to interrupts
 		 */
 		irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
-		titan_dispatch_irqs(irqmask, regs);
+		titan_dispatch_irqs(irqmask);
 	}	
 
 
@@ -701,7 +701,7 @@
 }
 
 void
-privateer_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
+privateer_machine_check(u64 vector, u64 la_ptr)
 {
 	struct el_common *mchk_header = (struct el_common *)la_ptr;
 	struct el_TITAN_sysdata_mcheck *tmchk =
@@ -723,7 +723,7 @@
 	 * Only handle system events here.
 	 */
 	if (vector != SCB_Q_SYSEVENT) 
-		return titan_machine_check(vector, la_ptr, regs);
+		return titan_machine_check(vector, la_ptr);
 
 	/*
 	 * Report the event - System Events should be reported even if no
@@ -746,7 +746,7 @@
 	/*
 	 * Dispatch the interrupt(s).
 	 */
-	titan_dispatch_irqs(irqmask, regs);
+	titan_dispatch_irqs(irqmask);
 
 	/* 
 	 * Release the logout frame.
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index 729c475..facf82a 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -127,7 +127,7 @@
 #define MAX_ILLEGAL_IRQS 16
 
 void
-handle_irq(int irq, struct pt_regs * regs)
+handle_irq(int irq)
 {	
 	/* 
 	 * We ack quickly, we don't want the irq controller
@@ -157,6 +157,6 @@
 	 * at IPL 0.
 	 */
 	local_irq_disable();
-	__do_IRQ(irq, regs);
+	__do_IRQ(irq);
 	irq_exit();
 }
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index ddf5cf8..e16aeb6 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/irq.h>
 #include <linux/kernel_stat.h>
+#include <linux/module.h>
 
 #include <asm/machvec.h>
 #include <asm/dma.h>
@@ -16,6 +17,7 @@
 /* Hack minimum IPL during interrupt processing for broken hardware.  */
 #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
 int __min_ipl;
+EXPORT_SYMBOL(__min_ipl);
 #endif
 
 /*
@@ -30,6 +32,7 @@
 }
 
 void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
+EXPORT_SYMBOL(perf_irq);
 
 /*
  * The main interrupt entry point.
@@ -39,6 +42,7 @@
 do_entInt(unsigned long type, unsigned long vector,
 	  unsigned long la_ptr, struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
 	switch (type) {
 	case 0:
 #ifdef CONFIG_SMP
@@ -51,6 +55,7 @@
 #endif
 		break;
 	case 1:
+		old_regs = set_irq_regs(regs);
 #ifdef CONFIG_SMP
 	  {
 		long cpu;
@@ -61,18 +66,23 @@
 		if (cpu != boot_cpuid) {
 		        kstat_cpu(cpu).irqs[RTC_IRQ]++;
 		} else {
-			handle_irq(RTC_IRQ, regs);
+			handle_irq(RTC_IRQ);
 		}
 	  }
 #else
-		handle_irq(RTC_IRQ, regs);
+		handle_irq(RTC_IRQ);
 #endif
+		set_irq_regs(old_regs);
 		return;
 	case 2:
-		alpha_mv.machine_check(vector, la_ptr, regs);
+		old_regs = set_irq_regs(regs);
+		alpha_mv.machine_check(vector, la_ptr);
+		set_irq_regs(old_regs);
 		return;
 	case 3:
-		alpha_mv.device_interrupt(vector, regs);
+		old_regs = set_irq_regs(regs);
+		alpha_mv.device_interrupt(vector);
+		set_irq_regs(old_regs);
 		return;
 	case 4:
 		perf_irq(la_ptr, regs);
@@ -120,8 +130,7 @@
 
 void
 process_mcheck_info(unsigned long vector, unsigned long la_ptr,
-		    struct pt_regs *regs, const char *machine,
-		    int expected)
+		    const char *machine, int expected)
 {
 	struct el_common *mchk_header;
 	const char *reason;
@@ -148,7 +157,7 @@
 	mchk_header = (struct el_common *)la_ptr;
 
 	printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%x\n",
-	       machine, vector, regs->pc, mchk_header->code);
+	       machine, vector, get_irq_regs()->pc, mchk_header->code);
 
 	switch (mchk_header->code) {
 	/* Machine check reasons.  Defined according to PALcode sources.  */
@@ -189,7 +198,7 @@
 	printk(KERN_CRIT "machine check type: %s%s\n",
 	       reason, mchk_header->retry ? " (retryable)" : "");
 
-	dik_show_regs(regs, NULL);
+	dik_show_regs(get_irq_regs(), NULL);
 
 #ifdef CONFIG_VERBOSE_MCHECK
 	if (alpha_verbose_mcheck > 1) {
diff --git a/arch/alpha/kernel/irq_i8259.c b/arch/alpha/kernel/irq_i8259.c
index ebbadbc..9405bee 100644
--- a/arch/alpha/kernel/irq_i8259.c
+++ b/arch/alpha/kernel/irq_i8259.c
@@ -137,7 +137,7 @@
 
 #if defined(IACK_SC)
 void
-isa_device_interrupt(unsigned long vector, struct pt_regs *regs)
+isa_device_interrupt(unsigned long vector)
 {
 	/*
 	 * Generate a PCI interrupt acknowledge cycle.  The PIC will
@@ -147,13 +147,13 @@
 	 */
 	int j = *(vuip) IACK_SC;
 	j &= 0xff;
-	handle_irq(j, regs);
+	handle_irq(j);
 }
 #endif
 
 #if defined(CONFIG_ALPHA_GENERIC) || !defined(IACK_SC)
 void
-isa_no_iack_sc_device_interrupt(unsigned long vector, struct pt_regs *regs)
+isa_no_iack_sc_device_interrupt(unsigned long vector)
 {
 	unsigned long pic;
 
@@ -176,7 +176,7 @@
 	while (pic) {
 		int j = ffz(~pic);
 		pic &= pic - 1;
-		handle_irq(j, regs);
+		handle_irq(j);
 	}
 }
 #endif
diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
index f201d8f..cc9a8a7 100644
--- a/arch/alpha/kernel/irq_impl.h
+++ b/arch/alpha/kernel/irq_impl.h
@@ -15,10 +15,10 @@
 
 #define RTC_IRQ    8
 
-extern void isa_device_interrupt(unsigned long, struct pt_regs *);
-extern void isa_no_iack_sc_device_interrupt(unsigned long, struct pt_regs *);
-extern void srm_device_interrupt(unsigned long, struct pt_regs *);
-extern void pyxis_device_interrupt(unsigned long, struct pt_regs *);
+extern void isa_device_interrupt(unsigned long);
+extern void isa_no_iack_sc_device_interrupt(unsigned long);
+extern void srm_device_interrupt(unsigned long);
+extern void pyxis_device_interrupt(unsigned long);
 
 extern struct irqaction timer_irqaction;
 extern struct irqaction isa_cascade_irqaction;
@@ -39,4 +39,4 @@
 extern struct hw_interrupt_type i8259a_irq_type;
 extern void init_i8259a_irqs(void);
 
-extern void handle_irq(int irq, struct pt_regs * regs);
+extern void handle_irq(int irq);
diff --git a/arch/alpha/kernel/irq_pyxis.c b/arch/alpha/kernel/irq_pyxis.c
index 3b581415..d53edbc 100644
--- a/arch/alpha/kernel/irq_pyxis.c
+++ b/arch/alpha/kernel/irq_pyxis.c
@@ -81,7 +81,7 @@
 };
 
 void 
-pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs)
+pyxis_device_interrupt(unsigned long vector)
 {
 	unsigned long pld;
 	unsigned int i;
@@ -98,9 +98,9 @@
 		i = ffz(~pld);
 		pld &= pld - 1; /* clear least bit set */
 		if (i == 7)
-			isa_device_interrupt(vector, regs);
+			isa_device_interrupt(vector);
 		else
-			handle_irq(16+i, regs);
+			handle_irq(16+i);
 	}
 }
 
diff --git a/arch/alpha/kernel/irq_srm.c b/arch/alpha/kernel/irq_srm.c
index 8e4d121..3221201 100644
--- a/arch/alpha/kernel/irq_srm.c
+++ b/arch/alpha/kernel/irq_srm.c
@@ -72,8 +72,8 @@
 }
 
 void 
-srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+srm_device_interrupt(unsigned long vector)
 {
 	int irq = (vector - 0x800) >> 4;
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index fff5cf9..174b729 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -201,6 +201,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(dma_set_mask);
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index c468e31..6e7d1fe 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -300,6 +300,7 @@
 	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
 	return pci_map_single_1(pdev, cpu_addr, size, dac_allowed);
 }
+EXPORT_SYMBOL(pci_map_single);
 
 dma_addr_t
 pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset,
@@ -314,6 +315,7 @@
 	return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
 				size, dac_allowed);
 }
+EXPORT_SYMBOL(pci_map_page);
 
 /* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
    SIZE must match what was provided for in a previous pci_map_single
@@ -379,6 +381,7 @@
 	DBGA2("pci_unmap_single: sg [%lx,%lx] np %ld from %p\n",
 	      dma_addr, size, npages, __builtin_return_address(0));
 }
+EXPORT_SYMBOL(pci_unmap_single);
 
 void
 pci_unmap_page(struct pci_dev *pdev, dma_addr_t dma_addr,
@@ -386,6 +389,7 @@
 {
 	pci_unmap_single(pdev, dma_addr, size, direction);
 }
+EXPORT_SYMBOL(pci_unmap_page);
 
 /* Allocate and map kernel buffer using consistent mode DMA for PCI
    device.  Returns non-NULL cpu-view pointer to the buffer if
@@ -427,6 +431,7 @@
 
 	return cpu_addr;
 }
+EXPORT_SYMBOL(pci_alloc_consistent);
 
 /* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
    be values that were returned from pci_alloc_consistent.  SIZE must
@@ -444,7 +449,7 @@
 	DBGA2("pci_free_consistent: [%x,%lx] from %p\n",
 	      dma_addr, size, __builtin_return_address(0));
 }
-
+EXPORT_SYMBOL(pci_free_consistent);
 
 /* Classify the elements of the scatterlist.  Write dma_address
    of each element with:
@@ -672,6 +677,7 @@
 		pci_unmap_sg(pdev, start, out - start, direction);
 	return 0;
 }
+EXPORT_SYMBOL(pci_map_sg);
 
 /* Unmap a set of streaming mode DMA translations.  Again, cpu read
    rules concerning calls here are the same as for pci_unmap_single()
@@ -752,6 +758,7 @@
 
 	DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg));
 }
+EXPORT_SYMBOL(pci_unmap_sg);
 
 
 /* Return whether the given PCI device DMA address mask can be
@@ -786,6 +793,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(pci_dma_supported);
 
 
 /*
@@ -908,6 +916,7 @@
 
 	return ok;
 }
+EXPORT_SYMBOL(pci_dac_dma_supported);
 
 dma64_addr_t
 pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page,
@@ -917,6 +926,7 @@
 		+ __pa(page_address(page)) 
 		+ (dma64_addr_t) offset);
 }
+EXPORT_SYMBOL(pci_dac_page_to_dma);
 
 struct page *
 pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
@@ -924,13 +934,14 @@
 	unsigned long paddr = (dma_addr & PAGE_MASK) - alpha_mv.pci_dac_offset;
 	return virt_to_page(__va(paddr));
 }
+EXPORT_SYMBOL(pci_dac_dma_to_page);
 
 unsigned long
 pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
 {
 	return (dma_addr & ~PAGE_MASK);
 }
-
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
 
 /* Helper for generic DMA-mapping functions. */
 
@@ -957,6 +968,7 @@
 	/* This assumes ISA bus master with dma_mask 0xffffff. */
 	return NULL;
 }
+EXPORT_SYMBOL(alpha_gendev_to_pci);
 
 int
 dma_set_mask(struct device *dev, u64 mask)
@@ -969,3 +981,4 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(dma_set_mask);
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index b3a8a29..3370e6f 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -205,6 +205,7 @@
 	regs->ps = 8;
 	wrusp(sp);
 }
+EXPORT_SYMBOL(start_thread);
 
 /*
  * Free current thread data structures etc..
@@ -376,6 +377,7 @@
 	dump->regs[EF_A2]  = pt->r18;
 	memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
 }
+EXPORT_SYMBOL(dump_thread);
 
 /*
  * Fill in the user structure for a ELF core dump.
@@ -424,6 +426,7 @@
 	   useful value of the thread's UNIQUE field.  */
 	dest[32] = ti->pcb.unique;
 }
+EXPORT_SYMBOL(dump_elf_thread);
 
 int
 dump_elf_task(elf_greg_t *dest, struct task_struct *task)
@@ -431,6 +434,7 @@
 	dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task));
 	return 1;
 }
+EXPORT_SYMBOL(dump_elf_task);
 
 int
 dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
@@ -439,6 +443,7 @@
 	memcpy(dest, sw->fp, 32 * 8);
 	return 1;
 }
+EXPORT_SYMBOL(dump_elf_task_fp);
 
 /*
  * sys_execve() executes a new program.
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 21f7128..95912ec 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -20,7 +20,7 @@
 extern struct pci_ops apecs_pci_ops;
 extern void apecs_init_arch(void);
 extern void apecs_pci_clr_err(void);
-extern void apecs_machine_check(u64, u64, struct pt_regs *);
+extern void apecs_machine_check(u64, u64);
 extern void apecs_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_cia.c */
@@ -29,27 +29,27 @@
 extern void cia_init_arch(void);
 extern void pyxis_init_arch(void);
 extern void cia_kill_arch(int);
-extern void cia_machine_check(u64, u64, struct pt_regs *);
+extern void cia_machine_check(u64, u64);
 extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_irongate.c */
 extern struct pci_ops irongate_pci_ops;
 extern int irongate_pci_clr_err(void);
 extern void irongate_init_arch(void);
-extern void irongate_machine_check(u64, u64, struct pt_regs *);
+extern void irongate_machine_check(u64, u64);
 #define irongate_pci_tbi ((void *)0)
 
 /* core_lca.c */
 extern struct pci_ops lca_pci_ops;
 extern void lca_init_arch(void);
-extern void lca_machine_check(u64, u64, struct pt_regs *);
+extern void lca_machine_check(u64, u64);
 extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_marvel.c */
 extern struct pci_ops marvel_pci_ops;
 extern void marvel_init_arch(void);
 extern void marvel_kill_arch(int);
-extern void marvel_machine_check(u64, u64, struct pt_regs *);
+extern void marvel_machine_check(u64, u64);
 extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 extern int marvel_pa_to_nid(unsigned long);
 extern int marvel_cpuid_to_nid(int);
@@ -64,7 +64,7 @@
 extern struct pci_ops mcpcia_pci_ops;
 extern void mcpcia_init_arch(void);
 extern void mcpcia_init_hoses(void);
-extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
+extern void mcpcia_machine_check(u64, u64);
 extern void mcpcia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_polaris.c */
@@ -72,21 +72,21 @@
 extern int polaris_read_config_dword(struct pci_dev *, int, u32 *);
 extern int polaris_write_config_dword(struct pci_dev *, int, u32);
 extern void polaris_init_arch(void);
-extern void polaris_machine_check(u64, u64, struct pt_regs *);
+extern void polaris_machine_check(u64, u64);
 #define polaris_pci_tbi ((void *)0)
 
 /* core_t2.c */
 extern struct pci_ops t2_pci_ops;
 extern void t2_init_arch(void);
 extern void t2_kill_arch(int);
-extern void t2_machine_check(u64, u64, struct pt_regs *);
+extern void t2_machine_check(u64, u64);
 extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_titan.c */
 extern struct pci_ops titan_pci_ops;
 extern void titan_init_arch(void);
 extern void titan_kill_arch(int);
-extern void titan_machine_check(u64, u64, struct pt_regs *);
+extern void titan_machine_check(u64, u64);
 extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 extern struct _alpha_agp_info *titan_agp_info(void);
 
@@ -94,14 +94,14 @@
 extern struct pci_ops tsunami_pci_ops;
 extern void tsunami_init_arch(void);
 extern void tsunami_kill_arch(int);
-extern void tsunami_machine_check(u64, u64, struct pt_regs *);
+extern void tsunami_machine_check(u64, u64);
 extern void tsunami_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_wildfire.c */
 extern struct pci_ops wildfire_pci_ops;
 extern void wildfire_init_arch(void);
 extern void wildfire_kill_arch(int);
-extern void wildfire_machine_check(u64, u64, struct pt_regs *);
+extern void wildfire_machine_check(u64, u64);
 extern void wildfire_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 extern int wildfire_pa_to_nid(unsigned long);
 extern int wildfire_cpuid_to_nid(int);
@@ -133,7 +133,7 @@
 /* extern void reset_for_srm(void); */
 
 /* time.c */
-extern irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs);
+extern irqreturn_t timer_interrupt(int irq, void *dev);
 extern void common_init_rtc(void);
 extern unsigned long est_cycle_freq;
 
@@ -177,7 +177,7 @@
 extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
 
 /* sys_titan.c */
-extern void titan_dispatch_irqs(u64, struct pt_regs *);
+extern void titan_dispatch_irqs(u64);
 
 /* ../mm/init.c */
 extern void switch_to_system_map(void);
@@ -214,5 +214,4 @@
 #endif
 
 extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr,
-				struct pt_regs *regs, const char *machine,
-				int expected);
+				const char *machine, int expected);
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index a94e6d9..1aea7c7 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -66,6 +66,7 @@
 
 
 struct hwrpb_struct *hwrpb;
+EXPORT_SYMBOL(hwrpb);
 unsigned long srm_hae;
 
 int alpha_l1i_cacheshape;
@@ -111,6 +112,7 @@
 #ifdef CONFIG_ALPHA_GENERIC
 struct alpha_machine_vector alpha_mv;
 int alpha_using_srm;
+EXPORT_SYMBOL(alpha_using_srm);
 #endif
 
 static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
@@ -137,6 +139,8 @@
 	.orig_video_points = 16
 };
 
+EXPORT_SYMBOL(screen_info);
+
 /*
  * The direct map I/O window, if any.  This should be the same
  * for all busses, since it's used by virt_to_bus.
@@ -144,6 +148,8 @@
 
 unsigned long __direct_map_base;
 unsigned long __direct_map_size;
+EXPORT_SYMBOL(__direct_map_base);
+EXPORT_SYMBOL(__direct_map_size);
 
 /*
  * Declare all of the machine vectors.
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 4dc273e..d1ec4f5 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -52,6 +52,7 @@
 
 /* A collection of per-processor data.  */
 struct cpuinfo_alpha cpu_data[NR_CPUS];
+EXPORT_SYMBOL(cpu_data);
 
 /* A collection of single bit ipi messages.  */
 static struct {
@@ -74,6 +75,7 @@
 
 int smp_num_probed;		/* Internal processor count */
 int smp_num_cpus = 1;		/* Number that came online.  */
+EXPORT_SYMBOL(smp_num_cpus);
 
 extern void calibrate_delay(void);
 
@@ -515,12 +517,15 @@
 void
 smp_percpu_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
 	int cpu = smp_processor_id();
 	unsigned long user = user_mode(regs);
 	struct cpuinfo_alpha *data = &cpu_data[cpu];
 
+	old_regs = set_irq_regs(regs);
+
 	/* Record kernel PC.  */
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 	if (!--data->prof_counter) {
 		/* We need to make like a normal interrupt -- otherwise
@@ -534,6 +539,7 @@
 
 		irq_exit();
 	}
+	set_irq_regs(old_regs);
 }
 
 int __init
@@ -786,6 +792,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(smp_call_function_on_cpu);
 
 int
 smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
@@ -793,6 +800,7 @@
 	return smp_call_function_on_cpu (func, info, retry, wait,
 					 cpu_online_map);
 }
+EXPORT_SYMBOL(smp_call_function);
 
 static void
 ipi_imb(void *ignored)
@@ -807,6 +815,7 @@
 	if (on_each_cpu(ipi_imb, NULL, 1, 1))
 		printk(KERN_CRIT "smp_imb: timed out\n");
 }
+EXPORT_SYMBOL(smp_imb);
 
 static void
 ipi_flush_tlb_all(void *ignored)
@@ -862,6 +871,7 @@
 
 	preempt_enable();
 }
+EXPORT_SYMBOL(flush_tlb_mm);
 
 struct flush_tlb_page_struct {
 	struct vm_area_struct *vma;
@@ -914,6 +924,7 @@
 
 	preempt_enable();
 }
+EXPORT_SYMBOL(flush_tlb_page);
 
 void
 flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
@@ -921,6 +932,7 @@
 	/* On the Alpha we always flush the whole user tlb.  */
 	flush_tlb_mm(vma->vm_mm);
 }
+EXPORT_SYMBOL(flush_tlb_range);
 
 static void
 ipi_flush_icache_page(void *x)
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index d6926b7..49bedfb 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -100,7 +100,7 @@
 };
 
 static void
-alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
+alcor_device_interrupt(unsigned long vector)
 {
 	unsigned long pld;
 	unsigned int i;
@@ -116,9 +116,9 @@
 		i = ffz(~pld);
 		pld &= pld - 1; /* clear least bit set */
 		if (i == 31) {
-			isa_device_interrupt(vector, regs);
+			isa_device_interrupt(vector);
 		} else {
-			handle_irq(16 + i, regs);
+			handle_irq(16 + i);
 		}
 	}
 }
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index 25a2150..ace475c 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -82,7 +82,7 @@
 };
 
 static void 
-cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
+cabriolet_device_interrupt(unsigned long v)
 {
 	unsigned long pld;
 	unsigned int i;
@@ -98,15 +98,15 @@
 		i = ffz(~pld);
 		pld &= pld - 1;	/* clear least bit set */
 		if (i == 4) {
-			isa_device_interrupt(v, r);
+			isa_device_interrupt(v);
 		} else {
-			handle_irq(16 + i, r);
+			handle_irq(16 + i);
 		}
 	}
 }
 
 static void __init
-common_init_irq(void (*srm_dev_int)(unsigned long v, struct pt_regs *r))
+common_init_irq(void (*srm_dev_int)(unsigned long v))
 {
 	init_i8259a_irqs();
 
@@ -154,18 +154,18 @@
    too invasive though.  */
 
 static void
-pc164_srm_device_interrupt(unsigned long v, struct pt_regs *r)
+pc164_srm_device_interrupt(unsigned long v)
 {
 	__min_ipl = getipl();
-	srm_device_interrupt(v, r);
+	srm_device_interrupt(v);
 	__min_ipl = 0;
 }
 
 static void
-pc164_device_interrupt(unsigned long v, struct pt_regs *r)
+pc164_device_interrupt(unsigned long v)
 {
 	__min_ipl = getipl();
-	cabriolet_device_interrupt(v, r);
+	cabriolet_device_interrupt(v);
 	__min_ipl = 0;
 }
 
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index dd6103b..85d2f93 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -217,7 +217,7 @@
 };
 
 static void
-dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
+dp264_device_interrupt(unsigned long vector)
 {
 #if 1
 	printk("dp264_device_interrupt: NOT IMPLEMENTED YET!! \n");
@@ -236,9 +236,9 @@
 		i = ffz(~pld);
 		pld &= pld - 1; /* clear least bit set */
 		if (i == 55)
-			isa_device_interrupt(vector, regs);
+			isa_device_interrupt(vector);
 		else
-			handle_irq(16 + i, 16 + i, regs);
+			handle_irq(16 + i);
 #if 0
 		TSUNAMI_cchip->dir0.csr = 1UL << i; mb();
 		tmp = TSUNAMI_cchip->dir0.csr;
@@ -248,7 +248,7 @@
 }
 
 static void 
-dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+dp264_srm_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -268,11 +268,11 @@
 	if (irq >= 32)
 		irq -= 16;
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void 
-clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+clipper_srm_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -290,7 +290,7 @@
 	 *
 	 * Eg IRQ 24 is DRIR bit 8, etc, etc
 	 */
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
index ed108b6..9c5a306 100644
--- a/arch/alpha/kernel/sys_eb64p.c
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -80,7 +80,7 @@
 };
 
 static void 
-eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
+eb64p_device_interrupt(unsigned long vector)
 {
 	unsigned long pld;
 	unsigned int i;
@@ -97,9 +97,9 @@
 		pld &= pld - 1;	/* clear least bit set */
 
 		if (i == 5) {
-			isa_device_interrupt(vector, regs);
+			isa_device_interrupt(vector);
 		} else {
-			handle_irq(16 + i, regs);
+			handle_irq(16 + i);
 		}
 	}
 }
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
index 64a785ba..7ef3b6f 100644
--- a/arch/alpha/kernel/sys_eiger.c
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -91,7 +91,7 @@
 };
 
 static void
-eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
+eiger_device_interrupt(unsigned long vector)
 {
 	unsigned intstatus;
 
@@ -118,20 +118,20 @@
 		 * despatch an interrupt if it's set.
 		 */
 
-		if (intstatus & 8) handle_irq(16+3, regs);
-		if (intstatus & 4) handle_irq(16+2, regs);
-		if (intstatus & 2) handle_irq(16+1, regs);
-		if (intstatus & 1) handle_irq(16+0, regs);
+		if (intstatus & 8) handle_irq(16+3);
+		if (intstatus & 4) handle_irq(16+2);
+		if (intstatus & 2) handle_irq(16+1);
+		if (intstatus & 1) handle_irq(16+0);
 	} else {
-		isa_device_interrupt(vector, regs);
+		isa_device_interrupt(vector);
 	}
 }
 
 static void
-eiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+eiger_srm_device_interrupt(unsigned long vector)
 {
 	int irq = (vector - 0x800) >> 4;
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index 4ac2b32..2c3de97 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -129,7 +129,7 @@
 };
 
 static void 
-jensen_device_interrupt(unsigned long vector, struct pt_regs * regs)
+jensen_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -189,7 +189,7 @@
           if (cc - last_msg > ((JENSEN_CYCLES_PER_SEC) * 3) ||
 	      irq != last_irq) {
                 printk(KERN_CRIT " irq %d count %d cc %u @ %lx\n",
-                       irq, count, cc-last_cc, regs->pc);
+                       irq, count, cc-last_cc, get_irq_regs()->pc);
                 count = 0;
                 last_msg = cc;
                 last_irq = irq;
@@ -198,7 +198,7 @@
         }
 #endif
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
@@ -244,7 +244,7 @@
 }
 
 static void
-jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
+jensen_machine_check (u64 vector, u64 la)
 {
 	printk(KERN_CRIT "Machine check\n");
 }
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 36d2159..e349f03 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -38,7 +38,7 @@
  * Interrupt handling.
  */
 static void 
-io7_device_interrupt(unsigned long vector, struct pt_regs * regs)
+io7_device_interrupt(unsigned long vector)
 {
 	unsigned int pid;
 	unsigned int irq;
@@ -64,7 +64,7 @@
 	irq &= MARVEL_IRQ_VEC_IRQ_MASK;		/* not too many bits */
 	irq |= pid << MARVEL_IRQ_VEC_PE_SHIFT;	/* merge the pid     */
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static volatile unsigned long *
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index 61ac56f..b8b817f 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -33,7 +33,7 @@
 
 
 static void 
-miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+miata_srm_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -56,7 +56,7 @@
 	if (irq >= 16)
 		irq = irq + 8;
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index cc4c581..8d3e942 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -79,7 +79,7 @@
 };
 
 static void 
-mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
+mikasa_device_interrupt(unsigned long vector)
 {
 	unsigned long pld;
 	unsigned int i;
@@ -97,9 +97,9 @@
 		i = ffz(~pld);
 		pld &= pld - 1; /* clear least bit set */
 		if (i < 16) {
-			isa_device_interrupt(vector, regs);
+			isa_device_interrupt(vector);
 		} else {
-			handle_irq(i, regs);
+			handle_irq(i);
 		}
 	}
 }
@@ -182,8 +182,7 @@
 
 #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
 static void
-mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
-		           struct pt_regs * regs)
+mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 #define MCHK_NO_DEVSEL 0x205U
 #define MCHK_NO_TABT 0x204U
@@ -202,7 +201,7 @@
 	mb();
 
 	code = mchk_header->code;
-	process_mcheck_info(vector, la_ptr, regs, "MIKASA APECS",
+	process_mcheck_info(vector, la_ptr, "MIKASA APECS",
 			    (mcheck_expected(0)
 			     && (code == MCHK_NO_DEVSEL
 			         || code == MCHK_NO_TABT)));
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index c0d696e..93744ba 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -124,8 +124,7 @@
    in the system.  They are analysed separately but all starts here.  */
 
 void
-nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
-		       struct pt_regs *regs)
+nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 	char *mchk_class;
 
@@ -165,7 +164,7 @@
 	else if (vector == SCB_Q_SYSMCHK)
 		mchk_class = "Fatal";
 	else {
-		ev6_machine_check(vector, la_ptr, regs);
+		ev6_machine_check(vector, la_ptr);
 		return;
 	}
 
@@ -173,7 +172,7 @@
 			 "[%s System Machine Check (NMI)]\n",
 	       vector, mchk_class);
 
-	naut_sys_machine_check(vector, la_ptr, regs);
+	naut_sys_machine_check(vector, la_ptr, get_irq_regs());
 
 	/* Tell the PALcode to clear the machine check */
 	draina();
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index 2d3cff7..de6ba34 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -77,7 +77,7 @@
 };
 
 static void 
-noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
+noritake_device_interrupt(unsigned long vector)
 {
 	unsigned long pld;
 	unsigned int i;
@@ -96,15 +96,15 @@
 		i = ffz(~pld);
 		pld &= pld - 1; /* clear least bit set */
 		if (i < 16) {
-			isa_device_interrupt(vector, regs);
+			isa_device_interrupt(vector);
 		} else {
-			handle_irq(i, regs);
+			handle_irq(i);
 		}
 	}
 }
 
 static void 
-noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+noritake_srm_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -122,7 +122,7 @@
 	if (irq >= 16)
 		irq = irq + 1;
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
@@ -264,8 +264,7 @@
 
 #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
 static void
-noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
-			     struct pt_regs * regs)
+noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr)
 {
 #define MCHK_NO_DEVSEL 0x205U
 #define MCHK_NO_TABT 0x204U
@@ -284,7 +283,7 @@
         mb();
 
         code = mchk_header->code;
-        process_mcheck_info(vector, la_ptr, regs, "NORITAKE APECS",
+        process_mcheck_info(vector, la_ptr, "NORITAKE APECS",
                             (mcheck_expected(0)
                              && (code == MCHK_NO_DEVSEL
                                  || code == MCHK_NO_TABT)));
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index 949607e..581d08c 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -134,7 +134,7 @@
 };
 
 static void 
-rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+rawhide_srm_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -158,7 +158,7 @@
 	/* Adjust by which hose it is from.  */
 	irq -= ((irq + 16) >> 2) & 0x38;
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
index 6ae50605..ce1faa6 100644
--- a/arch/alpha/kernel/sys_rx164.c
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -83,7 +83,7 @@
 };
 
 static void 
-rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
+rx164_device_interrupt(unsigned long vector)
 {
 	unsigned long pld;
 	volatile unsigned int *dirr;
@@ -102,9 +102,9 @@
 		i = ffz(~pld);
 		pld &= pld - 1; /* clear least bit set */
 		if (i == 20) {
-			isa_no_iack_sc_device_interrupt(vector, regs);
+			isa_no_iack_sc_device_interrupt(vector);
 		} else {
-			handle_irq(16+i, regs);
+			handle_irq(16+i);
 		}
 	}
 }
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index a7a1464..906019c 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -512,7 +512,7 @@
 };
 
 static void 
-sable_lynx_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+sable_lynx_srm_device_interrupt(unsigned long vector)
 {
 	/* Note that the vector reported by the SRM PALcode corresponds
 	   to the interrupt mask bits, but we have to manage via the
@@ -526,7 +526,7 @@
 	printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
 	       __FUNCTION__, vector, bit, irq);
 #endif
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index 2c75cd1..9bd9a31 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -85,7 +85,7 @@
 };
 
 static void
-takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
+takara_device_interrupt(unsigned long vector)
 {
 	unsigned intstatus;
 
@@ -112,20 +112,20 @@
 		 * despatch an interrupt if it's set.
 		 */
 
-		if (intstatus & 8) handle_irq(16+3, regs);
-		if (intstatus & 4) handle_irq(16+2, regs);
-		if (intstatus & 2) handle_irq(16+1, regs);
-		if (intstatus & 1) handle_irq(16+0, regs);
+		if (intstatus & 8) handle_irq(16+3);
+		if (intstatus & 4) handle_irq(16+2);
+		if (intstatus & 2) handle_irq(16+1);
+		if (intstatus & 1) handle_irq(16+0);
 	} else {
-		isa_device_interrupt (vector, regs);
+		isa_device_interrupt (vector);
 	}
 }
 
 static void 
-takara_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+takara_srm_device_interrupt(unsigned long vector)
 {
 	int irq = (vector - 0x800) >> 4;
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 static void __init
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index 302aab3..29ab7db 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -167,18 +167,18 @@
 }
 
 static void
-titan_device_interrupt(unsigned long vector, struct pt_regs * regs)
+titan_device_interrupt(unsigned long vector)
 {
 	printk("titan_device_interrupt: NOT IMPLEMENTED YET!! \n");
 }
 
 static void 
-titan_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+titan_srm_device_interrupt(unsigned long vector)
 {
 	int irq;
 
 	irq = (vector - 0x800) >> 4;
-	handle_irq(irq, regs);
+	handle_irq(irq);
 }
 
 
@@ -204,7 +204,7 @@
 };
 
 static irqreturn_t
-titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs)                    
+titan_intr_nop(int irq, void *dev_id)
 {
       /*
        * This is a NOP interrupt handler for the purposes of
@@ -243,7 +243,7 @@
 }
 
 void
-titan_dispatch_irqs(u64 mask, struct pt_regs *regs)
+titan_dispatch_irqs(u64 mask)
 {
 	unsigned long vector;
 
@@ -263,7 +263,7 @@
 		vector = 0x900 + (vector << 4);	/* convert to SRM vector */
 		
 		/* dispatch it */
-		alpha_mv.device_interrupt(vector, regs);
+		alpha_mv.device_interrupt(vector);
 	}
 }
   
diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c
index 22c5798..42c3eed 100644
--- a/arch/alpha/kernel/sys_wildfire.c
+++ b/arch/alpha/kernel/sys_wildfire.c
@@ -234,7 +234,7 @@
 }
 
 static void 
-wildfire_device_interrupt(unsigned long vector, struct pt_regs * regs)
+wildfire_device_interrupt(unsigned long vector)
 {
 	int irq;
 
@@ -246,7 +246,7 @@
 	 * bits 5-0:	irq in PCA
 	 */
 
-	handle_irq(irq, regs);
+	handle_irq(irq);
 	return;
 }
 
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 581ddcc..d7053eb 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -57,6 +57,7 @@
 static int set_rtc_mmss(unsigned long);
 
 DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
 
 #define TICK_SIZE (tick_nsec / 1000)
 
@@ -104,7 +105,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev)
 {
 	unsigned long delta;
 	__u32 now;
@@ -112,7 +113,7 @@
 
 #ifndef CONFIG_SMP
 	/* Not SMP, do kernel PC profiling here.  */
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #endif
 
 	write_seqlock(&xtime_lock);
@@ -132,7 +133,7 @@
 	while (nticks > 0) {
 		do_timer(1);
 #ifndef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 		nticks--;
 	}
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index b826f58..e3e3806 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -13,12 +13,14 @@
 #include <linux/swap.h>
 #include <linux/initrd.h>
 #include <linux/pfn.h>
+#include <linux/module.h>
 
 #include <asm/hwrpb.h>
 #include <asm/pgalloc.h>
 
 pg_data_t node_data[MAX_NUMNODES];
 bootmem_data_t node_bdata[MAX_NUMNODES];
+EXPORT_SYMBOL(node_data);
 
 #undef DEBUG_DISCONTIG
 #ifdef DEBUG_DISCONTIG
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 181ef1e..80a72c7 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -163,8 +163,7 @@
 #define	LOCOMO_IRQ_LT_START	(IRQ_LOCOMO_LT)
 #define	LOCOMO_IRQ_SPI_START	(IRQ_LOCOMO_SPI_RFR)
 
-static void locomo_handler(unsigned int irq, struct irqdesc *desc,
-			struct pt_regs *regs)
+static void locomo_handler(unsigned int irq, struct irqdesc *desc)
 {
 	int req, i;
 	struct irqdesc *d;
@@ -182,7 +181,7 @@
 		d = irq_desc + irq;
 		for (i = 0; i <= 3; i++, d++, irq++) {
 			if (req & (0x0100 << i)) {
-				desc_handle_irq(irq, d, regs);
+				desc_handle_irq(irq, d);
 			}
 
 		}
@@ -218,15 +217,14 @@
 	.unmask	= locomo_unmask_irq,
 };
 
-static void locomo_key_handler(unsigned int irq, struct irqdesc *desc,
-			    struct pt_regs *regs)
+static void locomo_key_handler(unsigned int irq, struct irqdesc *desc)
 {
 	struct irqdesc *d;
 	void __iomem *mapbase = get_irq_chipdata(irq);
 
 	if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
 		d = irq_desc + LOCOMO_IRQ_KEY_START;
-		desc_handle_irq(LOCOMO_IRQ_KEY_START, d, regs);
+		desc_handle_irq(LOCOMO_IRQ_KEY_START, d);
 	}
 }
 
@@ -264,8 +262,7 @@
 	.unmask	= locomo_key_unmask_irq,
 };
 
-static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc,
-			     struct pt_regs *regs)
+static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc)
 {
 	int req, i;
 	struct irqdesc *d;
@@ -280,7 +277,7 @@
 		d = irq_desc + LOCOMO_IRQ_GPIO_START;
 		for (i = 0; i <= 15; i++, irq++, d++) {
 			if (req & (0x0001 << i)) {
-				desc_handle_irq(irq, d, regs);
+				desc_handle_irq(irq, d);
 			}
 		}
 	}
@@ -328,15 +325,14 @@
 	.unmask	= locomo_gpio_unmask_irq,
 };
 
-static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc,
-			   struct pt_regs *regs)
+static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc)
 {
 	struct irqdesc *d;
 	void __iomem *mapbase = get_irq_chipdata(irq);
 
 	if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
 		d = irq_desc + LOCOMO_IRQ_LT_START;
-		desc_handle_irq(LOCOMO_IRQ_LT_START, d, regs);
+		desc_handle_irq(LOCOMO_IRQ_LT_START, d);
 	}
 }
 
@@ -374,8 +370,7 @@
 	.unmask	= locomo_lt_unmask_irq,
 };
 
-static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc,
-			    struct pt_regs *regs)
+static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc)
 {
 	int req, i;
 	struct irqdesc *d;
@@ -388,7 +383,7 @@
 
 		for (i = 0; i <= 3; i++, irq++, d++) {
 			if (req & (0x0001 << i)) {
-				desc_handle_irq(irq, d, regs);
+				desc_handle_irq(irq, d);
 			}
 		}
 	}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 30046ad..d5f7201 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -147,7 +147,7 @@
  * will call us again if there are more interrupts to process.
  */
 static void
-sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+sa1111_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int stat0, stat1, i;
 	void __iomem *base = get_irq_data(irq);
@@ -162,17 +162,17 @@
 	sa1111_writel(stat1, base + SA1111_INTSTATCLR1);
 
 	if (stat0 == 0 && stat1 == 0) {
-		do_bad_IRQ(irq, desc, regs);
+		do_bad_IRQ(irq, desc);
 		return;
 	}
 
 	for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
 		if (stat0 & 1)
-			handle_edge_irq(i, irq_desc + i, regs);
+			handle_edge_irq(i, irq_desc + i);
 
 	for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
 		if (stat1 & 1)
-			handle_edge_irq(i, irq_desc + i, regs);
+			handle_edge_irq(i, irq_desc + i);
 
 	/* For level-based interrupts */
 	desc->chip->unmask(irq);
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index f412ded..605dedf 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -258,7 +258,7 @@
 }
 
 
-irqreturn_t sharpsl_ac_isr(int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
 {
 	/* Delay the event slightly to debounce */
 	/* Must be a smaller delay than the chrg_full_isr below */
@@ -293,7 +293,7 @@
 /* Charging Finished Interrupt (Not present on Corgi) */
 /* Can trigger at the same time as an AC staus change so
    delay until after that has been processed */
-irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
 {
 	if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
 		return IRQ_HANDLED;
@@ -304,7 +304,7 @@
 	return IRQ_HANDLED;
 }
 
-irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
 {
 	int is_fatal = 0;
 
diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c
index 3f60dd9..34038ec 100644
--- a/arch/arm/common/time-acorn.c
+++ b/arch/arm/common/time-acorn.c
@@ -67,10 +67,10 @@
 }
 
 static irqreturn_t
-ioc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ioc_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index da69e66..4779f47 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -178,9 +178,3 @@
 EXPORT_SYMBOL(_find_first_bit_be);
 EXPORT_SYMBOL(_find_next_bit_be);
 #endif
-
-	/* syscalls */
-EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_exit);
-EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 3e14b13..b27513a 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -567,7 +567,7 @@
 }
 
 static void
-ecard_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+ecard_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	ecard_t *ec;
 	int called = 0;
@@ -586,7 +586,7 @@
 
 		if (pending) {
 			struct irqdesc *d = irq_desc + ec->irq;
-			desc_handle_irq(ec->irq, d, regs);
+			desc_handle_irq(ec->irq, d);
 			called ++;
 		}
 	}
@@ -609,7 +609,7 @@
 };
 
 static void
-ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc)
 {
 	const unsigned int statusmask = 15;
 	unsigned int status;
@@ -633,7 +633,7 @@
 			 * Serial cards should go in 0/1, ethernet/scsi in 2/3
 			 * otherwise you will lose serial data at high speeds!
 			 */
-			desc_handle_irq(ec->irq, d, regs);
+			desc_handle_irq(ec->irq, d);
 		} else {
 			printk(KERN_WARNING "card%d: interrupt from unclaimed "
 			       "card???\n", slot);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 2e1bf83..2c4ff1c 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -111,6 +111,7 @@
  */
 asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	struct irqdesc *desc = irq_desc + irq;
 
 	/*
@@ -122,12 +123,13 @@
 
 	irq_enter();
 
-	desc_handle_irq(irq, desc, regs);
+	desc_handle_irq(irq, desc);
 
 	/* AT91 specific workaround */
 	irq_finish(irq);
 
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 void set_irq_flags(unsigned int irq, unsigned int iflags)
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index b030320..c03cab5 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -27,6 +27,7 @@
 #include <linux/profile.h>
 #include <linux/sysdev.h>
 #include <linux/timer.h>
+#include <linux/irq.h>
 
 #include <asm/leds.h>
 #include <asm/thread_info.h>
@@ -324,9 +325,10 @@
 /*
  * Kernel system timer support.
  */
-void timer_tick(struct pt_regs *regs)
+void timer_tick(void)
 {
-	profile_tick(CPU_PROFILING, regs);
+	struct pt_regs *regs = get_irq_regs();
+	profile_tick(CPU_PROFILING);
 	do_leds();
 	do_set_rtc();
 	do_timer(1);
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index baa997c..fe3d297 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -127,12 +127,12 @@
 
 /* We enter here with IRQs enabled */
 static irqreturn_t
-aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+aaec2000_timer_interrupt(int irq, void *dev_id)
 {
 	/* TODO: Check timer accuracy */
 	write_seqlock(&xtime_lock);
 
-	timer_tick(regs);
+	timer_tick();
 	TIMER1_CLEAR = 1;
 
 	write_sequnlock(&xtime_lock);
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c
index a92a862..07c9cea 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_time.c
+++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c
@@ -65,13 +65,13 @@
 /*
  * IRQ handler for the timer.
  */
-static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 {
 	if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) {	/* This is a shared interrupt */
 		write_seqlock(&xtime_lock);
 
 		while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
-			timer_tick(regs);
+			timer_tick();
 			last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
 		}
 
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 58c9bf5..7467d64 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -332,7 +332,7 @@
 	.set_wake	= gpio_irq_set_wake,
 };
 
-static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs)
+static void gpio_irq_handler(unsigned irq, struct irqdesc *desc)
 {
 	unsigned	pin;
 	struct irqdesc	*gpio;
@@ -363,7 +363,7 @@
 					gpio_irq_mask(pin);
 				}
 				else
-					desc_handle_irq(pin, gpio, regs);
+					desc_handle_irq(pin, gpio);
 			}
 			pin++;
 			gpio++;
diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c
index a071eac..428493d 100644
--- a/arch/arm/mach-clps711x/time.c
+++ b/arch/arm/mach-clps711x/time.c
@@ -48,10 +48,10 @@
  * IRQ handler for the timer
  */
 static irqreturn_t
-p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+p720t_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index 92eaebd..fb10cf2 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -292,11 +292,11 @@
 extern unsigned long ioc_timer_gettimeoffset(void);
 
 static irqreturn_t
-clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+clps7500_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
-	timer_tick(regs);
+	timer_tick();
 
 	/* Why not using do_leds interface?? */
 	{
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index 70dd12e..90103ab 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -174,7 +174,7 @@
 }
 
 static irqreturn_t
-ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ebsa110_timer_interrupt(int irq, void *dev_id)
 {
 	u32 count;
 
@@ -190,7 +190,7 @@
 	__raw_writeb(count & 0xff, PIT_T1);
 	__raw_writeb(count >> 8, PIT_T1);
 
-	timer_tick(regs);
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index a87a784..e3fd1ab 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -97,7 +97,7 @@
 
 #define TIMER4_TICKS_PER_JIFFY		((CLOCK_TICK_RATE + (HZ/2)) / HZ)
 
-static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int ep93xx_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
@@ -106,7 +106,7 @@
 		(__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
 						>= TIMER4_TICKS_PER_JIFFY) {
 		last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
-		timer_tick(regs);
+		timer_tick();
 	}
 
 	write_sequnlock(&xtime_lock);
@@ -245,7 +245,7 @@
  * EP93xx IRQ handling
  *************************************************************************/
 static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
-		struct irqdesc *desc, struct pt_regs *regs)
+		struct irqdesc *desc)
 {
 	unsigned char status;
 	int i;
@@ -254,7 +254,7 @@
 	for (i = 0; i < 8; i++) {
 		if (status & (1 << i)) {
 			desc = irq_desc + IRQ_EP93XX_GPIO(0) + i;
-			desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc, regs);
+			desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc);
 		}
 	}
 
@@ -262,7 +262,7 @@
 	for (i = 0; i < 8; i++) {
 		if (status & (1 << i)) {
 			desc = irq_desc + IRQ_EP93XX_GPIO(8) + i;
-			desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc, regs);
+			desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc);
 		}
 	}
 }
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index 2af6108..fa6be87 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -28,13 +28,13 @@
 }
 
 static irqreturn_t
-timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer1_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
 	*CSR_TIMER1_CLR = 0;
 
-	timer_tick(regs);
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index a1ae49d..1463330 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -154,7 +155,7 @@
 /*
  * Warn on PCI errors.
  */
-static irqreturn_t dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dc21285_abort_irq(int irq, void *dev_id)
 {
 	unsigned int cmd;
 	unsigned int status;
@@ -165,7 +166,7 @@
 
 	if (status & PCI_STATUS_REC_MASTER_ABORT) {
 		printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n",
-			instruction_pointer(regs));
+			instruction_pointer(get_irq_regs()));
 		cmd |= PCI_STATUS_REC_MASTER_ABORT << 16;
 	}
 
@@ -184,7 +185,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dc21285_serr_irq(int irq, void *dev_id)
 {
 	struct timer_list *timer = dev_id;
 	unsigned int cntl;
@@ -206,7 +207,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dc21285_discard_irq(int irq, void *dev_id)
 {
 	printk(KERN_DEBUG "PCI: discard timer expired\n");
 	*CSR_SA110_CNTL &= 0xffffde07;
@@ -214,7 +215,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id)
 {
 	unsigned int cmd;
 
@@ -228,7 +229,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dc21285_parity_irq(int irq, void *dev_id)
 {
 	struct timer_list *timer = dev_id;
 	unsigned int cmd;
diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
index 87448c2..888dedd 100644
--- a/arch/arm/mach-footbridge/isa-irq.c
+++ b/arch/arm/mach-footbridge/isa-irq.c
@@ -85,17 +85,17 @@
 };
 
 static void
-isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+isa_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
 
 	if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
-		do_bad_IRQ(isa_irq, desc, regs);
+		do_bad_IRQ(isa_irq, desc);
 		return;
 	}
 
 	desc = irq_desc + isa_irq;
-	desc_handle_irq(isa_irq, desc, regs);
+	desc_handle_irq(isa_irq, desc);
 }
 
 static struct irqaction irq_cascade = {
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index c4810a4..d884a39 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -62,10 +62,10 @@
 }
 
 static irqreturn_t
-isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+isa_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
index c096b45..4719229 100644
--- a/arch/arm/mach-h720x/common.c
+++ b/arch/arm/mach-h720x/common.c
@@ -101,14 +101,14 @@
 
 static void
 h720x_gpio_handler(unsigned int mask, unsigned int irq,
-                 struct irqdesc *desc, struct pt_regs *regs)
+                 struct irqdesc *desc)
 {
 	IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
 	desc = irq_desc + irq;
 	while (mask) {
 		if (mask & 1) {
 			IRQDBG("handling irq %d\n", irq);
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 		}
 		irq++;
 		desc++;
@@ -117,63 +117,58 @@
 }
 
 static void
-h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = CPU_REG(GPIO_A_VIRT,GPIO_STAT);
 	irq = IRQ_CHAINED_GPIOA(0);
 	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
-	h720x_gpio_handler(mask, irq, desc, regs);
+	h720x_gpio_handler(mask, irq, desc);
 }
 
 static void
-h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 	mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT);
 	irq = IRQ_CHAINED_GPIOB(0);
 	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
-	h720x_gpio_handler(mask, irq, desc, regs);
+	h720x_gpio_handler(mask, irq, desc);
 }
 
 static void
-h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = CPU_REG(GPIO_C_VIRT,GPIO_STAT);
 	irq = IRQ_CHAINED_GPIOC(0);
 	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
-	h720x_gpio_handler(mask, irq, desc, regs);
+	h720x_gpio_handler(mask, irq, desc);
 }
 
 static void
-h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = CPU_REG(GPIO_D_VIRT,GPIO_STAT);
 	irq = IRQ_CHAINED_GPIOD(0);
 	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
-	h720x_gpio_handler(mask, irq, desc, regs);
+	h720x_gpio_handler(mask, irq, desc);
 }
 
 #ifdef CONFIG_CPU_H7202
 static void
-h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = CPU_REG(GPIO_E_VIRT,GPIO_STAT);
 	irq = IRQ_CHAINED_GPIOE(0);
 	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
-	h720x_gpio_handler(mask, irq, desc, regs);
+	h720x_gpio_handler(mask, irq, desc);
 }
 #endif
 
diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
index a9a8255..13f76bd 100644
--- a/arch/arm/mach-h720x/cpu-h7201.c
+++ b/arch/arm/mach-h720x/cpu-h7201.c
@@ -27,12 +27,12 @@
  * Timer interrupt handler
  */
 static irqreturn_t
-h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+h7201_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
 	CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
-	timer_tick(regs);
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
index da678d1..06fecae 100644
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ b/arch/arm/mach-h720x/cpu-h7202.c
@@ -106,8 +106,7 @@
  * we have to handle all timer interrupts in one place.
  */
 static void
-h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
@@ -115,7 +114,7 @@
 
 	if ( mask & TSTAT_T0INT ) {
 		write_seqlock(&xtime_lock);
-		timer_tick(regs);
+		timer_tick();
 		write_sequnlock(&xtime_lock);
 		if( mask == TSTAT_T0INT )
 			return;
@@ -126,7 +125,7 @@
 	desc = irq_desc + irq;
 	while (mask) {
 		if (mask & 1)
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 		irq++;
 		desc++;
 		mask >>= 1;
@@ -137,9 +136,9 @@
  * Timer interrupt handler
  */
 static irqreturn_t
-h7202_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+h7202_timer_interrupt(int irq, void *dev_id)
 {
-	h7202_timerx_demux_handler(0, NULL, regs);
+	h7202_timerx_demux_handler(0, NULL);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 3657887..6d50d85 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -279,8 +279,8 @@
  */
 int
 imx_dma_setup_handlers(imx_dmach_t dma_ch,
-		       void (*irq_handler) (int, void *, struct pt_regs *),
-		       void (*err_handler) (int, void *, struct pt_regs *, int),
+		       void (*irq_handler) (int, void *),
+		       void (*err_handler) (int, void *, int),
 		       void *data)
 {
 	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
@@ -461,7 +461,7 @@
 	return -ENODEV;
 }
 
-static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_err_handler(int irq, void *dev_id)
 {
 	int i, disr = DISR;
 	struct imx_dma_channel *channel;
@@ -500,7 +500,7 @@
 		/*imx_dma_channels[i].sg = NULL;*/
 
 		if (channel->name && channel->err_handler) {
-			channel->err_handler(i, channel->data, regs, errcode);
+			channel->err_handler(i, channel->data, errcode);
 			continue;
 		}
 
@@ -517,7 +517,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
 	int i, disr = DISR;
 
@@ -536,7 +536,7 @@
 				} else {
 					if (channel->irq_handler)
 						channel->irq_handler(i,
-							channel->data, regs);
+							channel->data);
 				}
 			} else {
 				/*
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
index 2688bd8..368b13b 100644
--- a/arch/arm/mach-imx/irq.c
+++ b/arch/arm/mach-imx/irq.c
@@ -146,13 +146,13 @@
 
 static void
 imx_gpio_handler(unsigned int mask, unsigned int irq,
-                 struct irqdesc *desc, struct pt_regs *regs)
+                 struct irqdesc *desc)
 {
 	desc = irq_desc + irq;
 	while (mask) {
 		if (mask & 1) {
 			DEBUG_IRQ("handling irq %d\n", irq);
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 		}
 		irq++;
 		desc++;
@@ -161,47 +161,43 @@
 }
 
 static void
-imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = ISR(0);
 	irq = IRQ_GPIOA(0);
-	imx_gpio_handler(mask, irq, desc, regs);
+	imx_gpio_handler(mask, irq, desc);
 }
 
 static void
-imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = ISR(1);
 	irq = IRQ_GPIOB(0);
-	imx_gpio_handler(mask, irq, desc, regs);
+	imx_gpio_handler(mask, irq, desc);
 }
 
 static void
-imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = ISR(2);
 	irq = IRQ_GPIOC(0);
-	imx_gpio_handler(mask, irq, desc, regs);
+	imx_gpio_handler(mask, irq, desc);
 }
 
 static void
-imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int mask, irq;
 
 	mask = ISR(3);
 	irq = IRQ_GPIOD(0);
-	imx_gpio_handler(mask, irq, desc, regs);
+	imx_gpio_handler(mask, irq, desc);
 }
 
 static struct irq_chip imx_internal_chip = {
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 6ed7523..8ae4a2c5 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -56,7 +56,7 @@
  * IRQ handler for the timer
  */
 static irqreturn_t
-imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+imx_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
@@ -64,7 +64,7 @@
 	if (IMX_TSTAT(TIMER_BASE))
 		IMX_TSTAT(TIMER_BASE) = 0;
 
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 
 	return IRQ_HANDLED;
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 42021fd..8d880cb 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -248,7 +248,7 @@
  * IRQ handler for the timer
  */
 static irqreturn_t
-integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+integrator_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
@@ -262,7 +262,7 @@
 	 * primary CPU
 	 */
 	if (hard_smp_processor_id() == 0) {
-		timer_tick(regs);
+		timer_tick();
 #ifdef CONFIG_SMP
 		smp_send_timer();
 #endif
@@ -272,7 +272,7 @@
 	/*
 	 * this is the ARM equivalent of the APIC timer interrupt
 	 */
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif /* CONFIG_SMP */
 
 	write_sequnlock(&xtime_lock);
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 678b6ba..771b65b 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -202,12 +202,12 @@
 };
 
 static void
-sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+sic_handle_irq(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS);
 
 	if (status == 0) {
-		do_bad_IRQ(irq, desc, regs);
+		do_bad_IRQ(irq, desc);
 		return;
 	}
 
@@ -218,7 +218,7 @@
 		irq += IRQ_SIC_START;
 
 		desc = irq_desc + irq;
-		desc_handle_irq(irq, desc, regs);
+		desc_handle_irq(irq, desc);
 	} while (status);
 }
 
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 4418f6d..fb8c6d9 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -440,9 +440,10 @@
 	return 1;
 }
 
-static irqreturn_t v3_irq(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t v3_irq(int irq, void *devid)
 {
 #ifdef CONFIG_DEBUG_LL
+	struct pt_regs *regs = get_irq_regs();
 	unsigned long pc = instruction_pointer(regs);
 	unsigned long instr = *(unsigned long *)pc;
 	char buf[128];
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
index ee49cf7..5278f58 100644
--- a/arch/arm/mach-integrator/time.c
+++ b/arch/arm/mach-integrator/time.c
@@ -96,8 +96,7 @@
 	.set_alarm	= integrator_rtc_set_alarm,
 };
 
-static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id,
-				     struct pt_regs *regs)
+static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id)
 {
 	writel(0, rtc_base + RTC_EOI);
 	return IRQ_HANDLED;
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 7f91f68..22c98e9 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -204,7 +204,7 @@
 	return offset / ticks_per_usec;
 }
 
-static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int ixp2000_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
@@ -213,7 +213,7 @@
 
 	while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr)
 							>= ticks_per_jiffy) {
-		timer_tick(regs);
+		timer_tick();
 		next_jiffy_time -= ticks_per_jiffy;
 	}
 
@@ -308,7 +308,7 @@
 /*************************************************************************
  * IRQ handling IXP2000
  *************************************************************************/
-static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc)
 {                               
 	int i;
 	unsigned long status = *IXP2000_GPIO_INST;
@@ -316,7 +316,7 @@
 	for (i = 0; i <= 7; i++) {
 		if (status & (1<<i)) {
 			desc = irq_desc + i + IRQ_IXP2000_GPIO0;
-			desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs);
+			desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc);
 		}
 	}
 }
@@ -401,7 +401,7 @@
 /*
  * Error interrupts. These are used extensively by the microengine drivers
  */
-static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc,  struct pt_regs *regs)
+static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	int i;
 	unsigned long status = *IXP2000_IRQ_ERR_STATUS;
@@ -409,7 +409,7 @@
 	for(i = 31; i >= 0; i--) {
 		if(status & (1 << i)) {
 			desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
-			desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);
+			desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc);
 		}
 	}
 }
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index a6f1480..9ee6383 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -133,11 +133,13 @@
 	struct pci_dev *dev;
 
 	if (ixdp2x00_master_npu()) {
-		dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
+		dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
 		pci_remove_bus_device(dev);
+		pci_dev_put(dev)
 	} else {
-		dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN);
+		dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN);
 		pci_remove_bus_device(dev);
+		pci_dev_put(dev)
 
 		ixdp2x00_slave_pci_postinit();
 	}
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index 91d36d9..70d247f 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -261,14 +261,16 @@
 
 		pci_common_init(&ixdp2800_pci);
 		if (ixdp2x00_master_npu()) {
-			dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+			dev = pci_get_bus_and_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
 			pci_remove_bus_device(dev);
+			pci_dev_put(dev);
 
 			ixdp2800_master_enable_slave();
 			ixdp2800_master_wait_for_slave_bus_scan();
 		} else {
-			dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+			dev = pci_get_bus_and_slot(1, IXDP2800_MASTER_ENET_DEVFN);
 			pci_remove_bus_device(dev);
+			pci_dev_put(dev);
 		}
 	}
 
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 40eef8b..aa26550 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -106,7 +106,7 @@
 		ixp2000_release_slowport(&old_cfg);
 }
 
-static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
         volatile u32 ex_interrupt = 0;
 	static struct slowport_cfg old_cfg;
@@ -132,7 +132,7 @@
 			struct irqdesc *cpld_desc;
 			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
 			cpld_desc = irq_desc + cpld_irq;
-			desc_handle_irq(cpld_irq, cpld_desc, regs);
+			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
 
@@ -241,11 +241,14 @@
 	/*
 	 * Remove PMC device is there is one
 	 */
-	if((dev = pci_find_slot(1, IXDP2X00_PMC_DEVFN)))
+	if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) {
 		pci_remove_bus_device(dev);
+		pci_dev_put(dev);
+	}
 
-	dev = pci_find_slot(0, IXDP2X00_21555_DEVFN);
+	dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN);
 	pci_remove_bus_device(dev);
+	pci_dev_put(dev);
 }
 
 /**************************************************************************
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 7f42366..9ccae9e 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -63,7 +63,7 @@
 
 static u32 valid_irq_mask;
 
-static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	u32 ex_interrupt;
 	int i;
@@ -82,7 +82,7 @@
 			struct irqdesc *cpld_desc;
 			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
 			cpld_desc = irq_desc + cpld_irq;
-			desc_handle_irq(cpld_irq, cpld_desc, regs);
+			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
 
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
index 566a078..a704a18 100644
--- a/arch/arm/mach-ixp23xx/core.c
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -251,7 +251,7 @@
 /*
  * TODO: Should this just be done at ASM level?
  */
-static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void pci_handler(unsigned int irq, struct irqdesc *desc)
 {
 	u32 pci_interrupt;
 	unsigned int irqno;
@@ -271,7 +271,7 @@
 	}
 
 	int_desc = irq_desc + irqno;
-	desc_handle_irq(irqno, int_desc, regs);
+	desc_handle_irq(irqno, int_desc);
 
 	desc->chip->unmask(irq);
 }
@@ -348,12 +348,12 @@
 }
 
 static irqreturn_t
-ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ixp23xx_timer_interrupt(int irq, void *dev_id)
 {
 	/* Clear Pending Interrupt by writing '1' to it */
 	*IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
 	while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) {
-		timer_tick(regs);
+		timer_tick();
 		next_jiffy_time += LATCH;
 	}
 
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index 37a32e6..b6ab0e8 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -60,7 +60,7 @@
 	*IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq);
 }
 
-static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc)
 {
 	u16 ex_interrupt =
 		*IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
@@ -74,7 +74,7 @@
 			int cpld_irq =
 				IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
 			cpld_desc = irq_desc + cpld_irq;
-			desc_handle_irq(cpld_irq, cpld_desc, regs);
+			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
 
@@ -97,7 +97,7 @@
 	*IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq);
 }
 
-static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc)
 {
 	u16 ex_interrupt =
 		*IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
@@ -111,7 +111,7 @@
 			int cpld_irq =
 				IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
 			cpld_desc = irq_desc + cpld_irq;
-			desc_handle_irq(cpld_irq, cpld_desc, regs);
+			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
 
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 35dd8b3..c7513f6 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -256,7 +256,7 @@
 
 #define CLOCK_TICKS_PER_USEC	((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
 
-static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
@@ -267,7 +267,7 @@
 	 * Catch up with the real idea of time
 	 */
 	while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
-		timer_tick(regs);
+		timer_tick();
 		last_jiffy_time += LATCH;
 	}
 
diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
index 81ffcae..29aa98d 100644
--- a/arch/arm/mach-ixp4xx/nas100d-power.c
+++ b/arch/arm/mach-ixp4xx/nas100d-power.c
@@ -24,7 +24,7 @@
 
 #include <asm/mach-types.h>
 
-static irqreturn_t nas100d_reset_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
 {
 	/* Signal init to do the ctrlaltdel action, this will bypass init if
 	 * it hasn't started and do a kernel_restart.
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
index a29b3b2..acd71e9 100644
--- a/arch/arm/mach-ixp4xx/nslu2-power.c
+++ b/arch/arm/mach-ixp4xx/nslu2-power.c
@@ -25,7 +25,7 @@
 
 #include <asm/mach-types.h>
 
-static irqreturn_t nslu2_power_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
 {
 	/* Signal init to do the ctrlaltdel action, this will bypass init if
 	 * it hasn't started and do a kernel_restart.
@@ -35,7 +35,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t nslu2_reset_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
 {
 	/* This is the paper-clip reset, it shuts the machine down directly.
 	 */
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 4f2ab48..15fbcc9 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -71,14 +71,13 @@
 };
 
 
-static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc,
-				  struct pt_regs *regs)
+static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc)
 {
 	u32 mask = CPLD_LATCHED_INTS;
 	irq = IRQ_KEV7A400_CPLD;
 	for (; mask; mask >>= 1, ++irq) {
 		if (mask & 1)
-			desc[irq].handle (irq, desc, regs);
+			desc[irq].handle (irq, desc);
 	}
 }
 
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index a21b12f..8441e0a 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -207,8 +207,7 @@
 	.unmask	= lh7a40x_unmask_cpld_irq,
 };
 
-static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
-				  struct pt_regs *regs)
+static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int mask = CPLD_INTERRUPTS;
 
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
index 18e8bb4..0ca20c6 100644
--- a/arch/arm/mach-lh7a40x/common.h
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -15,4 +15,4 @@
 extern void lh7a40x_clcd_init (void);
 extern void lh7a40x_init_board_irq (void);
 
-#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
+#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq))
diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c
index f9b3fe9..6460713 100644
--- a/arch/arm/mach-lh7a40x/irq-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/irq-kev7a400.c
@@ -51,14 +51,13 @@
 };
 
 static void
-lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc,
-		      struct pt_regs *regs)
+lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc)
 {
 	u32 mask = CPLD_LATCHED_INTS;
 	irq = IRQ_KEV_7A400_CPLD;
 	for (; mask; mask >>= 1, ++irq) {
 		if (mask & 1)
-			desc[irq].handle (irq, desc, regs);
+			desc[irq].handle (irq, desc);
 	}
 }
 
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
index d6055dd..b203768 100644
--- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
@@ -57,8 +57,7 @@
 	.unmask	= lh7a40x_unmask_cpld_irq,
 };
 
-static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
-				  struct pt_regs *regs)
+static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int mask = CPLD_INTERRUPTS;
 
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index ad5652e..bef3c4b 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -39,12 +39,12 @@
 #endif
 
 static irqreturn_t
-lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+lh7a40x_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
 	TIMER_EOI = 0;
-	timer_tick(regs);
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
index af0b135..edbbbdc 100644
--- a/arch/arm/mach-netx/generic.c
+++ b/arch/arm/mach-netx/generic.c
@@ -69,8 +69,7 @@
 #endif
 
 static void
-netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
-			struct pt_regs *regs)
+netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc)
 {
 	unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
 	unsigned int stat;
@@ -83,7 +82,7 @@
 	while (stat) {
 		if (stat & 1) {
 			DEBUG_IRQ("handling irq %d\n", irq);
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 		}
 		irq++;
 		desc++;
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index 6d72c81..0993336 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -38,11 +38,11 @@
  * IRQ handler for the timer
  */
 static irqreturn_t
-netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+netx_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 
 	/* acknowledge interrupt */
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 6b05647..3a62280 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -327,7 +327,7 @@
 
 #ifdef	CONFIG_PM
 static irqreturn_t
-osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
+osk_mistral_wake_interrupt(int irq, void *ignored)
 {
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index efe9bfc..8e40208 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -84,8 +84,7 @@
 	fpga_ack_irq(irq);
 }
 
-void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
-			      struct pt_regs *regs)
+void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc)
 {
 	struct irqdesc *d;
 	u32 stat;
@@ -101,7 +100,7 @@
 	     fpga_irq++, stat >>= 1) {
 		if (stat & 1) {
 			d = irq_desc + fpga_irq;
-			desc_handle_irq(fpga_irq, d, regs);
+			desc_handle_irq(fpga_irq, d);
 		}
 	}
 }
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index cd76185..4834758 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -682,8 +682,7 @@
 }
 
 
-static irqreturn_t  omap_wakeup_interrupt(int  irq, void *  dev,
-				     struct pt_regs *  regs)
+static irqreturn_t  omap_wakeup_interrupt(int irq, void *dev)
 {
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index c4b7902..4cc98a5 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -204,8 +204,7 @@
 
 #ifdef CONFIG_OMAP_SERIAL_WAKE
 
-static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id,
-					      struct pt_regs *regs)
+static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id)
 {
 	/* Need to do something with serial port right after wake-up? */
 	return IRQ_HANDLED;
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 4d91b9f..1b7e4a5 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -160,8 +160,7 @@
  * Latency during the interrupt is calculated using timer1.
  * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
  */
-static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
 {
 	unsigned long now, latency;
 
@@ -169,7 +168,7 @@
 	now = 0 - omap_mpu_timer_read(0);
 	latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
 	omap_mpu_timer_last = now - latency;
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 
 	return IRQ_HANDLED;
@@ -182,8 +181,7 @@
 };
 
 static unsigned long omap_mpu_timer1_overflows;
-static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id,
-					     struct pt_regs *regs)
+static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
 {
 	omap_mpu_timer1_overflows++;
 	return IRQ_HANDLED;
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index c37b0e6..03d6905 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -203,7 +203,7 @@
 	omap_set_gpio_dataout(LED2_GPIO15, 0);
 }
 
-static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs)
+static irqreturn_t apollon_sw_interrupt(int irq, void *ignored)
 {
 	static unsigned int led0, led1, led2;
 
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index fe5fd6d..973189c 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -37,13 +37,12 @@
 	omap_dm_timer_start(gptimer);
 }
 
-static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
-					    struct pt_regs *regs)
+static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
 	omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW);
-	timer_tick(regs);
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c
index ec01574..d6a279e 100644
--- a/arch/arm/mach-pnx4008/dma.c
+++ b/arch/arm/mach-pnx4008/dma.c
@@ -32,7 +32,7 @@
 
 static struct dma_channel {
 	char *name;
-	void (*irq_handler) (int, int, void *, struct pt_regs *);
+	void (*irq_handler) (int, int, void *);
 	void *data;
 	struct pnx4008_dma_ll *ll;
 	u32 ll_dma;
@@ -150,8 +150,7 @@
 #define VALID_CHANNEL(c)	(((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
 
 int pnx4008_request_channel(char *name, int ch,
-			    void (*irq_handler) (int, int, void *,
-						 struct pt_regs *), void *data)
+			    void (*irq_handler) (int, int, void *), void *data)
 {
 	int i, found = 0;
 
@@ -1033,7 +1032,7 @@
 
 EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled);
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
 	int i;
 	unsigned long dint = __raw_readl(DMAC_INT_STAT);
@@ -1053,8 +1052,7 @@
 					cause |= DMA_ERR_INT;
 				if (tcint & i_bit)
 					cause |= DMA_TC_INT;
-				channel->irq_handler(i, cause, channel->data,
-						     regs);
+				channel->irq_handler(i, cause, channel->data);
 			} else {
 				/*
 				 * IRQ for an unregistered DMA channel
diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c
index b986065..8621c20 100644
--- a/arch/arm/mach-pnx4008/time.c
+++ b/arch/arm/mach-pnx4008/time.c
@@ -47,15 +47,14 @@
 /*!
  * IRQ handler for the timer
  */
-static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id,
-					   struct pt_regs *regs)
+static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id)
 {
 	if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
 
 		write_seqlock(&xtime_lock);
 
 		do {
-			timer_tick(regs);
+			timer_tick();
 
 			/*
 			 * this algorithm takes care of possible delay
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 337c01c..a1a900d 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -212,7 +212,7 @@
  */
 static struct pxamci_platform_data corgi_mci_platform_data;
 
-static int corgi_mci_init(struct device *dev, irqreturn_t (*corgi_detect_int)(int, void *, struct pt_regs *), void *data)
+static int corgi_mci_init(struct device *dev, irq_handler_t corgi_detect_int, void *data)
 {
 	int err;
 
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 7d8c854..4440bab 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -27,13 +27,13 @@
 
 static struct dma_channel {
 	char *name;
-	void (*irq_handler)(int, void *, struct pt_regs *);
+	void (*irq_handler)(int, void *);
 	void *data;
 } dma_channels[PXA_DMA_CHANNELS];
 
 
 int pxa_request_dma (char *name, pxa_dma_prio prio,
-			 void (*irq_handler)(int, void *, struct pt_regs *),
+			 void (*irq_handler)(int, void *),
 		 	 void *data)
 {
 	unsigned long flags;
@@ -87,7 +87,7 @@
 	local_irq_restore(flags);
 }
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
 	int i, dint = DINT;
 
@@ -95,7 +95,7 @@
 		if (dint & (1 << i)) {
 			struct dma_channel *channel = &dma_channels[i];
 			if (channel->name && channel->irq_handler) {
-				channel->irq_handler(i, channel->data, regs);
+				channel->irq_handler(i, channel->data);
 			} else {
 				/*
 				 * IRQ for an unregistered DMA channel:
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 3e4b0ab..64df440 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -125,7 +125,7 @@
 	.pxafb_lcd_power = &idp_lcd_power
 };
 
-static int idp_mci_init(struct device *dev, irqreturn_t (*idp_detect_int)(int, void *, struct pt_regs *), void *data)
+static int idp_mci_init(struct device *dev, irq_handler_t idp_detect_int, void *data)
 {
 	/* setup GPIO for PXA25x MMC controller	*/
 	pxa_gpio_mode(GPIO6_MMCCLK_MD);
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 12141e2..ab1a160 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -143,8 +143,7 @@
  * Demux handler for GPIO>=2 edge detect interrupts
  */
 
-static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
-				   struct pt_regs *regs)
+static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int mask;
 	int loop;
@@ -160,7 +159,7 @@
 			mask >>= 2;
 			do {
 				if (mask & 1)
-					desc_handle_irq(irq, desc, regs);
+					desc_handle_irq(irq, desc);
 				irq++;
 				desc++;
 				mask >>= 1;
@@ -175,7 +174,7 @@
 			desc = irq_desc + irq;
 			do {
 				if (mask & 1)
-					desc_handle_irq(irq, desc, regs);
+					desc_handle_irq(irq, desc);
 				irq++;
 				desc++;
 				mask >>= 1;
@@ -190,7 +189,7 @@
 			desc = irq_desc + irq;
 			do {
 				if (mask & 1)
-					desc_handle_irq(irq, desc, regs);
+					desc_handle_irq(irq, desc);
 				irq++;
 				desc++;
 				mask >>= 1;
@@ -206,7 +205,7 @@
 			desc = irq_desc + irq;
 			do {
 				if (mask & 1)
-					desc_handle_irq(irq, desc, regs);
+					desc_handle_irq(irq, desc);
 				irq++;
 				desc++;
 				mask >>= 1;
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index eff2a91..5749f6b 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -75,8 +75,7 @@
 	.unmask		= lpd270_unmask_irq,
 };
 
-static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc,
-				  struct pt_regs *regs)
+static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned long pending;
 
@@ -86,7 +85,7 @@
 		if (likely(pending)) {
 			irq = LPD270_IRQ(0) + __ffs(pending);
 			desc = irq_desc + irq;
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 
 			pending = __raw_readw(LPD270_INT_STATUS) &
 						lpd270_irq_enabled;
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 157cf47..142c33c 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -85,8 +85,7 @@
 	.unmask		= lubbock_unmask_irq,
 };
 
-static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
-				struct pt_regs *regs)
+static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
 	do {
@@ -94,7 +93,7 @@
 		if (likely(pending)) {
 			irq = LUBBOCK_IRQ(0) + __ffs(pending);
 			desc = irq_desc + irq;
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 		}
 		pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
 	} while (pending);
@@ -379,7 +378,7 @@
 #define	MMC_POLL_RATE		msecs_to_jiffies(1000)
 
 static void lubbock_mmc_poll(unsigned long);
-static irqreturn_t (*mmc_detect_int)(int, void *, struct pt_regs *);
+static irq_handler_t mmc_detect_int;
 
 static struct timer_list mmc_timer = {
 	.function	= lubbock_mmc_poll,
@@ -398,22 +397,22 @@
 	if (LUB_IRQ_SET_CLR & (1 << 0))
 		mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE);
 	else {
-		(void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data, NULL);
+		(void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data);
 		enable_irq(LUBBOCK_SD_IRQ);
 	}
 }
 
-static irqreturn_t lubbock_detect_int(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t lubbock_detect_int(int irq, void *data)
 {
 	/* IRQ is level triggered; disable, and poll for removal */
 	disable_irq(irq);
 	mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE);
 
-	return mmc_detect_int(irq, data, regs);
+	return mmc_detect_int(irq, data);
 }
 
 static int lubbock_mci_init(struct device *dev,
-		irqreturn_t (*detect_int)(int, void *, struct pt_regs *),
+		irq_handler_t detect_int,
 		void *data)
 {
 	/* setup GPIO for PXA25x MMC controller	*/
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 7ba0447..49c34d9 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -71,8 +71,7 @@
 	.unmask		= mainstone_unmask_irq,
 };
 
-static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
-				  struct pt_regs *regs)
+static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
 	do {
@@ -80,7 +79,7 @@
 		if (likely(pending)) {
 			irq = MAINSTONE_IRQ(0) + __ffs(pending);
 			desc = irq_desc + irq;
-			desc_handle_irq(irq, desc, regs);
+			desc_handle_irq(irq, desc);
 		}
 		pending = MST_INTSETCLR & mainstone_irq_enabled;
 	} while (pending);
@@ -314,7 +313,7 @@
 	.pxafb_backlight_power	= mainstone_backlight_power,
 };
 
-static int mainstone_mci_init(struct device *dev, irqreturn_t (*mstone_detect_int)(int, void *, struct pt_regs *), void *data)
+static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_int, void *data)
 {
 	int err;
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 5e8c098..34fb80b 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -197,7 +197,7 @@
  */
 static struct pxamci_platform_data poodle_mci_platform_data;
 
-static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data)
+static int poodle_mci_init(struct device *dev, irq_handler_t poodle_detect_int, void *data)
 {
 	int err;
 
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 401cdb8..3cbac63 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -291,7 +291,7 @@
 
 static struct pxamci_platform_data spitz_mci_platform_data;
 
-static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(int, void *, struct pt_regs *), void *data)
+static int spitz_mci_init(struct device *dev, irq_handler_t spitz_detect_int, void *data)
 {
 	int err;
 
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 1fddfea..6cc2027 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -65,7 +65,7 @@
 static DEFINE_MUTEX(mutex);
 static int use_count[PXA_SSP_PORTS] = {0, 0, 0};
 
-static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ssp_interrupt(int irq, void *dev_id)
 {
 	struct ssp_dev *dev = (struct ssp_dev*) dev_id;
 	unsigned int status = SSSR_P(dev->port);
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 5dbd191..3ac268f 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -75,7 +75,7 @@
 #endif
 
 static irqreturn_t
-pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+pxa_timer_interrupt(int irq, void *dev_id)
 {
 	int next_match;
 
@@ -105,7 +105,7 @@
 	 * exactly one tick period which should be a pretty rare event.
 	 */
 	do {
-		timer_tick(regs);
+		timer_tick();
 		OSSR = OSSR_M0;  /* Clear match on timer 0 */
 		next_match = (OSMR0 += LATCH);
 	} while( (signed long)(next_match - OSCR) <= 8 );
@@ -157,13 +157,13 @@
 }
 
 static irqreturn_t
-pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
+pxa_dyn_tick_handler(int irq, void *dev_id)
 {
 	if (match_posponed) {
 		match_posponed = 0;
 		OSMR0 = initial_match;
 		if ( (signed long)(initial_match - OSCR) <= 8 )
-			return pxa_timer_interrupt(irq, dev_id, regs);
+			return pxa_timer_interrupt(irq, dev_id);
 	}
 	return IRQ_NONE;
 }
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 2493536..7915a5a 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -174,7 +174,7 @@
  */
 static struct pxamci_platform_data tosa_mci_platform_data;
 
-static int tosa_mci_init(struct device *dev, irqreturn_t (*tosa_detect_int)(int, void *, struct pt_regs *), void *data)
+static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void *data)
 {
 	int err;
 
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 910571e..c1827d0 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -270,7 +270,7 @@
 #endif		/* CONFIG_MACH_TRIZEPS4_CONXS */
 EXPORT_SYMBOL(board_pcmcia_power);
 
-static int trizeps4_mci_init(struct device *dev, irqreturn_t (*mci_detect_int)(int, void *, struct pt_regs *), void *data)
+static int trizeps4_mci_init(struct device *dev, irq_handler_t mci_detect_int, void *data)
 {
 	int err;
 	/* setup GPIO for PXA27x MMC controller */
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index da02869..68c6705 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -515,18 +515,18 @@
 /*
  * IRQ handler for the timer
  */
-static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
 	// ...clear the interrupt
 	writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
 
-	timer_tick(regs);
+	timer_tick();
 
 #if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
 	smp_send_timer();
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 
 	write_sequnlock(&xtime_lock);
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index ac511d4..596379a 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -83,7 +83,7 @@
 	sg->length |= flags;
 }
 
-static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 {
 	dma_t *dma = (dma_t *)dev_id;
 	unsigned long base = dma->dma_base;
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index 440e9aa..23d5bee 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -112,8 +112,7 @@
 
 static void
 bast_irq_pc104_demux(unsigned int irq,
-		     struct irqdesc *desc,
-		     struct pt_regs *regs)
+		     struct irqdesc *desc)
 {
 	unsigned int stat;
 	unsigned int irqno;
@@ -133,7 +132,7 @@
 			if (stat & 1) {
 				irqno = bast_pc104_irqs[i];
 				desc = irq_desc + irqno;
-				desc_handle_irq(irqno, desc, regs);
+				desc_handle_irq(irqno, desc);
 			}
 		}
 	}
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index d264bbb..3d211dc 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -595,7 +595,7 @@
 #define dmadbg2(x...)
 
 static irqreturn_t
-s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
+s3c2410_dma_irq(int irq, void *devpw)
 {
 	struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
 	struct s3c2410_dma_buf  *buf;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 3e9f346..683b349 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -480,8 +480,7 @@
 
 /* irq demux for adc */
 static void s3c_irq_demux_adc(unsigned int irq,
-			      struct irqdesc *desc,
-			      struct pt_regs *regs)
+			      struct irqdesc *desc)
 {
 	unsigned int subsrc, submsk;
 	unsigned int offset = 9;
@@ -500,17 +499,16 @@
 	if (subsrc != 0) {
 		if (subsrc & 1) {
 			mydesc = irq_desc + IRQ_TC;
-			desc_handle_irq(IRQ_TC, mydesc, regs);
+			desc_handle_irq(IRQ_TC, mydesc);
 		}
 		if (subsrc & 2) {
 			mydesc = irq_desc + IRQ_ADC;
-			desc_handle_irq(IRQ_ADC, mydesc, regs);
+			desc_handle_irq(IRQ_ADC, mydesc);
 		}
 	}
 }
 
-static void s3c_irq_demux_uart(unsigned int start,
-			       struct pt_regs *regs)
+static void s3c_irq_demux_uart(unsigned int start)
 {
 	unsigned int subsrc, submsk;
 	unsigned int offset = start - IRQ_S3CUART_RX0;
@@ -533,17 +531,17 @@
 		desc = irq_desc + start;
 
 		if (subsrc & 1)
-			desc_handle_irq(start, desc, regs);
+			desc_handle_irq(start, desc);
 
 		desc++;
 
 		if (subsrc & 2)
-			desc_handle_irq(start+1, desc, regs);
+			desc_handle_irq(start+1, desc);
 
 		desc++;
 
 		if (subsrc & 4)
-			desc_handle_irq(start+2, desc, regs);
+			desc_handle_irq(start+2, desc);
 	}
 }
 
@@ -551,35 +549,31 @@
 
 static void
 s3c_irq_demux_uart0(unsigned int irq,
-		    struct irqdesc *desc,
-		    struct pt_regs *regs)
+		    struct irqdesc *desc)
 {
 	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX0, regs);
+	s3c_irq_demux_uart(IRQ_S3CUART_RX0);
 }
 
 static void
 s3c_irq_demux_uart1(unsigned int irq,
-		    struct irqdesc *desc,
-		    struct pt_regs *regs)
+		    struct irqdesc *desc)
 {
 	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX1, regs);
+	s3c_irq_demux_uart(IRQ_S3CUART_RX1);
 }
 
 static void
 s3c_irq_demux_uart2(unsigned int irq,
-		    struct irqdesc *desc,
-		    struct pt_regs *regs)
+		    struct irqdesc *desc)
 {
 	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
+	s3c_irq_demux_uart(IRQ_S3CUART_RX2);
 }
 
 static void
 s3c_irq_demux_extint8(unsigned int irq,
-		      struct irqdesc *desc,
-		      struct pt_regs *regs)
+		      struct irqdesc *desc)
 {
 	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
 	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
@@ -594,15 +588,14 @@
 		eintpnd &= ~(1<<irq);
 
 		irq += (IRQ_EINT4 - 4);
-		desc_handle_irq(irq, irq_desc + irq, regs);
+		desc_handle_irq(irq, irq_desc + irq);
 	}
 
 }
 
 static void
 s3c_irq_demux_extint4t7(unsigned int irq,
-			struct irqdesc *desc,
-			struct pt_regs *regs)
+			struct irqdesc *desc)
 {
 	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
 	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
@@ -618,7 +611,7 @@
 
 		irq += (IRQ_EINT4 - 4);
 
-		desc_handle_irq(irq, irq_desc + irq, regs);
+		desc_handle_irq(irq, irq_desc + irq);
 	}
 }
 
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index ba5109a..817e2c6 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -226,7 +226,7 @@
 #endif
 
 static irqreturn_t
-amlm5900_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
+amlm5900_wake_interrupt(int irq, void *ignored)
 {
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
index fc08febe..39db075 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2440-irq.c
@@ -42,8 +42,7 @@
 /* WDT/AC97 */
 
 static void s3c_irq_demux_wdtac97(unsigned int irq,
-				  struct irqdesc *desc,
-				  struct pt_regs *regs)
+				  struct irqdesc *desc)
 {
 	unsigned int subsrc, submsk;
 	struct irqdesc *mydesc;
@@ -61,11 +60,11 @@
 	if (subsrc != 0) {
 		if (subsrc & 1) {
 			mydesc = irq_desc + IRQ_S3C2440_WDT;
-			desc_handle_irq(IRQ_S3C2440_WDT, mydesc, regs);
+			desc_handle_irq(IRQ_S3C2440_WDT, mydesc);
 		}
 		if (subsrc & 2) {
 			mydesc = irq_desc + IRQ_S3C2440_AC97;
-			desc_handle_irq(IRQ_S3C2440_AC97, mydesc, regs);
+			desc_handle_irq(IRQ_S3C2440_AC97, mydesc);
 		}
 	}
 }
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
index ec702f8..146f210 100644
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ b/arch/arm/mach-s3c2410/s3c244x-irq.c
@@ -42,8 +42,7 @@
 /* camera irq */
 
 static void s3c_irq_demux_cam(unsigned int irq,
-			      struct irqdesc *desc,
-			      struct pt_regs *regs)
+			      struct irqdesc *desc)
 {
 	unsigned int subsrc, submsk;
 	struct irqdesc *mydesc;
@@ -61,11 +60,11 @@
 	if (subsrc != 0) {
 		if (subsrc & 1) {
 			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
-			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
+			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc);
 		}
 		if (subsrc & 2) {
 			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
-			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
+			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc);
 		}
 	}
 }
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 00d1cfc..9910bf0 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -128,10 +128,10 @@
  * IRQ handler for the timer
  */
 static irqreturn_t
-s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+s3c2410_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index c635efa..22b0e1c 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -58,7 +58,7 @@
 }
 
 static irqreturn_t
-usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
+usb_simtec_ocirq(int irq, void *pw)
 {
 	struct s3c2410_hcd_info *info = (struct s3c2410_hcd_info *)pw;
 
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 6395977..90a4130 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -82,6 +82,14 @@
 		.twr		= 9,
 		.refresh	= 64000,
 		.cas_latency	= 3,
+	}, {    /* Samsung K4S281632B-1H */
+	        .name           = "K4S281632b-1H",
+		.rows           = 12,
+		.tck            = 10,
+		.trp            = 20,
+		.twr            = 10,
+		.refresh        = 64000,
+		.cas_latency    = 3,
 	}, {	/* Samsung KM416S4030CT */
 		.name		= "KM416S4030CT",
 		.rows		= 13,
@@ -366,6 +374,8 @@
 
 		if (machine_is_h3100())
 			name = "KM416S4030CT";
+		if (machine_is_jornada720())
+		        name = "K4S281632B-1H";
 	}
 
 	sdram = sa1110_find_sdram(name);
diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c
index 2ea2a65..1fbe053 100644
--- a/arch/arm/mach-sa1100/dma.c
+++ b/arch/arm/mach-sa1100/dma.c
@@ -42,7 +42,7 @@
 static spinlock_t dma_list_lock;
 
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
 	dma_regs_t *dma_regs = dev_id;
 	sa1100_dma_t *dma = dma_chan + (((u_int)dma_regs >> 5) & 7);
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 7364478..fa6dc71 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -702,7 +702,7 @@
 	GPIO2_SD_CON_SLT,
 };
 
-static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc)
 {
 	int i;
 
@@ -719,14 +719,14 @@
 		if (0) printk("%s KPIO 0x%08X\n", __FUNCTION__, irq);
 		for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
 			if (irq & kpio_irq_mask[j])
-				do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j, regs);
+				do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j);
 
 		/* GPIO2 */
 		irq = H3800_ASIC2_GPIINTFLAG;
 		if (0) printk("%s GPIO 0x%08X\n", __FUNCTION__, irq);
 		for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
 			if (irq & gpio_irq_mask[j])
-				do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j , regs);
+				do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j);
 	}
 
 	if (i >= MAX_ASIC_ISR_LOOPS)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index b55b90a..f4c6322 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -110,8 +110,7 @@
  * and call the handler.
  */
 static void
-sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
-			 struct pt_regs *regs)
+sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int mask;
 
@@ -128,7 +127,7 @@
 		mask >>= 11;
 		do {
 			if (mask & 1)
-				desc_handle_irq(irq, desc, regs);
+				desc_handle_irq(irq, desc);
 			mask >>= 1;
 			irq++;
 			desc++;
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index af6d277..354d5e9 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -29,7 +29,7 @@
  * is rather unfortunate.
  */
 static void
-neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+neponset_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned int irr;
 
@@ -69,12 +69,12 @@
 
 			if (irr & IRR_ETHERNET) {
 				d = irq_desc + IRQ_NEPONSET_SMC9196;
-				desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs);
+				desc_handle_irq(IRQ_NEPONSET_SMC9196, d);
 			}
 
 			if (irr & IRR_USAR) {
 				d = irq_desc + IRQ_NEPONSET_USAR;
-				desc_handle_irq(IRQ_NEPONSET_USAR, d, regs);
+				desc_handle_irq(IRQ_NEPONSET_USAR, d);
 			}
 
 			desc->chip->unmask(irq);
@@ -82,7 +82,7 @@
 
 		if (irr & IRR_SA1111) {
 			d = irq_desc + IRQ_NEPONSET_SA1111;
-			desc_handle_irq(IRQ_NEPONSET_SA1111, d, regs);
+			desc_handle_irq(IRQ_NEPONSET_SA1111, d);
 		}
 	}
 }
diff --git a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
index 5eba5fb..59703c6 100644
--- a/arch/arm/mach-sa1100/ssp.c
+++ b/arch/arm/mach-sa1100/ssp.c
@@ -25,7 +25,7 @@
 
 #define TIMEOUT 100000
 
-static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ssp_interrupt(int irq, void *dev_id)
 {
 	unsigned int status = Ser4SSSR;
 
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 49ae716..4284bd6 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -77,7 +77,7 @@
 #endif
 
 static irqreturn_t
-sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+sa1100_timer_interrupt(int irq, void *dev_id)
 {
 	unsigned int next_match;
 
@@ -99,7 +99,7 @@
 	 * handlers.
 	 */
 	do {
-		timer_tick(regs);
+		timer_tick();
 		OSSR = OSSR_M0;  /* Clear match on timer 0 */
 		next_match = (OSMR0 += LATCH);
 	} while ((signed long)(next_match - OSCR) <= 0);
@@ -151,13 +151,13 @@
 }
 
 static irqreturn_t
-sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
+sa1100_dyn_tick_handler(int irq, void *dev_id)
 {
 	if (match_posponed) {
 		match_posponed = 0;
 		OSMR0 = initial_match;
 		if ((signed long)(initial_match - OSCR) <= 0)
-			return sa1100_timer_interrupt(irq, dev_id, regs);
+			return sa1100_timer_interrupt(irq, dev_id);
 	}
 	return IRQ_NONE;
 }
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 1095df3..0e480fa 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -80,10 +80,10 @@
 #define HZ_TIME ((1193180 + HZ/2) / HZ)
 
 static irqreturn_t
-shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+shark_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
-	timer_tick(regs);
+	timer_tick();
 	write_sequnlock(&xtime_lock);
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c
index b227052..297ecf1 100644
--- a/arch/arm/mach-shark/irq.c
+++ b/arch/arm/mach-shark/irq.c
@@ -61,7 +61,7 @@
 
 static void shark_ack_8259A_irq(unsigned int irq){}
 
-static irqreturn_t bogus_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bogus_int(int irq, void *dev_id)
 {
 	printk("Got interrupt %i!\n",irq);
 	return IRQ_NONE;
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index f2bbef0..3b85761 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -77,12 +77,12 @@
 };
 
 static void
-sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+sic_handle_irq(unsigned int irq, struct irqdesc *desc)
 {
 	unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
 
 	if (status == 0) {
-		do_bad_IRQ(irq, desc, regs);
+		do_bad_IRQ(irq, desc);
 		return;
 	}
 
@@ -93,7 +93,7 @@
 		irq += IRQ_SIC_START;
 
 		desc = irq_desc + irq;
-		desc_handle_irq(irq, desc, regs);
+		desc_handle_irq(irq, desc);
 	} while (status);
 }
 
@@ -188,12 +188,12 @@
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	=  VERSATILE_PCI_VIRT_BASE,
+		.virtual	=  (unsigned long)VERSATILE_PCI_VIRT_BASE,
 		.pfn		= __phys_to_pfn(VERSATILE_PCI_BASE),
 		.length		= VERSATILE_PCI_BASE_SIZE,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	=  VERSATILE_PCI_CFG_VIRT_BASE,
+		.virtual	=  (unsigned long)VERSATILE_PCI_CFG_VIRT_BASE,
 		.pfn		= __phys_to_pfn(VERSATILE_PCI_CFG_BASE),
 		.length		= VERSATILE_PCI_CFG_BASE_SIZE,
 		.type		= MT_DEVICE
@@ -851,14 +851,14 @@
 /*
  * IRQ handler for the timer
  */
-static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
 	// ...clear the interrupt
 	writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
 
-	timer_tick(regs);
+	timer_tick();
 
 	write_sequnlock(&xtime_lock);
 
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index 13bbd08..5cd0b5d 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -40,14 +40,15 @@
  * Cfg   42000000 - 42FFFFFF	  PCI config
  *
  */
-#define SYS_PCICTL			IO_ADDRESS(VERSATILE_SYS_PCICTL)
-#define PCI_IMAP0			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
-#define PCI_IMAP1			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
-#define PCI_IMAP2			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
-#define PCI_SMAP0			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
-#define PCI_SMAP1			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
-#define PCI_SMAP2			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
-#define PCI_SELFID			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
+#define __IO_ADDRESS(n) ((void __iomem *)(unsigned long)IO_ADDRESS(n))
+#define SYS_PCICTL		__IO_ADDRESS(VERSATILE_SYS_PCICTL)
+#define PCI_IMAP0		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
+#define PCI_IMAP1		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
+#define PCI_IMAP2		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
+#define PCI_SMAP0		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
+#define PCI_SMAP1		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
+#define PCI_SMAP2		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SELFID		__IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
 
 #define DEVICE_ID_OFFSET		0x00
 #define CSR_OFFSET			0x04
@@ -76,7 +77,7 @@
 __setup("pci_slot_ignore=", versatile_pci_slot_ignore);
 
 
-static unsigned long __pci_addr(struct pci_bus *bus,
+static void __iomem *__pci_addr(struct pci_bus *bus,
 				unsigned int devfn, int offset)
 {
 	unsigned int busnr = bus->number;
@@ -91,14 +92,14 @@
 	if (devfn > 255)
 		BUG();
 
-	return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
+	return VERSATILE_PCI_CFG_VIRT_BASE + ((busnr << 16) |
 		(PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
 }
 
 static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 				 int size, u32 *val)
 {
-	unsigned long addr = __pci_addr(bus, devfn, where);
+	void __iomem *addr = __pci_addr(bus, devfn, where & ~3);
 	u32 v;
 	int slot = PCI_SLOT(devfn);
 
@@ -121,13 +122,12 @@
 			break;
 
 		case 2:
-			v = __raw_readl(addr & ~3);
-			if (addr & 2) v >>= 16;
+			v = __raw_readl(addr);
+			if (where & 2) v >>= 16;
  			v &= 0xffff;
 			break;
 
 		default:
-			addr &= ~3;
 			v = __raw_readl(addr);
 			break;
 		}
@@ -140,7 +140,7 @@
 static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 				  int size, u32 val)
 {
-	unsigned long addr = __pci_addr(bus, devfn, where);
+	void __iomem *addr = __pci_addr(bus, devfn, where);
 	int slot = PCI_SLOT(devfn);
 
 	if (pci_slot_ignore & (1 << slot)) {
@@ -279,7 +279,7 @@
 	printk("PCI core found (slot %d)\n",myslot);
 
 	__raw_writel(myslot, PCI_SELFID);
-	local_pci_cfg_base = (void *) VERSATILE_PCI_CFG_VIRT_BASE + (myslot << 11);
+	local_pci_cfg_base = VERSATILE_PCI_CFG_VIRT_BASE + (myslot << 11);
 
 	val = __raw_readl(local_pci_cfg_base + CSR_OFFSET);
 	val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 591fc31..4654405 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -361,14 +361,14 @@
 }
 EXPORT_SYMBOL(__ioremap);
 
-void __iounmap(void __iomem *addr)
+void __iounmap(volatile void __iomem *addr)
 {
 #ifndef CONFIG_SMP
 	struct vm_struct **p, *tmp;
 #endif
 	unsigned int section_mapping = 0;
 
-	addr = (void __iomem *)(PAGE_MASK & (unsigned long)addr);
+	addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long)addr);
 
 #ifndef CONFIG_SMP
 	/*
@@ -395,6 +395,6 @@
 #endif
 
 	if (!section_mapping)
-		vunmap(addr);
+		vunmap((void __force *)addr);
 }
 EXPORT_SYMBOL(__iounmap);
diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c
index 726ad2b..7c3289c 100644
--- a/arch/arm/oprofile/op_model_xscale.c
+++ b/arch/arm/oprofile/op_model_xscale.c
@@ -20,7 +20,8 @@
 #include <linux/sched.h>
 #include <linux/oprofile.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+
 #include <asm/system.h>
 
 #include "op_counter.h"
@@ -341,7 +342,7 @@
 	__asm__ __volatile__ ("mcr p14, 0, %0, c5, c1, 0" : : "r" (flag));
 }
 
-static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t xscale_pmu_interrupt(int irq, void *arg)
 {
 	int i;
 	u32 pmnc;
@@ -356,7 +357,7 @@
 			continue;
 
 		write_counter(i, -(u32)results[i].reset_counter);
-		oprofile_add_sample(regs, i);
+		oprofile_add_sample(get_irq_regs(), i);
 		results[i].ovf--;
 	}
 
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
index 06282df..f530abd 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/plat-iop/time.c
@@ -47,7 +47,7 @@
 }
 
 static irqreturn_t
-iop3xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+iop3xx_timer_interrupt(int irq, void *dev_id)
 {
 	write_seqlock(&xtime_lock);
 
@@ -57,7 +57,7 @@
 
 	while ((signed long)(next_jiffy_time - *IOP3XX_TU_TCR1)
 							>= ticks_per_jiffy) {
-		timer_tick(regs);
+		timer_tick();
 		next_jiffy_time -= ticks_per_jiffy;
 	}
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 1bbb431..bb045e5 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -899,8 +899,7 @@
 	return 1;
 }
 
-static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id,
-					 struct pt_regs *regs)
+static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
 {
 	int ch = ((int) dev_id) - 1;
 	int handled = 0;
@@ -962,8 +961,7 @@
 }
 
 /* STATUS register count is from 1-32 while our is 0-31 */
-static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id,
-					 struct pt_regs *regs)
+static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
 {
 	u32 val;
 	int i;
@@ -1220,8 +1218,7 @@
 	omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L);
 }
 
-static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id,
-				       struct pt_regs *regs)
+static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id)
 {
 	u16 w;
 
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index f55f99a..8162eed 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -783,8 +783,7 @@
  * line's interrupt handler has been run, we may miss some nested
  * interrupts.
  */
-static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
-			     struct pt_regs *regs)
+static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc)
 {
 	void __iomem *isr_reg = NULL;
 	u32 isr;
@@ -882,7 +881,7 @@
 				continue;
 			}
 
-			desc_handle_irq(gpio_irq, d, regs);
+			desc_handle_irq(gpio_irq, d);
 
 			if (unlikely((d->status & IRQ_PENDING) && !d->depth)) {
 				irq_mask = 1 <<
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index ade9a0f..ec50008 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -96,7 +96,7 @@
 	DBG("***********************\n");
 }
 
-static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
 {
 	struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
 
@@ -106,7 +106,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
 {
 	struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
 
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
index cf6df33..2653106 100644
--- a/arch/arm/plat-omap/timer32k.c
+++ b/arch/arm/plat-omap/timer32k.c
@@ -194,8 +194,7 @@
  * issues with dynamic tick. In the dynamic tick case, we need to lock
  * with irqsave.
  */
-static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id)
 {
 	unsigned long now;
 
@@ -205,7 +204,7 @@
 	while ((signed long)(now - omap_32k_last_tick)
 						>= OMAP_32K_TICKS_PER_HZ) {
 		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
-		timer_tick(regs);
+		timer_tick();
 	}
 
 	/* Restart timer so we don't drift off due to modulo or dynamic tick.
@@ -218,19 +217,17 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
 {
-	return _omap_32k_timer_interrupt(irq, dev_id, regs);
+	return _omap_32k_timer_interrupt(irq, dev_id);
 }
 
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
-					    struct pt_regs *regs)
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
 {
 	unsigned long flags;
 
 	write_seqlock_irqsave(&xtime_lock, flags);
-	_omap_32k_timer_interrupt(irq, dev_id, regs);
+	_omap_32k_timer_interrupt(irq, dev_id);
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	return IRQ_HANDLED;
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index b02af1d..579c69a 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -4,7 +4,7 @@
 #
 # Up to date versions of this file can be obtained from:
 #
-#   http://www.arm.linux.org.uk/developer/machines/?action=download
+#   http://www.arm.linux.org.uk/developer/machines/download.php
 #
 # Please do not send patches to this file; it is automatically generated!
 # To add an entry into this database, please see Documentation/arm/README,
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Sat Sep 23 13:20:43 2006
+# Last update: Mon Oct 16 21:13:36 2006
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1157,3 +1157,17 @@
 oti4110			MACH_OTI4110		OTI4110			1144
 hme_pxa			MACH_HME_PXA		HME_PXA			1145
 deisterdca		MACH_DEISTERDCA		DEISTERDCA		1146
+ces_ssem2		MACH_CES_SSEM2		CES_SSEM2		1147
+ces_mtr			MACH_CES_MTR		CES_MTR			1148
+tds_avng_sbc		MACH_TDS_AVNG_SBC	TDS_AVNG_SBC		1149
+everest			MACH_EVEREST		EVEREST			1150
+pnx4010			MACH_PNX4010		PNX4010			1151
+oxnas			MACH_OXNAS		OXNAS			1152
+fiori			MACH_FIORI		FIORI			1153
+ml1200			MACH_ML1200		ML1200			1154
+cactus			MACH_CACTUS		CACTUS			1155
+nb2xxx			MACH_NB2XXX		NB2XXX			1156
+hw6900			MACH_HW6900		HW6900			1157
+cdcs_quoll		MACH_CDCS_QUOLL		CDCS_QUOLL		1158
+quicksilver		MACH_QUICKSILVER	QUICKSILVER		1159
+uplat926		MACH_UPLAT926		UPLAT926		1160
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index dedbb44..a657a28 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -90,7 +90,7 @@
 
 	info.si_signo = SIGFPE;
 	info.si_code = sicode;
-	info.si_addr = (void *)(instruction_pointer(regs) - 4);
+	info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
 
 	/*
 	 * This is the same as NWFPE, because it's not clear what
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index 07907b6..93293d0 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -202,14 +202,6 @@
 EXPORT_SYMBOL(elf_platform);
 EXPORT_SYMBOL(elf_hwcap);
 
-	/* syscalls */
-EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
-EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
-EXPORT_SYMBOL(sys_exit);
-EXPORT_SYMBOL(sys_wait4);
-
 #ifdef CONFIG_PREEMPT
 EXPORT_SYMBOL(kernel_flag);
 #endif
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index 3e56b9f..5a247ba 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -124,15 +124,15 @@
  *
  * In UP mode, it is invoked from the (global) timer_interrupt.
  */
-static void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void local_timer_interrupt(int irq, void *dev_id)
 {
 	if (current->pid)
-		profile_tick(CPU_PROFILING, regs);
-	update_process_times(user_mode(regs));
+		profile_tick(CPU_PROFILING);
+	update_process_times(user_mode(get_irq_regs()));
 }
 
 static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer_interrupt(int irq, void *dev_id)
 {
 	unsigned int count;
 
@@ -157,7 +157,7 @@
 	 *
 	 * SMP is not supported yet.
 	 */
-	local_timer_interrupt(irq, dev_id, regs);
+	local_timer_interrupt(irq, dev_id);
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index 7da9c5f..4dff1f9 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -102,8 +102,7 @@
 	.set_type	= eim_set_irq_type,
 };
 
-static void demux_eim_irq(unsigned int irq, struct irq_desc *desc,
-			  struct pt_regs *regs)
+static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
 {
 	struct at32_sm *sm = desc->handler_data;
 	struct irq_desc *ext_desc;
@@ -121,7 +120,7 @@
 
 		ext_irq = i + sm->eim_first_irq;
 		ext_desc = irq_desc + ext_irq;
-		ext_desc->handle_irq(ext_irq, ext_desc, regs);
+		ext_desc->handle_irq(ext_irq, ext_desc);
 	}
 
 	spin_unlock(&sm->lock);
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index 74f8c9f..eb87a18 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -52,16 +52,19 @@
 asmlinkage void do_IRQ(int level, struct pt_regs *regs)
 {
 	struct irq_desc *desc;
+	struct pt_regs *old_regs;
 	unsigned int irq;
 	unsigned long status_reg;
 
 	local_irq_disable();
 
+	old_regs = set_irq_regs(regs);
+
 	irq_enter();
 
 	irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
 	desc = irq_desc + irq;
-	desc->handle_irq(irq, desc, regs);
+	desc->handle_irq(irq, desc);
 
 	/*
 	 * Clear all interrupt level masks so that we may handle
@@ -75,6 +78,8 @@
 	sysreg_write(SR, status_reg);
 
 	irq_exit();
+
+	set_irq_regs(old_regs);
 }
 
 void __init init_IRQ(void)
diff --git a/arch/frv/kernel/dma.c b/arch/frv/kernel/dma.c
index f5de6cf..156184e 100644
--- a/arch/frv/kernel/dma.c
+++ b/arch/frv/kernel/dma.c
@@ -121,15 +121,14 @@
 /*
  * DMA irq handler - determine channel involved, grab status and call real handler
  */
-static irqreturn_t dma_irq_handler(int irq, void *_channel, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *_channel)
 {
 	struct frv_dma_channel *channel = _channel;
 
 	frv_clear_dma_inprogress(channel - frv_dma_channels);
 	return channel->handler(channel - frv_dma_channels,
 				__get_DMAC(channel->ioaddr, CSTR),
-				channel->data,
-				regs);
+				channel->data);
 
 } /* end dma_irq_handler() */
 
diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c
index 369bc0a..ad753c1 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -80,7 +80,7 @@
 /*
  * FPGA PIC interrupt handler
  */
-static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
+static irqreturn_t fpga_interrupt(int irq, void *_mask)
 {
 	uint16_t imr, mask = (unsigned long) _mask;
 
@@ -95,7 +95,7 @@
 		irq = 31 - irq;
 		mask &= ~(1 << irq);
 
-		generic_handle_irq(IRQ_BASE_FPGA + irq, regs);
+		generic_handle_irq(IRQ_BASE_FPGA + irq);
 	}
 
 	return IRQ_HANDLED;
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index a43a221..e0983f6 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -79,7 +79,7 @@
 /*
  * FPGA PIC interrupt handler
  */
-static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
+static irqreturn_t fpga_interrupt(int irq, void *_mask)
 {
 	uint16_t imr, mask = (unsigned long) _mask;
 
@@ -94,7 +94,7 @@
 		irq = 31 - irq;
 		mask &= ~(1 << irq);
 
-		generic_irq_handle(IRQ_BASE_FPGA + irq, regs);
+		generic_irq_handle(IRQ_BASE_FPGA + irq);
 	}
 
 	return IRQ_HANDLED;
diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c
index 39c0188..c157eef 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -90,7 +90,7 @@
 /*
  * MB93493 PIC interrupt handler
  */
-static irqreturn_t mb93493_interrupt(int irq, void *_piqsr, struct pt_regs *regs)
+static irqreturn_t mb93493_interrupt(int irq, void *_piqsr)
 {
 	volatile void *piqsr = _piqsr;
 	uint32_t iqsr;
@@ -106,7 +106,7 @@
 		irq = 31 - irq;
 		iqsr &= ~(1 << irq);
 
-		generic_handle_irq(IRQ_BASE_MB93493 + irq, regs);
+		generic_handle_irq(IRQ_BASE_MB93493 + irq);
 	}
 
 	return IRQ_HANDLED;
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 5ac041c..87f360a 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -143,7 +143,7 @@
 asmlinkage void do_IRQ(void)
 {
 	irq_enter();
-	generic_handle_irq(__get_IRL(), __frame);
+	generic_handle_irq(__get_IRL());
 	irq_exit();
 }
 
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 44a9aeb..ed588d7 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -40,7 +40,7 @@
 unsigned long __nongprelbss __serial_clock_speed_HZ;
 unsigned long __delay_loops_MHz;
 
-static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs *regs);
+static irqreturn_t timer_interrupt(int irq, void *dummy);
 
 static struct irqaction timer_irq  = {
 	timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
@@ -55,7 +55,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	/* last time the cmos clock got updated */
 	static long last_rtc_update = 0;
@@ -70,8 +70,8 @@
 	write_seqlock(&xtime_lock);
 
 	do_timer(1);
-	update_process_times(user_mode(regs));
-	profile_tick(CPU_PROFILING, regs);
+	update_process_times(user_mode(get_irq_regs()));
+	profile_tick(CPU_PROFILING);
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 21c9a4e..fc4f2ab 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -7,6 +7,7 @@
 
 config M386
 	bool "386"
+	depends on !UML
 	---help---
 	  This is the processor type of your CPU. This information is used for
 	  optimizing purposes. In order to compile a kernel that can run on
@@ -301,7 +302,7 @@
 
 config X86_USE_3DNOW
 	bool
-	depends on MCYRIXIII || MK7 || MGEODE_LX
+	depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML
 	default y
 
 config X86_OOSTORE
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 7cc0b18..0677908 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -42,6 +42,10 @@
 # temporary until string.h is fixed
 cflags-y += -ffreestanding
 
+# this works around some issues with generating unwind tables in older gccs
+# newer gccs do it by default
+cflags-y += -maccumulate-outgoing-args
+
 # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
 # a lot more stack due to the lack of sharing of stacklots:
 CFLAGS				+= $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
@@ -51,8 +55,8 @@
 AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
 
 # is .cfi_signal_frame supported too?
-cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
-AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
 
 CFLAGS += $(cflags-y)
 
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index ee2d79b..97aacd6 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.18-git7
-# Wed Sep 27 21:53:10 2006
+# Linux kernel version: 2.6.19-rc2-git4
+# Sat Oct 21 03:38:56 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -31,9 +31,11 @@
 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_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -41,9 +43,10 @@
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,6 +79,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -163,6 +167,7 @@
 # CONFIG_I8K is not set
 # CONFIG_X86_REBOOTFIXUPS is not set
 CONFIG_MICROCODE=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
 CONFIG_X86_MSR=y
 CONFIG_X86_CPUID=y
 
@@ -177,6 +182,7 @@
 # CONFIG_HIGHMEM64G is not set
 CONFIG_PAGE_OFFSET=0xC0000000
 CONFIG_HIGHMEM=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -295,6 +301,7 @@
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_HT_IRQ is not set
 CONFIG_ISA_DMA_API=y
 # CONFIG_ISA is not set
 # CONFIG_MCA is not set
@@ -354,6 +361,7 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -370,9 +378,10 @@
 # CONFIG_INET6_TUNNEL is not set
 CONFIG_INET6_XFRM_MODE_TRANSPORT=y
 CONFIG_INET6_XFRM_MODE_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_BEET is not set
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
 # CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -474,6 +483,13 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -519,6 +535,7 @@
 # CONFIG_BLK_DEV_CS5535 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=y
 # CONFIG_BLK_DEV_IT821X is not set
@@ -615,6 +632,7 @@
 # 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
@@ -658,7 +676,6 @@
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_LEGACY is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
@@ -667,7 +684,6 @@
 # CONFIG_PATA_OPTI is not set
 # CONFIG_PATA_OPTIDMA is not set
 # CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_QDI is not set
 # CONFIG_PATA_RADISYS is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
@@ -684,6 +700,7 @@
 CONFIG_MD=y
 # CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
 # CONFIG_DM_CRYPT is not set
 # CONFIG_DM_SNAPSHOT is not set
 # CONFIG_DM_MIRROR is not set
@@ -874,6 +891,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -896,6 +914,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
@@ -1012,6 +1031,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -1020,15 +1040,9 @@
 # CONFIG_HWMON_VID is not set
 
 #
-# Misc devices
-#
-# CONFIG_IBM_ASM is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1134,6 +1148,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
 
 #
@@ -1187,6 +1202,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
@@ -1194,12 +1210,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
 
 #
@@ -1269,6 +1286,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
@@ -1281,6 +1299,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
@@ -1291,6 +1310,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1315,8 +1335,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1452,11 +1474,14 @@
 # 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_UNWIND_INFO=y
 CONFIG_STACK_UNWIND=y
 # 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
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 92f79cd..ab974ff 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -332,7 +332,7 @@
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -352,13 +352,13 @@
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
 	 * and for later update of acpi_fadt
 	 */
-	acpi_sci_override_gsi = gsi;
+	acpi_sci_override_gsi = bus_irq;
 	return;
 }
 
@@ -376,7 +376,7 @@
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->bus_irq == acpi_fadt.sci_int) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->bus_irq, intsrc->global_irq,
 				      intsrc->flags.polarity,
 				      intsrc->flags.trigger);
 		return 0;
@@ -879,7 +879,7 @@
 	 * pretend we got one so we can set the SCI flags.
 	 */
 	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
+		acpi_sci_ioapic_setup(acpi_fadt.sci_int, acpi_fadt.sci_int, 0, 0);
 
 	/* Fill in identity legacy mapings where no override */
 	mp_config_acpi_legacy_irqs();
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 25db49e..20563e5 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/cpu.h>
 
 #include <acpi/processor.h>
 #include <asm/acpi.h>
@@ -41,5 +42,124 @@
 		flags->bm_check = 1;
 	}
 }
-
 EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
+
+/* The code below handles cstate entry with monitor-mwait pair on Intel*/
+
+struct cstate_entry_s {
+	struct {
+		unsigned int eax;
+		unsigned int ecx;
+	} states[ACPI_PROCESSOR_MAX_POWER];
+};
+static struct cstate_entry_s *cpu_cstate_entry;	/* per CPU ptr */
+
+static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
+
+#define MWAIT_SUBSTATE_MASK	(0xf)
+#define MWAIT_SUBSTATE_SIZE	(4)
+
+#define CPUID_MWAIT_LEAF (5)
+#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
+#define CPUID5_ECX_INTERRUPT_BREAK	(0x2)
+
+#define MWAIT_ECX_INTERRUPT_BREAK	(0x1)
+
+#define NATIVE_CSTATE_BEYOND_HALT	(2)
+
+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 cpuinfo_x86 *c = cpu_data + cpu;
+
+	cpumask_t saved_mask;
+	int retval;
+	unsigned int eax, ebx, ecx, edx;
+	unsigned int edx_part;
+	unsigned int cstate_type; /* C-state type and not ACPI C-state type */
+	unsigned int num_cstate_subtype;
+
+	if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF )
+		return -1;
+
+	if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
+		return -1;
+
+	percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
+	percpu_entry->states[cx->index].eax = 0;
+	percpu_entry->states[cx->index].ecx = 0;
+
+	/* Make sure we are running on right CPU */
+	saved_mask = current->cpus_allowed;
+	retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	if (retval)
+		return -1;
+
+	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
+
+	/* Check whether this particular cx_type (in CST) is supported or not */
+	cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1;
+	edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
+	num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
+
+	retval = 0;
+	if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
+		retval = -1;
+		goto out;
+	}
+
+	/* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
+	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
+	    !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
+		retval = -1;
+		goto out;
+	}
+	percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
+
+	/* Use the hint in CST */
+	percpu_entry->states[cx->index].eax = cx->address;
+
+	if (!mwait_supported[cstate_type]) {
+		mwait_supported[cstate_type] = 1;
+		printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
+		       "state\n", cx->type);
+	}
+
+out:
+	set_cpus_allowed(current, saved_mask);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
+
+void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
+{
+	unsigned int cpu = smp_processor_id();
+	struct cstate_entry_s *percpu_entry;
+
+	percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
+	mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
+	                      percpu_entry->states[cx->index].ecx);
+}
+EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter);
+
+static int __init ffh_cstate_init(void)
+{
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+	if (c->x86_vendor != X86_VENDOR_INTEL)
+		return -1;
+
+	cpu_cstate_entry = alloc_percpu(struct cstate_entry_s);
+	return 0;
+}
+
+static void __exit ffh_cstate_exit(void)
+{
+	if (cpu_cstate_entry) {
+		free_percpu(cpu_cstate_entry);
+		cpu_cstate_entry = NULL;
+	}
+}
+
+arch_initcall(ffh_cstate_init);
+__exitcall(ffh_cstate_exit);
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c
index 28ab806..583c238 100644
--- a/arch/i386/kernel/alternative.c
+++ b/arch/i386/kernel/alternative.c
@@ -344,6 +344,7 @@
 
 void __init alternative_instructions(void)
 {
+	unsigned long flags;
 	if (no_replacement) {
 		printk(KERN_INFO "(SMP-)alternatives turned off\n");
 		free_init_pages("SMP alternatives",
@@ -351,6 +352,8 @@
 				(unsigned long)__smp_alt_end);
 		return;
 	}
+
+	local_irq_save(flags);
 	apply_alternatives(__alt_instructions, __alt_instructions_end);
 
 	/* switch to patch-once-at-boottime-only mode and free the
@@ -386,4 +389,5 @@
 		alternatives_smp_switch(0);
 	}
 #endif
+	local_irq_restore(flags);
 }
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 90faae5..2fd4b7d 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -1193,11 +1193,11 @@
  * value into /proc/profile.
  */
 
-inline void smp_local_timer_interrupt(struct pt_regs * regs)
+inline void smp_local_timer_interrupt(void)
 {
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #ifdef CONFIG_SMP
-	update_process_times(user_mode_vm(regs));
+	update_process_times(user_mode_vm(get_irq_regs()));
 #endif
 
 	/*
@@ -1223,6 +1223,7 @@
 
 fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	int cpu = smp_processor_id();
 
 	/*
@@ -1241,12 +1242,13 @@
 	 * interrupt lock, which is the WrongThing (tm) to do.
 	 */
 	irq_enter();
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 #ifndef CONFIG_SMP
-static void up_apic_timer_interrupt_call(struct pt_regs *regs)
+static void up_apic_timer_interrupt_call(void)
 {
 	int cpu = smp_processor_id();
 
@@ -1255,11 +1257,11 @@
 	 */
 	per_cpu(irq_stat, cpu).apic_timer_irqs++;
 
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 }
 #endif
 
-void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
+void smp_send_timer_broadcast_ipi(void)
 {
 	cpumask_t mask;
 
@@ -1272,7 +1274,7 @@
 		 * We can directly call the apic timer interrupt handler
 		 * in UP case. Minus all irq related functions
 		 */
-		up_apic_timer_interrupt_call(regs);
+		up_apic_timer_interrupt_call();
 #endif
 	}
 }
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index b42f2d9..2af6585 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -540,12 +540,31 @@
  * Also, we KNOW that for the non error case of apm_bios_call, there
  * is no useful data returned in the low order 8 bits of eax.
  */
-#define APM_DO_CLI	\
-	if (apm_info.allow_ints) \
-		local_irq_enable(); \
-	else \
+
+static inline unsigned long __apm_irq_save(void)
+{
+	unsigned long flags;
+	local_save_flags(flags);
+	if (apm_info.allow_ints) {
+		if (irqs_disabled_flags(flags))
+			local_irq_enable();
+	} else
 		local_irq_disable();
 
+	return flags;
+}
+
+#define apm_irq_save(flags) \
+	do { flags = __apm_irq_save(); } while (0)
+
+static inline void apm_irq_restore(unsigned long flags)
+{
+	if (irqs_disabled_flags(flags))
+		local_irq_disable();
+	else if (irqs_disabled())
+		local_irq_enable();
+}
+
 #ifdef APM_ZERO_SEGS
 #	define APM_DECL_SEGS \
 		unsigned int saved_fs; unsigned int saved_gs;
@@ -596,12 +615,11 @@
 	save_desc_40 = gdt[0x40 / 8];
 	gdt[0x40 / 8] = bad_bios_desc;
 
-	local_save_flags(flags);
-	APM_DO_CLI;
+	apm_irq_save(flags);
 	APM_DO_SAVE_SEGS;
 	apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
 	APM_DO_RESTORE_SEGS;
-	local_irq_restore(flags);
+	apm_irq_restore(flags);
 	gdt[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
@@ -640,12 +658,11 @@
 	save_desc_40 = gdt[0x40 / 8];
 	gdt[0x40 / 8] = bad_bios_desc;
 
-	local_save_flags(flags);
-	APM_DO_CLI;
+	apm_irq_save(flags);
 	APM_DO_SAVE_SEGS;
 	error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
 	APM_DO_RESTORE_SEGS;
-	local_irq_restore(flags);
+	apm_irq_restore(flags);
 	gdt[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c
index 4f43047..2d8703b 100644
--- a/arch/i386/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c
@@ -110,17 +110,15 @@
 
 #ifdef CONFIG_SYSFS
 /* Add/Remove thermal_throttle interface for CPU device */
-static __cpuinit int thermal_throttle_add_dev(struct sys_device * sys_dev)
+static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
 {
-	sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group);
-	return 0;
+	return sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static __cpuinit int thermal_throttle_remove_dev(struct sys_device * sys_dev)
+static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
 {
-	sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
-	return 0;
+	return sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
 }
 
 /* Mutex protecting device creation against CPU hotplug */
@@ -133,12 +131,14 @@
 {
 	unsigned int cpu = (unsigned long)hcpu;
 	struct sys_device *sys_dev;
+	int err;
 
 	sys_dev = get_cpu_sysdev(cpu);
 	mutex_lock(&therm_cpu_lock);
 	switch (action) {
 	case CPU_ONLINE:
-		thermal_throttle_add_dev(sys_dev);
+		err = thermal_throttle_add_dev(sys_dev);
+		WARN_ON(err);
 		break;
 	case CPU_DEAD:
 		thermal_throttle_remove_dev(sys_dev);
@@ -157,6 +157,7 @@
 static __init int thermal_throttle_init_device(void)
 {
 	unsigned int cpu = 0;
+	int err;
 
 	if (!atomic_read(&therm_throt_en))
 		return 0;
@@ -167,8 +168,10 @@
 	mutex_lock(&therm_cpu_lock);
 #endif
 	/* connect live CPUs to sysfs */
-	for_each_online_cpu(cpu)
-		thermal_throttle_add_dev(get_cpu_sysdev(cpu));
+	for_each_online_cpu(cpu) {
+		err = thermal_throttle_add_dev(get_cpu_sysdev(cpu));
+		WARN_ON(err);
+	}
 #ifdef CONFIG_HOTPLUG_CPU
 	mutex_unlock(&therm_cpu_lock);
 #endif
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index be9d883..ca31f18 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -317,7 +317,7 @@
 	movl %eax,%gs
 	lldt %ax
 	cld			# gcc2 wants the direction flag cleared at all times
-	pushl %eax		# fake return address
+	pushl $0		# fake return address for unwinder
 #ifdef CONFIG_SMP
 	movb ready, %cl
 	movb $1, ready
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
index 477b24d..9a0060b 100644
--- a/arch/i386/kernel/i8253.c
+++ b/arch/i386/kernel/i8253.c
@@ -109,7 +109,7 @@
 
 static int __init init_pit_clocksource(void)
 {
-	if (num_possible_cpus() > 4) /* PIT does not scale! */
+	if (num_possible_cpus() > 1) /* PIT does not scale! */
 		return 0;
 
 	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index d07ed31..62996cd 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -113,7 +113,8 @@
 {
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
-	set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
+	set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
+				      "XT");
 	enable_irq(irq);
 }
 
@@ -335,13 +336,13 @@
  */
  
 
-static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t math_error_irq(int cpl, void *dev_id)
 {
 	extern void math_error(void __user *);
 	outb(0,0xF0);
 	if (ignore_fpu_irq || !boot_cpu_data.hard_math)
 		return IRQ_NONE;
-	math_error((void __user *)regs->eip);
+	math_error((void __user *)get_irq_regs()->eip);
 	return IRQ_HANDLED;
 }
 
@@ -369,8 +370,8 @@
 			/*
 			 * 16 old-style INTA-cycle interrupts:
 			 */
-			set_irq_chip_and_handler(i, &i8259A_chip,
-						 handle_level_irq);
+			set_irq_chip_and_handler_name(i, &i8259A_chip,
+						      handle_level_irq, "XT");
 		} else {
 			/*
 			 * 'high' PCI IRQs filled in on demand
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index b7287fb..350192d 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1184,8 +1184,8 @@
 
 	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
 
-	if (IO_APIC_VECTOR(irq) > 0)
-		return IO_APIC_VECTOR(irq);
+	if (irq_vector[irq] > 0)
+		return irq_vector[irq];
 
 	current_vector += 8;
 	if (current_vector == SYSCALL_VECTOR)
@@ -1199,7 +1199,7 @@
 	}
 
 	vector = current_vector;
-	IO_APIC_VECTOR(irq) = vector;
+	irq_vector[irq] = vector;
 
 	return vector;
 }
@@ -1225,11 +1225,11 @@
 {
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 			trigger == IOAPIC_LEVEL)
-		set_irq_chip_and_handler(irq, &ioapic_chip,
-					 handle_fasteoi_irq);
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					 handle_fasteoi_irq, "fasteoi");
 	else
-		set_irq_chip_and_handler(irq, &ioapic_chip,
-					 handle_edge_irq);
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					 handle_edge_irq, "edge");
 	set_intr_gate(vector, interrupt[irq]);
 }
 
@@ -1967,7 +1967,7 @@
  * operation to prevent an edge-triggered interrupt escaping meanwhile.
  * The idea is from Manfred Spraul.  --macro
  */
-	i = IO_APIC_VECTOR(irq);
+	i = irq_vector[irq];
 
 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
 
@@ -1984,7 +1984,7 @@
 
 static int ioapic_retrigger_irq(unsigned int irq)
 {
-	send_IPI_self(IO_APIC_VECTOR(irq));
+	send_IPI_self(irq_vector[irq]);
 
 	return 1;
 }
@@ -2020,7 +2020,7 @@
 	 */
 	for (irq = 0; irq < NR_IRQS ; irq++) {
 		int tmp = irq;
-		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
+		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
 			/*
 			 * Hmm.. We don't have an entry for this,
 			 * so default to an old-fashioned 8259
@@ -2235,7 +2235,8 @@
 	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
 
 	disable_8259A_irq(0);
-	set_irq_chip_and_handler(0, &lapic_chip, handle_fasteoi_irq);
+	set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
+				      "fasteio");
 	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
 	enable_8259A_irq(0);
 
@@ -2541,7 +2542,8 @@
 
 	write_msi_msg(irq, &msg);
 
-	set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
+	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
+				      "edge");
 
 	return 0;
 }
@@ -2594,7 +2596,7 @@
 }
 #endif
 
-static struct hw_interrupt_type ht_irq_chip = {
+static struct irq_chip ht_irq_chip = {
 	.name		= "PCI-HT",
 	.mask		= mask_ht_irq,
 	.unmask		= unmask_ht_irq,
@@ -2636,7 +2638,8 @@
 		write_ht_irq_low(irq, low);
 		write_ht_irq_high(irq, high);
 
-		set_irq_chip_and_handler(irq, &ht_irq_chip, handle_edge_irq);
+		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+					      handle_edge_irq, "edge");
 	}
 	return vector;
 }
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 3dd2e18..3201d42 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -53,6 +53,7 @@
  */
 fastcall unsigned int do_IRQ(struct pt_regs *regs)
 {	
+	struct pt_regs *old_regs;
 	/* high bit used in ret_from_ code */
 	int irq = ~regs->orig_eax;
 	struct irq_desc *desc = irq_desc + irq;
@@ -67,6 +68,7 @@
 		BUG();
 	}
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* Debugging check for stack overflow: is there less than 1KB free? */
@@ -95,7 +97,7 @@
 	 * current stack (which is the irq stack already after all)
 	 */
 	if (curctx != irqctx) {
-		int arg1, arg2, arg3, ebx;
+		int arg1, arg2, ebx;
 
 		/* build the stack frame on the IRQ stack */
 		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
@@ -114,17 +116,17 @@
 			"       xchgl  %%ebx,%%esp      \n"
 			"       call   *%%edi           \n"
 			"       movl   %%ebx,%%esp      \n"
-			: "=a" (arg1), "=d" (arg2), "=c" (arg3), "=b" (ebx)
-			:  "0" (irq),   "1" (desc),  "2" (regs),  "3" (isp),
+			: "=a" (arg1), "=d" (arg2), "=b" (ebx)
+			:  "0" (irq),   "1" (desc),  "2" (isp),
 			   "D" (desc->handle_irq)
 			: "memory", "cc"
 		);
 	} else
 #endif
-		desc->handle_irq(irq, desc, regs);
+		desc->handle_irq(irq, desc);
 
 	irq_exit();
-
+	set_irq_regs(old_regs);
 	return 1;
 }
 
@@ -256,7 +258,7 @@
 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %8s", irq_desc[i].chip->name);
-		seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq));
+		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 9b94797..c4d0291 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -656,14 +656,18 @@
 
 static int mc_sysdev_add(struct sys_device *sys_dev)
 {
-	int cpu = sys_dev->id;
+	int err, cpu = sys_dev->id;
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
 	if (!cpu_online(cpu))
 		return 0;
+
 	pr_debug("Microcode:CPU %d added\n", cpu);
 	memset(uci, 0, sizeof(*uci));
-	sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+
+	err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+	if (err)
+		return err;
 
 	microcode_init_cpu(cpu);
 	return 0;
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 3e8e3ad..eaafe23 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -219,11 +219,11 @@
 	int cpu;
 
 	/* Enable NMI watchdog for newer systems.
-           Actually it should be safe for most systems before 2004 too except
-	   for some IBM systems that corrupt registers when NMI happens
-	   during SMM. Unfortunately we don't have more exact information
- 	   on these and use this coarse check. */
-	if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004)
+	   Probably safe on most older systems too, but let's be careful.
+	   IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM
+	   which hangs the system. Disable watchdog for all thinkpads */
+	if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 &&
+		!dmi_name_in_vendors("ThinkPad"))
 		nmi_watchdog = NMI_LOCAL_APIC;
 
 	if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index dad02a9..1e1fa3e 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -236,18 +236,26 @@
  * We execute MONITOR against need_resched and enter optimized wait state
  * through MWAIT. Whenever someone changes need_resched, we would be woken
  * up from MWAIT (without an IPI).
+ *
+ * New with Core Duo processors, MWAIT can take some hints based on CPU
+ * capability.
  */
+void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
+{
+	if (!need_resched()) {
+		__monitor((void *)&current_thread_info()->flags, 0, 0);
+		smp_mb();
+		if (!need_resched())
+			__mwait(eax, ecx);
+	}
+}
+
+/* Default MONITOR/MWAIT with no hints, used for default C1 state */
 static void mwait_idle(void)
 {
 	local_irq_enable();
-
-	while (!need_resched()) {
-		__monitor((void *)&current_thread_info()->flags, 0, 0);
-		smp_mb();
-		if (need_resched())
-			break;
-		__mwait(0, 0);
-	}
+	while (!need_resched())
+		mwait_idle_with_hints(0, 0);
 }
 
 void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 000cf03..519e63c 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -1083,16 +1083,15 @@
 
 void __init zone_sizes_init(void)
 {
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] =
+		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 #ifdef CONFIG_HIGHMEM
-	unsigned long max_zone_pfns[MAX_NR_ZONES] = {
-			virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
-			max_low_pfn,
-			highend_pfn};
+	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
 	add_active_range(0, 0, highend_pfn);
 #else
-	unsigned long max_zone_pfns[MAX_NR_ZONES] = {
-			virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
-			max_low_pfn};
 	add_active_range(0, 0, max_low_pfn);
 #endif
 
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 1b080ab..31e5c65 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -321,6 +321,7 @@
 
 fastcall void smp_invalidate_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	unsigned long cpu;
 
 	cpu = get_cpu();
@@ -351,6 +352,7 @@
 	smp_mb__after_clear_bit();
 out:
 	put_cpu_no_resched();
+	set_irq_regs(old_regs);
 }
 
 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
@@ -605,11 +607,14 @@
  */
 fastcall void smp_reschedule_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	ack_APIC_irq();
+	set_irq_regs(old_regs);
 }
 
 fastcall void smp_call_function_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	void (*func) (void *info) = call_data->func;
 	void *info = call_data->info;
 	int wait = call_data->wait;
@@ -632,6 +637,7 @@
 		mb();
 		atomic_inc(&call_data->finished);
 	}
+	set_irq_regs(old_regs);
 }
 
 /*
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 7e639f7..2697e92 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -318,3 +318,4 @@
 	.long sys_vmsplice
 	.long sys_move_pages
 	.long sys_getcpu
+	.long sys_epoll_pwait
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 58a2d55..78af572 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -161,7 +161,7 @@
  * Time Stamp Counter value at the time of the timer interrupt, so that
  * we later on can estimate the time of day more exactly.
  */
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	/*
 	 * Here we are in the timer irq handler. We just have irqs locally
@@ -188,7 +188,7 @@
 	}
 #endif
 
-	do_timer_interrupt_hook(regs);
+	do_timer_interrupt_hook();
 
 
 	if (MCA_bus) {
@@ -201,15 +201,15 @@
 		high bit of the PPI port B (0x61).  Note that some PS/2s,
 		notably the 55SX, work fine if this is removed.  */
 
-		irq = inb_p( 0x61 );	/* read the current state */
-		outb_p( irq|0x80, 0x61 );	/* reset the IRQ */
+		u8 irq_v = inb_p( 0x61 );	/* read the current state */
+		outb_p( irq_v|0x80, 0x61 );	/* reset the IRQ */
 	}
 
 	write_sequnlock(&xtime_lock);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 	if (using_apic_timer)
-		smp_send_timer_broadcast_ipi(regs);
+		smp_send_timer_broadcast_ipi();
 #endif
 
 	return IRQ_HANDLED;
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 6bf14a4..1a2a979 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -441,7 +441,7 @@
 	return 1;
 }
 
-irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
 {
 	struct rtc_time curr_time;
 	unsigned long rtc_int_flag = 0;
@@ -480,7 +480,7 @@
 	}
 	if (call_rtc_interrupt) {
 		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-		rtc_interrupt(rtc_int_flag, dev_id, regs);
+		rtc_interrupt(rtc_int_flag, dev_id);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index b8fa0a8..fbc9582 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -349,8 +349,8 @@
 	int change = 0;
 
 	/* check to see if we should switch to the safe clocksource: */
-	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
-		clocksource_tsc.rating = 50;
+	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
+		clocksource_tsc.rating = 0;
 		clocksource_reselect();
 		change = 1;
 	}
@@ -461,7 +461,7 @@
 							clocksource_tsc.shift);
 		/* lower the rating if we already know its unstable: */
 		if (check_tsc_unstable())
-			clocksource_tsc.rating = 50;
+			clocksource_tsc.rating = 0;
 
 		init_timer(&verify_tsc_freq_timer);
 		verify_tsc_freq_timer.function = verify_tsc_freq;
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 8355d8d..cbcd61d 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -714,7 +714,7 @@
 	| (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO)  | (1 << SIGURG) \
 	| (1 << SIGUNUSED) )
 	
-static irqreturn_t irq_handler(int intno, void *dev_id, struct pt_regs * regs)
+static irqreturn_t irq_handler(int intno, void *dev_id)
 {
 	int irq_bit;
 	unsigned long flags;
diff --git a/arch/i386/lib/semaphore.S b/arch/i386/lib/semaphore.S
index ef6ad9e..c01eb39 100644
--- a/arch/i386/lib/semaphore.S
+++ b/arch/i386/lib/semaphore.S
@@ -152,6 +152,8 @@
 
 #endif
 
+#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
+
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
 	CFI_STARTPROC
@@ -214,3 +216,4 @@
 	CFI_ENDPROC
 	END(call_rwsem_downgrade_wake)
 
+#endif
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 08502fc..d22cfc9 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -9,6 +9,7 @@
 #include <linux/highmem.h>
 #include <linux/blkdev.h>
 #include <linux/module.h>
+#include <linux/backing-dev.h>
 #include <asm/uaccess.h>
 #include <asm/mmx.h>
 
@@ -179,7 +180,7 @@
 EXPORT_SYMBOL(__clear_user);
 
 /**
- * strlen_user: - Get the size of a string in user space.
+ * strnlen_user: - Get the size of a string in user space.
  * @s: The string to measure.
  * @n: The maximum valid length
  *
@@ -741,7 +742,7 @@
 
 			if (retval == -ENOMEM && is_init(current)) {
 				up_read(&current->mm->mmap_sem);
-				blk_congestion_wait(WRITE, HZ/50);
+				congestion_wait(WRITE, HZ/50);
 				goto survive;
 			}
 
diff --git a/arch/i386/mach-visws/visws_apic.c b/arch/i386/mach-visws/visws_apic.c
index 5929f884..07097ed 100644
--- a/arch/i386/mach-visws/visws_apic.c
+++ b/arch/i386/mach-visws/visws_apic.c
@@ -191,7 +191,7 @@
  * enable_irq gets the right irq. This 'master' irq is never directly
  * manipulated by any driver.
  */
-static irqreturn_t piix4_master_intr(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t piix4_master_intr(int irq, void *dev_id)
 {
 	int realirq;
 	irq_desc_t *desc;
@@ -244,7 +244,7 @@
 	kstat_cpu(smp_processor_id()).irqs[realirq]++;
 
 	if (likely(desc->action != NULL))
-		handle_IRQ_event(realirq, regs, desc->action);
+		handle_IRQ_event(realirq, desc->action);
 
 	if (!(desc->status & IRQ_DISABLED))
 		enable_8259A_irq(realirq);
diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
index 80b7f2f..8fe7e45 100644
--- a/arch/i386/mach-voyager/voyager_basic.c
+++ b/arch/i386/mach-voyager/voyager_basic.c
@@ -44,7 +44,7 @@
 
 #ifdef CONFIG_SMP
 static void
-voyager_dump(int dummy1, struct pt_regs *dummy2, struct tty_struct *dummy3)
+voyager_dump(int dummy1, struct tty_struct *dummy3)
 {
 	/* get here via a sysrq */
 	voyager_smp_dump();
@@ -87,7 +87,7 @@
 }
 
 void
-voyager_system_interrupt(int cpl, void *dev_id, struct pt_regs *regs)
+voyager_system_interrupt(int cpl, void *dev_id)
 {
 	printk("Voyager: detected system interrupt\n");
 }
@@ -166,7 +166,7 @@
  * off the timer tick to the SMP code, since the VIC doesn't have an
  * internal timer (The QIC does, but that's another story). */
 void
-voyager_timer_interrupt(struct pt_regs *regs)
+voyager_timer_interrupt(void)
 {
 	if((jiffies & 0x3ff) == 0) {
 
@@ -202,7 +202,7 @@
 		}
 	}
 #ifdef CONFIG_SMP
-	smp_vic_timer_interrupt(regs);
+	smp_vic_timer_interrupt();
 #endif
 }
 
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 856c73f..f3fea2a 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -85,8 +85,8 @@
 static void ack_special_QIC_CPI(__u8 cpi);
 static void ack_VIC_CPI(__u8 cpi);
 static void send_CPI_allbutself(__u8 cpi);
-static void enable_vic_irq(unsigned int irq);
-static void disable_vic_irq(unsigned int irq);
+static void mask_vic_irq(unsigned int irq);
+static void unmask_vic_irq(unsigned int irq);
 static unsigned int startup_vic_irq(unsigned int irq);
 static void enable_local_vic_irq(unsigned int irq);
 static void disable_local_vic_irq(unsigned int irq);
@@ -126,10 +126,10 @@
 }
 
 static inline void
-wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
+wrapper_smp_local_timer_interrupt(void)
 {
 	irq_enter();
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 	irq_exit();
 }
 
@@ -205,15 +205,12 @@
 /* The VIC IRQ descriptors -- these look almost identical to the
  * 8259 IRQs except that masks and things must be kept per processor
  */
-static struct hw_interrupt_type vic_irq_type = {
-	.typename = "VIC-level",
-	.startup = startup_vic_irq,
-	.shutdown = disable_vic_irq,
-	.enable = enable_vic_irq,
-	.disable = disable_vic_irq,
-	.ack = before_handle_vic_irq,
-	.end = after_handle_vic_irq,
-	.set_affinity = set_vic_irq_affinity,
+static struct irq_chip vic_chip = {
+	.name		= "VIC",
+	.startup	= startup_vic_irq,
+	.mask		= mask_vic_irq,
+	.unmask		= unmask_vic_irq,
+	.set_affinity	= set_vic_irq_affinity,
 };
 
 /* used to count up as CPUs are brought on line (starts at 0) */
@@ -786,7 +783,7 @@
 smp_vic_sys_interrupt(struct pt_regs *regs)
 {
 	ack_CPI(VIC_SYS_INT);
-	printk("Voyager SYSTEM INTERRUPT\n");
+	printk("Voyager SYSTEM INTERRUPT\n");	
 }
 
 /* Handle a voyager CMN_INT; These interrupts occur either because of
@@ -1135,15 +1132,19 @@
 fastcall void 
 smp_apic_timer_interrupt(struct pt_regs *regs)
 {
-	wrapper_smp_local_timer_interrupt(regs);
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	wrapper_smp_local_timer_interrupt();
+	set_irq_regs(old_regs);
 }
 
 /* All of the QUAD interrupt GATES */
 fastcall void
 smp_qic_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	ack_QIC_CPI(QIC_TIMER_CPI);
-	wrapper_smp_local_timer_interrupt(regs);
+	wrapper_smp_local_timer_interrupt();
+	set_irq_regs(old_regs);
 }
 
 fastcall void
@@ -1177,6 +1178,7 @@
 fastcall void
 smp_vic_cpi_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	__u8 cpu = smp_processor_id();
 
 	if(is_cpu_quad())
@@ -1185,7 +1187,7 @@
 		ack_VIC_CPI(VIC_CPI_LEVEL0);
 
 	if(test_and_clear_bit(VIC_TIMER_CPI, &vic_cpi_mailbox[cpu]))
-		wrapper_smp_local_timer_interrupt(regs);
+		wrapper_smp_local_timer_interrupt();
 	if(test_and_clear_bit(VIC_INVALIDATE_CPI, &vic_cpi_mailbox[cpu]))
 		smp_invalidate_interrupt();
 	if(test_and_clear_bit(VIC_RESCHEDULE_CPI, &vic_cpi_mailbox[cpu]))
@@ -1194,6 +1196,7 @@
 		smp_enable_irq_interrupt();
 	if(test_and_clear_bit(VIC_CALL_FUNCTION_CPI, &vic_cpi_mailbox[cpu]))
 		smp_call_function_interrupt();
+	set_irq_regs(old_regs);
 }
 
 static void
@@ -1264,10 +1267,10 @@
 /* this function is triggered in time.c when a clock tick fires
  * we need to re-broadcast the tick to all CPUs */
 void
-smp_vic_timer_interrupt(struct pt_regs *regs)
+smp_vic_timer_interrupt(void)
 {
 	send_CPI_allbutself(VIC_TIMER_CPI);
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 }
 
 /* local (per CPU) timer interrupt.  It does both profiling and
@@ -1279,12 +1282,12 @@
  * value into /proc/profile.
  */
 void
-smp_local_timer_interrupt(struct pt_regs * regs)
+smp_local_timer_interrupt(void)
 {
 	int cpu = smp_processor_id();
 	long weight;
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
@@ -1302,7 +1305,7 @@
 						per_cpu(prof_counter, cpu);
 		}
 
-		update_process_times(user_mode_vm(regs));
+		update_process_times(user_mode_vm(get_irq_regs()));
 	}
 
 	if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
@@ -1389,6 +1392,17 @@
 	return 0;
 }
 
+/* This is a bit of a mess, but forced on us by the genirq changes
+ * there's no genirq handler that really does what voyager wants
+ * so hack it up with the simple IRQ handler */
+static void fastcall
+handle_vic_irq(unsigned int irq, struct irq_desc *desc)
+{
+	before_handle_vic_irq(irq);
+	handle_simple_irq(irq, desc);
+	after_handle_vic_irq(irq);
+}
+
 
 /*  The CPIs are handled in the per cpu 8259s, so they must be
  *  enabled to be received: FIX: enabling the CPIs in the early
@@ -1425,7 +1439,7 @@
 	 * This is for later: first 16 correspond to PC IRQs; next 16
 	 * are Primary MC IRQs and final 16 are Secondary MC IRQs */
 	for(i = 0; i < 48; i++)
-		irq_desc[i].chip = &vic_irq_type;
+		set_irq_chip_and_handler(i, &vic_chip, handle_vic_irq);
 }
 
 /* send a CPI at level cpi to a set of cpus in cpuset (set 1 bit per
@@ -1523,7 +1537,7 @@
 static unsigned int
 startup_vic_irq(unsigned int irq)
 {
-	enable_vic_irq(irq);
+	unmask_vic_irq(irq);
 
 	return 0;
 }
@@ -1550,7 +1564,7 @@
  *    adjust their masks accordingly.  */
 
 static void
-enable_vic_irq(unsigned int irq)
+unmask_vic_irq(unsigned int irq)
 {
 	/* linux doesn't to processor-irq affinity, so enable on
 	 * all CPUs we know about */
@@ -1559,7 +1573,7 @@
 	__u32 processorList = 0;
 	unsigned long flags;
 
-	VDEBUG(("VOYAGER: enable_vic_irq(%d) CPU%d affinity 0x%lx\n",
+	VDEBUG(("VOYAGER: unmask_vic_irq(%d) CPU%d affinity 0x%lx\n",
 		irq, cpu, cpu_irq_affinity[cpu]));
 	spin_lock_irqsave(&vic_irq_lock, flags);
 	for_each_online_cpu(real_cpu) {
@@ -1583,7 +1597,7 @@
 }
 
 static void
-disable_vic_irq(unsigned int irq)
+mask_vic_irq(unsigned int irq)
 {
 	/* lazy disable, do nothing */
 }
@@ -1811,7 +1825,7 @@
 	 * disabled again as it comes in (voyager lazy disable).  If
 	 * the affinity map is tightened to disable the interrupt on a
 	 * cpu, it will be pushed off when it comes in */
-	enable_vic_irq(irq);
+	unmask_vic_irq(irq);
 }
 
 static void
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 455597d..ddbdb03 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -356,11 +356,12 @@
 void __init zone_sizes_init(void)
 {
 	int nid;
-	unsigned long max_zone_pfns[MAX_NR_ZONES] = {
-		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
-		max_low_pfn,
-		highend_pfn
-	};
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] =
+		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
 
 	/* If SRAT has not registered memory, register it now */
 	if (find_max_pfn_with_active_regions() == 0) {
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 68bce19..6d5ace8 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -20,6 +20,7 @@
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
 				PCI_PROBE_MMCONF;
 
+int pci_bf_sort;
 int pci_routeirq;
 int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
@@ -118,6 +119,20 @@
 }
 
 /*
+ * Only use DMI information to set this if nothing was passed
+ * on the kernel command line (which was parsed earlier).
+ */
+
+static int __devinit set_bf_sort(struct dmi_system_id *d)
+{
+	if (pci_bf_sort == pci_bf_sort_default) {
+		pci_bf_sort = pci_dmi_bf;
+		printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
+	}
+	return 0;
+}
+
+/*
  * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
  */
 #ifdef __i386__
@@ -130,11 +145,11 @@
 }
 #endif
 
+static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
+#ifdef __i386__
 /*
  * Laptops which need pci=assign-busses to see Cardbus cards
  */
-static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
-#ifdef __i386__
 	{
 		.callback = assign_all_busses,
 		.ident = "Samsung X20 Laptop",
@@ -144,6 +159,38 @@
 		},
 	},
 #endif		/* __i386__ */
+	{
+		.callback = set_bf_sort,
+		.ident = "Dell PowerEdge 1950",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "Dell PowerEdge 1955",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "Dell PowerEdge 2900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
+		},
+	},
+	{
+		.callback = set_bf_sort,
+		.ident = "Dell PowerEdge 2950",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
+		},
+	},
 	{}
 };
 
@@ -189,6 +236,8 @@
 
 	pcibios_resource_survey();
 
+	if (pci_bf_sort >= pci_force_bf)
+		pci_sort_breadthfirst();
 #ifdef CONFIG_PCI_BIOS
 	if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
 		pcibios_sort();
@@ -203,6 +252,12 @@
 	if (!strcmp(str, "off")) {
 		pci_probe = 0;
 		return NULL;
+	} else if (!strcmp(str, "bfsort")) {
+		pci_bf_sort = pci_force_bf;
+		return NULL;
+	} else if (!strcmp(str, "nobfsort")) {
+		pci_bf_sort = pci_force_nobf;
+		return NULL;
 	}
 #ifdef CONFIG_PCI_BIOS
 	else if (!strcmp(str, "bios")) {
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 5acf0b4..431c9a5 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -256,6 +256,8 @@
 
 void __init pci_direct_init(int type)
 {
+	if (type == 0)
+		return;
 	printk(KERN_INFO "PCI: Using configuration type %d\n", type);
 	if (type == 1)
 		raw_pci_ops = &pci_direct_conf1;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index b60d7e8..908b410 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -343,51 +343,6 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_MCH_PC1,	pcie_rootport_aspm_quirk );
 
 /*
- * Fixup to mark boot BIOS video selected by BIOS before it changes
- *
- * From information provided by "Jon Smirl" <jonsmirl@gmail.com>
- *
- * The standard boot ROM sequence for an x86 machine uses the BIOS
- * to select an initial video card for boot display. This boot video 
- * card will have it's BIOS copied to C0000 in system RAM. 
- * IORESOURCE_ROM_SHADOW is used to associate the boot video
- * card with this copy. On laptops this copy has to be used since
- * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
- * is marked here since the boot video device will be the only enabled
- * video device at this point.
- */
-
-static void __devinit pci_fixup_video(struct pci_dev *pdev)
-{
-	struct pci_dev *bridge;
-	struct pci_bus *bus;
-	u16 config;
-
-	if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-		return;
-
-	/* Is VGA routed to us? */
-	bus = pdev->bus;
-	while (bus) {
-		bridge = bus->self;
-		if (bridge) {
-			pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
-						&config);
-			if (!(config & PCI_BRIDGE_CTL_VGA))
-				return;
-		}
-		bus = bus->parent;
-	}
-	pci_read_config_word(pdev, PCI_COMMAND, &config);
-	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-		printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
-
-/*
  * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
  *
  * We pretend to bring them out of full D3 state, and restore the proper
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c
index d028e1b..b21b6da 100644
--- a/arch/i386/pci/init.c
+++ b/arch/i386/pci/init.c
@@ -28,6 +28,10 @@
 #ifdef CONFIG_PCI_DIRECT
 	pci_direct_init(type);
 #endif
+	if (!raw_pci_ops)
+		printk(KERN_ERR
+		"PCI: Fatal: No config space access function found\n");
+
 	return 0;
 }
 arch_initcall(pci_access_init);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 47f02af..dbc4aae 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -1141,10 +1141,6 @@
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
-#ifdef CONFIG_PCI_MSI
-				if (!platform_legacy_irq(irq))
-					irq = IO_APIC_VECTOR(irq);
-#endif
 				printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
 					pci_name(dev), 'A' + pin, irq);
 				dev->irq = irq;
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index 1814f74..ad065ce 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -30,6 +30,13 @@
 extern unsigned int pci_probe;
 extern unsigned long pirq_table_addr;
 
+enum pci_bf_sort_state {
+	pci_bf_sort_default,
+	pci_force_nobf,
+	pci_force_bf,
+	pci_dmi_bf,
+};
+
 /* pci-i386.c */
 
 extern unsigned int pcibios_max_latency;
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 0f14a82..64e951d 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,8 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc3
-# Thu Apr 27 11:48:23 2006
+# Linux kernel version: 2.6.19-rc1
+# Mon Oct  9 10:53:59 2006
 #
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -18,16 +19,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_SYSCTL=y
+CONFIG_TASKSTATS=y
+# CONFIG_TASK_DELAY_ACCT is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_CPUSETS=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_TASK_XACCT=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -40,6 +47,8 @@
 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
@@ -58,6 +67,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -89,7 +99,7 @@
 CONFIG_GENERIC_IOMAP=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_IA64_UNCACHED_ALLOCATOR=y
-CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_ZX1 is not set
@@ -116,6 +126,7 @@
 CONFIG_SMP=y
 CONFIG_NR_CPUS=1024
 # CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_SCHED_SMT=y
 CONFIG_PREEMPT=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -128,6 +139,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
@@ -135,15 +147,24 @@
 CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
 CONFIG_NUMA=y
 CONFIG_NODES_SHIFT=10
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_IA64_MCA_RECOVERY=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
 CONFIG_SGI_SN=y
+# CONFIG_IA64_ESI is not set
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+CONFIG_SGI_IOC3=y
 
 #
 # Firmware Drivers
@@ -159,6 +180,7 @@
 CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
@@ -166,6 +188,7 @@
 CONFIG_ACPI=y
 # CONFIG_ACPI_BUTTON is not set
 # CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_DOCK is not set
 # CONFIG_ACPI_PROCESSOR is not set
 CONFIG_ACPI_NUMA=y
 CONFIG_ACPI_BLACKLIST_YEAR=0
@@ -185,7 +208,12 @@
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=y
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_PCIEAER=y
 # CONFIG_PCI_MSI is not set
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -215,6 +243,9 @@
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 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
@@ -231,19 +262,31 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # 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=m
 CONFIG_INET_TCP_DIAG=m
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=m
 # 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=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 # CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -269,7 +312,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
 
@@ -298,6 +340,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -335,6 +378,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 CONFIG_ATA_OVER_ETH=m
@@ -381,6 +425,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
@@ -404,6 +449,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -425,12 +471,14 @@
 # CONFIG_SCSI_LOGGING 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=y
+CONFIG_SCSI_SAS_LIBSAS=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
 
 #
 # SCSI low-level drivers
@@ -443,46 +491,82 @@
 # 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_SATA=y
-# CONFIG_SCSI_SATA_AHCI is not set
-# CONFIG_SCSI_SATA_SVW is not set
-# CONFIG_SCSI_ATA_PIIX is not set
-# CONFIG_SCSI_SATA_MV is not set
-# CONFIG_SCSI_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
-# CONFIG_SCSI_SATA_QSTOR is not set
-# CONFIG_SCSI_SATA_PROMISE is not set
-# CONFIG_SCSI_SATA_SX4 is not set
-# CONFIG_SCSI_SATA_SIL is not set
-# CONFIG_SCSI_SATA_SIL24 is not set
-# CONFIG_SCSI_SATA_SIS is not set
-# CONFIG_SCSI_SATA_ULI is not set
-# CONFIG_SCSI_SATA_VIA is not set
-CONFIG_SCSI_SATA_VITESSE=y
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN 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=y
 CONFIG_SCSI_QLA_FC=y
-CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
-# CONFIG_SCSI_QLA21XX is not set
-CONFIG_SCSI_QLA22XX=y
-CONFIG_SCSI_QLA2300=y
-CONFIG_SCSI_QLA2322=y
-# CONFIG_SCSI_QLA24XX 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
 
 #
+# 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=y
+# 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_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)
 #
 CONFIG_MD=y
@@ -491,12 +575,12 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
+CONFIG_MD_RAID456=y
 # CONFIG_MD_RAID5_RESHAPE is not set
-# CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=y
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -563,6 +647,7 @@
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -571,6 +656,7 @@
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -612,6 +698,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -646,6 +733,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_COMPUTONE is not set
 # CONFIG_ROCKETPORT is not set
@@ -659,10 +747,12 @@
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
 # CONFIG_SX is not set
+# CONFIG_RIO is not set
 # CONFIG_STALDRV is not set
 CONFIG_SGI_SNSC=y
 CONFIG_SGI_TIOCX=y
 CONFIG_SGI_MBCS=m
+CONFIG_MSPEC=y
 
 #
 # Serial drivers
@@ -701,6 +791,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=y
+# CONFIG_AGP_SIS is not set
 # CONFIG_AGP_VIA is not set
 CONFIG_AGP_SGI_TIOCA=y
 # CONFIG_DRM is not set
@@ -730,7 +821,6 @@
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -741,6 +831,7 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
@@ -756,6 +847,7 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
 
 #
@@ -764,6 +856,7 @@
 CONFIG_VGA_CONSOLE=y
 # CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -794,6 +887,7 @@
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -843,6 +937,7 @@
 # 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
@@ -874,15 +969,18 @@
 #
 # 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
 # CONFIG_USB_LCD is not set
 # 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
 
@@ -919,18 +1017,15 @@
 CONFIG_INFINIBAND=m
 # CONFIG_INFINIBAND_USER_MAD is not set
 CONFIG_INFINIBAND_USER_ACCESS=m
+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
 CONFIG_INFINIBAND_SRP=m
-
-#
-# SN Devices
-#
-CONFIG_SGI_IOC4=y
-CONFIG_SGI_IOC3=y
+# CONFIG_INFINIBAND_ISER is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -942,6 +1037,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -965,15 +1073,16 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
 CONFIG_XFS_QUOTA=y
 # CONFIG_XFS_SECURITY is not set
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
@@ -1007,8 +1116,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
@@ -1046,7 +1157,7 @@
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
@@ -1056,7 +1167,9 @@
 # CONFIG_SMB_NLS_DEFAULT is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1129,6 +1242,10 @@
 CONFIG_NLS_UTF8=y
 
 #
+# Distributed Lock Manager
+#
+
+#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
@@ -1138,9 +1255,11 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_PLIST=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
 
 #
 # Instrumentation Support
@@ -1152,20 +1271,26 @@
 # 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_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=20
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT 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_RCU_TORTURE_TEST is not set
 CONFIG_IA64_GRANULE_16MB=y
@@ -1186,6 +1311,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=m
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -1195,6 +1324,8 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index e1a1b11..424e925 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -54,7 +54,7 @@
 static int simeth_tx(struct sk_buff *skb, struct net_device *dev);
 static int simeth_rx(struct net_device *dev);
 static struct net_device_stats *simeth_get_stats(struct net_device *dev);
-static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t simeth_interrupt(int irq, void *dev_id);
 static void set_multicast_list(struct net_device *dev);
 static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr);
 
@@ -87,7 +87,7 @@
  */
 static struct notifier_block simeth_dev_notifier = {
 	simeth_device_event,
-	0
+	NULL
 };
 
 
@@ -497,7 +497,7 @@
  * Interrupt handler (Yes, we can do it too !!!)
  */
 static irqreturn_t
-simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+simeth_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index 8f0a16a..bb87682 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -103,7 +103,7 @@
 
 	while ((sc = queue[rd].sc) != 0) {
 		atomic_dec(&num_reqs);
-		queue[rd].sc = 0;
+		queue[rd].sc = NULL;
 		if (DBG)
 			printk("simscsi_interrupt: done with %ld\n", sc->serial_number);
 		(*sc->scsi_done)(sc);
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 246eb3d..caab986 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -92,7 +92,7 @@
 	{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
 		  UART_STARTECH },
 	{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
-	{ 0, 0}
+	{ NULL, 0}
 };
 
 struct tty_driver *hp_simserial_driver;
@@ -130,7 +130,7 @@
 #endif
 }
 
-static  void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
+static  void receive_chars(struct tty_struct *tty)
 {
 	unsigned char ch;
 	static unsigned char seen_esc = 0;
@@ -152,7 +152,7 @@
 						ch = ia64_ssc(0, 0, 0, 0,
 							      SSC_GETCHAR);
 					while (!ch);
-					handle_sysrq(ch, regs, NULL);
+					handle_sysrq(ch, NULL);
 				}
 #endif
 				seen_esc = 0;
@@ -170,7 +170,7 @@
 /*
  * This is the serial driver's interrupt routine for a single port
  */
-static irqreturn_t rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
 {
 	struct async_struct * info;
 
@@ -187,7 +187,7 @@
 	 * pretty simple in our case, because we only get interrupts
 	 * on inbound traffic
 	 */
-	receive_chars(info->tty, regs);
+	receive_chars(info->tty);
 	return IRQ_HANDLED;
 }
 
@@ -555,7 +555,7 @@
 
 		if (info->xmit.buf) {
 			free_page((unsigned long) info->xmit.buf);
-			info->xmit.buf = 0;
+			info->xmit.buf = NULL;
 		}
 
 		if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -628,7 +628,7 @@
 	if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty);
 	if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
 	info->event = 0;
-	info->tty = 0;
+	info->tty = NULL;
 	if (info->blocked_open) {
 		if (info->close_delay)
 			schedule_timeout_interruptible(info->close_delay);
@@ -668,7 +668,7 @@
 	info->event = 0;
 	state->count = 0;
 	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->tty = 0;
+	info->tty = NULL;
 	wake_up_interruptible(&info->open_wait);
 }
 
@@ -714,7 +714,7 @@
 {
 	unsigned long flags;
 	int	retval=0;
-	irqreturn_t (*handler)(int, void *, struct pt_regs *);
+	irq_handler_t handler;
 	struct serial_state *state= info->state;
 	unsigned long page;
 
@@ -769,7 +769,7 @@
 	/*
 	 * Insert serial port into IRQ chain.
 	 */
-	info->prev_port = 0;
+	info->prev_port = NULL;
 	info->next_port = IRQ_ports[state->irq];
 	if (info->next_port)
 		info->next_port->prev_port = info;
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 32c3abed..73ef4a85 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -64,9 +64,6 @@
 void (*pm_power_off) (void);
 EXPORT_SYMBOL(pm_power_off);
 
-unsigned char acpi_kbd_controller_present = 1;
-unsigned char acpi_legacy_devices;
-
 unsigned int acpi_cpei_override;
 unsigned int acpi_cpei_phys_cpuid;
 
@@ -628,12 +625,6 @@
 
 	fadt = (struct fadt_descriptor *)fadt_header;
 
-	if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
-		acpi_kbd_controller_present = 0;
-
-	if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
-		acpi_legacy_devices = 1;
-
 	acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
 	return 0;
 }
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 7852382..f07c086 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -194,8 +194,11 @@
 	 */
 	for (irq=0; irq < NR_IRQS; irq++) {
 		if (vectors_in_migration[irq]) {
+			struct pt_regs *old_regs = set_irq_regs(NULL);
+
 			vectors_in_migration[irq]=0;
-			__do_IRQ(irq, NULL);
+			__do_IRQ(irq);
+			set_irq_regs(old_regs);
 		}
 	}
 
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index ab2d19c..9c6dafa 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -138,6 +138,7 @@
 void
 ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	unsigned long saved_tpr;
 
 #if IRQ_DEBUG
@@ -179,11 +180,13 @@
 	saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
 	ia64_srlz_d();
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
-		if (!IS_RESCHEDULE(vector)) {
+		if (unlikely(IS_RESCHEDULE(vector)))
+			 kstat_this_cpu.irqs[vector]++;
+		else {
 			ia64_setreg(_IA64_REG_CR_TPR, vector);
 			ia64_srlz_d();
 
-			__do_IRQ(local_vector_to_irq(vector), regs);
+			__do_IRQ(local_vector_to_irq(vector));
 
 			/*
 			 * Disable interrupts and send EOI:
@@ -200,6 +203,7 @@
 	 * come through until ia64_eoi() has been done.
 	 */
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -223,7 +227,11 @@
 	  * Perform normal interrupt style processing
 	  */
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
-		if (!IS_RESCHEDULE(vector)) {
+		if (unlikely(IS_RESCHEDULE(vector)))
+			 kstat_this_cpu.irqs[vector]++;
+		else {
+			struct pt_regs *old_regs = set_irq_regs(NULL);
+
 			ia64_setreg(_IA64_REG_CR_TPR, vector);
 			ia64_srlz_d();
 
@@ -234,7 +242,8 @@
 			 * Probably could shared code.
 			 */
 			vectors_in_migration[local_vector_to_irq(vector)]=0;
-			__do_IRQ(local_vector_to_irq(vector), NULL);
+			__do_IRQ(local_vector_to_irq(vector));
+			set_irq_regs(old_regs);
 
 			/*
 			 * Disable interrupts and send EOI
@@ -251,13 +260,24 @@
 
 
 #ifdef CONFIG_SMP
-extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t handle_IPI (int irq, void *dev_id);
+
+static irqreturn_t dummy_handler (int irq, void *dev_id)
+{
+	BUG();
+}
 
 static struct irqaction ipi_irqaction = {
 	.handler =	handle_IPI,
 	.flags =	IRQF_DISABLED,
 	.name =		"IPI"
 };
+
+static struct irqaction resched_irqaction = {
+	.handler =	dummy_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"resched"
+};
 #endif
 
 void
@@ -282,6 +302,7 @@
 	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
 	register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
+	register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
 #endif
 #ifdef CONFIG_PERFMON
 	pfm_init_percpu();
diff --git a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
index d4a546a..9620822 100644
--- a/arch/ia64/kernel/machvec.c
+++ b/arch/ia64/kernel/machvec.c
@@ -60,7 +60,7 @@
 EXPORT_SYMBOL(machvec_setup);
 
 void
-machvec_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+machvec_timer_interrupt (int irq, void *dev_id)
 {
 }
 EXPORT_SYMBOL(machvec_timer_interrupt);
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 6632301..7cfa63a 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -499,7 +499,7 @@
 int ia64_cpe_irq = -1;
 
 static irqreturn_t
-ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_cpe_int_handler (int cpe_irq, void *arg)
 {
 	static unsigned long	cpe_history[CPE_HISTORY_LENGTH];
 	static int		index;
@@ -744,7 +744,7 @@
  *  Outputs :   None
  */
 static irqreturn_t
-ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
+ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
 {
 	unsigned long flags;
 	int cpu = smp_processor_id();
@@ -753,8 +753,8 @@
 
 	/* Mask all interrupts */
 	local_irq_save(flags);
-	if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, (long)&nd, 0, 0)
-			== NOTIFY_STOP)
+	if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", get_irq_regs(),
+		       (long)&nd, 0, 0) == NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
 	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
@@ -763,16 +763,16 @@
 	 */
 	ia64_sal_mc_rendez();
 
-	if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, (long)&nd, 0, 0)
-			== NOTIFY_STOP)
+	if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", get_irq_regs(),
+		       (long)&nd, 0, 0) == NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
 	/* Wait for the monarch cpu to exit. */
 	while (monarch_cpu != -1)
 	       cpu_relax();	/* spin until monarch leaves */
 
-	if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, (long)&nd, 0, 0)
-			== NOTIFY_STOP)
+	if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", get_irq_regs(),
+		       (long)&nd, 0, 0) == NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
 	/* Enable all interrupts */
@@ -791,12 +791,11 @@
  *
  *  Inputs  :   wakeup_irq  (Wakeup-interrupt bit)
  *	arg		(Interrupt handler specific argument)
- *	ptregs		(Exception frame at the time of the interrupt)
  *  Outputs :   None
  *
  */
 static irqreturn_t
-ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg)
 {
 	return IRQ_HANDLED;
 }
@@ -1261,13 +1260,12 @@
  * Inputs
  *      interrupt number
  *      client data arg ptr
- *      saved registers ptr
  *
  * Outputs
  *	None
  */
 static irqreturn_t
-ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_cmc_int_handler(int cmc_irq, void *arg)
 {
 	static unsigned long	cmc_history[CMC_HISTORY_LENGTH];
 	static int		index;
@@ -1336,12 +1334,11 @@
  * Inputs
  *	interrupt number
  *	client data arg ptr
- *	saved registers ptr
  * Outputs
  * 	handled
  */
 static irqreturn_t
-ia64_mca_cmc_int_caller(int cmc_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_cmc_int_caller(int cmc_irq, void *arg)
 {
 	static int start_count = -1;
 	unsigned int cpuid;
@@ -1352,7 +1349,7 @@
 	if (start_count == -1)
 		start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
 
-	ia64_mca_cmc_int_handler(cmc_irq, arg, ptregs);
+	ia64_mca_cmc_int_handler(cmc_irq, arg);
 
 	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
 
@@ -1403,14 +1400,13 @@
  * Inputs
  *	interrupt number
  *	client data arg ptr
- *	saved registers ptr
  * Outputs
  * 	handled
  */
 #ifdef CONFIG_ACPI
 
 static irqreturn_t
-ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_cpe_int_caller(int cpe_irq, void *arg)
 {
 	static int start_count = -1;
 	static int poll_time = MIN_CPE_POLL_INTERVAL;
@@ -1422,7 +1418,7 @@
 	if (start_count == -1)
 		start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE);
 
-	ia64_mca_cpe_int_handler(cpe_irq, arg, ptregs);
+	ia64_mca_cpe_int_handler(cpe_irq, arg);
 
 	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
 
diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
index ebaf1e6..0b53344 100644
--- a/arch/ia64/kernel/pal.S
+++ b/arch/ia64/kernel/pal.S
@@ -21,11 +21,12 @@
 	.text
 
 /*
- * Set the PAL entry point address.  This could be written in C code, but we do it here
- * to keep it all in one module (besides, it's so trivial that it's
+ * Set the PAL entry point address.  This could be written in C code, but we
+ * do it here to keep it all in one module (besides, it's so trivial that it's
  * not a big deal).
  *
- * in0		Address of the PAL entry point (text address, NOT a function descriptor).
+ * in0		Address of the PAL entry point (text address, NOT a function
+ *		descriptor).
  */
 GLOBAL_ENTRY(ia64_pal_handler_init)
 	alloc r3=ar.pfs,1,0,0,0
@@ -36,9 +37,9 @@
 END(ia64_pal_handler_init)
 
 /*
- * Default PAL call handler.  This needs to be coded in assembly because it uses
- * the static calling convention, i.e., the RSE may not be used and calls are
- * done via "br.cond" (not "br.call").
+ * Default PAL call handler.  This needs to be coded in assembly because it
+ * uses the static calling convention, i.e., the RSE may not be used and
+ * calls are done via "br.cond" (not "br.call").
  */
 GLOBAL_ENTRY(ia64_pal_default_handler)
 	mov r8=-1
@@ -50,12 +51,10 @@
  *
  * in0         Index of PAL service
  * in1 - in3   Remaining PAL arguments
- * in4	       1 ==> clear psr.ic,  0 ==> don't clear psr.ic
- *
  */
 GLOBAL_ENTRY(ia64_pal_call_static)
-	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
-	alloc loc1 = ar.pfs,5,5,0,0
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
+	alloc loc1 = ar.pfs,4,5,0,0
 	movl loc2 = pal_entry_point
 1:	{
 	  mov r28 = in0
@@ -64,7 +63,6 @@
 	}
 	;;
 	ld8 loc2 = [loc2]		// loc2 <- entry point
-	tbit.nz p6,p7 = in4, 0
 	adds r8 = 1f-1b,r8
 	mov loc4=ar.rsc			// save RSE configuration
 	;;
@@ -74,13 +72,11 @@
 	.body
 	mov r30 = in2
 
-(p6)	rsm psr.i | psr.ic
 	mov r31 = in3
 	mov b7 = loc2
 
-(p7)	rsm psr.i
+	rsm psr.i
 	;;
-(p6)	srlz.i
 	mov rp = r8
 	br.cond.sptk.many b7
 1:	mov psr.l = loc3
@@ -96,8 +92,8 @@
  * Make a PAL call using the stacked registers calling convention.
  *
  * Inputs:
- * 	in0         Index of PAL service
- * 	in2 - in3   Remaning PAL arguments
+ *	in0         Index of PAL service
+ *	in2 - in3   Remaining PAL arguments
  */
 GLOBAL_ENTRY(ia64_pal_call_stacked)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
@@ -131,18 +127,18 @@
  * Make a physical mode PAL call using the static registers calling convention.
  *
  * Inputs:
- * 	in0         Index of PAL service
- * 	in2 - in3   Remaning PAL arguments
+ *	in0         Index of PAL service
+ *	in2 - in3   Remaining PAL arguments
  *
  * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
  * So we don't need to clear them.
  */
-#define PAL_PSR_BITS_TO_CLEAR							\
-	(IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT  | IA64_PSR_DB | IA64_PSR_RT |	\
-	 IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |		\
+#define PAL_PSR_BITS_TO_CLEAR						      \
+	(IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT  | IA64_PSR_DB | IA64_PSR_RT |\
+	 IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |	      \
 	 IA64_PSR_DFL | IA64_PSR_DFH)
 
-#define PAL_PSR_BITS_TO_SET							\
+#define PAL_PSR_BITS_TO_SET						      \
 	(IA64_PSR_BN)
 
 
@@ -178,7 +174,7 @@
 	;;
 	andcm r16=loc3,r16		// removes bits to clear from psr
 	br.call.sptk.many rp=ia64_switch_mode_phys
-.ret1:	mov rp = r8			// install return address (physical)
+	mov rp = r8			// install return address (physical)
 	mov loc5 = r19
 	mov loc6 = r20
 	br.cond.sptk.many b7
@@ -188,7 +184,6 @@
 	mov r19=loc5
 	mov r20=loc6
 	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
-.ret2:
 	mov psr.l = loc3		// restore init PSR
 
 	mov ar.pfs = loc1
@@ -203,8 +198,8 @@
  * Make a PAL call using the stacked registers in physical mode.
  *
  * Inputs:
- * 	in0         Index of PAL service
- * 	in2 - in3   Remaning PAL arguments
+ *	in0         Index of PAL service
+ *	in2 - in3   Remaining PAL arguments
  */
 GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
@@ -212,7 +207,7 @@
 	movl	loc2 = pal_entry_point
 1:	{
 	  mov r28  = in0		// copy procedure index
-	  mov loc0 = rp		// save rp
+	  mov loc0 = rp			// save rp
 	}
 	.body
 	;;
@@ -245,7 +240,7 @@
 	mov r16=loc3			// r16= original psr
 	mov r19=loc5
 	mov r20=loc6
-	br.call.sptk.many rp=ia64_switch_mode_virt	// return to virtual mode
+	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
 
 	mov psr.l  = loc3		// restore init PSR
 	mov ar.pfs = loc1
@@ -257,10 +252,11 @@
 END(ia64_pal_call_phys_stacked)
 
 /*
- * Save scratch fp scratch regs which aren't saved in pt_regs already (fp10-fp15).
+ * Save scratch fp scratch regs which aren't saved in pt_regs already
+ * (fp10-fp15).
  *
- * NOTE: We need to do this since firmware (SAL and PAL) may use any of the scratch
- * regs fp-low partition.
+ * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
+ * scratch regs fp-low partition.
  *
  * Inputs:
  *      in0	Address of stack storage for fp regs
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 281004f..3aaede0 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -5558,12 +5558,13 @@
 }
 
 static irqreturn_t
-pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
+pfm_interrupt_handler(int irq, void *arg)
 {
 	unsigned long start_cycles, total_cycles;
 	unsigned long min, max;
 	int this_cpu;
 	int ret;
+	struct pt_regs *regs = get_irq_regs();
 
 	this_cpu = get_cpu();
 	if (likely(!pfm_alt_intr_handler)) {
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 62e07f9..39e0cd3 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -45,7 +45,7 @@
 };
 
 static irqreturn_t
-timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+timer_interrupt (int irq, void *dev_id)
 {
 	unsigned long new_itm;
 
@@ -53,7 +53,7 @@
 		return IRQ_HANDLED;
 	}
 
-	platform_timer_interrupt(irq, dev_id, regs);
+	platform_timer_interrupt(irq, dev_id);
 
 	new_itm = local_cpu_data->itm_next;
 
@@ -61,10 +61,10 @@
 		printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
 		       ia64_get_itc(), new_itm);
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 	while (1) {
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 
 		new_itm += local_cpu_data->itm_delta;
 
@@ -84,6 +84,12 @@
 
 		if (time_after(new_itm, ia64_get_itc()))
 			break;
+
+		/*
+		 * Allow IPIs to interrupt the timer loop.
+		 */
+		local_irq_enable();
+		local_irq_disable();
 	}
 
 	do {
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index daf977f..82deaa3 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -233,6 +233,7 @@
 	efi_memmap_walk(count_pages, &num_physpages);
 
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 	max_zone_pfns[ZONE_DMA] = max_dma;
 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index d497b6b..96722cb 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -709,6 +709,7 @@
 			max_pfn = mem_data[node].max_pfn;
 	}
 
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 	max_zone_pfns[ZONE_DMA] = max_dma;
 	max_zone_pfns[ZONE_NORMAL] = max_pfn;
 	free_area_init_nodes(max_zone_pfns);
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 96fb81e..abca6bd 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -22,7 +22,7 @@
 void hubiio_crb_error_handler(struct hubdev_info *hubdev_info);
 extern void bte_crb_error_handler(cnodeid_t, int, int, ioerror_t *,
 				  int);
-static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep)
+static irqreturn_t hub_eint_handler(int irq, void *arg)
 {
 	struct hubdev_info *hubdev_info;
 	struct ia64_sal_retval ret_stuff;
@@ -178,7 +178,7 @@
  */
 void hub_error_init(struct hubdev_info *hubdev_info)
 {
-	if (request_irq(SGI_II_ERROR, (void *)hub_eint_handler, IRQF_SHARED,
+	if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
 			"SN_hub_error", (void *)hubdev_info))
 		printk("hub_error_init: Failed to request_irq for 0x%p\n",
 		    hubdev_info);
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 5f2dcba..7a2d824 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -65,7 +65,6 @@
 extern unsigned long last_time_offset;
 extern void (*ia64_mark_idle) (int);
 extern void snidle(int);
-extern unsigned char acpi_kbd_controller_present;
 extern unsigned long long (*ia64_printk_clock)(void);
 
 unsigned long sn_rtc_cycles_per_second;
@@ -452,17 +451,6 @@
 
 	ia64_printk_clock = ia64_sn2_printk_clock;
 
-	/*
-	 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
-	 * support here so we don't have to listen to failed keyboard probe
-	 * messages.
-	 */
-	if (is_shub1() && version <= 0x0209 && acpi_kbd_controller_present) {
-		printk(KERN_INFO "Disabling legacy keyboard support as prom "
-		       "is too old and doesn't provide FADT\n");
-		acpi_kbd_controller_present = 0;
-	}
-
 	printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
 
 	/*
diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
index fa7f699..103d6ea 100644
--- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c
+++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
@@ -36,7 +36,7 @@
 
 #define SN_LB_INT_WAR_INTERVAL 100
 
-void sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+void sn_timer_interrupt(int irq, void *dev_id)
 {
 	/* LED blinking */
 	if (!pda->hb_count--) {
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 4d026f9..fa96dfc 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -222,7 +222,7 @@
  * Notify the heartbeat check thread that an IRQ has been received.
  */
 static irqreturn_t
-xpc_act_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)
+xpc_act_IRQ_handler(int irq, void *dev_id)
 {
 	atomic_inc(&xpc_act_IRQ_rcvd);
 	wake_up_interruptible(&xpc_act_IRQ_wq);
@@ -607,12 +607,9 @@
  *	irq - Interrupt ReQuest number. NOT USED.
  *
  *	dev_id - partid of IPI's potential sender.
- *
- *	regs - processor's context before the processor entered
- *	       interrupt code. NOT USED.
  */
 irqreturn_t
-xpc_notify_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)
+xpc_notify_IRQ_handler(int irq, void *dev_id)
 {
 	partid_t partid = (partid_t) (u64) dev_id;
 	struct xpc_partition *part = &xpc_partitions[partid];
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
index 5eb1e1e..935029f 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
@@ -126,7 +126,7 @@
  * Setup an Address Translation Entry as specified.  Use either the Bridge
  * internal maps or the external map RAM, as appropriate.
  */
-static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info,
+static inline u64 __iomem *pcibr_ate_addr(struct pcibus_info *pcibus_info,
 				       int ate_index)
 {
 	if (ate_index < pcibus_info->pbi_int_ate_size) {
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 838c93c..27dd7df 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -95,7 +95,7 @@
  * bridge sends an error interrupt.
  */
 static irqreturn_t
-pcibr_error_intr_handler(int irq, void *arg, struct pt_regs *regs)
+pcibr_error_intr_handler(int irq, void *arg)
 {
 	struct pcibus_info *soft = (struct pcibus_info *)arg;
 
@@ -138,7 +138,7 @@
 	/*
 	 * register the bridge's error interrupt handler
 	 */
-	if (request_irq(SGI_PCIASIC_ERROR, (void *)pcibr_error_intr_handler,
+	if (request_irq(SGI_PCIASIC_ERROR, pcibr_error_intr_handler,
 			IRQF_SHARED, "PCIBR error", (void *)(soft))) {
 		printk(KERN_WARNING
 		       "pcibr cannot allocate interrupt for error handler\n");
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index c36b0f5..8a2cb4e 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -550,13 +550,12 @@
  * tioca_error_intr_handler - SGI TIO CA error interrupt handler
  * @irq: unused
  * @arg: pointer to tioca_common struct for the given CA
- * @pt: unused
  *
  * Handle a CA error interrupt.  Simply a wrapper around a SAL call which
  * defers processing to the SGI prom.
  */
 static irqreturn_t
-tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
+tioca_error_intr_handler(int irq, void *arg)
 {
 	struct tioca_common *soft = arg;
 	struct ia64_sal_retval ret_stuff;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index af7171a..46e16dc 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -53,7 +53,7 @@
  */
 
 static void inline
-tioce_mmr_war_pre(struct tioce_kernel *kern, void *mmr_addr)
+tioce_mmr_war_pre(struct tioce_kernel *kern, void __iomem *mmr_addr)
 {
 	u64 mmr_base;
 	u64 mmr_offset;
@@ -62,7 +62,7 @@
 		return;
 
 	mmr_base = kern->ce_common->ce_pcibus.bs_base;
-	mmr_offset = (u64)mmr_addr - mmr_base;
+	mmr_offset = (unsigned long)mmr_addr - mmr_base;
 
 	if (mmr_offset < 0x45000) {
 		u64 mmr_war_offset;
@@ -79,7 +79,7 @@
 }
 
 static void inline
-tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr)
+tioce_mmr_war_post(struct tioce_kernel *kern, void __iomem *mmr_addr)
 {
 	u64 mmr_base;
 	u64 mmr_offset;
@@ -88,7 +88,7 @@
 		return;
 
 	mmr_base = kern->ce_common->ce_pcibus.bs_base;
-	mmr_offset = (u64)mmr_addr - mmr_base;
+	mmr_offset = (unsigned long)mmr_addr - mmr_base;
 
 	if (mmr_offset < 0x45000) {
 		if (mmr_offset == 0x100)
@@ -223,7 +223,7 @@
  * @pci_dev.
  */
 static inline void
-pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base,
+pcidev_to_tioce(struct pci_dev *pdev, struct tioce __iomem **base,
 		struct tioce_kernel **kernel, int *port)
 {
 	struct pcidev_info *pcidev_info;
@@ -235,7 +235,7 @@
 	ce_kernel = (struct tioce_kernel *)ce_common->ce_kernel_private;
 
 	if (base)
-		*base = (struct tioce *)ce_common->ce_pcibus.bs_base;
+		*base = (struct tioce __iomem *)ce_common->ce_pcibus.bs_base;
 	if (kernel)
 		*kernel = ce_kernel;
 
@@ -275,13 +275,13 @@
 	u64 pagesize;
 	int msi_capable, msi_wanted;
 	u64 *ate_shadow;
-	u64 *ate_reg;
+	u64 __iomem *ate_reg;
 	u64 addr;
-	struct tioce *ce_mmr;
+	struct tioce __iomem *ce_mmr;
 	u64 bus_base;
 	struct tioce_dmamap *map;
 
-	ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
+	ce_mmr = (struct tioce __iomem *)ce_kern->ce_common->ce_pcibus.bs_base;
 
 	switch (type) {
 	case TIOCE_ATE_M32:
@@ -386,7 +386,7 @@
 {
 	int dma_ok;
 	int port;
-	struct tioce *ce_mmr;
+	struct tioce __iomem *ce_mmr;
 	struct tioce_kernel *ce_kern;
 	u64 ct_upper;
 	u64 ct_lower;
@@ -461,7 +461,7 @@
 	int i;
 	int port;
 	struct tioce_kernel *ce_kern;
-	struct tioce *ce_mmr;
+	struct tioce __iomem *ce_mmr;
 	unsigned long flags;
 
 	bus_addr = tioce_dma_barrier(bus_addr, 0);
@@ -666,12 +666,11 @@
  * tioce_error_intr_handler - SGI TIO CE error interrupt handler
  * @irq: unused
  * @arg: pointer to tioce_common struct for the given CE
- * @pt: unused
  *
  * Handle a CE error interrupt.  Simply a wrapper around a SAL call which
  * defers processing to the SGI prom.
  */ static irqreturn_t
-tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
+tioce_error_intr_handler(int irq, void *arg)
 {
 	struct tioce_common *soft = arg;
 	struct ia64_sal_retval ret_stuff;
@@ -701,9 +700,9 @@
 tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
 {
 	int ate_index, last_ate, ps;
-	struct tioce *ce_mmr;
+	struct tioce __iomem *ce_mmr;
 
-	ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
+	ce_mmr = (struct tioce __iomem *)ce_kern->ce_common->ce_pcibus.bs_base;
 	ps = ce_kern->ce_ate3240_pagesize;
 	ate_index = ATE_PAGE(base, ps);
 	last_ate = ate_index + ATE_NPAGES(base, limit-base+1, ps) - 1;
@@ -737,7 +736,7 @@
 	int dev;
 	u32 tmp;
 	unsigned int seg, bus;
-	struct tioce *tioce_mmr;
+	struct tioce __iomem *tioce_mmr;
 	struct tioce_kernel *tioce_kern;
 
 	tioce_kern = kzalloc(sizeof(struct tioce_kernel), GFP_KERNEL);
@@ -768,7 +767,7 @@
 	 * the ate's.
 	 */
 
-	tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
+	tioce_mmr = (struct tioce __iomem *)tioce_common->ce_pcibus.bs_base;
 	tioce_mmr_clri(tioce_kern, &tioce_mmr->ce_ure_page_map,
 		       CE_URE_PAGESIZE_MASK);
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_ure_page_map,
@@ -859,7 +858,7 @@
 	struct pcidev_info *pcidev_info;
 	struct tioce_common *ce_common;
 	struct tioce_kernel *ce_kern;
-	struct tioce *ce_mmr;
+	struct tioce __iomem *ce_mmr;
 	u64 force_int_val;
 
 	if (!sn_irq_info->irq_bridge)
@@ -873,7 +872,7 @@
 		return;
 
 	ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
-	ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+	ce_mmr = (struct tioce __iomem *)ce_common->ce_pcibus.bs_base;
 	ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
 
 	/*
@@ -954,7 +953,7 @@
 	struct pcidev_info *pcidev_info;
 	struct tioce_common *ce_common;
 	struct tioce_kernel *ce_kern;
-	struct tioce *ce_mmr;
+	struct tioce __iomem *ce_mmr;
 	int bit;
 	u64 vector;
 
@@ -963,7 +962,7 @@
 		return;
 
 	ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
-	ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+	ce_mmr = (struct tioce __iomem *)ce_common->ce_pcibus.bs_base;
 	ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
 
 	bit = sn_irq_info->irq_int_bit;
@@ -995,7 +994,7 @@
 	cnodeid_t my_cnode, mem_cnode;
 	struct tioce_common *tioce_common;
 	struct tioce_kernel *tioce_kern;
-	struct tioce *tioce_mmr;
+	struct tioce __iomem *tioce_mmr;
 
 	/*
 	 * Allocate kernel bus soft and copy from prom.
@@ -1019,7 +1018,7 @@
 	 * interrupt handler.
 	 */
 
-	tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
+	tioce_mmr = (struct tioce __iomem *)tioce_common->ce_pcibus.bs_base;
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL);
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias,
 		       ~0ULL);
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
index 3841861..f8d8650 100644
--- a/arch/m32r/kernel/irq.c
+++ b/arch/m32r/kernel/irq.c
@@ -77,13 +77,16 @@
  */
 asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* FIXME M32R */
 #endif
-	__do_IRQ(irq, regs);
+	__do_IRQ(irq);
 	irq_exit();
+	set_irq_regs(old_regs);
 
 	return 1;
 }
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 3f35ab3..0e7778b 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -369,10 +369,10 @@
 }
 
 struct seq_operations cpuinfo_op = {
-	start:	c_start,
-	next:	c_next,
-	stop:	c_stop,
-	show:	show_cpuinfo,
+	.start = c_start,
+	.next = c_next,
+	.stop = c_stop,
+	.show = show_cpuinfo,
 };
 #endif	/* CONFIG_PROC_FS */
 
diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
index 67dbbdc..6b2d77d 100644
--- a/arch/m32r/kernel/setup_mappi.c
+++ b/arch/m32r/kernel/setup_mappi.c
@@ -86,7 +86,7 @@
 	/* INT0 : LAN controller (RTL8019AS) */
 	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_INT0].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].action = NULL;
 	irq_desc[M32R_IRQ_INT0].depth = 1;
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi_irq(M32R_IRQ_INT0);
@@ -95,7 +95,7 @@
 	/* MFT2 : system timer */
 	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_MFT2].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].action = NULL;
 	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
@@ -104,7 +104,7 @@
 	/* SIO0_R : uart receive data */
 	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].action = NULL;
 	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
@@ -112,7 +112,7 @@
 	/* SIO0_S : uart send data */
 	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].action = NULL;
 	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
@@ -120,7 +120,7 @@
 	/* SIO1_R : uart receive data */
 	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].action = NULL;
 	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
@@ -128,7 +128,7 @@
 	/* SIO1_S : uart send data */
 	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].action = NULL;
 	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
@@ -138,7 +138,7 @@
 	/* INT1 : pccard0 interrupt */
 	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_INT1].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_INT1].action = 0;
+	irq_desc[M32R_IRQ_INT1].action = NULL;
 	irq_desc[M32R_IRQ_INT1].depth = 1;
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT1);
@@ -146,7 +146,7 @@
 	/* INT2 : pccard1 interrupt */
 	irq_desc[M32R_IRQ_INT2].status = IRQ_DISABLED;
 	irq_desc[M32R_IRQ_INT2].chip = &mappi_irq_type;
-	irq_desc[M32R_IRQ_INT2].action = 0;
+	irq_desc[M32R_IRQ_INT2].action = NULL;
 	irq_desc[M32R_IRQ_INT2].depth = 1;
 	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT2);
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index a9174ef..b60cea4 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -33,7 +33,7 @@
 int do_signal(struct pt_regs *, sigset_t *);
 
 asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
 		  unsigned long r2, unsigned long r3, unsigned long r4,
 		  unsigned long r5, unsigned long r6, struct pt_regs *regs)
 {
@@ -78,8 +78,8 @@
 struct rt_sigframe
 {
 	int sig;
-	struct siginfo *pinfo;
-	void *puc;
+	struct siginfo __user *pinfo;
+	void __user *puc;
 	struct siginfo info;
 	struct ucontext uc;
 //	struct _fpstate fpstate;
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
index 8b1f6eb..3601291 100644
--- a/arch/m32r/kernel/smp.c
+++ b/arch/m32r/kernel/smp.c
@@ -101,7 +101,7 @@
 
 void smp_send_timer(void);
 void smp_ipi_timer_interrupt(struct pt_regs *);
-void smp_local_timer_interrupt(struct pt_regs *);
+void smp_local_timer_interrupt(void);
 
 void send_IPI_allbutself(int, int);
 static void send_IPI_mask(cpumask_t, int, int);
@@ -231,7 +231,7 @@
 	local_irq_save(flags);
 	__flush_tlb_all();
 	local_irq_restore(flags);
-	smp_call_function(flush_tlb_all_ipi, 0, 1, 1);
+	smp_call_function(flush_tlb_all_ipi, NULL, 1, 1);
 	preempt_enable();
 }
 
@@ -734,9 +734,12 @@
  *==========================================================================*/
 void smp_ipi_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
+	old_regs = set_irq_regs(regs);
 	irq_enter();
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 /*==========================================================================*
@@ -762,9 +765,9 @@
  * ---------- --- --------------------------------------------------------
  * 2003-06-24 hy  use per_cpu structure.
  *==========================================================================*/
-void smp_local_timer_interrupt(struct pt_regs *regs)
+void smp_local_timer_interrupt(void)
 {
-	int user = user_mode(regs);
+	int user = user_mode(get_irq_regs());
 	int cpu_id = smp_processor_id();
 
 	/*
@@ -774,7 +777,7 @@
 	 * useful with a profiling multiplier != 1
 	 */
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 	if (--per_cpu(prof_counter, cpu_id) <= 0) {
 		/*
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index b567351..b4e7bcb 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -31,7 +31,7 @@
 /*
  * sys_tas() - test-and-set
  */
-asmlinkage int sys_tas(int *addr)
+asmlinkage int sys_tas(int __user *addr)
 {
 	int oldval;
 
@@ -90,7 +90,7 @@
 
 	error = do_pipe(fd);
 	if (!error) {
-		if (copy_to_user((void *)r0, (void *)fd, 2*sizeof(int)))
+		if (copy_to_user((void __user *)r0, fd, 2*sizeof(int)))
 			error = -EFAULT;
 	}
 	return error;
@@ -201,7 +201,7 @@
 	}
 }
 
-asmlinkage int sys_uname(struct old_utsname * name)
+asmlinkage int sys_uname(struct old_utsname __user * name)
 {
 	int err;
 	if (!name)
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index d8af155..a090382 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -35,7 +35,7 @@
 
 #ifdef CONFIG_SMP
 extern void send_IPI_allbutself(int, int);
-extern void smp_local_timer_interrupt(struct pt_regs *);
+extern void smp_local_timer_interrupt(void);
 #endif
 
 #define TICK_SIZE	(tick_nsec / 1000)
@@ -188,15 +188,15 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 #ifndef CONFIG_SMP
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #endif
 	do_timer(1);
 
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 	/*
 	 * If we have an externally synchronized Linux clock, then update
@@ -221,7 +221,7 @@
 	   a hack, so don't look closely for now.. */
 
 #ifdef CONFIG_SMP
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 	smp_send_timer();
 #endif
 
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
index c1daf2c..97e0b1c 100644
--- a/arch/m32r/kernel/traps.c
+++ b/arch/m32r/kernel/traps.c
@@ -268,7 +268,7 @@
 #define DO_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
-	do_trap(trapnr, signr, 0, regs, error_code, NULL); \
+	do_trap(trapnr, signr, NULL, regs, error_code, NULL); \
 }
 
 #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 805b81f..7bc1446 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -600,7 +600,7 @@
 
 config SERIAL167
 	bool "CD2401 support for MVME166/7 serial ports"
-	depends on MVME16x && BROKEN
+	depends on MVME16x
 	help
 	  This is the driver for the serial ports on the Motorola MVME166,
 	  167, and 172 boards.  Everyone using one of these boards should say
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 96c79d8..28d95cf 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -47,10 +47,10 @@
 
 static void amiga_enable_irq(unsigned int irq);
 static void amiga_disable_irq(unsigned int irq);
-static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp);
-static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp);
-static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp);
-static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t ami_int1(int irq, void *dev_id);
+static irqreturn_t ami_int3(int irq, void *dev_id);
+static irqreturn_t ami_int4(int irq, void *dev_id);
+static irqreturn_t ami_int5(int irq, void *dev_id);
 
 static struct irq_controller amiga_irq_controller = {
 	.name		= "amiga",
@@ -113,98 +113,98 @@
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int1(int irq, void *dev_id)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if serial transmit buffer empty, interrupt */
 	if (ints & IF_TBE) {
 		amiga_custom.intreq = IF_TBE;
-		m68k_handle_int(IRQ_AMIGA_TBE, fp);
+		m68k_handle_int(IRQ_AMIGA_TBE);
 	}
 
 	/* if floppy disk transfer complete, interrupt */
 	if (ints & IF_DSKBLK) {
 		amiga_custom.intreq = IF_DSKBLK;
-		m68k_handle_int(IRQ_AMIGA_DSKBLK, fp);
+		m68k_handle_int(IRQ_AMIGA_DSKBLK);
 	}
 
 	/* if software interrupt set, interrupt */
 	if (ints & IF_SOFT) {
 		amiga_custom.intreq = IF_SOFT;
-		m68k_handle_int(IRQ_AMIGA_SOFT, fp);
+		m68k_handle_int(IRQ_AMIGA_SOFT);
 	}
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int3(int irq, void *dev_id)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
 		amiga_custom.intreq = IF_BLIT;
-		m68k_handle_int(IRQ_AMIGA_BLIT, fp);
+		m68k_handle_int(IRQ_AMIGA_BLIT);
 	}
 
 	/* if a copper interrupt */
 	if (ints & IF_COPER) {
 		amiga_custom.intreq = IF_COPER;
-		m68k_handle_int(IRQ_AMIGA_COPPER, fp);
+		m68k_handle_int(IRQ_AMIGA_COPPER);
 	}
 
 	/* if a vertical blank interrupt */
 	if (ints & IF_VERTB) {
 		amiga_custom.intreq = IF_VERTB;
-		m68k_handle_int(IRQ_AMIGA_VERTB, fp);
+		m68k_handle_int(IRQ_AMIGA_VERTB);
 	}
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int4(int irq, void *dev_id)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if audio 0 interrupt */
 	if (ints & IF_AUD0) {
 		amiga_custom.intreq = IF_AUD0;
-		m68k_handle_int(IRQ_AMIGA_AUD0, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD0);
 	}
 
 	/* if audio 1 interrupt */
 	if (ints & IF_AUD1) {
 		amiga_custom.intreq = IF_AUD1;
-		m68k_handle_int(IRQ_AMIGA_AUD1, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD1);
 	}
 
 	/* if audio 2 interrupt */
 	if (ints & IF_AUD2) {
 		amiga_custom.intreq = IF_AUD2;
-		m68k_handle_int(IRQ_AMIGA_AUD2, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD2);
 	}
 
 	/* if audio 3 interrupt */
 	if (ints & IF_AUD3) {
 		amiga_custom.intreq = IF_AUD3;
-		m68k_handle_int(IRQ_AMIGA_AUD3, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD3);
 	}
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int5(int irq, void *dev_id)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if serial receive buffer full interrupt */
 	if (ints & IF_RBF) {
 		/* acknowledge of IF_RBF must be done by the serial interrupt */
-		m68k_handle_int(IRQ_AMIGA_RBF, fp);
+		m68k_handle_int(IRQ_AMIGA_RBF);
 	}
 
 	/* if a disk sync interrupt */
 	if (ints & IF_DSKSYN) {
 		amiga_custom.intreq = IF_DSKSYN;
-		m68k_handle_int(IRQ_AMIGA_DSKSYN, fp);
+		m68k_handle_int(IRQ_AMIGA_DSKSYN);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index dbad300..7a20058 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -82,7 +82,7 @@
 	return old;
 }
 
-static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t cia_handler(int irq, void *dev_id)
 {
 	struct ciabase *base = (struct ciabase *)dev_id;
 	int mach_irq;
@@ -93,7 +93,7 @@
 	amiga_custom.intreq = base->int_mask;
 	for (; ints; mach_irq++, ints >>= 1) {
 		if (ints & 1)
-			m68k_handle_int(mach_irq, fp);
+			m68k_handle_int(mach_irq);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 092e50d..3204f41 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -83,7 +83,7 @@
 
 extern char m68k_debug_device[];
 
-static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+static void amiga_sched_init(irq_handler_t handler);
 /* amiga specific irq functions */
 extern void amiga_init_IRQ (void);
 static void amiga_get_model(char *model);
@@ -487,8 +487,7 @@
 
 static unsigned short jiffy_ticks;
 
-static void __init amiga_sched_init(irqreturn_t (*timer_routine)(int, void *,
-							  struct pt_regs *))
+static void __init amiga_sched_init(irq_handler_t timer_routine)
 {
 	static struct resource sched_res = {
 	    .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 6f45815..cb8e760 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -25,7 +25,7 @@
 u_long timer_physaddr;
 u_long apollo_model;
 
-extern void dn_sched_init(irqreturn_t (*handler)(int,void *,struct pt_regs *));
+extern void dn_sched_init(irq_handler_t handler);
 extern void dn_init_IRQ(void);
 extern unsigned long dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
@@ -38,7 +38,7 @@
 #ifdef CONFIG_HEARTBEAT
 static void dn_heartbeat(int on);
 #endif
-static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *);
+static irqreturn_t dn_timer_int(int irq,void *);
 static void dn_get_model(char *model);
 static const char *apollo_models[] = {
 	[APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)",
@@ -174,13 +174,13 @@
 
 }
 
-irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t dn_timer_int(int irq, void *dev_id)
 {
-	irqreturn_t (*timer_handler)(int, void *, struct pt_regs *) = dev_id;
+	irq_handler_t timer_handler = dev_id;
 
 	volatile unsigned char x;
 
-	timer_handler(irq, dev_id, fp);
+	timer_handler(irq, dev_id);
 
 	x=*(volatile unsigned char *)(timer+3);
 	x=*(volatile unsigned char *)(timer+5);
@@ -188,8 +188,8 @@
 	return IRQ_HANDLED;
 }
 
-void dn_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) {
-
+void dn_sched_init(irq_handler_t timer_routine)
+{
 	/* program timer 1 */
 	*(volatile unsigned char *)(timer+3)=0x01;
 	*(volatile unsigned char *)(timer+1)=0x40;
diff --git a/arch/m68k/apollo/dma.c b/arch/m68k/apollo/dma.c
deleted file mode 100644
index aed8be1..0000000
--- a/arch/m68k/apollo/dma.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/kd.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-
-#include <asm/setup.h>
-#include <asm/bootinfo.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/apollodma.h>
-#include <asm/io.h>
-
-/* note only works for 16 Bit 1 page DMA's */
-
-static unsigned short next_free_xlat_entry=0;
-
-unsigned short dma_map_page(unsigned long phys_addr,int count,int type) {
-
-	unsigned long page_aligned_addr=phys_addr & (~((1<<12)-1));
-	unsigned short start_map_addr=page_aligned_addr >> 10;
-	unsigned short free_xlat_entry, *xlat_map_entry;
-	int i;
-
-	free_xlat_entry=next_free_xlat_entry;
-	for(i=0,xlat_map_entry=addr_xlat_map+(free_xlat_entry<<2);i<8;i++,xlat_map_entry++) {
-#if 0
-		printk("phys_addr: %x, page_aligned_addr: %x, start_map_addr: %x\n",phys_addr,page_aligned_addr,start_map_addr+i);
-#endif
-		out_be16(xlat_map_entry, start_map_addr+i);
-	}
-
-	next_free_xlat_entry+=2;
-	if(next_free_xlat_entry>125)
-		next_free_xlat_entry=0;
-
-#if 0
-	printk("next_free_xlat_entry: %d\n",next_free_xlat_entry);
-#endif
-
-	return free_xlat_entry<<10;
-}
-
-void dma_unmap_page(unsigned short dma_addr) {
-
-	return ;
-
-}
-
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
index 9fe0780..4274af1 100644
--- a/arch/m68k/apollo/dn_ints.c
+++ b/arch/m68k/apollo/dn_ints.c
@@ -6,7 +6,7 @@
 
 void dn_process_int(unsigned int irq, struct pt_regs *fp)
 {
-	m68k_handle_int(irq, fp);
+	__m68k_handle_int(irq, fp);
 
 	*(volatile unsigned char *)(pica)=0x20;
 	*(volatile unsigned char *)(picb)=0x20;
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index ece13cb..7f81264 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -332,6 +332,9 @@
 	atari_disable_irq(irq);
 	atari_turnoff_irq(irq);
 	m68k_irq_shutdown(irq);
+
+	if (irq == IRQ_AUTO_4)
+	    vectors[VEC_INT4] = falcon_hblhandler;
 }
 
 static struct irq_controller atari_irq_controller = {
@@ -356,7 +359,7 @@
 
 void __init atari_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
 	m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
 
 	/* Initialize the MFP(s) */
@@ -403,8 +406,10 @@
 		 * gets overruns)
 		 */
 
-		if (!MACH_IS_HADES)
+		if (!MACH_IS_HADES) {
 			vectors[VEC_INT2] = falcon_hblhandler;
+			vectors[VEC_INT4] = falcon_hblhandler;
+		}
 	}
 
 	if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index b207925..ca5cd43 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -62,7 +62,7 @@
 #endif
 
 /* atari specific timer functions (in time.c) */
-extern void atari_sched_init(irqreturn_t (*)(int, void *, struct pt_regs *));
+extern void atari_sched_init(irq_handler_t );
 extern unsigned long atari_gettimeoffset (void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index 288f5e6..d64b580 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -44,7 +44,7 @@
 
 static int stdma_locked;			/* the semaphore */
 						/* int func to be called */
-static irqreturn_t (*stdma_isr)(int, void *, struct pt_regs *);
+static irq_handler_t stdma_isr;
 static void *stdma_isr_data;			/* data passed to isr */
 static DECLARE_WAIT_QUEUE_HEAD(stdma_wait);	/* wait queue for ST-DMA */
 
@@ -53,7 +53,7 @@
 
 /***************************** Prototypes *****************************/
 
-static irqreturn_t stdma_int (int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t stdma_int (int irq, void *dummy);
 
 /************************* End of Prototypes **************************/
 
@@ -75,8 +75,7 @@
  *
  */
 
-void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		void *data)
+void stdma_lock(irq_handler_t handler, void *data)
 {
 	unsigned long flags;
 
@@ -188,9 +187,9 @@
  *
  */
 
-static irqreturn_t stdma_int(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t stdma_int(int irq, void *dummy)
 {
   if (stdma_isr)
-      (*stdma_isr)(irq, stdma_isr_data, fp);
+      (*stdma_isr)(irq, stdma_isr_data);
   return IRQ_HANDLED;
 }
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index e79bbc9..e0d3c8b 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -16,11 +16,12 @@
 #include <linux/init.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
+#include <linux/delay.h>
 
 #include <asm/atariints.h>
 
 void __init
-atari_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+atari_sched_init(irq_handler_t timer_routine)
 {
     /* set Timer C data Register */
     mfp.tim_dt_c = INT_TICKS;
@@ -212,8 +213,12 @@
      * additionally the RTC_SET bit is set to prevent an update cycle.
      */
 
-    while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP )
-        schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
+    while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
+	if (in_atomic() || irqs_disabled())
+	    mdelay(1);
+	else
+	    schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
+    }
 
     local_irq_save(flags);
     RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index d1e916a..896ae3d 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -38,7 +38,7 @@
 
 static void bvme6000_get_model(char *model);
 static int  bvme6000_get_hardware_list(char *buffer);
-extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void bvme6000_sched_init(irq_handler_t handler);
 extern unsigned long bvme6000_gettimeoffset (void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern int bvme6000_set_clock_mmss (unsigned long);
@@ -52,7 +52,7 @@
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via bvme6000_process_int() */
 
-static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
+static irq_handler_t tick_handler;
 
 
 int bvme6000_parse_bootinfo(const struct bi_record *bi)
@@ -154,7 +154,7 @@
 }
 
 
-irqreturn_t bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t bvme6000_abort_int (int irq, void *dev_id)
 {
         unsigned long *new = (unsigned long *)vectors;
         unsigned long *old = (unsigned long *)0xf8000000;
@@ -171,14 +171,14 @@
 }
 
 
-static irqreturn_t bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
 {
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     unsigned char msr = rtc->msr & 0xc0;
 
     rtc->msr = msr | 0x20;		/* Ack the interrupt */
 
-    return tick_handler(irq, dev_id, fp);
+    return tick_handler(irq, dev_id);
 }
 
 /*
@@ -190,7 +190,7 @@
  * so divide by 8 to get the microsecond result.
  */
 
-void bvme6000_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+void bvme6000_sched_init (irq_handler_t timer_routine)
 {
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     unsigned char msr = rtc->msr & 0xc0;
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 7df0566..dd7c8a2 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -36,15 +36,15 @@
 
 #define INTVAL ((10000 / 4) - 1)
 
-static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hp300_tick(int irq, void *dev_id)
 {
 	unsigned long tmp;
-	irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id;
+	irq_handler_t vector = dev_id;
 	in_8(CLOCKBASE + CLKSR);
 	asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
 	/* Turn off the network and SCSI leds */
 	blinken_leds(0, 0xe0);
-	return vector(irq, NULL, regs);
+	return vector(irq, NULL);
 }
 
 unsigned long hp300_gettimeoffset(void)
@@ -63,7 +63,7 @@
   return (USECS_PER_JIFFY * ticks) / INTVAL;
 }
 
-void __init hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
+void __init hp300_sched_init(irq_handler_t vector)
 {
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
   out_8(CLOCKBASE + CLKCR1, 0x1);		/* reset */
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
index 8ef9987..f5b3d09 100644
--- a/arch/m68k/hp300/time.h
+++ b/arch/m68k/hp300/time.h
@@ -1,4 +1,4 @@
-extern void hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
+extern void hp300_sched_init(irq_handler_t vector);
 extern unsigned long hp300_gettimeoffset (void);
 
 
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index dae6097..1c9ecaa 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -9,10 +9,11 @@
 endif
 extra-y	+= vmlinux.lds
 
-obj-y	:= entry.o process.o traps.o ints.o dma.o signal.o ptrace.o \
+obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o \
 	   sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
 
 obj-$(CONFIG_PCI)	+= bios32.o
 obj-$(CONFIG_MODULES)	+= module.o
+obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo
 
 EXTRA_AFLAGS := -traditional
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index fc449f8..9d4e4b5 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -15,7 +15,7 @@
 #include <asm/scatterlist.h>
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *handle, int flag)
+			 dma_addr_t *handle, gfp_t flag)
 {
 	struct page *page, **map;
 	pgprot_t pgprot;
@@ -51,7 +51,7 @@
 		pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
 	else
 		pgprot_val(pgprot) |= _PAGE_NOCACHE030;
-	addr = vmap(map, size, flag, pgprot);
+	addr = vmap(map, size, VM_MAP, pgprot);
 	kfree(map);
 
 	return addr;
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 9083c8b..222ce42 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -205,7 +205,7 @@
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
 auto_irqhandler_fixup = . + 2
-	jsr	m68k_handle_int		|  process the IRQ
+	jsr	__m68k_handle_int	|  process the IRQ
 	addql	#8,%sp			|  pop parameters off stack
 
 ret_from_interrupt:
@@ -239,7 +239,7 @@
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
 user_irqhandler_fixup = . + 2
-	jsr	m68k_handle_int		|  process the IRQ
+	jsr	__m68k_handle_int	|  process the IRQ
 	addql	#8,%sp			|  pop parameters off stack
 
 	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
@@ -706,4 +706,33 @@
 	.long sys_add_key
 	.long sys_request_key	/* 280 */
 	.long sys_keyctl
+	.long sys_ioprio_set
+	.long sys_ioprio_get
+	.long sys_inotify_init
+	.long sys_inotify_add_watch	/* 285 */
+	.long sys_inotify_rm_watch
+	.long sys_migrate_pages
+	.long sys_openat
+	.long sys_mkdirat
+	.long sys_mknodat		/* 290 */
+	.long sys_fchownat
+	.long sys_futimesat
+	.long sys_fstatat64
+	.long sys_unlinkat
+	.long sys_renameat		/* 295 */
+	.long sys_linkat
+	.long sys_symlinkat
+	.long sys_readlinkat
+	.long sys_fchmodat
+	.long sys_faccessat		/* 300 */
+	.long sys_ni_syscall		/* Reserved for pselect6 */
+	.long sys_ni_syscall		/* Reserved for ppoll */
+	.long sys_unshare
+	.long sys_set_robust_list
+	.long sys_get_robust_list	/* 305 */
+	.long sys_splice
+	.long sys_sync_file_range
+	.long sys_tee
+	.long sys_vmsplice
+	.long sys_move_pages		/* 310 */
 
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index b33e37f..84aceca 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -39,6 +39,7 @@
 #include <asm/page.h>
 #include <asm/machdep.h>
 #include <asm/cacheflush.h>
+#include <asm/irq_regs.h>
 
 #ifdef CONFIG_Q40
 #include <asm/q40ints.h>
@@ -104,7 +105,7 @@
  * @handler: called from auto vector interrupts
  *
  * setup the handler to be called from auto vector interrupts instead of the
- * standard m68k_handle_int(), it will be called with irq numbers in the range
+ * standard __m68k_handle_int(), it will be called with irq numbers in the range
  * from IRQ_AUTO_1 - IRQ_AUTO_7.
  */
 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
@@ -123,7 +124,7 @@
  * setup user vector interrupts, this includes activating the specified range
  * of interrupts, only then these interrupts can be requested (note: this is
  * different from auto vector interrupts). An optional handler can be installed
- * to be called instead of the default m68k_handle_int(), it will be called
+ * to be called instead of the default __m68k_handle_int(), it will be called
  * with irq numbers starting from IRQ_USER.
  */
 void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
@@ -131,6 +132,7 @@
 {
 	int i;
 
+	BUG_ON(IRQ_USER + cnt >= NR_IRQS);
 	m68k_first_user_vec = vec;
 	for (i = 0; i < cnt; i++)
 		irq_controller[IRQ_USER + i] = &user_irq_controller;
@@ -215,7 +217,7 @@
 }
 
 int request_irq(unsigned int irq,
-		irqreturn_t (*handler) (int, void *, struct pt_regs *),
+		irq_handler_t handler,
 		unsigned long flags, const char *devname, void *dev_id)
 {
 	struct irq_node *node;
@@ -379,18 +381,25 @@
 
 EXPORT_SYMBOL(irq_canonicalize);
 
-asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs)
+asmlinkage void m68k_handle_int(unsigned int irq)
 {
 	struct irq_node *node;
-
 	kstat_cpu(0).irqs[irq]++;
 	node = irq_list[irq];
 	do {
-		node->handler(irq, node->dev_id, regs);
+		node->handler(irq, node->dev_id);
 		node = node->next;
 	} while (node);
 }
 
+asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs;
+	old_regs = set_irq_regs(regs);
+	m68k_handle_int(irq);
+	set_irq_regs(old_regs);
+}
+
 asmlinkage void handle_badint(struct pt_regs *regs)
 {
 	kstat_cpu(0).irqs[0]++;
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index aff26a5..6fc69c7 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -1,65 +1,10 @@
 #include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/machdep.h>
-#include <asm/pgalloc.h>
-#include <asm/irq.h>
-#include <asm/io.h>
 #include <asm/semaphore.h>
-#include <asm/checksum.h>
 
 asmlinkage long long __ashldi3 (long long, int);
 asmlinkage long long __ashrdi3 (long long, int);
 asmlinkage long long __lshrdi3 (long long, int);
 asmlinkage long long __muldi3 (long long, long long);
-extern char m68k_debug_device[];
-
-/* platform dependent support */
-
-EXPORT_SYMBOL(m68k_machtype);
-EXPORT_SYMBOL(m68k_cputype);
-EXPORT_SYMBOL(m68k_is040or060);
-EXPORT_SYMBOL(m68k_realnum_memory);
-EXPORT_SYMBOL(m68k_memory);
-#ifndef CONFIG_SUN3
-EXPORT_SYMBOL(cache_push);
-EXPORT_SYMBOL(cache_clear);
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-EXPORT_SYMBOL(mm_vtop);
-EXPORT_SYMBOL(mm_ptov);
-EXPORT_SYMBOL(mm_end_of_chunk);
-#else
-EXPORT_SYMBOL(m68k_memoffset);
-#endif /* !CONFIG_SINGLE_MEMORY_CHUNK */
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(kernel_set_cachemode);
-#endif /* !CONFIG_SUN3 */
-EXPORT_SYMBOL(m68k_debug_device);
-EXPORT_SYMBOL(mach_hwclk);
-EXPORT_SYMBOL(mach_get_ss);
-EXPORT_SYMBOL(mach_get_rtc_pll);
-EXPORT_SYMBOL(mach_set_rtc_pll);
-#ifdef CONFIG_INPUT_M68K_BEEP_MODULE
-EXPORT_SYMBOL(mach_beep);
-#endif
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(kernel_thread);
-#ifdef CONFIG_VME
-EXPORT_SYMBOL(vme_brdtype);
-#endif
 
 /* The following are special because they're not called
    explicitly (the C compiler generates them).  Fortunately,
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 45a4664..99fc122 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -187,6 +187,7 @@
 	set_fs (fs);
 	return pid;
 }
+EXPORT_SYMBOL(kernel_thread);
 
 void flush_thread(void)
 {
@@ -221,13 +222,13 @@
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
-	int *parent_tidptr, *child_tidptr;
+	int __user *parent_tidptr, *child_tidptr;
 
 	/* syscall2 puts clone_flags in d1 and usp in d2 */
 	clone_flags = regs->d1;
 	newsp = regs->d2;
-	parent_tidptr = (int *)regs->d3;
-	child_tidptr = (int *)regs->d4;
+	parent_tidptr = (int __user *)regs->d3;
+	child_tidptr = (int __user *)regs->d4;
 	if (!newsp)
 		newsp = rdusp();
 	return do_fork(clone_flags, newsp, regs, 0,
@@ -311,6 +312,7 @@
 		: "memory");
 	return 1;
 }
+EXPORT_SYMBOL(dump_fpu);
 
 /*
  * fill in the user structure for a core dump..
@@ -357,11 +359,12 @@
 	/* dump floating point stuff */
 	dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
 }
+EXPORT_SYMBOL(dump_thread);
 
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *name, char **argv, char **envp)
+asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
 {
 	int error;
 	char * filename;
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index f2d7ee0..9af3ee0 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -42,29 +42,39 @@
 
 unsigned long m68k_machtype;
 unsigned long m68k_cputype;
+EXPORT_SYMBOL(m68k_machtype);
+EXPORT_SYMBOL(m68k_cputype);
 unsigned long m68k_fputype;
 unsigned long m68k_mmutype;
 #ifdef CONFIG_VME
 unsigned long vme_brdtype;
+EXPORT_SYMBOL(vme_brdtype);
 #endif
 
 int m68k_is040or060;
+EXPORT_SYMBOL(m68k_is040or060);
 
 extern int end;
 extern unsigned long availmem;
 
 int m68k_num_memory;
 int m68k_realnum_memory;
+EXPORT_SYMBOL(m68k_realnum_memory);
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
 unsigned long m68k_memoffset;
+EXPORT_SYMBOL(m68k_memoffset);
+#endif
 struct mem_info m68k_memory[NUM_MEMINFO];
+EXPORT_SYMBOL(m68k_memory);
 
 static struct mem_info m68k_ramdisk;
 
 static char m68k_command_line[CL_SIZE];
 
 char m68k_debug_device[6] = "";
+EXPORT_SYMBOL(m68k_debug_device);
 
-void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
+void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void) __initdata = NULL;
 void (*mach_get_model) (char *model);
@@ -72,10 +82,14 @@
 /* machine dependent timer functions */
 unsigned long (*mach_gettimeoffset) (void);
 int (*mach_hwclk) (int, struct rtc_time*);
+EXPORT_SYMBOL(mach_hwclk);
 int (*mach_set_clock_mmss) (unsigned long);
 unsigned int (*mach_get_ss)(void);
 int (*mach_get_rtc_pll)(struct rtc_pll_info *);
 int (*mach_set_rtc_pll)(struct rtc_pll_info *);
+EXPORT_SYMBOL(mach_get_ss);
+EXPORT_SYMBOL(mach_get_rtc_pll);
+EXPORT_SYMBOL(mach_set_rtc_pll);
 void (*mach_reset)( void );
 void (*mach_halt)( void );
 void (*mach_power_off)( void );
@@ -89,6 +103,7 @@
 #endif
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
 void (*mach_beep)(unsigned int, unsigned int);
+EXPORT_SYMBOL(mach_beep);
 #endif
 #if defined(CONFIG_ISA) && defined(MULTI_ISA)
 int isa_type;
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 28b2fef..2a599c3 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -21,6 +21,7 @@
 
 #include <asm/machdep.h>
 #include <asm/io.h>
+#include <asm/irq_regs.h>
 
 #include <linux/time.h>
 #include <linux/timex.h>
@@ -37,13 +38,13 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 #ifdef CONFIG_HEARTBEAT
 	/* use power LED as a heartbeat instead -- much more useful
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 4569406..759fa244 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -326,13 +326,13 @@
 
 	switch (wbs & WBSIZ_040) {
 	case BA_SIZE_BYTE:
-		res = put_user(wbd & 0xff, (char *)wba);
+		res = put_user(wbd & 0xff, (char __user *)wba);
 		break;
 	case BA_SIZE_WORD:
-		res = put_user(wbd & 0xffff, (short *)wba);
+		res = put_user(wbd & 0xffff, (short __user *)wba);
 		break;
 	case BA_SIZE_LONG:
-		res = put_user(wbd, (int *)wba);
+		res = put_user(wbd, (int __user *)wba);
 		break;
 	}
 
diff --git a/arch/m68k/lib/string.c b/arch/m68k/lib/string.c
index b92b89e..891e134 100644
--- a/arch/m68k/lib/string.c
+++ b/arch/m68k/lib/string.c
@@ -1,6 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
 
-#include <linux/types.h>
+#define __IN_STRING_C
+
 #include <linux/module.h>
+#include <linux/string.h>
+
+char *strcpy(char *dest, const char *src)
+{
+	return __kernel_strcpy(dest, src);
+}
+EXPORT_SYMBOL(strcpy);
 
 void *memset(void *s, int c, size_t count)
 {
diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c
index 1bc188c..865f9fb 100644
--- a/arch/m68k/lib/uaccess.c
+++ b/arch/m68k/lib/uaccess.c
@@ -84,7 +84,7 @@
 		"	.even\n"
 		"20:	lsl.l	#2,%0\n"
 		"50:	add.l	%5,%0\n"
-		"	jra	7b\n"
+		"	jra	8b\n"
 		"	.previous\n"
 		"\n"
 		"	.section __ex_table,\"a\"\n"
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index 6eaa881..a1c7ec7 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -25,7 +25,7 @@
 int baboon_present,baboon_active;
 volatile struct baboon *baboon;
 
-irqreturn_t baboon_irq(int, void *, struct pt_regs *);
+irqreturn_t baboon_irq(int, void *);
 
 #if 0
 extern int macide_ack_intr(struct ata_channel *);
@@ -64,7 +64,7 @@
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-irqreturn_t baboon_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t baboon_irq(int irq, void *dev_id)
 {
 	int irq_bit,i;
 	unsigned char events;
@@ -81,7 +81,7 @@
 	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
 	        if (events & irq_bit/* & baboon_active*/) {
 			baboon_active &= ~irq_bit;
-			m68k_handle_int(IRQ_BABOON_0 + i, regs);
+			m68k_handle_int(IRQ_BABOON_0 + i);
 			baboon_active |= irq_bit;
 			baboon->mb_ifr &= ~irq_bit;
 		}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 85dda10..562b38d 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -72,7 +72,7 @@
 extern void iop_preinit(void);
 extern void iop_init(void);
 extern void via_init(void);
-extern void via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *));
+extern void via_init_clock(irq_handler_t func);
 extern void via_flush_cache(void);
 extern void oss_init(void);
 extern void psc_init(void);
@@ -88,7 +88,7 @@
 
 static void mac_get_model(char *str);
 
-static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
+static void mac_sched_init(irq_handler_t vector)
 {
 	via_init_clock(vector);
 }
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index bc657b1..0cea21f 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -132,7 +132,7 @@
 
 struct listener {
 	const char *devname;
-	void (*handler)(struct iop_msg *, struct pt_regs *);
+	void (*handler)(struct iop_msg *);
 };
 
 /*
@@ -152,7 +152,7 @@
 static struct iop_msg *iop_send_queue[NUM_IOPS][NUM_IOP_CHAN];
 static struct listener iop_listeners[NUM_IOPS][NUM_IOP_CHAN];
 
-irqreturn_t iop_ism_irq(int, void *, struct pt_regs *);
+irqreturn_t iop_ism_irq(int, void *);
 
 extern void oss_irq_enable(int);
 
@@ -342,7 +342,7 @@
  */
 
 int iop_listen(uint iop_num, uint chan,
-		void (*handler)(struct iop_msg *, struct pt_regs *),
+		void (*handler)(struct iop_msg *),
 		const char *devname)
 {
 	if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return -EINVAL;
@@ -407,7 +407,7 @@
  * has gone into the IOP_MSG_COMPLETE state.
  */
 
-static void iop_handle_send(uint iop_num, uint chan, struct pt_regs *regs)
+static void iop_handle_send(uint iop_num, uint chan)
 {
 	volatile struct mac_iop *iop = iop_base[iop_num];
 	struct iop_msg *msg,*msg2;
@@ -426,7 +426,7 @@
 	for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) {
 		msg->reply[i] = iop_readb(iop, offset);
 	}
-	if (msg->handler) (*msg->handler)(msg, regs);
+	if (msg->handler) (*msg->handler)(msg);
 	msg2 = msg;
 	msg = msg->next;
 	iop_free_msg(msg2);
@@ -440,7 +440,7 @@
  * gone into the IOP_MSG_NEW state.
  */
 
-static void iop_handle_recv(uint iop_num, uint chan, struct pt_regs *regs)
+static void iop_handle_recv(uint iop_num, uint chan)
 {
 	volatile struct mac_iop *iop = iop_base[iop_num];
 	int i,offset;
@@ -468,7 +468,7 @@
 	/* the message ourselves to avoid possible stalls.         */
 
 	if (msg->handler) {
-		(*msg->handler)(msg, regs);
+		(*msg->handler)(msg);
 	} else {
 #ifdef DEBUG_IOP
 		printk("iop_handle_recv: unclaimed message on iop %d channel %d\n", iop_num, chan);
@@ -492,7 +492,7 @@
 
 int iop_send_message(uint iop_num, uint chan, void *privdata,
 		      uint msg_len, __u8 *msg_data,
-		      void (*handler)(struct iop_msg *, struct pt_regs *))
+		      void (*handler)(struct iop_msg *))
 {
 	struct iop_msg *msg, *q;
 
@@ -584,7 +584,7 @@
  * Handle an ISM IOP interrupt
  */
 
-irqreturn_t iop_ism_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t iop_ism_irq(int irq, void *dev_id)
 {
 	uint iop_num = (uint) dev_id;
 	volatile struct mac_iop *iop = iop_base[iop_num];
@@ -608,7 +608,7 @@
 			printk(" %02X", state);
 #endif
 			if (state == IOP_MSG_COMPLETE) {
-				iop_handle_send(iop_num, i, regs);
+				iop_handle_send(iop_num, i);
 			}
 		}
 #ifdef DEBUG_IOP
@@ -628,7 +628,7 @@
 			printk(" %02X", state);
 #endif
 			if (state == IOP_MSG_NEW) {
-				iop_handle_recv(iop_num, i, regs);
+				iop_handle_recv(iop_num, i);
 			}
 		}
 #ifdef DEBUG_IOP
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 694b14b..f6fcd75 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -133,6 +133,7 @@
 #include <asm/hwtest.h>
 #include <asm/errno.h>
 #include <asm/macints.h>
+#include <asm/irq_regs.h>
 
 #define DEBUG_SPURIOUS
 #define SHUTUP_SONIC
@@ -208,8 +209,8 @@
  * console_loglevel determines NMI handler function
  */
 
-irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *);
-irqreturn_t mac_debug_handler(int, void *, struct pt_regs *);
+irqreturn_t mac_nmi_handler(int, void *);
+irqreturn_t mac_debug_handler(int, void *);
 
 /* #define DEBUG_MACINTS */
 
@@ -393,7 +394,7 @@
 
 static int num_debug[8];
 
-irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mac_debug_handler(int irq, void *dev_id)
 {
 	if (num_debug[irq] < 10) {
 		printk("DEBUG: Unexpected IRQ %d\n", irq);
@@ -405,7 +406,7 @@
 static int in_nmi;
 static volatile int nmi_hold;
 
-irqreturn_t mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t mac_nmi_handler(int irq, void *dev_id)
 {
 	int i;
 	/*
@@ -432,6 +433,7 @@
 
 	if (console_loglevel >= 8) {
 #if 0
+		struct pt_regs *fp = get_irq_regs();
 		show_state();
 		printk("PC: %08lx\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
 		printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
@@ -479,7 +481,7 @@
  * here is cleaner than hacking it into drivers/char/macserial.c.
  */
 
-void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs)
+void mac_scc_dispatch(int irq, void *dev_id)
 {
 	volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
 	unsigned char reg;
@@ -504,7 +506,7 @@
 	/* pretty much kill the system.                 */
 
 	if (reg & 0x38)
-		m68k_handle_int(IRQ_SCCA, regs);
+		m68k_handle_int(IRQ_SCCA);
 	if (reg & 0x07)
-		m68k_handle_int(IRQ_SCCB, regs);
+		m68k_handle_int(IRQ_SCCB);
 }
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 63e0436..6369081 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -30,11 +30,11 @@
 int oss_present;
 volatile struct mac_oss *oss;
 
-irqreturn_t oss_irq(int, void *, struct pt_regs *);
-irqreturn_t oss_nubus_irq(int, void *, struct pt_regs *);
+irqreturn_t oss_irq(int, void *);
+irqreturn_t oss_nubus_irq(int, void *);
 
-extern irqreturn_t via1_irq(int, void *, struct pt_regs *);
-extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
+extern irqreturn_t via1_irq(int, void *);
+extern irqreturn_t mac_scc_dispatch(int, void *);
 
 /*
  * Initialize the OSS
@@ -92,7 +92,7 @@
  * and SCSI; everything else is routed to its own autovector IRQ.
  */
 
-irqreturn_t oss_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t oss_irq(int irq, void *dev_id)
 {
 	int events;
 
@@ -113,7 +113,7 @@
 		oss->irq_pending &= ~OSS_IP_SOUND;
 	} else if (events & OSS_IP_SCSI) {
 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
-		m68k_handle_int(IRQ_MAC_SCSI, regs);
+		m68k_handle_int(IRQ_MAC_SCSI);
 		oss->irq_pending &= ~OSS_IP_SCSI;
 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
 	} else {
@@ -128,7 +128,7 @@
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-irqreturn_t oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t oss_nubus_irq(int irq, void *dev_id)
 {
 	int events, irq_bit, i;
 
@@ -146,7 +146,7 @@
 	for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
 		if (events & irq_bit) {
 			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
-			m68k_handle_int(NUBUS_SOURCE_BASE + i, regs);
+			m68k_handle_int(NUBUS_SOURCE_BASE + i);
 			oss->irq_pending &= ~irq_bit;
 			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
 		}
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index e262180..15378a5 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -30,7 +30,7 @@
 int psc_present;
 volatile __u8 *psc;
 
-irqreturn_t psc_irq(int, void *, struct pt_regs *);
+irqreturn_t psc_irq(int, void *);
 
 /*
  * Debugging dump, used in various places to see what's going on.
@@ -127,7 +127,7 @@
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-irqreturn_t psc_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t psc_irq(int irq, void *dev_id)
 {
 	int pIFR	= pIFRbase + ((int) dev_id);
 	int pIER	= pIERbase + ((int) dev_id);
@@ -149,7 +149,7 @@
 	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
 	        if (events & irq_bit) {
 			psc_write_byte(pIER, irq_bit);
-			m68k_handle_int(base_irq + i, regs);
+			m68k_handle_int(base_irq + i);
 			psc_write_byte(pIFR, irq_bit);
 			psc_write_byte(pIER, irq_bit | 0x80);
 		}
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index c4aa345..e27735b 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -63,14 +63,14 @@
 static int  nubus_active;
 
 void via_debug_dump(void);
-irqreturn_t via1_irq(int, void *, struct pt_regs *);
-irqreturn_t via2_irq(int, void *, struct pt_regs *);
-irqreturn_t via_nubus_irq(int, void *, struct pt_regs *);
+irqreturn_t via1_irq(int, void *);
+irqreturn_t via2_irq(int, void *);
+irqreturn_t via_nubus_irq(int, void *);
 void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
-extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
+extern irqreturn_t mac_scc_dispatch(int, void *);
 extern int oss_present;
 
 /*
@@ -235,7 +235,7 @@
  * Start the 100 Hz clock
  */
 
-void __init via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *))
+void __init via_init_clock(irq_handler_t func)
 {
 	via1[vACR] |= 0x40;
 	via1[vT1LL] = MAC_CLOCK_LOW;
@@ -412,7 +412,7 @@
  * the machspec interrupt number after clearing the interrupt.
  */
 
-irqreturn_t via1_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t via1_irq(int irq, void *dev_id)
 {
 	int irq_bit, i;
 	unsigned char events, mask;
@@ -424,7 +424,7 @@
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
 		if (events & irq_bit) {
 			via1[vIER] = irq_bit;
-			m68k_handle_int(VIA1_SOURCE_BASE + i, regs);
+			m68k_handle_int(VIA1_SOURCE_BASE + i);
 			via1[vIFR] = irq_bit;
 			via1[vIER] = irq_bit | 0x80;
 		}
@@ -439,14 +439,14 @@
 		/* No, it won't be set. that's why we're doing this. */
 		via_irq_disable(IRQ_MAC_NUBUS);
 		via_irq_clear(IRQ_MAC_NUBUS);
-		m68k_handle_int(IRQ_MAC_NUBUS, regs);
+		m68k_handle_int(IRQ_MAC_NUBUS);
 		via_irq_enable(IRQ_MAC_NUBUS);
 	}
 #endif
 	return IRQ_HANDLED;
 }
 
-irqreturn_t via2_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t via2_irq(int irq, void *dev_id)
 {
 	int irq_bit, i;
 	unsigned char events, mask;
@@ -459,7 +459,7 @@
 		if (events & irq_bit) {
 			via2[gIER] = irq_bit;
 			via2[gIFR] = irq_bit | rbv_clear;
-			m68k_handle_int(VIA2_SOURCE_BASE + i, regs);
+			m68k_handle_int(VIA2_SOURCE_BASE + i);
 			via2[gIER] = irq_bit | 0x80;
 		}
 	return IRQ_HANDLED;
@@ -470,7 +470,7 @@
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-irqreturn_t via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t via_nubus_irq(int irq, void *dev_id)
 {
 	int irq_bit, i;
 	unsigned char events;
@@ -481,7 +481,7 @@
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
 		if (events & irq_bit) {
 			via_irq_disable(NUBUS_SOURCE_BASE + i);
-			m68k_handle_int(NUBUS_SOURCE_BASE + i, regs);
+			m68k_handle_int(NUBUS_SOURCE_BASE + i);
 			via_irq_enable(NUBUS_SOURCE_BASE + i);
 		}
 	}
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index f46f049..b54ef17 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -7,6 +7,7 @@
  *	     used by other architectures		/Roman Zippel
  */
 
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -219,6 +220,7 @@
 
 	return (void __iomem *)retaddr;
 }
+EXPORT_SYMBOL(__ioremap);
 
 /*
  * Unmap a ioremap()ed region again
@@ -234,6 +236,7 @@
 	free_io_area((__force void *)addr);
 #endif
 }
+EXPORT_SYMBOL(iounmap);
 
 /*
  * __iounmap unmaps nearly everything, so be careful
@@ -360,3 +363,4 @@
 
 	flush_tlb_all();
 }
+EXPORT_SYMBOL(kernel_set_cachemode);
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index a0c095e..0f88812 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 1995  Hamish Macdonald
  */
 
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -157,9 +158,8 @@
 
 	return -1;
 }
-#endif
+EXPORT_SYMBOL(mm_vtop);
 
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
 unsigned long mm_ptov (unsigned long paddr)
 {
 	int i = 0;
@@ -185,6 +185,7 @@
 #endif
 	return -1;
 }
+EXPORT_SYMBOL(mm_ptov);
 #endif
 
 /* invalidate page in both caches */
@@ -298,6 +299,7 @@
 	mach_l2_flush(0);
 #endif
 }
+EXPORT_SYMBOL(cache_clear);	/* probably can be unexported */
 
 
 /*
@@ -350,6 +352,7 @@
 	mach_l2_flush(1);
 #endif
 }
+EXPORT_SYMBOL(cache_push);	/* probably can be unexported */
 
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
 int mm_end_of_chunk (unsigned long addr, int len)
@@ -361,4 +364,5 @@
 			return 1;
 	return 0;
 }
+EXPORT_SYMBOL(mm_end_of_chunk);
 #endif
diff --git a/arch/m68k/mm/sun3kmap.c b/arch/m68k/mm/sun3kmap.c
index 7f0d86f..1af24cb 100644
--- a/arch/m68k/mm/sun3kmap.c
+++ b/arch/m68k/mm/sun3kmap.c
@@ -8,6 +8,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -59,7 +60,7 @@
 	}
 }
 
-void *sun3_ioremap(unsigned long phys, unsigned long size,
+void __iomem *sun3_ioremap(unsigned long phys, unsigned long size,
 		   unsigned long type)
 {
 	struct vm_struct *area;
@@ -101,22 +102,24 @@
 		virt += seg_pages * PAGE_SIZE;
 	}
 
-	return (void *)ret;
+	return (void __iomem *)ret;
 
 }
 
 
-void *__ioremap(unsigned long phys, unsigned long size, int cache)
+void __iomem *__ioremap(unsigned long phys, unsigned long size, int cache)
 {
 
 	return sun3_ioremap(phys, size, SUN3_PAGE_TYPE_IO);
 
 }
+EXPORT_SYMBOL(__ioremap);
 
-void iounmap(void *addr)
+void iounmap(void __iomem *addr)
 {
 	vfree((void *)(PAGE_MASK & (unsigned long)addr));
 }
+EXPORT_SYMBOL(iounmap);
 
 /* sun3_map_test(addr, val) -- Reads a byte from addr, storing to val,
  * trapping the potential read fault.  Returns 0 if the access faulted,
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 0cd0e5b..4a7df9c 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -38,7 +38,7 @@
 
 static void mvme147_get_model(char *model);
 static int  mvme147_get_hardware_list(char *buffer);
-extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void mvme147_sched_init(irq_handler_t handler);
 extern unsigned long mvme147_gettimeoffset (void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern int mvme147_set_clock_mmss (unsigned long);
@@ -51,7 +51,7 @@
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via mvme147_process_int() */
 
-irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
+irq_handler_t tick_handler;
 
 
 int mvme147_parse_bootinfo(const struct bi_record *bi)
@@ -114,15 +114,15 @@
 
 /* Using pcc tick timer 1 */
 
-static irqreturn_t mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 {
 	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
 	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
-	return tick_handler(irq, dev_id, fp);
+	return tick_handler(irq, dev_id);
 }
 
 
-void mvme147_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+void mvme147_sched_init (irq_handler_t timer_routine)
 {
 	tick_handler = timer_routine;
 	request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index ce2727e..c829ebb 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -42,7 +42,7 @@
 
 static void mvme16x_get_model(char *model);
 static int  mvme16x_get_hardware_list(char *buffer);
-extern void mvme16x_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void mvme16x_sched_init(irq_handler_t handler);
 extern unsigned long mvme16x_gettimeoffset (void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern int mvme16x_set_clock_mmss (unsigned long);
@@ -54,7 +54,7 @@
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via mvme16x_process_int() */
 
-static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
+static irq_handler_t tick_handler;
 
 
 unsigned short mvme16x_config;
@@ -190,7 +190,7 @@
     }
 }
 
-static irqreturn_t mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
 {
 	p_bdid p = &mvme_bdid;
 	unsigned long *new = (unsigned long *)vectors;
@@ -218,13 +218,13 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 {
     *(volatile unsigned char *)0xfff4201b |= 8;
-    return tick_handler(irq, dev_id, fp);
+    return tick_handler(irq, dev_id);
 }
 
-void mvme16x_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+void mvme16x_sched_init (irq_handler_t timer_routine)
 {
     p_bdid p = &mvme_bdid;
     int irq;
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 9a18278..92f873c 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -39,7 +39,7 @@
 extern void q40_init_IRQ (void);
 static void q40_get_model(char *model);
 static int  q40_get_hardware_list(char *buffer);
-extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void q40_sched_init(irq_handler_t handler);
 
 extern unsigned long q40_gettimeoffset (void);
 extern int q40_hwclk (int, struct rtc_time *);
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 472f41c..31cc07d 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -125,9 +125,9 @@
 	sound_ticks = ticks << 1;
 }
 
-static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);
+static irq_handler_t q40_timer_routine;
 
-static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
+static irqreturn_t q40_timer_int (int irq, void * dev)
 {
 	ql_ticks = ql_ticks ? 0 : 1;
 	if (sound_ticks) {
@@ -138,11 +138,11 @@
 	}
 
 	if (!ql_ticks)
-		q40_timer_routine(irq, dev, regs);
+		q40_timer_routine(irq, dev);
 	return IRQ_HANDLED;
 }
 
-void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+void q40_sched_init (irq_handler_t timer_routine)
 {
 	int timer_irq;
 
@@ -218,11 +218,11 @@
 	switch (irq) {
 	case 4:
 	case 6:
-		m68k_handle_int(Q40_IRQ_SAMPLE, fp);
+		__m68k_handle_int(Q40_IRQ_SAMPLE, fp);
 		return;
 	}
 	if (mir & Q40_IRQ_FRAME_MASK) {
-		m68k_handle_int(Q40_IRQ_FRAME, fp);
+		__m68k_handle_int(Q40_IRQ_FRAME, fp);
 		master_outb(-1, FRAME_CLEAR_REG);
 	}
 	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
@@ -257,7 +257,7 @@
 					goto iirq;
 				}
 				q40_state[irq] |= IRQ_INPROGRESS;
-				m68k_handle_int(irq, fp);
+				__m68k_handle_int(irq, fp);
 				q40_state[irq] &= ~IRQ_INPROGRESS;
 
 				/* naively enable everything, if that fails than    */
@@ -288,7 +288,7 @@
 	mir = master_inb(IIRQ_REG);
 	/* should test whether keyboard irq is really enabled, doing it in defhand */
 	if (mir & Q40_IRQ_KEYB_MASK)
-		m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
+		__m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
 
 	return;
 }
diff --git a/arch/m68k/sun3/Makefile b/arch/m68k/sun3/Makefile
index 4d4f069..be1a847 100644
--- a/arch/m68k/sun3/Makefile
+++ b/arch/m68k/sun3/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Linux arch/m68k/sun3 source directory
 #
 
-obj-y	:= sun3_ksyms.o sun3ints.o sun3dvma.o sbus.o idprom.o
+obj-y	:= sun3ints.o sun3dvma.o sbus.o idprom.o
 
 obj-$(CONFIG_SUN3) += config.o mmu_emu.o leds.o dvma.o intersil.o
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index d09d03b..4851b84 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -35,7 +35,7 @@
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
 extern unsigned long sun3_gettimeoffset(void);
-extern void sun3_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void sun3_sched_init(irq_handler_t handler);
 extern void sun3_get_model (char* model);
 extern void idprom_init (void);
 extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -162,7 +162,7 @@
 	sun3_bootmem_alloc(memory_start, memory_end);
 }
 
-void __init sun3_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
+void __init sun3_sched_init(irq_handler_t timer_routine)
 {
 	sun3_disable_interrupts();
         intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_DISABLE|INTERSIL_24H_MODE);
diff --git a/arch/m68k/sun3/idprom.c b/arch/m68k/sun3/idprom.c
index 02c1fee..dca6ab6 100644
--- a/arch/m68k/sun3/idprom.c
+++ b/arch/m68k/sun3/idprom.c
@@ -6,6 +6,7 @@
  * Sun3/3x models added by David Monro (davidm@psrg.cs.usyd.edu.au)
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
@@ -16,6 +17,8 @@
 #include <asm/machines.h>  /* Fun with Sun released architectures. */
 
 struct idprom *idprom;
+EXPORT_SYMBOL(idprom);
+
 static struct idprom idprom_buffer;
 
 /* Here is the master table of Sun machines which use some implementation
diff --git a/arch/m68k/sun3/sun3_ksyms.c b/arch/m68k/sun3/sun3_ksyms.c
deleted file mode 100644
index 43e5a9a..0000000
--- a/arch/m68k/sun3/sun3_ksyms.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/dvma.h>
-#include <asm/idprom.h>
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(dvma_map_align);
-EXPORT_SYMBOL(dvma_unmap);
-EXPORT_SYMBOL(dvma_malloc_align);
-EXPORT_SYMBOL(dvma_free);
-EXPORT_SYMBOL(idprom);
diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c
index a2bc2da..8709677 100644
--- a/arch/m68k/sun3/sun3dvma.c
+++ b/arch/m68k/sun3/sun3dvma.c
@@ -6,6 +6,7 @@
  * Contains common routines for sun3/sun3x DVMA management.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/list.h>
@@ -312,6 +313,7 @@
 	BUG();
 	return 0;
 }
+EXPORT_SYMBOL(dvma_map_align);
 
 void dvma_unmap(void *baddr)
 {
@@ -327,7 +329,7 @@
 	return;
 
 }
-
+EXPORT_SYMBOL(dvma_unmap);
 
 void *dvma_malloc_align(unsigned long len, unsigned long align)
 {
@@ -367,6 +369,7 @@
 	return (void *)vaddr;
 
 }
+EXPORT_SYMBOL(dvma_malloc_align);
 
 void dvma_free(void *vaddr)
 {
@@ -374,3 +377,4 @@
 	return;
 
 }
+EXPORT_SYMBOL(dvma_free);
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index dc4ea7e..baf74e8 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -15,6 +15,7 @@
 #include <asm/intersil.h>
 #include <asm/oplib.h>
 #include <asm/sun3ints.h>
+#include <asm/irq_regs.h>
 #include <linux/seq_file.h>
 
 extern void sun3_leds (unsigned char);
@@ -48,7 +49,7 @@
 	*sun3_intreg &= ~(1 << irq);
 }
 
-static irqreturn_t sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_int7(int irq, void *dev_id)
 {
 	*sun3_intreg |=  (1 << irq);
 	if (!(kstat_cpu(0).irqs[irq] % 2000))
@@ -56,7 +57,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_int5(int irq, void *dev_id)
 {
 #ifdef CONFIG_SUN3
 	intersil_clear();
@@ -67,14 +68,14 @@
 #endif
         do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(fp));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
         if (!(kstat_cpu(0).irqs[irq] % 20))
                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_vec255(int irq, void *dev_id)
 {
 //	intersil_clear();
 	return IRQ_HANDLED;
@@ -84,7 +85,7 @@
 {
         *sun3_intreg &= ~(1 << irq);
 
-	m68k_handle_int(irq, fp);
+	__m68k_handle_int(irq, fp);
 }
 
 static struct irq_controller sun3_irq_controller = {
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index 6f4204f..f5eaafb 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -90,7 +90,7 @@
 }
 #endif
 
-void __init sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
+void __init sun3x_sched_init(irq_handler_t vector)
 {
 
 	sun3_disable_interrupts();
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
index e7e43b4..6909e12 100644
--- a/arch/m68k/sun3x/time.h
+++ b/arch/m68k/sun3x/time.h
@@ -3,7 +3,7 @@
 
 extern int sun3x_hwclk(int set, struct rtc_time *t);
 unsigned long sun3x_gettimeoffset (void);
-void sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
+void sun3x_sched_init(irq_handler_t vector);
 
 struct mostek_dt {
 	volatile unsigned char csr;
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 617e43e..4603f4f 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -296,10 +296,39 @@
 	.long sys_mq_notify	/* 275 */
 	.long sys_mq_getsetattr
 	.long sys_waitid
-	.long sys_ni_syscall	/* sys_setaltroot */
-	.long sys_ni_syscall	/* sys_add_key */
-	.long sys_ni_syscall	/* 280 */ /* sys_request_key */
-	.long sys_ni_syscall	/* sys_keyctl */
+	.long sys_ni_syscall	/* for sys_vserver */
+	.long sys_add_key
+	.long sys_request_key	/* 280 */
+	.long sys_keyctl
+	.long sys_ioprio_set
+	.long sys_ioprio_get
+	.long sys_inotify_init
+	.long sys_inotify_add_watch	/* 285 */
+	.long sys_inotify_rm_watch
+	.long sys_migrate_pages
+	.long sys_openat
+	.long sys_mkdirat
+	.long sys_mknodat		/* 290 */
+	.long sys_fchownat
+	.long sys_futimesat
+	.long sys_fstatat64
+	.long sys_unlinkat
+	.long sys_renameat		/* 295 */
+	.long sys_linkat
+	.long sys_symlinkat
+	.long sys_readlinkat
+	.long sys_fchmodat
+	.long sys_faccessat		/* 300 */
+	.long sys_ni_syscall		/* Reserved for pselect6 */
+	.long sys_ni_syscall		/* Reserved for ppoll */
+	.long sys_unshare
+	.long sys_set_robust_list
+	.long sys_get_robust_list	/* 305 */
+	.long sys_splice
+	.long sys_sync_file_range
+	.long sys_tee
+	.long sys_vmsplice
+	.long sys_move_pages		/* 310 */
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 8a49884..14af6cc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1010,11 +1010,6 @@
 config ARC32
 	bool
 
-config AU1X00_USB_DEVICE
-	bool
-	depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
-	default n
-
 config BOOT_ELF32
 	bool
 
@@ -1465,6 +1460,18 @@
 	  the option of an MT-enabled processor this option will be the only
 	  option in this menu.
 
+config MIPS_MT_SMP
+	bool "Use 1 TC on each available VPE for SMP"
+	depends on SYS_SUPPORTS_MULTITHREADING
+	select CPU_MIPSR2_IRQ_VI
+	select CPU_MIPSR2_SRS
+	select MIPS_MT
+	select SMP
+	select SYS_SUPPORTS_SMP
+	help
+	  This is a kernel model which is also known a VSMP or lately
+	  has been marketesed into SMVP.
+
 config MIPS_MT_SMTC
 	bool "SMTC: Use all TCs on all VPEs for SMP"
 	depends on CPU_MIPS32_R2
@@ -1479,18 +1486,6 @@
 	  This is a kernel model which is known a SMTC or lately has been
 	  marketesed into SMVP.
 
-config MIPS_MT_SMP
-	bool "Use 1 TC on each available VPE for SMP"
-	depends on SYS_SUPPORTS_MULTITHREADING
-	select CPU_MIPSR2_IRQ_VI
-	select CPU_MIPSR2_SRS
-	select MIPS_MT
-	select SMP
-	select SYS_SUPPORTS_SMP
-	help
-	  This is a kernel model which is also known a VSMP or lately
-	  has been marketesed into SMVP.
-
 config MIPS_VPE_LOADER
 	bool "VPE loader support."
 	depends on SYS_SUPPORTS_MULTITHREADING
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 2124350..641aa30 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -91,8 +91,17 @@
 # carefully avoid to add it redundantly because gcc 3.3/3.4 complains
 # when fed the toolchain default!
 #
-cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB -D__MIPSEB__)
-cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL -D__MIPSEL__)
+# Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of
+# 2006-10-10 don't properly change the the predefined symbols if -EB / -EL
+# are used, so we kludge that here.  A bug has been filed at
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413.
+#
+undef-all += -UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__
+undef-all += -UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__
+predef-be += -DMIPSEB -D_MIPSEB -D__MIPSEB -D__MIPSEB__
+predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__
+cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
+cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
 
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= $(call cc-option,-mno-sched-prolog) \
 				   -fno-omit-frame-pointer
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
index bf682f5..4c35525 100644
--- a/arch/mips/au1000/common/Makefile
+++ b/arch/mips/au1000/common/Makefile
@@ -10,6 +10,5 @@
 	au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
 	sleeper.o cputable.o dma.o dbdma.o gpio.o
 
-obj-$(CONFIG_AU1X00_USB_DEVICE)	+= usbdev.o
 obj-$(CONFIG_KGDB)		+= dbg_io.o
 obj-$(CONFIG_PCI)		+= pci.o
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
index c4fae8f..626de44 100644
--- a/arch/mips/au1000/common/dbdma.c
+++ b/arch/mips/au1000/common/dbdma.c
@@ -849,7 +849,7 @@
 EXPORT_SYMBOL(au1xxx_dbdma_chan_free);
 
 static irqreturn_t
-dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+dbdma_interrupt(int irq, void *dev_id)
 {
 	u32 intstat;
 	u32 chan_index;
diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c
index fb7c47c..c78260d 100644
--- a/arch/mips/au1000/common/dma.c
+++ b/arch/mips/au1000/common/dma.c
@@ -160,7 +160,7 @@
  * Requests the DMA done IRQ if irqhandler != NULL.
  */
 int request_au1000_dma(int dev_id, const char *dev_str,
-		       irqreturn_t (*irqhandler)(int, void *, struct pt_regs *),
+		       irq_handler_t irqhandler,
 		       unsigned long irqflags,
 		       void *irq_dev_id)
 {
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 316722e..2abe132 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -67,7 +67,7 @@
 
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
-extern void mips_timer_interrupt(struct pt_regs *regs);
+extern void mips_timer_interrupt(void);
 
 static void setup_local_irq(unsigned int irq, int type, int int_req);
 static unsigned int startup_irq(unsigned int irq);
@@ -81,10 +81,6 @@
 
 void	(*board_init_irq)(void);
 
-#ifdef CONFIG_PM
-extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
-#endif
-
 static DEFINE_SPINLOCK(irq_lock);
 
 
@@ -292,7 +288,7 @@
 };
 
 #ifdef CONFIG_PM
-void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *))
+void startup_match20_interrupt(irq_handler_t handler)
 {
 	struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT];
 
@@ -501,14 +497,15 @@
  * intcX_reqX_irqdispatch().
  */
 
-void intc0_req0_irqdispatch(struct pt_regs *regs)
+static void intc0_req0_irqdispatch(void)
 {
 	int irq = 0;
 	static unsigned long intc0_req0 = 0;
 
 	intc0_req0 |= au_readl(IC0_REQ0INT);
 
-	if (!intc0_req0) return;
+	if (!intc0_req0)
+		return;
 #ifdef AU1000_USB_DEV_REQ_INT
 	/*
 	 * Because of the tight timing of SETUP token to reply
@@ -517,28 +514,29 @@
 	 */
 	if ((intc0_req0 & (1<<AU1000_USB_DEV_REQ_INT))) {
 		intc0_req0 &= ~(1<<AU1000_USB_DEV_REQ_INT);
-		do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
+		do_IRQ(AU1000_USB_DEV_REQ_INT);
 		return;
 	}
 #endif
 	irq = au_ffs(intc0_req0) - 1;
 	intc0_req0 &= ~(1<<irq);
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
 
-void intc0_req1_irqdispatch(struct pt_regs *regs)
+static void intc0_req1_irqdispatch(void)
 {
 	int irq = 0;
 	static unsigned long intc0_req1 = 0;
 
 	intc0_req1 |= au_readl(IC0_REQ1INT);
 
-	if (!intc0_req1) return;
+	if (!intc0_req1)
+		return;
 
 	irq = au_ffs(intc0_req1) - 1;
 	intc0_req1 &= ~(1<<irq);
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
 
@@ -546,35 +544,37 @@
  * Interrupt Controller 1:
  * interrupts 32 - 63
  */
-void intc1_req0_irqdispatch(struct pt_regs *regs)
+static void intc1_req0_irqdispatch(void)
 {
 	int irq = 0;
 	static unsigned long intc1_req0 = 0;
 
 	intc1_req0 |= au_readl(IC1_REQ0INT);
 
-	if (!intc1_req0) return;
+	if (!intc1_req0)
+		return;
 
 	irq = au_ffs(intc1_req0) - 1;
 	intc1_req0 &= ~(1<<irq);
 	irq += 32;
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
 
-void intc1_req1_irqdispatch(struct pt_regs *regs)
+static void intc1_req1_irqdispatch(void)
 {
 	int irq = 0;
 	static unsigned long intc1_req1 = 0;
 
 	intc1_req1 |= au_readl(IC1_REQ1INT);
 
-	if (!intc1_req1) return;
+	if (!intc1_req1)
+		return;
 
 	irq = au_ffs(intc1_req1) - 1;
 	intc1_req1 &= ~(1<<irq);
 	irq += 32;
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
 #ifdef CONFIG_PM
@@ -660,20 +660,20 @@
 }
 #endif /* CONFIG_PM */
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
 
 	if (pending & CAUSEF_IP7)
-		mips_timer_interrupt(regs);
+		mips_timer_interrupt();
 	else if (pending & CAUSEF_IP2)
-		intc0_req0_irqdispatch(regs);
+		intc0_req0_irqdispatch();
 	else if (pending & CAUSEF_IP3)
-		intc0_req1_irqdispatch(regs);
+		intc0_req1_irqdispatch();
 	else if (pending & CAUSEF_IP4)
-		intc1_req0_irqdispatch(regs);
+		intc1_req0_irqdispatch();
 	else if (pending  & CAUSEF_IP5)
-		intc1_req1_irqdispatch(regs);
+		intc1_req1_irqdispatch();
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index 0a067f3..94f0919 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -41,7 +41,6 @@
 
 #include <asm/compiler.h>
 #include <asm/mipsregs.h>
-#include <asm/ptrace.h>
 #include <asm/time.h>
 #include <asm/div64.h>
 #include <asm/mach-au1x00/au1000.h>
@@ -62,7 +61,7 @@
 #error "unsupported HZ value! Must be in [100,1000]"
 #endif
 #define MATCH20_INC (328*100/HZ) /* magic number 328 is for HZ=100... */
-extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void startup_match20_interrupt(irq_handler_t handler);
 static unsigned long last_pc0, last_match20;
 #endif
 
@@ -79,7 +78,8 @@
  * is provably more robust.
  */
 unsigned long wtimer;
-void mips_timer_interrupt(struct pt_regs *regs)
+
+void mips_timer_interrupt(void)
 {
 	int irq = 63;
 	unsigned long count;
@@ -98,7 +98,7 @@
 		kstat_this_cpu.irqs[irq]++;
 		do_timer(1);
 #ifndef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 		r4k_cur += r4k_offset;
 		ack_r4ktimer(r4k_cur);
@@ -115,7 +115,7 @@
 }
 
 #ifdef CONFIG_PM
-irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t counter0_irq(int irq, void *dev_id)
 {
 	unsigned long pc0;
 	int time_elapsed;
@@ -139,7 +139,7 @@
 	while (time_elapsed > 0) {
 		do_timer(1);
 #ifndef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 		time_elapsed -= MATCH20_INC;
 		last_match20 += MATCH20_INC;
@@ -158,7 +158,7 @@
 		jiffie_drift -= 999;
 		do_timer(1); /* increment jiffies by one */
 #ifndef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 	}
 
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c
deleted file mode 100644
index 63bcb3a..0000000
--- a/arch/mips/au1000/common/usbdev.c
+++ /dev/null
@@ -1,1555 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Au1000 USB Device-Side (device layer)
- *
- * Copyright 2001-2002 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *		stevel@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/smp_lock.h>
-#define DEBUG
-#include <linux/usb.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/au1000.h>
-#include <asm/au1000_dma.h>
-#include <asm/au1000_usbdev.h>
-
-#ifdef DEBUG
-#undef VDEBUG
-#ifdef VDEBUG
-#define vdbg(fmt, arg...) printk(KERN_DEBUG __FILE__ ": " fmt "\n" , ## arg)
-#else
-#define vdbg(fmt, arg...) do {} while (0)
-#endif
-#else
-#define vdbg(fmt, arg...) do {} while (0)
-#endif
-
-#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)
-
-#define EP_FIFO_DEPTH 8
-
-typedef enum {
-	SETUP_STAGE = 0,
-	DATA_STAGE,
-	STATUS_STAGE
-} ep0_stage_t;
-
-typedef struct {
-	int read_fifo;
-	int write_fifo;
-	int ctrl_stat;
-	int read_fifo_status;
-	int write_fifo_status;
-} endpoint_reg_t;
-
-typedef struct {
-	usbdev_pkt_t *head;
-	usbdev_pkt_t *tail;
-	int count;
-} pkt_list_t;
-
-typedef struct {
-	int active;
-	struct usb_endpoint_descriptor *desc;
-	endpoint_reg_t *reg;
-	/* Only one of these are used, unless this is the control ep */
-	pkt_list_t inlist;
-	pkt_list_t outlist;
-	unsigned int indma, outdma; /* DMA channel numbers for IN, OUT */
-	/* following are extracted from endpoint descriptor for easy access */
-	int max_pkt_size;
-	int type;
-	int direction;
-	/* WE assign endpoint addresses! */
-	int address;
-	spinlock_t lock;
-} endpoint_t;
-
-
-static struct usb_dev {
-	endpoint_t ep[6];
-	ep0_stage_t ep0_stage;
-
-	struct usb_device_descriptor *   dev_desc;
-	struct usb_interface_descriptor* if_desc;
-	struct usb_config_descriptor *   conf_desc;
-	u8 *                             full_conf_desc;
-	struct usb_string_descriptor *   str_desc[6];
-
-	/* callback to function layer */
-	void (*func_cb)(usbdev_cb_type_t type, unsigned long arg,
-			void *cb_data);
-	void* cb_data;
-
-	usbdev_state_t state;	// device state
-	int suspended;		// suspended flag
-	int address;		// device address
-	int interface;
-	int num_ep;
-	u8 alternate_setting;
-	u8 configuration;	// configuration value
-	int remote_wakeup_en;
-} usbdev;
-
-
-static endpoint_reg_t ep_reg[] = {
-	// FIFO's 0 and 1 are EP0 default control
-	{USBD_EP0RD, USBD_EP0WR, USBD_EP0CS, USBD_EP0RDSTAT, USBD_EP0WRSTAT },
-	{0},
-	// FIFO 2 is EP2, IN
-	{ -1, USBD_EP2WR, USBD_EP2CS, -1, USBD_EP2WRSTAT },
-	// FIFO 3 is EP3, IN
-	{    -1,     USBD_EP3WR, USBD_EP3CS,     -1,         USBD_EP3WRSTAT },
-	// FIFO 4 is EP4, OUT
-	{USBD_EP4RD,     -1,     USBD_EP4CS, USBD_EP4RDSTAT,     -1         },
-	// FIFO 5 is EP5, OUT
-	{USBD_EP5RD,     -1,     USBD_EP5CS, USBD_EP5RDSTAT,     -1         }
-};
-
-static struct {
-	unsigned int id;
-	const char *str;
-} ep_dma_id[] = {
-	{ DMA_ID_USBDEV_EP0_TX, "USBDev EP0 IN" },
-	{ DMA_ID_USBDEV_EP0_RX, "USBDev EP0 OUT" },
-	{ DMA_ID_USBDEV_EP2_TX, "USBDev EP2 IN" },
-	{ DMA_ID_USBDEV_EP3_TX, "USBDev EP3 IN" },
-	{ DMA_ID_USBDEV_EP4_RX, "USBDev EP4 OUT" },
-	{ DMA_ID_USBDEV_EP5_RX, "USBDev EP5 OUT" }
-};
-
-#define DIR_OUT 0
-#define DIR_IN  (1<<3)
-
-#define CONTROL_EP USB_ENDPOINT_XFER_CONTROL
-#define BULK_EP    USB_ENDPOINT_XFER_BULK
-
-static inline endpoint_t *
-epaddr_to_ep(struct usb_dev* dev, int ep_addr)
-{
-	if (ep_addr >= 0 && ep_addr < 2)
-		return &dev->ep[0];
-	if (ep_addr < 6)
-		return &dev->ep[ep_addr];
-	return NULL;
-}
-
-static const char* std_req_name[] = {
-	"GET_STATUS",
-	"CLEAR_FEATURE",
-	"RESERVED",
-	"SET_FEATURE",
-	"RESERVED",
-	"SET_ADDRESS",
-	"GET_DESCRIPTOR",
-	"SET_DESCRIPTOR",
-	"GET_CONFIGURATION",
-	"SET_CONFIGURATION",
-	"GET_INTERFACE",
-	"SET_INTERFACE",
-	"SYNCH_FRAME"
-};
-
-static inline const char*
-get_std_req_name(int req)
-{
-	return (req >= 0 && req <= 12) ? std_req_name[req] : "UNKNOWN";
-}
-
-#if 0
-static void
-dump_setup(struct usb_ctrlrequest* s)
-{
-	dbg("%s: requesttype=%d", __FUNCTION__, s->requesttype);
-	dbg("%s: request=%d %s", __FUNCTION__, s->request,
-	    get_std_req_name(s->request));
-	dbg("%s: value=0x%04x", __FUNCTION__, s->wValue);
-	dbg("%s: index=%d", __FUNCTION__, s->index);
-	dbg("%s: length=%d", __FUNCTION__, s->length);
-}
-#endif
-
-static inline usbdev_pkt_t *
-alloc_packet(endpoint_t * ep, int data_size, void* data)
-{
-	usbdev_pkt_t* pkt = kmalloc(sizeof(usbdev_pkt_t) + data_size,
-				    ALLOC_FLAGS);
-	if (!pkt)
-		return NULL;
-	pkt->ep_addr = ep->address;
-	pkt->size = data_size;
-	pkt->status = 0;
-	pkt->next = NULL;
-	if (data)
-		memcpy(pkt->payload, data, data_size);
-
-	return pkt;
-}
-
-
-/*
- * Link a packet to the tail of the enpoint's packet list.
- * EP spinlock must be held when calling.
- */
-static void
-link_tail(endpoint_t * ep, pkt_list_t * list, usbdev_pkt_t * pkt)
-{
-	if (!list->tail) {
-		list->head = list->tail = pkt;
-		list->count = 1;
-	} else {
-		list->tail->next = pkt;
-		list->tail = pkt;
-		list->count++;
-	}
-}
-
-/*
- * Unlink and return a packet from the head of the given packet
- * list. It is the responsibility of the caller to free the packet.
- * EP spinlock must be held when calling.
- */
-static usbdev_pkt_t *
-unlink_head(pkt_list_t * list)
-{
-	usbdev_pkt_t *pkt;
-
-	pkt = list->head;
-	if (!pkt || !list->count) {
-		return NULL;
-	}
-
-	list->head = pkt->next;
-	if (!list->head) {
-		list->head = list->tail = NULL;
-		list->count = 0;
-	} else
-		list->count--;
-
-	return pkt;
-}
-
-/*
- * Create and attach a new packet to the tail of the enpoint's
- * packet list. EP spinlock must be held when calling.
- */
-static usbdev_pkt_t *
-add_packet(endpoint_t * ep, pkt_list_t * list, int size)
-{
-	usbdev_pkt_t *pkt = alloc_packet(ep, size, NULL);
-	if (!pkt)
-		return NULL;
-
-	link_tail(ep, list, pkt);
-	return pkt;
-}
-
-
-/*
- * Unlink and free a packet from the head of the enpoint's
- * packet list. EP spinlock must be held when calling.
- */
-static inline void
-free_packet(pkt_list_t * list)
-{
-	kfree(unlink_head(list));
-}
-
-/* EP spinlock must be held when calling. */
-static inline void
-flush_pkt_list(pkt_list_t * list)
-{
-	while (list->count)
-		free_packet(list);
-}
-
-/* EP spinlock must be held when calling */
-static inline void
-flush_write_fifo(endpoint_t * ep)
-{
-	if (ep->reg->write_fifo_status >= 0) {
-		au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF |
-			  USBDEV_FSTAT_OF,
-			  ep->reg->write_fifo_status);
-		//udelay(100);
-		//au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF,
-		//	  ep->reg->write_fifo_status);
-	}
-}
-
-/* EP spinlock must be held when calling */
-static inline void
-flush_read_fifo(endpoint_t * ep)
-{
-	if (ep->reg->read_fifo_status >= 0) {
-		au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF |
-			  USBDEV_FSTAT_OF,
-			  ep->reg->read_fifo_status);
-		//udelay(100);
-		//au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF,
-		//	  ep->reg->read_fifo_status);
-	}
-}
-
-
-/* EP spinlock must be held when calling. */
-static void
-endpoint_flush(endpoint_t * ep)
-{
-	// First, flush all packets
-	flush_pkt_list(&ep->inlist);
-	flush_pkt_list(&ep->outlist);
-
-	// Now flush the endpoint's h/w FIFO(s)
-	flush_write_fifo(ep);
-	flush_read_fifo(ep);
-}
-
-/* EP spinlock must be held when calling. */
-static void
-endpoint_stall(endpoint_t * ep)
-{
-	u32 cs;
-
-	warn("%s", __FUNCTION__);
-
-	cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL;
-	au_writel(cs, ep->reg->ctrl_stat);
-}
-
-/* EP spinlock must be held when calling. */
-static void
-endpoint_unstall(endpoint_t * ep)
-{
-	u32 cs;
-
-	warn("%s", __FUNCTION__);
-
-	cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL;
-	au_writel(cs, ep->reg->ctrl_stat);
-}
-
-static void
-endpoint_reset_datatoggle(endpoint_t * ep)
-{
-	// FIXME: is this possible?
-}
-
-
-/* EP spinlock must be held when calling. */
-static int
-endpoint_fifo_read(endpoint_t * ep)
-{
-	int read_count = 0;
-	u8 *bufptr;
-	usbdev_pkt_t *pkt = ep->outlist.tail;
-
-	if (!pkt)
-		return -EINVAL;
-
-	bufptr = &pkt->payload[pkt->size];
-	while (au_readl(ep->reg->read_fifo_status) & USBDEV_FSTAT_FCNT_MASK) {
-		*bufptr++ = au_readl(ep->reg->read_fifo) & 0xff;
-		read_count++;
-		pkt->size++;
-	}
-
-	return read_count;
-}
-
-#if 0
-/* EP spinlock must be held when calling. */
-static int
-endpoint_fifo_write(endpoint_t * ep, int index)
-{
-	int write_count = 0;
-	u8 *bufptr;
-	usbdev_pkt_t *pkt = ep->inlist.head;
-
-	if (!pkt)
-		return -EINVAL;
-
-	bufptr = &pkt->payload[index];
-	while ((au_readl(ep->reg->write_fifo_status) &
-		USBDEV_FSTAT_FCNT_MASK) < EP_FIFO_DEPTH) {
-		if (bufptr < pkt->payload + pkt->size) {
-			au_writel(*bufptr++, ep->reg->write_fifo);
-			write_count++;
-		} else {
-			break;
-		}
-	}
-
-	return write_count;
-}
-#endif
-
-/*
- * This routine is called to restart transmission of a packet.
- * The endpoint's TSIZE must be set to the new packet's size,
- * and DMA to the write FIFO needs to be restarted.
- * EP spinlock must be held when calling.
- */
-static void
-kickstart_send_packet(endpoint_t * ep)
-{
-	u32 cs;
-	usbdev_pkt_t *pkt = ep->inlist.head;
-
-	vdbg("%s: ep%d, pkt=%p", __FUNCTION__, ep->address, pkt);
-
-	if (!pkt) {
-		err("%s: head=NULL! list->count=%d", __FUNCTION__,
-		    ep->inlist.count);
-		return;
-	}
-
-	dma_cache_wback_inv((unsigned long)pkt->payload, pkt->size);
-
-	/*
-	 * make sure FIFO is empty
-	 */
-	flush_write_fifo(ep);
-
-	cs = au_readl(ep->reg->ctrl_stat) & USBDEV_CS_STALL;
-	cs |= (pkt->size << USBDEV_CS_TSIZE_BIT);
-	au_writel(cs, ep->reg->ctrl_stat);
-
-	if (get_dma_active_buffer(ep->indma) == 1) {
-		set_dma_count1(ep->indma, pkt->size);
-		set_dma_addr1(ep->indma, virt_to_phys(pkt->payload));
-		enable_dma_buffer1(ep->indma);	// reenable
-	} else {
-		set_dma_count0(ep->indma, pkt->size);
-		set_dma_addr0(ep->indma, virt_to_phys(pkt->payload));
-		enable_dma_buffer0(ep->indma);	// reenable
-	}
-	if (dma_halted(ep->indma))
-		start_dma(ep->indma);
-}
-
-
-/*
- * This routine is called when a packet in the inlist has been
- * completed. Frees the completed packet and starts sending the
- * next. EP spinlock must be held when calling.
- */
-static usbdev_pkt_t *
-send_packet_complete(endpoint_t * ep)
-{
-	usbdev_pkt_t *pkt = unlink_head(&ep->inlist);
-
-	if (pkt) {
-		pkt->status =
-			(au_readl(ep->reg->ctrl_stat) & USBDEV_CS_NAK) ?
-			PKT_STATUS_NAK : PKT_STATUS_ACK;
-
-		vdbg("%s: ep%d, %s pkt=%p, list count=%d", __FUNCTION__,
-		     ep->address, (pkt->status & PKT_STATUS_NAK) ?
-		     "NAK" : "ACK", pkt, ep->inlist.count);
-	}
-
-	/*
-	 * The write fifo should already be drained if things are
-	 * working right, but flush it anyway just in case.
-	 */
-	flush_write_fifo(ep);
-
-	// begin transmitting next packet in the inlist
-	if (ep->inlist.count) {
-		kickstart_send_packet(ep);
-	}
-
-	return pkt;
-}
-
-/*
- * Add a new packet to the tail of the given ep's packet
- * inlist. The transmit complete interrupt frees packets from
- * the head of this list. EP spinlock must be held when calling.
- */
-static int
-send_packet(struct usb_dev* dev, usbdev_pkt_t *pkt, int async)
-{
-	pkt_list_t *list;
-	endpoint_t* ep;
-
-	if (!pkt || !(ep = epaddr_to_ep(dev, pkt->ep_addr)))
-		return -EINVAL;
-
-	if (!pkt->size)
-		return 0;
-
-	list = &ep->inlist;
-
-	if (!async && list->count) {
-		halt_dma(ep->indma);
-		flush_pkt_list(list);
-	}
-
-	link_tail(ep, list, pkt);
-
-	vdbg("%s: ep%d, pkt=%p, size=%d, list count=%d", __FUNCTION__,
-	     ep->address, pkt, pkt->size, list->count);
-
-	if (list->count == 1) {
-		/*
-		 * if the packet count is one, it means the list was empty,
-		 * and no more data will go out this ep until we kick-start
-		 * it again.
-		 */
-		kickstart_send_packet(ep);
-	}
-
-	return pkt->size;
-}
-
-/*
- * This routine is called to restart reception of a packet.
- * EP spinlock must be held when calling.
- */
-static void
-kickstart_receive_packet(endpoint_t * ep)
-{
-	usbdev_pkt_t *pkt;
-
-	// get and link a new packet for next reception
-	if (!(pkt = add_packet(ep, &ep->outlist, ep->max_pkt_size))) {
-		err("%s: could not alloc new packet", __FUNCTION__);
-		return;
-	}
-
-	if (get_dma_active_buffer(ep->outdma) == 1) {
-		clear_dma_done1(ep->outdma);
-		set_dma_count1(ep->outdma, ep->max_pkt_size);
-		set_dma_count0(ep->outdma, 0);
-		set_dma_addr1(ep->outdma, virt_to_phys(pkt->payload));
-		enable_dma_buffer1(ep->outdma);	// reenable
-	} else {
-		clear_dma_done0(ep->outdma);
-		set_dma_count0(ep->outdma, ep->max_pkt_size);
-		set_dma_count1(ep->outdma, 0);
-		set_dma_addr0(ep->outdma, virt_to_phys(pkt->payload));
-		enable_dma_buffer0(ep->outdma);	// reenable
-	}
-	if (dma_halted(ep->outdma))
-		start_dma(ep->outdma);
-}
-
-
-/*
- * This routine is called when a packet in the outlist has been
- * completed (received) and we need to prepare for a new packet
- * to be received. Halts DMA and computes the packet size from the
- * remaining DMA counter. Then prepares a new packet for reception
- * and restarts DMA. FIXME: what if another packet comes in
- * on top of the completed packet? Counter would be wrong.
- * EP spinlock must be held when calling.
- */
-static usbdev_pkt_t *
-receive_packet_complete(endpoint_t * ep)
-{
-	usbdev_pkt_t *pkt = ep->outlist.tail;
-	u32 cs;
-
-	halt_dma(ep->outdma);
-
-	cs = au_readl(ep->reg->ctrl_stat);
-
-	if (!pkt)
-		return NULL;
-
-	pkt->size = ep->max_pkt_size - get_dma_residue(ep->outdma);
-	if (pkt->size)
-		dma_cache_inv((unsigned long)pkt->payload, pkt->size);
-	/*
-	 * need to pull out any remaining bytes in the FIFO.
-	 */
-	endpoint_fifo_read(ep);
-	/*
-	 * should be drained now, but flush anyway just in case.
-	 */
-	flush_read_fifo(ep);
-
-	pkt->status = (cs & USBDEV_CS_NAK) ? PKT_STATUS_NAK : PKT_STATUS_ACK;
-	if (ep->address == 0 && (cs & USBDEV_CS_SU))
-		pkt->status |= PKT_STATUS_SU;
-
-	vdbg("%s: ep%d, %s pkt=%p, size=%d", __FUNCTION__,
-	     ep->address, (pkt->status & PKT_STATUS_NAK) ?
-	     "NAK" : "ACK", pkt, pkt->size);
-
-	kickstart_receive_packet(ep);
-
-	return pkt;
-}
-
-
-/*
- ****************************************************************************
- * Here starts the standard device request handlers. They are
- * all called by do_setup() via a table of function pointers.
- ****************************************************************************
- */
-
-static ep0_stage_t
-do_get_status(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	switch (setup->bRequestType) {
-	case 0x80:	// Device
-		// FIXME: send device status
-		break;
-	case 0x81:	// Interface
-		// FIXME: send interface status
-		break;
-	case 0x82:	// End Point
-		// FIXME: send endpoint status
-		break;
-	default:
-		// Invalid Command
-		endpoint_stall(&dev->ep[0]); // Stall End Point 0
-		break;
-	}
-
-	return STATUS_STAGE;
-}
-
-static ep0_stage_t
-do_clear_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	switch (setup->bRequestType) {
-	case 0x00:	// Device
-		if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
-			dev->remote_wakeup_en = 0;
-	else
-			endpoint_stall(&dev->ep[0]);
-		break;
-	case 0x02:	// End Point
-		if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
-			endpoint_t *ep =
-				epaddr_to_ep(dev,
-					     le16_to_cpu(setup->wIndex) & 0xff);
-
-			endpoint_unstall(ep);
-			endpoint_reset_datatoggle(ep);
-		} else
-			endpoint_stall(&dev->ep[0]);
-		break;
-	}
-
-	return SETUP_STAGE;
-}
-
-static ep0_stage_t
-do_reserved(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	// Invalid request, stall End Point 0
-	endpoint_stall(&dev->ep[0]);
-	return SETUP_STAGE;
-}
-
-static ep0_stage_t
-do_set_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	switch (setup->bRequestType) {
-	case 0x00:	// Device
-		if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
-			dev->remote_wakeup_en = 1;
-		else
-			endpoint_stall(&dev->ep[0]);
-		break;
-	case 0x02:	// End Point
-		if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
-			endpoint_t *ep =
-				epaddr_to_ep(dev,
-					     le16_to_cpu(setup->wIndex) & 0xff);
-
-			endpoint_stall(ep);
-		} else
-			endpoint_stall(&dev->ep[0]);
-		break;
-	}
-
-	return SETUP_STAGE;
-}
-
-static ep0_stage_t
-do_set_address(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	int new_state = dev->state;
-	int new_addr = le16_to_cpu(setup->wValue);
-
-	dbg("%s: our address=%d", __FUNCTION__, new_addr);
-
-	if (new_addr > 127) {
-			// usb spec doesn't tell us what to do, so just go to
-			// default state
-		new_state = DEFAULT;
-		dev->address = 0;
-	} else if (dev->address != new_addr) {
-		dev->address = new_addr;
-		new_state = ADDRESS;
-	}
-
-	if (dev->state != new_state) {
-		dev->state = new_state;
-		/* inform function layer of usbdev state change */
-		dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
-	}
-
-	return SETUP_STAGE;
-}
-
-static ep0_stage_t
-do_get_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	int strnum, desc_len = le16_to_cpu(setup->wLength);
-
-		switch (le16_to_cpu(setup->wValue) >> 8) {
-		case USB_DT_DEVICE:
-			// send device descriptor!
-		desc_len = desc_len > dev->dev_desc->bLength ?
-			dev->dev_desc->bLength : desc_len;
-			dbg("sending device desc, size=%d", desc_len);
-		send_packet(dev, alloc_packet(&dev->ep[0], desc_len,
-					      dev->dev_desc), 0);
-			break;
-		case USB_DT_CONFIG:
-			// If the config descr index in low-byte of
-			// setup->wValue	is valid, send config descr,
-			// otherwise stall ep0.
-			if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
-				// send config descriptor!
-				if (desc_len <= USB_DT_CONFIG_SIZE) {
-					dbg("sending partial config desc, size=%d",
-					     desc_len);
-				send_packet(dev,
-					    alloc_packet(&dev->ep[0],
-							 desc_len,
-							 dev->conf_desc),
-					    0);
-				} else {
-				int len = le16_to_cpu(dev->conf_desc->wTotalLength);
-				dbg("sending whole config desc,"
-				    " size=%d, our size=%d", desc_len, len);
-				desc_len = desc_len > len ? len : desc_len;
-				send_packet(dev,
-					    alloc_packet(&dev->ep[0],
-							 desc_len,
-							 dev->full_conf_desc),
-					    0);
-				}
-			} else
-			endpoint_stall(&dev->ep[0]);
-			break;
-		case USB_DT_STRING:
-			// If the string descr index in low-byte of setup->wValue
-			// is valid, send string descr, otherwise stall ep0.
-			strnum = le16_to_cpu(setup->wValue) & 0xff;
-			if (strnum >= 0 && strnum < 6) {
-				struct usb_string_descriptor *desc =
-				dev->str_desc[strnum];
-				desc_len = desc_len > desc->bLength ?
-					desc->bLength : desc_len;
-				dbg("sending string desc %d", strnum);
-			send_packet(dev,
-				    alloc_packet(&dev->ep[0], desc_len,
-						 desc), 0);
-			} else
-			endpoint_stall(&dev->ep[0]);
-			break;
-	default:
-		// Invalid request
-		err("invalid get desc=%d, stalled",
-			    le16_to_cpu(setup->wValue) >> 8);
-		endpoint_stall(&dev->ep[0]);	// Stall endpoint 0
-			break;
-		}
-
-	return STATUS_STAGE;
-}
-
-static ep0_stage_t
-do_set_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	// TODO: implement
-	// there will be an OUT data stage (the descriptor to set)
-	return DATA_STAGE;
-}
-
-static ep0_stage_t
-do_get_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	// send dev->configuration
-	dbg("sending config");
-	send_packet(dev, alloc_packet(&dev->ep[0], 1, &dev->configuration),
-		    0);
-	return STATUS_STAGE;
-}
-
-static ep0_stage_t
-do_set_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	// set active config to low-byte of setup->wValue
-	dev->configuration = le16_to_cpu(setup->wValue) & 0xff;
-	dbg("set config, config=%d", dev->configuration);
-	if (!dev->configuration && dev->state > DEFAULT) {
-		dev->state = ADDRESS;
-		/* inform function layer of usbdev state change */
-		dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
-	} else if (dev->configuration == 1) {
-		dev->state = CONFIGURED;
-		/* inform function layer of usbdev state change */
-		dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
-	} else {
-		// FIXME: "respond with request error" - how?
-	}
-
-	return SETUP_STAGE;
-}
-
-static ep0_stage_t
-do_get_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-		// interface must be zero.
-	if ((le16_to_cpu(setup->wIndex) & 0xff) || dev->state == ADDRESS) {
-			// FIXME: respond with "request error". how?
-	} else if (dev->state == CONFIGURED) {
-		// send dev->alternate_setting
-			dbg("sending alt setting");
-		send_packet(dev, alloc_packet(&dev->ep[0], 1,
-					      &dev->alternate_setting), 0);
-		}
-
-	return STATUS_STAGE;
-
-}
-
-static ep0_stage_t
-do_set_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	if (dev->state == ADDRESS) {
-			// FIXME: respond with "request error". how?
-	} else if (dev->state == CONFIGURED) {
-		dev->interface = le16_to_cpu(setup->wIndex) & 0xff;
-		dev->alternate_setting =
-			    le16_to_cpu(setup->wValue) & 0xff;
-			// interface and alternate_setting must be zero
-		if (dev->interface || dev->alternate_setting) {
-				// FIXME: respond with "request error". how?
-			}
-		}
-
-	return SETUP_STAGE;
-}
-
-static ep0_stage_t
-do_synch_frame(struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	// TODO
-	return SETUP_STAGE;
-}
-
-typedef ep0_stage_t (*req_method_t)(struct usb_dev* dev,
-				    struct usb_ctrlrequest* setup);
-
-
-/* Table of the standard device request handlers */
-static const req_method_t req_method[] = {
-	do_get_status,
-	do_clear_feature,
-	do_reserved,
-	do_set_feature,
-	do_reserved,
-	do_set_address,
-	do_get_descriptor,
-	do_set_descriptor,
-	do_get_configuration,
-	do_set_configuration,
-	do_get_interface,
-	do_set_interface,
-	do_synch_frame
-};
-
-
-// SETUP packet request dispatcher
-static void
-do_setup (struct usb_dev* dev, struct usb_ctrlrequest* setup)
-{
-	req_method_t m;
-
-	dbg("%s: req %d %s", __FUNCTION__, setup->bRequestType,
-	    get_std_req_name(setup->bRequestType));
-
-	if ((setup->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD ||
-	    (setup->bRequestType & USB_RECIP_MASK) != USB_RECIP_DEVICE) {
-		err("%s: invalid requesttype 0x%02x", __FUNCTION__,
-		    setup->bRequestType);
-		return;
-		}
-
-	if ((setup->bRequestType & 0x80) == USB_DIR_OUT && setup->wLength)
-		dbg("%s: OUT phase! length=%d", __FUNCTION__, setup->wLength);
-
-	if (setup->bRequestType < sizeof(req_method)/sizeof(req_method_t))
-		m = req_method[setup->bRequestType];
-			else
-		m = do_reserved;
-
-	dev->ep0_stage = (*m)(dev, setup);
-}
-
-/*
- * A SETUP, DATA0, or DATA1 packet has been received
- * on the default control endpoint's fifo.
- */
-static void
-process_ep0_receive (struct usb_dev* dev)
-{
-	endpoint_t *ep0 = &dev->ep[0];
-	usbdev_pkt_t *pkt;
-
-	spin_lock(&ep0->lock);
-
-		// complete packet and prepare a new packet
-	pkt = receive_packet_complete(ep0);
-	if (!pkt) {
-		// FIXME: should  put a warn/err here.
-		spin_unlock(&ep0->lock);
-			return;
-		}
-
-	// unlink immediately from endpoint.
-	unlink_head(&ep0->outlist);
-
-	// override current stage if h/w says it's a setup packet
-	if (pkt->status & PKT_STATUS_SU)
-		dev->ep0_stage = SETUP_STAGE;
-
-	switch (dev->ep0_stage) {
-	case SETUP_STAGE:
-		vdbg("SU bit is %s in setup stage",
-		     (pkt->status & PKT_STATUS_SU) ? "set" : "not set");
-
-			if (pkt->size == sizeof(struct usb_ctrlrequest)) {
-#ifdef VDEBUG
-			if (pkt->status & PKT_STATUS_ACK)
-				vdbg("received SETUP");
-				else
-				vdbg("received NAK SETUP");
-#endif
-			do_setup(dev, (struct usb_ctrlrequest*)pkt->payload);
-		} else
-			err("%s: wrong size SETUP received", __FUNCTION__);
-		break;
-	case DATA_STAGE:
-		/*
-		 * this setup has an OUT data stage. Of the standard
-		 * device requests, only set_descriptor has this stage,
-		 * so this packet is that descriptor. TODO: drop it for
-		 * now, set_descriptor not implemented.
-		 *
-		 * Need to place a byte in the write FIFO here, to prepare
-		 * to send a zero-length DATA ack packet to the host in the
-		 * STATUS stage.
-		 */
-		au_writel(0, ep0->reg->write_fifo);
-		dbg("received OUT stage DATAx on EP0, size=%d", pkt->size);
-		dev->ep0_stage = SETUP_STAGE;
-		break;
-	case STATUS_STAGE:
-		// this setup had an IN data stage, and host is ACK'ing
-		// the packet we sent during that stage.
-		if (pkt->size != 0)
-			warn("received non-zero ACK on EP0??");
-#ifdef VDEBUG
-		else
-			vdbg("received ACK on EP0");
-#endif
-		dev->ep0_stage = SETUP_STAGE;
-		break;
-	}
-
-	spin_unlock(&ep0->lock);
-	// we're done processing the packet, free it
-	kfree(pkt);
-}
-
-
-/*
- * A DATA0/1 packet has been received on one of the OUT endpoints (4 or 5)
- */
-static void
-process_ep_receive (struct usb_dev* dev, endpoint_t *ep)
-{
-	usbdev_pkt_t *pkt;
-
-		spin_lock(&ep->lock);
-	pkt = receive_packet_complete(ep);
-		spin_unlock(&ep->lock);
-
-	dev->func_cb(CB_PKT_COMPLETE, (unsigned long)pkt, dev->cb_data);
-}
-
-
-
-/* This ISR handles the receive complete and suspend events */
-static void
-req_sus_intr (int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct usb_dev *dev = (struct usb_dev *) dev_id;
-	u32 status;
-
-	status = au_readl(USBD_INTSTAT);
-	au_writel(status, USBD_INTSTAT);	// ack'em
-
-	if (status & (1<<0))
-		process_ep0_receive(dev);
-	if (status & (1<<4))
-		process_ep_receive(dev, &dev->ep[4]);
-	if (status & (1<<5))
-		process_ep_receive(dev, &dev->ep[5]);
-}
-
-
-/* This ISR handles the DMA done events on EP0 */
-static void
-dma_done_ep0_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct usb_dev *dev = (struct usb_dev *) dev_id;
-	usbdev_pkt_t* pkt;
-	endpoint_t *ep0 = &dev->ep[0];
-	u32 cs0, buff_done;
-
-	spin_lock(&ep0->lock);
-	cs0 = au_readl(ep0->reg->ctrl_stat);
-
-	// first check packet transmit done
-	if ((buff_done = get_dma_buffer_done(ep0->indma)) != 0) {
-		// transmitted a DATAx packet during DATA stage
-		// on control endpoint 0
-		// clear DMA done bit
-		if (buff_done & DMA_D0)
-			clear_dma_done0(ep0->indma);
-		if (buff_done & DMA_D1)
-			clear_dma_done1(ep0->indma);
-
-		pkt = send_packet_complete(ep0);
-		kfree(pkt);
-	}
-
-	/*
-	 * Now check packet receive done. Shouldn't get these,
-	 * the receive packet complete intr should happen
-	 * before the DMA done intr occurs.
-	 */
-	if ((buff_done = get_dma_buffer_done(ep0->outdma)) != 0) {
-		// clear DMA done bit
-		if (buff_done & DMA_D0)
-			clear_dma_done0(ep0->outdma);
-		if (buff_done & DMA_D1)
-			clear_dma_done1(ep0->outdma);
-
-		//process_ep0_receive(dev);
-	}
-
-	spin_unlock(&ep0->lock);
-}
-
-/* This ISR handles the DMA done events on endpoints 2,3,4,5 */
-static void
-dma_done_ep_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct usb_dev *dev = (struct usb_dev *) dev_id;
-	int i;
-
-	for (i = 2; i < 6; i++) {
-	u32 buff_done;
-		usbdev_pkt_t* pkt;
-		endpoint_t *ep = &dev->ep[i];
-
-		if (!ep->active) continue;
-
-	spin_lock(&ep->lock);
-
-		if (ep->direction == USB_DIR_IN) {
-			buff_done = get_dma_buffer_done(ep->indma);
-			if (buff_done != 0) {
-				// transmitted a DATAx pkt on the IN ep
-		// clear DMA done bit
-		if (buff_done & DMA_D0)
-			clear_dma_done0(ep->indma);
-		if (buff_done & DMA_D1)
-			clear_dma_done1(ep->indma);
-
-				pkt = send_packet_complete(ep);
-
-				spin_unlock(&ep->lock);
-				dev->func_cb(CB_PKT_COMPLETE,
-					     (unsigned long)pkt,
-					     dev->cb_data);
-				spin_lock(&ep->lock);
-			}
-		} else {
-	/*
-			 * Check packet receive done (OUT ep). Shouldn't get
-			 * these, the rx packet complete intr should happen
-	 * before the DMA done intr occurs.
-	 */
-			buff_done = get_dma_buffer_done(ep->outdma);
-			if (buff_done != 0) {
-				// received a DATAx pkt on the OUT ep
-		// clear DMA done bit
-		if (buff_done & DMA_D0)
-			clear_dma_done0(ep->outdma);
-		if (buff_done & DMA_D1)
-			clear_dma_done1(ep->outdma);
-
-				//process_ep_receive(dev, ep);
-	}
-	}
-
-		spin_unlock(&ep->lock);
-	}
-}
-
-
-/***************************************************************************
- * Here begins the external interface functions
- ***************************************************************************
- */
-
-/*
- * allocate a new packet
- */
-int
-usbdev_alloc_packet(int ep_addr, int data_size, usbdev_pkt_t** pkt)
-{
-	endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr);
-	usbdev_pkt_t* lpkt = NULL;
-
-	if (!ep || !ep->active || ep->address < 2)
-		return -ENODEV;
-	if (data_size > ep->max_pkt_size)
-		return -EINVAL;
-
-	lpkt = *pkt = alloc_packet(ep, data_size, NULL);
-	if (!lpkt)
-		return -ENOMEM;
-	return 0;
-}
-
-
-/*
- * packet send
- */
-int
-usbdev_send_packet(int ep_addr, usbdev_pkt_t * pkt)
-{
-	unsigned long flags;
-	int count;
-	endpoint_t * ep;
-
-	if (!pkt || !(ep = epaddr_to_ep(&usbdev, pkt->ep_addr)) ||
-	    !ep->active || ep->address < 2)
-		return -ENODEV;
-	if (ep->direction != USB_DIR_IN)
-		return -EINVAL;
-
-	spin_lock_irqsave(&ep->lock, flags);
-	count = send_packet(&usbdev, pkt, 1);
-	spin_unlock_irqrestore(&ep->lock, flags);
-
-	return count;
-}
-
-/*
- * packet receive
- */
-int
-usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt)
-{
-	unsigned long flags;
-	usbdev_pkt_t* lpkt = NULL;
-	endpoint_t *ep = epaddr_to_ep(&usbdev, ep_addr);
-
-	if (!ep || !ep->active || ep->address < 2)
-		return -ENODEV;
-	if (ep->direction != USB_DIR_OUT)
-		return -EINVAL;
-
-	spin_lock_irqsave(&ep->lock, flags);
-	if (ep->outlist.count > 1)
-		lpkt = unlink_head(&ep->outlist);
-	spin_unlock_irqrestore(&ep->lock, flags);
-
-	if (!lpkt) {
-		/* no packet available */
-		*pkt = NULL;
-		return -ENODATA;
-	}
-
-	*pkt = lpkt;
-
-	return lpkt->size;
-}
-
-
-/*
- * return total queued byte count on the endpoint.
- */
-int
-usbdev_get_byte_count(int ep_addr)
-{
-        unsigned long flags;
-        pkt_list_t *list;
-        usbdev_pkt_t *scan;
-        int count = 0;
-	endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr);
-
-	if (!ep || !ep->active || ep->address < 2)
-		return -ENODEV;
-
-	if (ep->direction == USB_DIR_IN) {
-		list = &ep->inlist;
-
-		spin_lock_irqsave(&ep->lock, flags);
-		for (scan = list->head; scan; scan = scan->next)
-			count += scan->size;
-		spin_unlock_irqrestore(&ep->lock, flags);
-	} else {
-		list = &ep->outlist;
-
-		spin_lock_irqsave(&ep->lock, flags);
-		if (list->count > 1) {
-			for (scan = list->head; scan != list->tail;
-			     scan = scan->next)
-				count += scan->size;
-	}
-		spin_unlock_irqrestore(&ep->lock, flags);
-	}
-
-	return count;
-}
-
-
-void
-usbdev_exit(void)
-{
-	endpoint_t *ep;
-	int i;
-
-	au_writel(0, USBD_INTEN);	// disable usb dev ints
-	au_writel(0, USBD_ENABLE);	// disable usb dev
-
-	free_irq(AU1000_USB_DEV_REQ_INT, &usbdev);
-	free_irq(AU1000_USB_DEV_SUS_INT, &usbdev);
-
-	// free all control endpoint resources
-	ep = &usbdev.ep[0];
-	free_au1000_dma(ep->indma);
-	free_au1000_dma(ep->outdma);
-	endpoint_flush(ep);
-
-	// free ep resources
-	for (i = 2; i < 6; i++) {
-		ep = &usbdev.ep[i];
-		if (!ep->active) continue;
-
-		if (ep->direction == USB_DIR_IN) {
-			free_au1000_dma(ep->indma);
-		} else {
-		free_au1000_dma(ep->outdma);
-		}
-		endpoint_flush(ep);
-	}
-
-	kfree(usbdev.full_conf_desc);
-}
-
-int
-usbdev_init(struct usb_device_descriptor* dev_desc,
-	    struct usb_config_descriptor* config_desc,
-	    struct usb_interface_descriptor* if_desc,
-	    struct usb_endpoint_descriptor* ep_desc,
-	    struct usb_string_descriptor* str_desc[],
-	    void (*cb)(usbdev_cb_type_t, unsigned long, void *),
-	    void* cb_data)
-{
-	endpoint_t *ep0;
-	int i, ret=0;
-	u8* fcd;
-
-	if (dev_desc->bNumConfigurations > 1 ||
-	    config_desc->bNumInterfaces > 1 ||
-	    if_desc->bNumEndpoints > 4) {
-		err("Only one config, one i/f, and no more "
-		    "than 4 ep's allowed");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (!cb) {
-		err("Function-layer callback required");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (dev_desc->bMaxPacketSize0 != USBDEV_EP0_MAX_PACKET_SIZE) {
-		warn("EP0 Max Packet size must be %d",
-		     USBDEV_EP0_MAX_PACKET_SIZE);
-		dev_desc->bMaxPacketSize0 = USBDEV_EP0_MAX_PACKET_SIZE;
-	}
-
-	memset(&usbdev, 0, sizeof(struct usb_dev));
-
-	usbdev.state = DEFAULT;
-	usbdev.dev_desc = dev_desc;
-	usbdev.if_desc = if_desc;
-	usbdev.conf_desc = config_desc;
-	for (i=0; i<6; i++)
-		usbdev.str_desc[i] = str_desc[i];
-	usbdev.func_cb = cb;
-	usbdev.cb_data = cb_data;
-
-	/* Initialize default control endpoint */
-	ep0 = &usbdev.ep[0];
-	ep0->active = 1;
-	ep0->type = CONTROL_EP;
-	ep0->max_pkt_size = USBDEV_EP0_MAX_PACKET_SIZE;
-	spin_lock_init(&ep0->lock);
-	ep0->desc = NULL;	// ep0 has no descriptor
-	ep0->address = 0;
-	ep0->direction = 0;
-	ep0->reg = &ep_reg[0];
-
-	/* Initialize the other requested endpoints */
-	for (i = 0; i < if_desc->bNumEndpoints; i++) {
-		struct usb_endpoint_descriptor* epd = &ep_desc[i];
-	endpoint_t *ep;
-
-		if ((epd->bEndpointAddress & 0x80) == USB_DIR_IN) {
-			ep = &usbdev.ep[2];
-			ep->address = 2;
-			if (ep->active) {
-				ep = &usbdev.ep[3];
-				ep->address = 3;
-				if (ep->active) {
-					err("too many IN ep's requested");
-					ret = -ENODEV;
-					goto out;
-	}
-	}
-		} else {
-			ep = &usbdev.ep[4];
-			ep->address = 4;
-			if (ep->active) {
-				ep = &usbdev.ep[5];
-				ep->address = 5;
-				if (ep->active) {
-					err("too many OUT ep's requested");
-					ret = -ENODEV;
-					goto out;
-	}
-	}
-		}
-
-		ep->active = 1;
-		epd->bEndpointAddress &= ~0x0f;
-		epd->bEndpointAddress |= (u8)ep->address;
-		ep->direction = epd->bEndpointAddress & 0x80;
-		ep->type = epd->bmAttributes & 0x03;
-		ep->max_pkt_size = le16_to_cpu(epd->wMaxPacketSize);
-		spin_lock_init(&ep->lock);
-		ep->desc = epd;
-		ep->reg = &ep_reg[ep->address];
-		}
-
-	/*
-	 * initialize the full config descriptor
-	 */
-	usbdev.full_conf_desc = fcd = kmalloc(le16_to_cpu(config_desc->wTotalLength),
-					      ALLOC_FLAGS);
-	if (!fcd) {
-		err("failed to alloc full config descriptor");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	memcpy(fcd, config_desc, USB_DT_CONFIG_SIZE);
-	fcd += USB_DT_CONFIG_SIZE;
-	memcpy(fcd, if_desc, USB_DT_INTERFACE_SIZE);
-	fcd += USB_DT_INTERFACE_SIZE;
-	for (i = 0; i < if_desc->bNumEndpoints; i++) {
-		memcpy(fcd, &ep_desc[i], USB_DT_ENDPOINT_SIZE);
-		fcd += USB_DT_ENDPOINT_SIZE;
-	}
-
-	/* Now we're ready to enable the controller */
-	au_writel(0x0002, USBD_ENABLE);
-	udelay(100);
-	au_writel(0x0003, USBD_ENABLE);
-	udelay(100);
-
-	/* build and send config table based on ep descriptors */
-	for (i = 0; i < 6; i++) {
-		endpoint_t *ep;
-		if (i == 1)
-			continue; // skip dummy ep
-		ep = &usbdev.ep[i];
-		if (ep->active) {
-			au_writel((ep->address << 4) | 0x04, USBD_CONFIG);
-			au_writel(((ep->max_pkt_size & 0x380) >> 7) |
-				  (ep->direction >> 4) | (ep->type << 4),
-				  USBD_CONFIG);
-			au_writel((ep->max_pkt_size & 0x7f) << 1, USBD_CONFIG);
-			au_writel(0x00, USBD_CONFIG);
-			au_writel(ep->address, USBD_CONFIG);
-		} else {
-			u8 dir = (i==2 || i==3) ? DIR_IN : DIR_OUT;
-			au_writel((i << 4) | 0x04, USBD_CONFIG);
-			au_writel(((16 & 0x380) >> 7) | dir |
-				  (BULK_EP << 4), USBD_CONFIG);
-			au_writel((16 & 0x7f) << 1, USBD_CONFIG);
-			au_writel(0x00, USBD_CONFIG);
-			au_writel(i, USBD_CONFIG);
-		}
-	}
-
-	/*
-	 * Enable Receive FIFO Complete interrupts only. Transmit
-	 * complete is being handled by the DMA done interrupts.
-	 */
-	au_writel(0x31, USBD_INTEN);
-
-	/*
-	 * Controller is now enabled, request DMA and IRQ
-	 * resources.
-	 */
-
-	/* request the USB device transfer complete interrupt */
-	if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, IRQF_DISABLED,
-			"USBdev req", &usbdev)) {
-		err("Can't get device request intr");
-		ret = -ENXIO;
-		goto out;
-	}
-	/* request the USB device suspend interrupt */
-	if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, IRQF_DISABLED,
-			"USBdev sus", &usbdev)) {
-		err("Can't get device suspend intr");
-		ret = -ENXIO;
-		goto out;
-	}
-
-	/* Request EP0 DMA and IRQ */
-	if ((ep0->indma = request_au1000_dma(ep_dma_id[0].id,
-					     ep_dma_id[0].str,
-					     dma_done_ep0_intr,
-					     IRQF_DISABLED,
-					     &usbdev)) < 0) {
-		err("Can't get %s DMA", ep_dma_id[0].str);
-		ret = -ENXIO;
-		goto out;
-	}
-	if ((ep0->outdma = request_au1000_dma(ep_dma_id[1].id,
-					      ep_dma_id[1].str,
-					      NULL, 0, NULL)) < 0) {
-		err("Can't get %s DMA", ep_dma_id[1].str);
-		ret = -ENXIO;
-		goto out;
-	}
-
-	// Flush the ep0 buffers and FIFOs
-	endpoint_flush(ep0);
-	// start packet reception on ep0
-	kickstart_receive_packet(ep0);
-
-	/* Request DMA and IRQ for the other endpoints */
-	for (i = 2; i < 6; i++) {
-		endpoint_t *ep = &usbdev.ep[i];
-		if (!ep->active)
-			continue;
-
-		// Flush the endpoint buffers and FIFOs
-		endpoint_flush(ep);
-
-		if (ep->direction == USB_DIR_IN) {
-			ep->indma =
-				request_au1000_dma(ep_dma_id[ep->address].id,
-						   ep_dma_id[ep->address].str,
-						   dma_done_ep_intr,
-						   IRQF_DISABLED,
-						   &usbdev);
-			if (ep->indma < 0) {
-				err("Can't get %s DMA",
-				    ep_dma_id[ep->address].str);
-				ret = -ENXIO;
-				goto out;
-			}
-		} else {
-			ep->outdma =
-				request_au1000_dma(ep_dma_id[ep->address].id,
-						   ep_dma_id[ep->address].str,
-						   NULL, 0, NULL);
-			if (ep->outdma < 0) {
-				err("Can't get %s DMA",
-				    ep_dma_id[ep->address].str);
-				ret = -ENXIO;
-				goto out;
-			}
-
-			// start packet reception on OUT endpoint
-			kickstart_receive_packet(ep);
-		}
-	}
-
- out:
-	if (ret)
-		usbdev_exit();
-	return ret;
-}
-
-EXPORT_SYMBOL(usbdev_init);
-EXPORT_SYMBOL(usbdev_exit);
-EXPORT_SYMBOL(usbdev_alloc_packet);
-EXPORT_SYMBOL(usbdev_receive_packet);
-EXPORT_SYMBOL(usbdev_send_packet);
-EXPORT_SYMBOL(usbdev_get_byte_count);
diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c
index 7a79293..8b08edb 100644
--- a/arch/mips/au1000/db1x00/board_setup.c
+++ b/arch/mips/au1000/db1x00/board_setup.c
@@ -58,11 +58,6 @@
 
 	pin_func = 0;
 	/* not valid for 1550 */
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	// 2nd USB port is USB device
-	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-	au_writel(pin_func, SYS_PINFUNC);
-#endif
 
 #if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
 	/* set IRFIRSEL instead of GPIO15 */
diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c
index e917e54..13f9bf5 100644
--- a/arch/mips/au1000/mtx-1/board_setup.c
+++ b/arch/mips/au1000/mtx-1/board_setup.c
@@ -51,15 +51,11 @@
 
 void __init board_setup(void)
 {
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	// 2nd USB port is USB device
-	au_writel(au_readl(SYS_PINFUNC) & (u32)(~0x8000), SYS_PINFUNC);
-#endif
+#ifdef CONFIG_USB_OHCI
 	// enable USB power switch
 	au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR );
 	au_writel( 0x100000, GPIO2_OUTPUT );
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#endif // defined (CONFIG_USB_OHCI)
 
 #ifdef CONFIG_PCI
 #if defined(__MIPSEB__)
diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c
index 1cf18e16..824cfaf 100644
--- a/arch/mips/au1000/pb1000/board_setup.c
+++ b/arch/mips/au1000/pb1000/board_setup.c
@@ -54,7 +54,7 @@
 	au_writel(0, SYS_PINSTATERD);
 	udelay(100);
 
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#ifdef CONFIG_USB_OHCI
 	/* zero and disable FREQ2 */
 	sys_freqctrl = au_readl(SYS_FREQCTRL0);
 	sys_freqctrl &= ~0xFFF00000;
@@ -105,22 +105,18 @@
 #ifdef CONFIG_USB_OHCI
 	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
 #endif
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
-#endif
 	au_writel(sys_clksrc, SYS_CLKSRC);
 
 	// configure pins GPIO[14:9] as GPIO
 	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080);
 
-#ifndef CONFIG_AU1X00_USB_DEVICE
 	// 2nd USB port is USB host
 	pin_func |= 0x8000;
-#endif
+
 	au_writel(pin_func, SYS_PINFUNC);
 	au_writel(0x2800, SYS_TRIOUTCLR);
 	au_writel(0x0030, SYS_OUTPUTCLR);
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#endif // defined (CONFIG_USB_OHCI)
 
 	// make gpio 15 an input (for interrupt line)
 	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100);
diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c
index db27b93..2d1533f 100644
--- a/arch/mips/au1000/pb1100/board_setup.c
+++ b/arch/mips/au1000/pb1100/board_setup.c
@@ -55,7 +55,7 @@
 	au_writel(0, SYS_PININPUTEN);
 	udelay(100);
 
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#ifdef CONFIG_USB_OHCI
 	// configure pins GPIO[14:9] as GPIO
 	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
 
@@ -92,12 +92,10 @@
 
 	// get USB Functionality pin state (device vs host drive pins)
 	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-#ifndef CONFIG_AU1X00_USB_DEVICE
 	// 2nd USB port is USB host
 	pin_func |= 0x8000;
-#endif
 	au_writel(pin_func, SYS_PINFUNC);
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#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);
diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
index f66779f..91983ba 100644
--- a/arch/mips/au1000/pb1200/irqmap.c
+++ b/arch/mips/au1000/pb1200/irqmap.c
@@ -65,7 +65,7 @@
  */
 static volatile int pb1200_cascade_en=0;
 
-irqreturn_t pb1200_cascade_handler( int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t pb1200_cascade_handler( int irq, void *dev_id)
 {
 	unsigned short bisr = bcsr->int_status;
 	int extirq_nr = 0;
@@ -76,8 +76,9 @@
 	{
 		extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr);
 		/* Ack and dispatch IRQ */
-		do_IRQ(extirq_nr,regs);
+		do_IRQ(extirq_nr);
 	}
+
 	return IRQ_RETVAL(1);
 }
 
diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c
index 1a9a293..0ffdb4f 100644
--- a/arch/mips/au1000/pb1500/board_setup.c
+++ b/arch/mips/au1000/pb1500/board_setup.c
@@ -56,7 +56,7 @@
 	au_writel(0, SYS_PINSTATERD);
 	udelay(100);
 
-#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#ifdef CONFIG_USB_OHCI
 
 	/* GPIO201 is input for PCMCIA card detect */
 	/* GPIO203 is input for PCMCIA interrupt request */
@@ -88,19 +88,14 @@
 #ifdef CONFIG_USB_OHCI
 	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
 #endif
-#ifdef CONFIG_AU1X00_USB_DEVICE
-	sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
-#endif
 	au_writel(sys_clksrc, SYS_CLKSRC);
 
 
 	pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-#ifndef CONFIG_AU1X00_USB_DEVICE
 	// 2nd USB port is USB host
 	pin_func |= 0x8000;
-#endif
 	au_writel(pin_func, SYS_PINFUNC);
-#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#endif // defined (CONFIG_USB_OHCI)
 
 
 
diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c
index c04505a..d289e3a 100644
--- a/arch/mips/basler/excite/excite_dbg_io.c
+++ b/arch/mips/basler/excite/excite_dbg_io.c
@@ -112,7 +112,7 @@
 }
 
 /* KGDB interrupt handler */
-asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs)
+asmlinkage void excite_kgdb_inthdl(void)
 {
 	if (unlikely(
 		((titan_readl(UAIIR) & 0x7) == 4)
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
index 10bbb8c..6af0b21 100644
--- a/arch/mips/basler/excite/excite_iodev.c
+++ b/arch/mips/basler/excite/excite_iodev.c
@@ -38,7 +38,7 @@
 static int iodev_release(struct inode *, struct file *);
 static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
 static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
-static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *);
+static irqreturn_t iodev_irqhdl(int, void *);
 
 
 
@@ -108,16 +108,12 @@
 	return misc_deregister(&miscdev);
 }
 
-
-
 static int iodev_open(struct inode *i, struct file *f)
 {
 	return request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED,
 			   iodev_name, &miscdev);
 }
 
-
-
 static int iodev_release(struct inode *i, struct file *f)
 {
 	free_irq(iodev_irq, &miscdev);
@@ -148,17 +144,13 @@
 	return POLLOUT | POLLWRNORM;
 }
 
-
-
-
-static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
+static irqreturn_t iodev_irqhdl(int irq, void *ctxt)
 {
 	wake_up(&wq);
+
 	return IRQ_HANDLED;
 }
 
-
-
 static int __init iodev_init_module(void)
 {
 	return driver_register(&iodev_driver);
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
index 511ad87..2e2061a 100644
--- a/arch/mips/basler/excite/excite_irq.c
+++ b/arch/mips/basler/excite/excite_irq.c
@@ -56,7 +56,7 @@
 #endif
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	const u32
 		interrupts = read_c0_cause() >> 8,
@@ -67,7 +67,7 @@
 
 	/* process timer interrupt */
 	if (pending & (1 << TIMER_IRQ)) {
-		do_IRQ(TIMER_IRQ, regs);
+		do_IRQ(TIMER_IRQ);
 		return;
 	}
 
@@ -80,7 +80,7 @@
 #else
 	if (pending & (1 << USB_IRQ)) {
 #endif
-		do_IRQ(USB_IRQ, regs);
+		do_IRQ(USB_IRQ);
 		return;
 	}
 
@@ -91,9 +91,9 @@
 	if ((pending & (1 << TITAN_IRQ)) && msgint) {
 		ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
 #if defined(CONFIG_KGDB)
-		excite_kgdb_inthdl(regs);
+		excite_kgdb_inthdl();
 #endif
-		do_IRQ(TITAN_IRQ, regs);
+		do_IRQ(TITAN_IRQ);
 		return;
 	}
 
@@ -102,7 +102,7 @@
 	msgintmask  = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10));
 	msgint	    = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20));
 	if ((pending & (1 << FPGA0_IRQ)) && msgint) {
-		do_IRQ(FPGA0_IRQ, regs);
+		do_IRQ(FPGA0_IRQ);
 		return;
 	}
 
@@ -111,7 +111,7 @@
 	msgintmask  = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10));
 	msgint	    = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20));
 	if ((pending & (1 << FPGA1_IRQ)) && msgint) {
-		do_IRQ(FPGA1_IRQ, regs);
+		do_IRQ(FPGA1_IRQ);
 		return;
 	}
 
@@ -120,10 +120,10 @@
 	msgintmask  = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10));
 	msgint	    = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20));
 	if ((pending & (1 << PHY_IRQ)) && msgint) {
-		do_IRQ(PHY_IRQ, regs);
+		do_IRQ(PHY_IRQ);
 		return;
 	}
 
 	/* Process spurious interrupts */
-	spurious_interrupt(regs);
+	spurious_interrupt();
 }
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index 0b75f4f..82e569d 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -16,7 +16,6 @@
 #include <asm/i8259.h>
 #include <asm/irq_cpu.h>
 #include <asm/gt64120.h>
-#include <asm/ptrace.h>
 
 #include <asm/mach-cobalt/cobalt.h>
 
@@ -42,7 +41,7 @@
  *    15  - IDE1
  */
 
-static inline void galileo_irq(struct pt_regs *regs)
+static inline void galileo_irq(void)
 {
 	unsigned int mask, pending, devfn;
 
@@ -52,7 +51,7 @@
 	if (pending & GALILEO_INTR_T0EXP) {
 
 		GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS);
-		do_IRQ(COBALT_GALILEO_IRQ, regs);
+		do_IRQ(COBALT_GALILEO_IRQ);
 
 	} else if (pending & GALILEO_INTR_RETRY_CTR) {
 
@@ -68,44 +67,31 @@
 	}
 }
 
-static inline void via_pic_irq(struct pt_regs *regs)
+static inline void via_pic_irq(void)
 {
 	int irq;
 
 	irq = i8259_irq();
 	if (irq >= 0)
-		do_IRQ(irq, regs);
+		do_IRQ(irq);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
-	unsigned pending;
+	unsigned pending = read_c0_status() & read_c0_cause();
 
-	pending = read_c0_status() & read_c0_cause();
-
-	if (pending & CAUSEF_IP2)			/* COBALT_GALILEO_IRQ (18) */
-
-		galileo_irq(regs);
-
-	else if (pending & CAUSEF_IP6)			/* COBALT_VIA_IRQ (22) */
-
-		via_pic_irq(regs);
-
-	else if (pending & CAUSEF_IP3)			/* COBALT_ETH0_IRQ (19) */
-
-		do_IRQ(COBALT_CPU_IRQ + 3, regs);
-
-	else if (pending & CAUSEF_IP4)			/* COBALT_ETH1_IRQ (20) */
-
-		do_IRQ(COBALT_CPU_IRQ + 4, regs);
-
-	else if (pending & CAUSEF_IP5)			/* COBALT_SERIAL_IRQ (21) */
-
-		do_IRQ(COBALT_CPU_IRQ + 5, regs);
-
-	else if (pending & CAUSEF_IP7)			/* IRQ 23 */
-
-		do_IRQ(COBALT_CPU_IRQ + 7, regs);
+	if (pending & CAUSEF_IP2)		/* COBALT_GALILEO_IRQ (18) */
+		galileo_irq();
+	else if (pending & CAUSEF_IP6)		/* COBALT_VIA_IRQ (22) */
+		via_pic_irq();
+	else if (pending & CAUSEF_IP3)		/* COBALT_ETH0_IRQ (19) */
+		do_IRQ(COBALT_CPU_IRQ + 3);
+	else if (pending & CAUSEF_IP4)		/* COBALT_ETH1_IRQ (20) */
+		do_IRQ(COBALT_CPU_IRQ + 4);
+	else if (pending & CAUSEF_IP5)		/* COBALT_SERIAL_IRQ (21) */
+		do_IRQ(COBALT_CPU_IRQ + 5);
+	else if (pending & CAUSEF_IP7)		/* IRQ 23 */
+		do_IRQ(COBALT_CPU_IRQ + 7);
 }
 
 static struct irqaction irq_via = {
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index 0b347cf..bf9dc72 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -50,8 +50,8 @@
 
 void __init plat_timer_setup(struct irqaction *irq)
 {
-	/* Load timer value for 1KHz (TCLK is 50MHz) */
-	GALILEO_OUTL(50*1000*1000 / 1000, GT_TC0_OFS);
+	/* Load timer value for HZ (TCLK is 50MHz) */
+	GALILEO_OUTL(50*1000*1000 / HZ, GT_TC0_OFS);
 
 	/* Enable timer */
 	GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS);
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index c6a0159..ba3bf73 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:02:58 2006
+# Linux kernel version: 2.6.19-rc1
+# Wed Oct 11 01:41:41 2006
 #
 CONFIG_MIPS=y
 
@@ -25,8 +25,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
 # CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
@@ -83,6 +81,7 @@
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -132,8 +131,8 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_SIBYTE_DMA_PAGEOPS is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
@@ -185,9 +184,11 @@
 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_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -195,7 +196,9 @@
 # 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 is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -204,12 +207,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
@@ -228,6 +231,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -249,18 +253,17 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_PCI_DEBUG=y
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
 #
-# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -271,7 +274,7 @@
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
-# CONFIG_MIPS32_N32 is not set
+CONFIG_MIPS32_N32=y
 CONFIG_BINFMT_ELF32=y
 
 #
@@ -288,6 +291,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -308,10 +312,12 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+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_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -341,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
 
@@ -368,7 +373,6 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
@@ -404,7 +408,7 @@
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -412,6 +416,7 @@
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -429,10 +434,40 @@
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# 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
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# 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_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_BLK_DEV_IDE_SWARM is not set
 # CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
@@ -441,6 +476,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)
@@ -516,6 +557,7 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -650,7 +692,6 @@
 # CONFIG_I2C_ALGOBIT is not set
 # CONFIG_I2C_ALGOPCF is not set
 # CONFIG_I2C_ALGOPCA is not set
-CONFIG_I2C_ALGO_SIBYTE=y
 
 #
 # I2C Hardware Bus support
@@ -712,12 +753,12 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -729,6 +770,7 @@
 #
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -811,6 +853,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
@@ -840,8 +883,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+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
@@ -851,6 +896,7 @@
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -881,7 +927,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -899,6 +944,10 @@
 # CONFIG_NLS is not set
 
 #
+# Distributed Lock Manager
+#
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -907,7 +956,8 @@
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_PRINTK_TIME=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
@@ -920,12 +970,15 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT 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_CROSSCOMPILE=y
@@ -946,6 +999,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_MD4=y
@@ -955,9 +1012,12 @@
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
 CONFIG_CRYPTO_SERPENT=y
 CONFIG_CRYPTO_AES=m
 # CONFIG_CRYPTO_CAST5 is not set
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
new file mode 100644
index 0000000..382083e
--- /dev/null
+++ b/arch/mips/configs/jazz_defconfig
@@ -0,0 +1,1404 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19-rc1
+# Sun Oct  8 19:03:07 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+CONFIG_MACH_JAZZ=y
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+CONFIG_OLIVETTI_M700=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARC=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_ARC32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_ARC_MEMORY=y
+CONFIG_ARC_PROMLIB=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_100HZ=y
+CONFIG_HZ=100
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=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
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# 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
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_ISA=y
+CONFIG_MMU=y
+CONFIG_I8253=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+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_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=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_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+# CONFIG_NETFILTER_XT_TARGET_CONNSECMARK is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=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=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+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_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_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_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_BAYCOM_PAR is not set
+# CONFIG_BAYCOM_EPP is not set
+# CONFIG_YAM is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# 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
+#
+CONFIG_ISCSI_TCP=m
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_JAZZ_ESP=y
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+# CONFIG_DM_CRYPT is not set
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MIPS_JAZZ_SONIC=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PLIP=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# 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
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_RTC=m
+# 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
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+# CONFIG_HFSPLUS_FS is not set
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+CONFIG_CODA_FS_OLD_API=y
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# 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
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Distributed Lock Manager
+#
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# 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_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_DES=m
+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
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index aeefe28..101e803 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:13 2006
+# Linux kernel version: 2.6.19-rc1
+# Fri Oct  6 17:34:55 2006
 #
 CONFIG_MIPS=y
 
@@ -25,8 +25,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
 # CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
@@ -67,6 +65,7 @@
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
@@ -134,19 +133,19 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT_DISABLED is not set
 # CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_MT_SMP is not set
-CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_SMP=y
+# CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_MIPS_MT=y
 CONFIG_SYS_SUPPORTS_MULTITHREADING=y
 CONFIG_MIPS_MT_FPAFF=y
-CONFIG_MIPS_VPE_LOADER_TOM=y
-CONFIG_MIPS_VPE_APSP_API=y
-CONFIG_MIPS_APSP_KSPD=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_MIPSR2_SRS=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -158,6 +157,9 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+CONFIG_SMP=y
+CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_NR_CPUS=2
 # CONFIG_HZ_48 is not set
 CONFIG_HZ_100=y
 # CONFIG_HZ_128 is not set
@@ -170,6 +172,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -178,7 +181,7 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
@@ -188,15 +191,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_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -204,12 +212,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
@@ -223,10 +231,12 @@
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
 
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -249,6 +259,7 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_MMU=y
 
 #
@@ -282,6 +293,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -313,10 +325,12 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+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"
 
 #
 # IP: Virtual Server Configuration
@@ -358,11 +372,16 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -377,6 +396,7 @@
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=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_NOTRACK=m
@@ -387,6 +407,7 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -429,7 +450,6 @@
 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
@@ -457,7 +477,6 @@
 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_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -536,13 +555,12 @@
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=y
+CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
 CONFIG_IPDDP_DECAP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -604,6 +622,7 @@
 CONFIG_IEEE80211_SOFTMAC=m
 # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -652,6 +671,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -662,6 +682,7 @@
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -699,6 +720,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=y
 # CONFIG_BLK_DEV_IT821X is not set
@@ -721,6 +743,7 @@
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -742,12 +765,13 @@
 CONFIG_SCSI_LOGGING=y
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SAS_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -765,21 +789,23 @@
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # 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_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN 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
@@ -787,6 +813,11 @@
 # CONFIG_SCSI_DEBUG 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
@@ -800,6 +831,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
@@ -854,6 +886,7 @@
 CONFIG_CICADA_PHY=m
 CONFIG_VITESSE_PHY=m
 CONFIG_SMSC_PHY=m
+# CONFIG_FIXED_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -873,6 +906,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
@@ -909,6 +943,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -956,6 +991,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -1070,12 +1106,12 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1093,6 +1129,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1191,6 +1228,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=m
 CONFIG_ROMFS_FS=m
@@ -1230,8 +1268,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
@@ -1279,7 +1319,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1336,6 +1375,11 @@
 CONFIG_NLS_UTF8=m
 
 #
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -1345,10 +1389,11 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # 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_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
@@ -1363,6 +1408,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
@@ -1372,9 +1421,12 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_DES=m
 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/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 741f825..9e672f6 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -76,7 +76,6 @@
 CONFIG_SOC_AU1100=y
 CONFIG_SOC_AU1X00=y
 CONFIG_SWAP_IO_SPACE=y
-# CONFIG_AU1X00_USB_DEVICE is not set
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 8576340..d0c0f4a 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -75,7 +75,6 @@
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SOC_AU1500=y
 CONFIG_SOC_AU1X00=y
-# CONFIG_AU1X00_USB_DEVICE is not set
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index 26b0b98..280a800 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:18 2006
+# Linux kernel version: 2.6.19-rc2
+# Sat Oct 14 23:01:16 2006
 #
 CONFIG_MIPS=y
 
@@ -25,8 +25,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
 # CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
@@ -41,13 +39,13 @@
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
-# CONFIG_PNX8550_JBS is not set
+CONFIG_PNX8550_JBS=y
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
 # CONFIG_QEMU is not set
 # CONFIG_MARKEINS is not set
-CONFIG_SGI_IP22=y
+# CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 # CONFIG_SGI_IP32 is not set
 # CONFIG_SIBYTE_BIGSUR is not set
@@ -67,25 +65,21 @@
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_ARC32=y
-CONFIG_BOOT_ELF32=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_PNX8550=y
+CONFIG_SOC_PNX8550=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
-# CONFIG_ARC_CONSOLE is not set
-CONFIG_ARC_PROMLIB=y
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R1=y
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
 # CONFIG_CPU_MIPS64_R2 is not set
@@ -93,7 +87,7 @@
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
 # CONFIG_CPU_R4300 is not set
-CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
@@ -104,12 +98,11 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R4X00=y
-CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
@@ -120,17 +113,17 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_IP22_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -144,12 +137,12 @@
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
 # CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
 # CONFIG_HZ_1024 is not set
 CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -171,16 +164,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_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=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 is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -189,12 +186,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
@@ -211,6 +208,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -231,8 +229,10 @@
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
 #
-CONFIG_HW_HAS_EISA=y
-# CONFIG_EISA is not set
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_PCI_DEBUG is not set
 CONFIG_MMU=y
 
 #
@@ -243,6 +243,7 @@
 #
 # PCI Hotplug Support
 #
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -265,6 +266,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 is not set
@@ -283,16 +285,18 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
+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_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -318,7 +322,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
 
@@ -371,13 +374,20 @@
 #
 # Block devices
 #
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -386,6 +396,7 @@
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -404,8 +415,39 @@
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# 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
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# 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_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
@@ -414,6 +456,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -434,22 +477,54 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 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
 #
 CONFIG_ISCSI_TCP=m
-# CONFIG_SGIWD93_SCSI is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# 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_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN 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_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
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -458,14 +533,19 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Network device support
@@ -477,6 +557,11 @@
 # CONFIG_TUN is not set
 
 #
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
 # PHY device support
 #
 # CONFIG_PHYLIB is not set
@@ -486,20 +571,73 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_DM9000 is not set
-# CONFIG_SGISEEQ is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
 
 #
 # Ethernet (1000 Mbit)
 #
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
 #
+# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -510,8 +648,11 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -531,6 +672,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -556,6 +698,7 @@
 CONFIG_SERIO=y
 # CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
@@ -566,7 +709,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -577,7 +720,8 @@
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_IP22_ZILOG is not set
+# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -591,16 +735,17 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_SGI_DS1286 is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
+# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -631,35 +776,37 @@
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
 # CONFIG_HWMON_DEBUG_CHIP 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
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_SGI_NEWPORT_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -669,15 +816,131 @@
 #
 # USB support
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
 #
 
 #
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# 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
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# 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
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -703,6 +966,7 @@
 #
 # InfiniBand support
 #
+# CONFIG_INFINIBAND is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -733,10 +997,12 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
 # 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 +1035,10 @@
 #
 CONFIG_PROC_FS=y
 # CONFIG_PROC_KCORE is not set
+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
@@ -813,7 +1081,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -824,7 +1091,6 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_SGI_PARTITION=y
 
 #
 # Native Language Support
@@ -880,6 +1146,7 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
@@ -893,13 +1160,17 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT 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_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
@@ -918,6 +1189,9 @@
 # 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_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -927,6 +1201,8 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index e93266b..64b9fbf 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:18 2006
+# Linux kernel version: 2.6.19-rc2
+# Sat Oct 14 23:12:15 2006
 #
 CONFIG_MIPS=y
 
@@ -25,8 +25,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
 # CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
@@ -40,14 +38,14 @@
 # CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_V2PCI is not set
+CONFIG_PNX8550_V2PCI=y
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
 # CONFIG_QEMU is not set
 # CONFIG_MARKEINS is not set
-CONFIG_SGI_IP22=y
+# CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 # CONFIG_SGI_IP32 is not set
 # CONFIG_SIBYTE_BIGSUR is not set
@@ -67,25 +65,21 @@
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_ARC32=y
-CONFIG_BOOT_ELF32=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_PNX8550=y
+CONFIG_SOC_PNX8550=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
-# CONFIG_ARC_CONSOLE is not set
-CONFIG_ARC_PROMLIB=y
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R1=y
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
 # CONFIG_CPU_MIPS64_R2 is not set
@@ -93,7 +87,7 @@
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
 # CONFIG_CPU_R4300 is not set
-CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
@@ -104,12 +98,11 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R4X00=y
-CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
@@ -120,17 +113,17 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_IP22_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -144,12 +137,12 @@
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
 # CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
 # CONFIG_HZ_1024 is not set
 CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -171,16 +164,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_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=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 is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -188,12 +185,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
@@ -210,6 +207,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -230,8 +228,9 @@
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
 #
-CONFIG_HW_HAS_EISA=y
-# CONFIG_EISA is not set
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_MMU=y
 
 #
@@ -242,6 +241,7 @@
 #
 # PCI Hotplug Support
 #
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -264,6 +264,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 is not set
@@ -282,12 +283,14 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
+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"
 
 #
 # IP: Virtual Server Configuration
@@ -300,12 +303,18 @@
 # 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=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
 # CONFIG_IPV6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -318,9 +327,9 @@
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -329,10 +338,10 @@
 # CONFIG_NETFILTER_XT_MATCH_POLICY is not set
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
@@ -373,7 +382,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
 
@@ -426,13 +434,20 @@
 #
 # Block devices
 #
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -441,6 +456,7 @@
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -459,9 +475,41 @@
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# 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
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# 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_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -469,6 +517,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -489,22 +538,59 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=m
 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
 #
 CONFIG_ISCSI_TCP=m
-# CONFIG_SGIWD93_SCSI is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC7XXX_OLD 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_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN 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_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
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -513,14 +599,19 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Network device support
@@ -532,6 +623,11 @@
 CONFIG_TUN=m
 
 #
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
 # PHY device support
 #
 # CONFIG_PHYLIB is not set
@@ -541,20 +637,73 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_DM9000 is not set
-# CONFIG_SGISEEQ is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
 
 #
 # Ethernet (1000 Mbit)
 #
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
 #
+# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -565,6 +714,8 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
 CONFIG_PPP=m
 # CONFIG_PPP_MULTILINK is not set
 # CONFIG_PPP_FILTER is not set
@@ -575,6 +726,8 @@
 CONFIG_PPP_MPPE=m
 # CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -594,6 +747,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -616,6 +770,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
@@ -630,6 +785,7 @@
 CONFIG_SERIO=y
 CONFIG_SERIO_I8042=y
 CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
@@ -640,7 +796,7 @@
 CONFIG_VT=y
 # CONFIG_VT_CONSOLE is not set
 CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_COMPUTONE is not set
 # CONFIG_ROCKETPORT is not set
@@ -650,6 +806,7 @@
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
 # CONFIG_SPECIALIX is not set
@@ -665,7 +822,8 @@
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_IP22_ZILOG is not set
+# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -679,16 +837,17 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_RTC is not set
-# CONFIG_SGI_DS1286 is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
+# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -709,14 +868,30 @@
 CONFIG_I2C_ALGOBIT=m
 # CONFIG_I2C_ALGOPCF is not set
 # CONFIG_I2C_ALGOPCA is not set
-# CONFIG_I2C_ALGO_SGI is not set
 
 #
 # I2C Hardware Bus support
 #
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
 # CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
 
 #
@@ -776,9 +951,13 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 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
@@ -790,23 +969,25 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
+# CONFIG_FB_DDC is not set
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
@@ -814,14 +995,32 @@
 # CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_SGI_NEWPORT_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
 
@@ -839,15 +1038,129 @@
 #
 # USB support
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
 #
 
 #
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# 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
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# 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
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# 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
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -873,6 +1186,7 @@
 #
 # InfiniBand support
 #
+# CONFIG_INFINIBAND is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -906,6 +1220,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
@@ -917,6 +1232,7 @@
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # 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
@@ -949,8 +1265,10 @@
 #
 CONFIG_PROC_FS=y
 # CONFIG_PROC_KCORE is not set
+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
@@ -994,7 +1312,6 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1005,7 +1322,6 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_SGI_PARTITION=y
 
 #
 # Native Language Support
@@ -1061,11 +1377,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # 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_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -1079,6 +1397,9 @@
 # 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_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -1088,6 +1409,8 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index ad7271b..f7e8194 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:21 2006
+# Linux kernel version: 2.6.19-rc2
+# Wed Oct 18 12:57:11 2006
 #
 CONFIG_MIPS=y
 
@@ -25,8 +25,6 @@
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
 # CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
@@ -72,11 +70,11 @@
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
-# CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -123,8 +121,8 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -169,15 +167,19 @@
 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_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # 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 is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -185,12 +187,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
@@ -208,6 +210,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -230,17 +233,16 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
 #
-# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -263,6 +265,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
@@ -291,13 +294,10 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 CONFIG_TCP_CONG_ADVANCED=y
-
-#
-# TCP congestion control
-#
 CONFIG_TCP_CONG_BIC=y
 CONFIG_TCP_CONG_CUBIC=m
 CONFIG_TCP_CONG_WESTWOOD=m
@@ -308,7 +308,13 @@
 # CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_TCP_CONG_LP is not set
 # CONFIG_TCP_CONG_VENO is not set
-# CONFIG_TCP_CONG_COMPOUND is not set
+CONFIG_DEFAULT_BIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="bic"
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -338,7 +344,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
 
@@ -355,6 +360,7 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_IEEE80211 is not set
+CONFIG_FIB_RULES=y
 
 #
 # Device Drivers
@@ -365,7 +371,6 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -403,6 +408,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -410,65 +416,14 @@
 #
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-CONFIG_BLK_DEV_SIIMAGE=y
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -489,12 +444,13 @@
 # CONFIG_SCSI_LOGGING 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
@@ -507,21 +463,24 @@
 # 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_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN 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
@@ -529,6 +488,59 @@
 # CONFIG_SCSI_DEBUG 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_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=y
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -632,6 +644,7 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -679,6 +692,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -758,7 +772,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -784,12 +797,12 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -897,13 +910,13 @@
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # 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
 
 #
@@ -932,6 +945,7 @@
 # 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
@@ -963,16 +977,17 @@
 #
 # 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
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 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
@@ -1041,6 +1056,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
@@ -1052,6 +1068,7 @@
 # CONFIG_XFS_SECURITY is not set
 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=m
@@ -1082,8 +1099,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
@@ -1123,7 +1142,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1150,11 +1168,13 @@
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # 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_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
 
@@ -1170,10 +1190,6 @@
 # CONFIG_CRYPTO is not set
 
 #
-# Hardware crypto devices
-#
-
-#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 513fc67..a8bd2e6 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -153,8 +153,7 @@
  * the first level int-handler will jump here if it is a vrc5477 irq
  */
 #define	NUM_5477_IRQS	32
-static void
-vrc5477_irq_dispatch(struct pt_regs *regs)
+static void vrc5477_irq_dispatch(void)
 {
 	u32 intStatus;
 	u32 bitmask;
@@ -178,7 +177,7 @@
 		/* check for i8259 interrupts */
 		if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
 			int i8259_irq = i8259_interrupt_ack();
-			do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
+			do_IRQ(I8259_IRQ_BASE + i8259_irq);
 			return;
 		}
 	}
@@ -186,7 +185,7 @@
 	for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) {
 		/* do we need to "and" with the int mask? */
 		if (intStatus & bitmask) {
-			do_IRQ(VRC5477_IRQ_BASE + i, regs);
+			do_IRQ(VRC5477_IRQ_BASE + i);
 			return;
 		}
 	}
@@ -194,18 +193,18 @@
 
 #define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status();
 
 	if (pending & STATUSF_IP7)
-		do_IRQ(CPU_IRQ_BASE + 7, regs);
+		do_IRQ(CPU_IRQ_BASE + 7);
 	else if (pending & VR5477INTS)
-		vrc5477_irq_dispatch(regs);
+		vrc5477_irq_dispatch();
 	else if (pending & STATUSF_IP0)
-		do_IRQ(CPU_IRQ_BASE, regs);
+		do_IRQ(CPU_IRQ_BASE);
 	else if (pending & STATUSF_IP1)
-		do_IRQ(CPU_IRQ_BASE + 1, regs);
+		do_IRQ(CPU_IRQ_BASE + 1);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index cc24c5e..3e374d0 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -24,6 +24,7 @@
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/irq_regs.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/traps.h>
@@ -200,8 +201,10 @@
 	return dec_ecc_be_backend(regs, is_fixup, 0);
 }
 
-irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id)
 {
+	struct pt_regs *regs = get_irq_regs();
+
 	int action = dec_ecc_be_backend(regs, 0, 1);
 
 	if (action == MIPS_BE_DISCARD)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 455a65b..31dd47d 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -264,10 +264,10 @@
 		 srlv	t3,t1,t2
 
 handle_it:
-		jal	do_IRQ
-		 move	a1,sp
-
-		j	ret_from_irq
+		LONG_L	s0, TI_REGS($28)
+		LONG_S	sp, TI_REGS($28)
+		PTR_LA	ra, ret_from_irq
+		j	do_IRQ
 		 nop
 
 #ifdef CONFIG_32BIT
@@ -277,9 +277,8 @@
 #endif
 
 spurious:
-		jal	spurious_interrupt
-		 nop
-		j	ret_from_irq
+		PTR_LA	ra, _ret_from_irq
+		j	spurious_interrupt
 		 nop
 		END(plat_irq_dispatch)
 
diff --git a/arch/mips/dec/kn01-berr.c b/arch/mips/dec/kn01-berr.c
index b9271db..f19b461 100644
--- a/arch/mips/dec/kn01-berr.c
+++ b/arch/mips/dec/kn01-berr.c
@@ -150,10 +150,10 @@
 	return dec_kn01_be_backend(regs, is_fixup, 0);
 }
 
-irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs)
+irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id)
 {
 	volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
+	struct pt_regs *regs = get_irq_regs();
 	int action;
 
 	if (!(*csr & KN01_CSR_MEMERR))
diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c
index 6cd3f94..7a053aa 100644
--- a/arch/mips/dec/kn02xa-berr.c
+++ b/arch/mips/dec/kn02xa-berr.c
@@ -21,6 +21,8 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/traps.h>
 
@@ -104,9 +106,9 @@
 	return dec_kn02xa_be_backend(regs, is_fixup, 0);
 }
 
-irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs)
+irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id)
 {
+	struct pt_regs *regs = get_irq_regs();
 	int action = dec_kn02xa_be_backend(regs, 0, 1);
 
 	if (action == MIPS_BE_DISCARD)
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
index f78c6da..5639722 100644
--- a/arch/mips/dec/reset.c
+++ b/arch/mips/dec/reset.c
@@ -8,7 +8,6 @@
 #include <linux/linkage.h>
 
 #include <asm/addrspace.h>
-#include <asm/ptrace.h>
 
 typedef void ATTRIB_NORET (* noret_func_t)(void);
 
@@ -35,7 +34,7 @@
 	back_to_prom();
 }
 
-irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t dec_intr_halt(int irq, void *dev_id)
 {
 	dec_machine_halt();
 }
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index d43241c..6b7481e 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -46,7 +46,7 @@
 extern void dec_machine_restart(char *command);
 extern void dec_machine_halt(void);
 extern void dec_machine_power_off(void);
-extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t dec_intr_halt(int irq, void *dev_id);
 
 unsigned long dec_kn_slot_base, dec_kn_slot_size;
 
diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c
index 3af5769..c191b3e 100644
--- a/arch/mips/emma2rh/common/irq.c
+++ b/arch/mips/emma2rh/common/irq.c
@@ -39,7 +39,7 @@
 /*
  * the first level int-handler will jump here if it is a emma2rh irq
  */
-asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs)
+void emma2rh_irq_dispatch(void)
 {
 	u32 intStatus;
 	u32 bitmask;
@@ -56,7 +56,7 @@
 		    & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
 		for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
 			if (swIntStatus & bitmask) {
-				do_IRQ(EMMA2RH_SW_IRQ_BASE + i, regs);
+				do_IRQ(EMMA2RH_SW_IRQ_BASE + i);
 				return;
 			}
 		}
@@ -65,7 +65,7 @@
 
 	for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
 		if (intStatus & bitmask) {
-			do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+			do_IRQ(EMMA2RH_IRQ_BASE + i);
 			return;
 		}
 	}
@@ -81,7 +81,7 @@
 		    & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 		for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
 			if (gpioIntStatus & bitmask) {
-				do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i, regs);
+				do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i);
 				return;
 			}
 		}
@@ -90,7 +90,7 @@
 
 	for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
 		if (intStatus & bitmask) {
-			do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+			do_IRQ(EMMA2RH_IRQ_BASE + i);
 			return;
 		}
 	}
@@ -100,7 +100,7 @@
 
 	for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
 		if (intStatus & bitmask) {
-			do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+			do_IRQ(EMMA2RH_IRQ_BASE + i);
 			return;
 		}
 	}
diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c
index 2a736be..c93369c 100644
--- a/arch/mips/emma2rh/markeins/irq.c
+++ b/arch/mips/emma2rh/markeins/irq.c
@@ -57,7 +57,7 @@
 extern void emma2rh_sw_irq_init(u32 base);
 extern void emma2rh_gpio_irq_init(u32 base);
 extern void emma2rh_irq_init(u32 base);
-extern asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs);
+extern void emma2rh_irq_dispatch(void);
 
 static struct irqaction irq_cascade = {
 	   .handler = no_action,
@@ -114,20 +114,20 @@
 	setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
         unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & STATUSF_IP7)
-		do_IRQ(CPU_IRQ_BASE + 7, regs);
+		do_IRQ(CPU_IRQ_BASE + 7);
 	else if (pending & STATUSF_IP2)
-		emma2rh_irq_dispatch(regs);
+		emma2rh_irq_dispatch();
 	else if (pending & STATUSF_IP1)
-		do_IRQ(CPU_IRQ_BASE + 1, regs);
+		do_IRQ(CPU_IRQ_BASE + 1);
 	else if (pending & STATUSF_IP0)
-		do_IRQ(CPU_IRQ_BASE + 0, regs);
+		do_IRQ(CPU_IRQ_BASE + 0);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 
diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c
index 7feca49..c83ae6a 100644
--- a/arch/mips/gt64120/common/time.c
+++ b/arch/mips/gt64120/common/time.c
@@ -10,7 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
-#include <asm/ptrace.h>
+#include <asm/irq_regs.h>
 #include <asm/gt64120.h>
 
 /*
@@ -19,7 +19,7 @@
  * differently than other MIPS interrupts.
  */
 
-static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gt64120_irq(int irq, void *dev_id)
 {
 	unsigned int irq_src, int_high_src, irq_src_mask, int_high_src_mask;
 	int handled = 0;
@@ -36,12 +36,14 @@
 		irq_src &= ~0x00000800;
 		do_timer(1);
 #ifndef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 	}
 
 	GT_WRITE(GT_INTRCAUSE_OFS, 0);
 	GT_WRITE(GT_HINTRCAUSE_OFS, 0);
+
+	return IRQ_HANDLED;
 }
 
 /*
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index 5d939ac..ed4d82b 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -46,22 +46,22 @@
 #include <asm/system.h>
 #include <asm/gt64120.h>
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & STATUSF_IP4)		/* int2 hardware line (timer) */
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	else if (pending & STATUSF_IP2)		/* int0 hardware line */
-		do_IRQ(GT_INTA, regs);
+		do_IRQ(GT_INTA);
 	else if (pending & STATUSF_IP5)		/* int3 hardware line */
-		do_IRQ(GT_INTD, regs);
+		do_IRQ(GT_INTD);
 	else if (pending & STATUSF_IP6)		/* int4 hardware line */
-		do_IRQ(6, regs);
+		do_IRQ(6);
 	else if (pending & STATUSF_IP7)		/* compare int */
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 static void disable_ev64120_irq(unsigned int irq_nr)
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
index 4236da3..91c2d3f 100644
--- a/arch/mips/gt64120/ev64120/setup.c
+++ b/arch/mips/gt64120/ev64120/setup.c
@@ -42,7 +42,6 @@
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
 #include <asm/traps.h>
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index 885f67f..d929440 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -48,22 +48,22 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & STATUSF_IP2)		/* int0 hardware line */
-		do_IRQ(2, regs);
+		do_IRQ(2);
 	else if (pending & STATUSF_IP3)		/* int1 hardware line */
-		do_IRQ(3, regs);
+		do_IRQ(3);
 	else if (pending & STATUSF_IP4)		/* int2 hardware line */
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	else if (pending & STATUSF_IP5)		/* int3 hardware line */
-		do_IRQ(5, regs);
+		do_IRQ(5);
 	else if (pending & STATUSF_IP6)		/* int4 hardware line */
-		do_IRQ(6, regs);
+		do_IRQ(6);
 	else if (pending & STATUSF_IP7)		/* cpu timer */
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	else {
 		/*
 		 * Now look at the extended interrupts
@@ -71,13 +71,13 @@
 		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
 
 		if (pending & STATUSF_IP8)		/* int6 hardware line */
-			do_IRQ(8, regs);
+			do_IRQ(8);
 		else if (pending & STATUSF_IP9)		/* int7 hardware line */
-			do_IRQ(9, regs);
+			do_IRQ(9);
 		else if (pending & STATUSF_IP10)	/* int8 hardware line */
-			do_IRQ(10, regs);
+			do_IRQ(10);
 		else if (pending & STATUSF_IP11)	/* int9 hardware line */
-			do_IRQ(11, regs);
+			do_IRQ(11);
 	}
 }
 
diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c
index 9804642..0e5bbee 100644
--- a/arch/mips/gt64120/momenco_ocelot/setup.c
+++ b/arch/mips/gt64120/momenco_ocelot/setup.c
@@ -56,7 +56,6 @@
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/traps.h>
 #include <linux/bootmem.h>
diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c
index 8d75a43..eedfc24 100644
--- a/arch/mips/gt64120/wrppmc/irq.c
+++ b/arch/mips/gt64120/wrppmc/irq.c
@@ -30,18 +30,18 @@
 #include <asm/irq_cpu.h>
 #include <asm/gt64120.h>
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & STATUSF_IP7)
-		do_IRQ(WRPPMC_MIPS_TIMER_IRQ, regs);	/* CPU Compare/Count internal timer */
+		do_IRQ(WRPPMC_MIPS_TIMER_IRQ);	/* CPU Compare/Count internal timer */
 	else if (pending & STATUSF_IP6)
-		do_IRQ(WRPPMC_UART16550_IRQ, regs);	/* UART 16550 port */
+		do_IRQ(WRPPMC_UART16550_IRQ);	/* UART 16550 port */
 	else if (pending & STATUSF_IP3)
-		do_IRQ(WRPPMC_PCI_INTA_IRQ, regs);	/* PCI INT_A */
+		do_IRQ(WRPPMC_PCI_INTA_IRQ);	/* PCI INT_A */
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 /**
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index eef0509..d5bd6b3 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -94,26 +94,26 @@
 	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
 }
 
-static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
+static void loc_call(unsigned int irq, unsigned int mask)
 {
 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
 	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
 	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
 }
 
-static void ll_local_dev(struct pt_regs *regs)
+static void ll_local_dev(void)
 {
 	switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
 	case 0:
 		panic("Unimplemented loc_no_irq handler");
 		break;
 	case 4:
-		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
+		loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_PARALLEL);
 		break;
 	case 8:
-		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
+		loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_FLOPPY);
 		break;
 	case 12:
 		panic("Unimplemented loc_sound handler");
@@ -122,27 +122,27 @@
 		panic("Unimplemented loc_video handler");
 		break;
 	case 20:
-		loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
+		loc_call(JAZZ_ETHERNET_IRQ, JAZZ_IE_ETHERNET);
 		break;
 	case 24:
-		loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
+		loc_call(JAZZ_SCSI_IRQ, JAZZ_IE_SCSI);
 		break;
 	case 28:
-		loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
+		loc_call(JAZZ_KEYBOARD_IRQ, JAZZ_IE_KEYBOARD);
 		break;
 	case 32:
-		loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
+		loc_call(JAZZ_MOUSE_IRQ, JAZZ_IE_MOUSE);
 		break;
 	case 36:
-		loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
+		loc_call(JAZZ_SERIAL1_IRQ, JAZZ_IE_SERIAL1);
 		break;
 	case 40:
-		loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
+		loc_call(JAZZ_SERIAL2_IRQ, JAZZ_IE_SERIAL2);
 		break;
 	}
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 
@@ -150,13 +150,13 @@
 		write_c0_compare(0);
 	else if (pending & IE_IRQ4) {
 		r4030_read_reg32(JAZZ_TIMER_REGISTER);
-		do_IRQ(JAZZ_TIMER_IRQ, regs);
+		do_IRQ(JAZZ_TIMER_IRQ);
 	} else if (pending & IE_IRQ3)
 		panic("Unimplemented ISA NMI handler");
 	else if (pending & IE_IRQ2)
-		do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
+		do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK));
 	else if (pending & IE_IRQ1) {
-		ll_local_dev(regs);
+		ll_local_dev();
 	} else if (unlikely(pending & IE_IRQ0))
 		panic("Unimplemented local_dma handler");
 	else if (pending & IE_SW1) {
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index 487a9ea..d848f1a 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -19,12 +19,12 @@
 #include <linux/fb.h>
 #include <linux/ide.h>
 #include <linux/pm.h>
+#include <linux/screen_info.h>
 
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/jazz.h>
 #include <asm/jazzdma.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -37,7 +37,7 @@
 extern void jazz_machine_halt(void);
 extern void jazz_machine_power_off(void);
 
-void __init plat_time_init(struct irqaction *irq)
+void __init plat_timer_setup(struct irqaction *irq)
 {
 	/* set the clock to 100 Hz */
 	r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
@@ -45,10 +45,27 @@
 }
 
 static struct resource jazz_io_resources[] = {
-	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+	{
+		.start	= 0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.end	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	}
 };
 
 void __init plat_mem_setup(void)
@@ -81,8 +98,6 @@
 	_machine_halt = jazz_machine_halt;
 	pm_power_off = jazz_machine_power_off;
 
-#warning "Somebody should check if screen_info is ok for Jazz."
-
 	screen_info = (struct screen_info) {
 		0, 0,		/* orig-x, orig-y */
 		0,		/* unused */
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 7221744..39a0243 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -46,6 +46,7 @@
 #include <linux/smp_lock.h>
 #include <linux/bitops.h>
 
+#include <asm/irq_regs.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
@@ -239,45 +240,80 @@
 	.space_id = 0,
 	can_share : 1
 };
+
 struct tb_irq_space jmr3927_irc_irqspace = {
-	.next = NULL,
-	.start_irqno = JMR3927_IRQ_IRC,
-	nr_irqs : JMR3927_NR_IRQ_IRC,
-	.mask_func = mask_irq_irc,
-	.unmask_func = unmask_irq_irc,
-	.name = "on-chip",
-	.space_id = 0,
-	can_share : 0
+	.next		= NULL,
+	.start_irqno	= JMR3927_IRQ_IRC,
+	.nr_irqs	= JMR3927_NR_IRQ_IRC,
+	.mask_func	= mask_irq_irc,
+	.unmask_func	= unmask_irq_irc,
+	.name		= "on-chip",
+	.space_id	= 0,
+	.can_share	= 0
 };
 
-void jmr3927_spurious(struct pt_regs *regs)
+
+#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
+static int tx_branch_likely_bug_count = 0;
+static int have_tx_branch_likely_bug = 0;
+
+static void tx_branch_likely_bug_fixup(void)
+{
+	struct pt_regs *regs = get_irq_regs();
+
+	/* TX39/49-BUG: Under this condition, the insn in delay slot
+           of the branch likely insn is executed (not nullified) even
+           the branch condition is false. */
+	if (!have_tx_branch_likely_bug)
+		return;
+	if ((regs->cp0_epc & 0xfff) == 0xffc &&
+	    KSEGX(regs->cp0_epc) != KSEG0 &&
+	    KSEGX(regs->cp0_epc) != KSEG1) {
+		unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4);
+		/* beql,bnel,blezl,bgtzl */
+		/* bltzl,bgezl,blezall,bgezall */
+		/* bczfl, bcztl */
+		if ((insn & 0xf0000000) == 0x50000000 ||
+		    (insn & 0xfc0e0000) == 0x04020000 ||
+		    (insn & 0xf3fe0000) == 0x41020000) {
+			regs->cp0_epc -= 4;
+			tx_branch_likely_bug_count++;
+			printk(KERN_INFO
+			       "fix branch-likery bug in %s (insn %08x)\n",
+			       current->comm, insn);
+		}
+	}
+}
+#endif
+
+static void jmr3927_spurious(void)
 {
 #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
-	tx_branch_likely_bug_fixup(regs);
+	tx_branch_likely_bug_fixup();
 #endif
 	printk(KERN_WARNING "spurious interrupt (cause 0x%lx, pc 0x%lx, ra 0x%lx).\n",
 	       regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	int irq;
 
 #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
-	tx_branch_likely_bug_fixup(regs);
+	tx_branch_likely_bug_fixup();
 #endif
 	if ((regs->cp0_cause & CAUSEF_IP7) == 0) {
 #if 0
-		jmr3927_spurious(regs);
+		jmr3927_spurious();
 #endif
 		return;
 	}
 	irq = (regs->cp0_cause >> CAUSEB_IP2) & 0x0f;
 
-	do_IRQ(irq + JMR3927_IRQ_IRC, regs);
+	do_IRQ(irq + JMR3927_IRQ_IRC);
 }
 
-static irqreturn_t jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t jmr3927_ioc_interrupt(int irq, void *dev_id)
 {
 	unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR);
 	int i;
@@ -285,7 +321,7 @@
 	for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) {
 		if (istat & (1 << i)) {
 			irq = JMR3927_IRQ_IOC + i;
-			do_IRQ(irq, regs);
+			do_IRQ(irq);
 		}
 	}
 	return IRQ_HANDLED;
@@ -295,7 +331,7 @@
 	jmr3927_ioc_interrupt, 0, CPU_MASK_NONE, "IOC", NULL, NULL,
 };
 
-static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id)
 {
 	unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR);
 	int i;
@@ -303,7 +339,7 @@
 	for (i = 0; i < JMR3927_NR_IRQ_ISAC; i++) {
 		if (istat & (1 << i)) {
 			irq = JMR3927_IRQ_ISAC + i;
-			do_IRQ(irq, regs);
+			do_IRQ(irq);
 		}
 	}
 	return IRQ_HANDLED;
@@ -314,7 +350,7 @@
 };
 
 
-static irqreturn_t jmr3927_isaerr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t jmr3927_isaerr_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq);
 
@@ -324,7 +360,7 @@
 	jmr3927_isaerr_interrupt, 0, CPU_MASK_NONE, "ISA error", NULL, NULL,
 };
 
-static irqreturn_t jmr3927_pcierr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t jmr3927_pcierr_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq);
 	printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n",
@@ -439,33 +475,3 @@
 
 	jmr3927_irq_base = irq_base;
 }
-
-#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
-static int tx_branch_likely_bug_count = 0;
-static int have_tx_branch_likely_bug = 0;
-void tx_branch_likely_bug_fixup(struct pt_regs *regs)
-{
-	/* TX39/49-BUG: Under this condition, the insn in delay slot
-           of the branch likely insn is executed (not nullified) even
-           the branch condition is false. */
-	if (!have_tx_branch_likely_bug)
-		return;
-	if ((regs->cp0_epc & 0xfff) == 0xffc &&
-	    KSEGX(regs->cp0_epc) != KSEG0 &&
-	    KSEGX(regs->cp0_epc) != KSEG1) {
-		unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4);
-		/* beql,bnel,blezl,bgtzl */
-		/* bltzl,bgezl,blezall,bgezall */
-		/* bczfl, bcztl */
-		if ((insn & 0xf0000000) == 0x50000000 ||
-		    (insn & 0xfc0e0000) == 0x04020000 ||
-		    (insn & 0xf3fe0000) == 0x41020000) {
-			regs->cp0_epc -= 4;
-			tx_branch_likely_bug_count++;
-			printk(KERN_INFO
-			       "fix branch-likery bug in %s (insn %08x)\n",
-			       current->comm, insn);
-		}
-	}
-}
-#endif
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ec28077..e9ce5b3 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -93,11 +93,12 @@
 	offset("#define TI_TASK            ", struct thread_info, task);
 	offset("#define TI_EXEC_DOMAIN     ", struct thread_info, exec_domain);
 	offset("#define TI_FLAGS           ", struct thread_info, flags);
+	offset("#define TI_TP_VALUE	   ", struct thread_info, tp_value);
 	offset("#define TI_CPU             ", struct thread_info, cpu);
 	offset("#define TI_PRE_COUNT       ", struct thread_info, preempt_count);
 	offset("#define TI_ADDR_LIMIT      ", struct thread_info, addr_limit);
 	offset("#define TI_RESTART_BLOCK   ", struct thread_info, restart_block);
-	offset("#define TI_TP_VALUE	   ", struct thread_info, tp_value);
+	offset("#define TI_REGS            ", struct thread_info, regs);
 	constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
 	constant("#define _THREAD_SIZE       ", THREAD_SIZE);
 	constant("#define _THREAD_MASK       ", THREAD_MASK);
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 9fbf843..8485af3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -135,7 +135,6 @@
 	case CPU_R5000:
 	case CPU_NEVADA:
 	case CPU_RM7000:
-	case CPU_RM9000:
 	case CPU_4KC:
 	case CPU_4KEC:
 	case CPU_4KSC:
@@ -164,6 +163,14 @@
 		} else
 			printk(" unavailable.\n");
 		break;
+	case CPU_RM9000:
+		if ((c->processor_id & 0x00ff) >= 0x40) {
+			cpu_wait = r4k_wait;
+			printk(" available.\n");
+		} else {
+			printk(" unavailable.\n");
+		}
+		break;
 	default:
 		printk(" unavailable.\n");
 		break;
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 766655f..417c08a 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -20,10 +20,7 @@
 #include <asm/mipsmtregs.h>
 #endif
 
-#ifdef CONFIG_PREEMPT
-	.macro	preempt_stop
-	.endm
-#else
+#ifndef CONFIG_PREEMPT
 	.macro	preempt_stop
 	local_irq_disable
 	.endm
@@ -32,9 +29,16 @@
 
 	.text
 	.align	5
+FEXPORT(ret_from_irq)
+	LONG_S	s0, TI_REGS($28)
+#ifdef CONFIG_PREEMPT
+FEXPORT(ret_from_exception)
+#else
+	b	_ret_from_irq
 FEXPORT(ret_from_exception)
 	preempt_stop
-FEXPORT(ret_from_irq)
+#endif
+FEXPORT(_ret_from_irq)
 	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
 	andi	t0, t0, KU_USER
 	beqz	t0, resume_kernel
@@ -79,7 +83,6 @@
 FEXPORT(restore_all)			# restore full frame
 #ifdef CONFIG_MIPS_MT_SMTC
 /* Detect and execute deferred IPI "interrupts" */
-	move	a0,sp
 	jal	deferred_smtc_ipi
 /* Re-arm any temporarily masked interrupts not explicitly "acked" */
 	mfc0	v0, CP0_TCSTATUS
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index af6ef2f..5baca16 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -131,8 +131,9 @@
 	CLI
 	TRACE_IRQS_OFF
 
+	LONG_L	s0, TI_REGS($28)
+	LONG_S	sp, TI_REGS($28)
 	PTR_LA	ra, ret_from_irq
-	move	a0, sp
 	j	plat_irq_dispatch
 	END(handle_int)
 
@@ -219,7 +220,9 @@
 #endif /* CONFIG_MIPS_MT_SMTC */
 	CLI
 	TRACE_IRQS_OFF
-	move	a0, sp
+
+	LONG_L	s0, TI_REGS($28)
+	LONG_S	sp, TI_REGS($28)
 	PTR_LA	ra, ret_from_irq
 	jr	v0
 	END(except_vec_vi_handler)
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 63dfeb4..650a80c 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -1,16 +1,17 @@
 /*
- * Copyright (c) 2004 MIPS Inc
- * Author: chris@mips.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.
+ *
+ * Copyright (c) 2004 MIPS Inc
+ * Author: chris@mips.com
+ *
+ * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <asm/ptrace.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
@@ -115,14 +116,14 @@
 /*
  * Interrupt handler for interrupts coming from SOC-it.
  */
-void ll_msc_irq(struct pt_regs *regs)
+void ll_msc_irq(void)
 {
  	unsigned int irq;
 
 	/* read the interrupt vector register */
 	MSCIC_READ(MSC01_IC_VEC, irq);
 	if (irq < 64)
-		do_IRQ(irq + irq_base, regs);
+		do_IRQ(irq + irq_base);
 	else {
 		/* Ignore spurious interrupt */
 	}
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
index b117e64..37d1062 100644
--- a/arch/mips/kernel/irq-mv6434x.c
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -1,7 +1,7 @@
 /*
  * Copyright 2002 Momentum Computer
  * Author: mdharm@momenco.com
- * Copyright (C) 2004 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
  *
  * 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
@@ -15,7 +15,6 @@
 #include <linux/mv643xx.h>
 #include <linux/sched.h>
 
-#include <asm/ptrace.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/marvell.h>
@@ -113,7 +112,7 @@
  * Interrupt handler for interrupts coming from the Marvell chip.
  * It could be built in ethernet ports etc...
  */
-void ll_mv64340_irq(struct pt_regs *regs)
+void ll_mv64340_irq(void)
 {
 	unsigned int irq_src_low, irq_src_high;
  	unsigned int irq_mask_low, irq_mask_high;
@@ -129,9 +128,9 @@
 	irq_src_high &= irq_mask_high;
 
 	if (irq_src_low)
-		do_IRQ(ls1bit32(irq_src_low) + irq_base, regs);
+		do_IRQ(ls1bit32(irq_src_low) + irq_base);
 	else
-		do_IRQ(ls1bit32(irq_src_high) + irq_base + 32, regs);
+		do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
 }
 
 #define shutdown_mv64340_irq	disable_mv64340_irq
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index d955aae..dd24434 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -53,12 +53,12 @@
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
-asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs)
+asmlinkage unsigned int do_IRQ(unsigned int irq)
 {
 	irq_enter();
 
 	__DO_IRQ_SMTC_HOOK();
-	__do_IRQ(irq, regs);
+	__do_IRQ(irq);
 
 	irq_exit();
 
@@ -110,7 +110,7 @@
 	return 0;
 }
 
-asmlinkage void spurious_interrupt(struct pt_regs *regs)
+asmlinkage void spurious_interrupt(void)
 {
 	atomic_inc(&irq_err_count);
 }
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 53f4171..7a3ebbe 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -1055,7 +1055,9 @@
 asmlinkage int sys32_personality(unsigned long personality)
 {
 	int ret;
-	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+	personality &= 0xffffffff;
+	if (personality(current->personality) == PER_LINUX32 &&
+	    personality == PER_LINUX)
 		personality = PER_LINUX32;
 	ret = sys_personality(personality);
 	if (ret == PER_LINUX32)
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index d8beef1..4ed37ba 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -89,9 +89,9 @@
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	unsigned int version = current_cpu_data.processor_id;
-	unsigned int fp_vers = current_cpu_data.fpu_id;
 	unsigned long n = (unsigned long) v - 1;
+	unsigned int version = cpu_data[n].processor_id;
+	unsigned int fp_vers = cpu_data[n].fpu_id;
 	char fmt [64];
 
 #ifdef CONFIG_SMP
@@ -107,9 +107,9 @@
 
 	seq_printf(m, "processor\t\t: %ld\n", n);
 	sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
-	        cpu_has_fpu ? "  FPU V%d.%d" : "");
-	seq_printf(m, fmt, cpu_name[current_cpu_data.cputype <= CPU_LAST ?
-	                            current_cpu_data.cputype : CPU_UNKNOWN],
+	        cpu_data[n].options & MIPS_CPU_FPU ? "  FPU V%d.%d" : "");
+	seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ?
+	                            cpu_data[n].cputype : CPU_UNKNOWN],
 	                           (version >> 4) & 0x0f, version & 0x0f,
 	                           (fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
 	seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n",
@@ -118,7 +118,7 @@
 	seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no");
 	seq_printf(m, "microsecond timers\t: %s\n",
 	              cpu_has_counter ? "yes" : "no");
-	seq_printf(m, "tlb_entries\t\t: %d\n", current_cpu_data.tlbsize);
+	seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize);
 	seq_printf(m, "extra interrupt vector\t: %s\n",
 	              cpu_has_divec ? "yes" : "no");
 	seq_printf(m, "hardware watchpoint\t: %s\n",
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 045d987..ec8209f 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -115,7 +115,7 @@
 	status |= KU_USER;
 	regs->cp0_status = status;
 	clear_used_math();
-	lose_fpu();
+	clear_fpu_owner();
 	if (cpu_has_dsp)
 		__init_dsp();
 	regs->cp0_epc = pc;
@@ -358,10 +358,8 @@
 	unsigned long size = 0;
 #ifdef CONFIG_KALLSYMS
 	unsigned long ofs;
-	char *modname;
-	char namebuf[KSYM_NAME_LEN + 1];
 
-	kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf);
+	kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs);
 #endif
 	schedule_mfi.func = schedule;
 	schedule_mfi.func_size = size;
@@ -403,8 +401,6 @@
 {
 	unsigned long stack_page;
 	struct mips_frame_info info;
-	char *modname;
-	char namebuf[KSYM_NAME_LEN + 1];
 	unsigned long size, ofs;
 	int leaf;
 	extern void ret_from_irq(void);
@@ -433,7 +429,7 @@
 		}
 		return 0;
 	}
-	if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf))
+	if (!kallsyms_lookup_size_offset(pc, &size, &ofs))
 		return 0;
 	/*
 	 * Return ra if an exception occured at the first instruction
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 362d172..258d74f 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -106,6 +106,7 @@
 int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
 {
 	int i;
+	unsigned int tmp;
 
 	if (!access_ok(VERIFY_WRITE, data, 33 * 8))
 		return -EIO;
@@ -121,10 +122,10 @@
 
 	__put_user (child->thread.fpu.fcr31, data + 64);
 
+	preempt_disable();
 	if (cpu_has_fpu) {
-		unsigned int flags, tmp;
+		unsigned int flags;
 
-		preempt_disable();
 		if (cpu_has_mipsmt) {
 			unsigned int vpflags = dvpe();
 			flags = read_c0_status();
@@ -138,11 +139,11 @@
 			__asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
 			write_c0_status(flags);
 		}
-		preempt_enable();
-		__put_user (tmp, data + 65);
 	} else {
-		__put_user ((__u32) 0, data + 65);
+		tmp = 0;
 	}
+	preempt_enable();
+	__put_user (tmp, data + 65);
 
 	return 0;
 }
@@ -245,16 +246,17 @@
 			unsigned int mtflags;
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-			if (!cpu_has_fpu)
+			preempt_disable();
+			if (!cpu_has_fpu) {
+				preempt_enable();
 				break;
+			}
 
 #ifdef CONFIG_MIPS_MT_SMTC
 			/* Read-modify-write of Status must be atomic */
 			local_irq_save(irqflags);
 			mtflags = dmt();
 #endif /* CONFIG_MIPS_MT_SMTC */
-
-			preempt_disable();
 			if (cpu_has_mipsmt) {
 				unsigned int vpflags = dvpe();
 				flags = read_c0_status();
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index f40ecd8..d9a39c1 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -175,7 +175,9 @@
 			unsigned int mtflags;
 #endif /* CONFIG_MIPS_MT_SMTC */
 
+			preempt_disable();
 			if (!cpu_has_fpu) {
+				preempt_enable();
 				tmp = 0;
 				break;
 			}
@@ -186,7 +188,6 @@
 			mtflags = dmt();
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-			preempt_disable();
 			if (cpu_has_mipsmt) {
 				unsigned int vpflags = dvpe();
 				flags = read_c0_status();
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index cdab1b2..8c8c832 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -61,16 +61,16 @@
 
 extern void *vpe_get_shared(int index);
 
-static void rtlx_dispatch(struct pt_regs *regs)
+static void rtlx_dispatch(void)
 {
-	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
+	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ);
 }
 
 
 /* Interrupt handler may be called before rtlx_init has otherwise had
    a chance to run.
 */
-static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
 {
 	int i;
 
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 61362e6..720fac3 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -652,7 +652,8 @@
 	sys	sys_vmsplice		4
 	sys	sys_move_pages		6
 	sys	sys_set_robust_list	2
-	sys	sys_get_robust_list	3
+	sys	sys_get_robust_list	3	/* 4310 */
+	sys	sys_ni_syscall		0
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 6c7b5ed..3a34f62 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -468,3 +468,4 @@
 	PTR	sys_move_pages
 	PTR	sys_set_robust_list
 	PTR	sys_get_robust_list
+	PTR	sys_ni_syscall			/* 5270 */
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6d9f187..67b92a1 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -280,7 +280,7 @@
 	PTR	sys_sync
 	PTR	sys_acct
 	PTR	sys32_settimeofday
-	PTR	sys_mount			/* 6160 */
+	PTR	compat_sys_mount		/* 6160 */
 	PTR	sys_umount
 	PTR	sys_swapon
 	PTR	sys_swapoff
@@ -394,3 +394,4 @@
 	PTR	sys_move_pages
 	PTR	compat_sys_set_robust_list
 	PTR	compat_sys_get_robust_list
+	PTR	sys_ni_syscall
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 2e6d067..2875c4a 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -226,7 +226,7 @@
 	PTR	sys_ni_syscall			/* was sys_stat */
 	PTR	sys_lseek
 	PTR	sys_getpid			/* 4020 */
-	PTR	sys_mount
+	PTR	compat_sys_mount
 	PTR	sys_oldumount
 	PTR	sys_setuid
 	PTR	sys_getuid
@@ -516,4 +516,5 @@
 	PTR	compat_sys_move_pages
 	PTR	compat_sys_set_robust_list
 	PTR	compat_sys_get_robust_list	/* 4310 */
+	PTR	sys_ni_syscall
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 766253c..3b5f3b6 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -106,22 +106,22 @@
 	clear_c0_mvpcontrol(MVPCONTROL_VPC);
 }
 
-static void ipi_resched_dispatch (struct pt_regs *regs)
+static void ipi_resched_dispatch(void)
 {
-	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ, regs);
+	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
 }
 
-static void ipi_call_dispatch (struct pt_regs *regs)
+static void ipi_call_dispatch(void)
 {
-	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ, regs);
+	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ);
 }
 
-irqreturn_t ipi_resched_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
 {
 	return IRQ_HANDLED;
 }
 
-irqreturn_t ipi_call_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
 {
 	smp_call_function_interrupt();
 
@@ -250,8 +250,8 @@
 {
 	/* set up ipi interrupts */
 	if (cpu_has_vint) {
-		set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
-		set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
+		set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
+		set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
 	}
 
 	cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 2218958..db80957 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -310,7 +310,7 @@
 
 void flush_tlb_all(void)
 {
-	on_each_cpu(flush_tlb_all_ipi, 0, 1, 1);
+	on_each_cpu(flush_tlb_all_ipi, NULL, 1, 1);
 }
 
 static void flush_tlb_mm_ipi(void *mm)
@@ -467,14 +467,18 @@
 
 static int __init topology_init(void)
 {
-	int cpu;
-	int ret;
+	int i, ret;
 
-	for_each_present_cpu(cpu) {
-		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu);
+#ifdef CONFIG_NUMA
+	for_each_online_node(i)
+		register_one_node(i);
+#endif /* CONFIG_NUMA */
+
+	for_each_present_cpu(i) {
+		ret = register_cpu(&per_cpu(cpu_devices, i), i);
 		if (ret)
 			printk(KERN_WARNING "topology_init: register_cpu %d "
-			       "failed (%d)\n", cpu, ret);
+			       "failed (%d)\n", i, ret);
 	}
 
 	return 0;
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
index 76cb31d..1cb9441 100644
--- a/arch/mips/kernel/smtc-asm.S
+++ b/arch/mips/kernel/smtc-asm.S
@@ -97,15 +97,12 @@
 	SAVE_ALL
 	CLI
 	TRACE_IRQS_OFF
-	move	a0,sp
 	/* Function to be invoked passed stack pad slot 5 */
 	lw	t0,PT_PADSLOT5(sp)
 	/* Argument from sender passed in stack pad slot 4 */
-	lw	a1,PT_PADSLOT4(sp)
-	jalr	t0
-	nop
-	j	ret_from_irq
-	nop
+	lw	a0,PT_PADSLOT4(sp)
+	PTR_LA	ra, _ret_from_irq
+	jr	t0
 
 /*
  * Called from idle loop to provoke processing of queued IPIs
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 604bcc5..cc1f747 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -82,7 +82,7 @@
 
 /* Forward declarations */
 
-void ipi_decode(struct pt_regs *, struct smtc_ipi *);
+void ipi_decode(struct smtc_ipi *);
 void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
 void setup_cross_vpe_interrupts(void);
 void init_smtc_stats(void);
@@ -820,19 +820,19 @@
 	write_tc_c0_tcrestart(__smtc_ipi_vector);
 }
 
-void ipi_resched_interrupt(struct pt_regs *regs)
+static void ipi_resched_interrupt(void)
 {
 	/* Return from interrupt should be enough to cause scheduler check */
 }
 
 
-void ipi_call_interrupt(struct pt_regs *regs)
+static void ipi_call_interrupt(void)
 {
 	/* Invoke generic function invocation code in smp.c */
 	smp_call_function_interrupt();
 }
 
-void ipi_decode(struct pt_regs *regs, struct smtc_ipi *pipi)
+void ipi_decode(struct smtc_ipi *pipi)
 {
 	void *arg_copy = pipi->arg;
 	int type_copy = pipi->type;
@@ -846,15 +846,15 @@
 #ifdef SMTC_IDLE_HOOK_DEBUG
 		clock_hang_reported[dest_copy] = 0;
 #endif /* SMTC_IDLE_HOOK_DEBUG */
-		local_timer_interrupt(0, NULL, regs);
+		local_timer_interrupt(0, NULL);
 		break;
 	case LINUX_SMP_IPI:
 		switch ((int)arg_copy) {
 		case SMP_RESCHEDULE_YOURSELF:
-			ipi_resched_interrupt(regs);
+			ipi_resched_interrupt();
 			break;
 		case SMP_CALL_FUNCTION:
-			ipi_call_interrupt(regs);
+			ipi_call_interrupt();
 			break;
 		default:
 			printk("Impossible SMTC IPI Argument 0x%x\n",
@@ -868,7 +868,7 @@
 	}
 }
 
-void deferred_smtc_ipi(struct pt_regs *regs)
+void deferred_smtc_ipi(void)
 {
 	struct smtc_ipi *pipi;
 	unsigned long flags;
@@ -883,7 +883,7 @@
 		while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
 			/* ipi_decode() should be called with interrupts off */
 			local_irq_save(flags);
-			ipi_decode(regs, pipi);
+			ipi_decode(pipi);
 			local_irq_restore(flags);
 		}
 	}
@@ -917,7 +917,7 @@
 
 static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
 
-static irqreturn_t ipi_interrupt(int irq, void *dev_idm, struct pt_regs *regs)
+static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
 {
 	int my_vpe = cpu_data[smp_processor_id()].vpe_id;
 	int my_tc = cpu_data[smp_processor_id()].tc_id;
@@ -978,7 +978,7 @@
 				 * with interrupts off
 				 */
 				local_irq_save(flags);
-				ipi_decode(regs, pipi);
+				ipi_decode(pipi);
 				local_irq_restore(flags);
 			}
 		}
@@ -987,9 +987,9 @@
 	return IRQ_HANDLED;
 }
 
-static void ipi_irq_dispatch(struct pt_regs *regs)
+static void ipi_irq_dispatch(void)
 {
-	do_IRQ(cpu_ipi_irq, regs);
+	do_IRQ(cpu_ipi_irq);
 }
 
 static struct irqaction irq_ipi;
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index 4aabe52..a586aba 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -57,7 +57,7 @@
 		pc = unwind_stack(task, &sp, pc, &ra);
 	} while (pc);
 #else
-	save_raw_context_stack(sp);
+	save_raw_context_stack(trace, sp);
 #endif
 }
 
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index a834080..debe86c 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -322,18 +322,17 @@
  * a broadcasted inter-processor interrupt which itself is triggered
  * by the global timer interrupt.
  */
-void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+void local_timer_interrupt(int irq, void *dev_id)
 {
-	if (current->pid)
-		profile_tick(CPU_PROFILING, regs);
-	update_process_times(user_mode(regs));
+	profile_tick(CPU_PROFILING);
+	update_process_times(user_mode(get_irq_regs()));
 }
 
 /*
  * High-level timer interrupt service routines.  This function
  * is set as irqaction->handler and is invoked through do_IRQ.
  */
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	unsigned long j;
 	unsigned int count;
@@ -419,22 +418,22 @@
 	 * In SMP mode, local_timer_interrupt() is invoked by appropriate
 	 * low-level local timer interrupt handler.
 	 */
-	local_timer_interrupt(irq, dev_id, regs);
+	local_timer_interrupt(irq, dev_id);
 
 	return IRQ_HANDLED;
 }
 
-int null_perf_irq(struct pt_regs *regs)
+int null_perf_irq(void)
 {
 	return 0;
 }
 
-int (*perf_irq)(struct pt_regs *regs) = null_perf_irq;
+int (*perf_irq)(void) = null_perf_irq;
 
 EXPORT_SYMBOL(null_perf_irq);
 EXPORT_SYMBOL(perf_irq);
 
-asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
+asmlinkage void ll_timer_interrupt(int irq)
 {
 	int r2 = cpu_has_mips_r2;
 
@@ -448,25 +447,25 @@
 	 * performance counter interrupt handler anyway.
 	 */
 	if (!r2 || (read_c0_cause() & (1 << 26)))
-		if (perf_irq(regs))
+		if (perf_irq())
 			goto out;
 
 	/* we keep interrupt disabled all the time */
 	if (!r2 || (read_c0_cause() & (1 << 30)))
-		timer_interrupt(irq, NULL, regs);
+		timer_interrupt(irq, NULL);
 
 out:
 	irq_exit();
 }
 
-asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs)
+asmlinkage void ll_local_timer_interrupt(int irq)
 {
 	irq_enter();
 	if (smp_processor_id() != 0)
 		kstat_this_cpu.irqs[irq]++;
 
 	/* we keep interrupt disabled all the time */
-	local_timer_interrupt(irq, NULL, regs);
+	local_timer_interrupt(irq, NULL);
 
 	irq_exit();
 }
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b7292a5..cce8313 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -66,7 +66,7 @@
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-	struct mips_fpu_struct *ctx);
+	struct mips_fpu_struct *ctx, int has_fpu);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -641,7 +641,7 @@
 		preempt_enable();
 
 		/* Run the emulator */
-		sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu);
+		sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1);
 
 		preempt_disable();
 
@@ -791,11 +791,13 @@
 			set_used_math();
 		}
 
-		preempt_enable();
-
-		if (!cpu_has_fpu) {
-			int sig = fpu_emulator_cop1Handler(regs,
-						&current->thread.fpu);
+		if (cpu_has_fpu) {
+			preempt_enable();
+		} else {
+			int sig;
+			preempt_enable();
+			sig = fpu_emulator_cop1Handler(regs,
+						&current->thread.fpu, 0);
 			if (sig)
 				force_sig(sig, current);
 #ifdef CONFIG_MIPS_MT_FPAFF
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 456be8f..a144a00 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -108,14 +108,14 @@
 	return int_status;
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned long int_status;
 	unsigned int cause = read_c0_cause();
 	int irq;
 
 	if (cause & CAUSEF_IP7) {	/* R4000 count / compare IRQ */
-		ll_timer_interrupt(7, regs);
+		ll_timer_interrupt(7);
 		return;
 	}
 
@@ -125,7 +125,7 @@
 	if (int_status) {
 		irq = ls1bit32(int_status);
 
-		do_IRQ(irq, regs);
+		do_IRQ(irq);
 	}
 }
 
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 3f0d5d2..80531b3 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -38,8 +38,6 @@
 
 #include <asm/inst.h>
 #include <asm/bootinfo.h>
-#include <asm/cpu.h>
-#include <asm/cpu-features.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
@@ -1233,7 +1231,8 @@
 	return 0;
 }
 
-int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+	int has_fpu)
 {
 	unsigned long oldepc, prevepc;
 	mips_instruction insn;
@@ -1263,7 +1262,7 @@
 			ieee754_csr.rm = mips_rm[ieee754_csr.rm];
 		}
 
-		if (cpu_has_fpu)
+		if (has_fpu)
 			break;
 		if (sig)
 			break;
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index a020a3c..be624b8 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -101,7 +101,7 @@
 	return b;
 }
 
-static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
+static inline void atlas_hw0_irqdispatch(void)
 {
 	unsigned long int_status;
 	int irq;
@@ -116,7 +116,7 @@
 
 	DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
 
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
 static inline int clz(unsigned long x)
@@ -188,7 +188,7 @@
  * then we just return, if multiple IRQs are pending then we will just take
  * another exception, big deal.
  */
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 	int irq;
@@ -196,11 +196,11 @@
 	irq = irq_ffs(pending);
 
 	if (irq == MIPSCPU_INT_ATLAS)
-		atlas_hw0_irqdispatch(regs);
+		atlas_hw0_irqdispatch();
 	else if (irq >= 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+		do_IRQ(MIPSCPU_INT_BASE + irq);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 static inline void init_atlas_irqs (int base)
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 8d15861..c079e2a 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -30,7 +30,6 @@
 
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
-#include <asm/ptrace.h>
 #include <asm/hardirq.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
@@ -82,19 +81,19 @@
 	}
 }
 
-static void mips_timer_dispatch (struct pt_regs *regs)
+static void mips_timer_dispatch(void)
 {
-	do_IRQ (mips_cpu_timer_irq, regs);
+	do_IRQ(mips_cpu_timer_irq);
 }
 
 /*
  * Redeclare until I get around mopping the timer code insanity on MIPS.
  */
-extern int null_perf_irq(struct pt_regs *regs);
+extern int null_perf_irq(void);
 
-extern int (*perf_irq)(struct pt_regs *regs);
+extern int (*perf_irq)(void);
 
-irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
 
@@ -119,7 +118,7 @@
 	 * perf counter overflow, or both.
 	 */
 	if (read_c0_cause() & (1 << 26))
-		perf_irq(regs);
+		perf_irq();
 
 	if (read_c0_cause() & (1 << 30)) {
 		/* If timer interrupt, make it de-assert */
@@ -139,13 +138,13 @@
 		 * the tick on VPE 0 to run the full timer_interrupt().
 		 */
 		if (cpu_data[cpu].vpe_id == 0) {
-				timer_interrupt(irq, NULL, regs);
+				timer_interrupt(irq, NULL);
 				smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 				scroll_display_message();
 		} else {
 			write_c0_compare(read_c0_count() +
 			                 (mips_hpt_frequency/HZ));
-			local_timer_interrupt(irq, dev_id, regs);
+			local_timer_interrupt(irq, dev_id);
 			smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 		}
 	}
@@ -159,12 +158,12 @@
 		 * timer int.
 		 */
 		if (!r2 || (read_c0_cause() & (1 << 26)))
-			if (perf_irq(regs))
+			if (perf_irq())
 				goto out;
 
 		/* we keep interrupt disabled all the time */
 		if (!r2 || (read_c0_cause() & (1 << 30)))
-			timer_interrupt(irq, NULL, regs);
+			timer_interrupt(irq, NULL);
 
 		scroll_display_message();
 	} else {
@@ -180,7 +179,7 @@
 		/*
 		 * Other CPUs should do profiling and process accounting
 		 */
-		local_timer_interrupt(irq, dev_id, regs);
+		local_timer_interrupt(irq, dev_id);
 	}
 out:
 #endif /* CONFIG_MIPS_MT_SMTC */
@@ -188,7 +187,7 @@
 }
 
 /*
- * Estimate CPU frequency.  Sets mips_counter_frequency as a side-effect
+ * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
  */
 static unsigned int __init estimate_cpu_frequency(void)
 {
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 7cc0ba4..90ad5bf 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -32,6 +32,7 @@
 #include <asm/i8259.h>
 #include <asm/irq_cpu.h>
 #include <asm/io.h>
+#include <asm/irq_regs.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
 #include <asm/mips-boards/piix4.h>
@@ -114,7 +115,7 @@
 	return irq;
 }
 
-static void malta_hw0_irqdispatch(struct pt_regs *regs)
+static void malta_hw0_irqdispatch(void)
 {
 	int irq;
 
@@ -123,17 +124,21 @@
 		return;  /* interrupt has already been cleared */
 	}
 
-	do_IRQ(MALTA_INT_BASE+irq, regs);
+	do_IRQ(MALTA_INT_BASE + irq);
 }
 
-void corehi_irqdispatch(struct pt_regs *regs)
+static void corehi_irqdispatch(void)
 {
+	unsigned int intedge, intsteer, pcicmd, pcibadaddr;
+        unsigned int pcimstat, intisr, inten, intpol;
 	unsigned int intrcause,datalo,datahi;
-        unsigned int pcimstat, intisr, inten, intpol, intedge, intsteer, pcicmd, pcibadaddr;
+	struct pt_regs *regs = get_irq_regs();
 
         printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n");
-        printk("epc   : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n"
-, regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr);
+        printk("epc   : %08lx\nStatus: %08lx\n"
+	       "Cause : %08lx\nbadVaddr : %08lx\n",
+	       regs->cp0_epc, regs->cp0_status,
+	       regs->cp0_cause, regs->cp0_badvaddr);
 
 	/* Read all the registers and then print them as there is a
 	   problem with interspersed printk's upsetting the Bonito controller.
@@ -146,7 +151,7 @@
         case MIPS_REVISION_CORID_CORE_FPGA3:
         case MIPS_REVISION_CORID_CORE_24K:
         case MIPS_REVISION_CORID_CORE_EMUL_MSC:
-                ll_msc_irq(regs);
+                ll_msc_irq();
                 break;
         case MIPS_REVISION_CORID_QED_RM5261:
         case MIPS_REVISION_CORID_CORE_LV:
@@ -208,23 +213,23 @@
 	unsigned int a0 = 7;
 	unsigned int t0;
 
-	t0 = s0 & 0xf000;
+	t0 = pending & 0xf000;
 	t0 = t0 < 1;
 	t0 = t0 << 2;
 	a0 = a0 - t0;
-	s0 = s0 << t0;
+	pending = pending << t0;
 
-	t0 = s0 & 0xc000;
+	t0 = pending & 0xc000;
 	t0 = t0 < 1;
 	t0 = t0 << 1;
 	a0 = a0 - t0;
-	s0 = s0 << t0;
+	pending = pending << t0;
 
-	t0 = s0 & 0x8000;
+	t0 = pending & 0x8000;
 	t0 = t0 < 1;
 	//t0 = t0 << 2;
 	a0 = a0 - t0;
-	//s0 = s0 << t0;
+	//pending = pending << t0;
 
 	return a0;
 #endif
@@ -255,7 +260,7 @@
  * another exception, big deal.
  */
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 	int irq;
@@ -263,11 +268,11 @@
 	irq = irq_ffs(pending);
 
 	if (irq == MIPSCPU_INT_I8259A)
-		malta_hw0_irqdispatch(regs);
+		malta_hw0_irqdispatch();
 	else if (irq > 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+		do_IRQ(MIPSCPU_INT_BASE + irq);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 static struct irqaction i8259irq = {
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index 9168d93..f445fcd 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -98,7 +98,7 @@
  * then we just return, if multiple IRQs are pending then we will just take
  * another exception, big deal.
  */
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 	int irq;
@@ -106,7 +106,7 @@
 	irq = irq_ffs(pending);
 
 	if (irq >= 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+		do_IRQ(MIPSCPU_INT_BASE + irq);
 	else
 		spurious_interrupt(regs);
 }
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index 2c15c8e..2ce449d 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -71,12 +71,7 @@
 #endif
 }
 
-static inline void sim_hw0_irqdispatch(struct pt_regs *regs)
-{
-	do_IRQ(2, regs);
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 	int irq;
@@ -84,9 +79,9 @@
 	irq = irq_ffs(pending);
 
 	if (irq > 0)
-		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+		do_IRQ(MIPSCPU_INT_BASE + irq);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 void __init arch_init_irq(void)
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c
index 230929e..24a4ed0 100644
--- a/arch/mips/mips-boards/sim/sim_time.c
+++ b/arch/mips/mips-boards/sim/sim_time.c
@@ -15,7 +15,6 @@
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 #include <asm/mipsregs.h>
-#include <asm/ptrace.h>
 #include <asm/hardirq.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
@@ -33,7 +32,7 @@
 
 unsigned long cpu_khz;
 
-irqreturn_t sim_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
 {
 #ifdef CONFIG_SMP
 	int cpu = smp_processor_id();
@@ -44,7 +43,7 @@
 	 */
 #ifndef CONFIG_MIPS_MT_SMTC
 	if (cpu == 0) {
-		timer_interrupt(irq, dev_id, regs);
+		timer_interrupt(irq, dev_id);
 	}
 	else {
 		/* Everyone else needs to reset the timer int here as
@@ -84,7 +83,7 @@
 	irq_enable_hazard();
 	evpe(vpflags);
 
-	if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id, regs);
+	if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id);
 	else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
 	smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 
@@ -93,17 +92,17 @@
 	/*
 	 * every CPU should do profiling and process accounting
 	 */
- 	local_timer_interrupt (irq, dev_id, regs);
+ 	local_timer_interrupt (irq, dev_id);
 	return IRQ_HANDLED;
 #else
-	return timer_interrupt (irq, dev_id, regs);
+	return timer_interrupt (irq, dev_id);
 #endif
 }
 
 
 
 /*
- * Estimate CPU frequency.  Sets mips_counter_frequency as a side-effect
+ * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
  */
 static unsigned int __init estimate_cpu_frequency(void)
 {
@@ -177,9 +176,9 @@
 
 static int mips_cpu_timer_irq;
 
-static void mips_timer_dispatch (struct pt_regs *regs)
+static void mips_timer_dispatch(void)
 {
-	do_IRQ (mips_cpu_timer_irq, regs);
+	do_IRQ(mips_cpu_timer_irq);
 }
 
 
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 88b72c9..2de4d3c 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -30,11 +30,34 @@
 #include <asm/cachectl.h>
 #include <asm/cpu.h>
 #include <asm/dma.h>
+#include <asm/kmap_types.h>
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
+#include <asm/fixmap.h>
+
+/* Atomicity and interruptability */
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#include <asm/mipsmtregs.h>
+
+#define ENTER_CRITICAL(flags) \
+	{ \
+	unsigned int mvpflags; \
+	local_irq_save(flags);\
+	mvpflags = dvpe()
+#define EXIT_CRITICAL(flags) \
+	evpe(mvpflags); \
+	local_irq_restore(flags); \
+	}
+#else
+
+#define ENTER_CRITICAL(flags) local_irq_save(flags)
+#define EXIT_CRITICAL(flags) local_irq_restore(flags)
+
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
@@ -80,13 +103,142 @@
 	return 1UL << order;
 }
 
-#ifdef CONFIG_HIGHMEM
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
+/*
+ * These are almost like kmap_atomic / kunmap_atmic except they take an
+ * additional address argument as the hint.
+ */
 
 #define kmap_get_fixmap_pte(vaddr)					\
 	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
 
+#ifdef CONFIG_MIPS_MT_SMTC
+static pte_t *kmap_coherent_pte;
+static void __init kmap_coherent_init(void)
+{
+	unsigned long vaddr;
+
+	/* cache the first coherent kmap pte */
+	vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
+	kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
+}
+#else
+static inline void kmap_coherent_init(void) {}
+#endif
+
+static inline void *kmap_coherent(struct page *page, unsigned long addr)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr, flags, entrylo;
+	unsigned long old_ctx;
+	pte_t pte;
+	int tlbidx;
+
+	inc_preempt_count();
+	idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
+#ifdef CONFIG_MIPS_MT_SMTC
+	idx += FIX_N_COLOURS * smp_processor_id();
+#endif
+	vaddr = __fix_to_virt(FIX_CMAP_END - idx);
+	pte = mk_pte(page, PAGE_KERNEL);
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
+	entrylo = pte.pte_high;
+#else
+	entrylo = pte_val(pte) >> 6;
+#endif
+
+	ENTER_CRITICAL(flags);
+	old_ctx = read_c0_entryhi();
+	write_c0_entryhi(vaddr & (PAGE_MASK << 1));
+	write_c0_entrylo0(entrylo);
+	write_c0_entrylo1(entrylo);
+#ifdef CONFIG_MIPS_MT_SMTC
+	set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
+	/* preload TLB instead of local_flush_tlb_one() */
+	mtc0_tlbw_hazard();
+	tlb_probe();
+	tlb_probe_hazard();
+	tlbidx = read_c0_index();
+	mtc0_tlbw_hazard();
+	if (tlbidx < 0)
+		tlb_write_random();
+	else
+		tlb_write_indexed();
+#else
+	tlbidx = read_c0_wired();
+	write_c0_wired(tlbidx + 1);
+	write_c0_index(tlbidx);
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+#endif
+	tlbw_use_hazard();
+	write_c0_entryhi(old_ctx);
+	EXIT_CRITICAL(flags);
+
+	return (void*) vaddr;
+}
+
+#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+
+static inline void kunmap_coherent(struct page *page)
+{
+#ifndef CONFIG_MIPS_MT_SMTC
+	unsigned int wired;
+	unsigned long flags, old_ctx;
+
+	ENTER_CRITICAL(flags);
+	old_ctx = read_c0_entryhi();
+	wired = read_c0_wired() - 1;
+	write_c0_wired(wired);
+	write_c0_index(wired);
+	write_c0_entryhi(UNIQUE_ENTRYHI(wired));
+	write_c0_entrylo0(0);
+	write_c0_entrylo1(0);
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+	tlbw_use_hazard();
+	write_c0_entryhi(old_ctx);
+	EXIT_CRITICAL(flags);
+#endif
+	dec_preempt_count();
+	preempt_check_resched();
+}
+
+void copy_to_user_page(struct vm_area_struct *vma,
+	struct page *page, unsigned long vaddr, void *dst, const void *src,
+	unsigned long len)
+{
+	if (cpu_has_dc_aliases) {
+		void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+		memcpy(vto, src, len);
+		kunmap_coherent(page);
+	} else
+		memcpy(dst, src, len);
+	if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)
+		flush_cache_page(vma, vaddr, page_to_pfn(page));
+}
+
+EXPORT_SYMBOL(copy_to_user_page);
+
+void copy_from_user_page(struct vm_area_struct *vma,
+	struct page *page, unsigned long vaddr, void *dst, const void *src,
+	unsigned long len)
+{
+	if (cpu_has_dc_aliases) {
+		void *vfrom =
+			kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
+		memcpy(dst, vfrom, len);
+		kunmap_coherent(page);
+	} else
+		memcpy(dst, src, len);
+}
+
+EXPORT_SYMBOL(copy_from_user_page);
+
+
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
 static void __init kmap_init(void)
 {
 	unsigned long kmap_vstart;
@@ -97,11 +249,12 @@
 
 	kmap_prot = PAGE_KERNEL;
 }
+#endif /* CONFIG_HIGHMEM */
 
-#ifdef CONFIG_32BIT
 void __init fixrange_init(unsigned long start, unsigned long end,
 	pgd_t *pgd_base)
 {
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC)
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
@@ -122,7 +275,7 @@
 			for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
 				if (pmd_none(*pmd)) {
 					pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-					set_pmd(pmd, __pmd(pte));
+					set_pmd(pmd, __pmd((unsigned long)pte));
 					if (pte != pte_offset_kernel(pmd, 0))
 						BUG();
 				}
@@ -132,9 +285,8 @@
 		}
 		j = 0;
 	}
+#endif
 }
-#endif /* CONFIG_32BIT */
-#endif /* CONFIG_HIGHMEM */
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 extern void pagetable_init(void);
@@ -175,6 +327,7 @@
 #ifdef CONFIG_HIGHMEM
 	kmap_init();
 #endif
+	kmap_coherent_init();
 
 	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	low = max_low_pfn;
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index 3101d1d..cea7d0e 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -176,7 +176,7 @@
 
 #define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
 
-void __iounmap(volatile void __iomem *addr)
+void __iounmap(const volatile void __iomem *addr)
 {
 	struct vm_struct *p;
 
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index 4bdaa05..4a61e62 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -31,9 +31,10 @@
 
 void __init pagetable_init(void)
 {
-#ifdef CONFIG_HIGHMEM
 	unsigned long vaddr;
-	pgd_t *pgd, *pgd_base;
+	pgd_t *pgd_base;
+#ifdef CONFIG_HIGHMEM
+	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
@@ -44,7 +45,6 @@
 	pgd_init((unsigned long)swapper_pg_dir
 		 + sizeof(pgd_t) * USER_PTRS_PER_PGD);
 
-#ifdef CONFIG_HIGHMEM
 	pgd_base = swapper_pg_dir;
 
 	/*
@@ -53,6 +53,7 @@
 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
 	fixrange_init(vaddr, 0, pgd_base);
 
+#ifdef CONFIG_HIGHMEM
 	/*
 	 * Permanent kmaps:
 	 */
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index 44b5e97..8d600d3 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -8,6 +8,7 @@
  */
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <asm/fixmap.h>
 #include <asm/pgtable.h>
 
 void pgd_init(unsigned long page)
@@ -52,7 +53,17 @@
 
 void __init pagetable_init(void)
 {
+	unsigned long vaddr;
+	pgd_t *pgd_base;
+
 	/* Initialize the entire pgd.  */
 	pgd_init((unsigned long)swapper_pg_dir);
 	pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
+
+	pgd_base = swapper_pg_dir;
+	/*
+	 * Fixed mappings:
+	 */
+	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+	fixrange_init(vaddr, 0, pgd_base);
 }
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
index f906746..2efb25a 100644
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -40,33 +40,33 @@
 #include <asm/mipsregs.h>
 #include <asm/time.h>
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status();
 
 	if (pending & STATUSF_IP0)
-		do_IRQ(0, regs);
+		do_IRQ(0);
 	else if (pending & STATUSF_IP1)
-		do_IRQ(1, regs);
+		do_IRQ(1);
 	else if (pending & STATUSF_IP2)
-		do_IRQ(2, regs);
+		do_IRQ(2);
 	else if (pending & STATUSF_IP3)
-		do_IRQ(3, regs);
+		do_IRQ(3);
 	else if (pending & STATUSF_IP4)
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	else if (pending & STATUSF_IP5)
-		do_IRQ(5, regs);
+		do_IRQ(5);
 	else if (pending & STATUSF_IP6)
-		do_IRQ(6, regs);
+		do_IRQ(6);
 	else if (pending & STATUSF_IP7)
-		ll_timer_interrupt(7, regs);
+		ll_timer_interrupt(7);
 	else {
 		/*
 		 * Now look at the extended interrupts
 		 */
 		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
 		if (pending & STATUSF_IP8)
-			ll_mv64340_irq(regs);
+			ll_mv64340_irq();
 	}
 }
 
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index e6fe299..5a51014 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -62,7 +62,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/tlbflush.h>
 
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
index 793782a..cea0e5d 100644
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -75,26 +75,26 @@
 
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status();
 
 	if (pending & STATUSF_IP0)
-		do_IRQ(0, regs);
+		do_IRQ(0);
 	else if (pending & STATUSF_IP1)
-		do_IRQ(1, regs);
+		do_IRQ(1);
 	else if (pending & STATUSF_IP2)
-		do_IRQ(2, regs);
+		do_IRQ(2);
 	else if (pending & STATUSF_IP3)
-		do_IRQ(3, regs);
+		do_IRQ(3);
 	else if (pending & STATUSF_IP4)
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	else if (pending & STATUSF_IP5)
-		do_IRQ(5, regs);
+		do_IRQ(5);
 	else if (pending & STATUSF_IP6)
-		do_IRQ(6, regs);
+		do_IRQ(6);
 	else if (pending & STATUSF_IP7)
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	else {
 		/*
 		 * Now look at the extended interrupts
@@ -102,8 +102,8 @@
 		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
 
 		if (pending & STATUSF_IP8)
-			ll_mv64340_irq(regs);
+			ll_mv64340_irq();
 		else
-			spurious_interrupt(regs);
+			spurious_interrupt();
 	}
 }
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index 435d078..7d74f8c 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -67,7 +67,6 @@
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/mc146818rtc.h>
 #include <asm/tlbflush.h>
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
index a5dc230..47e3fa3 100644
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ b/arch/mips/momentum/ocelot_c/cpci-irq.c
@@ -21,7 +21,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
-#include <asm/ptrace.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
@@ -112,7 +111,7 @@
  * Interrupt handler for interrupts coming from the FPGA chip.
  * It could be built in ethernet ports etc...
  */
-void ll_cpci_irq(struct pt_regs *regs)
+void ll_cpci_irq(void)
 {
 	unsigned int irq_src, irq_mask;
 
@@ -123,7 +122,7 @@
 	/* mask for just the interrupts we want */
 	irq_src &= ~irq_mask;
 
-	do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE, regs);
+	do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE);
 }
 
 #define shutdown_cpci_irq	disable_cpci_irq
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
index 9d44ae1..ea65223 100644
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -59,31 +59,31 @@
 	no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
 };
 
-extern void ll_uart_irq(struct pt_regs *regs);
-extern void ll_cpci_irq(struct pt_regs *regs);
+extern void ll_uart_irq(void);
+extern void ll_cpci_irq(void);
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status();
 
 	if (pending & STATUSF_IP0)
-		do_IRQ(0, regs);
+		do_IRQ(0);
 	else if (pending & STATUSF_IP1)
-		do_IRQ(1, regs);
+		do_IRQ(1);
 	else if (pending & STATUSF_IP2)
-		do_IRQ(2, regs);
+		do_IRQ(2);
 	else if (pending & STATUSF_IP3)
-		ll_uart_irq(regs);
+		ll_uart_irq();
 	else if (pending & STATUSF_IP4)
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	else if (pending & STATUSF_IP5)
-		ll_cpci_irq(regs);
+		ll_cpci_irq();
 	else if (pending & STATUSF_IP6)
-		ll_mv64340_irq(regs);
+		ll_mv64340_irq();
 	else if (pending & STATUSF_IP7)
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 void __init arch_init_irq(void)
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index 36f570e..9c0c462 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -62,7 +62,6 @@
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/marvell.h>
 #include <linux/bootmem.h>
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
index 9f33d8f..510257d 100644
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ b/arch/mips/momentum/ocelot_c/uart-irq.c
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
-#include <asm/ptrace.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/io.h>
@@ -105,7 +104,7 @@
 /*
  * Interrupt handler for interrupts coming from the FPGA chip.
  */
-void ll_uart_irq(struct pt_regs *regs)
+void ll_uart_irq(void)
 {
 	unsigned int irq_src, irq_mask;
 
@@ -116,7 +115,7 @@
 	/* mask for just the interrupts we want */
 	irq_src &= ~irq_mask;
 
-	do_IRQ(ls1bit8(irq_src) + 74, regs);
+	do_IRQ(ls1bit8(irq_src) + 74);
 }
 
 #define shutdown_uart_irq	disable_uart_irq
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c
index 6cd87cf..7b5cc66 100644
--- a/arch/mips/momentum/ocelot_g/gt-irq.c
+++ b/arch/mips/momentum/ocelot_g/gt-irq.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <asm/ptrace.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <asm/gt64240.h>
@@ -108,7 +107,7 @@
  * we keep this particular structure in the function.
  */
 
-static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t gt64240_p0int_irq(int irq, void *dev)
 {
 	uint32_t irq_src, irq_src_mask;
 	int handled;
@@ -135,7 +134,7 @@
 		/* handle the timer call */
 		do_timer(1);
 #ifndef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 	}
 
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
index 7a4a419..da46524 100644
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -48,22 +48,22 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status();
 
 	if (pending & STATUSF_IP2)
-		do_IRQ(2, regs);
+		do_IRQ(2);
 	else if (pending & STATUSF_IP3)
-		do_IRQ(3, regs);
+		do_IRQ(3);
 	else if (pending & STATUSF_IP4)
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	else if (pending & STATUSF_IP5)
-		do_IRQ(5, regs);
+		do_IRQ(5);
 	else if (pending & STATUSF_IP6)
-		do_IRQ(6, regs);
+		do_IRQ(6);
 	else if (pending & STATUSF_IP7)
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	else {
 		/*
 		 * Now look at the extended interrupts
@@ -71,15 +71,15 @@
 		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
 
 		if (pending & STATUSF_IP8)
-			do_IRQ(8, regs);
+			do_IRQ(8);
 		else if (pending & STATUSF_IP9)
-			do_IRQ(9, regs);
+			do_IRQ(9);
 		else if (pending & STATUSF_IP10)
-			do_IRQ(10, regs);
+			do_IRQ(10);
 		else if (pending & STATUSF_IP11)
-			do_IRQ(11, regs);
+			do_IRQ(11);
 		else
-			spurious_interrupt(regs);
+			spurious_interrupt();
 	}
 }
 
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
index c580b1d..56ec470 100644
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -58,7 +58,6 @@
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <linux/bootmem.h>
 
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
index 5cfce7d..fa6b4aa 100644
--- a/arch/mips/oprofile/op_impl.h
+++ b/arch/mips/oprofile/op_impl.h
@@ -10,10 +10,8 @@
 #ifndef OP_IMPL_H
 #define OP_IMPL_H 1
 
-struct pt_regs;
-
-extern int null_perf_irq(struct pt_regs *regs);
-extern int (*perf_irq)(struct pt_regs *regs);
+extern int null_perf_irq(void);
+extern int (*perf_irq)(void);
 
 /* Per-counter configuration as set via oprofilefs.  */
 struct op_counter_config {
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index a175d67..dd0aec9 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -3,12 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004, 2005 by Ralf Baechle
+ * Copyright (C) 2004, 05, 06 by Ralf Baechle
  * Copyright (C) 2005 by MIPS Technologies, Inc.
  */
 #include <linux/oprofile.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
+#include <asm/irq_regs.h>
 
 #include "op_impl.h"
 
@@ -170,7 +171,7 @@
 	}
 }
 
-static int mipsxx_perfcount_handler(struct pt_regs *regs)
+static int mipsxx_perfcount_handler(void)
 {
 	unsigned int counters = op_model_mipsxx_ops.num_counters;
 	unsigned int control;
@@ -184,7 +185,7 @@
 		counter = r_c0_perfcntr ## n();				\
 		if ((control & M_PERFCTL_INTERRUPT_ENABLE) &&		\
 		    (counter & M_COUNTER_OVERFLOW)) {			\
-			oprofile_add_sample(regs, n);			\
+			oprofile_add_sample(get_irq_regs(), n);		\
 			w_c0_perfcntr ## n(reg.counter[n]);		\
 			handled = 1;					\
 		}
diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c
index b7063fe..7dc9bf6 100644
--- a/arch/mips/oprofile/op_model_rm9000.c
+++ b/arch/mips/oprofile/op_model_rm9000.c
@@ -80,8 +80,7 @@
 	write_c0_perfcontrol(0);
 }
 
-static irqreturn_t rm9000_perfcount_handler(int irq, void * dev_id,
-	struct pt_regs *regs)
+static irqreturn_t rm9000_perfcount_handler(int irq, void * dev_id)
 {
 	unsigned int control = read_c0_perfcontrol();
 	uint32_t counter1, counter2;
diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c
index 17c7932..618ea7d 100644
--- a/arch/mips/pci/pci-ip32.c
+++ b/arch/mips/pci/pci-ip32.c
@@ -22,7 +22,7 @@
  * registered on the bridge error irq.  It's conceivable that some of these
  * conditions warrant a panic.  Anybody care to say which ones?
  */
-static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t macepci_error(int irq, void *dev)
 {
 	char s;
 	unsigned int flags = mace->pci.error;
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index 3c93512..7106116 100644
--- a/arch/mips/philips/pnx8550/common/int.c
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -23,6 +23,7 @@
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
  */
+#include <linux/compiler.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
@@ -52,7 +53,7 @@
 	1			//  70
 };
 
-static void hw0_irqdispatch(int irq, struct pt_regs *regs)
+static void hw0_irqdispatch(int irq)
 {
 	/* find out which interrupt */
 	irq = PNX8550_GIC_VECTOR_0 >> 3;
@@ -61,42 +62,39 @@
 		printk("hw0_irqdispatch: irq 0, spurious interrupt?\n");
 		return;
 	}
-	do_IRQ(PNX8550_INT_GIC_MIN + irq, regs);
+	do_IRQ(PNX8550_INT_GIC_MIN + irq);
 }
 
 
-static void timer_irqdispatch(int irq, struct pt_regs *regs)
+static void timer_irqdispatch(int irq)
 {
 	irq = (0x01c0 & read_c0_config7()) >> 6;
 
-	if (irq == 0) {
+	if (unlikely(irq == 0)) {
 		printk("timer_irqdispatch: irq 0, spurious interrupt?\n");
 		return;
 	}
 
-	if (irq & 0x1) {
-		do_IRQ(PNX8550_INT_TIMER1, regs);
-	}
-	if (irq & 0x2) {
-		do_IRQ(PNX8550_INT_TIMER2, regs);
-	}
-	if (irq & 0x4) {
-		do_IRQ(PNX8550_INT_TIMER3, regs);
-	}
+	if (irq & 0x1)
+		do_IRQ(PNX8550_INT_TIMER1);
+	if (irq & 0x2)
+		do_IRQ(PNX8550_INT_TIMER2);
+	if (irq & 0x4)
+		do_IRQ(PNX8550_INT_TIMER3);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & STATUSF_IP2)
-		hw0_irqdispatch(2, regs);
+		hw0_irqdispatch(2);
 	else if (pending & STATUSF_IP7) {
 		if (read_c0_config7() & 0x01c0)
-			timer_irqdispatch(7, regs);
+			timer_irqdispatch(7);
 	}
 
-	spurious_interrupt(regs);
+	spurious_interrupt();
 }
 
 static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
index b91d0aa..adb0485 100644
--- a/arch/mips/pmc-sierra/yosemite/irq.c
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -56,15 +56,13 @@
 #define HYPERTRANSPORT_INTC     0x7a		/* INTC# */
 #define HYPERTRANSPORT_INTD     0x7b		/* INTD# */
 
-extern void jaguar_mailbox_irq(struct pt_regs *);
-
 /*
  * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
  * For interprocessor interrupts, the best thing to do is to use the INTMSG
  * register. We use the same external interrupt line, i.e. INTB3 and monitor
  * another status bit
  */
-asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
+static void ll_ht_smp_irq_handler(int irq)
 {
 	u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
 
@@ -107,50 +105,35 @@
 	}
 #endif /* CONFIG_HT_LEVEL_TRIGGER */
 
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
-asmlinkage void do_extended_irq(struct pt_regs *regs)
-{
-	unsigned int intcontrol = read_c0_intcontrol();
-	unsigned int cause = read_c0_cause();
-	unsigned int status = read_c0_status();
-	unsigned int pending_sr, pending_ic;
-
-	pending_sr = status & cause & 0xff00;
-	pending_ic = (cause >> 8) & intcontrol & 0xff00;
-
-	if (pending_ic & (1 << 13))
-		do_IRQ(13, regs);
-
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int cause = read_c0_cause();
 	unsigned int status = read_c0_status();
 	unsigned int pending = cause & status;
 
 	if (pending & STATUSF_IP7) {
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	} else if (pending & STATUSF_IP2) {
 #ifdef CONFIG_HYPERTRANSPORT
-		ll_ht_smp_irq_handler(2, regs);
+		ll_ht_smp_irq_handler(2);
 #else
-		do_IRQ(2, regs);
+		do_IRQ(2);
 #endif
 	} else if (pending & STATUSF_IP3) {
-		do_IRQ(3, regs);
+		do_IRQ(3);
 	} else if (pending & STATUSF_IP4) {
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	} else if (pending & STATUSF_IP5) {
 #ifdef CONFIG_SMP
-		titan_mailbox_irq(regs);
+		titan_mailbox_irq();
 #else
-		do_IRQ(5, regs);
+		do_IRQ(5);
 #endif
 	} else if (pending & STATUSF_IP6) {
-		do_IRQ(4, regs);
+		do_IRQ(4);
 	}
 }
 
@@ -178,18 +161,3 @@
 	register_gdb_console();
 #endif
 }
-
-#ifdef CONFIG_KGDB
-/*
- * The 16550 DUART has two ports, but is allocated one IRQ
- * for the serial console. Hence, a generic framework for
- * serial IRQ routing in place. Currently, just calls the
- * do_IRQ fuction. But, going in the future, need to check
- * DUART registers for channel A and B, then decide the
- * appropriate action
- */
-asmlinkage void yosemite_kgdb_irq(int irq, struct pt_regs *regs)
-{
-	do_IRQ(irq, regs);
-}
-#endif
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 0a6ee8e..1b9b0d3 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/serial.h>
 #include <asm/titan_dep.h>
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index c197311..65fa3a2 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -110,7 +110,7 @@
 {
 }
 
-asmlinkage void titan_mailbox_irq(struct pt_regs *regs)
+asmlinkage void titan_mailbox_irq(void)
 {
 	int cpu = smp_processor_id();
 	unsigned long status;
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 3352374..f5ea2fe 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -9,19 +9,19 @@
 
 extern asmlinkage void qemu_handle_int(void);
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & 0x8000) {
-		ll_timer_interrupt(Q_COUNT_COMPARE_IRQ, regs);
+		ll_timer_interrupt(Q_COUNT_COMPARE_IRQ);
 		return;
 	}
 	if (pending & 0x0400) {
 		int irq = i8259_irq();
 
 		if (likely(irq >= 0))
-			do_IRQ(irq, regs);
+			do_IRQ(irq);
 
 		return;
 	}
diff --git a/arch/mips/sgi-ip22/ip22-berr.c b/arch/mips/sgi-ip22/ip22-berr.c
index a28dc78..de6a0cc 100644
--- a/arch/mips/sgi-ip22/ip22-berr.c
+++ b/arch/mips/sgi-ip22/ip22-berr.c
@@ -12,6 +12,7 @@
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/branch.h>
+#include <asm/irq_regs.h>
 #include <asm/sgi/mc.h>
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ioc.h>
@@ -85,9 +86,10 @@
  * and then clear the interrupt when this happens.
  */
 
-void ip22_be_interrupt(int irq, struct pt_regs *regs)
+void ip22_be_interrupt(int irq)
 {
 	const int field = 2 * sizeof(unsigned long);
+	const struct pt_regs *regs = get_irq_regs();
 
 	save_and_clear_buserr();
 	print_buserr();
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index ee0514a..0d18ed4 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -70,7 +70,7 @@
 	return sig_str;
 }
 
-static irqreturn_t ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ip22_eisa_intr(int irq, void *dev_id)
 {
 	u8 eisa_irq;
 	u8 dma1, dma2;
@@ -80,7 +80,7 @@
 	dma2 = inb(EISA_DMA2_STATUS);
 
 	if (eisa_irq < EISA_MAX_IRQ) {
-		do_IRQ(eisa_irq, regs);
+		do_IRQ(eisa_irq);
 		return IRQ_HANDLED;
 	}
 
@@ -89,6 +89,7 @@
 
 	outb(0x20, EISA_INT2_CTRL);
 	outb(0x20, EISA_INT1_CTRL);
+
 	return IRQ_NONE;
 }
 
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index f66026e..af51889 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -222,7 +222,7 @@
 	.end		= end_local3_irq,
 };
 
-static void indy_local0_irqdispatch(struct pt_regs *regs)
+static void indy_local0_irqdispatch(void)
 {
 	u8 mask = sgint->istat0 & sgint->imask0;
 	u8 mask2;
@@ -236,11 +236,10 @@
 
 	/* if irq == 0, then the interrupt has already been cleared */
 	if (irq)
-		do_IRQ(irq, regs);
-	return;
+		do_IRQ(irq);
 }
 
-static void indy_local1_irqdispatch(struct pt_regs *regs)
+static void indy_local1_irqdispatch(void)
 {
 	u8 mask = sgint->istat1 & sgint->imask1;
 	u8 mask2;
@@ -254,19 +253,18 @@
 
 	/* if irq == 0, then the interrupt has already been cleared */
 	if (irq)
-		do_IRQ(irq, regs);
-	return;
+		do_IRQ(irq);
 }
 
-extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
+extern void ip22_be_interrupt(int irq);
 
-static void indy_buserror_irq(struct pt_regs *regs)
+static void indy_buserror_irq(void)
 {
 	int irq = SGI_BUSERR_IRQ;
 
 	irq_enter();
 	kstat_this_cpu.irqs[irq]++;
-	ip22_be_interrupt(irq, regs);
+	ip22_be_interrupt(irq);
 	irq_exit();
 }
 
@@ -305,8 +303,8 @@
 #define SGI_INTERRUPTS	SGINT_LOCAL3
 #endif
 
-extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
-extern void indy_8254timer_irq(struct pt_regs *regs);
+extern void indy_r4k_timer_interrupt(void);
+extern void indy_8254timer_irq(void);
 
 /*
  * IRQs on the INDY look basically (barring software IRQs which we don't use
@@ -336,7 +334,7 @@
  * another exception, big deal.
  */
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause();
 
@@ -344,15 +342,15 @@
 	 * First we check for r4k counter/timer IRQ.
 	 */
 	if (pending & CAUSEF_IP7)
-		indy_r4k_timer_interrupt(regs);
+		indy_r4k_timer_interrupt();
 	else if (pending & CAUSEF_IP2)
-		indy_local0_irqdispatch(regs);
+		indy_local0_irqdispatch();
 	else if (pending & CAUSEF_IP3)
-		indy_local1_irqdispatch(regs);
+		indy_local1_irqdispatch();
 	else if (pending & CAUSEF_IP6)
-		indy_buserror_irq(regs);
+		indy_buserror_irq();
 	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
-		indy_8254timer_irq(regs);
+		indy_8254timer_irq();
 }
 
 extern void mips_cpu_irq_init(unsigned int irq_base);
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 7a941ec..66df5ac 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -169,7 +169,7 @@
 	}
 }
 
-static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t panel_int(int irq, void *dev_id)
 {
 	unsigned int buttons;
 
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 0e06189..2055547 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -175,7 +175,7 @@
 }
 
 /* Generic SGI handler for (spurious) 8254 interrupts */
-void indy_8254timer_irq(struct pt_regs *regs)
+void indy_8254timer_irq(void)
 {
 	int irq = SGI_8254_0_IRQ;
 	ULONG cnt;
@@ -189,13 +189,13 @@
 	irq_exit();
 }
 
-void indy_r4k_timer_interrupt(struct pt_regs *regs)
+void indy_r4k_timer_interrupt(void)
 {
 	int irq = SGI_TIMER_IRQ;
 
 	irq_enter();
 	kstat_this_cpu.irqs[irq]++;
-	timer_interrupt(irq, NULL, regs);
+	timer_interrupt(irq, NULL);
 	irq_exit();
 }
 
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 24a8537..f01ba1f 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -30,7 +30,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-#include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/pci/bridge.h>
 #include <asm/sn/addrs.h>
@@ -129,7 +128,7 @@
  * Kanoj 05.13.00
  */
 
-static void ip27_do_irq_mask0(struct pt_regs *regs)
+static void ip27_do_irq_mask0(void)
 {
 	int irq, swlevel;
 	hubreg_t pend0, mask0;
@@ -164,13 +163,13 @@
 		struct slice_data *si = cpu_data[cpu].data;
 
 		irq = si->level_to_irq[swlevel];
-		do_IRQ(irq, regs);
+		do_IRQ(irq);
 	}
 
 	LOCAL_HUB_L(PI_INT_PEND0);
 }
 
-static void ip27_do_irq_mask1(struct pt_regs *regs)
+static void ip27_do_irq_mask1(void)
 {
 	int irq, swlevel;
 	hubreg_t pend1, mask1;
@@ -190,17 +189,17 @@
 	/* "map" swlevel to irq */
 	irq = si->level_to_irq[swlevel];
 	LOCAL_HUB_CLR_INTR(swlevel);
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 
 	LOCAL_HUB_L(PI_INT_PEND1);
 }
 
-static void ip27_prof_timer(struct pt_regs *regs)
+static void ip27_prof_timer(void)
 {
 	panic("CPU %d got a profiling interrupt", smp_processor_id());
 }
 
-static void ip27_hub_error(struct pt_regs *regs)
+static void ip27_hub_error(void)
 {
 	panic("CPU %d got a hub error interrupt", smp_processor_id());
 }
@@ -418,22 +417,22 @@
 	return irq;
 }
 
-extern void ip27_rt_timer_interrupt(struct pt_regs *regs);
+extern void ip27_rt_timer_interrupt(void);
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned long pending = read_c0_cause() & read_c0_status();
 
 	if (pending & CAUSEF_IP4)
-		ip27_rt_timer_interrupt(regs);
+		ip27_rt_timer_interrupt();
 	else if (pending & CAUSEF_IP2)	/* PI_INT_PEND_0 or CC_PEND_{A|B} */
-		ip27_do_irq_mask0(regs);
+		ip27_do_irq_mask0();
 	else if (pending & CAUSEF_IP3)	/* PI_INT_PEND_1 */
-		ip27_do_irq_mask1(regs);
+		ip27_do_irq_mask1();
 	else if (pending & CAUSEF_IP5)
-		ip27_prof_timer(regs);
+		ip27_prof_timer();
 	else if (pending & CAUSEF_IP6)
-		ip27_hub_error(regs);
+		ip27_hub_error();
 }
 
 void __init arch_init_irq(void)
diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c
index d777b7d..f9f404a 100644
--- a/arch/mips/sgi-ip27/ip27-klnuma.c
+++ b/arch/mips/sgi-ip27/ip27-klnuma.c
@@ -26,7 +26,7 @@
  * kernel.  For example, we should never put a copy on a headless node,
  * and we should respect the topology of the machine.
  */
-void __init setup_replication_mask()
+void __init setup_replication_mask(void)
 {
 	cnodeid_t	cnode;
 
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 257ce11..4e870fc 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -89,7 +89,7 @@
 
 static unsigned int rt_timer_irq;
 
-void ip27_rt_timer_interrupt(struct pt_regs *regs)
+void ip27_rt_timer_interrupt(void)
 {
 	int cpu = smp_processor_id();
 	int cpuA = cputoslice(cpu) == 0;
@@ -111,7 +111,7 @@
 	if (cpu == 0)
 		do_timer(1);
 
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff --git a/arch/mips/sgi-ip32/crime.c b/arch/mips/sgi-ip32/crime.c
index 41b5eca..bff5087 100644
--- a/arch/mips/sgi-ip32/crime.c
+++ b/arch/mips/sgi-ip32/crime.c
@@ -14,7 +14,6 @@
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
-#include <asm/ptrace.h>
 #include <asm/page.h>
 #include <asm/ip32/crime.h>
 #include <asm/ip32/mace.h>
@@ -40,8 +39,7 @@
 		id, rev, field, (unsigned long) CRIME_BASE);
 }
 
-irqreturn_t
-crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t crime_memerr_intr(unsigned int irq, void *dev_id)
 {
 	unsigned long stat, addr;
 	int fatal = 0;
@@ -92,8 +90,7 @@
 	return IRQ_HANDLED;
 }
 
-irqreturn_t
-crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t crime_cpuerr_intr(unsigned int irq, void *dev_id)
 {
 	unsigned long stat = crime->cpu_error_stat & CRIME_CPU_ERROR_MASK;
 	unsigned long addr = crime->cpu_error_addr & CRIME_CPU_ERROR_ADDR_MASK;
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index c64a820..c9acadd 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -120,10 +120,8 @@
 static DEFINE_SPINLOCK(ip32_irq_lock);
 
 /* Some initial interrupts to set up */
-extern irqreturn_t crime_memerr_intr (int irq, void *dev_id,
-				      struct pt_regs *regs);
-extern irqreturn_t crime_cpuerr_intr (int irq, void *dev_id,
-				      struct pt_regs *regs);
+extern irqreturn_t crime_memerr_intr(int irq, void *dev_id);
+extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id);
 
 struct irqaction memerr_irq = { crime_memerr_intr, IRQF_DISABLED,
 			CPU_MASK_NONE, "CRIME memory error", NULL, NULL };
@@ -479,7 +477,7 @@
 	.end = end_mace_irq,
 };
 
-static void ip32_unknown_interrupt(struct pt_regs *regs)
+static void ip32_unknown_interrupt(void)
 {
 	printk ("Unknown interrupt occurred!\n");
 	printk ("cp0_status: %08x\n", read_c0_status());
@@ -492,7 +490,7 @@
 	printk ("MACE PCI control register: %08x\n", mace->pci.control);
 
 	printk("Register dump:\n");
-	show_regs(regs);
+	show_regs(get_irq_regs());
 
 	printk("Please mail this report to linux-mips@linux-mips.org\n");
 	printk("Spinning...");
@@ -501,7 +499,7 @@
 
 /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
 /* change this to loop over all edge-triggered irqs, exception masked out ones */
-static void ip32_irq0(struct pt_regs *regs)
+static void ip32_irq0(void)
 {
 	uint64_t crime_int;
 	int irq = 0;
@@ -516,50 +514,50 @@
 	}
 	irq++;
 	DBG("*irq %u*\n", irq);
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 }
 
-static void ip32_irq1(struct pt_regs *regs)
+static void ip32_irq1(void)
 {
-	ip32_unknown_interrupt(regs);
+	ip32_unknown_interrupt();
 }
 
-static void ip32_irq2(struct pt_regs *regs)
+static void ip32_irq2(void)
 {
-	ip32_unknown_interrupt(regs);
+	ip32_unknown_interrupt();
 }
 
-static void ip32_irq3(struct pt_regs *regs)
+static void ip32_irq3(void)
 {
-	ip32_unknown_interrupt(regs);
+	ip32_unknown_interrupt();
 }
 
-static void ip32_irq4(struct pt_regs *regs)
+static void ip32_irq4(void)
 {
-	ip32_unknown_interrupt(regs);
+	ip32_unknown_interrupt();
 }
 
-static void ip32_irq5(struct pt_regs *regs)
+static void ip32_irq5(void)
 {
-	ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
+	ll_timer_interrupt(IP32_R4K_TIMER_IRQ);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause();
 
 	if (likely(pending & IE_IRQ0))
-		ip32_irq0(regs);
+		ip32_irq0();
 	else if (unlikely(pending & IE_IRQ1))
-		ip32_irq1(regs);
+		ip32_irq1();
 	else if (unlikely(pending & IE_IRQ2))
-		ip32_irq2(regs);
+		ip32_irq2();
 	else if (unlikely(pending & IE_IRQ3))
-		ip32_irq3(regs);
+		ip32_irq3();
 	else if (unlikely(pending & IE_IRQ4))
-		ip32_irq4(regs);
+		ip32_irq4();
 	else if (likely(pending & IE_IRQ5))
-		ip32_irq5(regs);
+		ip32_irq5();
 }
 
 void __init arch_init_irq(void)
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index fd0932b..db80844 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -135,7 +135,7 @@
 	add_timer(&power_timer);
 }
 
-static irqreturn_t ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ip32_rtc_int(int irq, void *dev_id)
 {
 	volatile unsigned char reg_c;
 
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index a46b75b..8b1f414 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -25,9 +25,9 @@
 #include <linux/kernel_stat.h>
 
 #include <asm/errno.h>
+#include <asm/irq_regs.h>
 #include <asm/signal.h>
 #include <asm/system.h>
-#include <asm/ptrace.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/bcm1480_regs.h>
@@ -284,8 +284,7 @@
 }
 
 
-static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id,
-	struct pt_regs *regs)
+static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id)
 {
 	return IRQ_NONE;
 }
@@ -453,7 +452,7 @@
 #define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 #define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
-void bcm1480_kgdb_interrupt(struct pt_regs *regs)
+static void bcm1480_kgdb_interrupt(void)
 {
 	/*
 	 * Clear break-change status (allow some time for the remote
@@ -464,16 +463,15 @@
 	mdelay(500);
 	duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
 				M_DUART_RX_EN | M_DUART_TX_EN);
-	set_async_breakpoint(&regs->cp0_epc);
+	set_async_breakpoint(&get_irq_regs()->cp0_epc);
 }
 
 #endif 	/* CONFIG_KGDB */
 
-extern void bcm1480_timer_interrupt(struct pt_regs *regs);
-extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
-extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
+extern void bcm1480_timer_interrupt(void);
+extern void bcm1480_mailbox_interrupt(void);
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending;
 
@@ -486,21 +484,21 @@
 
 #ifdef CONFIG_SIBYTE_BCM1480_PROF
 	if (pending & CAUSEF_IP7)	/* Cpu performance counter interrupt */
-		sbprof_cpu_intr(exception_epc(regs));
+		sbprof_cpu_intr();
 	else
 #endif
 
 	if (pending & CAUSEF_IP4)
-		bcm1480_timer_interrupt(regs);
+		bcm1480_timer_interrupt();
 
 #ifdef CONFIG_SMP
 	else if (pending & CAUSEF_IP3)
-		bcm1480_mailbox_interrupt(regs);
+		bcm1480_mailbox_interrupt();
 #endif
 
 #ifdef CONFIG_KGDB
 	else if (pending & CAUSEF_IP6)
-		bcm1480_kgdb_interrupt(regs);		/* KGDB (uart 1) */
+		bcm1480_kgdb_interrupt();		/* KGDB (uart 1) */
 #endif
 
 	else if (pending & CAUSEF_IP2) {
@@ -521,9 +519,9 @@
 
 		if (mask_h) {
 			if (mask_h ^ 1)
-				do_IRQ(fls64(mask_h) - 1, regs);
+				do_IRQ(fls64(mask_h) - 1);
 			else
-				do_IRQ(63 + fls64(mask_l), regs);
+				do_IRQ(63 + fls64(mask_l));
 		}
 	}
 }
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index 584a4b3..bf32827 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -34,21 +34,21 @@
  * independent of board/firmware
  */
 
-static void *mailbox_0_set_regs[] = {
+static volatile void *mailbox_0_set_regs[] = {
 	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
 	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
 	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
 	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
 };
 
-static void *mailbox_0_clear_regs[] = {
+static volatile void *mailbox_0_clear_regs[] = {
 	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
 	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
 	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
 	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
 };
 
-static void *mailbox_0_regs[] = {
+static volatile void *mailbox_0_regs[] = {
 	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
 	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
 	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
@@ -88,7 +88,7 @@
 	__raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
 }
 
-void bcm1480_mailbox_interrupt(struct pt_regs *regs)
+void bcm1480_mailbox_interrupt(void)
 {
 	int cpu = smp_processor_id();
 	unsigned int action;
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index 7e088f6..bf12af4 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -31,7 +31,6 @@
 #include <linux/kernel_stat.h>
 
 #include <asm/irq.h>
-#include <asm/ptrace.h>
 #include <asm/addrspace.h>
 #include <asm/time.h>
 #include <asm/io.h>
@@ -100,10 +99,10 @@
 
 #include <asm/sibyte/sb1250.h>
 
-void bcm1480_timer_interrupt(struct pt_regs *regs)
+void bcm1480_timer_interrupt(void)
 {
 	int cpu = smp_processor_id();
-	int irq = K_BCM1480_INT_TIMER_0+cpu;
+	int irq = K_BCM1480_INT_TIMER_0 + cpu;
 
 	/* Reset the timer */
 	__raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
@@ -113,13 +112,13 @@
 		/*
 		 * CPU 0 handles the global timer interrupt job
 		 */
-		ll_timer_interrupt(irq, regs);
+		ll_timer_interrupt(irq);
 	}
 	else {
 		/*
 		 * other CPUs should just do profiling and process accounting
 		 */
-		ll_local_timer_interrupt(irq, regs);
+		ll_local_timer_interrupt(irq);
 	}
 }
 
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
index 992e0d8..d1a906e 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -88,7 +88,7 @@
 	sbp.tb_armed = 1;
 }
 
-static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sbprof_tb_intr(int irq, void *dev_id)
 {
 	int i;
 	DBG(printk(DEVNAME ": tb_intr\n"));
@@ -138,7 +138,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sbprof_pc_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sbprof_pc_intr(int irq, void *dev_id)
 {
 	printk(DEVNAME ": unexpected pc_intr");
 	return IRQ_NONE;
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c
index bb90649..45274bd 100644
--- a/arch/mips/sibyte/sb1250/bus_watcher.c
+++ b/arch/mips/sibyte/sb1250/bus_watcher.c
@@ -171,7 +171,7 @@
  * notes: possible re-entry due to multiple sources
  *        should check/indicate saturation
  */
-static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t sibyte_bw_int(int irq, void *data)
 {
 	struct bw_stats_struct *stats = data;
 	unsigned long cntr;
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index f9bd9f0..d5d2677 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -28,7 +28,6 @@
 #include <asm/errno.h>
 #include <asm/signal.h>
 #include <asm/system.h>
-#include <asm/ptrace.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/sb1250_regs.h>
@@ -254,8 +253,7 @@
 }
 
 
-static irqreturn_t  sb1250_dummy_handler(int irq, void *dev_id,
-	struct pt_regs *regs)
+static irqreturn_t  sb1250_dummy_handler(int irq, void *dev_id)
 {
 	return IRQ_NONE;
 }
@@ -403,7 +401,7 @@
 #define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 #define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
-static void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static void sb1250_kgdb_interrupt(void)
 {
 	/*
 	 * Clear break-change status (allow some time for the remote
@@ -414,16 +412,15 @@
 	mdelay(500);
 	duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
 				M_DUART_RX_EN | M_DUART_TX_EN);
-	set_async_breakpoint(&regs->cp0_epc);
+	set_async_breakpoint(&get_irq_regs()->cp0_epc);
 }
 
 #endif 	/* CONFIG_KGDB */
 
-extern void sb1250_timer_interrupt(struct pt_regs *regs);
-extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
-extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
+extern void sb1250_timer_interrupt(void);
+extern void sb1250_mailbox_interrupt(void);
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending;
 
@@ -446,21 +443,21 @@
 
 #ifdef CONFIG_SIBYTE_SB1250_PROF
 	if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
-		sbprof_cpu_intr(exception_epc(regs));
+		sbprof_cpu_intr();
 	else
 #endif
 
 	if (pending & CAUSEF_IP4)
-		sb1250_timer_interrupt(regs);
+		sb1250_timer_interrupt();
 
 #ifdef CONFIG_SMP
 	else if (pending & CAUSEF_IP3)
-		sb1250_mailbox_interrupt(regs);
+		sb1250_mailbox_interrupt();
 #endif
 
 #ifdef CONFIG_KGDB
 	else if (pending & CAUSEF_IP6)			/* KGDB (uart 1) */
-		sb1250_kgdb_interrupt(regs);
+		sb1250_kgdb_interrupt();
 #endif
 
 	else if (pending & CAUSEF_IP2) {
@@ -475,9 +472,9 @@
 		mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
 		                              R_IMR_INTERRUPT_STATUS_BASE)));
 		if (mask)
-			do_IRQ(fls64(mask) - 1, regs);
+			do_IRQ(fls64(mask) - 1);
 		else
-			spurious_interrupt(regs);
+			spurious_interrupt();
 	} else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index f859db0..c38e1f3 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -76,7 +76,7 @@
 	__raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
 }
 
-void sb1250_mailbox_interrupt(struct pt_regs *regs)
+void sb1250_mailbox_interrupt(void)
 {
 	int cpu = smp_processor_id();
 	unsigned int action;
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 4b669dc..0ccf179 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -31,7 +31,6 @@
 #include <linux/kernel_stat.h>
 
 #include <asm/irq.h>
-#include <asm/ptrace.h>
 #include <asm/addrspace.h>
 #include <asm/time.h>
 #include <asm/io.h>
@@ -125,7 +124,7 @@
 	 */
 }
 
-void sb1250_timer_interrupt(struct pt_regs *regs)
+void sb1250_timer_interrupt(void)
 {
 	int cpu = smp_processor_id();
 	int irq = K_INT_TIMER_0 + cpu;
@@ -138,13 +137,13 @@
 		/*
 		 * CPU 0 handles the global timer interrupt job
 		 */
-		ll_timer_interrupt(irq, regs);
+		ll_timer_interrupt(irq);
 	}
 	else {
 		/*
 		 * other CPUs should just do profiling and process accounting
 		 */
-		ll_local_timer_interrupt(irq, regs);
+		ll_local_timer_interrupt(irq);
 	}
 }
 
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index cda165f..48fb74a 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -69,20 +69,20 @@
  * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
  * button interrupts.  Later ...
  */
-static void pciasic_hwint0(struct pt_regs *regs)
+static void pciasic_hwint0(void)
 {
 	panic("Received int0 but no handler yet ...");
 }
 
 /* This interrupt was used for the com1 console on the first prototypes.  */
-static void pciasic_hwint2(struct pt_regs *regs)
+static void pciasic_hwint2(void)
 {
 	/* I think this shouldn't happen on production machines.  */
 	panic("hwint2 and no handler yet");
 }
 
 /* hwint5 is the r4k count / compare interrupt  */
-static void pciasic_hwint5(struct pt_regs *regs)
+static void pciasic_hwint5(void)
 {
 	panic("hwint5 and no handler yet");
 }
@@ -103,7 +103,7 @@
  *
  * The EISA_INT bit in CSITPEND is high active, all others are low active.
  */
-static void pciasic_hwint1(struct pt_regs *regs)
+static void pciasic_hwint1(void)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	unsigned long flags;
@@ -119,13 +119,13 @@
 		if (unlikely(irq < 0))
 			return;
 
-		do_IRQ(irq, regs);
+		do_IRQ(irq);
 	}
 
 	if (!(pend & IT_SCSI)) {
 		flags = read_c0_status();
 		clear_c0_status(ST0_IM);
-		do_IRQ(PCIMT_IRQ_SCSI, regs);
+		do_IRQ(PCIMT_IRQ_SCSI);
 		write_c0_status(flags);
 	}
 }
@@ -133,7 +133,7 @@
 /*
  * hwint 3 should deal with the PCI A - D interrupts,
  */
-static void pciasic_hwint3(struct pt_regs *regs)
+static void pciasic_hwint3(void)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	int irq;
@@ -141,21 +141,21 @@
 	pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
 	clear_c0_status(IE_IRQ3);
 	irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
-	do_IRQ(irq, regs);
+	do_IRQ(irq);
 	set_c0_status(IE_IRQ3);
 }
 
 /*
  * hwint 4 is used for only the onboard PCnet 32.
  */
-static void pciasic_hwint4(struct pt_regs *regs)
+static void pciasic_hwint4(void)
 {
 	clear_c0_status(IE_IRQ4);
-	do_IRQ(PCIMT_IRQ_ETHERNET, regs);
+	do_IRQ(PCIMT_IRQ_ETHERNET);
 	set_c0_status(IE_IRQ4);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 	static unsigned char led_cache;
@@ -163,17 +163,17 @@
 	*(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
 
 	if (pending & 0x0800)
-		pciasic_hwint1(regs);
+		pciasic_hwint1();
 	else if (pending & 0x4000)
-		pciasic_hwint4(regs);
+		pciasic_hwint4();
 	else if (pending & 0x2000)
-		pciasic_hwint3(regs);
+		pciasic_hwint3();
 	else if (pending & 0x1000)
-		pciasic_hwint2(regs);
+		pciasic_hwint2();
 	else if (pending & 0x8000)
-		pciasic_hwint5(regs);
+		pciasic_hwint5();
 	else if (pending & 0x0400)
-		pciasic_hwint0(regs);
+		pciasic_hwint0();
 }
 
 void __init init_pciasic(void)
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 4e98feb..afeb7f1 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -31,7 +31,6 @@
 #include <asm/irq.h>
 #include <asm/mc146818-time.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/sni.h>
 #include <asm/time.h>
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index cd176f6..8266a88 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -576,24 +576,24 @@
 	return (sw_irq);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
 	if (pending & STATUSF_IP7)			/* cpu timer */
-		do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+		do_IRQ(TX4927_IRQ_CPU_TIMER);
 	else if (pending & STATUSF_IP2) {		/* tx4927 pic */
 		unsigned int irq = tx4927_irq_nested();
 
 		if (unlikely(irq == 0)) {
-			spurious_interrupt(regs);
+			spurious_interrupt();
 			return;
 		}
-		do_IRQ(irq, regs);
+		do_IRQ(irq);
 	} else if (pending & STATUSF_IP0)		/* user line 0 */
-		do_IRQ(TX4927_IRQ_USER0, regs);
+		do_IRQ(TX4927_IRQ_USER0);
 	else if (pending & STATUSF_IP1)			/* user line 1 */
-		do_IRQ(TX4927_IRQ_USER1, regs);
+		do_IRQ(TX4927_IRQ_USER1);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
index 3ace403..4658b2a 100644
--- a/arch/mips/tx4927/common/tx4927_setup.c
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -53,19 +53,9 @@
 void dump_cp0(char *key);
 
 
-void (*__wbflush) (void);
-
-static void tx4927_write_buffer_flush(void)
-{
-	__asm__ __volatile__
-	    ("sync\n\t" "nop\n\t" "loop: bc0f loop\n\t" "nop\n\t");
-}
-
-
 void __init plat_mem_setup(void)
 {
 	board_time_init = tx4927_time_init;
-	__wbflush = tx4927_write_buffer_flush;
 
 #ifdef CONFIG_TOSHIBA_RBTX4927
 	{
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
index b0f021f..0c3c3f6 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
@@ -127,9 +127,9 @@
 #include <asm/irq.h>
 #include <asm/pci.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
+#include <asm/wbflush.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
 #ifdef CONFIG_RTC_DS1742
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index f0d70c4..735cb87 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -58,8 +58,8 @@
 #include <asm/page.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/irq_regs.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <linux/bootmem.h>
@@ -160,8 +160,7 @@
 char *toshiba_name = "";
 
 #ifdef CONFIG_PCI
-static void tx4927_pcierr_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs)
+static void tx4927_pcierr_interrupt(int irq, void *dev_id)
 {
 #ifdef CONFIG_BLK_DEV_IDEPCI
 	/* ignore MasterAbort for ide probing... */
@@ -185,7 +184,7 @@
 	       (unsigned long) tx4927_ccfgptr->ccfg,
 	       (unsigned long) (tx4927_ccfgptr->tear >> 32),
 	       (unsigned long) tx4927_ccfgptr->tear);
-	show_regs(regs);
+	show_regs(get_irq_regs());
 }
 
 void __init toshiba_rbtx4927_pci_irq_init(void)
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index cbfb342..77fe245 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -30,6 +30,7 @@
 #include <asm/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
+#include <asm/wbflush.h>
 #include <asm/tx4938/rbtx4938.h>
 
 /**********************************************************************************/
@@ -104,8 +105,6 @@
 		irq_desc[i].depth = 1;
 		irq_desc[i].chip = &tx4938_irq_cp0_type;
 	}
-
-	return;
 }
 
 static unsigned int
@@ -113,7 +112,7 @@
 {
 	tx4938_irq_cp0_enable(irq);
 
-	return (0);
+	return 0;
 }
 
 static void
@@ -144,16 +143,12 @@
 	clear_c0_status(tx4938_irq_cp0_mask(irq));
 
 	spin_unlock_irqrestore(&tx4938_cp0_lock, flags);
-
-	return;
 }
 
 static void
 tx4938_irq_cp0_mask_and_ack(unsigned int irq)
 {
 	tx4938_irq_cp0_disable(irq);
-
-	return;
 }
 
 static void
@@ -162,8 +157,6 @@
 	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		tx4938_irq_cp0_enable(irq);
 	}
-
-	return;
 }
 
 /**********************************************************************************/
@@ -227,7 +220,7 @@
 		}
 	}
 
-	return (0);
+	return 0;
 }
 
 u32
@@ -278,7 +271,7 @@
 			return (0x00000007);
 		}
 	}
-	return (0x00000000);
+	return 0x00000000;
 }
 
 static void
@@ -292,8 +285,6 @@
 	TX4938_WR(pic_reg, val);
 	mmiowb();
 	TX4938_RD(pic_reg);
-
-	return;
 }
 
 static void __init
@@ -317,8 +308,6 @@
 	TX4938_WR(0xff1ff600, TX4938_RD(0xff1ff600) | 0x1);	/* irq enable */
 
 	spin_unlock_irqrestore(&tx4938_pic_lock, flags);
-
-	return;
 }
 
 static unsigned int
@@ -326,15 +315,13 @@
 {
 	tx4938_irq_pic_enable(irq);
 
-	return (0);
+	return 0;
 }
 
 static void
 tx4938_irq_pic_shutdown(unsigned int irq)
 {
 	tx4938_irq_pic_disable(irq);
-
-	return;
 }
 
 static void
@@ -348,8 +335,6 @@
 			      tx4938_irq_pic_mask(irq));
 
 	spin_unlock_irqrestore(&tx4938_pic_lock, flags);
-
-	return;
 }
 
 static void
@@ -363,16 +348,12 @@
 			      tx4938_irq_pic_mask(irq), 0);
 
 	spin_unlock_irqrestore(&tx4938_pic_lock, flags);
-
-	return;
 }
 
 static void
 tx4938_irq_pic_mask_and_ack(unsigned int irq)
 {
 	tx4938_irq_pic_disable(irq);
-
-	return;
 }
 
 static void
@@ -381,8 +362,6 @@
 	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		tx4938_irq_pic_enable(irq);
 	}
-
-	return;
 }
 
 /**********************************************************************************/
@@ -394,8 +373,6 @@
 {
 	tx4938_irq_cp0_init();
 	tx4938_irq_pic_init();
-
-	return;
 }
 
 int
@@ -417,23 +394,23 @@
 	}
 
 	wbflush();
-	return (sw_irq);
+	return sw_irq;
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status();
 
 	if (pending & STATUSF_IP7)
-		do_IRQ(TX4938_IRQ_CPU_TIMER, regs);
+		do_IRQ(TX4938_IRQ_CPU_TIMER);
 	else if (pending & STATUSF_IP2) {
 		int irq = tx4938_irq_nested();
 		if (irq)
-			do_IRQ(irq, regs);
+			do_IRQ(irq);
 		else
-			spurious_interrupt(regs);
+			spurious_interrupt();
 	} else if (pending & STATUSF_IP1)
-		do_IRQ(TX4938_IRQ_USER1, regs);
+		do_IRQ(TX4938_IRQ_USER1);
 	else if (pending & STATUSF_IP0)
-		do_IRQ(TX4938_IRQ_USER0, regs);
+		do_IRQ(TX4938_IRQ_USER0);
 }
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c
index 71859c4..f415a1f 100644
--- a/arch/mips/tx4938/common/setup.c
+++ b/arch/mips/tx4938/common/setup.c
@@ -41,29 +41,10 @@
 void __init tx4938_time_init(void);
 void dump_cp0(char *key);
 
-void (*__wbflush) (void);
-
-static void
-tx4938_write_buffer_flush(void)
-{
-	mmiowb();
-
-	__asm__ __volatile__(
-		".set	push\n\t"
-		".set	noreorder\n\t"
-		"lw	$0,%0\n\t"
-		"nop\n\t"
-		".set	pop"
-		: /* no output */
-		: "m" (*(int *)KSEG1)
-		: "memory");
-}
-
 void __init
 plat_mem_setup(void)
 {
 	board_time_init = tx4938_time_init;
-	__wbflush = tx4938_write_buffer_flush;
 	toshiba_rbtx4938_setup();
 }
 
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index 83f2750..102e473 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -81,9 +81,9 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
-#include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
+#include <asm/wbflush.h>
 #include <linux/bootmem.h>
 #include <asm/tx4938/rbtx4938.h>
 
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
index fae3136..b926e6a 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
@@ -35,7 +35,8 @@
 }
 
 static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
-static void txx9_spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+
+static void txx9_spi_interrupt(int irq, void *dev_id)
 {
 	/* disable rx intr */
 	tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index 7a5c31d..c215c0d 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -635,7 +635,7 @@
 
 EXPORT_SYMBOL(vr41xx_set_intassign);
 
-static int icu_get_irq(unsigned int irq, struct pt_regs *regs)
+static int icu_get_irq(unsigned int irq)
 {
 	uint16_t pend1, pend2;
 	uint16_t mask1, mask2;
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 4733c53..397ba94 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -25,7 +25,7 @@
 #include <asm/vr41xx/irq.h>
 
 typedef struct irq_cascade {
-	int (*get_irq)(unsigned int, struct pt_regs *);
+	int (*get_irq)(unsigned int);
 } irq_cascade_t;
 
 static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned;
@@ -36,7 +36,7 @@
 	.name		= "cascade",
 };
 
-int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *))
+int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int))
 {
 	int retval = 0;
 
@@ -59,7 +59,7 @@
 
 EXPORT_SYMBOL_GPL(cascade_irq);
 
-static void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+static void irq_dispatch(unsigned int irq)
 {
 	irq_cascade_t *cascade;
 	struct irq_desc *desc;
@@ -74,39 +74,39 @@
 		unsigned int source_irq = irq;
 		desc = irq_desc + source_irq;
 		desc->chip->ack(source_irq);
-		irq = cascade->get_irq(irq, regs);
+		irq = cascade->get_irq(irq);
 		if (irq < 0)
 			atomic_inc(&irq_err_count);
 		else
-			irq_dispatch(irq, regs);
+			irq_dispatch(irq);
 		desc->chip->end(source_irq);
 	} else
-		do_IRQ(irq, regs);
+		do_IRQ(irq);
 }
 
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 
 	if (pending & CAUSEF_IP7)
-		do_IRQ(7, regs);
+		do_IRQ(7);
 	else if (pending & 0x7800) {
 		if (pending & CAUSEF_IP3)
-			irq_dispatch(3, regs);
+			irq_dispatch(3);
 		else if (pending & CAUSEF_IP4)
-			irq_dispatch(4, regs);
+			irq_dispatch(4);
 		else if (pending & CAUSEF_IP5)
-			irq_dispatch(5, regs);
+			irq_dispatch(5);
 		else if (pending & CAUSEF_IP6)
-			irq_dispatch(6, regs);
+			irq_dispatch(6);
 	} else if (pending & CAUSEF_IP2)
-		irq_dispatch(2, regs);
+		irq_dispatch(2);
 	else if (pending & CAUSEF_IP0)
-		do_IRQ(0, regs);
+		do_IRQ(0);
 	else if (pending & CAUSEF_IP1)
-		do_IRQ(1, regs);
+		do_IRQ(1);
 	else
-		spurious_interrupt(regs);
+		spurious_interrupt();
 }
 
 void __init arch_init_irq(void)
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index 2d58b92..4204cd1 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -73,7 +73,7 @@
 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
 
 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
-		ino_t ino, unsigned d_type)
+		u64 ino, unsigned d_type)
 {
 	struct hpux_dirent * dirent;
 	struct getdents_callback * buf = (struct getdents_callback *) __buf;
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 3d569a4..d6c486e 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -424,7 +424,10 @@
 	/* make the generic dma mask a pointer to the parisc one */
 	dev->dev.dma_mask = &dev->dma_mask;
 	dev->dev.coherent_dma_mask = dev->dma_mask;
-	device_register(&dev->dev);
+	if (device_register(&dev->dev)) {
+		kfree(dev);
+		return NULL;
+	}
 
 	return dev;
 }
@@ -850,8 +853,10 @@
  */
 void init_parisc_bus(void)
 {
-	bus_register(&parisc_bus_type);
-	device_register(&root);
+	if (bus_register(&parisc_bus_type))
+		panic("Could not register PA-RISC bus type\n");
+	if (device_register(&root))
+		panic("Could not register PA-RISC root device\n");
 	get_device(&root);
 }
 
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index c2531ae..9158b70 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -160,13 +160,14 @@
 {
 #ifdef __LP64__
 	int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
 	convert_to_wide(pdc_result);
 	if(pdc_result[0] != NARROW_FIRMWARE)
 		parisc_narrow_firmware = 0;
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 #endif
 }
 
@@ -196,10 +197,11 @@
 int pdc_add_valid(unsigned long address)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address);
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -216,15 +218,16 @@
 int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         memcpy(&pdc_result, chassis_info, sizeof(*chassis_info));
         memcpy(&pdc_result2, led_info, len);
         retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO,
                               __pa(pdc_result), __pa(pdc_result2), len);
         memcpy(chassis_info, pdc_result, sizeof(*chassis_info));
         memcpy(led_info, pdc_result2, len);
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -239,13 +242,14 @@
 int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
 {
 	int retval = 0;
+	unsigned long flags;
         
 	if (!is_pdc_pat())
 		return -1;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_CHASSIS_LOG, PDC_PAT_CHASSIS_WRITE_LOG, __pa(&state), __pa(&data));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -258,10 +262,11 @@
 int pdc_chassis_disp(unsigned long disp)
 {
 	int retval = 0;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -273,11 +278,12 @@
 int pdc_chassis_warn(unsigned long *warn)
 {
 	int retval = 0;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(pdc_result));
 	*warn = pdc_result[0];
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -292,15 +298,16 @@
 int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result));
         convert_to_wide(pdc_result);
         pdc_coproc_info->ccr_functional = pdc_result[0];
         pdc_coproc_info->ccr_present = pdc_result[1];
         pdc_coproc_info->revision = pdc_result[17];
         pdc_coproc_info->model = pdc_result[18];
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -320,14 +327,15 @@
 		  void *iodc_data, unsigned int iodc_data_size)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa, 
 			      index, __pa(pdc_result2), iodc_data_size);
 	convert_to_wide(pdc_result);
 	*actcnt = pdc_result[0];
 	memcpy(iodc_data, pdc_result2, iodc_data_size);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -346,14 +354,15 @@
 			     struct pdc_module_path *mod_path, long mod_index)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result), 
 			      __pa(pdc_result2), mod_index);
 	convert_to_wide(pdc_result);
 	memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));
 	memcpy(mod_path, pdc_result2, sizeof(*mod_path));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr);
 	return retval;
@@ -372,13 +381,14 @@
 			      long mod_index, long addr_index)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result),
 			      mod_index, addr_index);
 	convert_to_wide(pdc_result);
 	memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr);
 	return retval;
@@ -393,12 +403,13 @@
 int pdc_model_info(struct pdc_model *model) 
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0);
 	convert_to_wide(pdc_result);
 	memcpy(model, pdc_result, sizeof(*model));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -414,8 +425,9 @@
 int pdc_model_sysmodel(char *name)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result),
                               OS_ID_HPUX, __pa(name));
         convert_to_wide(pdc_result);
@@ -425,7 +437,7 @@
         } else {
                 name[0] = 0;
         }
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -443,12 +455,13 @@
 int pdc_model_versions(unsigned long *versions, int id)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id);
         convert_to_wide(pdc_result);
         *versions = pdc_result[0];
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -463,13 +476,14 @@
 int pdc_model_cpuid(unsigned long *cpu_id)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
         retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0);
         convert_to_wide(pdc_result);
         *cpu_id = pdc_result[0];
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -484,13 +498,14 @@
 int pdc_model_capabilities(unsigned long *capabilities)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
         retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
         convert_to_wide(pdc_result);
         *capabilities = pdc_result[0];
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -504,12 +519,13 @@
 int pdc_cache_info(struct pdc_cache_info *cache_info)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0);
         convert_to_wide(pdc_result);
         memcpy(cache_info, pdc_result, sizeof(*cache_info));
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -523,13 +539,14 @@
 int pdc_spaceid_bits(unsigned long *space_bits)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	pdc_result[0] = 0;
 	retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_RET_SPID, __pa(pdc_result), 0);
 	convert_to_wide(pdc_result);
 	*space_bits = pdc_result[0];
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -544,11 +561,12 @@
 int pdc_btlb_info(struct pdc_btlb_info *btlb) 
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
         memcpy(btlb, pdc_result, sizeof(*btlb));
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         if(retval < 0) {
                 btlb->max_size = 0;
@@ -572,13 +590,14 @@
 		struct pdc_module_path *mod_path)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         memcpy(pdc_result2, mod_path, sizeof(*mod_path));
         retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result),
 				__pa(pdc_result2));
         memcpy(address, pdc_result, sizeof(*address));
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -594,8 +613,9 @@
 int pdc_lan_station_id(char *lan_addr, unsigned long hpa)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
 			__pa(pdc_result), hpa);
 	if (retval < 0) {
@@ -604,7 +624,7 @@
 	} else {
 		memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE);
 	}
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -623,13 +643,14 @@
 int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count)
 {
        int retval;
+	unsigned long flags;
 
-       spin_lock_irq(&pdc_lock);
+       spin_lock_irqsave(&pdc_lock, flags);
        retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_READ, staddr,
                __pa(pdc_result), count);
        convert_to_wide(pdc_result);
        memcpy(memaddr, pdc_result, count);
-       spin_unlock_irq(&pdc_lock);
+       spin_unlock_irqrestore(&pdc_lock, flags);
 
        return retval;
 }
@@ -648,13 +669,14 @@
 int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count)
 {
        int retval;
+	unsigned long flags;
 
-       spin_lock_irq(&pdc_lock);
+       spin_lock_irqsave(&pdc_lock, flags);
        memcpy(pdc_result, memaddr, count);
        convert_to_wide(pdc_result);
        retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_WRITE, staddr,
                __pa(pdc_result), count);
-       spin_unlock_irq(&pdc_lock);
+       spin_unlock_irqrestore(&pdc_lock, flags);
 
        return retval;
 }
@@ -672,11 +694,12 @@
 int pdc_stable_get_size(unsigned long *size)
 {
        int retval;
+	unsigned long flags;
 
-       spin_lock_irq(&pdc_lock);
+       spin_lock_irqsave(&pdc_lock, flags);
        retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_RETURN_SIZE, __pa(pdc_result));
        *size = pdc_result[0];
-       spin_unlock_irq(&pdc_lock);
+       spin_unlock_irqrestore(&pdc_lock, flags);
 
        return retval;
 }
@@ -691,10 +714,11 @@
 int pdc_stable_verify_contents(void)
 {
        int retval;
+	unsigned long flags;
 
-       spin_lock_irq(&pdc_lock);
+       spin_lock_irqsave(&pdc_lock, flags);
        retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_VERIFY_CONTENTS);
-       spin_unlock_irq(&pdc_lock);
+       spin_unlock_irqrestore(&pdc_lock, flags);
 
        return retval;
 }
@@ -709,10 +733,11 @@
 int pdc_stable_initialize(void)
 {
        int retval;
+	unsigned long flags;
 
-       spin_lock_irq(&pdc_lock);
+       spin_lock_irqsave(&pdc_lock, flags);
        retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_INITIALIZE);
-       spin_unlock_irq(&pdc_lock);
+       spin_unlock_irqrestore(&pdc_lock, flags);
 
        return retval;
 }
@@ -735,8 +760,9 @@
 int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 
 /* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */
 #define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
@@ -776,7 +802,8 @@
 	}
 
  out:
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
+
 	return (retval >= PDC_OK);
 }
 EXPORT_SYMBOL(pdc_get_initiator);
@@ -794,13 +821,14 @@
 int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, 
 			      __pa(pdc_result), hpa);
 	convert_to_wide(pdc_result);
 	*num_entries = pdc_result[0];
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -817,14 +845,15 @@
 int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl)
 {
 	int retval;
+	unsigned long flags;
 
 	BUG_ON((unsigned long)tbl & 0x7);
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	pdc_result[0] = num_entries;
 	retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, 
 			      __pa(pdc_result), hpa, __pa(tbl));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -842,12 +871,15 @@
 unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr)
 {
 	int retval;
-	spin_lock_irq(&pdc_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdc_lock, flags);
 	pdc_result[0] = 0;
 	pdc_result[1] = 0;
 	retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_READ_CONFIG, 
 			      __pa(pdc_result), hpa, cfg_addr&~3UL, 4UL);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
+
 	return retval ? ~0 : (unsigned int) pdc_result[0];
 }
 
@@ -863,12 +895,15 @@
 void pdc_pci_config_write(void *hpa, unsigned long cfg_addr, unsigned int val)
 {
 	int retval;
-	spin_lock_irq(&pdc_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdc_lock, flags);
 	pdc_result[0] = 0;
 	retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_WRITE_CONFIG, 
 			      __pa(pdc_result), hpa,
 			      cfg_addr&~3UL, 4UL, (unsigned long) val);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
+
 	return retval;
 }
 #endif /* UNTESTED CODE */
@@ -882,12 +917,13 @@
 int pdc_tod_read(struct pdc_tod *tod)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0);
         convert_to_wide(pdc_result);
         memcpy(tod, pdc_result, sizeof(*tod));
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -903,10 +939,11 @@
 int pdc_tod_set(unsigned long sec, unsigned long usec)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -917,13 +954,14 @@
 		struct pdc_memory_table *tbl, unsigned long entries)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries);
 	convert_to_wide(pdc_result);
 	memcpy(r_addr, pdc_result, sizeof(*r_addr));
 	memcpy(tbl, pdc_result2, entries * sizeof(*tbl));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -936,11 +974,12 @@
 int pdc_do_firm_test_reset(unsigned long ftc_bitmap)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET,
                               PDC_FIRM_TEST_MAGIC, ftc_bitmap);
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -953,10 +992,11 @@
 int pdc_do_reset(void)
 {
         int retval;
+	unsigned long flags;
 
-        spin_lock_irq(&pdc_lock);
+        spin_lock_irqsave(&pdc_lock, flags);
         retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET);
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, flags);
 
         return retval;
 }
@@ -970,16 +1010,17 @@
 int __init pdc_soft_power_info(unsigned long *power_reg)
 {
 	int retval;
+	unsigned long flags;
 
 	*power_reg = (unsigned long) (-1);
 	
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0);
 	if (retval == PDC_OK) {
                 convert_to_wide(pdc_result);
                 *power_reg = f_extend(pdc_result[0]);
 	}
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -998,9 +1039,12 @@
 int pdc_soft_power_button(int sw_control)
 {
 	int retval;
-	spin_lock_irq(&pdc_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
+
 	return retval;
 }
 
@@ -1011,9 +1055,11 @@
  */
 void pdc_io_reset(void)
 {
-	spin_lock_irq(&pdc_lock);  
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdc_lock, flags);
 	mem_pdc_call(PDC_IO, PDC_IO_RESET, 0);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 }
 
 /*
@@ -1027,9 +1073,11 @@
  */
 void pdc_io_reset_devices(void)
 {
-	spin_lock_irq(&pdc_lock);  
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdc_lock, flags);
 	mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 }
 
 
@@ -1146,10 +1194,11 @@
                  unsigned long glob_cfg)
 {
         int retval;
+	unsigned long irqflags;
 
-        spin_lock_irq(&pdc_lock);  
+        spin_lock_irqsave(&pdc_lock, irqflags);  
         retval = real32_call(func, flags, inptr, outputr, glob_cfg);
-        spin_unlock_irq(&pdc_lock);
+        spin_unlock_irqrestore(&pdc_lock, irqflags);
 
         return retval;
 }
@@ -1166,11 +1215,12 @@
 int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result));
 	memcpy(cell_info, pdc_result, sizeof(*cell_info));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1190,16 +1240,17 @@
 			unsigned long view_type, void *mem_addr)
 {
 	int retval;
+	unsigned long flags;
 	static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8)));
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result), 
 			      ploc, mod, view_type, __pa(&result));
 	if(!retval) {
 		*actcnt = pdc_result[0];
 		memcpy(mem_addr, &result, *actcnt);
 	}
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1214,12 +1265,13 @@
 int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
 			      __pa(&pdc_result), hpa);
 	memcpy(cpu_info, pdc_result, sizeof(*cpu_info));
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1235,12 +1287,13 @@
 int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE,
 			      __pa(pdc_result), cell_num);
 	*num_entries = pdc_result[0];
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1255,11 +1308,12 @@
 int pdc_pat_get_irt(void *r_addr, unsigned long cell_num)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE,
 			      __pa(r_addr), cell_num);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1276,13 +1330,14 @@
 			    unsigned long count, unsigned long offset)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result), 
 			      __pa(pdc_result2), count, offset);
 	*actual_len = pdc_result[0];
 	memcpy(mem_addr, pdc_result2, *actual_len);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1297,7 +1352,9 @@
 int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr)
 {
 	int retval;
-	spin_lock_irq(&pdc_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ,
 					__pa(pdc_result), pci_addr, pci_size);
 	switch(pci_size) {
@@ -1305,7 +1362,7 @@
 		case 2: *(u16 *)mem_addr =  (u16) pdc_result[0];
 		case 4: *(u32 *)mem_addr =  (u32) pdc_result[0];
 	}
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
@@ -1321,11 +1378,12 @@
 int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val)
 {
 	int retval;
+	unsigned long flags;
 
-	spin_lock_irq(&pdc_lock);
+	spin_lock_irqsave(&pdc_lock, flags);
 	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE,
 				pci_addr, pci_size, val);
-	spin_unlock_irq(&pdc_lock);
+	spin_unlock_irqrestore(&pdc_lock, flags);
 
 	return retval;
 }
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 9bdd019..b39c5b9 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -35,8 +35,8 @@
 
 #undef PARISC_IRQ_CR16_COUNTS
 
-extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
-extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
+extern irqreturn_t timer_interrupt(int, void *);
+extern irqreturn_t ipi_interrupt(int, void *);
 
 #define EIEM_MASK(irq)       (1UL<<(CPU_IRQ_MAX - irq))
 
@@ -347,12 +347,14 @@
 /* ONLY called from entry.S:intr_extint() */
 void do_cpu_irq_mask(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
 	unsigned long eirr_val;
 	int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
 	cpumask_t dest;
 #endif
 
+	old_regs = set_irq_regs(regs);
 	local_irq_disable();
 	irq_enter();
 
@@ -375,10 +377,11 @@
 		goto set_out;
 	}
 #endif
-	__do_IRQ(irq, regs);
+	__do_IRQ(irq);
 
  out:
 	irq_exit();
+	set_irq_regs(old_regs);
 	return;
 
  set_out:
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 6d57553..8f6a0b3 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -69,10 +69,6 @@
 EXPORT_SYMBOL(memcpy_fromio);
 EXPORT_SYMBOL(memset_io);
 
-#include <asm/unistd.h>
-EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_write);
-
 #include <asm/semaphore.h>
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down_interruptible);
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index d3b8fc5..199887a 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -290,7 +290,7 @@
 void pcibios_align_resource(void *data, struct resource *res,
 				resource_size_t size, resource_size_t alignment)
 {
-	unsigned long mask, align;
+	resource_size_t mask, align;
 
 	DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n",
 		pci_name(((struct pci_dev *) data)),
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index faad338..4a23a97 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -154,7 +154,7 @@
 
 
 irqreturn_t
-ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+ipi_interrupt(int irq, void *dev_id) 
 {
 	int this_cpu = smp_processor_id();
 	struct cpuinfo_parisc *p = &cpu_data[this_cpu];
@@ -414,19 +414,6 @@
 	on_each_cpu(flush_tlb_all_local, NULL, 1, 1);
 }
 
-
-void 
-smp_do_timer(struct pt_regs *regs)
-{
-	int cpu = smp_processor_id();
-	struct cpuinfo_parisc *data = &cpu_data[cpu];
-
-        if (!--data->prof_counter) {
-		data->prof_counter = data->prof_multiplier;
-		update_process_times(user_mode(regs));
-	}
-}
-
 /*
  * Called by secondaries to update state and initialize CPU registers.
  */
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 1db5588..512642d 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -266,30 +266,17 @@
 	return err;
 }
 
-static inline int override_machine(char __user *mach) {
-#ifdef CONFIG_COMPAT
-	if (personality(current->personality) == PER_LINUX32) {
-		if (__put_user(0, mach + 6) ||
-		    __put_user(0, mach + 7))
-			return -EFAULT;
-	}
-
-	return 0;
-#else /*!CONFIG_COMPAT*/
-	return 0;
-#endif /*CONFIG_COMPAT*/
-}
-
-long parisc_newuname(struct new_utsname __user *utsname)
+long parisc_newuname(struct new_utsname __user *name)
 {
-	int err = 0;
+	int err = sys_newuname(name);
 
-	down_read(&uts_sem);
-	if (copy_to_user(utsname, &system_utsname, sizeof(*utsname)))
-		err = -EFAULT;
-	up_read(&uts_sem);
+#ifdef CONFIG_COMPAT
+	if (!err && personality(current->personality) == PER_LINUX32) {
+		if (__put_user(0, name->machine + 6) ||
+		    __put_user(0, name->machine + 7))
+			err = -EFAULT;
+	}
+#endif
 
-	err = override_machine(utsname->machine);
-
-	return (long)err;
+	return err;
 }
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index e3b30bc..29be437 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -111,13 +111,14 @@
 
 asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
+#ifndef CONFIG_SYSCTL_SYSCALL
+	return -ENOSYS;
+#else
 	struct __sysctl_args32 tmp;
 	int error;
 	unsigned int oldlen32;
-	size_t oldlen, *oldlenp = NULL;
+	size_t oldlen, __user *oldlenp = NULL;
 	unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
-	extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
-	       void *newval, size_t newlen);
 
 	DBG(("sysctl32(%p)\n", args));
 
@@ -144,8 +145,9 @@
 	}
 
 	lock_kernel();
-	error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval,
-			  oldlenp, (void *)(u64)tmp.newval, tmp.newlen);
+	error = do_sysctl((int __user *)(u64)tmp.name, tmp.nlen,
+			  (void __user *)(u64)tmp.oldval, oldlenp,
+			  (void __user *)(u64)tmp.newval, tmp.newlen);
 	unlock_kernel();
 	if (oldlenp) {
 		if (!error) {
@@ -157,10 +159,11 @@
 					error = -EFAULT;
 			}
 		}
-		if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused)))
+		if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
 			error = -EFAULT;
 	}
 	return error;
+#endif
 }
 
 #endif /* CONFIG_SYSCTL */
@@ -310,9 +313,8 @@
 
 #define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-static int
-filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
-	   unsigned int d_type)
+static int filldir32 (void *__buf, const char *name, int namlen,
+			loff_t offset, u64 ino, unsigned int d_type)
 {
 	struct linux32_dirent __user * dirent;
 	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
@@ -374,9 +376,8 @@
 	return error;
 }
 
-static int
-fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
-	      unsigned int d_type)
+static int fillonedir32(void * __buf, const char * name, int namlen,
+			loff_t offset, u64 ino, unsigned int d_type)
 {
 	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
 	struct old_linux32_dirent __user * dirent;
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index b3496b5..bad7d1e 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -34,25 +34,39 @@
 
 static unsigned long clocktick __read_mostly;	/* timer cycles per tick */
 
-#ifdef CONFIG_SMP
-extern void smp_do_timer(struct pt_regs *regs);
-#endif
-
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+/*
+ * We keep time on PA-RISC Linux by using the Interval Timer which is
+ * a pair of registers; one is read-only and one is write-only; both
+ * accessed through CR16.  The read-only register is 32 or 64 bits wide,
+ * and increments by 1 every CPU clock tick.  The architecture only
+ * guarantees us a rate between 0.5 and 2, but all implementations use a
+ * rate of 1.  The write-only register is 32-bits wide.  When the lowest
+ * 32 bits of the read-only register compare equal to the write-only
+ * register, it raises a maskable external interrupt.  Each processor has
+ * an Interval Timer of its own and they are not synchronised.  
+ *
+ * We want to generate an interrupt every 1/HZ seconds.  So we program
+ * CR16 to interrupt every @clocktick cycles.  The it_value in cpu_data
+ * is programmed with the intended time of the next tick.  We can be
+ * held off for an arbitrarily long period of time by interrupts being
+ * disabled, so we may miss one or more ticks.
+ */
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	unsigned long now;
 	unsigned long next_tick;
-	unsigned long cycles_elapsed;
+	unsigned long cycles_elapsed, ticks_elapsed;
 	unsigned long cycles_remainder;
 	unsigned int cpu = smp_processor_id();
+	struct cpuinfo_parisc *cpuinfo = &cpu_data[cpu];
 
 	/* gcc can optimize for "read-only" case with a local clocktick */
 	unsigned long cpt = clocktick;
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 	/* Initialize next_tick to the expected tick time. */
-	next_tick = cpu_data[cpu].it_value;
+	next_tick = cpuinfo->it_value;
 
 	/* Get current interval timer.
 	 * CR16 reads as 64 bits in CPU wide mode.
@@ -67,11 +81,14 @@
 		 * of the more expensive div/mul method
 		 */
 		cycles_remainder = cycles_elapsed;
+		ticks_elapsed = 1;
 		while (cycles_remainder > cpt) {
 			cycles_remainder -= cpt;
+			ticks_elapsed++;
 		}
 	} else {
 		cycles_remainder = cycles_elapsed % cpt;
+		ticks_elapsed = 1 + cycles_elapsed / cpt;
 	}
 
 	/* Can we differentiate between "early CR16" (aka Scenario 1) and
@@ -81,18 +98,7 @@
 	 * cycles after the IT fires. But it's arbitrary how much time passes
 	 * before we call it "late". I've picked one second.
 	 */
-/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */
-#if HZ == 1000
-	if (cycles_elapsed > (cpt << 10) )
-#elif HZ == 250
-	if (cycles_elapsed > (cpt << 8) )
-#elif HZ == 100
-	if (cycles_elapsed > (cpt << 7) )
-#else
-#warn WTF is HZ set to anyway?
-	if (cycles_elapsed > (HZ * cpt) )
-#endif
-	{
+	if (ticks_elapsed > HZ) {
 		/* Scenario 3: very long delay?  bad in any case */
 		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
 			" cycles %lX rem %lX "
@@ -111,7 +117,7 @@
 	 */
 	next_tick = now + cycles_remainder;
 
-	cpu_data[cpu].it_value = next_tick;
+	cpuinfo->it_value = next_tick;
 
 	/* Skip one clocktick on purpose if we are likely to miss next_tick.
 	 * We want to avoid the new next_tick being less than CR16.
@@ -122,21 +128,22 @@
 		next_tick += cpt;
 
 	/* Program the IT when to deliver the next interrupt. */
-        /* Only bottom 32-bits of next_tick are written to cr16.  */
+	/* Only bottom 32-bits of next_tick are written to cr16.  */
 	mtctl(next_tick, 16);
 
 
 	/* Done mucking with unreliable delivery of interrupts.
 	 * Go do system house keeping.
 	 */
-#ifdef CONFIG_SMP
-	smp_do_timer(regs);
-#else
-	update_process_times(user_mode(regs));
-#endif
+
+	if (!--cpuinfo->prof_counter) {
+		cpuinfo->prof_counter = cpuinfo->prof_multiplier;
+		update_process_times(user_mode(get_irq_regs()));
+	}
+
 	if (cpu == 0) {
 		write_seqlock(&xtime_lock);
-		do_timer(regs);
+		do_timer(ticks_elapsed);
 		write_sequnlock(&xtime_lock);
 	}
 
@@ -310,13 +317,15 @@
 
 	start_cpu_itimer();	/* get CPU 0 started */
 
-	if(pdc_tod_read(&tod_data) == 0) {
-		write_seqlock_irq(&xtime_lock);
+	if (pdc_tod_read(&tod_data) == 0) {
+		unsigned long flags;
+
+		write_seqlock_irqsave(&xtime_lock, flags);
 		xtime.tv_sec = tod_data.tod_sec;
 		xtime.tv_nsec = tod_data.tod_usec * 1000;
 		set_normalized_timespec(&wall_to_monotonic,
 		                        -xtime.tv_sec, -xtime.tv_nsec);
-		write_sequnlock_irq(&xtime_lock);
+		write_sequnlock_irqrestore(&xtime_lock, flags);
 	} else {
 		printk(KERN_ERR "Error reading tod clock\n");
 	        xtime.tv_sec = 0;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8b69104..2bd9b7f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -751,6 +751,15 @@
 	def_bool y
 	depends on MEMORY_HOTPLUG
 
+# Some NUMA nodes have memory ranges that span
+# other nodes.  Even though a pfn is valid and
+# between a node's start and end pfns, it may not
+# reside on that node.  See memmap_init_zone()
+# for details.
+config NODES_SPAN_OTHER_NODES
+	def_bool y
+	depends on NEED_MULTIPLE_NODES
+
 config PPC_64K_PAGES
 	bool "64k page size"
 	depends on PPC64
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 003520b..37ddfca 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -105,10 +105,10 @@
 # Bits for building various flavours of zImage
 
 ifneq ($(CROSS32_COMPILE),)
-CROSSWRAP := -C $(CROSS32_COMPILE)
+CROSSWRAP := -C "$(CROSS32_COMPILE)"
 else
 ifneq ($(CROSS_COMPILE),)
-CROSSWRAP := -C $(CROSS_COMPILE)
+CROSSWRAP := -C "$(CROSS_COMPILE)"
 endif
 endif
 
@@ -151,12 +151,12 @@
 $(obj)/uImage: vmlinux $(wrapperbits)
 	$(call cmd,wrap,uboot)
 
-image-$(CONFIG_PPC_PSERIES)	+= zImage.pseries
-image-$(CONFIG_PPC_MAPLE)	+= zImage.pseries
-image-$(CONFIG_PPC_CELL)	+= zImage.pseries
-image-$(CONFIG_PPC_CHRP)	+= zImage.chrp
-image-$(CONFIG_PPC_PMAC)	+= zImage.pmac
-image-$(CONFIG_DEFAULT_UIMAGE)	+= uImage
+image-$(CONFIG_PPC_PSERIES)		+= zImage.pseries
+image-$(CONFIG_PPC_MAPLE)		+= zImage.pseries
+image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
+image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
+image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
+image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
 
 # For 32-bit powermacs, build the COFF and miboot images
 # as well as the ELF images.
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
new file mode 100644
index 0000000..27807fc
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -0,0 +1,246 @@
+/*
+ * MPC8349E-mITX Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor 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.
+ */
+/ {
+	model = "MPC8349EMITX";
+	compatible = "MPC834xMITX";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8349@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;
+			i-cache-line-size = <20>;
+			d-cache-size = <8000>;
+			i-cache-size = <8000>;
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;
+	};
+
+	soc8349@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;                    // from bootloader
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = <700>;
+			mode = <0>;
+		};
+
+		usb@22000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-mph";
+			reg = <22000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <27 2>;
+			phy_type = "ulpi";
+			port1;
+		};
+
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <26 2>;
+			phy_type = "ulpi";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			linux,phandle = <24520>;
+
+			/* Vitesse 8201 */
+			ethernet-phy@1c {
+				linux,phandle = <245201c>;
+				interrupt-parent = <700>;
+				interrupts = <12 2>;
+				reg = <1c>;
+				device_type = "ethernet-phy";
+			};
+
+			/* Vitesse 7385 */
+			ethernet-phy@1f {
+				linux,phandle = <245201f>;
+				interrupt-parent = <700>;
+				interrupts = <12 2>;
+				reg = <1f>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <20 8 21 8 22 8>;
+			interrupt-parent = <700>;
+			phy-handle = <245201c>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 8 24 8 25 8>;
+			interrupt-parent = <700>;
+			phy-handle = <245201f>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;		// from bootloader
+			interrupts = <9 8>;
+			interrupt-parent = <700>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;		// from bootloader
+			interrupts = <a 8>;
+			interrupt-parent = <700>;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+					/* IDSEL 0x10 - SATA */
+					8000 0 0 1 700 16 8 /* SATA_INTA */
+					>;
+			interrupt-parent = <700>;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <42000000 0 80000000 80000000 0 10000000
+				  02000000 0 90000000 90000000 0 10000000
+				  01000000 0 00000000 e2000000 0 01000000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		pci@8600 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+					/* IDSEL 0x0E - MiniPCI Slot */
+					7000 0 0 1 700 15 8 /* PCI_INTA */
+
+					/* IDSEL 0x0F - PCI Slot */
+					7800 0 0 1 700 14 8 /* PCI_INTA */
+					7800 0 0 2 700 15 8 /* PCI_INTB */
+					 >;
+			interrupt-parent = <700>;
+			interrupts = <43 8>;
+			bus-range = <1 1>;
+			ranges = <42000000 0 a0000000 a0000000 0 10000000
+				  02000000 0 b0000000 b0000000 0 10000000
+				  01000000 0 00000000 e3000000 0 01000000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8600 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = <700>;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		pic@700 {
+			linux,phandle = <700>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index fd99f78..3a71845 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -176,12 +176,9 @@
 static void *of_try_claim(u32 size)
 {
 	unsigned long addr = 0;
-	static u8 first_time = 1;
 
-	if (first_time) {
+	if (claim_base == 0)
 		claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
-		first_time = 0;
-	}
 
 	for(; claim_base < RAM_END; claim_base += ONE_MB) {
 #ifdef DEBUG
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 6fd9e7a..892d5dd 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.18-rc6
-# Sun Sep 10 10:20:32 2006
+# Linux kernel version: 2.6.18
+# Wed Oct  4 15:30:50 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -22,6 +22,7 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -52,10 +53,11 @@
 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=y
 CONFIG_IKCONFIG_PROC=y
@@ -63,7 +65,9 @@
 # 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_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -72,12 +76,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
@@ -96,6 +100,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -115,12 +120,13 @@
 # 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_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
+# CONFIG_PPC_PASEMI is not set
 CONFIG_PPC_CELL=y
 CONFIG_PPC_CELL_NATIVE=y
 CONFIG_PPC_IBM_CELL_BLADE=y
@@ -142,7 +148,6 @@
 #
 CONFIG_SPU_FS=m
 CONFIG_SPU_BASE=y
-CONFIG_SPUFS_MMAP=y
 CONFIG_CBE_RAS=y
 
 #
@@ -158,7 +163,7 @@
 CONFIG_PREEMPT_BKL=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
-CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_FORCE_MAX_ZONEORDER=9
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_KEXEC=y
@@ -168,6 +173,7 @@
 CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -178,12 +184,12 @@
 # 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_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
-CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_ARCH_MEMORY_PROBE=y
-# CONFIG_PPC_64K_PAGES is not set
+CONFIG_PPC_64K_PAGES=y
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
@@ -201,6 +207,7 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCIEPORTBUS=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -228,6 +235,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
@@ -249,7 +257,8 @@
 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"
 
 #
 # IP: Virtual Server Configuration
@@ -261,11 +270,15 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=y
 CONFIG_INET6_XFRM_MODE_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -322,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
 
@@ -434,6 +446,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
@@ -456,6 +469,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)
@@ -470,6 +489,7 @@
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -504,7 +524,7 @@
 # CONFIG_DUMMY is not set
 CONFIG_BONDING=y
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=y
 
 #
 # ARCnet devices
@@ -552,7 +572,7 @@
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=m
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -599,6 +619,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -865,6 +886,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=y
@@ -916,7 +938,7 @@
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=m
 # CONFIG_FUSE_FS is not set
 
 #
@@ -943,8 +965,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
@@ -1084,6 +1108,7 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
@@ -1102,6 +1127,7 @@
 # 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
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -1123,6 +1149,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+# CONFIG_CRYPTO_MANAGER is not set
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -1132,6 +1162,8 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index d58f82f..b500550 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.18-rc6
-# Sun Sep 10 10:22:57 2006
+# Linux kernel version: 2.6.19-rc1
+# Fri Oct  6 13:25:04 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -22,6 +22,7 @@
 CONFIG_PPC_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -52,10 +53,11 @@
 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
@@ -64,7 +66,9 @@
 # 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_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -73,12 +77,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 +101,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -115,13 +120,18 @@
 #
 # Platform support
 #
-# CONFIG_PPC_MULTIPLATFORM is not set
-CONFIG_PPC_ISERIES=y
+CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
+# CONFIG_PPC_PSERIES is not set
+CONFIG_PPC_ISERIES=y
+# 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_UDBG_RTAS_CONSOLE is not set
+# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_U3_DART is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
@@ -147,12 +157,15 @@
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_LPARCFG=y
 # CONFIG_NUMA is not set
 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
@@ -179,6 +192,7 @@
 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
 
 #
@@ -206,6 +220,7 @@
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
 CONFIG_NET_KEY=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -224,10 +239,12 @@
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=m
 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"
 
 #
 # IP: Virtual Server Configuration
@@ -247,6 +264,7 @@
 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
@@ -255,6 +273,7 @@
 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_LENGTH=m
@@ -294,7 +313,6 @@
 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 is not set
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -319,7 +337,6 @@
 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_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -351,7 +368,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
 
@@ -433,6 +449,7 @@
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -454,12 +471,14 @@
 # CONFIG_SCSI_LOGGING 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_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_LIBSAS_DEBUG=y
 
 #
 # SCSI low-level drivers
@@ -472,10 +491,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 is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -486,16 +506,22 @@
 CONFIG_SCSI_IBMVSCSI=m
 # 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
 
 #
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 CONFIG_MD=y
@@ -508,6 +534,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
@@ -573,6 +600,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
+CONFIG_PCNET32_NAPI=y
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -610,6 +638,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -649,6 +678,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
@@ -671,6 +701,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -774,12 +805,12 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -893,6 +924,9 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_NOLOCK=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -929,12 +963,14 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -988,6 +1024,7 @@
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 # CONFIG_9P_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # Partition Types
@@ -1040,6 +1077,12 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
 # iSeries device drivers
 #
 CONFIG_VIOCONS=y
@@ -1073,6 +1116,7 @@
 # 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_KERNEL=y
@@ -1091,6 +1135,7 @@
 # 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
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
@@ -1109,6 +1154,10 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
@@ -1118,9 +1167,12 @@
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 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/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 62ba660..ae96a5b 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-rc6
-# Sun Sep 10 10:24:55 2006
+# Linux kernel version: 2.6.18
+# Mon Oct  9 11:59:34 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -22,6 +22,7 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -34,7 +35,7 @@
 CONFIG_PPC_STD_MMU=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
-CONFIG_NR_CPUS=2
+CONFIG_NR_CPUS=4
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -51,10 +52,11 @@
 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
@@ -62,7 +64,9 @@
 # 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_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -71,12 +75,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 +99,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -114,16 +119,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_PSERIES is not set
+# CONFIG_PPC_ISERIES 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_UDBG_RTAS_CONSOLE is not set
 CONFIG_U3_DART=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
@@ -157,6 +162,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
@@ -184,6 +190,7 @@
 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
 
 #
@@ -211,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
@@ -232,10 +240,12 @@
 # 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_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
@@ -265,7 +275,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
 
@@ -377,6 +386,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
@@ -399,6 +409,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)
@@ -498,7 +514,7 @@
 # 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)
@@ -545,6 +561,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -704,6 +721,7 @@
 #
 # Misc devices
 #
+# CONFIG_TIFM_CORE is not set
 
 #
 # Multimedia devices
@@ -779,7 +797,6 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -802,6 +819,7 @@
 # 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
@@ -828,6 +846,7 @@
 CONFIG_USB_SERIAL=y
 # CONFIG_USB_SERIAL_CONSOLE is not set
 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 is not set
@@ -862,6 +881,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_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
@@ -879,6 +899,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
@@ -886,9 +907,9 @@
 # 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
@@ -995,8 +1016,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
@@ -1129,6 +1152,7 @@
 # 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_KERNEL=y
@@ -1148,6 +1172,7 @@
 # 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
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
@@ -1169,6 +1194,9 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -1178,6 +1206,8 @@
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index cd3535e..0561b73 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -1248,7 +1248,7 @@
 # CONFIG_AMIGA_PARTITION is not set
 # CONFIG_ATARI_PARTITION is not set
 # CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
 # CONFIG_LDM_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 44175fb..d2833c1 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -184,6 +184,7 @@
 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
 CONFIG_PROC_DEVICETREE=y
@@ -506,7 +507,7 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_ATA is not set
+CONFIG_ATA=y
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 47a613c..95382f9 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -268,7 +268,7 @@
 		.cpu_user_features	= COMMON_USER_POWER6,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.num_pmcs		= 8,
+		.num_pmcs		= 6,
 		.oprofile_cpu_type	= "ppc64/power6",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
  		.oprofile_mmcra_sihv	= POWER6_MMCRA_SIHV,
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 124dbcb..39db7a3 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -319,7 +319,7 @@
 
 int ibmebus_request_irq(struct ibmebus_dev *dev,
 			u32 ist, 
-			irqreturn_t (*handler)(int, void*, struct pt_regs *),
+			irq_handler_t handler,
 			unsigned long irq_flags, const char * devname,
 			void *dev_id)
 {
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index ba06940..f88a2a6 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -75,7 +75,7 @@
 	/* This allocator was derived from x86_64's bit string search */
 
 	/* Sanity check */
-	if (unlikely(npages) == 0) {
+	if (unlikely(npages == 0)) {
 		if (printk_ratelimit())
 			WARN_ON(1);
 		return DMA_ERROR_CODE;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index c3f58f2..5e37bf1 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -187,6 +187,7 @@
 
 void do_IRQ(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	unsigned int irq;
 #ifdef CONFIG_IRQSTACKS
 	struct thread_info *curtp, *irqtp;
@@ -216,7 +217,7 @@
 	 * The value -2 is for buggy hardware and means that this IRQ
 	 * has already been handled. -- Tom
 	 */
-	irq = ppc_md.get_irq(regs);
+	irq = ppc_md.get_irq();
 
 	if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) {
 #ifdef CONFIG_IRQSTACKS
@@ -230,18 +231,19 @@
 				handler = &__do_IRQ;
 			irqtp->task = curtp->task;
 			irqtp->flags = 0;
-			call_handle_irq(irq, desc, regs, irqtp, handler);
+			call_handle_irq(irq, desc, irqtp, handler);
 			irqtp->task = NULL;
 			if (irqtp->flags)
 				set_bits(irqtp->flags, &curtp->flags);
 		} else
 #endif
-			generic_handle_irq(irq, regs);
+			generic_handle_irq(irq);
 	} else if (irq != NO_IRQ_IGNORE)
 		/* That's not SMP safe ... but who cares ? */
 		ppc_spurious_interrupts++;
 
         irq_exit();
+	set_irq_regs(old_regs);
 
 #ifdef CONFIG_PPC_ISERIES
 	if (get_lppaca()->int_dword.fields.decr_int) {
@@ -570,8 +572,8 @@
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
 
-extern unsigned int irq_create_of_mapping(struct device_node *controller,
-					  u32 *intspec, unsigned int intsize)
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   u32 *intspec, unsigned int intsize)
 {
 	struct irq_host *host;
 	irq_hw_number_t hwirq;
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 41521b3..c70e207 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -52,12 +52,12 @@
 	blr
 
 _GLOBAL(call_handle_irq)
-	ld	r8,0(r7)
+	ld	r8,0(r6)
 	mflr	r0
 	std	r0,16(r1)
 	mtctr	r8
-	stdu	r1,THREAD_SIZE-112(r6)
-	mr	r1,r6
+	stdu	r1,THREAD_SIZE-112(r5)
+	mr	r1,r5
 	bctrl
 	ld	r1,0(r1)
 	ld	r0,16(r1)
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 9b49f86..0d9ff72 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -441,14 +441,14 @@
 		end = res->end - off;
 		io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;
 		io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;
-		if (end > 0xffff) {
-			pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
-					      start >> 16);
-			pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
-					      end >> 16);
+		if (end > 0xffff)
 			io_base_lo |= PCI_IO_RANGE_TYPE_32;
-		} else
+		else
 			io_base_lo |= PCI_IO_RANGE_TYPE_16;
+		pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+				start >> 16);
+		pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+				end >> 16);
 		pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);
 		pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);
 
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 78d3c0f..9bae8a5 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -199,8 +199,14 @@
 	pci_setup_pci_controller(phb);
 	phb->arch_data = dev;
 	phb->is_dynamic = mem_init_done;
-	if (dev)
-		PHB_SET_NODE(phb, of_node_to_nid(dev));
+	if (dev) {
+		int nid = of_node_to_nid(dev);
+
+		if (nid < 0 || !node_online(nid))
+			nid = -1;
+
+		PHB_SET_NODE(phb, nid);
+	}
 	return phb;
 }
 
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7b2f645..f3d4dd5 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -341,13 +341,6 @@
 
 static int instructions_to_print = 16;
 
-#ifdef CONFIG_PPC64
-#define BAD_PC(pc)	((REGION_ID(pc) != KERNEL_REGION_ID) && \
-		         (REGION_ID(pc) != VMALLOC_REGION_ID))
-#else
-#define BAD_PC(pc)	((pc) < KERNELBASE)
-#endif
-
 static void show_instructions(struct pt_regs *regs)
 {
 	int i;
@@ -366,7 +359,8 @@
 		 * bad address because the pc *should* only be a
 		 * kernel address.
 		 */
-		if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) {
+		if (!__kernel_text_address(pc) ||
+		     __get_user(instr, (unsigned int __user *)pc)) {
 			printk("XXXXXXXX ");
 		} else {
 			if (regs->nip == pc)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index eb913f8..865b964 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -724,7 +724,7 @@
 		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
 
 #ifdef CONFIG_CMDLINE
-	if (l == 0 || (l == 1 && (*p) == 0))
+	if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
 		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif /* CONFIG_CMDLINE */
 
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 6a9bc9c..35c6309 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -115,7 +115,7 @@
 }
 #endif
 
-void smp_message_recv(int msg, struct pt_regs *regs)
+void smp_message_recv(int msg)
 {
 	switch(msg) {
 	case PPC_MSG_CALL_FUNCTION:
@@ -127,11 +127,11 @@
 		break;
 	case PPC_MSG_DEBUGGER_BREAK:
 		if (crash_ipi_function_ptr) {
-			crash_ipi_function_ptr(regs);
+			crash_ipi_function_ptr(get_irq_regs());
 			break;
 		}
 #ifdef CONFIG_DEBUGGER
-		debugger_ipi(regs);
+		debugger_ipi(get_irq_regs());
 		break;
 #endif /* CONFIG_DEBUGGER */
 		/* FALLTHROUGH */
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 85b9244..5b59bc1 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -51,6 +51,7 @@
 #include <linux/rtc.h>
 #include <linux/jiffies.h>
 #include <linux/posix-timers.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -643,6 +644,7 @@
  */
 void timer_interrupt(struct pt_regs * regs)
 {
+	struct pt_regs *old_regs;
 	int next_dec;
 	int cpu = smp_processor_id();
 	unsigned long ticks;
@@ -653,9 +655,10 @@
 		do_IRQ(regs);
 #endif
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 	calculate_steal_time();
 
 #ifdef CONFIG_PPC_ISERIES
@@ -703,7 +706,7 @@
 
 #ifdef CONFIG_PPC_ISERIES
 	if (hvlpevent_is_pending())
-		process_hvlpevents(regs);
+		process_hvlpevents();
 #endif
 
 #ifdef CONFIG_PPC64
@@ -715,6 +718,7 @@
 #endif
 
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 void wakeup_decrementer(void)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d9f10f2..5ed4c2c 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -900,14 +900,13 @@
 
 void altivec_unavailable_exception(struct pt_regs *regs)
 {
-#if !defined(CONFIG_ALTIVEC)
 	if (user_mode(regs)) {
 		/* A user program has executed an altivec instruction,
 		   but this kernel doesn't support altivec. */
 		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 		return;
 	}
-#endif
+
 	printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
 			"%lx at %lx\n", regs->trap, regs->nip);
 	die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 16fe027..d1c0758 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -307,11 +307,12 @@
 	       top_of_ram, total_ram);
 	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (top_of_ram - total_ram) >> 20);
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 #ifdef CONFIG_HIGHMEM
-	max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
-	max_zone_pfns[1] = top_of_ram >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT;
 #else
-	max_zone_pfns[0] = top_of_ram >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 #endif
 	free_area_init_nodes(max_zone_pfns);
 }
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 43c2720..9da01dc 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -617,9 +617,9 @@
 
 void __init paging_init(void)
 {
-	unsigned long max_zone_pfns[MAX_NR_ZONES] = {
-				lmb_end_of_DRAM() >> PAGE_SHIFT
-	};
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] = lmb_end_of_DRAM() >> PAGE_SHIFT;
 	free_area_init_nodes(max_zone_pfns);
 }
 
diff --git a/arch/powerpc/platforms/82xx/mpc82xx.c b/arch/powerpc/platforms/82xx/mpc82xx.c
index 89d702d..0f5b30d 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx.c
@@ -11,7 +11,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index 4276f08..bb9acbb 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -12,8 +12,6 @@
  * option) any later version.
  */
 
-
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -384,8 +382,7 @@
 };
 
 static void
-m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc,
-		    struct pt_regs *regs)
+m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned long stat, mask, pend;
 	int bit;
@@ -398,7 +395,7 @@
 			break;
 		for (bit = 0; pend != 0; ++bit, pend <<= 1) {
 			if (pend & 0x80000000)
-				__do_IRQ(pci_int_base + bit, regs);
+				__do_IRQ(pci_int_base + bit);
 		}
 	}
 }
diff --git a/arch/powerpc/platforms/82xx/pq2ads.h b/arch/powerpc/platforms/82xx/pq2ads.h
index a734821..fb2f92b 100644
--- a/arch/powerpc/platforms/82xx/pq2ads.h
+++ b/arch/powerpc/platforms/82xx/pq2ads.h
@@ -22,8 +22,6 @@
 #ifndef __MACH_ADS8260_DEFS
 #define __MACH_ADS8260_DEFS
 
-#include <linux/config.h>
-
 #include <asm/ppcboot.h>
 
 /* For our show_cpuinfo hooks. */
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 0975e94..7edb6b4 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -32,6 +32,13 @@
 	  Be aware that PCI initialization is the bootloader's
 	  responsiblilty.
 
+config MPC8360E_PB
+	bool "Freescale MPC8360E PB"
+	select DEFAULT_UIMAGE
+	select QUICC_ENGINE
+	help
+	  This option enables support for the MPC836x EMDS Processor Board.
+
 endchoice
 
 config PPC_MPC832x
@@ -46,4 +53,10 @@
 	select PPC_INDIRECT_PCI
 	default y if MPC834x_SYS || MPC834x_ITX
 
+config PPC_MPC836x
+	bool
+	select PPC_UDBG_16550
+	select PPC_INDIRECT_PCI
+	default y if MPC8360E_PB
+
 endmenu
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 9387a11..f1aa7e2 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -5,3 +5,5 @@
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_MPC834x_SYS)	+= mpc834x_sys.o
 obj-$(CONFIG_MPC834x_ITX)	+= mpc834x_itx.o
+obj-$(CONFIG_MPC8360E_PB)	+= mpc8360e_pb.o
+obj-$(CONFIG_MPC832x_MDS)	+= mpc832x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
index c019190..1a523c8 100644
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
@@ -30,6 +30,7 @@
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
 
+#include <asm/of_device.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
@@ -141,6 +142,24 @@
 #endif
 }
 
+static int __init mpc8360_declare_of_platform_devices(void)
+{
+	struct device_node *np;
+
+	for (np = NULL; (np = of_find_compatible_node(np, "network",
+					"ucc_geth")) != NULL;) {
+		int ucc_num;
+		char bus_id[BUS_ID_SIZE];
+
+		ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
+		snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
+		of_platform_device_create(np, bus_id, NULL);
+	}
+
+	return 0;
+}
+device_initcall(mpc8360_declare_of_platform_devices);
+
 void __init mpc8360_sys_init_IRQ(void)
 {
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 28070e7..d3e669d 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -66,13 +66,12 @@
 
 #ifdef CONFIG_CPM2
 
-static void cpm2_cascade(unsigned int irq, struct irq_desc *desc,
-			 struct pt_regs *regs)
+static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
 	int cascade_irq;
 
-	while ((cascade_irq = cpm2_get_irq(regs)) >= 0) {
-		generic_handle_irq(cascade_irq, regs);
+	while ((cascade_irq = cpm2_get_irq()) >= 0) {
+		generic_handle_irq(cascade_irq);
 	}
 	desc->chip->eoi(irq);
 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 193a5d7..953cd5d 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -132,13 +132,12 @@
 
 #ifdef CONFIG_PPC_I8259
 #warning The i8259 PIC support is currently broken
-static void mpc85xx_8259_cascade(unsigned int irq, struct
-		irq_desc *desc, struct pt_regs *regs)
+static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int cascade_irq = i8259_irq(regs);
+	unsigned int cascade_irq = i8259_irq();
 
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 
 	desc->chip->eoi(irq);
 }
@@ -150,8 +149,10 @@
 	struct mpic *mpic;
 	struct resource r;
 	struct device_node *np = NULL;
+#ifdef CONFIG_PPC_I8259
 	struct device_node *cascade_node = NULL;
 	int cascade_irq;
+#endif
 
 	np = of_find_node_by_type(np, "open-pic");
 
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index b637e81..1a1c226 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -53,12 +53,11 @@
 
 
 #ifdef CONFIG_PCI
-static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
-				 struct pt_regs *regs)
+static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int cascade_irq = i8259_irq(regs);
+	unsigned int cascade_irq = i8259_irq();
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	desc->chip->eoi(irq);
 }
 #endif	/* CONFIG_PCI */
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 0c8c7b6..3e430b4 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -16,11 +16,6 @@
 	bool
 	default n
 
-config SPUFS_MMAP
-	bool
-	depends on SPU_FS && SPARSEMEM
-	default y
-
 config CBE_RAS
 	bool "RAS features for bare metal Cell BE"
 	default y
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 6cc59e0..a914c12 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -98,10 +98,9 @@
 {
 }
 
-static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc,
-			    struct pt_regs *regs)
+static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct cbe_iic_regs *node_iic = desc->handler_data;
+	struct cbe_iic_regs __iomem *node_iic = (void __iomem *)desc->handler_data;
 	unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
 	unsigned long bits, ack;
 	int cascade;
@@ -121,7 +120,7 @@
 					irq_linear_revmap(iic_host,
 							  base | cascade);
 				if (cirq != NO_IRQ)
-					generic_handle_irq(cirq, regs);
+					generic_handle_irq(cirq);
 			}
 		/* post-ack level interrupts */
 		ack = bits & ~IIC_ISR_EDGE_MASK;
@@ -140,7 +139,7 @@
 };
 
 /* Get an IRQ number from the pending state register of the IIC */
-static unsigned int iic_get_irq(struct pt_regs *regs)
+static unsigned int iic_get_irq(void)
 {
 	struct cbe_iic_pending_bits pending;
 	struct iic *iic;
@@ -190,11 +189,11 @@
 EXPORT_SYMBOL_GPL(iic_get_irq_host);
 
 
-static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t iic_ipi_action(int irq, void *dev_id)
 {
 	int ipi = (int)(long)dev_id;
 
-	smp_message_recv(ipi, regs);
+	smp_message_recv(ipi);
 
 	return IRQ_HANDLED;
 }
@@ -320,7 +319,7 @@
 	struct device_node *dn;
 	struct resource r0, r1;
 	unsigned int node, cascade, found = 0;
-	struct cbe_iic_regs *node_iic;
+	struct cbe_iic_regs __iomem *node_iic;
 	const u32 *np;
 
 	for (dn = NULL;
@@ -357,7 +356,11 @@
 		cascade = irq_create_mapping(iic_host, cascade);
 		if (cascade == NO_IRQ)
 			continue;
-		set_irq_data(cascade, node_iic);
+		/*
+		 * irq_data is a generic pointer that gets passed back
+		 * to us later, so the forced cast is fine.
+		 */
+		set_irq_data(cascade, (void __force *)node_iic);
 		set_irq_chained_handler(cascade , iic_ioexc_cascade);
 		out_be64(&node_iic->iic_ir,
 			 (1 << 12)		/* priority */ |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index d2b20eb..aca4c3d 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -345,8 +345,8 @@
 
 	/* node 0 */
 	iommu = &cell_iommus[0];
-	iommu->mapped_base = ioremap(0x20000511000, 0x1000);
-	iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000);
+	iommu->mapped_base = ioremap(0x20000511000ul, 0x1000);
+	iommu->mapped_mmio_base = ioremap(0x20000510000ul, 0x1000);
 
 	enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
@@ -358,8 +358,8 @@
 
 	/* node 1 */
 	iommu = &cell_iommus[1];
-	iommu->mapped_base = ioremap(0x30000511000, 0x1000);
-	iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000);
+	iommu->mapped_base = ioremap(0x30000511000ul, 0x1000);
+	iommu->mapped_mmio_base = ioremap(0x30000510000ul, 0x1000);
 
 	enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 608b1eb..21a9ebd 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -213,8 +213,7 @@
 	.xlate = spider_host_xlate,
 };
 
-static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc,
-			       struct pt_regs *regs)
+static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
 	struct spider_pic *pic = desc->handler_data;
 	unsigned int cs, virq;
@@ -225,7 +224,7 @@
 	else
 		virq = irq_linear_revmap(pic->host, cs);
 	if (virq != NO_IRQ)
-		generic_handle_irq(virq, regs);
+		generic_handle_irq(virq);
 	desc->chip->eoi(irq);
 }
 
@@ -244,7 +243,6 @@
 	int imaplen, intsize, unit;
 	struct device_node *iic;
 
-#if 0 /* Enable that when we have a way to retreive the node as well */
 	/* First, we check wether we have a real "interrupts" in the device
 	 * tree in case the device-tree is ever fixed
 	 */
@@ -252,9 +250,8 @@
 	if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) {
 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 					     oirq.size);
-		goto bail;
+		return virq;
 	}
-#endif
 
 	/* Now do the horrible hacks */
 	tmp = get_property(pic->of_node, "#interrupt-cells", NULL);
@@ -369,7 +366,7 @@
 		} else if (device_is_compatible(dn, "sti,platform-spider-pic")
 			   && (chip < 2)) {
 			static long hard_coded_pics[] =
-				{ 0x24000008000, 0x34000008000 };
+				{ 0x24000008000ul, 0x34000008000ul};
 			r.start = hard_coded_pics[chip];
 		} else
 			continue;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index f786803..d0fb959 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -25,11 +25,13 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
 
+#include <asm/firmware.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <linux/mutex.h>
@@ -46,21 +48,21 @@
 static int __spu_trap_invalid_dma(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	force_sig(SIGBUS, /* info, */ current);
+	spu->dma_callback(spu, SPE_EVENT_INVALID_DMA);
 	return 0;
 }
 
 static int __spu_trap_dma_align(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	force_sig(SIGBUS, /* info, */ current);
+	spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT);
 	return 0;
 }
 
 static int __spu_trap_error(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	force_sig(SIGILL, /* info, */ current);
+	spu->dma_callback(spu, SPE_EVENT_SPE_ERROR);
 	return 0;
 }
 
@@ -145,7 +147,7 @@
 }
 
 static irqreturn_t
-spu_irq_class_0(int irq, void *data, struct pt_regs *regs)
+spu_irq_class_0(int irq, void *data)
 {
 	struct spu *spu;
 
@@ -184,7 +186,7 @@
 EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);
 
 static irqreturn_t
-spu_irq_class_1(int irq, void *data, struct pt_regs *regs)
+spu_irq_class_1(int irq, void *data)
 {
 	struct spu *spu;
 	unsigned long stat, mask, dar, dsisr;
@@ -222,7 +224,7 @@
 EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom);
 
 static irqreturn_t
-spu_irq_class_2(int irq, void *data, struct pt_regs *regs)
+spu_irq_class_2(int irq, void *data)
 {
 	struct spu *spu;
 	unsigned long stat;
@@ -317,7 +319,7 @@
 		free_irq(spu->irqs[2], spu);
 }
 
-static LIST_HEAD(spu_list);
+static struct list_head spu_list[MAX_NUMNODES];
 static DEFINE_MUTEX(spu_mutex);
 
 static void spu_init_channels(struct spu *spu)
@@ -354,32 +356,42 @@
 	}
 }
 
-struct spu *spu_alloc(void)
+struct spu *spu_alloc_node(int node)
 {
-	struct spu *spu;
+	struct spu *spu = NULL;
 
 	mutex_lock(&spu_mutex);
-	if (!list_empty(&spu_list)) {
-		spu = list_entry(spu_list.next, struct spu, list);
+	if (!list_empty(&spu_list[node])) {
+		spu = list_entry(spu_list[node].next, struct spu, list);
 		list_del_init(&spu->list);
-		pr_debug("Got SPU %x %d\n", spu->isrc, spu->number);
-	} else {
-		pr_debug("No SPU left\n");
-		spu = NULL;
+		pr_debug("Got SPU %x %d %d\n",
+			 spu->isrc, spu->number, spu->node);
+		spu_init_channels(spu);
 	}
 	mutex_unlock(&spu_mutex);
 
-	if (spu)
-		spu_init_channels(spu);
+	return spu;
+}
+EXPORT_SYMBOL_GPL(spu_alloc_node);
+
+struct spu *spu_alloc(void)
+{
+	struct spu *spu = NULL;
+	int node;
+
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		spu = spu_alloc_node(node);
+		if (spu)
+			break;
+	}
 
 	return spu;
 }
-EXPORT_SYMBOL_GPL(spu_alloc);
 
 void spu_free(struct spu *spu)
 {
 	mutex_lock(&spu_mutex);
-	list_add_tail(&spu->list, &spu_list);
+	list_add_tail(&spu->list, &spu_list[spu->node]);
 	mutex_unlock(&spu_mutex);
 }
 EXPORT_SYMBOL_GPL(spu_free);
@@ -566,7 +578,7 @@
 }
 
 /* This function shall be abstracted for HV platforms */
-static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np)
 {
 	unsigned int isrc;
 	const u32 *tmp;
@@ -590,7 +602,7 @@
 	return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
 }
 
-static int __init spu_map_device(struct spu *spu, struct device_node *node)
+static int __init spu_map_device_old(struct spu *spu, struct device_node *node)
 {
 	const char *prop;
 	int ret;
@@ -635,6 +647,88 @@
 	return ret;
 }
 
+static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+{
+	struct of_irq oirq;
+	int ret;
+	int i;
+
+	for (i=0; i < 3; i++) {
+		ret = of_irq_map_one(np, i, &oirq);
+		if (ret)
+			goto err;
+
+		ret = -EINVAL;
+		spu->irqs[i] = irq_create_of_mapping(oirq.controller,
+					oirq.specifier, oirq.size);
+		if (spu->irqs[i] == NO_IRQ)
+			goto err;
+	}
+	return 0;
+
+err:
+	pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name);
+	for (; i >= 0; i--) {
+		if (spu->irqs[i] != NO_IRQ)
+			irq_dispose_mapping(spu->irqs[i]);
+	}
+	return ret;
+}
+
+static int spu_map_resource(struct device_node *node, int nr,
+		void __iomem** virt, unsigned long *phys)
+{
+	struct resource resource = { };
+	int ret;
+
+	ret = of_address_to_resource(node, 0, &resource);
+	if (ret)
+		goto out;
+
+	if (phys)
+		*phys = resource.start;
+	*virt = ioremap(resource.start, resource.end - resource.start);
+	if (!*virt)
+		ret = -EINVAL;
+
+out:
+	return ret;
+}
+
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
+{
+	int ret = -ENODEV;
+	spu->name = get_property(node, "name", NULL);
+	if (!spu->name)
+		goto out;
+
+	ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
+					&spu->local_store_phys);
+	if (ret)
+		goto out;
+	ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
+					&spu->problem_phys);
+	if (ret)
+		goto out_unmap;
+	ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
+					NULL);
+	if (ret)
+		goto out_unmap;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1,
+					NULL);
+	if (ret)
+		goto out_unmap;
+	return 0;
+
+out_unmap:
+	spu_unmap(spu);
+out:
+	pr_debug("failed to map spe %s: %d\n", spu->name, ret);
+	return ret;
+}
+
 struct sysdev_class spu_sysdev_class = {
 	set_kset_name("spu")
 };
@@ -687,16 +781,28 @@
 	if (!spu)
 		goto out;
 
-	ret = spu_map_device(spu, spe);
-	if (ret)
-		goto out_free;
-
 	spu->node = find_spu_node_id(spe);
+	if (spu->node >= MAX_NUMNODES) {
+		printk(KERN_WARNING "SPE %s on node %d ignored,"
+		       " node number too big\n", spe->full_name, spu->node);
+		printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n");
+		return -ENODEV;
+	}
 	spu->nid = of_node_to_nid(spe);
 	if (spu->nid == -1)
 		spu->nid = 0;
+
+	ret = spu_map_device(spu, spe);
+	/* try old method */
+	if (ret)
+		ret = spu_map_device_old(spu, spe);
+	if (ret)
+		goto out_free;
+
 	ret = spu_map_interrupts(spu, spe);
 	if (ret)
+		ret = spu_map_interrupts_old(spu, spe);
+	if (ret)
 		goto out_unmap;
 	spin_lock_init(&spu->register_lock);
 	spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
@@ -706,13 +812,13 @@
 	spu->number = number++;
 	ret = spu_request_irqs(spu);
 	if (ret)
-		goto out_unmap;
+		goto out_unlock;
 
 	ret = spu_create_sysdev(spu);
 	if (ret)
 		goto out_free_irqs;
 
-	list_add(&spu->list, &spu_list);
+	list_add(&spu->list, &spu_list[spu->node]);
 	mutex_unlock(&spu_mutex);
 
 	pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
@@ -722,9 +828,9 @@
 
 out_free_irqs:
 	spu_free_irqs(spu);
-
-out_unmap:
+out_unlock:
 	mutex_unlock(&spu_mutex);
+out_unmap:
 	spu_unmap(spu);
 out_free:
 	kfree(spu);
@@ -745,9 +851,13 @@
 static void cleanup_spu_base(void)
 {
 	struct spu *spu, *tmp;
+	int node;
+
 	mutex_lock(&spu_mutex);
-	list_for_each_entry_safe(spu, tmp, &spu_list, list)
-		destroy_spu(spu);
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		list_for_each_entry_safe(spu, tmp, &spu_list[node], list)
+			destroy_spu(spu);
+	}
 	mutex_unlock(&spu_mutex);
 	sysdev_class_unregister(&spu_sysdev_class);
 }
@@ -756,13 +866,16 @@
 static int __init init_spu_base(void)
 {
 	struct device_node *node;
-	int ret;
+	int i, ret;
 
 	/* create sysdev class for spus */
 	ret = sysdev_class_register(&spu_sysdev_class);
 	if (ret)
 		return ret;
 
+	for (i = 0; i < MAX_NUMNODES; i++)
+		INIT_LIST_HEAD(&spu_list[i]);
+
 	ret = -ENODEV;
 	for (node = of_find_node_by_type(NULL, "spe");
 			node; node = of_find_node_by_type(node, "spe")) {
@@ -774,18 +887,6 @@
 			break;
 		}
 	}
-	/* in some old firmware versions, the spe is called 'spc', so we
-	   look for that as well */
-	for (node = of_find_node_by_type(NULL, "spc");
-			node; node = of_find_node_by_type(node, "spc")) {
-		ret = create_spu(node);
-		if (ret) {
-			printk(KERN_WARNING "%s: Error initializing %s\n",
-				__FUNCTION__, node->name);
-			cleanup_spu_base();
-			break;
-		}
-	}
 	return ret;
 }
 module_init(init_spu_base);
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index bb5dc63..ecdfbb3 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -2,7 +2,7 @@
 
 obj-$(CONFIG_SPU_FS) += spufs.o
 spufs-y += inode.o file.o context.o syscalls.o
-spufs-y += sched.o backing_ops.o hw_ops.o run.o
+spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
 
 # Rules to build switch.o with the help of SPU tool chain
 SPU_CROSS	:= spu-
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 36439c5..034cf6a 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -27,7 +27,7 @@
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
-struct spu_context *alloc_spu_context(void)
+struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
@@ -51,6 +51,8 @@
 	ctx->state = SPU_STATE_SAVED;
 	ctx->ops = &spu_backing_ops;
 	ctx->owner = get_task_mm(current);
+	if (gang)
+		spu_gang_add_ctx(gang, ctx);
 	goto out;
 out_free:
 	kfree(ctx);
@@ -67,6 +69,8 @@
 	spu_deactivate(ctx);
 	up_write(&ctx->state_sema);
 	spu_fini_csa(&ctx->csa);
+	if (ctx->gang)
+		spu_gang_remove_ctx(ctx->gang, ctx);
 	kfree(ctx);
 }
 
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 51fd197..0de8e11 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -36,6 +36,8 @@
 
 #include "spufs.h"
 
+#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
+
 
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
@@ -88,7 +90,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_SPUFS_MMAP
 static struct page *
 spufs_mem_mmap_nopage(struct vm_area_struct *vma,
 		      unsigned long address, int *type)
@@ -101,12 +102,16 @@
 
 	spu_acquire(ctx);
 
-	if (ctx->state == SPU_STATE_SAVED)
+	if (ctx->state == SPU_STATE_SAVED) {
+		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+					& ~(_PAGE_NO_CACHE | _PAGE_GUARDED));
 		page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
-	else
+	} else {
+		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+					| _PAGE_NO_CACHE | _PAGE_GUARDED);
 		page = pfn_to_page((ctx->spu->local_store_phys + offset)
 				   >> PAGE_SHIFT);
-
+	}
 	spu_release(ctx);
 
 	if (type)
@@ -133,22 +138,19 @@
 	vma->vm_ops = &spufs_mem_mmap_vmops;
 	return 0;
 }
-#endif
 
 static struct file_operations spufs_mem_fops = {
 	.open	 = spufs_mem_open,
 	.read    = spufs_mem_read,
 	.write   = spufs_mem_write,
 	.llseek  = generic_file_llseek,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap    = spufs_mem_mmap,
-#endif
 };
 
-#ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
 				    unsigned long address,
-				    int *type, unsigned long ps_offs)
+				    int *type, unsigned long ps_offs,
+				    unsigned long ps_size)
 {
 	struct page *page = NOPAGE_SIGBUS;
 	int fault_type = VM_FAULT_SIGBUS;
@@ -158,7 +160,7 @@
 	int ret;
 
 	offset += vma->vm_pgoff << PAGE_SHIFT;
-	if (offset >= 0x4000)
+	if (offset >= ps_size)
 		goto out;
 
 	ret = spu_acquire_runnable(ctx);
@@ -179,10 +181,11 @@
 	return page;
 }
 
+#if SPUFS_MMAP_4K
 static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x4000);
+	return spufs_ps_nopage(vma, address, type, 0x4000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_cntl_mmap_vmops = {
@@ -191,17 +194,12 @@
 
 /*
  * mmap support for problem state control area [0x4000 - 0x4fff].
- * Mapping this area requires that the application have CAP_SYS_RAWIO,
- * as these registers require special care when read/writing.
  */
 static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -209,7 +207,30 @@
 	vma->vm_ops = &spufs_cntl_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_cntl_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
+
+static u64 spufs_cntl_get(void *data)
+{
+	struct spu_context *ctx = data;
+	u64 val;
+
+	spu_acquire(ctx);
+	val = ctx->ops->status_read(ctx);
+	spu_release(ctx);
+
+	return val;
+}
+
+static void spufs_cntl_set(void *data, u64 val)
+{
+	struct spu_context *ctx = data;
+
+	spu_acquire(ctx);
+	ctx->ops->runcntl_write(ctx, val);
+	spu_release(ctx);
+}
 
 static int spufs_cntl_open(struct inode *inode, struct file *file)
 {
@@ -219,32 +240,16 @@
 	file->private_data = ctx;
 	file->f_mapping = inode->i_mapping;
 	ctx->cntl = inode->i_mapping;
-	return 0;
-}
-
-static ssize_t
-spufs_cntl_read(struct file *file, char __user *buffer,
-		size_t size, loff_t *pos)
-{
-	/* FIXME: read from spu status */
-	return -EINVAL;
-}
-
-static ssize_t
-spufs_cntl_write(struct file *file, const char __user *buffer,
-		 size_t size, loff_t *pos)
-{
-	/* FIXME: write to runctl bit */
-	return -EINVAL;
+	return simple_attr_open(inode, file, spufs_cntl_get,
+					spufs_cntl_set, "0x%08lx");
 }
 
 static struct file_operations spufs_cntl_fops = {
 	.open = spufs_cntl_open,
-	.read = spufs_cntl_read,
-	.write = spufs_cntl_write,
-#ifdef CONFIG_SPUFS_MMAP
+	.release = simple_attr_close,
+	.read = simple_attr_read,
+	.write = simple_attr_write,
 	.mmap = spufs_cntl_mmap,
-#endif
 };
 
 static int
@@ -356,27 +361,54 @@
 	return nonseekable_open(inode, file);
 }
 
+/*
+ * Read as many bytes from the mailbox as possible, until
+ * one of the conditions becomes true:
+ *
+ * - no more data available in the mailbox
+ * - end of the user provided buffer
+ * - end of the mapped area
+ */
 static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	u32 mbox_data;
-	int ret;
+	u32 mbox_data, __user *udata;
+	ssize_t count;
 
 	if (len < 4)
 		return -EINVAL;
 
-	spu_acquire(ctx);
-	ret = ctx->ops->mbox_read(ctx, &mbox_data);
-	spu_release(ctx);
-
-	if (!ret)
-		return -EAGAIN;
-
-	if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
+	if (!access_ok(VERIFY_WRITE, buf, len))
 		return -EFAULT;
 
-	return 4;
+	udata = (void __user *)buf;
+
+	spu_acquire(ctx);
+	for (count = 0; count <= len; count += 4, udata++) {
+		int ret;
+		ret = ctx->ops->mbox_read(ctx, &mbox_data);
+		if (ret == 0)
+			break;
+
+		/*
+		 * at the end of the mapped area, we can fault
+		 * but still need to return the data we have
+		 * read successfully so far.
+		 */
+		ret = __put_user(mbox_data, udata);
+		if (ret) {
+			if (!count)
+				count = -EFAULT;
+			break;
+		}
+	}
+	spu_release(ctx);
+
+	if (!count)
+		count = -EAGAIN;
+
+	return count;
 }
 
 static struct file_operations spufs_mbox_fops = {
@@ -432,36 +464,70 @@
 	kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
 }
 
+/*
+ * Read as many bytes from the interrupt mailbox as possible, until
+ * one of the conditions becomes true:
+ *
+ * - no more data available in the mailbox
+ * - end of the user provided buffer
+ * - end of the mapped area
+ *
+ * If the file is opened without O_NONBLOCK, we wait here until
+ * any data is available, but return when we have been able to
+ * read something.
+ */
 static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	u32 ibox_data;
-	ssize_t ret;
+	u32 ibox_data, __user *udata;
+	ssize_t count;
 
 	if (len < 4)
 		return -EINVAL;
 
+	if (!access_ok(VERIFY_WRITE, buf, len))
+		return -EFAULT;
+
+	udata = (void __user *)buf;
+
 	spu_acquire(ctx);
 
-	ret = 0;
+	/* wait only for the first element */
+	count = 0;
 	if (file->f_flags & O_NONBLOCK) {
 		if (!spu_ibox_read(ctx, &ibox_data))
-			ret = -EAGAIN;
+			count = -EAGAIN;
 	} else {
-		ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
+		count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
+	}
+	if (count)
+		goto out;
+
+	/* if we can't write at all, return -EFAULT */
+	count = __put_user(ibox_data, udata);
+	if (count)
+		goto out;
+
+	for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
+		int ret;
+		ret = ctx->ops->ibox_read(ctx, &ibox_data);
+		if (ret == 0)
+			break;
+		/*
+		 * at the end of the mapped area, we can fault
+		 * but still need to return the data we have
+		 * read successfully so far.
+		 */
+		ret = __put_user(ibox_data, udata);
+		if (ret)
+			break;
 	}
 
+out:
 	spu_release(ctx);
 
-	if (ret)
-		return ret;
-
-	ret = 4;
-	if (copy_to_user(buf, &ibox_data, sizeof ibox_data))
-		ret = -EFAULT;
-
-	return ret;
+	return count;
 }
 
 static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
@@ -534,32 +600,67 @@
 	kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
 }
 
+/*
+ * Write as many bytes to the interrupt mailbox as possible, until
+ * one of the conditions becomes true:
+ *
+ * - the mailbox is full
+ * - end of the user provided buffer
+ * - end of the mapped area
+ *
+ * If the file is opened without O_NONBLOCK, we wait here until
+ * space is availabyl, but return when we have been able to
+ * write something.
+ */
 static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	u32 wbox_data;
-	int ret;
+	u32 wbox_data, __user *udata;
+	ssize_t count;
 
 	if (len < 4)
 		return -EINVAL;
 
-	if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
+	udata = (void __user *)buf;
+	if (!access_ok(VERIFY_READ, buf, len))
+		return -EFAULT;
+
+	if (__get_user(wbox_data, udata))
 		return -EFAULT;
 
 	spu_acquire(ctx);
 
-	ret = 0;
+	/*
+	 * make sure we can at least write one element, by waiting
+	 * in case of !O_NONBLOCK
+	 */
+	count = 0;
 	if (file->f_flags & O_NONBLOCK) {
 		if (!spu_wbox_write(ctx, wbox_data))
-			ret = -EAGAIN;
+			count = -EAGAIN;
 	} else {
-		ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
+		count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
 	}
 
-	spu_release(ctx);
+	if (count)
+		goto out;
 
-	return ret ? ret : sizeof wbox_data;
+	/* write aѕ much as possible */
+	for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
+		int ret;
+		ret = __get_user(wbox_data, udata);
+		if (ret)
+			break;
+
+		ret = spu_wbox_write(ctx, wbox_data);
+		if (ret == 0)
+			break;
+	}
+
+out:
+	spu_release(ctx);
+	return count;
 }
 
 static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
@@ -657,11 +758,19 @@
 	return 4;
 }
 
-#ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
 					      unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x14000);
+#if PAGE_SIZE == 0x1000
+	return spufs_ps_nopage(vma, address, type, 0x14000, 0x1000);
+#elif PAGE_SIZE == 0x10000
+	/* For 64k pages, both signal1 and signal2 can be used to mmap the whole
+	 * signal 1 and 2 area
+	 */
+	return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
+#else
+#error unsupported page size
+#endif
 }
 
 static struct vm_operations_struct spufs_signal1_mmap_vmops = {
@@ -680,15 +789,12 @@
 	vma->vm_ops = &spufs_signal1_mmap_vmops;
 	return 0;
 }
-#endif
 
 static struct file_operations spufs_signal1_fops = {
 	.open = spufs_signal1_open,
 	.read = spufs_signal1_read,
 	.write = spufs_signal1_write,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap = spufs_signal1_mmap,
-#endif
 };
 
 static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -743,11 +849,20 @@
 	return 4;
 }
 
-#ifdef CONFIG_SPUFS_MMAP
+#if SPUFS_MMAP_4K
 static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
 					      unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x1c000);
+#if PAGE_SIZE == 0x1000
+	return spufs_ps_nopage(vma, address, type, 0x1c000, 0x1000);
+#elif PAGE_SIZE == 0x10000
+	/* For 64k pages, both signal1 and signal2 can be used to mmap the whole
+	 * signal 1 and 2 area
+	 */
+	return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
+#else
+#error unsupported page size
+#endif
 }
 
 static struct vm_operations_struct spufs_signal2_mmap_vmops = {
@@ -767,15 +882,15 @@
 	vma->vm_ops = &spufs_signal2_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_signal2_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static struct file_operations spufs_signal2_fops = {
 	.open = spufs_signal2_open,
 	.read = spufs_signal2_read,
 	.write = spufs_signal2_write,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap = spufs_signal2_mmap,
-#endif
 };
 
 static void spufs_signal1_type_set(void *data, u64 val)
@@ -824,11 +939,11 @@
 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
 					spufs_signal2_type_set, "%llu");
 
-#ifdef CONFIG_SPUFS_MMAP
+#if SPUFS_MMAP_4K
 static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x0000);
+	return spufs_ps_nopage(vma, address, type, 0x0000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_mss_mmap_vmops = {
@@ -837,17 +952,12 @@
 
 /*
  * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
- * Mapping this area requires that the application have CAP_SYS_RAWIO,
- * as these registers require special care when read/writing.
  */
 static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -855,7 +965,9 @@
 	vma->vm_ops = &spufs_mss_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_mss_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static int spufs_mss_open(struct inode *inode, struct file *file)
 {
@@ -867,17 +979,54 @@
 
 static struct file_operations spufs_mss_fops = {
 	.open	 = spufs_mss_open,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap	 = spufs_mss_mmap,
-#endif
+};
+
+static struct page *spufs_psmap_mmap_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x0000, 0x20000);
+}
+
+static struct vm_operations_struct spufs_psmap_mmap_vmops = {
+	.nopage = spufs_psmap_mmap_nopage,
+};
+
+/*
+ * mmap support for full problem state area [0x00000 - 0x1ffff].
+ */
+static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
+
+	vma->vm_ops = &spufs_psmap_mmap_vmops;
+	return 0;
+}
+
+static int spufs_psmap_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+
+	file->private_data = i->i_ctx;
+	return nonseekable_open(inode, file);
+}
+
+static struct file_operations spufs_psmap_fops = {
+	.open	 = spufs_psmap_open,
+	.mmap	 = spufs_psmap_mmap,
 };
 
 
-#ifdef CONFIG_SPUFS_MMAP
+#if SPUFS_MMAP_4K
 static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
-	return spufs_ps_nopage(vma, address, type, 0x3000);
+	return spufs_ps_nopage(vma, address, type, 0x3000, 0x1000);
 }
 
 static struct vm_operations_struct spufs_mfc_mmap_vmops = {
@@ -886,17 +1035,12 @@
 
 /*
  * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
- * Mapping this area requires that the application have CAP_SYS_RAWIO,
- * as these registers require special care when read/writing.
  */
 static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	if (!(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
 				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -904,7 +1048,9 @@
 	vma->vm_ops = &spufs_mfc_mmap_vmops;
 	return 0;
 }
-#endif
+#else /* SPUFS_MMAP_4K */
+#define spufs_mfc_mmap NULL
+#endif /* !SPUFS_MMAP_4K */
 
 static int spufs_mfc_open(struct inode *inode, struct file *file)
 {
@@ -1194,9 +1340,7 @@
 	.flush	 = spufs_mfc_flush,
 	.fsync	 = spufs_mfc_fsync,
 	.fasync	 = spufs_mfc_fasync,
-#ifdef CONFIG_SPUFS_MMAP
 	.mmap	 = spufs_mfc_mmap,
-#endif
 };
 
 static void spufs_npc_set(void *data, u64 val)
@@ -1344,6 +1488,21 @@
 }
 DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
 
+static u64 spufs_object_id_get(void *data)
+{
+	struct spu_context *ctx = data;
+	return ctx->object_id;
+}
+
+static void spufs_object_id_set(void *data, u64 id)
+{
+	struct spu_context *ctx = data;
+	ctx->object_id = id;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
+		spufs_object_id_set, "0x%llx\n");
+
 struct tree_descr spufs_dir_contents[] = {
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "regs", &spufs_regs_fops,  0666, },
@@ -1367,6 +1526,8 @@
 	{ "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
 	{ "event_mask", &spufs_event_mask_ops, 0666, },
 	{ "srr0", &spufs_srr0_ops, 0666, },
+	{ "psmap", &spufs_psmap_fops, 0666, },
 	{ "phys-id", &spufs_id_ops, 0666, },
+	{ "object-id", &spufs_object_id_ops, 0666, },
 	{},
 };
diff --git a/arch/powerpc/platforms/cell/spufs/gang.c b/arch/powerpc/platforms/cell/spufs/gang.c
new file mode 100644
index 0000000..212ea78
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/gang.c
@@ -0,0 +1,81 @@
+/*
+ * SPU file system
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "spufs.h"
+
+struct spu_gang *alloc_spu_gang(void)
+{
+	struct spu_gang *gang;
+
+	gang = kzalloc(sizeof *gang, GFP_KERNEL);
+	if (!gang)
+		goto out;
+
+	kref_init(&gang->kref);
+	mutex_init(&gang->mutex);
+	INIT_LIST_HEAD(&gang->list);
+
+out:
+	return gang;
+}
+
+static void destroy_spu_gang(struct kref *kref)
+{
+	struct spu_gang *gang;
+	gang = container_of(kref, struct spu_gang, kref);
+	WARN_ON(gang->contexts || !list_empty(&gang->list));
+	kfree(gang);
+}
+
+struct spu_gang *get_spu_gang(struct spu_gang *gang)
+{
+	kref_get(&gang->kref);
+	return gang;
+}
+
+int put_spu_gang(struct spu_gang *gang)
+{
+	return kref_put(&gang->kref, &destroy_spu_gang);
+}
+
+void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx)
+{
+	mutex_lock(&gang->mutex);
+	ctx->gang = get_spu_gang(gang);
+	list_add(&ctx->gang_list, &gang->list);
+	gang->contexts++;
+	mutex_unlock(&gang->mutex);
+}
+
+void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx)
+{
+	mutex_lock(&gang->mutex);
+	WARN_ON(ctx->gang != gang);
+	list_del_init(&ctx->gang_list);
+	gang->contexts--;
+	mutex_unlock(&gang->mutex);
+
+	put_spu_gang(gang);
+}
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 3950ddc..427d00a 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -50,6 +50,10 @@
 	ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL);
 	if (!ei)
 		return NULL;
+
+	ei->i_gang = NULL;
+	ei->i_ctx = NULL;
+
 	return &ei->vfs_inode;
 }
 
@@ -128,14 +132,19 @@
 static void
 spufs_delete_inode(struct inode *inode)
 {
-	if (SPUFS_I(inode)->i_ctx)
-		put_spu_context(SPUFS_I(inode)->i_ctx);
+	struct spufs_inode_info *ei = SPUFS_I(inode);
+
+	if (ei->i_ctx)
+		put_spu_context(ei->i_ctx);
+	if (ei->i_gang)
+		put_spu_gang(ei->i_gang);
 	clear_inode(inode);
 }
 
 static void spufs_prune_dir(struct dentry *dir)
 {
 	struct dentry *dentry, *tmp;
+
 	mutex_lock(&dir->d_inode->i_mutex);
 	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
 		spin_lock(&dcache_lock);
@@ -156,13 +165,13 @@
 	mutex_unlock(&dir->d_inode->i_mutex);
 }
 
-/* Caller must hold root->i_mutex */
-static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+/* Caller must hold parent->i_mutex */
+static int spufs_rmdir(struct inode *parent, struct dentry *dir)
 {
 	/* remove all entries */
-	spufs_prune_dir(dir_dentry);
+	spufs_prune_dir(dir);
 
-	return simple_rmdir(root, dir_dentry);
+	return simple_rmdir(parent, dir);
 }
 
 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
@@ -191,17 +200,17 @@
 static int spufs_dir_close(struct inode *inode, struct file *file)
 {
 	struct spu_context *ctx;
-	struct inode *dir;
-	struct dentry *dentry;
+	struct inode *parent;
+	struct dentry *dir;
 	int ret;
 
-	dentry = file->f_dentry;
-	dir = dentry->d_parent->d_inode;
-	ctx = SPUFS_I(dentry->d_inode)->i_ctx;
+	dir = file->f_dentry;
+	parent = dir->d_parent->d_inode;
+	ctx = SPUFS_I(dir->d_inode)->i_ctx;
 
-	mutex_lock(&dir->i_mutex);
-	ret = spufs_rmdir(dir, dentry);
-	mutex_unlock(&dir->i_mutex);
+	mutex_lock(&parent->i_mutex);
+	ret = spufs_rmdir(parent, dir);
+	mutex_unlock(&parent->i_mutex);
 	WARN_ON(ret);
 
 	/* We have to give up the mm_struct */
@@ -224,7 +233,8 @@
 };
 
 static int
-spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
+		int mode)
 {
 	int ret;
 	struct inode *inode;
@@ -239,11 +249,13 @@
 		inode->i_gid = dir->i_gid;
 		inode->i_mode &= S_ISGID;
 	}
-	ctx = alloc_spu_context();
+	ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */
 	SPUFS_I(inode)->i_ctx = ctx;
 	if (!ctx)
 		goto out_iput;
 
+	ctx->flags = flags;
+
 	inode->i_op = &spufs_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
@@ -289,24 +301,177 @@
 	return ret;
 }
 
+static int spufs_create_context(struct inode *inode,
+			struct dentry *dentry,
+			struct vfsmount *mnt, int flags, int mode)
+{
+	int ret;
+
+	ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
+	if (ret)
+		goto out_unlock;
+
+	/*
+	 * get references for dget and mntget, will be released
+	 * in error path of *_open().
+	 */
+	ret = spufs_context_open(dget(dentry), mntget(mnt));
+	if (ret < 0) {
+		WARN_ON(spufs_rmdir(inode, dentry));
+		mutex_unlock(&inode->i_mutex);
+		spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
+		goto out;
+	}
+
+out_unlock:
+	mutex_unlock(&inode->i_mutex);
+out:
+	dput(dentry);
+	return ret;
+}
+
+static int spufs_rmgang(struct inode *root, struct dentry *dir)
+{
+	/* FIXME: this fails if the dir is not empty,
+	          which causes a leak of gangs. */
+	return simple_rmdir(root, dir);
+}
+
+static int spufs_gang_close(struct inode *inode, struct file *file)
+{
+	struct inode *parent;
+	struct dentry *dir;
+	int ret;
+
+	dir = file->f_dentry;
+	parent = dir->d_parent->d_inode;
+
+	ret = spufs_rmgang(parent, dir);
+	WARN_ON(ret);
+
+	return dcache_dir_close(inode, file);
+}
+
+struct file_operations spufs_gang_fops = {
+	.open		= dcache_dir_open,
+	.release	= spufs_gang_close,
+	.llseek		= dcache_dir_lseek,
+	.read		= generic_read_dir,
+	.readdir	= dcache_readdir,
+	.fsync		= simple_sync_file,
+};
+
+static int
+spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int ret;
+	struct inode *inode;
+	struct spu_gang *gang;
+
+	ret = -ENOSPC;
+	inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
+	if (!inode)
+		goto out;
+
+	ret = 0;
+	if (dir->i_mode & S_ISGID) {
+		inode->i_gid = dir->i_gid;
+		inode->i_mode &= S_ISGID;
+	}
+	gang = alloc_spu_gang();
+	SPUFS_I(inode)->i_ctx = NULL;
+	SPUFS_I(inode)->i_gang = gang;
+	if (!gang)
+		goto out_iput;
+
+	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_fop = &simple_dir_operations;
+
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	dir->i_nlink++;
+	dentry->d_inode->i_nlink++;
+	return ret;
+
+out_iput:
+	iput(inode);
+out:
+	return ret;
+}
+
+static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
+{
+	int ret;
+	struct file *filp;
+
+	ret = get_unused_fd();
+	if (ret < 0) {
+		dput(dentry);
+		mntput(mnt);
+		goto out;
+	}
+
+	filp = dentry_open(dentry, mnt, O_RDONLY);
+	if (IS_ERR(filp)) {
+		put_unused_fd(ret);
+		ret = PTR_ERR(filp);
+		goto out;
+	}
+
+	filp->f_op = &spufs_gang_fops;
+	fd_install(ret, filp);
+out:
+	return ret;
+}
+
+static int spufs_create_gang(struct inode *inode,
+			struct dentry *dentry,
+			struct vfsmount *mnt, int mode)
+{
+	int ret;
+
+	ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
+	if (ret)
+		goto out;
+
+	/*
+	 * get references for dget and mntget, will be released
+	 * in error path of *_open().
+	 */
+	ret = spufs_gang_open(dget(dentry), mntget(mnt));
+	if (ret < 0)
+		WARN_ON(spufs_rmgang(inode, dentry));
+
+out:
+	mutex_unlock(&inode->i_mutex);
+	dput(dentry);
+	return ret;
+}
+
+
 static struct file_system_type spufs_type;
 
-long spufs_create_thread(struct nameidata *nd,
-			 unsigned int flags, mode_t mode)
+long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode)
 {
 	struct dentry *dentry;
 	int ret;
 
-	/* need to be at the root of spufs */
 	ret = -EINVAL;
-	if (nd->dentry->d_sb->s_type != &spufs_type ||
-	    nd->dentry != nd->dentry->d_sb->s_root)
+	/* check if we are on spufs */
+	if (nd->dentry->d_sb->s_type != &spufs_type)
 		goto out;
 
-	/* all flags are reserved */
-	if (flags)
+	/* don't accept undefined flags */
+	if (flags & (~SPU_CREATE_FLAG_ALL))
 		goto out;
 
+	/* only threads can be underneath a gang */
+	if (nd->dentry != nd->dentry->d_sb->s_root) {
+		if ((flags & SPU_CREATE_GANG) ||
+		    !SPUFS_I(nd->dentry->d_inode)->i_gang)
+			goto out;
+	}
+
 	dentry = lookup_create(nd, 1);
 	ret = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
@@ -317,22 +482,13 @@
 		goto out_dput;
 
 	mode &= ~current->fs->umask;
-	ret = spufs_mkdir(nd->dentry->d_inode, dentry, mode & S_IRWXUGO);
-	if (ret)
-		goto out_dput;
 
-	/*
-	 * get references for dget and mntget, will be released
-	 * in error path of *_open().
-	 */
-	ret = spufs_context_open(dget(dentry), mntget(nd->mnt));
-	if (ret < 0) {
-		WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry));
-		mutex_unlock(&nd->dentry->d_inode->i_mutex);
-		spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
-		dput(dentry);
-		goto out;
-	}
+	if (flags & SPU_CREATE_GANG)
+		return spufs_create_gang(nd->dentry->d_inode,
+					dentry, nd->mnt, mode);
+	else
+		return spufs_create_context(nd->dentry->d_inode,
+					dentry, nd->mnt, flags, mode);
 
 out_dput:
 	dput(dentry);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 483c8b7..63df8cf 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -14,6 +14,26 @@
 	wake_up_all(&ctx->stop_wq);
 }
 
+void spufs_dma_callback(struct spu *spu, int type)
+{
+	struct spu_context *ctx = spu->ctx;
+
+	if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
+		ctx->event_return |= type;
+		wake_up_all(&ctx->stop_wq);
+	} else {
+		switch (type) {
+		case SPE_EVENT_DMA_ALIGNMENT:
+		case SPE_EVENT_INVALID_DMA:
+			force_sig(SIGBUS, /* info, */ current);
+			break;
+		case SPE_EVENT_SPE_ERROR:
+			force_sig(SIGILL, /* info */ current);
+			break;
+		}
+	}
+}
+
 static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
 {
 	struct spu *spu;
@@ -28,8 +48,7 @@
 	return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
 }
 
-static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
-			       u32 * status)
+static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
 {
 	int ret;
 
@@ -72,7 +91,7 @@
 		       SPU_STATUS_STOPPED_BY_HALT)) {
 		return *status;
 	}
-	if ((ret = spu_run_init(ctx, npc, status)) != 0)
+	if ((ret = spu_run_init(ctx, npc)) != 0)
 		return ret;
 	return 0;
 }
@@ -177,46 +196,49 @@
 }
 
 long spufs_run_spu(struct file *file, struct spu_context *ctx,
-		   u32 * npc, u32 * status)
+		   u32 *npc, u32 *event)
 {
 	int ret;
+	u32 status;
 
 	if (down_interruptible(&ctx->run_sema))
 		return -ERESTARTSYS;
 
-	ret = spu_run_init(ctx, npc, status);
+	ctx->event_return = 0;
+	ret = spu_run_init(ctx, npc);
 	if (ret)
 		goto out;
 
 	do {
-		ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
+		ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
 		if (unlikely(ret))
 			break;
-		if ((*status & SPU_STATUS_STOPPED_BY_STOP) &&
-		    (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
+		if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+		    (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
 			ret = spu_process_callback(ctx);
 			if (ret)
 				break;
-			*status &= ~SPU_STATUS_STOPPED_BY_STOP;
+			status &= ~SPU_STATUS_STOPPED_BY_STOP;
 		}
 		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
-			ret = spu_reacquire_runnable(ctx, npc, status);
+			ret = spu_reacquire_runnable(ctx, npc, &status);
 			if (ret)
 				goto out;
 			continue;
 		}
 		ret = spu_process_events(ctx);
 
-	} while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
+	} while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
 				      SPU_STATUS_STOPPED_BY_HALT)));
 
 	ctx->ops->runcntl_stop(ctx);
-	ret = spu_run_fini(ctx, npc, status);
+	ret = spu_run_fini(ctx, npc, &status);
 	if (!ret)
-		ret = *status;
+		ret = status;
 	spu_yield(ctx);
 
 out:
+	*event = ctx->event_return;
 	up(&ctx->run_sema);
 	return ret;
 }
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 1350294..bd6fe4b 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -3,11 +3,7 @@
  * Copyright (C) IBM 2005
  * Author: Mark Nutter <mnutter@us.ibm.com>
  *
- * SPU scheduler, based on Linux thread priority.  For now use
- * a simple "cooperative" yield model with no preemption.  SPU
- * scheduling will eventually be preemptive: When a thread with
- * a higher static priority gets ready to run, then an active SPU
- * context will be preempted and returned to the waitq.
+ * 2006-03-31	NUMA domains added.
  *
  * 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
@@ -37,6 +33,9 @@
 #include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
+#include <linux/numa.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -49,128 +48,59 @@
 
 #define SPU_BITMAP_SIZE (((MAX_PRIO+BITS_PER_LONG)/BITS_PER_LONG)+1)
 struct spu_prio_array {
-	atomic_t nr_blocked;
 	unsigned long bitmap[SPU_BITMAP_SIZE];
 	wait_queue_head_t waitq[MAX_PRIO];
+	struct list_head active_list[MAX_NUMNODES];
+	struct mutex active_mutex[MAX_NUMNODES];
 };
 
-/* spu_runqueue - This is the main runqueue data structure for SPUs. */
-struct spu_runqueue {
-	struct semaphore sem;
-	unsigned long nr_active;
-	unsigned long nr_idle;
-	unsigned long nr_switches;
-	struct list_head active_list;
-	struct list_head idle_list;
-	struct spu_prio_array prio;
-};
+static struct spu_prio_array *spu_prio;
 
-static struct spu_runqueue *spu_runqueues = NULL;
-
-static inline struct spu_runqueue *spu_rq(void)
+static inline int node_allowed(int node)
 {
-	/* Future: make this a per-NODE array,
-	 * and use cpu_to_node(smp_processor_id())
-	 */
-	return spu_runqueues;
-}
+	cpumask_t mask;
 
-static inline struct spu *del_idle(struct spu_runqueue *rq)
-{
-	struct spu *spu;
-
-	BUG_ON(rq->nr_idle <= 0);
-	BUG_ON(list_empty(&rq->idle_list));
-	/* Future: Move SPU out of low-power SRI state. */
-	spu = list_entry(rq->idle_list.next, struct spu, sched_list);
-	list_del_init(&spu->sched_list);
-	rq->nr_idle--;
-	return spu;
-}
-
-static inline void del_active(struct spu_runqueue *rq, struct spu *spu)
-{
-	BUG_ON(rq->nr_active <= 0);
-	BUG_ON(list_empty(&rq->active_list));
-	list_del_init(&spu->sched_list);
-	rq->nr_active--;
-}
-
-static inline void add_idle(struct spu_runqueue *rq, struct spu *spu)
-{
-	/* Future: Put SPU into low-power SRI state. */
-	list_add_tail(&spu->sched_list, &rq->idle_list);
-	rq->nr_idle++;
-}
-
-static inline void add_active(struct spu_runqueue *rq, struct spu *spu)
-{
-	rq->nr_active++;
-	rq->nr_switches++;
-	list_add_tail(&spu->sched_list, &rq->active_list);
-}
-
-static void prio_wakeup(struct spu_runqueue *rq)
-{
-	if (atomic_read(&rq->prio.nr_blocked) && rq->nr_idle) {
-		int best = sched_find_first_bit(rq->prio.bitmap);
-		if (best < MAX_PRIO) {
-			wait_queue_head_t *wq = &rq->prio.waitq[best];
-			wake_up_interruptible_nr(wq, 1);
-		}
-	}
-}
-
-static void prio_wait(struct spu_runqueue *rq, struct spu_context *ctx,
-		      u64 flags)
-{
-	int prio = current->prio;
-	wait_queue_head_t *wq = &rq->prio.waitq[prio];
-	DEFINE_WAIT(wait);
-
-	__set_bit(prio, rq->prio.bitmap);
-	atomic_inc(&rq->prio.nr_blocked);
-	prepare_to_wait_exclusive(wq, &wait, TASK_INTERRUPTIBLE);
-	if (!signal_pending(current)) {
-		up(&rq->sem);
-		up_write(&ctx->state_sema);
-		pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__,
-			 current->pid, current->prio);
-		schedule();
-		down_write(&ctx->state_sema);
-		down(&rq->sem);
-	}
-	finish_wait(wq, &wait);
-	atomic_dec(&rq->prio.nr_blocked);
-	if (!waitqueue_active(wq))
-		__clear_bit(prio, rq->prio.bitmap);
-}
-
-static inline int is_best_prio(struct spu_runqueue *rq)
-{
-	int best_prio;
-
-	best_prio = sched_find_first_bit(rq->prio.bitmap);
-	return (current->prio < best_prio) ? 1 : 0;
+	if (!nr_cpus_node(node))
+		return 0;
+	mask = node_to_cpumask(node);
+	if (!cpus_intersects(mask, current->cpus_allowed))
+		return 0;
+	return 1;
 }
 
 static inline void mm_needs_global_tlbie(struct mm_struct *mm)
 {
+	int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
+
 	/* Global TLBIE broadcast required with SPEs. */
-#if (NR_CPUS > 1)
-	__cpus_setall(&mm->cpu_vm_mask, NR_CPUS);
-#else
-	__cpus_setall(&mm->cpu_vm_mask, NR_CPUS+1); /* is this ok? */
-#endif
+	__cpus_setall(&mm->cpu_vm_mask, nr);
 }
 
+static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
+
+static void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
+{
+	blocking_notifier_call_chain(&spu_switch_notifier,
+			    ctx ? ctx->object_id : 0, spu);
+}
+
+int spu_switch_event_register(struct notifier_block * n)
+{
+	return blocking_notifier_chain_register(&spu_switch_notifier, n);
+}
+
+int spu_switch_event_unregister(struct notifier_block * n)
+{
+	return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
+}
+
+
 static inline void bind_context(struct spu *spu, struct spu_context *ctx)
 {
-	pr_debug("%s: pid=%d SPU=%d\n", __FUNCTION__, current->pid,
-		 spu->number);
+	pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
+		 spu->number, spu->node);
 	spu->ctx = ctx;
 	spu->flags = 0;
-	ctx->flags = 0;
 	ctx->spu = spu;
 	ctx->ops = &spu_hw_ops;
 	spu->pid = current->pid;
@@ -181,16 +111,20 @@
 	spu->wbox_callback = spufs_wbox_callback;
 	spu->stop_callback = spufs_stop_callback;
 	spu->mfc_callback = spufs_mfc_callback;
+	spu->dma_callback = spufs_dma_callback;
 	mb();
 	spu_unmap_mappings(ctx);
 	spu_restore(&ctx->csa, spu);
 	spu->timestamp = jiffies;
+	spu_cpu_affinity_set(spu, raw_smp_processor_id());
+	spu_switch_notify(spu, ctx);
 }
 
 static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
 {
-	pr_debug("%s: unbind pid=%d SPU=%d\n", __FUNCTION__,
-		 spu->pid, spu->number);
+	pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
+		 spu->pid, spu->number, spu->node);
+	spu_switch_notify(spu, NULL);
 	spu_unmap_mappings(ctx);
 	spu_save(&ctx->csa, spu);
 	spu->timestamp = jiffies;
@@ -199,173 +133,158 @@
 	spu->wbox_callback = NULL;
 	spu->stop_callback = NULL;
 	spu->mfc_callback = NULL;
+	spu->dma_callback = NULL;
 	spu->mm = NULL;
 	spu->pid = 0;
 	spu->prio = MAX_PRIO;
 	ctx->ops = &spu_backing_ops;
 	ctx->spu = NULL;
-	ctx->flags = 0;
 	spu->flags = 0;
 	spu->ctx = NULL;
 }
 
-static void spu_reaper(void *data)
+static inline void spu_add_wq(wait_queue_head_t * wq, wait_queue_t * wait,
+			      int prio)
 {
-	struct spu_context *ctx = data;
-	struct spu *spu;
+	prepare_to_wait_exclusive(wq, wait, TASK_INTERRUPTIBLE);
+	set_bit(prio, spu_prio->bitmap);
+}
 
-	down_write(&ctx->state_sema);
-	spu = ctx->spu;
-	if (spu && test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) {
-		if (atomic_read(&spu->rq->prio.nr_blocked)) {
-			pr_debug("%s: spu=%d\n", __func__, spu->number);
-			ctx->ops->runcntl_stop(ctx);
-			spu_deactivate(ctx);
-			wake_up_all(&ctx->stop_wq);
-		} else {
-			clear_bit(SPU_CONTEXT_PREEMPT, &ctx->flags);
-		}
+static inline void spu_del_wq(wait_queue_head_t * wq, wait_queue_t * wait,
+			      int prio)
+{
+	u64 flags;
+
+	__set_current_state(TASK_RUNNING);
+
+	spin_lock_irqsave(&wq->lock, flags);
+
+	remove_wait_queue_locked(wq, wait);
+	if (list_empty(&wq->task_list))
+		clear_bit(prio, spu_prio->bitmap);
+
+	spin_unlock_irqrestore(&wq->lock, flags);
+}
+
+static void spu_prio_wait(struct spu_context *ctx, u64 flags)
+{
+	int prio = current->prio;
+	wait_queue_head_t *wq = &spu_prio->waitq[prio];
+	DEFINE_WAIT(wait);
+
+	if (ctx->spu)
+		return;
+
+	spu_add_wq(wq, &wait, prio);
+
+	if (!signal_pending(current)) {
+		up_write(&ctx->state_sema);
+		pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__,
+			 current->pid, current->prio);
+		schedule();
+		down_write(&ctx->state_sema);
 	}
-	up_write(&ctx->state_sema);
-	put_spu_context(ctx);
+
+	spu_del_wq(wq, &wait, prio);
 }
 
-static void schedule_spu_reaper(struct spu_runqueue *rq, struct spu *spu)
+static void spu_prio_wakeup(void)
 {
-	struct spu_context *ctx = get_spu_context(spu->ctx);
-	unsigned long now = jiffies;
-	unsigned long expire = spu->timestamp + SPU_MIN_TIMESLICE;
-
-	set_bit(SPU_CONTEXT_PREEMPT, &ctx->flags);
-	INIT_WORK(&ctx->reap_work, spu_reaper, ctx);
-	if (time_after(now, expire))
-		schedule_work(&ctx->reap_work);
-	else
-		schedule_delayed_work(&ctx->reap_work, expire - now);
-}
-
-static void check_preempt_active(struct spu_runqueue *rq)
-{
-	struct list_head *p;
-	struct spu *worst = NULL;
-
-	list_for_each(p, &rq->active_list) {
-		struct spu *spu = list_entry(p, struct spu, sched_list);
-		struct spu_context *ctx = spu->ctx;
-		if (!test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) {
-			if (!worst || (spu->prio > worst->prio)) {
-				worst = spu;
-			}
-		}
+	int best = sched_find_first_bit(spu_prio->bitmap);
+	if (best < MAX_PRIO) {
+		wait_queue_head_t *wq = &spu_prio->waitq[best];
+		wake_up_interruptible_nr(wq, 1);
 	}
-	if (worst && (current->prio < worst->prio))
-		schedule_spu_reaper(rq, worst);
-}
-
-static struct spu *get_idle_spu(struct spu_context *ctx, u64 flags)
-{
-	struct spu_runqueue *rq;
-	struct spu *spu = NULL;
-
-	rq = spu_rq();
-	down(&rq->sem);
-	for (;;) {
-		if (rq->nr_idle > 0) {
-			if (is_best_prio(rq)) {
-				/* Fall through. */
-				spu = del_idle(rq);
-				break;
-			} else {
-				prio_wakeup(rq);
-				up(&rq->sem);
-				yield();
-				if (signal_pending(current)) {
-					return NULL;
-				}
-				rq = spu_rq();
-				down(&rq->sem);
-				continue;
-			}
-		} else {
-			check_preempt_active(rq);
-			prio_wait(rq, ctx, flags);
-			if (signal_pending(current)) {
-				prio_wakeup(rq);
-				spu = NULL;
-				break;
-			}
-			continue;
-		}
-	}
-	up(&rq->sem);
-	return spu;
-}
-
-static void put_idle_spu(struct spu *spu)
-{
-	struct spu_runqueue *rq = spu->rq;
-
-	down(&rq->sem);
-	add_idle(rq, spu);
-	prio_wakeup(rq);
-	up(&rq->sem);
 }
 
 static int get_active_spu(struct spu *spu)
 {
-	struct spu_runqueue *rq = spu->rq;
-	struct list_head *p;
+	int node = spu->node;
 	struct spu *tmp;
 	int rc = 0;
 
-	down(&rq->sem);
-	list_for_each(p, &rq->active_list) {
-		tmp = list_entry(p, struct spu, sched_list);
+	mutex_lock(&spu_prio->active_mutex[node]);
+	list_for_each_entry(tmp, &spu_prio->active_list[node], list) {
 		if (tmp == spu) {
-			del_active(rq, spu);
+			list_del_init(&spu->list);
 			rc = 1;
 			break;
 		}
 	}
-	up(&rq->sem);
+	mutex_unlock(&spu_prio->active_mutex[node]);
 	return rc;
 }
 
 static void put_active_spu(struct spu *spu)
 {
-	struct spu_runqueue *rq = spu->rq;
+	int node = spu->node;
 
-	down(&rq->sem);
-	add_active(rq, spu);
-	up(&rq->sem);
+	mutex_lock(&spu_prio->active_mutex[node]);
+	list_add_tail(&spu->list, &spu_prio->active_list[node]);
+	mutex_unlock(&spu_prio->active_mutex[node]);
 }
 
-/* Lock order:
- *	spu_activate() & spu_deactivate() require the
- *	caller to have down_write(&ctx->state_sema).
+static struct spu *spu_get_idle(struct spu_context *ctx, u64 flags)
+{
+	struct spu *spu = NULL;
+	int node = cpu_to_node(raw_smp_processor_id());
+	int n;
+
+	for (n = 0; n < MAX_NUMNODES; n++, node++) {
+		node = (node < MAX_NUMNODES) ? node : 0;
+		if (!node_allowed(node))
+			continue;
+		spu = spu_alloc_node(node);
+		if (spu)
+			break;
+	}
+	return spu;
+}
+
+static inline struct spu *spu_get(struct spu_context *ctx, u64 flags)
+{
+	/* Future: spu_get_idle() if possible,
+	 * otherwise try to preempt an active
+	 * context.
+	 */
+	return spu_get_idle(ctx, flags);
+}
+
+/* The three externally callable interfaces
+ * for the scheduler begin here.
  *
- *	The rq->sem is breifly held (inside or outside a
- *	given ctx lock) for list management, but is never
- *	held during save/restore.
+ *	spu_activate	- bind a context to SPU, waiting as needed.
+ *	spu_deactivate	- unbind a context from its SPU.
+ *	spu_yield	- yield an SPU if others are waiting.
  */
 
 int spu_activate(struct spu_context *ctx, u64 flags)
 {
 	struct spu *spu;
+	int ret = 0;
 
-	if (ctx->spu)
-		return 0;
-	spu = get_idle_spu(ctx, flags);
-	if (!spu)
-		return (signal_pending(current)) ? -ERESTARTSYS : -EAGAIN;
-	bind_context(spu, ctx);
-	/*
-	 * We're likely to wait for interrupts on the same
-	 * CPU that we are now on, so send them here.
-	 */
-	spu_cpu_affinity_set(spu, raw_smp_processor_id());
-	put_active_spu(spu);
-	return 0;
+	for (;;) {
+		if (ctx->spu)
+			return 0;
+		spu = spu_get(ctx, flags);
+		if (spu != NULL) {
+			if (ctx->spu != NULL) {
+				spu_free(spu);
+				spu_prio_wakeup();
+				break;
+			}
+			bind_context(spu, ctx);
+			put_active_spu(spu);
+			break;
+		}
+		spu_prio_wait(ctx, flags);
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			spu_prio_wakeup();
+			break;
+		}
+	}
+	return ret;
 }
 
 void spu_deactivate(struct spu_context *ctx)
@@ -378,8 +297,10 @@
 		return;
 	needs_idle = get_active_spu(spu);
 	unbind_context(spu, ctx);
-	if (needs_idle)
-		put_idle_spu(spu);
+	if (needs_idle) {
+		spu_free(spu);
+		spu_prio_wakeup();
+	}
 }
 
 void spu_yield(struct spu_context *ctx)
@@ -387,77 +308,60 @@
 	struct spu *spu;
 	int need_yield = 0;
 
-	down_write(&ctx->state_sema);
-	spu = ctx->spu;
-	if (spu && (sched_find_first_bit(spu->rq->prio.bitmap) < MAX_PRIO)) {
-		pr_debug("%s: yielding SPU %d\n", __FUNCTION__, spu->number);
-		spu_deactivate(ctx);
-		ctx->state = SPU_STATE_SAVED;
-		need_yield = 1;
-	} else if (spu) {
-		spu->prio = MAX_PRIO;
+	if (down_write_trylock(&ctx->state_sema)) {
+		if ((spu = ctx->spu) != NULL) {
+			int best = sched_find_first_bit(spu_prio->bitmap);
+			if (best < MAX_PRIO) {
+				pr_debug("%s: yielding SPU %d NODE %d\n",
+					 __FUNCTION__, spu->number, spu->node);
+				spu_deactivate(ctx);
+				ctx->state = SPU_STATE_SAVED;
+				need_yield = 1;
+			} else {
+				spu->prio = MAX_PRIO;
+			}
+		}
+		up_write(&ctx->state_sema);
 	}
-	up_write(&ctx->state_sema);
 	if (unlikely(need_yield))
 		yield();
 }
 
 int __init spu_sched_init(void)
 {
-	struct spu_runqueue *rq;
-	struct spu *spu;
 	int i;
 
-	rq = spu_runqueues = kmalloc(sizeof(struct spu_runqueue), GFP_KERNEL);
-	if (!rq) {
-		printk(KERN_WARNING "%s: Unable to allocate runqueues.\n",
+	spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
+	if (!spu_prio) {
+		printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
 		       __FUNCTION__);
 		return 1;
 	}
-	memset(rq, 0, sizeof(struct spu_runqueue));
-	init_MUTEX(&rq->sem);
-	INIT_LIST_HEAD(&rq->active_list);
-	INIT_LIST_HEAD(&rq->idle_list);
-	rq->nr_active = 0;
-	rq->nr_idle = 0;
-	rq->nr_switches = 0;
-	atomic_set(&rq->prio.nr_blocked, 0);
 	for (i = 0; i < MAX_PRIO; i++) {
-		init_waitqueue_head(&rq->prio.waitq[i]);
-		__clear_bit(i, rq->prio.bitmap);
+		init_waitqueue_head(&spu_prio->waitq[i]);
+		__clear_bit(i, spu_prio->bitmap);
 	}
-	__set_bit(MAX_PRIO, rq->prio.bitmap);
-	for (;;) {
-		spu = spu_alloc();
-		if (!spu)
-			break;
-		pr_debug("%s: adding SPU[%d]\n", __FUNCTION__, spu->number);
-		add_idle(rq, spu);
-		spu->rq = rq;
-		spu->timestamp = jiffies;
-	}
-	if (!rq->nr_idle) {
-		printk(KERN_WARNING "%s: No available SPUs.\n", __FUNCTION__);
-		kfree(rq);
-		return 1;
+	__set_bit(MAX_PRIO, spu_prio->bitmap);
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		mutex_init(&spu_prio->active_mutex[i]);
+		INIT_LIST_HEAD(&spu_prio->active_list[i]);
 	}
 	return 0;
 }
 
 void __exit spu_sched_exit(void)
 {
-	struct spu_runqueue *rq = spu_rq();
-	struct spu *spu;
+	struct spu *spu, *tmp;
+	int node;
 
-	if (!rq) {
-		printk(KERN_WARNING "%s: no runqueues!\n", __FUNCTION__);
-		return;
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		mutex_lock(&spu_prio->active_mutex[node]);
+		list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
+					 list) {
+			list_del_init(&spu->list);
+			spu_free(spu);
+		}
+		mutex_unlock(&spu_prio->active_mutex[node]);
 	}
-	while (rq->nr_idle > 0) {
-		spu = del_idle(rq);
-		if (!spu)
-			break;
-		spu_free(spu);
-	}
-	kfree(rq);
+	kfree(spu_prio);
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 4485738..a0f55ca 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -39,6 +39,8 @@
 
 #define SPU_CONTEXT_PREEMPT          0UL
 
+struct spu_gang;
+
 struct spu_context {
 	struct spu *spu;		  /* pointer to a physical SPU */
 	struct spu_state csa;		  /* SPU context save area. */
@@ -48,6 +50,7 @@
 	struct address_space *cntl; 	   /* 'control' area mappings. */
 	struct address_space *signal1; 	   /* 'signal1' area mappings. */
 	struct address_space *signal2; 	   /* 'signal2' area mappings. */
+	u64 object_id;		   /* user space pointer for oprofile */
 
 	enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
 	struct rw_semaphore state_sema;
@@ -66,7 +69,18 @@
 	u32 tagwait;
 	struct spu_context_ops *ops;
 	struct work_struct reap_work;
-	u64 flags;
+	unsigned long flags;
+	unsigned long event_return;
+
+	struct list_head gang_list;
+	struct spu_gang *gang;
+};
+
+struct spu_gang {
+	struct list_head list;
+	struct mutex mutex;
+	struct kref kref;
+	int contexts;
 };
 
 struct mfc_dma_command {
@@ -114,6 +128,7 @@
 
 struct spufs_inode_info {
 	struct spu_context *i_ctx;
+	struct spu_gang *i_gang;
 	struct inode vfs_inode;
 };
 #define SPUFS_I(inode) \
@@ -124,12 +139,19 @@
 /* system call implementation */
 long spufs_run_spu(struct file *file,
 		   struct spu_context *ctx, u32 *npc, u32 *status);
-long spufs_create_thread(struct nameidata *nd,
+long spufs_create(struct nameidata *nd,
 			 unsigned int flags, mode_t mode);
 extern struct file_operations spufs_context_fops;
 
+/* gang management */
+struct spu_gang *alloc_spu_gang(void);
+struct spu_gang *get_spu_gang(struct spu_gang *gang);
+int put_spu_gang(struct spu_gang *gang);
+void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx);
+void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
+
 /* context management */
-struct spu_context * alloc_spu_context(void);
+struct spu_context * alloc_spu_context(struct spu_gang *gang);
 void destroy_spu_context(struct kref *kref);
 struct spu_context * get_spu_context(struct spu_context *ctx);
 int put_spu_context(struct spu_context *ctx);
@@ -183,5 +205,6 @@
 void spufs_wbox_callback(struct spu *spu);
 void spufs_stop_callback(struct spu *spu);
 void spufs_mfc_callback(struct spu *spu);
+void spufs_dma_callback(struct spu *spu, int type);
 
 #endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 9d9d82d..0f782ca 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -1779,6 +1779,15 @@
 	 */
 	out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW);
 	eieio();
+	/*
+	 * FIXME: this is to restart a DMA that we were processing
+	 *        before the save. better remember the fault information
+	 *        in the csa instead.
+	 */
+	if ((csa->priv2.mfc_control_RW & MFC_CNTL_SUSPEND_DMA_QUEUE_MASK)) {
+		out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
+		eieio();
+	}
 }
 
 static inline void enable_user_access(struct spu_state *csa, struct spu *spu)
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index e6565a9..a6d1ae4 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -38,7 +38,7 @@
 	u32 npc, status;
 
 	ret = -EFAULT;
-	if (get_user(npc, unpc) || get_user(status, ustatus))
+	if (get_user(npc, unpc))
 		goto out;
 
 	/* check if this file was created by spu_create */
@@ -49,7 +49,10 @@
 	i = SPUFS_I(filp->f_dentry->d_inode);
 	ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
 
-	if (put_user(npc, unpc) || put_user(status, ustatus))
+	if (put_user(npc, unpc))
+		ret = -EFAULT;
+
+	if (ustatus && put_user(status, ustatus))
 		ret = -EFAULT;
 out:
 	return ret;
@@ -87,7 +90,7 @@
 		ret = path_lookup(tmp, LOOKUP_PARENT|
 				LOOKUP_OPEN|LOOKUP_CREATE, &nd);
 		if (!ret) {
-			ret = spufs_create_thread(&nd, flags, mode);
+			ret = spufs_create(&nd, flags, mode);
 			path_release(&nd);
 		}
 		putname(tmp);
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 488dbd9..cae3d13 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -70,7 +70,7 @@
  * has to include <linux/interrupt.h> (to get irqreturn_t), which
  * causes all sorts of problems.  -- paulus
  */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+extern irqreturn_t xmon_irq(int, void *);
 
 extern unsigned long loops_per_jiffy;
 
@@ -335,12 +335,11 @@
 		  jiffies + event_scan_interval);
 }
 
-static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc,
-			      struct pt_regs *regs)
+static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int cascade_irq = i8259_irq(regs);
+	unsigned int cascade_irq = i8259_irq();
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	desc->chip->eoi(irq);
 }
 
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index cb6f084..bdb475c 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -61,8 +61,7 @@
 extern int tsi108_setup_pci(struct device_node *dev);
 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 extern void tsi108_pci_int_init(void);
-extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
-			    struct pt_regs *regs);
+extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc);
 
 int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
 {
@@ -200,7 +199,7 @@
 	tsi_pic = of_find_node_by_type(NULL, "open-pic");
 	if (tsi_pic) {
 		unsigned int size;
-		void *prop = get_property(tsi_pic, "reg", &size);
+		const void *prop = get_property(tsi_pic, "reg", &size);
 		mpic_paddr = of_translate_address(tsi_pic, prop);
 	}
 
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index e324468..5225abf 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -43,10 +43,7 @@
 #include "irq.h"
 #include "pci.h"
 #include "call_pci.h"
-
-#if defined(CONFIG_SMP)
-extern void iSeries_smp_message_recv(struct pt_regs *);
-#endif
+#include "smp.h"
 
 #ifdef CONFIG_PCI
 
@@ -88,7 +85,7 @@
 static int num_pending_irqs;
 static int pending_irqs[NR_IRQS];
 
-static void int_received(struct pci_event *event, struct pt_regs *regs)
+static void int_received(struct pci_event *event)
 {
 	int irq;
 
@@ -146,11 +143,11 @@
 	}
 }
 
-static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs)
+static void pci_event_handler(struct HvLpEvent *event)
 {
 	if (event && (event->xType == HvLpEvent_Type_PciIo)) {
 		if (hvlpevent_is_int(event))
-			int_received((struct pci_event *)event, regs);
+			int_received((struct pci_event *)event);
 		else
 			printk(KERN_ERR
 				"pci_event_handler: unexpected ack received\n");
@@ -308,18 +305,18 @@
 /*
  * Get the next pending IRQ.
  */
-unsigned int iSeries_get_irq(struct pt_regs *regs)
+unsigned int iSeries_get_irq(void)
 {
 	int irq = NO_IRQ_IGNORE;
 
 #ifdef CONFIG_SMP
 	if (get_lppaca()->int_dword.fields.ipi_cnt) {
 		get_lppaca()->int_dword.fields.ipi_cnt = 0;
-		iSeries_smp_message_recv(regs);
+		iSeries_smp_message_recv();
 	}
 #endif /* CONFIG_SMP */
 	if (hvlpevent_is_pending())
-		process_hvlpevents(regs);
+		process_hvlpevents();
 
 #ifdef CONFIG_PCI
 	if (num_pending_irqs) {
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index 1ee8985..69f1b43 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -4,6 +4,6 @@
 extern void iSeries_init_IRQ(void);
 extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
 extern void iSeries_activate_IRQs(void);
-extern unsigned int iSeries_get_irq(struct pt_regs *);
+extern unsigned int iSeries_get_irq(void);
 
 #endif /* _ISERIES_IRQ_H */
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index 98c1c24..e3e929e 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -116,7 +116,7 @@
 	hvlpevent_invalidate(event);
 }
 
-void process_hvlpevents(struct pt_regs *regs)
+void process_hvlpevents(void)
 {
 	struct HvLpEvent * event;
 
@@ -144,7 +144,7 @@
 				__get_cpu_var(hvlpevent_counts)[event->xType]++;
 			if (event->xType < HvLpEvent_Type_NumTypes &&
 					lpEventHandler[event->xType])
-				lpEventHandler[event->xType](event, regs);
+				lpEventHandler[event->xType](event);
 			else
 				printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
 
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 1983b64..b5737d6 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -513,7 +513,7 @@
  * parse it enough to know if it is an interrupt or an
  * acknowledge.
  */
-static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs)
+static void hv_handler(struct HvLpEvent *event)
 {
 	if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
 		if (hvlpevent_is_ack(event))
@@ -847,7 +847,7 @@
 	/* We need to poll here as we are not yet taking interrupts */
 	while (rtc_data.busy) {
 		if (hvlpevent_is_pending())
-			process_hvlpevents(NULL);
+			process_hvlpevents();
 	}
 	return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
 }
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index 2eb095e..aee5908 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -43,9 +43,11 @@
 #include <asm/cputable.h>
 #include <asm/system.h>
 
+#include "smp.h"
+
 static unsigned long iSeries_smp_message[NR_CPUS];
 
-void iSeries_smp_message_recv(struct pt_regs *regs)
+void iSeries_smp_message_recv(void)
 {
 	int cpu = smp_processor_id();
 	int msg;
@@ -55,7 +57,7 @@
 
 	for (msg = 0; msg < 4; msg++)
 		if (test_and_clear_bit(msg, &iSeries_smp_message[cpu]))
-			smp_message_recv(msg, regs);
+			smp_message_recv(msg);
 }
 
 static inline void smp_iSeries_do_message(int cpu, int msg)
diff --git a/arch/powerpc/platforms/iseries/smp.h b/arch/powerpc/platforms/iseries/smp.h
new file mode 100644
index 0000000..d501f7d
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/smp.h
@@ -0,0 +1,6 @@
+#ifndef _PLATFORMS_ISERIES_SMP_H
+#define _PLATFORMS_ISERIES_SMP_H
+
+extern void iSeries_smp_message_recv(void);
+
+#endif	/* _PLATFORMS_ISERIES_SMP_H */
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 9baa4ee..04e07e5 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -378,7 +378,7 @@
 }
 EXPORT_SYMBOL(vio_set_hostlp);
 
-static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
+static void vio_handleEvent(struct HvLpEvent *event)
 {
 	HvLpIndex remoteLp;
 	int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 1b82761..63b4d1b 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -8,7 +8,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/irq.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
@@ -33,7 +34,7 @@
 #define DBG(x...)
 #endif
 
-static struct pci_controller *u3_agp, *u3_ht;
+static struct pci_controller *u3_agp, *u3_ht, *u4_pcie;
 
 static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
 {
@@ -287,6 +288,114 @@
 	u3_ht_write_config
 };
 
+static unsigned int u4_pcie_cfa0(unsigned int devfn, unsigned int off)
+{
+	return (1 << PCI_SLOT(devfn))	|
+	       (PCI_FUNC(devfn) << 8)	|
+	       ((off >> 8) << 28) 	|
+	       (off & 0xfcu);
+}
+
+static unsigned int u4_pcie_cfa1(unsigned int bus, unsigned int devfn,
+				 unsigned int off)
+{
+        return (bus << 16)		|
+	       (devfn << 8)		|
+	       ((off >> 8) << 28)	|
+	       (off & 0xfcu)		| 1u;
+}
+
+static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose,
+                                        u8 bus, u8 dev_fn, int offset)
+{
+        unsigned int caddr;
+
+        if (bus == hose->first_busno)
+                caddr = u4_pcie_cfa0(dev_fn, offset);
+        else
+                caddr = u4_pcie_cfa1(bus, dev_fn, offset);
+
+        /* Uninorth will return garbage if we don't read back the value ! */
+        do {
+                out_le32(hose->cfg_addr, caddr);
+        } while (in_le32(hose->cfg_addr) != caddr);
+
+        offset &= 0x03;
+        return hose->cfg_data + offset;
+}
+
+static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+                               int offset, int len, u32 *val)
+{
+        struct pci_controller *hose;
+        volatile void __iomem *addr;
+
+        hose = pci_bus_to_host(bus);
+        if (hose == NULL)
+                return PCIBIOS_DEVICE_NOT_FOUND;
+        if (offset >= 0x1000)
+                return  PCIBIOS_BAD_REGISTER_NUMBER;
+        addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
+        if (!addr)
+                return PCIBIOS_DEVICE_NOT_FOUND;
+        /*
+         * Note: the caller has already checked that offset is
+         * suitably aligned and that len is 1, 2 or 4.
+         */
+        switch (len) {
+        case 1:
+                *val = in_8(addr);
+                break;
+        case 2:
+                *val = in_le16(addr);
+                break;
+        default:
+                *val = in_le32(addr);
+                break;
+        }
+        return PCIBIOS_SUCCESSFUL;
+}
+static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+                                int offset, int len, u32 val)
+{
+        struct pci_controller *hose;
+        volatile void __iomem *addr;
+
+        hose = pci_bus_to_host(bus);
+        if (hose == NULL)
+                return PCIBIOS_DEVICE_NOT_FOUND;
+        if (offset >= 0x1000)
+                return  PCIBIOS_BAD_REGISTER_NUMBER;
+        addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
+        if (!addr)
+                return PCIBIOS_DEVICE_NOT_FOUND;
+        /*
+         * Note: the caller has already checked that offset is
+         * suitably aligned and that len is 1, 2 or 4.
+         */
+        switch (len) {
+        case 1:
+                out_8(addr, val);
+                (void) in_8(addr);
+                break;
+        case 2:
+                out_le16(addr, val);
+                (void) in_le16(addr);
+                break;
+        default:
+                out_le32(addr, val);
+                (void) in_le32(addr);
+                break;
+        }
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u4_pcie_pci_ops =
+{
+        u4_pcie_read_config,
+        u4_pcie_write_config
+};
+
 static void __init setup_u3_agp(struct pci_controller* hose)
 {
 	/* On G5, we move AGP up to high bus number so we don't need
@@ -307,6 +416,26 @@
 	u3_agp = hose;
 }
 
+static void __init setup_u4_pcie(struct pci_controller* hose)
+{
+        /* We currently only implement the "non-atomic" config space, to
+         * be optimised later.
+         */
+        hose->ops = &u4_pcie_pci_ops;
+        hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+        hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+
+        /* The bus contains a bridge from root -> device, we need to
+         * make it visible on bus 0 so that we pick the right type
+         * of config cycles. If we didn't, we would have to force all
+         * config cycles to be type 1. So we override the "bus-range"
+         * property here
+         */
+        hose->first_busno = 0x00;
+        hose->last_busno = 0xff;
+        u4_pcie = hose;
+}
+
 static void __init setup_u3_ht(struct pci_controller* hose)
 {
 	hose->ops = &u3_ht_pci_ops;
@@ -354,6 +483,10 @@
 		setup_u3_ht(hose);
 		disp_name = "U3-HT";
 		primary = 1;
+        } else if (device_is_compatible(dev, "u4-pcie")) {
+                setup_u4_pcie(hose);
+                disp_name = "U4-PCIE";
+                primary = 0;
 	}
 	printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
 		disp_name, hose->first_busno, hose->last_busno);
@@ -361,7 +494,6 @@
 	/* Interpret the "ranges" property */
 	/* This also maps the I/O region and sets isa_io/mem_base */
 	pci_process_bridge_OF_ranges(hose, dev, primary);
-	pci_setup_phb_io(hose, primary);
 
 	/* Fixup "bus-range" OF property */
 	fixup_bus_range(dev);
@@ -376,8 +508,30 @@
 
 	DBG(" -> maple_pcibios_fixup\n");
 
-	for_each_pci_dev(dev)
+	for_each_pci_dev(dev) {
+		/* Fixup IRQ for PCIe host */
+		if (u4_pcie != NULL && dev->bus->number == 0 &&
+		    pci_bus_to_host(dev->bus) == u4_pcie) {
+			printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
+			dev->irq = irq_create_mapping(NULL, 1);
+			if (dev->irq != NO_IRQ)
+				set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+			continue;
+		}
+
+		/* Hide AMD8111 IDE interrupt when in legacy mode so
+		 * the driver calls pci_get_legacy_ide_irq()
+		 */
+		if (dev->vendor == PCI_VENDOR_ID_AMD &&
+		    dev->device == PCI_DEVICE_ID_AMD_8111_IDE &&
+		    (dev->class & 5) != 5) {
+			dev->irq = NO_IRQ;
+			continue;
+		}
+
+		/* For all others, map the interrupt from the device-tree */
 		pci_read_irq_line(dev);
+	}
 
 	DBG(" <- maple_pcibios_fixup\n");
 }
@@ -388,8 +542,10 @@
 	
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
 		hose->io_resource.start += offset;
 		hose->io_resource.end += offset;
+
 		printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
 		       hose->global_number,
 		       (unsigned long long)hose->io_resource.start,
@@ -431,6 +587,19 @@
 	if (ht && add_bridge(ht) != 0)
 		of_node_put(ht);
 
+        /*
+         * We need to call pci_setup_phb_io for the HT bridge first
+         * so it gets the I/O port numbers starting at 0, and we
+         * need to call it for the AGP bridge after that so it gets
+         * small positive I/O port numbers.
+         */
+        if (u3_ht)
+                pci_setup_phb_io(u3_ht, 1);
+        if (u3_agp)
+                pci_setup_phb_io(u3_agp, 0);
+        if (u4_pcie)
+                pci_setup_phb_io(u4_pcie, 0);
+
 	/* Fixup the IO resources on our host bridges as the common code
 	 * does it only for childs of the host bridges
 	 */
@@ -465,8 +634,11 @@
 		return defirq;
 
 	np = pci_device_to_OF_node(pdev);
-	if (np == NULL)
+	if (np == NULL) {
+		printk("Failed to locate OF node for IDE %s\n",
+		       pci_name(pdev));
 		return defirq;
+	}
 	irq = irq_of_parse_and_map(np, channel & 0x1);
 	if (irq == NO_IRQ) {
 		printk("Failed to map onboard IDE interrupt for channel %d\n",
@@ -479,6 +651,9 @@
 /* XXX: To remove once all firmwares are ok */
 static void fixup_maple_ide(struct pci_dev* dev)
 {
+	if (!machine_is(maple))
+		return;
+
 #if 0 /* Enable this to enable IDE port 0 */
 	{
 		u8 v;
@@ -495,7 +670,7 @@
 	dev->resource[4].start = 0xcc00;
 	dev->resource[4].end = 0xcc10;
 #endif
-#if 1 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
+#if 0 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
 	{
 		struct pci_dev *apicdev;
 		u32 v;
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index 4679c52..39020c1 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -35,17 +35,17 @@
 
 #define CONFIG_OFFSET_VALID(off) ((off) < 4096)
 
-static unsigned long pa_pxp_cfg_addr(struct pci_controller *hose,
+static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
 				       u8 bus, u8 devfn, int offset)
 {
-	return ((unsigned long)hose->cfg_data) + PA_PXP_CFA(bus, devfn, offset);
+	return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset);
 }
 
 static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
 			      int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	void volatile __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (!hose)
@@ -62,13 +62,13 @@
 	 */
 	switch (len) {
 	case 1:
-		*val = in_8((u8 *)addr);
+		*val = in_8(addr);
 		break;
 	case 2:
-		*val = in_le16((u16 *)addr);
+		*val = in_le16(addr);
 		break;
 	default:
-		*val = in_le32((u32 *)addr);
+		*val = in_le32(addr);
 		break;
 	}
 
@@ -79,7 +79,7 @@
 			       int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	unsigned long addr;
+	void volatile __iomem *addr;
 
 	hose = pci_bus_to_host(bus);
 	if (!hose)
@@ -96,16 +96,16 @@
 	 */
 	switch (len) {
 	case 1:
-		out_8((u8 *)addr, val);
-		(void) in_8((u8 *)addr);
+		out_8(addr, val);
+		(void) in_8(addr);
 		break;
 	case 2:
-		out_le16((u16 *)addr, val);
-		(void) in_le16((u16 *)addr);
+		out_le16(addr, val);
+		(void) in_le16(addr);
 		break;
 	default:
-		out_le32((u32 *)addr, val);
-		(void) in_le32((u32 *)addr);
+		out_le32(addr, val);
+		(void) in_le32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index c2c7cf7..bfc4829 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -342,7 +342,7 @@
 }
 
 /* Interrupt handler */
-static irqreturn_t kw_i2c_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t kw_i2c_irq(int irq, void *dev_id)
 {
 	struct pmac_i2c_host_kw *host = dev_id;
 	unsigned long flags;
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index ee3b223..5c6c15c 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -15,7 +15,7 @@
 #define DBG(fmt...)
 #endif
 
-static irqreturn_t macio_gpio_irq(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t macio_gpio_irq(int irq, void *data)
 {
 	pmf_do_irq(data);
 
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 39f7ddb..39db128 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -42,7 +42,7 @@
  * has to include <linux/interrupt.h> (to get irqreturn_t), which
  * causes all sorts of problems.  -- paulus
  */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+extern irqreturn_t xmon_irq(int, void *);
 
 #ifdef CONFIG_PPC32
 struct pmac_irq_hw {
@@ -210,7 +210,7 @@
 	.retrigger	= pmac_retrigger,
 };
 
-static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gatwick_action(int cpl, void *dev_id)
 {
 	unsigned long flags;
 	int irq, bits;
@@ -227,7 +227,7 @@
 			continue;
 		irq += __ilog2(bits);
 		spin_unlock_irqrestore(&pmac_pic_lock, flags);
-		__do_IRQ(irq, regs);
+		__do_IRQ(irq);
 		spin_lock_irqsave(&pmac_pic_lock, flags);
 		rc = IRQ_HANDLED;
 	}
@@ -235,18 +235,18 @@
 	return rc;
 }
 
-static unsigned int pmac_pic_get_irq(struct pt_regs *regs)
+static unsigned int pmac_pic_get_irq(void)
 {
 	int irq;
 	unsigned long bits = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_SMP
-	void psurge_smp_message_recv(struct pt_regs *);
+	void psurge_smp_message_recv(void);
 
        	/* IPI's are a hack on the powersurge -- Cort */
        	if ( smp_processor_id() != 0 ) {
-		psurge_smp_message_recv(regs);
+		psurge_smp_message_recv();
 		return NO_IRQ_IGNORE;	/* ignore, already handled */
         }
 #endif /* CONFIG_SMP */
@@ -440,14 +440,13 @@
 }
 #endif /* CONFIG_PPC32 */
 
-static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc,
-			    struct pt_regs *regs)
+static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
 {
 	struct mpic *mpic = desc->handler_data;
 
-	unsigned int cascade_irq = mpic_get_one_irq(mpic, regs);
+	unsigned int cascade_irq = mpic_get_one_irq(mpic);
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	desc->chip->eoi(irq);
 }
 
diff --git a/arch/powerpc/platforms/powermac/pic.h b/arch/powerpc/platforms/powermac/pic.h
index 664103d..c44c89f 100644
--- a/arch/powerpc/platforms/powermac/pic.h
+++ b/arch/powerpc/platforms/powermac/pic.h
@@ -5,7 +5,7 @@
 
 extern struct hw_interrupt_type pmac_pic;
 
-void pmac_pic_init(void);
-int pmac_get_irq(struct pt_regs *regs);
+extern void pmac_pic_init(void);
+extern int pmac_get_irq(void);
 
 #endif /* __PPC_PLATFORMS_PMAC_PIC_H */
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 1949b65..eeb2ae5 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -160,7 +160,7 @@
  */
 static unsigned long psurge_smp_message[NR_CPUS];
 
-void psurge_smp_message_recv(struct pt_regs *regs)
+void psurge_smp_message_recv(void)
 {
 	int cpu = smp_processor_id();
 	int msg;
@@ -174,12 +174,12 @@
 	/* make sure there is a message there */
 	for (msg = 0; msg < 4; msg++)
 		if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
-			smp_message_recv(msg, regs);
+			smp_message_recv(msg);
 }
 
-irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
+irqreturn_t psurge_primary_intr(int irq, void *d)
 {
-	psurge_smp_message_recv(regs);
+	psurge_smp_message_recv();
 	return IRQ_HANDLED;
 }
 
@@ -328,6 +328,7 @@
 {
 	unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
 	unsigned long a;
+	int i;
 
 	/* may need to flush here if secondary bats aren't setup */
 	for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
@@ -340,7 +341,11 @@
 	mb();
 
 	psurge_set_ipi(nr);
-	udelay(10);
+	/*
+	 * We can't use udelay here because the timebase is now frozen.
+	 */
+	for (i = 0; i < 2000; ++i)
+		barrier();
 	psurge_clr_ipi(nr);
 
 	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index bbf2e34..d24ba54 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -267,7 +267,8 @@
 				 struct iommu_table *tbl)
 {
 	struct device_node *node;
-	const unsigned long *basep, *sizep;
+	const unsigned long *basep;
+	const u32 *sizep;
 
 	node = (struct device_node *)phb->arch_data;
 
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 311ed19..b1d3d16 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -65,16 +65,14 @@
 #define EPOW_SENSOR_INDEX	0
 #define RAS_VECTOR_OFFSET	0x500
 
-static irqreturn_t ras_epow_interrupt(int irq, void *dev_id,
-					struct pt_regs * regs);
-static irqreturn_t ras_error_interrupt(int irq, void *dev_id,
-					struct pt_regs * regs);
+static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
+static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
 
 /* #define DEBUG */
 
 
 static void request_ras_irqs(struct device_node *np,
-			irqreturn_t (*handler)(int, void *, struct pt_regs *),
+			irq_handler_t handler,
 			const char *name)
 {
 	int i, index, count = 0;
@@ -166,8 +164,7 @@
  * to examine the type of power failure and take appropriate action where
  * the time horizon permits something useful to be done.
  */
-static irqreturn_t
-ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 {
 	int status = 0xdeadbeef;
 	int state = 0;
@@ -210,8 +207,7 @@
  * For nonrecoverable errors, an error is logged and we stop all processing
  * as quickly as possible in order to prevent propagation of the failure.
  */
-static irqreturn_t
-ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 {
 	struct rtas_error_log *rtas_elog;
 	int status = 0xdeadbeef;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f82b13e..89a8119 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -121,12 +121,11 @@
 		fwnmi_active = 1;
 }
 
-void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc,
-			  struct pt_regs *regs)
+void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int cascade_irq = i8259_irq(regs);
+	unsigned int cascade_irq = i8259_irq();
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	desc->chip->eoi(irq);
 }
 
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 253972e..d071abe 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -308,14 +308,14 @@
 	return NO_IRQ;
 }
 
-static unsigned int xics_get_irq_direct(struct pt_regs *regs)
+static unsigned int xics_get_irq_direct(void)
 {
 	unsigned int cpu = smp_processor_id();
 
 	return xics_remap_irq(direct_xirr_info_get(cpu));
 }
 
-static unsigned int xics_get_irq_lpar(struct pt_regs *regs)
+static unsigned int xics_get_irq_lpar(void)
 {
 	unsigned int cpu = smp_processor_id();
 
@@ -324,7 +324,7 @@
 
 #ifdef CONFIG_SMP
 
-static irqreturn_t xics_ipi_dispatch(int cpu, struct pt_regs *regs)
+static irqreturn_t xics_ipi_dispatch(int cpu)
 {
 	WARN_ON(cpu_is_offline(cpu));
 
@@ -332,47 +332,47 @@
 		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
 				       &xics_ipi_message[cpu].value)) {
 			mb();
-			smp_message_recv(PPC_MSG_CALL_FUNCTION, regs);
+			smp_message_recv(PPC_MSG_CALL_FUNCTION);
 		}
 		if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
 				       &xics_ipi_message[cpu].value)) {
 			mb();
-			smp_message_recv(PPC_MSG_RESCHEDULE, regs);
+			smp_message_recv(PPC_MSG_RESCHEDULE);
 		}
 #if 0
 		if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK,
 				       &xics_ipi_message[cpu].value)) {
 			mb();
-			smp_message_recv(PPC_MSG_MIGRATE_TASK, regs);
+			smp_message_recv(PPC_MSG_MIGRATE_TASK);
 		}
 #endif
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 		if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
 				       &xics_ipi_message[cpu].value)) {
 			mb();
-			smp_message_recv(PPC_MSG_DEBUGGER_BREAK, regs);
+			smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
 		}
 #endif
 	}
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
 
 	direct_qirr_info(cpu, 0xff);
 
-	return xics_ipi_dispatch(cpu, regs);
+	return xics_ipi_dispatch(cpu);
 }
 
-static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
 
 	lpar_qirr_info(cpu, 0xff);
 
-	return xics_ipi_dispatch(cpu, regs);
+	return xics_ipi_dispatch(cpu);
 }
 
 void xics_cause_IPI(int cpu)
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index 6ee1055..db0ec3b 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -31,7 +31,6 @@
 extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
 struct irq_desc;
-extern void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc,
-				 struct pt_regs *regs);
+extern void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc);
 
 #endif /* _POWERPC_KERNEL_XICS_H */
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 28b0189..767ee66 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -147,7 +147,7 @@
 	.end = cpm2_end_irq,
 };
 
-unsigned int cpm2_get_irq(struct pt_regs *regs)
+unsigned int cpm2_get_irq(void)
 {
 	int irq;
 	unsigned long bits;
diff --git a/arch/powerpc/sysdev/cpm2_pic.h b/arch/powerpc/sysdev/cpm2_pic.h
index 3c513e5..2840616 100644
--- a/arch/powerpc/sysdev/cpm2_pic.h
+++ b/arch/powerpc/sysdev/cpm2_pic.h
@@ -3,7 +3,7 @@
 
 extern intctl_cpm2_t *cpm2_intctl;
 
-extern unsigned int cpm2_get_irq(struct pt_regs *regs);
+extern unsigned int cpm2_get_irq(void);
 
 extern void cpm2_pic_init(struct device_node*);
 
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 7d759f1..dbe92ae 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -567,7 +567,7 @@
 		struct resource r[4];
 		struct device_node *phy, *mdio;
 		struct fs_platform_info fs_enet_data;
-		const unsigned int *id, *phy_addr, phy_irq;
+		const unsigned int *id, *phy_addr, *phy_irq;
 		const void *mac_addr;
 		const phandle *ph;
 		const char *model;
@@ -641,7 +641,7 @@
 
 		if (strstr(model, "FCC")) {
 			int fcc_index = *id - 1;
-			unsigned char* mdio_bb_prop;
+			const unsigned char *mdio_bb_prop;
 
 			fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
 			fs_enet_data.rx_ring = 32;
@@ -708,8 +708,9 @@
 			ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
 						     sizeof(struct
 							    fs_platform_info));
-		if (ret)
-			goto unreg;
+			if (ret)
+				goto unreg;
+		}
 	}
 	return 0;
 
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 26a6a3b..0450265 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -34,7 +34,7 @@
  * which is called.  It should be noted that polling is broken on some
  * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
  */
-unsigned int i8259_irq(struct pt_regs *regs)
+unsigned int i8259_irq(void)
 {
 	int irq;
 	int lock = 0;
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 6ebdae8..bc4d4a7 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -709,7 +709,7 @@
 }
 
 /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
-unsigned int ipic_get_irq(struct pt_regs *regs)
+unsigned int ipic_get_irq(void)
 {
 	int irq;
 
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 3ee03a9..ba4833f 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -489,9 +489,9 @@
 }
 
 #ifdef CONFIG_SMP
-static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
 {
-	smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0, regs);
+	smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0);
 	return IRQ_HANDLED;
 }
 #endif /* CONFIG_SMP */
@@ -1217,7 +1217,7 @@
 		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
 }
 
-unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
+unsigned int mpic_get_one_irq(struct mpic *mpic)
 {
 	u32 src;
 
@@ -1230,13 +1230,13 @@
 	return irq_linear_revmap(mpic->irqhost, src);
 }
 
-unsigned int mpic_get_irq(struct pt_regs *regs)
+unsigned int mpic_get_irq(void)
 {
 	struct mpic *mpic = mpic_primary;
 
 	BUG_ON(mpic == NULL);
 
-	return mpic_get_one_irq(mpic, regs);
+	return mpic_get_one_irq(mpic);
 }
 
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index c229d07..6995f51 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -300,7 +300,7 @@
 };
 
 /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
-unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic, struct pt_regs *regs)
+unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
 {
 	int irq;
 
@@ -316,7 +316,7 @@
 }
 
 /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
-unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic, struct pt_regs *regs)
+unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
 {
 	int irq;
 
@@ -333,33 +333,31 @@
 
 /* FIXME: We mask all the QE Low interrupts while handling.  We should
  * let other interrupt come in, but BAD interrupts are generated */
-void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc,
-				struct pt_regs *regs)
+void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc)
 {
 	struct qe_ic *qe_ic = desc->handler_data;
 	struct irq_chip *chip = irq_desc[irq].chip;
 
-	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic, regs);
+	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
 
 	chip->mask_ack(irq);
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	chip->unmask(irq);
 }
 
 /* FIXME: We mask all the QE High interrupts while handling.  We should
  * let other interrupt come in, but BAD interrupts are generated */
-void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc,
-				 struct pt_regs *regs)
+void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc)
 {
 	struct qe_ic *qe_ic = desc->handler_data;
 	struct irq_chip *chip = irq_desc[irq].chip;
 
-	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic, regs);
+	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
 
 	chip->mask_ack(irq);
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	chip->unmask(irq);
 }
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index aea4359..0afe6bf 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -14,7 +14,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index c28f69b..322f86e 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -405,11 +405,10 @@
 	init_pci_source();
 }
 
-void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
-			    struct pt_regs *regs)
+void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int cascade_irq = get_pci_source();
 	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq, regs);
+		generic_handle_irq(cascade_irq);
 	desc->chip->eoi(irq);
 }
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 708236f..f56ffef 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -35,6 +36,7 @@
 #include <asm/rtas.h>
 #include <asm/sstep.h>
 #include <asm/bug.h>
+#include <asm/irq_regs.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
@@ -520,13 +522,12 @@
 }
 EXPORT_SYMBOL(xmon);
 
-irqreturn_t
-xmon_irq(int irq, void *d, struct pt_regs *regs)
+irqreturn_t xmon_irq(int irq, void *d)
 {
 	unsigned long flags;
 	local_irq_save(flags);
 	printf("Keyboard interrupt\n");
-	xmon(regs);
+	xmon(get_irq_regs());
 	local_irq_restore(flags);
 	return IRQ_HANDLED;
 }
@@ -2577,12 +2578,11 @@
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
-static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
-			      struct tty_struct *tty) 
+static void sysrq_handle_xmon(int key, struct tty_struct *tty) 
 {
 	/* ensure xmon is enabled */
 	xmon_init(1);
-	debugger(pt_regs);
+	debugger(get_irq_regs());
 }
 
 static struct sysrq_key_op sysrq_xmon_op = 
diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
index 87fe9a8..e354839 100644
--- a/arch/ppc/4xx_io/serial_sicc.c
+++ b/arch/ppc/4xx_io/serial_sicc.c
@@ -414,7 +414,7 @@
 }
 
 static void
-siccuart_rx_chars(struct SICC_info *info, struct pt_regs *regs)
+siccuart_rx_chars(struct SICC_info *info)
 {
     struct tty_struct *tty = info->tty;
     unsigned int status, ch, rsr, flg, ignored = 0;
@@ -441,7 +441,7 @@
 #ifdef SUPPORT_SYSRQ
         if (info->sysrq) {
             if (ch && time_before(jiffies, info->sysrq)) {
-                handle_sysrq(ch, regs, NULL);
+                handle_sysrq(ch, NULL);
                 info->sysrq = 0;
                 goto ignore_char;
             }
@@ -553,15 +553,15 @@
 }
 
 
-static irqreturn_t siccuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t siccuart_int_rx(int irq, void *dev_id)
 {
     struct SICC_info *info = dev_id;
-    siccuart_rx_chars(info, regs);
+    siccuart_rx_chars(info)
     return IRQ_HANDLED;
 }
 
 
-static irqreturn_t siccuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t siccuart_int_tx(int irq, void *dev_id)
 {
     struct SICC_info *info = dev_id;
     siccuart_tx_chars(info);
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index ac6d55f..a6056c2 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -122,7 +122,7 @@
 static int scc_enet_open(struct net_device *dev);
 static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int scc_enet_rx(struct net_device *dev);
-static irqreturn_t scc_enet_interrupt(int irq, void *dev_id, struct pt_regs *);
+static irqreturn_t scc_enet_interrupt(int irq, void *dev_id);
 static int scc_enet_close(struct net_device *dev);
 static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -273,7 +273,7 @@
  * This is called from the CPM handler, not the MPC core interrupt.
  */
 static irqreturn_t
-scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+scc_enet_interrupt(int irq, void * dev_id)
 {
 	struct	net_device *dev = dev_id;
 	volatile struct	scc_enet_private *cep;
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index e347fe8..2e1943e 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -140,7 +140,7 @@
 static int fcc_enet_open(struct net_device *dev);
 static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int fcc_enet_rx(struct net_device *dev);
-static irqreturn_t fcc_enet_interrupt(int irq, void *dev_id, struct pt_regs *);
+static irqreturn_t fcc_enet_interrupt(int irq, void *dev_id);
 static int fcc_enet_close(struct net_device *dev);
 static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
 /* static void set_multicast_list(struct net_device *dev); */
@@ -524,7 +524,7 @@
 
 /* The interrupt handler. */
 static irqreturn_t
-fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+fcc_enet_interrupt(int irq, void * dev_id)
 {
 	struct	net_device *dev = dev_id;
 	volatile struct	fcc_enet_private *cep;
@@ -1563,7 +1563,7 @@
 #ifdef PHY_INTERRUPT
 /* This interrupt occurs when the PHY detects a link change. */
 static irqreturn_t
-mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+mii_link_interrupt(int irq, void * dev_id)
 {
 	struct	net_device *dev = dev_id;
 	struct fcc_enet_private *fep = dev->priv;
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 9b3ace2..3b23bcb 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -47,12 +47,12 @@
 /* CPM interrupt vector functions.
 */
 struct	cpm_action {
-	void	(*handler)(void *, struct pt_regs * regs);
+	void	(*handler)(void *);
 	void	*dev_id;
 };
 static	struct	cpm_action cpm_vecs[CPMVEC_NR];
-static	irqreturn_t cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
-static	irqreturn_t cpm_error_interrupt(int irq, void *dev, struct pt_regs * regs);
+static	irqreturn_t cpm_interrupt(int irq, void * dev);
+static	irqreturn_t cpm_error_interrupt(int irq, void *dev);
 static	void	alloc_host_memory(void);
 /* Define a table of names to identify CPM interrupt handlers in
  * /proc/interrupts.
@@ -205,7 +205,7 @@
  * Get the CPM interrupt vector.
  */
 int
-cpm_get_irq(struct pt_regs *regs)
+cpm_get_irq(void)
 {
 	int cpm_vec;
 
@@ -222,7 +222,7 @@
 /* CPM interrupt controller cascade interrupt.
 */
 static	irqreturn_t
-cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
+cpm_interrupt(int irq, void * dev)
 {
 	/* This interrupt handler never actually gets called.  It is
 	 * installed only to unmask the CPM cascade interrupt in the SIU
@@ -237,7 +237,7 @@
  * tests in the interrupt handler.
  */
 static	irqreturn_t
-cpm_error_interrupt(int irq, void *dev, struct pt_regs *regs)
+cpm_error_interrupt(int irq, void *dev)
 {
 	return IRQ_HANDLED;
 }
@@ -246,11 +246,11 @@
  * request_irq() to the handler prototype required by cpm_install_handler().
  */
 static irqreturn_t
-cpm_handler_helper(int irq, void *dev_id, struct pt_regs *regs)
+cpm_handler_helper(int irq, void *dev_id)
 {
 	int cpm_vec = irq - CPM_IRQ_OFFSET;
 
-	(*cpm_vecs[cpm_vec].handler)(dev_id, regs);
+	(*cpm_vecs[cpm_vec].handler)(dev_id);
 
 	return IRQ_HANDLED;
 }
@@ -267,8 +267,7 @@
  * request_irq() or cpm_install_handler().
  */
 void
-cpm_install_handler(int cpm_vec, void (*handler)(void *, struct pt_regs *regs),
-		    void *dev_id)
+cpm_install_handler(int cpm_vec, void (*handler)(void *), void *dev_id)
 {
 	int err;
 
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index f5f300f..959d31c 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -331,7 +331,7 @@
 static int CS_SetVolume(int volume);
 static void cs4218_tdm_tx_intr(void *devid);
 static void cs4218_tdm_rx_intr(void *devid);
-static void cs4218_intr(void *devid, struct pt_regs *regs);
+static void cs4218_intr(void *devid);
 static int cs_get_volume(uint reg);
 static int cs_volume_setter(int volume, int mute);
 static int cs_get_gain(uint reg);
@@ -2646,7 +2646,7 @@
  * full duplex operation.
  */
 static void
-cs4218_intr(void *dev_id, struct pt_regs *regs)
+cs4218_intr(void *dev_id)
 {
 	volatile smc_t	*sp;
 	volatile cpm8xx_t	*cp;
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index a695375..b23c45b 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -149,7 +149,7 @@
 static int scc_enet_open(struct net_device *dev);
 static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int scc_enet_rx(struct net_device *dev);
-static void scc_enet_interrupt(void *dev_id, struct pt_regs *regs);
+static void scc_enet_interrupt(void *dev_id);
 static int scc_enet_close(struct net_device *dev);
 static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -305,7 +305,7 @@
  * This is called from the CPM handler, not the MPC core interrupt.
  */
 static void
-scc_enet_interrupt(void *dev_id, struct pt_regs *regs)
+scc_enet_interrupt(void *dev_id)
 {
 	struct	net_device *dev = dev_id;
 	volatile struct	scc_enet_private *cep;
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index 8b6295b..2f9fa9e 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -198,8 +198,7 @@
 #ifdef	CONFIG_USE_MDIO
 static void fec_enet_mii(struct net_device *dev);
 #endif	/* CONFIG_USE_MDIO */
-static irqreturn_t fec_enet_interrupt(int irq, void * dev_id,
-		       					struct pt_regs * regs);
+static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
 #ifdef CONFIG_FEC_PACKETHOOK
 static void  fec_enet_tx(struct net_device *dev, __u32 regval);
 static void  fec_enet_rx(struct net_device *dev, __u32 regval);
@@ -472,7 +471,7 @@
  * This is called from the MPC core interrupt.
  */
 static	irqreturn_t
-fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+fec_enet_interrupt(int irq, void * dev_id)
 {
 	struct	net_device *dev = dev_id;
 	volatile fec_t	*fecp;
@@ -1408,7 +1407,7 @@
 #ifdef CONFIG_RPXCLASSIC
 void mii_link_interrupt(void *dev_id)
 #else
-irqreturn_t mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+irqreturn_t mii_link_interrupt(int irq, void * dev_id)
 #endif
 {
 #ifdef	CONFIG_USE_MDIO
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index ca57e89..96a5597 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -84,7 +84,7 @@
 /*
  * Common functions
  */
-void smp_message_recv(int msg, struct pt_regs *regs)
+void smp_message_recv(int msg)
 {
 	atomic_inc(&ipi_recv);
 
@@ -100,7 +100,7 @@
 		break;
 #ifdef CONFIG_XMON
 	case PPC_MSG_XMON_BREAK:
-		xmon(regs);
+		xmon(get_irq_regs());
 		break;
 #endif /* CONFIG_XMON */
 	default:
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 1873886..18ee851 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -62,6 +62,7 @@
 #include <asm/cache.h>
 #include <asm/8xx_immap.h>
 #include <asm/machdep.h>
+#include <asm/irq_regs.h>
 
 #include <asm/time.h>
 
@@ -129,6 +130,7 @@
  */
 void timer_interrupt(struct pt_regs * regs)
 {
+	struct pt_regs *old_regs;
 	int next_dec;
 	unsigned long cpu = smp_processor_id();
 	unsigned jiffy_stamp = last_jiffy_stamp(cpu);
@@ -137,12 +139,13 @@
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 
 	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
 		
-		profile_tick(CPU_PROFILING, regs);
+		profile_tick(CPU_PROFILING);
 		update_process_times(user_mode(regs));
 
 	  	if (smp_processor_id())
@@ -188,6 +191,7 @@
 		ppc_md.heartbeat();
 
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 /*
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 4102000..c374e53 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -374,11 +374,12 @@
 	end_pfn = start_pfn + (total_memory >> PAGE_SHIFT);
 	add_active_range(0, start_pfn, end_pfn);
 
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 #ifdef CONFIG_HIGHMEM
-	max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
-	max_zone_pfns[1] = total_memory >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_HIGHMEM] = total_memory >> PAGE_SHIFT;
 #else
-	max_zone_pfns[0] = total_memory >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_DMA] = total_memory >> PAGE_SHIFT;
 #endif /* CONFIG_HIGHMEM */
 	free_area_init_nodes(max_zone_pfns);
 }
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 94badaf..14ecec7 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -211,10 +211,10 @@
 #endif
 }
 
-static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpm2_cascade(int irq, void *dev_id)
 {
-	while ((irq = cpm2_get_irq(regs)) >= 0)
-		__do_IRQ(irq, regs);
+	while ((irq = cpm2_get_irq()) >= 0)
+		__do_IRQ(irq);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 7520458..5ce0f69 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -127,10 +127,10 @@
 }
 
 #ifdef CONFIG_CPM2
-static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpm2_cascade(int irq, void *dev_id)
 {
-	while((irq = cpm2_get_irq(regs)) >= 0)
-		__do_IRQ(irq, regs);
+	while((irq = cpm2_get_irq()) >= 0)
+		__do_IRQ(irq);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 495aa79..4bb18ab 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -156,10 +156,10 @@
 	printk ("bi_immr_base = %8.8lx\n", binfo->bi_immr_base);
 }
 
-static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpm2_cascade(int irq, void *dev_id)
 {
-	while ((irq = cpm2_get_irq(regs)) >= 0)
-		__do_IRQ(irq, regs);
+	while ((irq = cpm2_get_irq()) >= 0)
+		__do_IRQ(irq);
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c
index 189ed41..dd45f2e 100644
--- a/arch/ppc/platforms/85xx/tqm85xx.c
+++ b/arch/ppc/platforms/85xx/tqm85xx.c
@@ -181,10 +181,10 @@
 }
 
 #ifdef CONFIG_MPC8560
-static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpm2_cascade(int irq, void *dev_id)
 {
-	while ((irq = cpm2_get_irq(regs)) >= 0)
-		__do_IRQ(irq, regs);
+	while ((irq = cpm2_get_irq()) >= 0)
+		__do_IRQ(irq);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c
index 1d034ea..063274d 100644
--- a/arch/ppc/platforms/apus_setup.c
+++ b/arch/ppc/platforms/apus_setup.c
@@ -492,7 +492,7 @@
 
 static unsigned char last_ipl[8];
 
-int apus_get_irq(struct pt_regs* regs)
+int apus_get_irq(void)
 {
 	unsigned char ipl_emu, mask;
 	unsigned int level;
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
index e0f112a..d809e17 100644
--- a/arch/ppc/platforms/hdpu.c
+++ b/arch/ppc/platforms/hdpu.c
@@ -659,8 +659,7 @@
 char hdpu_smp0[] = "SMP Cpu #0";
 char hdpu_smp1[] = "SMP Cpu #1";
 
-static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id,
-					     struct pt_regs *regs)
+static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id)
 {
 	volatile unsigned int doorbell;
 
@@ -670,22 +669,21 @@
 	mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell);
 
 	if (doorbell & 1) {
-		smp_message_recv(0, regs);
+		smp_message_recv(0);
 	}
 	if (doorbell & 2) {
-		smp_message_recv(1, regs);
+		smp_message_recv(1);
 	}
 	if (doorbell & 4) {
-		smp_message_recv(2, regs);
+		smp_message_recv(2);
 	}
 	if (doorbell & 8) {
-		smp_message_recv(3, regs);
+		smp_message_recv(3);
 	}
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id,
-					     struct pt_regs *regs)
+static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id)
 {
 	volatile unsigned int doorbell;
 
@@ -695,16 +693,16 @@
 	mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell);
 
 	if (doorbell & 1) {
-		smp_message_recv(0, regs);
+		smp_message_recv(0);
 	}
 	if (doorbell & 2) {
-		smp_message_recv(1, regs);
+		smp_message_recv(1);
 	}
 	if (doorbell & 4) {
-		smp_message_recv(2, regs);
+		smp_message_recv(2);
 	}
 	if (doorbell & 8) {
-		smp_message_recv(3, regs);
+		smp_message_recv(3);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index d7b3a6a..1f9ea36 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -196,7 +196,7 @@
 	bd_t* bi = (void*)__res;
 	int fs_no = fsid_fcc1+pdev->id-1;
 
-	if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) {
+	if(fs_no >= ARRAY_SIZE(mpc82xx_enet_pdata)) {
 		return;
 	}
 
@@ -222,7 +222,7 @@
 	int id = fs_uart_id_scc2fsid(idx);
 
 	/* no need to alter anything if console */
-	if ((id <= num) && (!pdev->dev.platform_data)) {
+	if ((id < num) && (!pdev->dev.platform_data)) {
 		pinfo = &mpc8272_uart_pdata[id];
 		pinfo->uart_clk = bd->bi_intfreq;
 		pdev->dev.platform_data = pinfo;
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index 5f130dc..e95d2c1 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -259,7 +259,7 @@
 	/* Get pointer to Communication Processor */
 	cp = cpmp;
 
-	if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+	if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) {
 		printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
 		return;
 	}
@@ -305,7 +305,7 @@
 	int id = fs_uart_id_smc2fsid(idx);
 
 	/* no need to alter anything if console */
-	if ((id <= num) && (!pdev->dev.platform_data)) {
+	if ((id < num) && (!pdev->dev.platform_data)) {
 		pinfo = &mpc866_uart_pdata[id];
 		pinfo->uart_clk = bd->bi_intfreq;
 		pdev->dev.platform_data = pinfo;
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index 0229314..f8161f3 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -263,7 +263,7 @@
 	char *e;
 	int i;
 
-	if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+	if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) {
 		printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
 		return;
 	}
@@ -371,7 +371,7 @@
 	int id = fs_uart_id_smc2fsid(idx);
 
 	/* no need to alter anything if console */
-	if ((id <= num) && (!pdev->dev.platform_data)) {
+	if ((id < num) && (!pdev->dev.platform_data)) {
 		pinfo = &mpc885_uart_pdata[id];
 		pinfo->uart_clk = bd->bi_intfreq;
 		pdev->dev.platform_data = pinfo;
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
index 3bb530a..13d70ab 100644
--- a/arch/ppc/platforms/radstone_ppc7d.c
+++ b/arch/ppc/platforms/radstone_ppc7d.c
@@ -451,11 +451,11 @@
  * Interrupt stuff
  *****************************************************************************/
 
-static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id)
 {
 	u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
 	if (temp & (1 << 28)) {
-		i8259_irq(regs);
+		i8259_irq();
 		mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 28)));
 		return IRQ_HANDLED;
 	}
@@ -536,13 +536,13 @@
 	return irq;
 }
 
-static int ppc7d_get_irq(struct pt_regs *regs)
+static int ppc7d_get_irq(void)
 {
 	int irq;
 
-	irq = mv64360_get_irq(regs);
+	irq = mv64360_get_irq();
 	if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28))
-		irq = i8259_irq(regs);
+		irq = i8259_irq();
 	return irq;
 }
 
diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
index 60b769c..cc0935c 100644
--- a/arch/ppc/platforms/sbc82xx.c
+++ b/arch/ppc/platforms/sbc82xx.c
@@ -121,7 +121,7 @@
 	.end = sbc82xx_i8259_end_irq,
 };
 
-static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id)
 {
 	spin_lock(&sbc82xx_i8259_lock);
 
@@ -139,7 +139,7 @@
 			return IRQ_HANDLED;
 		}
 	}
-	__do_IRQ(NR_SIU_INTS + irq, regs);
+	__do_IRQ(NR_SIU_INTS + irq);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h
index 0a8a5d8..987e9aa 100644
--- a/arch/ppc/syslib/cpc700.h
+++ b/arch/ppc/syslib/cpc700.h
@@ -91,6 +91,6 @@
 extern unsigned int cpc700_irq_assigns[32][2];
 
 extern void __init cpc700_init_IRQ(void);
-extern int cpc700_get_irq(struct pt_regs *);
+extern int cpc700_get_irq(void);
 
 #endif	/* __PPC_SYSLIB_CPC700_H__ */
diff --git a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c
index 172aa21..d48e8f4 100644
--- a/arch/ppc/syslib/cpc700_pic.c
+++ b/arch/ppc/syslib/cpc700_pic.c
@@ -158,7 +158,7 @@
  * Find the highest IRQ that generating an interrupt, if any.
  */
 int
-cpc700_get_irq(struct pt_regs *regs)
+cpc700_get_irq(void)
 {
 	int irq = 0;
 	u_int irq_status, irq_test = 1;
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index c0fee0b..fb2d584 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -123,7 +123,7 @@
 	.end = cpm2_end_irq,
 };
 
-int cpm2_get_irq(struct pt_regs *regs)
+int cpm2_get_irq(void)
 {
 	int irq;
         unsigned long bits;
diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
index 97cab8f..4673393 100644
--- a/arch/ppc/syslib/cpm2_pic.h
+++ b/arch/ppc/syslib/cpm2_pic.h
@@ -1,7 +1,7 @@
 #ifndef _PPC_KERNEL_CPM2_H
 #define _PPC_KERNEL_CPM2_H
 
-extern int cpm2_get_irq(struct pt_regs *regs);
+extern int cpm2_get_irq(void);
 
 extern void cpm2_init_IRQ(void);
 
diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c
index 7fd550a..e84d432 100644
--- a/arch/ppc/syslib/gt64260_pic.c
+++ b/arch/ppc/syslib/gt64260_pic.c
@@ -110,9 +110,6 @@
  *  This function returns the lowest interrupt number of all interrupts that
  *  are currently asserted.
  *
- * Input Variable(s):
- *  struct pt_regs*	not used
- *
  * Output Variable(s):
  *  None.
  *
@@ -120,7 +117,7 @@
  *  int	<interrupt number> or -2 (bogus interrupt)
  */
 int
-gt64260_get_irq(struct pt_regs *regs)
+gt64260_get_irq(void)
 {
 	int irq;
 	int irq_gpp;
@@ -229,7 +226,7 @@
 }
 
 static irqreturn_t
-gt64260_cpu_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+gt64260_cpu_error_int_handler(int irq, void *dev_id)
 {
 	printk(KERN_ERR "gt64260_cpu_error_int_handler: %s 0x%08x\n",
 		"Error on CPU interface - Cause regiser",
@@ -250,7 +247,7 @@
 }
 
 static irqreturn_t
-gt64260_pci_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+gt64260_pci_error_int_handler(int irq, void *dev_id)
 {
 	u32 val;
 	unsigned int pci_bus = (unsigned int)dev_id;
diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
index eb35353..a43dda5 100644
--- a/arch/ppc/syslib/i8259.c
+++ b/arch/ppc/syslib/i8259.c
@@ -28,7 +28,7 @@
  * which is called.  It should be noted that polling is broken on some
  * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
  */
-int i8259_irq(struct pt_regs *regs)
+int i8259_irq(void)
 {
 	int irq;
 
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
index 4b77e6c..6ad52f4 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -119,7 +119,7 @@
 	return mfdcr(DCRN_L2C0_DATA);
 }
 
-static irqreturn_t l2c_error_handler(int irq, void* dev, struct pt_regs* regs)
+static irqreturn_t l2c_error_handler(int irq, void* dev)
 {
 	u32 sr = mfdcr(DCRN_L2C0_SR);
 	if (sr & L2C_SR_CPE){
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
index 46801f5..10659c2 100644
--- a/arch/ppc/syslib/ipic.c
+++ b/arch/ppc/syslib/ipic.c
@@ -601,7 +601,7 @@
 }
 
 /* Return an interrupt vector or -1 if no interrupt is pending. */
-int ipic_get_irq(struct pt_regs *regs)
+int ipic_get_irq(void)
 {
 	int irq;
 
diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
index d3fa264..e3b586b 100644
--- a/arch/ppc/syslib/m82xx_pci.c
+++ b/arch/ppc/syslib/m82xx_pci.c
@@ -117,7 +117,7 @@
 };
 
 static irqreturn_t
-pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
+pq2pci_irq_demux(int irq, void *dev_id)
 {
 	unsigned long stat, mask, pend;
 	int bit;
@@ -130,7 +130,7 @@
 			break;
 		for (bit = 0; pend != 0; ++bit, pend <<= 1) {
 			if (pend & 0x80000000)
-				__do_IRQ(NR_CPM_INTS + bit, regs);
+				__do_IRQ(NR_CPM_INTS + bit);
 		}
 	}
 
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 54303a7..d8d299b 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -169,7 +169,7 @@
 }
 
 /* A place holder for time base interrupts, if they are ever enabled. */
-irqreturn_t timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
+irqreturn_t timebase_interrupt(int irq, void * dev)
 {
 	printk ("timebase_interrupt()\n");
 
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
index ac11d7b..fffac8c 100644
--- a/arch/ppc/syslib/m8xx_wdt.c
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -21,7 +21,7 @@
 static int wdt_timeout;
 int m8xx_has_internal_rtc = 0;
 
-static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t m8xx_wdt_interrupt(int, void *);
 static struct irqaction m8xx_wdt_irqaction = {
 	.handler = m8xx_wdt_interrupt,
 	.name = "watchdog",
@@ -35,7 +35,7 @@
 	out_be16(&imap->im_siu_conf.sc_swsr, 0xaa39);	/* write magic2 */
 }
 
-static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev)
 {
 	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
 
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
index 6425b5c..af35a31 100644
--- a/arch/ppc/syslib/mpc52xx_pic.c
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -220,7 +220,7 @@
 }
 
 int
-mpc52xx_get_irq(struct pt_regs *regs)
+mpc52xx_get_irq(void)
 {
 	u32 status;
 	int irq = -1;
diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
index 3f6d162..4b7a333 100644
--- a/arch/ppc/syslib/mv64360_pic.c
+++ b/arch/ppc/syslib/mv64360_pic.c
@@ -55,10 +55,9 @@
 
 static void mv64360_unmask_irq(unsigned int);
 static void mv64360_mask_irq(unsigned int);
-static irqreturn_t mv64360_cpu_error_int_handler(int, void *, struct pt_regs *);
-static irqreturn_t mv64360_sram_error_int_handler(int, void *,
-						  struct pt_regs *);
-static irqreturn_t mv64360_pci_error_int_handler(int, void *, struct pt_regs *);
+static irqreturn_t mv64360_cpu_error_int_handler(int, void *);
+static irqreturn_t mv64360_sram_error_int_handler(int, void *);
+static irqreturn_t mv64360_pci_error_int_handler(int, void *);
 
 /* ========================== local declarations =========================== */
 
@@ -131,9 +130,6 @@
  * This function returns the lowest interrupt number of all interrupts that
  * are currently asserted.
  *
- * Input Variable(s):
- *  struct pt_regs*	not used
- *
  * Output Variable(s):
  *  None.
  *
@@ -142,7 +138,7 @@
  *
  */
 int
-mv64360_get_irq(struct pt_regs *regs)
+mv64360_get_irq(void)
 {
 	int irq;
 	int irq_gpp;
@@ -283,7 +279,7 @@
 }
 
 static irqreturn_t
-mv64360_cpu_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+mv64360_cpu_error_int_handler(int irq, void *dev_id)
 {
 	printk(KERN_ERR "mv64360_cpu_error_int_handler: %s 0x%08x\n",
 		"Error on CPU interface - Cause regiser",
@@ -304,7 +300,7 @@
 }
 
 static irqreturn_t
-mv64360_sram_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+mv64360_sram_error_int_handler(int irq, void *dev_id)
 {
 	printk(KERN_ERR "mv64360_sram_error_int_handler: %s 0x%08x\n",
 		"Error in internal SRAM - Cause register",
@@ -325,7 +321,7 @@
 }
 
 static irqreturn_t
-mv64360_pci_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+mv64360_pci_error_int_handler(int irq, void *dev_id)
 {
 	u32 val;
 	unsigned int pci_bus = (unsigned int)dev_id;
@@ -380,7 +376,7 @@
 	/* Clear old errors and register CPU interface error intr handler */
 	mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0);
 	if ((rc = request_irq(MV64x60_IRQ_CPU_ERR + mv64360_irq_base,
-		mv64360_cpu_error_int_handler, IRQF_DISABLED, CPU_INTR_STR, 0)))
+		mv64360_cpu_error_int_handler, IRQF_DISABLED, CPU_INTR_STR, NULL)))
 		printk(KERN_WARNING "Can't register cpu error handler: %d", rc);
 
 	mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0);
@@ -389,7 +385,7 @@
 	/* Clear old errors and register internal SRAM error intr handler */
 	mv64x60_write(&bh, MV64360_SRAM_ERR_CAUSE, 0);
 	if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR + mv64360_irq_base,
-		mv64360_sram_error_int_handler,IRQF_DISABLED,SRAM_INTR_STR, 0)))
+		mv64360_sram_error_int_handler,IRQF_DISABLED,SRAM_INTR_STR, NULL)))
 		printk(KERN_WARNING "Can't register SRAM error handler: %d",rc);
 
 	/* Clear old errors and register PCI 0 error intr handler */
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index aa0b957..18ec947 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -45,7 +45,7 @@
 static int open_pic_irq_offset;
 static volatile OpenPIC_Source __iomem *ISR[NR_IRQS];
 static int openpic_cascade_irq = -1;
-static int (*openpic_cascade_fn)(struct pt_regs *);
+static int (*openpic_cascade_fn)(void);
 
 /* Global Operations */
 static void openpic_disable_8259_pass_through(void);
@@ -54,7 +54,7 @@
 #ifdef CONFIG_SMP
 /* Interprocessor Interrupts */
 static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *);
+static irqreturn_t openpic_ipi_action(int cpl, void *dev_id);
 #endif
 
 /* Timer Interrupts */
@@ -700,7 +700,7 @@
 
 void __init
 openpic_hookup_cascade(u_int irq, char *name,
-	int (*cascade_fn)(struct pt_regs *))
+	int (*cascade_fn)(void))
 {
 	openpic_cascade_irq = irq;
 	openpic_cascade_fn = cascade_fn;
@@ -857,16 +857,16 @@
 {
 }
 
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t openpic_ipi_action(int cpl, void *dev_id)
 {
-	smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset, regs);
+	smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset);
 	return IRQ_HANDLED;
 }
 
 #endif /* CONFIG_SMP */
 
 int
-openpic_get_irq(struct pt_regs *regs)
+openpic_get_irq(void)
 {
 	int irq = openpic_irq();
 
@@ -876,7 +876,7 @@
 	 * This should move to irq.c eventually.  -- paulus
 	 */
 	if (irq == openpic_cascade_irq && openpic_cascade_fn != NULL) {
-		int cirq = openpic_cascade_fn(regs);
+		int cirq = openpic_cascade_fn();
 
 		/* Allow for the cascade being shared with other devices */
 		if (cirq != -1) {
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index e1ff971..d585207 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -529,7 +529,7 @@
 }
 
 int
-openpic2_get_irq(struct pt_regs *regs)
+openpic2_get_irq(void)
 {
 	int irq = openpic2_irq();
 
diff --git a/arch/ppc/syslib/ppc403_pic.c b/arch/ppc/syslib/ppc403_pic.c
index 1584c8b..607ebd1 100644
--- a/arch/ppc/syslib/ppc403_pic.c
+++ b/arch/ppc/syslib/ppc403_pic.c
@@ -42,7 +42,7 @@
 };
 
 int
-ppc403_pic_get_irq(struct pt_regs *regs)
+ppc403_pic_get_irq(void)
 {
 	int irq;
 	unsigned long bits;
diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
index 745685df5..ee0da4b 100644
--- a/arch/ppc/syslib/ppc4xx_pic.c
+++ b/arch/ppc/syslib/ppc4xx_pic.c
@@ -96,7 +96,7 @@
 UIC_HANDLERS(2);
 UIC_HANDLERS(3);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
 	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
 	if (uic0 & UIC0_UIC1NC)
@@ -125,7 +125,7 @@
 UIC_HANDLERS(1);
 UIC_HANDLERS(2);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
 	u32 uicb = mfdcr(DCRN_UIC_MSR(UICB));
 	if (uicb & UICB_UIC0NC)
@@ -158,7 +158,7 @@
 UIC_HANDLERS(0);
 UIC_HANDLERS(1);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
 	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
 	if (uic0 & UIC0_UIC1NC)
@@ -179,7 +179,7 @@
 #define ACK_UIC0_PARENT
 UIC_HANDLERS(0);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
 	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
 	return uic0 ? 32 - ffs(uic0) : -1;
diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c
index d9b471b..05b0e94 100644
--- a/arch/ppc/syslib/ppc85xx_rio.c
+++ b/arch/ppc/syslib/ppc85xx_rio.c
@@ -349,13 +349,12 @@
  * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler
  * @irq: Linux interrupt number
  * @dev_instance: Pointer to interrupt-specific data
- * @regs: Register context
  *
  * Handles outbound message interrupts. Executes a register outbound
  * mailbox event handler and acks the interrupt occurence.
  */
 static irqreturn_t
-mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs)
+mpc85xx_rio_tx_handler(int irq, void *dev_instance)
 {
 	int osr;
 	struct rio_mport *port = (struct rio_mport *)dev_instance;
@@ -517,13 +516,12 @@
  * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler
  * @irq: Linux interrupt number
  * @dev_instance: Pointer to interrupt-specific data
- * @regs: Register context
  *
  * Handles inbound message interrupts. Executes a registered inbound
  * mailbox event handler and acks the interrupt occurence.
  */
 static irqreturn_t
-mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs)
+mpc85xx_rio_rx_handler(int irq, void *dev_instance)
 {
 	int isr;
 	struct rio_mport *port = (struct rio_mport *)dev_instance;
@@ -736,13 +734,12 @@
  * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler
  * @irq: Linux interrupt number
  * @dev_instance: Pointer to interrupt-specific data
- * @regs: Register context
  *
  * Handles doorbell interrupts. Parses a list of registered
  * doorbell event handlers and executes a matching event handler.
  */
 static irqreturn_t
-mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs)
+mpc85xx_rio_dbell_handler(int irq, void *dev_instance)
 {
 	int dsr;
 	struct rio_mport *port = (struct rio_mport *)dev_instance;
diff --git a/arch/ppc/syslib/ppc8xx_pic.c b/arch/ppc/syslib/ppc8xx_pic.c
index d6c25fe..e8619c75 100644
--- a/arch/ppc/syslib/ppc8xx_pic.c
+++ b/arch/ppc/syslib/ppc8xx_pic.c
@@ -10,7 +10,7 @@
 #include <asm/mpc8xx.h>
 #include "ppc8xx_pic.h"
 
-extern int cpm_get_irq(struct pt_regs *regs);
+extern int cpm_get_irq(void);
 
 /* The 8xx internal interrupt controller.  It is usually
  * the only interrupt controller.  Some boards, like the MBX and
@@ -96,7 +96,7 @@
 	 * get back SIU_LEVEL7.  In this case, return -1
 	 */
         if (irq == CPM_INTERRUPT)
-        	irq = CPM_IRQ_OFFSET + cpm_get_irq(regs);
+        	irq = CPM_IRQ_OFFSET + cpm_get_irq();
 #if defined(CONFIG_PCI)
 	else if (irq == ISA_BRIDGE_INT) {
 		int isa_irq;
diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c
index 39a93dc..6fd4cdb 100644
--- a/arch/ppc/syslib/xilinx_pic.c
+++ b/arch/ppc/syslib/xilinx_pic.c
@@ -86,7 +86,7 @@
 };
 
 int
-xilinx_pic_get_irq(struct pt_regs *regs)
+xilinx_pic_get_irq(void)
 {
 	int irq;
 
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 51c2dfe..608193c 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -30,6 +30,9 @@
 	bool
 	default y
 
+config GENERIC_TIME
+	def_bool y
+
 config GENERIC_BUST_SPINLOCK
 	bool
 
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 2b1e6c9..45c9fa7 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -109,7 +109,7 @@
  *
  * schedule work and reschedule timer
  */
-static void appldata_timer_function(unsigned long data, struct pt_regs *regs)
+static void appldata_timer_function(unsigned long data)
 {
 	P_DEBUG("   -= Timer =-\n");
 	P_DEBUG("CPU: %i, expire_count: %i\n", smp_processor_id(),
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index b6cad75..c313e9a 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Wed Oct  4 19:45:46 2006
+# Linux kernel version: 2.6.19-rc2
+# Wed Oct 18 17:11:10 2006
 #
 CONFIG_MMU=y
 CONFIG_LOCKDEP_SUPPORT=y
@@ -9,6 +9,7 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
 CONFIG_S390=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -210,6 +211,7 @@
 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_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
@@ -527,6 +529,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
@@ -645,10 +648,6 @@
 # CONFIG_NLS is not set
 
 #
-# Distributed Lock Manager
-#
-
-#
 # Instrumentation Support
 #
 
@@ -668,7 +667,6 @@
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
@@ -689,6 +687,7 @@
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
+CONFIG_HEADERS_CHECK=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index e15e148..2001767 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -295,6 +295,7 @@
  *
  * This is really horribly ugly.
  */
+#ifdef CONFIG_SYSVIPC
 asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
 {
 	if (call >> 16)		/* hack for backward compatibility */
@@ -338,6 +339,7 @@
 
 	return -ENOSYS;
 }
+#endif
 
 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
 {
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index c1b3835..4faf96f 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -16,6 +16,7 @@
 
 #include <asm/lowcore.h>
 #include <asm/s390_ext.h>
+#include <asm/irq_regs.h>
 #include <asm/irq.h>
 
 /*
@@ -114,7 +115,9 @@
 {
         ext_int_info_t *p;
         int index;
+	struct pt_regs *old_regs;
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 	asm volatile ("mc 0,0");
 	if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
@@ -122,18 +125,18 @@
 		 * Make sure that the i/o interrupt did not "overtake"
 		 * the last HZ timer interrupt.
 		 */
-		account_ticks(regs);
+		account_ticks();
 	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(regs, code);
+				p->handler(code);
 		}
 	}
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 EXPORT_SYMBOL(register_external_interrupt);
 EXPORT_SYMBOL(unregister_external_interrupt);
-
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 9f19e83..90b5ef5 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -51,4 +51,3 @@
 EXPORT_SYMBOL(console_mode);
 EXPORT_SYMBOL(console_devno);
 EXPORT_SYMBOL(console_irq);
-EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index a8e6199..6282224 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -339,7 +339,7 @@
  * cpus are handled.
  */
 
-void do_ext_call_interrupt(struct pt_regs *regs, __u16 code)
+void do_ext_call_interrupt(__u16 code)
 {
         unsigned long bits;
 
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index d9428a0..0d14a47 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -62,27 +62,26 @@
 void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
 {
 	register unsigned long sp asm ("15");
-	unsigned long orig_sp;
+	unsigned long orig_sp, new_sp;
 
-	sp &= PSW_ADDR_INSN;
-	orig_sp = sp;
+	orig_sp = sp & PSW_ADDR_INSN;
 
-	sp = save_context_stack(trace, &trace->skip, sp,
+	new_sp = save_context_stack(trace, &trace->skip, orig_sp,
 				S390_lowcore.panic_stack - PAGE_SIZE,
 				S390_lowcore.panic_stack);
-	if ((sp != orig_sp) && !trace->all_contexts)
+	if ((new_sp != orig_sp) && !trace->all_contexts)
 		return;
-	sp = save_context_stack(trace, &trace->skip, sp,
+	new_sp = save_context_stack(trace, &trace->skip, new_sp,
 				S390_lowcore.async_stack - ASYNC_SIZE,
 				S390_lowcore.async_stack);
-	if ((sp != orig_sp) && !trace->all_contexts)
+	if ((new_sp != orig_sp) && !trace->all_contexts)
 		return;
 	if (task)
-		save_context_stack(trace, &trace->skip, sp,
+		save_context_stack(trace, &trace->skip, new_sp,
 				   (unsigned long) task_stack_page(task),
 				   (unsigned long) task_stack_page(task) + THREAD_SIZE);
 	else
-		save_context_stack(trace, &trace->skip, sp,
+		save_context_stack(trace, &trace->skip, new_sp,
 				   S390_lowcore.thread_info,
 				   S390_lowcore.thread_info + THREAD_SIZE);
 	return;
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index e59baec..a4ceae3 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -320,3 +320,4 @@
 SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper)
 NI_SYSCALL							/* 310 sys_move_pages */
 SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
+SYSCALL(sys_epoll_pwait,sys_epoll_pwait,sys_ni_syscall)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 4bf66cc..6cceed4 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -28,12 +28,14 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/notifier.h>
+#include <linux/clocksource.h>
 
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
 #include <asm/div64.h>
 #include <asm/irq.h>
+#include <asm/irq_regs.h>
 #include <asm/timer.h>
 
 /* change this if you have some constant time drift */
@@ -81,78 +83,10 @@
 	xtime->tv_nsec = ((todval * 1000) >> 12);
 }
 
-static inline unsigned long do_gettimeoffset(void) 
-{
-	__u64 now;
-
-	now = (get_clock() - jiffies_timer_cc) >> 12;
-	now -= (__u64) jiffies * USECS_PER_JIFFY;
-	return (unsigned long) now;
-}
-
-/*
- * This version of gettimeofday has microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long flags;
-	unsigned long seq;
-	unsigned long usec, sec;
-
-	do {
-		seq = read_seqbegin_irqsave(&xtime_lock, flags);
-
-		sec = xtime.tv_sec;
-		usec = xtime.tv_nsec / 1000 + do_gettimeoffset();
-	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	/* This is revolting. We need to set the xtime.tv_nsec
-	 * correctly. However, the value in this location is
-	 * is value at the last tick.
-	 * Discover what correction gettimeofday
-	 * would have done, and then undo it!
-	 */
-	nsec -= do_gettimeoffset() * 1000;
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-
 #ifdef CONFIG_PROFILING
-#define s390_do_profile(regs)	profile_tick(CPU_PROFILING, regs)
+#define s390_do_profile()	profile_tick(CPU_PROFILING)
 #else
-#define s390_do_profile(regs)  do { ; } while(0)
+#define s390_do_profile()	do { ; } while(0)
 #endif /* CONFIG_PROFILING */
 
 
@@ -160,7 +94,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-void account_ticks(struct pt_regs *regs)
+void account_ticks(void)
 {
 	__u64 tmp;
 	__u32 ticks;
@@ -221,10 +155,10 @@
 	account_tick_vtime(current);
 #else
 	while (ticks--)
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 
-	s390_do_profile(regs);
+	s390_do_profile();
 }
 
 #ifdef CONFIG_NO_IDLE_HZ
@@ -285,9 +219,11 @@
  */
 static inline void start_hz_timer(void)
 {
+	BUG_ON(!in_interrupt());
+
 	if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
 		return;
-	account_ticks(task_pt_regs(current));
+	account_ticks();
 	cpu_clear(smp_processor_id(), nohz_cpu_mask);
 }
 
@@ -337,6 +273,22 @@
 
 extern void vtime_init(void);
 
+static cycle_t read_tod_clock(void)
+{
+	return get_clock();
+}
+
+static struct clocksource clocksource_tod = {
+	.name		= "tod",
+	.rating		= 100,
+	.read		= read_tod_clock,
+	.mask		= -1ULL,
+	.mult		= 1000,
+	.shift		= 12,
+	.is_continuous	= 1,
+};
+
+
 /*
  * Initialize the TOD clock and the CPU timer of
  * the boot cpu.
@@ -381,6 +333,9 @@
 					      &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();
 
 #ifdef CONFIG_NO_IDLE_HZ
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 3eb4fab..66375a5 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -61,7 +61,7 @@
 #ifdef CONFIG_PFAULT
 extern int pfault_init(void);
 extern void pfault_fini(void);
-extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
+extern void pfault_interrupt(__u16 error_code);
 static ext_int_info_t ext_int_pfault;
 #endif
 extern pgm_check_handler_t do_monitor_call;
@@ -474,7 +474,7 @@
 			signal = math_emu_b3(opcode, regs);
                 } else if (opcode[0] == 0xed) {
 			get_user(*((__u32 *) (opcode+2)),
-				 (__u32 *)(location+1));
+				 (__u32 __user *)(location+1));
 			signal = math_emu_ed(opcode, regs);
 		} else if (*((__u16 *) opcode) == 0xb299) {
 			get_user(*((__u16 *) (opcode+2)), location+1);
@@ -499,7 +499,7 @@
 		info.si_signo = signal;
 		info.si_errno = 0;
 		info.si_code = SEGV_MAPERR;
-		info.si_addr = (void *) location;
+		info.si_addr = (void __user *) location;
 		do_trap(interruption_code, signal,
 			"user address fault", regs, &info);
 	} else
@@ -520,10 +520,10 @@
 specification_exception(struct pt_regs * regs, long interruption_code)
 {
         __u8 opcode[6];
-	__u16 *location = NULL;
+	__u16 __user *location = NULL;
 	int signal = 0;
 
-	location = (__u16 *) get_check_address(regs);
+	location = (__u16 __user *) get_check_address(regs);
 
 	/*
 	 * We got all needed information from the lowcore and can
@@ -632,7 +632,7 @@
 			break;
                 case 0xed:
 			get_user(*((__u32 *) (opcode+2)),
-				 (__u32 *)(location+1));
+				 (__u32 __user *)(location+1));
 			signal = math_emu_ed(opcode, regs);
 			break;
 	        case 0xb2:
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 2306cd8..21baaf5 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -22,6 +22,7 @@
 
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
+#include <asm/irq_regs.h>
 
 static ext_int_info_t ext_int_info_timer;
 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
@@ -208,11 +209,11 @@
  * Do the callback functions of expired vtimer events.
  * Called from within the interrupt handler.
  */
-static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs)
+static void do_callbacks(struct list_head *cb_list)
 {
 	struct vtimer_queue *vt_list;
 	struct vtimer_list *event, *tmp;
-	void (*fn)(unsigned long, struct pt_regs*);
+	void (*fn)(unsigned long);
 	unsigned long data;
 
 	if (list_empty(cb_list))
@@ -223,7 +224,7 @@
 	list_for_each_entry_safe(event, tmp, cb_list, entry) {
 		fn = event->function;
 		data = event->data;
-		fn(data, regs);
+		fn(data);
 
 		if (!event->interval)
 			/* delete one shot timer */
@@ -241,7 +242,7 @@
 /*
  * Handler for the virtual CPU timer.
  */
-static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code)
+static void do_cpu_timer_interrupt(__u16 error_code)
 {
 	int cpu;
 	__u64 next, delta;
@@ -274,7 +275,7 @@
 		list_move_tail(&event->entry, &cb_list);
 	}
 	spin_unlock(&vt_list->lock);
-	do_callbacks(&cb_list, regs);
+	do_callbacks(&cb_list);
 
 	/* next event is first in list */
 	spin_lock(&vt_list->lock);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 9c3c19f..1c323bb 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -451,7 +451,7 @@
 }
 
 asmlinkage void
-pfault_interrupt(struct pt_regs *regs, __u16 error_code)
+pfault_interrupt(__u16 error_code)
 {
 	struct task_struct *tsk;
 	__u16 subcode;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index f6a0c44..6a461d4 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -45,6 +45,9 @@
 config GENERIC_IOMAP
 	bool
 
+config GENERIC_TIME
+	def_bool n
+
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
@@ -357,6 +360,7 @@
 endmenu
 
 menu "Timer support"
+depends on !GENERIC_TIME
 
 config SH_TMU
 	bool "TMU timer support"
diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c
index 75f91aa..d146cda 100644
--- a/arch/sh/boards/hp6xx/hp6xx_apm.c
+++ b/arch/sh/boards/hp6xx/hp6xx_apm.c
@@ -14,7 +14,7 @@
 #include <asm/io.h>
 #include <asm/apm.h>
 #include <asm/adc.h>
-#include <asm/hp6xx/hp6xx.h>
+#include <asm/hp6xx.h>
 
 #define SH7709_PGDR			0xa400012c
 
@@ -83,7 +83,7 @@
 	return p - buf;
 }
 
-static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev)
 {
 	if (!apm_suspended)
 		apm_queue_event(APM_USER_SUSPEND);
@@ -96,7 +96,7 @@
 	int ret;
 
 	ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
-			  SA_INTERRUPT, MODNAME, 0);
+			  IRQF_DISABLED, MODNAME, 0);
 	if (unlikely(ret < 0)) {
 		printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
 		       HP680_BTN_IRQ);
diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c
index 83d3272..d194773 100644
--- a/arch/sh/boards/hp6xx/pm.c
+++ b/arch/sh/boards/hp6xx/pm.c
@@ -12,7 +12,7 @@
 #include <linux/time.h>
 #include <asm/io.h>
 #include <asm/hd64461.h>
-#include <asm/hp6xx/hp6xx.h>
+#include <asm/hp6xx.h>
 #include <asm/cpu/dac.h>
 #include <asm/pm.h>
 
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 2d3a5b4..b5a9664 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -13,7 +13,7 @@
 #include <asm/hd64461.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/hp6xx/hp6xx.h>
+#include <asm/hp6xx.h>
 #include <asm/cpu/dac.h>
 
 #define	SCPCR	0xa4000116
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
index 0b7bee1..e625249 100644
--- a/arch/sh/boards/landisk/landisk_pwb.c
+++ b/arch/sh/boards/landisk/landisk_pwb.c
@@ -135,7 +135,7 @@
 	return count;
 }
 
-static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sw_interrupt(int irq, void *dev_id)
 {
 	landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
 	disable_irq(IRQ_BUTTON);
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 01c10fa..7c3d1d3 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -69,7 +69,6 @@
 
 static unsigned char m_irq_mask = 0xfb;
 static unsigned char s_irq_mask = 0xff;
-volatile unsigned long irq_err_count;
 
 static void disable_mpc1211_irq(unsigned int irq)
 {
@@ -118,7 +117,7 @@
 	if(irq < 8) {
 		if(m_irq_mask & (1<<irq)){
 		  if(!mpc1211_irq_real(irq)){
-		    irq_err_count++;
+		    atomic_inc(&irq_err_count)
 		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
 		   }
 		} else {
@@ -131,7 +130,7 @@
 	} else {
 		if(s_irq_mask & (1<<(irq - 8))){
 		  if(!mpc1211_irq_real(irq)){
-		    irq_err_count++;
+		    atomic_inc(&irq_err_count);
 		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
 		  }
 		} else {
diff --git a/arch/sh/boards/renesas/hs7751rvoip/io.c b/arch/sh/boards/renesas/hs7751rvoip/io.c
index 51f3f65..bb9aa0d 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/io.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/io.c
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/io.h>
-#include <asm/hs7751rvoip/hs7751rvoip.h>
+#include <asm/hs7751rvoip.h>
 #include <asm/addrspace.h>
 
 extern void *area6_io8_base;	/* Area 6 8bit I/O Base address */
diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c
index c617b18..943f93a 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/irq.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c
@@ -14,7 +14,7 @@
 #include <linux/irq.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/hs7751rvoip/hs7751rvoip.h>
+#include <asm/hs7751rvoip.h>
 
 static int mask_pos[] = {8, 9, 10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7};
 
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
index 0414c15..1d997ff 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/setup.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -10,15 +10,10 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
 #include <linux/pm.h>
+#include <asm/hs7751rvoip.h>
 #include <asm/io.h>
-#include <asm/hs7751rvoip/hs7751rvoip.h>
 #include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
 
 static void __init hs7751rvoip_init_irq(void)
 {
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c
index db92d6e..311cccc 100644
--- a/arch/sh/boards/renesas/r7780rp/io.c
+++ b/arch/sh/boards/renesas/r7780rp/io.c
@@ -11,7 +11,7 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <asm/r7780rp/r7780rp.h>
+#include <asm/r7780rp.h>
 #include <asm/addrspace.h>
 #include <asm/io.h>
 
diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c
index 2d960e9..aa15ec5 100644
--- a/arch/sh/boards/renesas/r7780rp/irq.c
+++ b/arch/sh/boards/renesas/r7780rp/irq.c
@@ -1,18 +1,17 @@
 /*
- * linux/arch/sh/boards/renesas/r7780rp/irq.c
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
  * Renesas Solutions Highlander R7780RP-1 Support.
  *
- * Modified for R7780RP-1 by
- * Atom Create Engineering Co., Ltd. 2002.
+ * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/r7780rp/r7780rp.h>
+#include <linux/io.h>
+#include <asm/r7780rp.h>
 
 #ifdef CONFIG_SH_R7780MP
 static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
@@ -20,71 +19,26 @@
 static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0};
 #endif
 
-static void enable_r7780rp_irq(unsigned int irq);
-static void disable_r7780rp_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_r7780rp_irq disable_r7780rp_irq
-
-static void ack_r7780rp_irq(unsigned int irq);
-static void end_r7780rp_irq(unsigned int irq);
-
-static unsigned int startup_r7780rp_irq(unsigned int irq)
+static void enable_r7780rp_irq(unsigned int irq)
 {
-	enable_r7780rp_irq(irq);
-	return 0; /* never anything pending */
+	/* Set priority in IPR back to original value */
+	ctrl_outw(ctrl_inw(IRLCNTR1) | (1 << mask_pos[irq]), IRLCNTR1);
 }
 
 static void disable_r7780rp_irq(unsigned int irq)
 {
-	unsigned short val;
-	unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
-
 	/* Set the priority in IPR to 0 */
-	val = ctrl_inw(IRLCNTR1);
-	val &= mask;
-	ctrl_outw(val, IRLCNTR1);
+	ctrl_outw(ctrl_inw(IRLCNTR1) & (0xffff ^ (1 << mask_pos[irq])),
+		  IRLCNTR1);
 }
 
-static void enable_r7780rp_irq(unsigned int irq)
-{
-	unsigned short val;
-	unsigned short value = (0x0001 << mask_pos[irq]);
-
-	/* Set priority in IPR back to original value */
-	val = ctrl_inw(IRLCNTR1);
-	val |= value;
-	ctrl_outw(val, IRLCNTR1);
-}
-
-static void ack_r7780rp_irq(unsigned int irq)
-{
-	disable_r7780rp_irq(irq);
-}
-
-static void end_r7780rp_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_r7780rp_irq(irq);
-}
-
-static struct hw_interrupt_type r7780rp_irq_type = {
-	.typename = "R7780RP-IRQ",
-	.startup = startup_r7780rp_irq,
-	.shutdown = shutdown_r7780rp_irq,
-	.enable = enable_r7780rp_irq,
-	.disable = disable_r7780rp_irq,
-	.ack = ack_r7780rp_irq,
-	.end = end_r7780rp_irq,
+static struct irq_chip r7780rp_irq_chip __read_mostly = {
+	.name		= "R7780RP",
+	.mask		= disable_r7780rp_irq,
+	.unmask		= enable_r7780rp_irq,
+	.mask_ack	= disable_r7780rp_irq,
 };
 
-static void make_r7780rp_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	irq_desc[irq].chip = &r7780rp_irq_type;
-	disable_r7780rp_irq(irq);
-}
-
 /*
  * Initialize IRQ setting
  */
@@ -92,24 +46,10 @@
 {
 	int i;
 
-	/* IRL0=PCI Slot #A
-	 * IRL1=PCI Slot #B
-	 * IRL2=PCI Slot #C
-	 * IRL3=PCI Slot #D
-	 * IRL4=CF Card
-	 * IRL5=CF Card Insert
-	 * IRL6=M66596
-	 * IRL7=SD Card
-	 * IRL8=Touch Panel
-	 * IRL9=SCI
-	 * IRL10=Serial
-	 * IRL11=Extention #A
-	 * IRL11=Extention #B
-	 * IRL12=Debug LAN
-	 * IRL13=Push Switch
-	 * IRL14=ZiggBee IO
-	 */
-
-	for (i=0; i<15; i++)
-		make_r7780rp_irq(i);
+	for (i = 0; i < 15; i++) {
+		disable_irq_nosync(i);
+		set_irq_chip_and_handler_name(i, &r7780rp_irq_chip,
+					      handle_level_irq, "level");
+		enable_r7780rp_irq(i);
+	}
 }
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index b941aa0..c331cae 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <asm/machvec.h>
-#include <asm/r7780rp/r7780rp.h>
+#include <asm/r7780rp.h>
 #include <asm/clock.h>
 #include <asm/io.h>
 
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
index 135aa0b..f2507a8 100644
--- a/arch/sh/boards/renesas/rts7751r2d/io.c
+++ b/arch/sh/boards/renesas/rts7751r2d/io.c
@@ -11,8 +11,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
-#include <asm/io.h>
+#include <linux/io.h>
+#include <asm/rts7751r2d.h>
 #include <asm/addrspace.h>
 
 /*
diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c
index c915e7a..cb0eb20 100644
--- a/arch/sh/boards/renesas/rts7751r2d/irq.c
+++ b/arch/sh/boards/renesas/rts7751r2d/irq.c
@@ -8,12 +8,10 @@
  * Modified for RTS7751R2D by
  * Atom Create Engineering Co., Ltd. 2002.
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
+#include <linux/io.h>
+#include <asm/rts7751r2d.h>
 
 #if defined(CONFIG_RTS7751R2D_REV11)
 static int mask_pos[] = {11, 9, 8, 12, 10, 6, 5, 4, 7, 14, 13, 0, 0, 0, 0};
diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c
index a7ce66c..509f548 100644
--- a/arch/sh/boards/renesas/rts7751r2d/led.c
+++ b/arch/sh/boards/renesas/rts7751r2d/led.c
@@ -8,13 +8,9 @@
  *
  * This file contains Renesas Technology Sales RTS7751R2D specific LED code.
  */
-
-#include <asm/io.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
-
-#ifdef CONFIG_HEARTBEAT
-
+#include <linux/io.h>
 #include <linux/sched.h>
+#include <asm/rts7751r2d.h>
 
 /* Cycle the LED's in the clasic Knightriger/Sun pattern */
 void heartbeat_rts7751r2d(void)
@@ -46,10 +42,3 @@
 	else
 		bit--;
 }
-#endif /* CONFIG_HEARTBEAT */
-
-void rts7751r2d_led(unsigned short value)
-{
-	ctrl_outw(value, PA_OUTPORT);
-}
-
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 20597a6..5c042d3 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -12,9 +12,9 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/pm.h>
-#include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mach/rts7751r2d.h>
+#include <asm/io.h>
 #include <asm/voyagergx.h>
 
 extern void heartbeat_rts7751r2d(void);
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
index 2f0c197..a31a1d1 100644
--- a/arch/sh/boards/shmin/setup.c
+++ b/arch/sh/boards/shmin/setup.c
@@ -7,7 +7,7 @@
  */
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/shmin/shmin.h>
+#include <asm/shmin.h>
 #include <asm/clock.h>
 #include <asm/irq.h>
 #include <asm/io.h>
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index f5e98c5..540d0bf 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -33,7 +33,7 @@
  * EraseConfig handling functions
  */
 
-static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
 {
 	volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000;
 
diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c
index 38f1e81..4d49b5c 100644
--- a/arch/sh/cchips/hd6446x/hd64461/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64461/setup.c
@@ -71,7 +71,7 @@
 	.end		= end_hd64461_irq,
 };
 
-static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hd64461_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
diff --git a/arch/sh/cchips/hd6446x/hd64465/gpio.c b/arch/sh/cchips/hd6446x/hd64465/gpio.c
index 72320d0..4343185 100644
--- a/arch/sh/cchips/hd6446x/hd64465/gpio.c
+++ b/arch/sh/cchips/hd6446x/hd64465/gpio.c
@@ -85,7 +85,7 @@
     void *dev;
 } handlers[GPIO_NPORTS * 8];
 
-static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev)
 {
     	unsigned short port, pin, isr, mask, portpin;
 	
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c
index 30573d3..d126e1f 100644
--- a/arch/sh/cchips/hd6446x/hd64465/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -84,7 +84,7 @@
 };
 
 
-static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hd64465_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 392c8b1..f7ea700 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -17,29 +17,18 @@
 
     Copyright 2003 (c) Lineo uSolutions,Inc.
 */
-/* -------------------------------------------------------------------- */
-
-#undef DEBUG
-
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
+#include <linux/io.h>
 #include <asm/voyagergx.h>
+#include <asm/rts7751r2d.h>
 
 static void disable_voyagergx_irq(unsigned int irq)
 {
 	unsigned long val;
 	unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-    	pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+    	pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
         val = inl(VOYAGER_INT_MASK);
         val &= ~mask;
         outl(val, VOYAGER_INT_MASK);
@@ -50,7 +39,7 @@
         unsigned long val;
         unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
-        pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+        pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
         val = inl(VOYAGER_INT_MASK);
         val |= mask;
         outl(val, VOYAGER_INT_MASK);
@@ -88,8 +77,7 @@
 	.end = end_voyagergx_irq,
 };
 
-static irqreturn_t voyagergx_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t voyagergx_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "VoyagerGX: spurious interrupt, status: 0x%x\n",
@@ -138,7 +126,7 @@
 		} else {
 			printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
 		}
-		pr_debug("voyagergx_irq_demux %d \n", i);
+		pr_debug("voyagergx_irq_demux %ld\n", i);
 #else
 		for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
 			if (val & bit)
@@ -186,4 +174,3 @@
 
 	setup_irq(IRQ_VOYAGER, &irq0);
 }
-
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
index 9cb0709..0caf11b 100644
--- a/arch/sh/drivers/dma/dma-g2.c
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -51,7 +51,7 @@
 	((g2_dma->channel[i].size - \
 	  g2_dma->status[i].size) & 0x0fffffff)
 
-static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t g2_dma_interrupt(int irq, void *dev_id)
 {
 	int i;
 
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index c1b6bc2..838fad5 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -21,7 +21,7 @@
 static unsigned int xfer_complete;
 static int count;
 
-static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id)
 {
 	if (get_dma_residue(PVR2_CASCADE_CHAN)) {
 		printk(KERN_WARNING "DMA: SH DMAC did not complete transfer "
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index cbbe8bc..d8ece20 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -60,9 +60,9 @@
  * Besides that it needs to waken any waiting process, which should handle
  * setting up the next transfer.
  */
-static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_tei(int irq, void *dev_id)
 {
-	struct dma_channel *chan = (struct dma_channel *)dev_id;
+	struct dma_channel *chan = dev_id;
 	u32 chcr;
 
 	chcr = ctrl_inl(CHCR[chan->chan]);
@@ -228,7 +228,7 @@
 }
 
 #if defined(CONFIG_CPU_SH4)
-static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_err(int irq, void *dummy)
 {
 	dmaor_reset();
 	disable_irq(irq);
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
index 6e3ba9c6..eeea157 100644
--- a/arch/sh/drivers/pci/ops-r7780rp.c
+++ b/arch/sh/drivers/pci/ops-r7780rp.c
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <asm/r7780rp/r7780rp.h>
+#include <asm/r7780rp.h>
 #include <asm/io.h>
 #include "pci-sh4.h"
 
diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c
index b68824c..4a518d9 100644
--- a/arch/sh/drivers/pci/ops-rts7751r2d.c
+++ b/arch/sh/drivers/pci/ops-rts7751r2d.c
@@ -10,28 +10,24 @@
  *
  * PCI initialization for the Renesas SH7751R RTS7751R2D board
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/module.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
-#include <asm/io.h>
+#include <linux/io.h>
+#include <asm/rts7751r2d.h>
 #include "pci-sh4.h"
 
+static u8 rts7751r2d_irq_tab[] __initdata = {
+	IRQ_PCISLOT1,
+	IRQ_PCISLOT2,
+	IRQ_PCMCIA,
+	IRQ_PCIETH,
+};
+
 int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
-        switch (slot) {
-	case 0: return IRQ_PCISLOT1;	/* PCI Extend slot #1 */
-	case 1: return IRQ_PCISLOT2;	/* PCI Extend slot #2 */
-	case 2: return IRQ_PCMCIA;	/* PCI Cardbus Bridge */
-	case 3: return IRQ_PCIETH;	/* Realtek Ethernet controller */
-	default:
-		printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
-		return -1;
-	}
+	return rts7751r2d_irq_tab[slot];
 }
 
 static struct resource sh7751_io_resource = {
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index dbe8378..85e1ee2 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -155,7 +155,7 @@
 	 */
 	pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
 		 PCIBIOS_MIN_IO, (64 << 10),
-		 SH4_PCI_IO_BASE + PCIBIOS_MIN_IO);
+		 SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
 
 	/*
 	 * XXX: For now, leave this board-specific. In the event we have other
@@ -163,7 +163,7 @@
 	 */
 #ifdef CONFIG_SH_BIGSUR
 	bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
-			SH4_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
+			SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
 #endif
 
 	/* Make sure the MSB's of IO window are set to access PCI space
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index 4ab5ea6..efecb3d 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -161,7 +161,7 @@
 	"Memory Write-and-Invalidate"
 };
 
-static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t st40_pci_irq(int irq, void *dev_instance)
 {
 	unsigned pci_int, pci_air, pci_cir, pci_aint;
 	static int count=0;
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index e30e4b7..74ca576 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -10,93 +10,31 @@
  * These are the "new Hitachi style" interrupts, as present on the
  * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
  */
-
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-
-struct intc2_data {
-	unsigned char msk_offset;
-	unsigned char msk_shift;
-
-	int (*clear_irq) (int);
-};
-
-static struct intc2_data intc2_data[NR_INTC2_IRQS];
-
-static void enable_intc2_irq(unsigned int irq);
-static void disable_intc2_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_intc2_irq disable_intc2_irq
-
-static void mask_and_ack_intc2(unsigned int);
-static void end_intc2_irq(unsigned int irq);
-
-static unsigned int startup_intc2_irq(unsigned int irq)
-{
-	enable_intc2_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type intc2_irq_type = {
-	.typename	= "INTC2-IRQ",
-	.startup	= startup_intc2_irq,
-	.shutdown	= shutdown_intc2_irq,
-	.enable		= enable_intc2_irq,
-	.disable	= disable_intc2_irq,
-	.ack		= mask_and_ack_intc2,
-	.end		= end_intc2_irq
-};
 
 static void disable_intc2_irq(unsigned int irq)
 {
-	int irq_offset = irq - INTC2_FIRST_IRQ;
-	int msk_shift, msk_offset;
-
-	/* Sanity check */
-	if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
-		return;
-
-	msk_shift = intc2_data[irq_offset].msk_shift;
-	msk_offset = intc2_data[irq_offset].msk_offset;
-
-	ctrl_outl(1 << msk_shift,
-		  INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset);
+	struct intc2_data *p = get_irq_chip_data(irq);
+	ctrl_outl(1 << p->msk_shift,
+		  INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
 }
 
 static void enable_intc2_irq(unsigned int irq)
 {
-	int irq_offset = irq - INTC2_FIRST_IRQ;
-	int msk_shift, msk_offset;
-
-	/* Sanity check */
-	if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
-		return;
-
-	msk_shift = intc2_data[irq_offset].msk_shift;
-	msk_offset = intc2_data[irq_offset].msk_offset;
-
-	ctrl_outl(1 << msk_shift,
-		  INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset);
+	struct intc2_data *p = get_irq_chip_data(irq);
+	ctrl_outl(1 << p->msk_shift,
+		  INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
 }
 
-static void mask_and_ack_intc2(unsigned int irq)
-{
-	disable_intc2_irq(irq);
-}
-
-static void end_intc2_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_intc2_irq(irq);
-
-	if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq))
-		intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq);
-}
+static struct irq_chip intc2_irq_chip = {
+	.name		= "INTC2",
+	.mask		= disable_intc2_irq,
+	.unmask		= enable_intc2_irq,
+	.mask_ack	= disable_intc2_irq,
+};
 
 /*
  * Setup an INTC2 style interrupt.
@@ -106,179 +44,36 @@
  *    PIO1 which is INTPRI00[19,16] and INTMSK00[13]
  * would be:               ^     ^             ^  ^
  *                         |     |             |  |
- *    make_intc2_irq(84,   0,   16,            0, 13);
+ *     { 84,		   0,   16,            0, 13 },
+ *
+ * in the intc2_data table.
  */
-void make_intc2_irq(unsigned int irq,
-		    unsigned int ipr_offset, unsigned int ipr_shift,
-		    unsigned int msk_offset, unsigned int msk_shift,
-		    unsigned int priority)
-{
-	int irq_offset = irq - INTC2_FIRST_IRQ;
-	unsigned int flags;
-	unsigned long ipr;
-
-	if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
-		return;
-
-	disable_irq_nosync(irq);
-
-	/* Fill the data we need */
-	intc2_data[irq_offset].msk_offset = msk_offset;
-	intc2_data[irq_offset].msk_shift  = msk_shift;
-	intc2_data[irq_offset].clear_irq = NULL;
-
-	/* Set the priority level */
-	local_irq_save(flags);
-
-	ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
-	ipr &= ~(0xf << ipr_shift);
-	ipr |= priority << ipr_shift;
-	ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
-
-	local_irq_restore(flags);
-
-	irq_desc[irq].chip = &intc2_irq_type;
-
-	disable_intc2_irq(irq);
-}
-
-static struct intc2_init {
-	unsigned short irq;
-	unsigned char ipr_offset, ipr_shift;
-	unsigned char msk_offset, msk_shift;
-	unsigned char priority;
-} intc2_init_data[]  __initdata = {
-#if defined(CONFIG_CPU_SUBTYPE_ST40)
-	{64,  0,  0, 0,  0, 13},	/* PCI serr */
-	{65,  0,  4, 0,  1, 13},	/* PCI err */
-	{66,  0,  4, 0,  2, 13},	/* PCI ad */
-	{67,  0,  4, 0,  3, 13},	/* PCI pwd down */
-	{72,  0,  8, 0,  5, 13},	/* DMAC INT0 */
-	{73,  0,  8, 0,  6, 13},	/* DMAC INT1 */
-	{74,  0,  8, 0,  7, 13},	/* DMAC INT2 */
-	{75,  0,  8, 0,  8, 13},	/* DMAC INT3 */
-	{76,  0,  8, 0,  9, 13},	/* DMAC INT4 */
-	{78,  0,  8, 0, 11, 13},	/* DMAC ERR */
-	{80,  0, 12, 0, 12, 13},	/* PIO0 */
-	{84,  0, 16, 0, 13, 13},	/* PIO1 */
-	{88,  0, 20, 0, 14, 13},	/* PIO2 */
-	{112, 4,  0, 4,  0, 13},	/* Mailbox */
- #ifdef CONFIG_CPU_SUBTYPE_ST40GX1
-	{116, 4,  4, 4,  4, 13},	/* SSC0 */
-	{120, 4,  8, 4,  8, 13},	/* IR Blaster */
-	{124, 4, 12, 4, 12, 13},	/* USB host */
-	{128, 4, 16, 4, 16, 13},	/* Video processor BLITTER */
-	{132, 4, 20, 4, 20, 13},	/* UART0 */
-	{134, 4, 20, 4, 22, 13},	/* UART2 */
-	{136, 4, 24, 4, 24, 13},	/* IO_PIO0 */
-	{140, 4, 28, 4, 28, 13},	/* EMPI */
-	{144, 8,  0, 8,  0, 13},	/* MAFE */
-	{148, 8,  4, 8,  4, 13},	/* PWM */
-	{152, 8,  8, 8,  8, 13},	/* SSC1 */
-	{156, 8, 12, 8, 12, 13},	/* IO_PIO1 */
-	{160, 8, 16, 8, 16, 13},	/* USB target */
-	{164, 8, 20, 8, 20, 13},	/* UART1 */
-	{168, 8, 24, 8, 24, 13},	/* Teletext */
-	{172, 8, 28, 8, 28, 13},	/* VideoSync VTG */
-	{173, 8, 28, 8, 29, 13},	/* VideoSync DVP0 */
-	{174, 8, 28, 8, 30, 13},	/* VideoSync DVP1 */
-#endif
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-/*
- * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
- */
-	/* INTPRIO0 | INTMSK0 */
-	{48,  0, 28, 0, 31,  3},	/* IRQ 4 */
-	{49,  0, 24, 0, 30,  3},	/* IRQ 3 */
-	{50,  0, 20, 0, 29,  3},	/* IRQ 2 */
-	{51,  0, 16, 0, 28,  3},	/* IRQ 1 */
-	/* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
-	/* INTPRIO4 | INTMSK0 */
-	{56,  4, 28, 0, 25,  3},	/* HCAN2_CHAN0 */
-	{57,  4, 24, 0, 24,  3},	/* HCAN2_CHAN1 */
-	{58,  4, 20, 0, 23,  3},	/* I2S_CHAN0   */
-	{59,  4, 16, 0, 22,  3},	/* I2S_CHAN1   */
-	{60,  4, 12, 0, 21,  3},	/* AC97_CHAN0  */
-	{61,  4,  8, 0, 20,  3},	/* AC97_CHAN1  */
-	{62,  4,  4, 0, 19,  3},	/* I2C_CHAN0   */
-	{63,  4,  0, 0, 18,  3},	/* I2C_CHAN1   */
-	/* INTPRIO8 | INTMSK0 */
-	{52,  8, 16, 0, 11,  3},	/* SCIF0_ERI_IRQ */
-	{53,  8, 16, 0, 10,  3},	/* SCIF0_RXI_IRQ */
-	{54,  8, 16, 0,  9,  3},	/* SCIF0_BRI_IRQ */
-	{55,  8, 16, 0,  8,  3},	/* SCIF0_TXI_IRQ */
-	{64,  8, 28, 0, 17,  3},	/* USBHI_IRQ */
-	{65,  8, 24, 0, 16,  3},	/* LCDC      */
-	/* 66, 67 unused */
-	{68,  8, 20, 0, 14, 13},	/* DMABRGI0_IRQ */
-	{69,  8, 20, 0, 13, 13},	/* DMABRGI1_IRQ */
-	{70,  8, 20, 0, 12, 13},	/* DMABRGI2_IRQ */
-	/* 71 unused */
-	{72,  8, 12, 0,  7,  3},	/* SCIF1_ERI_IRQ */
-	{73,  8, 12, 0,  6,  3},	/* SCIF1_RXI_IRQ */
-	{74,  8, 12, 0,  5,  3},	/* SCIF1_BRI_IRQ */
-	{75,  8, 12, 0,  4,  3},	/* SCIF1_TXI_IRQ */
-	{76,  8,  8, 0,  3,  3},	/* SCIF2_ERI_IRQ */
-	{77,  8,  8, 0,  2,  3},	/* SCIF2_RXI_IRQ */
-	{78,  8,  8, 0,  1,  3},	/* SCIF2_BRI_IRQ */
-	{79,  8,  8, 0,  0,  3},	/* SCIF2_TXI_IRQ */
-	/*          | INTMSK4 */
-	{80,  8,  4, 4, 23,  3},	/* SIM_ERI */
-	{81,  8,  4, 4, 22,  3},	/* SIM_RXI */
-	{82,  8,  4, 4, 21,  3},	/* SIM_TXI */
-	{83,  8,  4, 4, 20,  3},	/* SIM_TEI */
-	{84,  8,  0, 4, 19,  3},	/* HSPII */
-	/* INTPRIOC | INTMSK4 */
-	/* 85-87 unused/reserved */
-	{88, 12, 20, 4, 18,  3},	/* MMCI0 */
-	{89, 12, 20, 4, 17,  3},	/* MMCI1 */
-	{90, 12, 20, 4, 16,  3},	/* MMCI2 */
-	{91, 12, 20, 4, 15,  3},	/* MMCI3 */
-	{92, 12, 12, 4,  6,  3},	/* MFI (unsure, bug? in my 7760 manual*/
-	/* 93-107 reserved/undocumented */
-	{108,12,  4, 4,  1,  3},	/* ADC  */
-	{109,12,  0, 4,  0,  3},	/* CMTI */
-	/* 110-111 reserved/unused */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-	{ TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
-	{ 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
-	{ 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
-	{ 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
-	{ SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
-	{ SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
-	{ SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
-	{ SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
-
-	{ SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-	{ SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-	{ SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-	{ SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
-
-	{ PCIC0_IRQ, 0x10,  8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY },
-	{ PCIC1_IRQ, 0x10,  0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
-	{ PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
-	{ PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
-	{ PCIC4_IRQ, 0x14,  8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
-#endif
-};
-
-void __init init_IRQ_intc2(void)
+void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) {
-		struct intc2_init *p = intc2_init_data + i;
-		make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
-			       p-> msk_offset, p->msk_shift, p->priority);
+	for (i = 0; i < nr_irqs; i++) {
+		unsigned long ipr, flags;
+		struct intc2_data *p = table + i;
+
+		disable_irq_nosync(p->irq);
+
+		/* Set the priority level */
+		local_irq_save(flags);
+
+		ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET +
+			       p->ipr_offset);
+		ipr &= ~(0xf << p->ipr_shift);
+		ipr |= p->priority << p->ipr_shift;
+		ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET +
+			  p->ipr_offset);
+
+		local_irq_restore(flags);
+
+		set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
+					      handle_level_irq, "level");
+		set_irq_chip_data(p->irq, p);
+
+		enable_intc2_irq(p->irq);
 	}
 }
-
-/* Adds a termination callback to the interrupt */
-void intc2_add_clear_irq(int irq, int (*fn)(int))
-{
-	if (unlikely(irq < INTC2_FIRST_IRQ))
-		return;
-
-	intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
-}
-
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index f785822..f799731 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -1,11 +1,10 @@
 /*
- * arch/sh/kernel/cpu/irq/ipr.c
+ * Interrupt handling for IPR-based IRQ.
  *
  * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
  * Copyright (C) 2000  Kazumoto Kojima
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- *
- * Interrupt handling for IPR-based IRQ.
+ * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Copyright (C) 2006  Paul Mundt
  *
  * Supported system:
  *	On-chip supporting modules (TMU, RTC, etc.).
@@ -13,12 +12,13 @@
  *	Hitachi SolutionEngine external I/O:
  *		MS7709SE01, MS7709ASE01, and MS7750SE01
  *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/module.h>
-
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
@@ -28,93 +28,46 @@
 	int shift;		/* Shifts of the 16-bit data */
 	int priority;		/* The priority */
 };
-static struct ipr_data ipr_data[NR_IRQS];
-
-static void enable_ipr_irq(unsigned int irq);
-static void disable_ipr_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_ipr_irq disable_ipr_irq
-
-static void mask_and_ack_ipr(unsigned int);
-static void end_ipr_irq(unsigned int irq);
-
-static unsigned int startup_ipr_irq(unsigned int irq)
-{
-	enable_ipr_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type ipr_irq_type = {
-	.typename = "IPR-IRQ",
-	.startup = startup_ipr_irq,
-	.shutdown = shutdown_ipr_irq,
-	.enable = enable_ipr_irq,
-	.disable = disable_ipr_irq,
-	.ack = mask_and_ack_ipr,
-	.end = end_ipr_irq
-};
 
 static void disable_ipr_irq(unsigned int irq)
 {
-	unsigned long val;
-	unsigned int addr = ipr_data[irq].addr;
-	unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
-
+	struct ipr_data *p = get_irq_chip_data(irq);
 	/* Set the priority in IPR to 0 */
-	val = ctrl_inw(addr);
-	val &= mask;
-	ctrl_outw(val, addr);
+	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
-	unsigned long val;
-	unsigned int addr = ipr_data[irq].addr;
-	int priority = ipr_data[irq].priority;
-	unsigned short value = (priority << ipr_data[irq].shift);
-
+	struct ipr_data *p = get_irq_chip_data(irq);
 	/* Set priority in IPR back to original value */
-	val = ctrl_inw(addr);
-	val |= value;
-	ctrl_outw(val, addr);
+	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
 }
 
-static void mask_and_ack_ipr(unsigned int irq)
-{
-	disable_ipr_irq(irq);
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
-	/* This is needed when we use edge triggered setting */
-	/* XXX: Is it really needed? */
-	if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
-		/* Clear external interrupt request */
-		int a = ctrl_inb(INTC_IRR0);
-		a &= ~(1 << (irq - IRQ0_IRQ));
-		ctrl_outb(a, INTC_IRR0);
-	}
-#endif
-}
-
-static void end_ipr_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_ipr_irq(irq);
-}
+static struct irq_chip ipr_irq_chip = {
+	.name		= "IPR",
+	.mask		= disable_ipr_irq,
+	.unmask		= enable_ipr_irq,
+	.mask_ack	= disable_ipr_irq,
+};
 
 void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
 {
-	disable_irq_nosync(irq);
-	ipr_data[irq].addr = addr;
-	ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
-	ipr_data[irq].priority = priority;
+	struct ipr_data ipr_data;
 
-	irq_desc[irq].chip = &ipr_irq_type;
-	disable_ipr_irq(irq);
+	disable_irq_nosync(irq);
+
+	ipr_data.addr = addr;
+	ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */
+	ipr_data.priority = priority;
+
+	set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
+				      handle_level_irq, "level");
+	set_irq_chip_data(irq, &ipr_data);
+
+	enable_ipr_irq(irq);
 }
 
+/* XXX: This needs to die a horrible death.. */
 void __init init_IRQ(void)
 {
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index 44daf44..ba3082d 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -4,7 +4,7 @@
  *  The SH-3 exception vector table.
 
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * 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
@@ -49,198 +49,10 @@
 #endif
 ENTRY(user_break_point_trap)
 	.long	break_point_trap	/* 1E0 */
-ENTRY(interrupt_table)
-	! external hardware
-	.long	do_IRQ	! 0000		/* 200 */
-	.long	do_IRQ	! 0001
-	.long	do_IRQ	! 0010
-	.long	do_IRQ	! 0011
-	.long	do_IRQ	! 0100
-	.long	do_IRQ	! 0101
-	.long	do_IRQ	! 0110
-	.long	do_IRQ	! 0111
-	.long	do_IRQ	! 1000		/* 300 */
-	.long	do_IRQ	! 1001
-	.long	do_IRQ	! 1010
-	.long	do_IRQ	! 1011
-	.long	do_IRQ	! 1100
-	.long	do_IRQ	! 1101
-	.long	do_IRQ	! 1110
-	.long	exception_error		
-	! Internal hardware
-	.long	do_IRQ	! TMU0 tuni0	/* 400 */
-	.long	do_IRQ	! TMU1 tuni1
-	.long	do_IRQ	! TMU2 tuni2
-	.long	do_IRQ	!      ticpi2
-	.long	do_IRQ	! RTC  ati
-	.long	do_IRQ	!      pri
-	.long	do_IRQ	!      cui
-	.long	do_IRQ	! SCI  eri
-	.long	do_IRQ	!      rxi	/* 500 */
-	.long	do_IRQ	!      txi
-	.long	do_IRQ	!      tei
-	.long	do_IRQ	! WDT  iti	/* 560 */
-	.long	do_IRQ	! REF  rcmi
-	.long	do_IRQ	!      rovi
-	.long	do_IRQ			
-	.long	do_IRQ			/* 5E0 */
-#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7710)
-	.long	do_IRQ	! 32 IRQ  irq0	/* 600 */
-	.long	do_IRQ	! 33      irq1
-	.long	do_IRQ	! 34      irq2
-	.long	do_IRQ	! 35      irq3
-	.long	do_IRQ	! 36      irq4
-	.long	do_IRQ	! 37      irq5
-	.long	do_IRQ	! 38
-	.long	do_IRQ	! 39
-	.long	do_IRQ	! 40 PINT pint0-7	/* 700 */
-	.long	do_IRQ	! 41      pint8-15
-	.long	do_IRQ	! 42
-	.long	do_IRQ	! 43
-	.long	do_IRQ	! 44
-	.long	do_IRQ	! 45	
-	.long	do_IRQ	! 46
-	.long	do_IRQ	! 47
-	.long	do_IRQ	! 48 DMAC dei0	/* 800 */
-	.long	do_IRQ	! 49      dei1
-	.long	do_IRQ	! 50      dei2
-	.long	do_IRQ	! 51      dei3
-	.long	do_IRQ	! 52 IrDA eri1
-	.long	do_IRQ	! 53      rxi1
-	.long	do_IRQ	! 54      bri1
-	.long	do_IRQ	! 55      txi1
-	.long	do_IRQ	! 56 SCIF eri2
-	.long	do_IRQ	! 57      rxi2
-	.long	do_IRQ	! 58      bri2
-	.long	do_IRQ	! 59      txi2
-	.long	do_IRQ	! 60 ADC  adi	/* 980 */
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
-	.long	exception_none	! 61	/* 9A0 */
-	.long	exception_none	! 62
-	.long	exception_none	! 63
-	.long	exception_none	! 64	/* A00 */
-	.long	do_IRQ	! 65 USB  usi0
-	.long	do_IRQ	! 66      usi1
-	.long	exception_none	! 67
-	.long	exception_none	! 68
-	.long	exception_none	! 69
-	.long	exception_none	! 70
-	.long	exception_none	! 71
-	.long	exception_none	! 72	/* B00 */
-	.long	exception_none	! 73
-	.long	exception_none	! 74
-	.long	exception_none	! 75
-	.long	exception_none	! 76
-	.long	exception_none	! 77
-	.long	exception_none	! 78
-	.long	exception_none	! 79
-	.long	do_IRQ	! 80 TPU0 tpi0	/* C00 */
-	.long	do_IRQ	! 81 TPU1 tpi1
-	.long	exception_none	! 82
-	.long	exception_none	! 83
-	.long	do_IRQ	! 84 TPU2 tpi2
-	.long	do_IRQ	! 85 TPU3 tpi3	/* CA0 */
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7300)
-	.long   do_IRQ	! 61 LCDC lcdi	/* 9A0 */
-	.long   do_IRQ	! 62 PCC  pcc0i
-	.long   do_IRQ	! 63      pcc1i	/* 9E0 */
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7710)
-	.long   exception_none	! 61 	/* 9A0 */
-	.long   exception_none	! 62
-	.long   exception_none	! 63
-	.long   exception_none	! 64	/* A00 */
-	.long   exception_none	! 65
-	.long   exception_none	! 66
-	.long   exception_none	! 67
-	.long   exception_none	! 68
-	.long   exception_none	! 69
-	.long   exception_none	! 70
-	.long   exception_none	! 71
-	.long   exception_none	! 72	/* B00 */
-	.long   exception_none	! 73
-	.long   exception_none	! 74
-	.long   exception_none	! 75
-	.long   do_IRQ	! 76 DMAC2 dei4	/* B80 */
-	.long   do_IRQ	! 77 DMAC2 dei5
-	.long   exception_none	! 78
-	.long   do_IRQ	! 79 IPSEC ipseci /* BE0 */
-	.long   do_IRQ	! 80 EDMAC eint0 /* C00 */
-	.long   do_IRQ	! 81 EDMAC eint1
-	.long   do_IRQ	! 82 EDMAC eint2
-	.long   exception_none	! 83	/* C60 */
-	.long   exception_none	! 84
-	.long   exception_none	! 85
-	.long   exception_none	! 86
-	.long   exception_none	! 87
-	.long   exception_none	! 88	/* D00 */
-	.long   exception_none	! 89
-	.long   exception_none	! 90
-	.long   exception_none	! 91
-	.long   exception_none	! 92
-	.long   exception_none	! 93
-	.long   exception_none	! 94
-	.long   exception_none	! 95
-	.long   do_IRQ	! 96 SIOF eri0	/* E00 */
-	.long   do_IRQ	! 97      txi0
-	.long   do_IRQ	! 98      rxi0
-	.long   do_IRQ	! 99      cci0
-	.long   do_IRQ	! 100     eri1	/* E80 */
-	.long   do_IRQ	! 101     txi1
-	.long   do_IRQ	! 102     rxi2
-	.long   do_IRQ	! 103     cci3
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-	.long   do_IRQ	! 64
-	.long   do_IRQ	! 65
-	.long   do_IRQ	! 66
-	.long   do_IRQ	! 67
-	.long   do_IRQ	! 68
-	.long   do_IRQ	! 69
-	.long   do_IRQ	! 70
-	.long   do_IRQ	! 71
-	.long   do_IRQ	! 72
-	.long   do_IRQ	! 73
-	.long   do_IRQ	! 74
-	.long   do_IRQ	! 75
-	.long   do_IRQ	! 76
-	.long   do_IRQ	! 77
-	.long   do_IRQ	! 78
-	.long   do_IRQ	! 79
-	.long   do_IRQ	! 80 SCIF0(SH7300)
-	.long   do_IRQ	! 81
-	.long   do_IRQ	! 82
-	.long   do_IRQ	! 83
-	.long   do_IRQ	! 84
-	.long   do_IRQ	! 85
-	.long   do_IRQ	! 86
-	.long   do_IRQ	! 87
-	.long   do_IRQ	! 88
-	.long   do_IRQ	! 89
-	.long   do_IRQ	! 90
-	.long   do_IRQ	! 91
-	.long   do_IRQ	! 92
-	.long   do_IRQ	! 93
-	.long   do_IRQ	! 94
-	.long   do_IRQ	! 95
-	.long   do_IRQ	! 96
-	.long   do_IRQ	! 97
-	.long   do_IRQ	! 98
-	.long   do_IRQ	! 99
-	.long   do_IRQ	! 100
-	.long   do_IRQ	! 101
-	.long   do_IRQ	! 102
-	.long   do_IRQ	! 103
-	.long   do_IRQ	! 104
-	.long   do_IRQ	! 105
-	.long   do_IRQ	! 106
-	.long   do_IRQ	! 107
-	.long   do_IRQ	! 108
-#endif
-#endif
+
+	/*
+	 * Pad the remainder of the table out, exceptions residing in far
+	 * away offsets can be manually inserted in to their appropriate
+	 * location via set_exception_table_{evt,vec}().
+	 */
+	.balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
index 7146893..ac8ab57 100644
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ b/arch/sh/kernel/cpu/sh4/ex.S
@@ -4,7 +4,7 @@
  *  The SH-4 exception vector table.
 
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * 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
@@ -53,503 +53,10 @@
 #endif
 ENTRY(user_break_point_trap)
 	.long	break_point_trap	/* 1E0 */
-ENTRY(interrupt_table)
-	! external hardware
-	.long	do_IRQ	! 0000		/* 200 */
-	.long	do_IRQ	! 0001
-	.long	do_IRQ	! 0010
-	.long	do_IRQ	! 0011
-	.long	do_IRQ	! 0100
-	.long	do_IRQ	! 0101
-	.long	do_IRQ	! 0110
-	.long	do_IRQ	! 0111
-	.long	do_IRQ	! 1000		/* 300 */
-	.long	do_IRQ	! 1001
-	.long	do_IRQ	! 1010
-	.long	do_IRQ	! 1011
-	.long	do_IRQ	! 1100
-	.long	do_IRQ	! 1101
-	.long	do_IRQ	! 1110
-	.long	exception_error		
-	! Internal hardware
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
-	.long	do_IRQ	! TMU0 tuni0	/* 400 */
-	.long	do_IRQ	! TMU1 tuni1
-	.long	do_IRQ	! TMU2 tuni2
-	.long	do_IRQ	!      ticpi2
-#if  defined(CONFIG_CPU_SUBTYPE_SH7760)
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* 500 */
-	.long	exception_error
-	.long	exception_error
-#else
-	.long	do_IRQ	! RTC  ati
-	.long	do_IRQ	!      pri
-	.long	do_IRQ	!      cui
-	.long	do_IRQ	! SCI  eri
-	.long	do_IRQ	!      rxi	/* 500 */
-	.long	do_IRQ	!      txi
-	.long	do_IRQ	!      tei
-#endif
-	.long	do_IRQ	! WDT  iti	/* 560 */
-	.long	do_IRQ	! REF  rcmi
-	.long	do_IRQ	!      rovi
-	.long	do_IRQ			
-	.long	do_IRQ			/* 5E0 */
-	.long	do_IRQ	! 32 Hitachi UDI	/* 600 */
-	.long	do_IRQ	! 33 GPIO
-	.long	do_IRQ	! 34 DMAC dmte0
-	.long	do_IRQ	! 35      dmte1
-	.long	do_IRQ	! 36      dmte2
-	.long	do_IRQ	! 37      dmte3
-	.long	do_IRQ	! 38      dmae
-	.long	exception_error			! 39	/* 6E0 */
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-	.long	exception_error				/* 700 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error				/* 760 */
-#else
-	.long	do_IRQ	! 40 SCIF eri		/* 700 */
-	.long	do_IRQ	! 41      rxi
-	.long	do_IRQ	! 42      bri
-	.long	do_IRQ	! 43      txi
-#endif
-#if CONFIG_NR_ONCHIP_DMA_CHANNELS == 8
-	.long	do_IRQ	! 44 DMAC dmte4		/* 780 */
-	.long	do_IRQ	! 45      dmte5
-	.long	do_IRQ	! 46      dmte6
-	.long	do_IRQ	! 47      dmte7		/* 7E0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-	.long	do_IRQ	! 44 IIC1 ali		/* 780 */
-	.long	do_IRQ	! 45      tacki
-	.long	do_IRQ	! 46      waiti
-	.long	do_IRQ	! 47      dtei		/* 7E0 */
-	.long	do_IRQ	! 48 DMAC dei0		/* 800 */
-	.long	do_IRQ	! 49      dei1		/* 820 */
-#else
-	.long	exception_error			! 44	/* 780 */
-	.long	exception_error			! 45
-	.long	exception_error			! 46
-	.long	exception_error			! 47
-#endif
-#if defined(CONFIG_SH_FPU)
-	.long	do_fpu_state_restore	! 48	/* 800 */
-	.long	do_fpu_state_restore	! 49	/* 820 */
-#elif !defined(CONFIG_CPU_SUBTYPE_SH7343) && \
-      !defined(CONFIG_CPU_SUBTYPE_SH73180)
-	.long	exception_error
-	.long	exception_error
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7751)
-	.long	exception_error			/* 840 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* 900 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! PCI serr	/* A00 */
-	.long	do_IRQ	!     dma3
-	.long	do_IRQ	!     dma2
-	.long	do_IRQ	!     dma1
-	.long	do_IRQ	!     dma0
-	.long	do_IRQ	!     pwon
-	.long	do_IRQ	!     pwdwn
-	.long	do_IRQ	!     err
-	.long	do_IRQ	! TMU3 tuni3	/* B00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! TMU4 tuni4	/* B80 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-	.long	do_IRQ	! IRQ	irq6	/* 840 */
-	.long	do_IRQ	!	irq7
-	.long	do_IRQ	! SCIF	eri0
-	.long	do_IRQ	!	rxi0
-	.long	do_IRQ	!	bri0
-	.long	do_IRQ	!	txi0
-	.long	do_IRQ	! HCAN2	cani0	/* 900 */
-	.long	do_IRQ	!	cani1
-	.long	do_IRQ	! SSI	ssii0
-	.long	do_IRQ	!	ssii1
-	.long	do_IRQ	! HAC	haci0
-	.long	do_IRQ	!	haci1
-	.long	do_IRQ	! IIC	iici0
-	.long	do_IRQ	!	iici1
-	.long	do_IRQ	! USB	usbi	/* A00 */
-	.long	do_IRQ	! LCDC	vint
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! DMABRG dmabrgi0
-	.long	do_IRQ	!        dmabrgi1
-	.long	do_IRQ	!        dmabrgi2
-	.long	exception_error
-	.long	do_IRQ	! SCIF	eri1	/* B00 */
-	.long	do_IRQ	!	rxi1
-	.long	do_IRQ	!	bri1
-	.long	do_IRQ	!	txi1
-	.long	do_IRQ	!	eri2
-	.long	do_IRQ	!	rxi2
-	.long	do_IRQ	!	bri2
-	.long	do_IRQ  !	txi2
-	.long	do_IRQ	! SIM	simeri	/* C00 */
-	.long	do_IRQ	!	simrxi
-	.long	do_IRQ	!	simtxi
-	.long	do_IRQ	!	simtei
-	.long	do_IRQ	! HSPI	spii
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! MMCIF	mmci0	/* D00 */
-	.long	do_IRQ	!	mmci1
-	.long	do_IRQ	!	mmci2
-	.long	do_IRQ	!	mmci3
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* E00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! MFI	mfii
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* F00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! ADC	adi
-	.long	do_IRQ	! CMT	cmti	/* FA0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7343)
-	.long	do_IRQ	!  50 0x840
-	.long	do_IRQ	!  51 0x860
-	.long	do_IRQ	!  52 0x880
-	.long	do_IRQ	!  53 0x8a0
-	.long	do_IRQ	!  54 0x8c0
-	.long	do_IRQ	!  55 0x8e0
-	.long	do_IRQ	!  56 0x900
-	.long	do_IRQ	!  57 0x920
-	.long	do_IRQ	!  58 0x940
-	.long	do_IRQ	!  59 0x960
-	.long	do_IRQ	!  60 0x980
-	.long	do_IRQ	!  61 0x9a0
-	.long	do_IRQ	!  62 0x9c0
-	.long	do_IRQ	!  63 0x9e0
-	.long	do_IRQ	!  64 0xa00
-	.long	do_IRQ	!  65 0xa20
-	.long	do_IRQ	!  66 0xa40
-	.long	do_IRQ	!  67 0xa60
-	.long	do_IRQ	!  68 0xa80
-	.long	do_IRQ	!  69 0xaa0
-	.long	do_IRQ	!  70 0xac0
-	.long	do_IRQ	!  71 0xae0
-	.long	do_IRQ	!  72 0xb00
-	.long	do_IRQ	!  73 0xb20
-	.long	do_IRQ	!  74 0xb40
-	.long	do_IRQ	!  75 0xb60
-	.long	do_IRQ	!  76 0xb80
-	.long	do_IRQ	!  77 0xba0
-	.long	do_IRQ	!  78 0xbc0
-	.long	do_IRQ	!  79 0xbe0
-	.long	do_IRQ	!  80 0xc00
-	.long	do_IRQ	!  81 0xc20
-	.long	do_IRQ	!  82 0xc40
-	.long	do_IRQ	!  83 0xc60
-	.long	do_IRQ	!  84 0xc80
-	.long	do_IRQ	!  85 0xca0
-	.long	do_IRQ	!  86 0xcc0
-	.long	do_IRQ	!  87 0xce0
-	.long	do_IRQ	!  88 0xd00
-	.long	do_IRQ	!  89 0xd20
-	.long	do_IRQ	!  90 0xd40
-	.long	do_IRQ	!  91 0xd60
-	.long	do_IRQ	!  92 0xd80
-	.long	do_IRQ	!  93 0xda0
-	.long	do_IRQ	!  94 0xdc0
-	.long	do_IRQ	!  95 0xde0
-	.long	do_IRQ	!  96 0xe00
-	.long	do_IRQ	!  97 0xe20
-	.long	do_IRQ	!  98 0xe40
-	.long	do_IRQ	!  99 0xe60
-	.long	do_IRQ	! 100 0xe80
-	.long	do_IRQ	! 101 0xea0
-	.long	do_IRQ	! 102 0xec0
-	.long	do_IRQ	! 103 0xee0
-	.long	do_IRQ	! 104 0xf00
-	.long	do_IRQ	! 105 0xf20
-	.long	do_IRQ	! 106 0xf40
-	.long	do_IRQ	! 107 0xf60
-	.long	do_IRQ	! 108 0xf80
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-	.long	exception_error			!  50 0x840
-	.long	exception_error			!  51 0x860
-	.long	exception_error			!  52 0x880
-	.long	exception_error			!  53 0x8a0
-	.long	exception_error			!  54 0x8c0
-	.long	exception_error			!  55 0x8e0
-	.long	exception_error			!  56 0x900
-	.long	exception_error			!  57 0x920
-	.long	exception_error			!  58 0x940
-	.long	exception_error			!  59 0x960
-	.long	exception_error			!  60 0x980
-	.long	exception_error			!  61 0x9a0
-	.long	exception_error			!  62 0x9c0
-	.long	exception_error			!  63 0x9e0
-	.long	do_IRQ	!  64 0xa00 PCI serr
-	.long	do_IRQ	!  65 0xa20     err
-	.long	do_IRQ	!  66 0xa40     ad
-	.long	do_IRQ	!  67 0xa60     pwr_dwn
-	.long	exception_error			!  68 0xa80
-	.long	exception_error			!  69 0xaa0
-	.long	exception_error			!  70 0xac0
-	.long	exception_error			!  71 0xae0
-	.long	do_IRQ	!  72 0xb00 DMA INT0
-	.long	do_IRQ	!  73 0xb20     INT1
-	.long	do_IRQ	!  74 0xb40     INT2
-	.long	do_IRQ	!  75 0xb60     INT3
-	.long	do_IRQ	!  76 0xb80     INT4
-	.long	exception_error			!  77 0xba0
-	.long	do_IRQ	!  78 0xbc0 DMA ERR
-	.long	exception_error			!  79 0xbe0
-	.long	do_IRQ	!  80 0xc00 PIO0
-	.long	do_IRQ	!  81 0xc20 PIO1
-	.long	do_IRQ	!  82 0xc40 PIO2
-	.long	exception_error			!  83 0xc60
-	.long	exception_error			!  84 0xc80
-	.long	exception_error			!  85 0xca0
-	.long	exception_error			!  86 0xcc0
-	.long	exception_error			!  87 0xce0
-	.long	exception_error			!  88 0xd00
-	.long	exception_error			!  89 0xd20
-	.long	exception_error			!  90 0xd40
-	.long	exception_error			!  91 0xd60
-	.long	exception_error			!  92 0xd80
-	.long	exception_error			!  93 0xda0
-	.long	exception_error			!  94 0xdc0
-	.long	exception_error			!  95 0xde0
-	.long	exception_error			!  96 0xe00
-	.long	exception_error			!  97 0xe20
-	.long	exception_error			!  98 0xe40
-	.long	exception_error			!  99 0xe60
-	.long	exception_error			! 100 0xe80
-	.long	exception_error			! 101 0xea0
-	.long	exception_error			! 102 0xec0
-	.long	exception_error			! 103 0xee0
-	.long	exception_error			! 104 0xf00
-	.long	exception_error			! 105 0xf20
-	.long	exception_error			! 106 0xf40
-	.long	exception_error			! 107 0xf60
-	.long	exception_error			! 108 0xf80
-	.long	exception_error			! 109 0xfa0
-	.long	exception_error			! 110 0xfc0
-	.long	exception_error			! 111 0xfe0
-	.long	do_IRQ	! 112 0x1000 Mailbox
-	.long	exception_error			! 113 0x1020
-	.long	exception_error			! 114 0x1040
-	.long	exception_error			! 115 0x1060
-	.long	exception_error			! 116 0x1080
-	.long	exception_error			! 117 0x10a0
-	.long	exception_error			! 118 0x10c0
-	.long	exception_error			! 119 0x10e0
-	.long	exception_error			! 120 0x1100
-	.long	exception_error			! 121 0x1120
-	.long	exception_error			! 122 0x1140
-	.long	exception_error			! 123 0x1160
-	.long	exception_error			! 124 0x1180
-	.long	exception_error			! 125 0x11a0
-	.long	exception_error			! 126 0x11c0
-	.long	exception_error			! 127 0x11e0
-	.long	exception_error			! 128 0x1200
-	.long	exception_error			! 129 0x1220
-	.long	exception_error			! 130 0x1240
-	.long	exception_error			! 131 0x1260
-	.long	exception_error			! 132 0x1280
-	.long	exception_error			! 133 0x12a0
-	.long	exception_error			! 134 0x12c0
-	.long	exception_error			! 135 0x12e0
-	.long	exception_error			! 136 0x1300
-	.long	exception_error			! 137 0x1320
-	.long	exception_error			! 138 0x1340
-	.long	exception_error			! 139 0x1360
-	.long	do_IRQ	! 140 0x1380 EMPI INV_ADDR
-	.long	exception_error			! 141 0x13a0
-	.long	exception_error			! 142 0x13c0
-	.long	exception_error			! 143 0x13e0
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-	.long	do_IRQ	!  50 0x840
-	.long	do_IRQ	!  51 0x860
-	.long	do_IRQ	!  52 0x880
-	.long	do_IRQ	!  53 0x8a0
-	.long	do_IRQ	!  54 0x8c0
-	.long	do_IRQ	!  55 0x8e0
-	.long	do_IRQ	!  56 0x900
-	.long	do_IRQ	!  57 0x920
-	.long	do_IRQ	!  58 0x940
-	.long	do_IRQ	!  59 0x960
-	.long	do_IRQ	!  60 0x980
-	.long	do_IRQ	!  61 0x9a0
-	.long	do_IRQ	!  62 0x9c0
-	.long	do_IRQ	!  63 0x9e0
-	.long	do_IRQ	!  64 0xa00
-	.long	do_IRQ	!  65 0xa20
-	.long	do_IRQ	!  66 0xa4d
-	.long	do_IRQ	!  67 0xa60
-	.long	do_IRQ	!  68 0xa80
-	.long	do_IRQ	!  69 0xaa0
-	.long	do_IRQ	!  70 0xac0
-	.long	do_IRQ	!  71 0xae0
-	.long	do_IRQ	!  72 0xb00
-	.long	do_IRQ	!  73 0xb20
-	.long	do_IRQ	!  74 0xb40
-	.long	do_IRQ	!  75 0xb60
-	.long	do_IRQ	!  76 0xb80
-	.long	do_IRQ	!  77 0xba0
-	.long	do_IRQ	!  78 0xbc0
-	.long	do_IRQ	!  79 0xbe0
-	.long	do_IRQ	!  80 0xc00
-	.long	do_IRQ	!  81 0xc20
-	.long	do_IRQ	!  82 0xc40
-	.long	do_IRQ	!  83 0xc60
-	.long	do_IRQ	!  84 0xc80
-	.long	do_IRQ	!  85 0xca0
-	.long	do_IRQ	!  86 0xcc0
-	.long	do_IRQ	!  87 0xce0
-	.long	do_IRQ	!  88 0xd00
-	.long	do_IRQ	!  89 0xd20
-	.long	do_IRQ	!  90 0xd40
-	.long	do_IRQ	!  91 0xd60
-	.long	do_IRQ	!  92 0xd80
-	.long	do_IRQ	!  93 0xda0
-	.long	do_IRQ	!  94 0xdc0
-	.long	do_IRQ	!  95 0xde0
-	.long	do_IRQ	!  96 0xe00
-	.long	do_IRQ	!  97 0xe20
-	.long	do_IRQ	!  98 0xe40
-	.long	do_IRQ	!  99 0xe60
-	.long	do_IRQ	! 100 0xe80
-	.long	do_IRQ	! 101 0xea0
-	.long	do_IRQ	! 102 0xec0
-	.long	do_IRQ	! 103 0xee0
-	.long	do_IRQ	! 104 0xf00
-	.long	do_IRQ	! 105 0xf20
-	.long	do_IRQ	! 106 0xf40
-	.long	do_IRQ	! 107 0xf60
-	.long	do_IRQ	! 108 0xf80
-#endif
-#else
-	.long	exception_error		/* 400 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! RTC	ati
-	.long	do_IRQ	!	pri
-	.long	do_IRQ	!	cui
-	.long	exception_error
-	.long	exception_error		/* 500 */
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! WDT	iti	/* 560 */
-	.long	do_IRQ	! TMU-ch0
-	.long	do_IRQ	! TMU-ch1
-	.long	do_IRQ	! TMU-ch2
-	.long	do_IRQ	! ticpi2	/* 5E0 */
-	.long	do_IRQ	! 32 Hitachi UDI	/* 600 */
-	.long	exception_error
-	.long	do_IRQ	! 34 DMAC dmte0
-	.long	do_IRQ	! 35	  dmte1
-	.long	do_IRQ	! 36	  dmte2
-	.long	do_IRQ	! 37	  dmte3
-	.long	do_IRQ	! 38	  dmae
-	.long	exception_error			! 39	/* 6E0 */
-	.long	do_IRQ	! 40 SCIF-ch0 eri		/* 700 */
-	.long	do_IRQ	! 41	      rxi
-	.long	do_IRQ	! 42	      bri
-	.long	do_IRQ	! 43	      txi
-	.long	do_IRQ	! 44 DMAC dmte4		/* 780 */
-	.long	do_IRQ	! 45	  dmte5
-	.long	do_IRQ	! 46	  dmte6
-	.long	do_IRQ	! 47	  dmte7		/* 7E0 */
-#if defined(CONFIG_SH_FPU)
-	.long	do_fpu_state_restore	! 48	/* 800 */
-	.long	do_fpu_state_restore	! 49	/* 820 */
-#else
-	.long	exception_error
-	.long	exception_error
-#endif
-	.long	exception_error			/* 840 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! 56 CMT	/* 900 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! 60 HAC
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! PCI serr	/* A00 */
-	.long	do_IRQ	!     INTA
-	.long	do_IRQ	!     INTB
-	.long	do_IRQ	!     INTC
-	.long	do_IRQ	!     INTD
-	.long	do_IRQ	!     err
-	.long	do_IRQ	!     pwd3
-	.long	do_IRQ	!     pwd2
-	.long	do_IRQ	!     pwd1	/* B00 */
-	.long	do_IRQ	!     pwd0
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! SCIF-ch1 eri	/* B80 */
-	.long	do_IRQ	!	   rxi
-	.long	do_IRQ	!	   bri
-	.long	do_IRQ	!	   txi
-	.long	do_IRQ	! SIOF		/* C00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! HSPI		/* C80 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! MMCIF	fatat	/* D00 */
-	.long	do_IRQ	!	tran
-	.long	do_IRQ	!	err
-	.long	do_IRQ	!	frdy
-	.long	do_IRQ	! DMAC dmint8	/* D80 */
-	.long	do_IRQ	!      dmint9
-	.long	do_IRQ	!      dmint10
-	.long	do_IRQ	!      dmint11
-	.long	do_IRQ	! TMU-ch3	/* E00 */
-	.long	do_IRQ	! TMU-ch4
-	.long	do_IRQ	! TMU-ch5
-	.long	exception_error
-	.long	do_IRQ	! SSI
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! FLCTL	flste	/* F00 */
-	.long	do_IRQ	!	fltend
-	.long	do_IRQ	!	fltrq0
-	.long	do_IRQ	!	fltrq1
-	.long	do_IRQ	! GPIO gpioi0	/* F80 */
-	.long	do_IRQ	!      gpioi1
-	.long	do_IRQ	!      gpioi2
-	.long	do_IRQ	!      gpioi3
-#endif
 
+	/*
+	 * Pad the remainder of the table out, exceptions residing in far
+	 * away offsets can be manually inserted in to their appropriate
+	 * location via set_exception_table_{evt,vec}().
+	 */
+	.balign	4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 97f1c9a..07e5377 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -51,3 +51,66 @@
 				    ARRAY_SIZE(sh7760_devices));
 }
 __initcall(sh7760_devices_setup);
+
+/*
+ * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
+ */
+static struct intc2_data intc2_irq_table[] = {
+	/* INTPRIO0 | INTMSK0 */
+	{48,  0, 28, 0, 31,  3},	/* IRQ 4 */
+	{49,  0, 24, 0, 30,  3},	/* IRQ 3 */
+	{50,  0, 20, 0, 29,  3},	/* IRQ 2 */
+	{51,  0, 16, 0, 28,  3},	/* IRQ 1 */
+	/* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
+	/* INTPRIO4 | INTMSK0 */
+	{56,  4, 28, 0, 25,  3},	/* HCAN2_CHAN0 */
+	{57,  4, 24, 0, 24,  3},	/* HCAN2_CHAN1 */
+	{58,  4, 20, 0, 23,  3},	/* I2S_CHAN0   */
+	{59,  4, 16, 0, 22,  3},	/* I2S_CHAN1   */
+	{60,  4, 12, 0, 21,  3},	/* AC97_CHAN0  */
+	{61,  4,  8, 0, 20,  3},	/* AC97_CHAN1  */
+	{62,  4,  4, 0, 19,  3},	/* I2C_CHAN0   */
+	{63,  4,  0, 0, 18,  3},	/* I2C_CHAN1   */
+	/* INTPRIO8 | INTMSK0 */
+	{52,  8, 16, 0, 11,  3},	/* SCIF0_ERI_IRQ */
+	{53,  8, 16, 0, 10,  3},	/* SCIF0_RXI_IRQ */
+	{54,  8, 16, 0,  9,  3},	/* SCIF0_BRI_IRQ */
+	{55,  8, 16, 0,  8,  3},	/* SCIF0_TXI_IRQ */
+	{64,  8, 28, 0, 17,  3},	/* USBHI_IRQ */
+	{65,  8, 24, 0, 16,  3},	/* LCDC      */
+	/* 66, 67 unused */
+	{68,  8, 20, 0, 14, 13},	/* DMABRGI0_IRQ */
+	{69,  8, 20, 0, 13, 13},	/* DMABRGI1_IRQ */
+	{70,  8, 20, 0, 12, 13},	/* DMABRGI2_IRQ */
+	/* 71 unused */
+	{72,  8, 12, 0,  7,  3},	/* SCIF1_ERI_IRQ */
+	{73,  8, 12, 0,  6,  3},	/* SCIF1_RXI_IRQ */
+	{74,  8, 12, 0,  5,  3},	/* SCIF1_BRI_IRQ */
+	{75,  8, 12, 0,  4,  3},	/* SCIF1_TXI_IRQ */
+	{76,  8,  8, 0,  3,  3},	/* SCIF2_ERI_IRQ */
+	{77,  8,  8, 0,  2,  3},	/* SCIF2_RXI_IRQ */
+	{78,  8,  8, 0,  1,  3},	/* SCIF2_BRI_IRQ */
+	{79,  8,  8, 0,  0,  3},	/* SCIF2_TXI_IRQ */
+	/*          | INTMSK4 */
+	{80,  8,  4, 4, 23,  3},	/* SIM_ERI */
+	{81,  8,  4, 4, 22,  3},	/* SIM_RXI */
+	{82,  8,  4, 4, 21,  3},	/* SIM_TXI */
+	{83,  8,  4, 4, 20,  3},	/* SIM_TEI */
+	{84,  8,  0, 4, 19,  3},	/* HSPII */
+	/* INTPRIOC | INTMSK4 */
+	/* 85-87 unused/reserved */
+	{88, 12, 20, 4, 18,  3},	/* MMCI0 */
+	{89, 12, 20, 4, 17,  3},	/* MMCI1 */
+	{90, 12, 20, 4, 16,  3},	/* MMCI2 */
+	{91, 12, 20, 4, 15,  3},	/* MMCI3 */
+	{92, 12, 12, 4,  6,  3},	/* MFI (unsure, bug? in my 7760 manual*/
+	/* 93-107 reserved/undocumented */
+	{108,12,  4, 4,  1,  3},	/* ADC  */
+	{109,12,  0, 4,  0,  3},	/* CMTI */
+	/* 110-111 reserved/unused */
+};
+
+void __init init_IRQ_intc2(void)
+{
+	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
index 72493f2..814ddb2 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
@@ -77,3 +77,30 @@
 				    ARRAY_SIZE(sh7780_devices));
 }
 __initcall(sh7780_devices_setup);
+
+static struct intc2_data intc2_irq_table[] = {
+	{ TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 },
+	{ 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+	{ 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+	{ 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+	{ SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+	{ SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+	{ SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+	{ SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+
+	{ SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+	{ SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+	{ SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+	{ SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+
+	{ PCIC0_IRQ, 0x10,  8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY },
+	{ PCIC1_IRQ, 0x10,  0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
+	{ PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
+	{ PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
+	{ PCIC4_IRQ, 0x14,  8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
+};
+
+void __init init_IRQ_intc2(void)
+{
+	make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+}
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index 97c571f..39aaefb 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -1,9 +1,8 @@
-/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
- *
+/*
  *  linux/arch/sh/entry.S
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * 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
@@ -78,7 +77,6 @@
 #define k3	r3
 #define k4	r4
 
-#define k_ex_code	r2_bank	/* r2_bank1 */
 #define g_imask		r6	/* r6_bank1 */
 #define k_g_imask	r6_bank	/* r6_bank1 */
 #define current		r7	/* r7_bank1 */
@@ -691,7 +689,7 @@
 0:
 #endif /* defined(CONFIG_KGDB_NMI) */
 	bra	handle_exception
-	 mov.l	@k2, k2
+	 mov	#-1, k2		! interrupt exception marker
 
 	.align	2
 1:	.long	EXPEVT
@@ -717,8 +715,7 @@
 	add	current, k1
 	mov	k1, r15		! change to kernel stack
 	!
-1:  	mov	#-1, k4
-	mov.l	2f, k1
+1:	mov.l	2f, k1
 	!
 #ifdef CONFIG_SH_DSP
 	mov.l	r2, @-r15		! Save r2, we need another reg
@@ -763,6 +760,8 @@
 #endif
 	! Save the user registers on the stack.
 	mov.l	k2, @-r15	! EXPEVT
+
+ 	mov	#-1, k4
 	mov.l	k4, @-r15	! set TRA (default: -1)
 	!
 	sts.l	macl, @-r15
@@ -797,8 +796,21 @@
 	mov.l	r2, @-r15
 	mov.l	r1, @-r15
 	mov.l	r0, @-r15
-	! Then, dispatch to the handler, according to the exception code.
-	stc	k_ex_code, r8
+
+	/*
+	 * This gets a bit tricky.. in the INTEVT case we don't want to use
+	 * the VBR offset as a destination in the jump call table, since all
+	 * of the destinations are the same. In this case, (interrupt) sets
+	 * a marker in r2 (now r2_bank since SR.RB changed), which we check
+	 * to determine the exception type. For all other exceptions, we
+	 * forcibly read EXPEVT from memory and fix up the jump address, in
+	 * the interrupt exception case we jump to do_IRQ() and defer the
+	 * INTEVT read until there. As a bonus, we can also clean up the SR.RB
+	 * checks that do_IRQ() was doing..
+	 */
+	stc	r2_bank, r8
+	cmp/pz	r8
+	bf	interrupt_exception
 	shlr2	r8
 	shlr	r8
 	mov.l	4f, r9
@@ -806,6 +818,8 @@
 	mov.l	@r9, r9
 	jmp	@r9
 	 nop
+	rts
+	 nop
 
 	.align	2
 1:	.long	0x00001000	! DSP=1
@@ -813,8 +827,17 @@
 3:	.long	0xcfffffff	! RB=0, BL=0
 4:	.long	exception_handling_table
 
+interrupt_exception:
+	mov.l	1f, r9
+	jmp	@r9
+	 nop
+	rts
+	 nop
+
+	.align 2
+1:	.long	do_IRQ
+
 	.align	2
 ENTRY(exception_none)
 	rts
 	 nop
-
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index c7ebd6a..944128c 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -11,12 +11,15 @@
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/thread_info.h>
 #include <asm/cpu/mmu_context.h>
 
+atomic_t irq_err_count;
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves, it doesn't deserve
@@ -24,6 +27,7 @@
  */
 void ack_bad_irq(unsigned int irq)
 {
+	atomic_inc(&irq_err_count);
 	printk("unexpected IRQ trap at vector %02x\n", irq);
 }
 
@@ -47,8 +51,10 @@
 		if (!action)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "%10u ", kstat_irqs(i));
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -56,7 +62,9 @@
 		seq_putc(p, '\n');
 unlock:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
+	} else if (i == NR_IRQS)
+		seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
+
 	return 0;
 }
 #endif
@@ -78,7 +86,8 @@
 		      unsigned long r6, unsigned long r7,
 		      struct pt_regs regs)
 {
-	int irq = r4;
+	struct pt_regs *old_regs = set_irq_regs(&regs);
+	int irq;
 #ifdef CONFIG_4KSTACKS
 	union irq_ctx *curctx, *irqctx;
 #endif
@@ -102,20 +111,9 @@
 #endif
 
 #ifdef CONFIG_CPU_HAS_INTEVT
-	__asm__ __volatile__ (
-#ifdef CONFIG_CPU_HAS_SR_RB
-		"stc	r2_bank, %0\n\t"
+	irq = (ctrl_inl(INTEVT) >> 5) - 16;
 #else
-		"mov.l	@%1, %0\n\t"
-#endif
-		"shlr2	%0\n\t"
-		"shlr2	%0\n\t"
-		"shlr	%0\n\t"
-		"add	#-16, %0\n\t"
-		: "=z" (irq), "=r" (r4)
-		: "1" (INTEVT)
-		: "memory"
-	);
+	irq = r4;
 #endif
 
 	irq = irq_demux(irq);
@@ -139,25 +137,25 @@
 
 		__asm__ __volatile__ (
 			"mov	%0, r4		\n"
-			"mov	%1, r5		\n"
 			"mov	r15, r9		\n"
-			"jsr	@%2		\n"
+			"jsr	@%1		\n"
 			/* swith to the irq stack */
-			" mov	%3, r15		\n"
+			" mov	%2, r15		\n"
 			/* restore the stack (ring zero) */
 			"mov	r9, r15		\n"
 			: /* no outputs */
-			: "r" (irq), "r" (&regs), "r" (__do_IRQ), "r" (isp)
+			: "r" (irq), "r" (generic_handle_irq), "r" (isp)
 			/* XXX: A somewhat excessive clobber list? -PFM */
 			: "memory", "r0", "r1", "r2", "r3", "r4",
 			  "r5", "r6", "r7", "r8", "t", "pr"
 		);
 	} else
 #endif
-		__do_IRQ(irq, &regs);
+		generic_handle_irq(irq);
 
 	irq_exit();
 
+	set_irq_regs(old_regs);
 	return 1;
 }
 
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 0b1d5dd..a52b13a 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -5,6 +5,7 @@
  *  Copyright (C) 1995  Linus Torvalds
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
+ *		     Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
  */
 
 /*
@@ -104,7 +105,7 @@
 {
 	printk("\n");
 	printk("Pid : %d, Comm: %20s\n", current->pid, current->comm);
-	print_symbol("PC is at %s\n", regs->pc);
+	print_symbol("PC is at %s\n", instruction_pointer(regs));
 	printk("PC  : %08lx SP  : %08lx SR  : %08lx ",
 	       regs->pc, regs->regs[15], regs->sr);
 #ifdef CONFIG_MMU
@@ -129,15 +130,7 @@
 	printk("MACH: %08lx MACL: %08lx GBR : %08lx PR  : %08lx\n",
 	       regs->mach, regs->macl, regs->gbr, regs->pr);
 
-	/*
-	 * If we're in kernel mode, dump the stack too..
-	 */
-	if (!user_mode(regs)) {
-		extern void show_task(unsigned long *sp);
-		unsigned long sp = regs->regs[15];
-
-		show_task((unsigned long *)sp);
-	}
+	show_trace(NULL, (unsigned long *)regs->regs[15], regs);
 }
 
 /*
@@ -290,6 +283,24 @@
 static void
 ubc_set_tracing(int asid, unsigned long pc)
 {
+#if defined(CONFIG_CPU_SH4A)
+	unsigned long val;
+
+	val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
+	val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
+
+	ctrl_outl(val, UBC_CBR0);
+	ctrl_outl(pc,  UBC_CAR0);
+	ctrl_outl(0x0, UBC_CAMR0);
+	ctrl_outl(0x0, UBC_CBCR);
+
+	val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
+	ctrl_outl(val, UBC_CRR0);
+
+	/* Read UBC register that we writed last. For chekking UBC Register changed */
+	val = ctrl_inl(UBC_CRR0);
+
+#else	/* CONFIG_CPU_SH4A */
 	ctrl_outl(pc, UBC_BARA);
 
 #ifdef CONFIG_MMU
@@ -307,6 +318,7 @@
 		ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
 		ctrl_outw(BRCR_PCBA, UBC_BRCR);
 	}
+#endif	/* CONFIG_CPU_SH4A */
 }
 
 /*
@@ -359,8 +371,13 @@
 #endif
 		ubc_set_tracing(asid, next->thread.ubc_pc);
 	} else {
+#if defined(CONFIG_CPU_SH4A)
+		ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
+		ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
+#else
 		ctrl_outw(0, UBC_BBRA);
 		ctrl_outw(0, UBC_BBRB);
+#endif
 	}
 
 	return prev;
@@ -460,8 +477,13 @@
 				 struct pt_regs regs)
 {
 	/* Clear tracing.  */
+#if defined(CONFIG_CPU_SH4A)
+	ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
+	ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
+#else
 	ctrl_outw(0, UBC_BBRA);
 	ctrl_outw(0, UBC_BBRB);
+#endif
 	current->thread.ubc_pc = 0;
 	ubc_usercnt -= 1;
 
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 450c68f..57e708d 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -47,6 +47,7 @@
 	return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
+#ifndef CONFIG_GENERIC_TIME
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long seq;
@@ -99,6 +100,7 @@
 	return 0;
 }
 EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
 
 /* last time the RTC clock got updated */
 static long last_rtc_update;
@@ -107,13 +109,14 @@
  * handle_timer_tick() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-void handle_timer_tick(struct pt_regs *regs)
+void handle_timer_tick(void)
 {
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
-	profile_tick(CPU_PROFILING, regs);
+	if (current->pid)
+		profile_tick(CPU_PROFILING);
 
 #ifdef CONFIG_HEARTBEAT
 	if (sh_mv.mv_heartbeat != NULL)
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 205816f..2492701 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -80,8 +80,7 @@
 	return count;
 }
 
-static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id,
-				       struct pt_regs *regs)
+static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 {
 	unsigned long timer_status;
 
@@ -98,7 +97,7 @@
 	 * locally disabled. -arca
 	 */
 	write_seqlock(&xtime_lock);
-	handle_timer_tick(regs);
+	handle_timer_tick();
 	write_sequnlock(&xtime_lock);
 
 	return IRQ_HANDLED;
@@ -111,60 +110,6 @@
 	.mask		= CPU_MASK_NONE,
 };
 
-/*
- * Hah!  We'll see if this works (switching from usecs to nsecs).
- */
-static unsigned long tmu_timer_get_frequency(void)
-{
-	u32 freq;
-	struct timespec ts1, ts2;
-	unsigned long diff_nsec;
-	unsigned long factor;
-
-	/* Setup the timer:  We don't want to generate interrupts, just
-	 * have it count down at its natural rate.
-	 */
-	ctrl_outb(0, TMU_TSTR);
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
-	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-#endif
-	ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
-	ctrl_outl(0xffffffff, TMU0_TCOR);
-	ctrl_outl(0xffffffff, TMU0_TCNT);
-
-	rtc_sh_get_time(&ts2);
-
-	do {
-		rtc_sh_get_time(&ts1);
-	} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
-
-	/* actually start the timer */
-	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-
-	do {
-		rtc_sh_get_time(&ts2);
-	} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
-
-	freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
-	if (ts2.tv_nsec < ts1.tv_nsec) {
-		ts2.tv_nsec += 1000000000;
-		ts2.tv_sec--;
-	}
-
-	diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
-
-	/* this should work well if the RTC has a precision of n Hz, where
-	 * n is an integer.  I don't think we have to worry about the other
-	 * cases. */
-	factor = (1000000000 + diff_nsec/2) / diff_nsec;
-
-	if (factor * diff_nsec > 1100000000 ||
-	    factor * diff_nsec <  900000000)
-		panic("weird RTC (diff_nsec %ld)", diff_nsec);
-
-	return freq * factor;
-}
-
 static void tmu_clk_init(struct clk *clk)
 {
 	u8 divisor = TMU0_TCR_INIT & 0x7;
@@ -232,12 +177,12 @@
 	.init		= tmu_timer_init,
 	.start		= tmu_timer_start,
 	.stop		= tmu_timer_stop,
-	.get_frequency	= tmu_timer_get_frequency,
+#ifndef CONFIG_GENERIC_TIME
 	.get_offset	= tmu_timer_get_offset,
+#endif
 };
 
 struct sys_timer tmu_timer = {
 	.name	= "tmu",
 	.ops	= &tmu_timer_ops,
 };
-
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index c2c597e..53dfa55 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -1,38 +1,25 @@
-/* $Id: traps.c,v 1.17 2004/05/02 01:46:30 sugioka Exp $
- *
- *  linux/arch/sh/traps.c
+/*
+ * 'traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
  *
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
- *                  Copyright (C) 2002, 2003 Paul Mundt
+ *                  Copyright (C) 2002 - 2006 Paul Mundt
+ *
+ * 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.
  */
-
-/*
- * 'Traps.c' handles hardware traps and faults after we have saved some
- * state in 'entry.S'.
- */
-#include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
 #include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
-
+#include <linux/io.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/atomic.h>
-#include <asm/processor.h>
-#include <asm/sections.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -53,13 +40,32 @@
 #define TRAP_ILLEGAL_SLOT_INST	13
 #endif
 
-/*
- * These constants are for searching for possible module text
- * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
- */
-#define VMALLOC_OFFSET (8*1024*1024)
-#define MODULE_RANGE (8*1024*1024)
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+	unsigned long p;
+	int i;
+
+	printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+	for (p = bottom & ~31; p < top; ) {
+		printk("%04lx: ", p & 0xffff);
+
+		for (i = 0; i < 8; i++, p += 4) {
+			unsigned int val;
+
+			if (p < bottom || p >= top)
+				printk("         ");
+			else {
+				if (__get_user(val, (unsigned int __user *)p)) {
+					printk("\n");
+					return;
+				}
+				printk("%08x ", val);
+			}
+		}
+		printk("\n");
+	}
+}
 
 DEFINE_SPINLOCK(die_lock);
 
@@ -69,14 +75,28 @@
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+
 	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+
 	CHK_REMOTE_DEBUG(regs);
+	print_modules();
 	show_regs(regs);
+
+	printk("Process: %s (pid: %d, stack limit = %p)\n",
+	       current->comm, current->pid, task_stack_page(current) + 1);
+
+	if (!user_mode(regs) || in_interrupt())
+		dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
+		 	 (unsigned long)task_stack_page(current));
+
+	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
 }
 
-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+static inline void die_if_kernel(const char *str, struct pt_regs *regs,
+				 long err)
 {
 	if (!user_mode(regs))
 		die(str, regs, err);
@@ -93,8 +113,7 @@
  */
 static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
 {
-	if (!user_mode(regs))
-	{
+	if (!user_mode(regs)) {
 		const struct exception_table_entry *fixup;
 		fixup = search_exception_tables(regs->pc);
 		if (fixup) {
@@ -550,7 +569,10 @@
 #define is_dsp_inst(regs)	(0)
 #endif /* CONFIG_SH_DSP */
 
-extern int do_fpu_inst(unsigned short, struct pt_regs*);
+/* arch/sh/kernel/cpu/sh4/fpu.c */
+extern int do_fpu_inst(unsigned short, struct pt_regs *);
+extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7, struct pt_regs regs);
 
 asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
 				unsigned long r6, unsigned long r7,
@@ -709,14 +731,20 @@
 		     : "memory");
 }
 
-void __init trap_init(void)
+void *set_exception_table_vec(unsigned int vec, void *handler)
 {
 	extern void *exception_handling_table[];
+	void *old_handler;
+	
+	old_handler = exception_handling_table[vec];
+	exception_handling_table[vec] = handler;
+	return old_handler;
+}
 
-	exception_handling_table[TRAP_RESERVED_INST]
-		= (void *)do_reserved_inst;
-	exception_handling_table[TRAP_ILLEGAL_SLOT_INST]
-		= (void *)do_illegal_slot_inst;
+void __init trap_init(void)
+{
+	set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
+	set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst);
 
 #if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
     defined(CONFIG_SH_FPU_EMU)
@@ -725,21 +753,42 @@
 	 * reserved. They'll be handled in the math-emu case, or faulted on
 	 * otherwise.
 	 */
-	/* entry 64 corresponds to EXPEVT=0x800 */
-	exception_handling_table[64] = (void *)do_reserved_inst;
-	exception_handling_table[65] = (void *)do_illegal_slot_inst;
+	set_exception_table_evt(0x800, do_reserved_inst);
+	set_exception_table_evt(0x820, do_illegal_slot_inst);
+#elif defined(CONFIG_SH_FPU)
+	set_exception_table_evt(0x800, do_fpu_state_restore);
+	set_exception_table_evt(0x820, do_fpu_state_restore);
 #endif
 		
 	/* Setup VBR for boot cpu */
 	per_cpu_trap_init();
 }
 
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+		struct pt_regs *regs)
+{
+	unsigned long addr;
+
+	if (regs && user_mode(regs))
+		return;
+
+	printk("\nCall trace: ");
+#ifdef CONFIG_KALLSYMS
+	printk("\n");
+#endif
+
+	while (!kstack_end(sp)) {
+		addr = *sp++;
+		if (kernel_text_address(addr))
+			print_ip_sym(addr);
+	}
+
+	printk("\n");
+}
+
 void show_stack(struct task_struct *tsk, unsigned long *sp)
 {
-	unsigned long *stack, addr;
-	unsigned long module_start = VMALLOC_START;
-	unsigned long module_end = VMALLOC_END;
-	int i = 1;
+	unsigned long stack;
 
 	if (!tsk)
 		tsk = current;
@@ -748,38 +797,10 @@
 	else
 		sp = (unsigned long *)tsk->thread.sp;
 
-	stack = sp;
-
-	printk("\nCall trace: ");
-#ifdef CONFIG_KALLSYMS
-	printk("\n");
-#endif
-
-	while (!kstack_end(stack)) {
-		addr = *stack++;
-		if (((addr >= (unsigned long)_text) &&
-		     (addr <= (unsigned long)_etext)) ||
-		    ((addr >= module_start) && (addr <= module_end))) {
-			/*
-			 * For 80-columns display, 6 entry is maximum.
-			 * NOTE: '[<8c00abcd>] ' consumes 13 columns .
-			 */
-#ifndef CONFIG_KALLSYMS
-			if (i && ((i % 6) == 0))
-				printk("\n       ");
-#endif
-			printk("[<%08lx>] ", addr);
-			print_symbol("%s\n", addr);
-			i++;
-		}
-	}
-
-	printk("\n");
-}
-
-void show_task(unsigned long *sp)
-{
-	show_stack(NULL, sp);
+	stack = (unsigned long)sp;
+	dump_mem("Stack: ", stack, THREAD_SIZE +
+		 (unsigned long)task_stack_page(tsk));
+	show_trace(tsk, sp, NULL);
 }
 
 void dump_stack(void)
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index c81e6b6..38c82d8 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -28,6 +28,7 @@
 	split_page(page, order);
 
 	ret = page_address(page);
+	memset(ret, 0, size);
 	*handle = virt_to_phys(ret);
 
 	/*
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9431e96..2f96610 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -289,6 +289,13 @@
 
 source "fs/Kconfig"
 
+menu "Instrumentation Support"
+	depends on EXPERIMENTAL
+
+source "arch/sparc/oprofile/Kconfig"
+
+endmenu
+
 source "arch/sparc/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 4cdbb2d..f33c381 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -30,6 +30,8 @@
 core-y += arch/sparc/kernel/ arch/sparc/mm/ arch/sparc/math-emu/
 libs-y += arch/sparc/prom/ arch/sparc/lib/
 
+drivers-$(CONFIG_OPROFILE)	+= arch/sparc/oprofile/
+
 # Export what is needed by arch/sparc/boot/Makefile
 # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-)
 INIT_Y		:= $(patsubst %/, %/built-in.o, $(init-y))
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 72f0201..c8cb211 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -46,6 +46,7 @@
 #include <asm/pgtable.h>
 #include <asm/pcic.h>
 #include <asm/cacheflush.h>
+#include <asm/irq_regs.h>
 
 #ifdef CONFIG_SMP
 #define SMP_NOP2 "nop; nop;\n\t"
@@ -133,8 +134,8 @@
     prom_halt();
 }
 
-void (*sparc_init_timers)(irqreturn_t (*)(int, void *,struct pt_regs *)) =
-    (void (*)(irqreturn_t (*)(int, void *,struct pt_regs *))) irq_panic;
+void (*sparc_init_timers)(irq_handler_t ) =
+    (void (*)(irq_handler_t )) irq_panic;
 
 /*
  * Dave Redman (djhr@tadpole.co.uk)
@@ -319,12 +320,14 @@
 
 void handler_irq(int irq, struct pt_regs * regs)
 {
+	struct pt_regs *old_regs;
 	struct irqaction * action;
 	int cpu = smp_processor_id();
 #ifdef CONFIG_SMP
 	extern void smp4m_irq_rotate(int cpu);
 #endif
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 	disable_pil_irq(irq);
 #ifdef CONFIG_SMP
@@ -338,27 +341,31 @@
 	do {
 		if (!action || !action->handler)
 			unexpected_irq(irq, NULL, regs);
-		action->handler(irq, action->dev_id, regs);
+		action->handler(irq, action->dev_id);
 		action = action->next;
 	} while (action);
 	sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
 	enable_pil_irq(irq);
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 #ifdef CONFIG_BLK_DEV_FD
-extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern void floppy_interrupt(int irq, void *dev_id);
 
 void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
 	int cpu = smp_processor_id();
 
+	old_regs = set_irq_regs(regs);
 	disable_pil_irq(irq);
 	irq_enter();
 	kstat_cpu(cpu).irqs[irq]++;
-	floppy_interrupt(irq, dev_id, regs);
+	floppy_interrupt(irq, dev_id);
 	irq_exit();
 	enable_pil_irq(irq);
+	set_irq_regs(old_regs);
 	// XXX Eek, it's totally changed with preempt_count() and such
 	// if (softirq_pending(cpu))
 	//	do_softirq();
@@ -369,7 +376,7 @@
  * thus no sharing possible.
  */
 int request_fast_irq(unsigned int irq,
-		     irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		     irq_handler_t handler,
 		     unsigned long irqflags, const char *devname)
 {
 	struct irqaction *action;
@@ -468,7 +475,7 @@
 }
 
 int request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		irq_handler_t handler,
 		unsigned long irqflags, const char * devname, void *dev_id)
 {
 	struct irqaction * action, **actionp;
@@ -478,7 +485,7 @@
 	
 	if (sparc_cpu_model == sun4d) {
 		extern int sun4d_request_irq(unsigned int, 
-					     irqreturn_t (*)(int, void *, struct pt_regs *),
+					     irq_handler_t ,
 					     unsigned long, const char *, void *);
 		return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
 	}
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index edb6cc6..207f1b6 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -34,6 +34,7 @@
 #include <asm/pcic.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
+#include <asm/irq_regs.h>
 
 
 unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
@@ -708,13 +709,13 @@
 	pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);
 }
 
-static irqreturn_t pcic_timer_handler (int irq, void *h, struct pt_regs *regs)
+static irqreturn_t pcic_timer_handler (int irq, void *h)
 {
 	write_seqlock(&xtime_lock);	/* Dummy, to show that we remember */
 	pcic_clear_clock_irq();
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 	write_sequnlock(&xtime_lock);
 	return IRQ_HANDLED;
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
index 4ca9e5f..2cc302b 100644
--- a/arch/sparc/kernel/prom.c
+++ b/arch/sparc/kernel/prom.c
@@ -243,7 +243,7 @@
 			void *old_val = prop->value;
 			int ret;
 
-			ret = prom_setprop(dp->node, name, val, len);
+			ret = prom_setprop(dp->node, (char *) name, val, len);
 			err = -EINVAL;
 			if (ret >= 0) {
 				prop->value = new_val;
@@ -477,7 +477,10 @@
 			p->length = 0;
 		} else {
 			p->value = prom_early_alloc(p->length + 1);
-			prom_getproperty(node, p->name, p->value, p->length);
+			len = prom_getproperty(node, p->name, p->value,
+					       p->length);
+			if (len <= 0)
+				p->length = 0;
 			((unsigned char *)p->value)[p->length] = '\0';
 		}
 	}
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 0251cab..383526a 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -103,7 +103,6 @@
 
 unsigned int boot_flags __initdata = 0;
 #define BOOTME_DEBUG  0x1
-#define BOOTME_SINGLE 0x2
 
 /* Exported for mm/init.c:paging_init. */
 unsigned long cmdline_memory_size __initdata = 0;
@@ -121,16 +120,6 @@
 	.index =	-1,
 };
 
-int obp_system_intr(void)
-{
-	if (boot_flags & BOOTME_DEBUG) {
-		printk("OBP: system interrupted\n");
-		prom_halt();
-		return 1;
-	}
-	return 0;
-}
-
 /* 
  * Process kernel command line switches that are specific to the
  * SPARC or that require special low-level processing.
@@ -142,7 +131,6 @@
 		boot_flags |= BOOTME_DEBUG;
 		break;
 	case 's':
-		boot_flags |= BOOTME_SINGLE;
 		break;
 	case 'h':
 		prom_printf("boot_flags_init: Halt!\n");
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 4d441a5..33dadd9 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -87,6 +87,7 @@
 extern void ___clear_bit(void);
 extern void ___change_bit(void);
 extern void ___rw_read_enter(void);
+extern void ___rw_read_try(void);
 extern void ___rw_read_exit(void);
 extern void ___rw_write_enter(void);
 
@@ -104,8 +105,9 @@
 EXPORT_SYMBOL(sparc_cpu_model);
 EXPORT_SYMBOL(kernel_thread);
 #ifdef CONFIG_SMP
-// XXX find what uses (or used) these.
+// XXX find what uses (or used) these.   AV: see asm/spinlock.h
 EXPORT_SYMBOL(___rw_read_enter);
+EXPORT_SYMBOL(___rw_read_try);
 EXPORT_SYMBOL(___rw_read_exit);
 EXPORT_SYMBOL(___rw_write_enter);
 #endif
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index 4be2c86..009e891 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -154,7 +154,7 @@
 	/* Errm.. not sure how to do this.. */
 }
 
-static void __init sun4c_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *))
+static void __init sun4c_init_timers(irq_handler_t counter_fn)
 {
 	int irq;
 
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 74eed97..d4f9da8 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -38,6 +38,7 @@
 #include <asm/sbus.h>
 #include <asm/sbi.h>
 #include <asm/cacheflush.h>
+#include <asm/irq_regs.h>
 
 /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */
 /* #define DISTRIBUTE_IRQS */
@@ -198,6 +199,7 @@
 
 void sun4d_handler_irq(int irq, struct pt_regs * regs)
 {
+	struct pt_regs *old_regs;
 	struct irqaction * action;
 	int cpu = smp_processor_id();
 	/* SBUS IRQ level (1 - 7) */
@@ -208,6 +210,7 @@
 	
 	cc_set_iclr(1 << irq);
 	
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 	kstat_cpu(cpu).irqs[irq]++;
 	if (!sbusl) {
@@ -215,7 +218,7 @@
 		if (!action)
 			unexpected_irq(irq, NULL, regs);
 		do {
-			action->handler(irq, action->dev_id, regs);
+			action->handler(irq, action->dev_id);
 			action = action->next;
 		} while (action);
 	} else {
@@ -242,7 +245,7 @@
 						if (!action)
 							unexpected_irq(irq, NULL, regs);
 						do {
-							action->handler(irq, action->dev_id, regs);
+							action->handler(irq, action->dev_id);
 							action = action->next;
 						} while (action);
 						release_sbi(SBI2DEVID(sbino), slot);
@@ -250,6 +253,7 @@
 			}
 	}
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq)
@@ -272,7 +276,7 @@
 }
 
 int sun4d_request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		irq_handler_t handler,
 		unsigned long irqflags, const char * devname, void *dev_id)
 {
 	struct irqaction *action, *tmp = NULL, **actionp;
@@ -466,7 +470,7 @@
 	bw_set_prof_limit(cpu, limit);
 }
 
-static void __init sun4d_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *))
+static void __init sun4d_init_timers(irq_handler_t counter_fn)
 {
 	int irq;
 	int cpu;
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 3ff4edd..c80ea61 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -23,6 +23,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
+#include <asm/irq_regs.h>
 
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -369,10 +370,12 @@
 
 void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
 	int cpu = hard_smp4d_processor_id();
 	static int cpu_tick[NR_CPUS];
 	static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
 
+	old_regs = set_irq_regs(regs);
 	bw_get_prof_limit(cpu);	
 	bw_clear_intr_mask(0, 1);	/* INTR_TABLE[0] & 1 is Profile IRQ */
 
@@ -384,7 +387,7 @@
 		show_leds(cpu);
 	}
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 	if(!--prof_counter(cpu)) {
 		int user = user_mode(regs);
@@ -395,6 +398,7 @@
 
 		prof_counter(cpu) = prof_multiplier(cpu);
 	}
+	set_irq_regs(old_regs);
 }
 
 extern unsigned int lvl14_resolution;
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 7cefa30..a654c16 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -228,7 +228,7 @@
 	sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit;
 }
 
-static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *))
+static void __init sun4m_init_timers(irq_handler_t counter_fn)
 {
 	int reg_count, irq, cpu;
 	struct linux_prom_registers cnt_regs[PROMREG_MAX];
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 7d4a649..e2d9c01 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -19,6 +19,7 @@
 #include <linux/profile.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <asm/irq_regs.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -353,11 +354,14 @@
 
 void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs;
 	int cpu = smp_processor_id();
 
+	old_regs = set_irq_regs(regs);
+
 	clear_profile_irq(cpu);
 
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 
 	if(!--prof_counter(cpu)) {
 		int user = user_mode(regs);
@@ -368,6 +372,7 @@
 
 		prof_counter(cpu) = prof_multiplier(cpu);
 	}
+	set_irq_regs(old_regs);
 }
 
 extern unsigned int lvl14_resolution;
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c
index d3b4daa..f1a7bd1 100644
--- a/arch/sparc/kernel/tick14.c
+++ b/arch/sparc/kernel/tick14.c
@@ -55,7 +55,7 @@
 	linux_lvl14[3] =  obp_lvl14[3]; 
 }
 
-void claim_ticker14(irqreturn_t (*handler)(int, void *, struct pt_regs *),
+void claim_ticker14(irq_handler_t handler,
 		    int irq_nr, unsigned int timeout )
 {
 	int cpu = smp_processor_id();
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index e10dc83..6c7aa51 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -42,6 +42,7 @@
 #include <asm/page.h>
 #include <asm/pcic.h>
 #include <asm/of_device.h>
+#include <asm/irq_regs.h>
 
 DEFINE_SPINLOCK(rtc_lock);
 enum sparc_clock_type sp_clock_typ;
@@ -94,6 +95,8 @@
 	return pc;
 }
 
+EXPORT_SYMBOL(profile_pc);
+
 __volatile__ unsigned int *master_l10_counter;
 __volatile__ unsigned int *master_l10_limit;
 
@@ -104,13 +107,13 @@
 
 #define TICK_SIZE (tick_nsec / 1000)
 
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	/* last time the cmos clock got updated */
 	static long last_rtc_update;
 
 #ifndef CONFIG_SMP
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #endif
 
 	/* Protect counter clear so that do_gettimeoffset works */
@@ -128,7 +131,7 @@
 
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 
 
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 346c19a..1dd78c8 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -36,11 +36,11 @@
 
   . = ALIGN(4096);
   __init_begin = .;
+  _sinittext = .;
   .init.text : { 
-	_sinittext = .;
 	*(.init.text)
-	_einittext = .;
   }
+  _einittext = .;
   __init_text_end = .;
   .init.data : { *(.init.data) }
   . = ALIGN(16);
diff --git a/arch/sparc/lib/locks.S b/arch/sparc/lib/locks.S
index 95fa484..b1df55c 100644
--- a/arch/sparc/lib/locks.S
+++ b/arch/sparc/lib/locks.S
@@ -25,6 +25,15 @@
 	 ldstub	[%g1 + 3], %g2
 	b	___rw_read_enter_spin_on_wlock
 	 ldub	[%g1 + 3], %g2
+___rw_read_try_spin_on_wlock:
+	andcc	%g2, 0xff, %g0
+	be,a	___rw_read_try
+	 ldstub	[%g1 + 3], %g2
+	xnorcc	%g2, 0x0, %o0	/* if g2 is ~0, set o0 to 0 and bugger off */
+	bne,a	___rw_read_enter_spin_on_wlock
+	 ld	[%g1], %g2
+	retl
+	 mov	%g4, %o7
 ___rw_read_exit_spin_on_wlock:
 	orcc	%g2, 0x0, %g0
 	be,a	___rw_read_exit
@@ -60,6 +69,17 @@
 	retl
 	 mov	%g4, %o7
 
+	.globl	___rw_read_try
+___rw_read_try:
+	orcc	%g2, 0x0, %g0
+	bne	___rw_read_try_spin_on_wlock
+	 ld	[%g1], %g2
+	add	%g2, 1, %g2
+	st	%g2, [%g1]
+	set	1, %o1
+	retl
+	 mov	%g4, %o7
+
 	.globl	___rw_write_enter
 ___rw_write_enter:
 	orcc	%g2, 0x0, %g0
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index b27a506..0df7121 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -402,7 +402,7 @@
 	srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size;
 }
 
-void srmmu_nocache_init(void)
+void __init srmmu_nocache_init(void)
 {
 	unsigned int bitmap_bits;
 	pgd_t *pgd;
diff --git a/arch/sparc/oprofile/Kconfig b/arch/sparc/oprofile/Kconfig
new file mode 100644
index 0000000..d8a8408
--- /dev/null
+++ b/arch/sparc/oprofile/Kconfig
@@ -0,0 +1,17 @@
+config PROFILING
+	bool "Profiling support (EXPERIMENTAL)"
+	help
+	  Say Y here to enable the extended profiling support mechanisms used
+	  by profilers such as OProfile.
+	  
+
+config OPROFILE
+	tristate "OProfile system profiling (EXPERIMENTAL)"
+	depends on PROFILING
+	help
+	  OProfile is a profiling system capable of profiling the
+	  whole system, include the kernel, kernel modules, libraries,
+	  and applications.
+
+	  If unsure, say N.
+
diff --git a/arch/sparc/oprofile/Makefile b/arch/sparc/oprofile/Makefile
new file mode 100644
index 0000000..e9feca1
--- /dev/null
+++ b/arch/sparc/oprofile/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+		oprof.o cpu_buffer.o buffer_sync.o \
+		event_buffer.o oprofile_files.o \
+		oprofilefs.o oprofile_stats.o \
+		timer_int.o )
+
+oprofile-y				:= $(DRIVER_OBJS) init.o
diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c
new file mode 100644
index 0000000..9ab815b
--- /dev/null
+++ b/arch/sparc/oprofile/init.c
@@ -0,0 +1,23 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+ 
+int __init oprofile_arch_init(struct oprofile_operations * ops)
+{
+	return -ENODEV;
+}
+
+
+void oprofile_arch_exit(void)
+{
+}
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index f54ab37..2f4612f 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Mon Oct  2 14:24:40 2006
+# Linux kernel version: 2.6.19-rc2
+# Tue Oct 17 19:29:20 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -197,6 +197,7 @@
 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
@@ -214,7 +215,9 @@
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
@@ -332,6 +335,12 @@
 CONFIG_ATA_OVER_ETH=m
 
 #
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -373,6 +382,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
@@ -449,10 +459,10 @@
 # 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_QLOGICPTI 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
@@ -478,6 +488,7 @@
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -724,7 +735,6 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -838,14 +848,9 @@
 # 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
@@ -858,6 +863,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
@@ -1099,7 +1105,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
@@ -1145,6 +1150,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
 
 #
@@ -1229,6 +1235,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
@@ -1236,6 +1243,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
@@ -1279,6 +1287,7 @@
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -1388,6 +1397,7 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
+# CONFIG_HEADERS_CHECK is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index 8a9b470..2df25c2 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -79,7 +79,7 @@
 	}
 }
 
-static irqreturn_t ebus_dma_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ebus_dma_irq(int irq, void *dev_id)
 {
 	struct ebus_dma_info *p = dev_id;
 	unsigned long flags;
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 4e64724..d64b1ea8 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -522,12 +522,13 @@
 }
 
 #ifndef CONFIG_SMP
-extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
+extern irqreturn_t timer_interrupt(int, void *);
 
 void timer_irq(int irq, struct pt_regs *regs)
 {
 	unsigned long clr_mask = 1 << irq;
 	unsigned long tick_mask = tick_ops->softint_mask;
+	struct pt_regs *old_regs;
 
 	if (get_softint() & tick_mask) {
 		irq = 0;
@@ -535,21 +536,25 @@
 	}
 	clear_softint(clr_mask);
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 
 	kstat_this_cpu.irqs[0]++;
-	timer_interrupt(irq, NULL, regs);
+	timer_interrupt(irq, NULL);
 
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 #endif
 
 void handler_irq(int irq, struct pt_regs *regs)
 {
 	struct ino_bucket *bucket;
+	struct pt_regs *old_regs;
 
 	clear_softint(1 << irq);
 
+	old_regs = set_irq_regs(regs);
 	irq_enter();
 
 	/* Sliiiick... */
@@ -558,12 +563,13 @@
 		struct ino_bucket *next = __bucket(bucket->irq_chain);
 
 		bucket->irq_chain = 0;
-		__do_IRQ(bucket->virt_irq, regs);
+		__do_IRQ(bucket->virt_irq);
 
 		bucket = next;
 	}
 
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 struct sun5_timer {
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 7f92045..d3dfb2a 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -131,8 +131,13 @@
 void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name)
 {
 	unsigned long ret = res->start + offset;
+	struct resource *r;
 
-	if (!request_region(ret, size, name))
+	if (res->flags & IORESOURCE_MEM)
+		r = request_mem_region(ret, size, name);
+	else
+		r = request_region(ret, size, name);
+	if (!r)
 		ret = 0;
 
 	return (void __iomem *) ret;
@@ -841,7 +846,7 @@
 	if (!parent)
 		strcpy(op->dev.bus_id, "root");
 	else
-		strcpy(op->dev.bus_id, dp->path_component_name);
+		sprintf(op->dev.bus_id, "%s@%08x", dp->name, dp->node);
 
 	if (of_device_register(op)) {
 		printk("%s: Could not register of device.\n",
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 7a59cc7..827ae30 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -330,19 +330,6 @@
 	return res;
 }
 
-static int __init pdev_resource_collisions_expected(struct pci_dev *pdev)
-{
-	if (pdev->vendor != PCI_VENDOR_ID_SUN)
-		return 0;
-
-	if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS ||
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 ||
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
-		return 1;
-
-	return 0;
-}
-
 static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
 					   struct pci_dev *pdev)
 {
@@ -400,19 +387,23 @@
 		pbm->parent->resource_adjust(pdev, res, root);
 
 		if (request_resource(root, res) < 0) {
+			int rnum;
+
 			/* OK, there is some conflict.  But this is fine
 			 * since we'll reassign it in the fixup pass.
 			 *
-			 * We notify the user that OBP made an error if it
-			 * is a case we don't expect.
+			 * Do not print the warning for ROM resources
+			 * as such a conflict is quite common and
+			 * harmless as the ROM bar is disabled.
 			 */
-			if (!pdev_resource_collisions_expected(pdev)) {
-				printk(KERN_ERR "PCI: Address space collision on region %ld "
+			rnum = (res - &pdev->resource[0]);
+			if (rnum != PCI_ROM_RESOURCE)
+				printk(KERN_ERR "PCI: Resource collision, "
+				       "region %d "
 				       "[%016lx:%016lx] of device %s\n",
-				       (res - &pdev->resource[0]),
+				       rnum,
 				       res->start, res->end,
 				       pci_name(pdev));
-			}
 		}
 	}
 }
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 1ec0aab..fda5db2 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -533,7 +533,7 @@
 #define  PSYCHO_UEAFSR_RESV2	0x00000000007fffffUL /* Reserved                     */
 #define PSYCHO_UE_AFAR	0x0038UL
 
-static irqreturn_t psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR;
@@ -610,7 +610,7 @@
 #define  PSYCHO_CEAFSR_RESV2	0x00000000007fffffUL /* Reserved                     */
 #define PSYCHO_CE_AFAR	0x0040UL
 
-static irqreturn_t psycho_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t psycho_ce_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR;
@@ -735,7 +735,7 @@
 	return ret;
 }
 
-static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
 {
 	struct pci_pbm_info *pbm = dev_id;
 	struct pci_controller_info *p = pbm->parent;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 4589185..94bb681 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -574,7 +574,7 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sabre_ue_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR;
@@ -634,7 +634,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sabre_ce_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR;
@@ -726,7 +726,7 @@
 	return ret;
 }
 
-static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg, afar_reg;
@@ -1196,7 +1196,7 @@
 					    &pbm->mem_space);
 }
 
-static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
+static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end)
 {
 	struct pci_pbm_info *pbm;
 	struct device_node *node;
@@ -1261,6 +1261,8 @@
 		node = node->sibling;
 	}
 	if (simbas_found == 0) {
+		struct resource *rp;
+
 		/* No APBs underneath, probably this is a hummingbird
 		 * system.
 		 */
@@ -1302,8 +1304,10 @@
 		pbm->io_space.end   = pbm->io_space.start + (1UL << 24) - 1UL;
 		pbm->io_space.flags = IORESOURCE_IO;
 
-		pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE;
-		pbm->mem_space.end   = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
+		pbm->mem_space.start =
+			(p->pbm_A.controller_regs + SABRE_MEMSPACE);
+		pbm->mem_space.end =
+			(pbm->mem_space.start + ((1UL << 32UL) - 1UL));
 		pbm->mem_space.flags = IORESOURCE_MEM;
 
 		if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
@@ -1315,6 +1319,17 @@
 			prom_halt();
 		}
 
+		rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+		if (!rp) {
+			prom_printf("Cannot allocate IOMMU resource.\n");
+			prom_halt();
+		}
+		rp->name = "IOMMU";
+		rp->start = pbm->mem_space.start + (unsigned long) dma_start;
+		rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL;
+		rp->flags = IORESOURCE_BUSY;
+		request_resource(&pbm->mem_space, rp);
+
 		pci_register_legacy_regions(&pbm->io_space,
 					    &pbm->mem_space);
 	}
@@ -1450,5 +1465,5 @@
 	/*
 	 * Look for APB underneath.
 	 */
-	sabre_pbm_init(p, dp, vdma[0]);
+	sabre_pbm_init(p, dp, vdma[0], vdma[0] + vdma[1]);
 }
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 75ade83e..66911b1 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -515,7 +515,7 @@
 #define SCHIZO_UEAFSR_MTAG	0x000000000000e000UL /* Safari */
 #define SCHIZO_UEAFSR_ECCSYND	0x00000000000001ffUL /* Safari */
 
-static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR;
@@ -603,7 +603,7 @@
 #define SCHIZO_CEAFSR_MTAG	0x000000000000e000UL
 #define SCHIZO_CEAFSR_ECCSYND	0x00000000000001ffUL
 
-static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_ce_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR;
@@ -778,7 +778,7 @@
 	return ret;
 }
 
-static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
 {
 	struct pci_pbm_info *pbm = dev_id;
 	struct pci_controller_info *p = pbm->parent;
@@ -933,7 +933,7 @@
 /* We only expect UNMAP errors here.  The rest of the Safari errors
  * are marked fatal and thus cause a system reset.
  */
-static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
 {
 	struct pci_controller_info *p = dev_id;
 	u64 errlog;
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 0b9c706..699b24b 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -35,7 +35,7 @@
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
 static int button_pressed;
 
-static irqreturn_t power_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t power_handler(int irq, void *dev_id)
 {
 	if (button_pressed == 0) {
 		button_pressed = 1;
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index c49a577..01d6d86 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -839,7 +839,7 @@
 #define  SYSIO_UEAFSR_SIZE  0x00001c0000000000UL /* Bad transfer size 2^SIZE  */
 #define  SYSIO_UEAFSR_MID   0x000003e000000000UL /* UPA MID causing the fault */
 #define  SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved                  */
-static irqreturn_t sysio_ue_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
 {
 	struct sbus_bus *sbus = dev_id;
 	struct sbus_iommu *iommu = sbus->iommu;
@@ -911,7 +911,7 @@
 #define  SYSIO_CEAFSR_SIZE  0x00001c0000000000UL /* Bad transfer size 2^SIZE  */
 #define  SYSIO_CEAFSR_MID   0x000003e000000000UL /* UPA MID causing the fault */
 #define  SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved                  */
-static irqreturn_t sysio_ce_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
 {
 	struct sbus_bus *sbus = dev_id;
 	struct sbus_iommu *iommu = sbus->iommu;
@@ -988,7 +988,7 @@
 #define  SYSIO_SBAFSR_SIZE  0x00001c0000000000UL /* Size of transfer          */
 #define  SYSIO_SBAFSR_MID   0x000003e000000000UL /* MID causing the error     */
 #define  SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved                  */
-static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
 {
 	struct sbus_bus *sbus = dev_id;
 	struct sbus_iommu *iommu = sbus->iommu;
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 9582874..bf033b3 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -74,7 +74,6 @@
 
 unsigned int boot_flags = 0;
 #define BOOTME_DEBUG  0x1
-#define BOOTME_SINGLE 0x2
 
 /* Exported for mm/init.c:paging_init. */
 unsigned long cmdline_memory_size = 0;
@@ -91,16 +90,6 @@
 {
 }
 
-int obp_system_intr(void)
-{
-	if (boot_flags & BOOTME_DEBUG) {
-		printk("OBP: system interrupted\n");
-		prom_halt();
-		return 1;
-	}
-	return 0;
-}
-
 /* 
  * Process kernel command line switches that are specific to the
  * SPARC or that require special low-level processing.
@@ -112,7 +101,6 @@
 		boot_flags |= BOOTME_DEBUG;
 		break;
 	case 's':
-		boot_flags |= BOOTME_SINGLE;
 		break;
 	case 'h':
 		prom_printf("boot_flags_init: Halt!\n");
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index f62bf3a..cc09d82 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -31,6 +31,7 @@
 #include <asm/cpudata.h>
 
 #include <asm/irq.h>
+#include <asm/irq_regs.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
@@ -1187,6 +1188,7 @@
 	unsigned long compare, tick, pstate;
 	int cpu = smp_processor_id();
 	int user = user_mode(regs);
+	struct pt_regs *old_regs;
 
 	/*
 	 * Check for level 14 softint.
@@ -1203,8 +1205,9 @@
 		clear_softint(tick_mask);
 	}
 
+	old_regs = set_irq_regs(regs);
 	do {
-		profile_tick(CPU_PROFILING, regs);
+		profile_tick(CPU_PROFILING);
 		if (!--prof_counter(cpu)) {
 			irq_enter();
 
@@ -1236,6 +1239,7 @@
 				     : /* no outputs */
 				     : "r" (pstate));
 	} while (time_after_eq(tick, compare));
+	set_irq_regs(old_regs);
 }
 
 static void __init smp_setup_percpu_timer(void)
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 00f6fc4..061e1b1 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -45,6 +45,7 @@
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
 #include <asm/prom.h>
+#include <asm/irq_regs.h>
 
 DEFINE_SPINLOCK(mostek_lock);
 DEFINE_SPINLOCK(rtc_lock);
@@ -452,7 +453,7 @@
 	}
 }
 
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	unsigned long ticks, compare, pstate;
 
@@ -460,8 +461,8 @@
 
 	do {
 #ifndef CONFIG_SMP
-		profile_tick(CPU_PROFILING, regs);
-		update_process_times(user_mode(regs));
+		profile_tick(CPU_PROFILING);
+		update_process_times(user_mode(get_irq_regs()));
 #endif
 		do_timer(1);
 
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index d753075..5ac1f29 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -1,3 +1,8 @@
+config DEFCONFIG_LIST
+	string
+	option defconfig_list
+	default "arch/$ARCH/defconfig"
+
 # UML uses the generic IRQ sugsystem
 config GENERIC_HARDIRQS
 	bool
@@ -25,6 +30,19 @@
 config PCMCIA
 	bool
 
+# Yet to do!
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	default n
+
+config LOCKDEP_SUPPORT
+	bool
+	default y
+
+config STACKTRACE_SUPPORT
+	bool
+	default y
+
 config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
@@ -37,13 +55,16 @@
 menu "UML-specific options"
 
 config MODE_TT
-	bool "Tracing thread support"
+	bool "Tracing thread support (DEPRECATED)"
 	default n
+	depends on BROKEN
 	help
 	This option controls whether tracing thread support is compiled
-	into UML.  This option is largely obsolete, given that skas0 provides
+	into UML. This option is largely obsolete, given that skas0 provides
 	skas security and performance without needing to patch the host.
-	It is safe to say 'N' here.
+	It is safe to say 'N' here; saying 'Y' may cause additional problems
+	with the resulting binary even if you run UML in SKAS mode, and running
+	in TT mode is strongly *NOT RECOMMENDED*.
 
 config STATIC_LINK
 	bool "Force a static link"
@@ -56,6 +77,9 @@
 	for use in a chroot jail.  So, if you intend to run UML inside a
 	chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
 	here.
+	Additionally, this option enables using higher memory spaces (up to
+	2.75G) for UML - disabling CONFIG_MODE_TT and enabling this option leads
+	to best results for this.
 
 config KERNEL_HALF_GIGS
 	int "Kernel address space size (in .5G units)"
@@ -72,10 +96,13 @@
 	default y
 	help
 	This option controls whether skas (separate kernel address space)
-	support is compiled in.  If you have applied the skas patch to the
-	host, then you certainly want to say Y here (and consider saying N
-	to CONFIG_MODE_TT).  Otherwise, it is safe to say Y.  Disabling this
-	option will shrink the UML binary slightly.
+	support is compiled in.
+	Unless you have specific needs to use TT mode (which applies almost only
+	to developers), you should say Y here.
+	SKAS mode will make use of the SKAS3 patch if it is applied on the host
+	(and your UML will run in SKAS3 mode), but if no SKAS patch is applied
+	on the host it will run in SKAS0 mode, which is anyway faster than TT
+	mode.
 
 source "arch/um/Kconfig.arch"
 source "mm/Kconfig"
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 62d87b7..e03e40c 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -190,6 +190,11 @@
 	tristate
 	default UML_SOUND
 
+#It is selected elsewhere, so kconfig would warn without this.
+config HW_RANDOM
+	tristate
+	default n
+
 config UML_RANDOM
 	tristate "Hardware random number generator"
 	help
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index f6eb72d..f191a55 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -16,23 +16,42 @@
 	bool
 	default y
 
-config HOST_2G_2G
-	bool "2G/2G host address space split"
-	default n
-	help
-	This is needed when the host on which you run has a 2G/2G memory
-	split, instead of the customary 3G/1G.
+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.
 
-	Note that to enable such a host
-	configuration, which makes sense only in some cases, you need special
-	host patches.
+	   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.
 
-	So, if you do not know what to do here, say 'N'.
+	   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'.
+
+	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
- 	hex
- 	default 0xc0000000 if !HOST_2G_2G
- 	default 0x80000000 if HOST_2G_2G
+	hex
+	default 0xB0000000 if HOST_VMSPLIT_3G_OPT
+	default 0x78000000 if HOST_VMSPLIT_2G
+	default 0x40000000 if HOST_VMSPLIT_1G
+	default 0xC0000000
 
 config 3_LEVEL_PGTABLES
 	bool "Three-level pagetables (EXPERIMENTAL)"
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 11154b6..d278682 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -1,10 +1,10 @@
 # Copyright 2003 - 2004 Pathscale, Inc
 # Released under the GPL
 
-core-y += arch/um/sys-x86_64/
+core-y += arch/um/sys-x86_64/ arch/x86_64/crypto/
 START := 0x60000000
 
-_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel
+_extra_flags_ = -fno-builtin -m64
 
 #We #undef __x86_64__ for kernelspace, not for userspace where
 #it's needed for headers to work!
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 7a5b4af..c6a3084 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -5,6 +5,7 @@
 #include "user_util.h"
 #include "os.h"
 #include "user.h"
+#include "um_malloc.h"
 
 static inline void *cow_malloc(int size)
 {
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index 77954ea..310af0f 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -17,6 +17,7 @@
 #include "user_util.h"
 #include "user.h"
 #include "os.h"
+#include "um_malloc.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 108b7da..218aa0e 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -12,6 +12,7 @@
 #include "user_util.h"
 #include "chan_user.h"
 #include "os.h"
+#include "um_malloc.h"
 
 struct fd_chan {
 	int fd;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index cfd9f01..426633e 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -20,7 +20,7 @@
 
 #define LINE_BUFSIZE 4096
 
-static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_interrupt(int irq, void *data)
 {
 	struct chan *chan = data;
 	struct line *line = chan->line;
@@ -364,8 +364,7 @@
 		reactivate_chan(&line->chan_list, line->driver->read_irq);
 }
 
-static irqreturn_t line_write_interrupt(int irq, void *data,
-					struct pt_regs *unused)
+static irqreturn_t line_write_interrupt(int irq, void *data)
 {
 	struct chan *chan = data;
 	struct line *line = chan->line;
@@ -712,7 +711,7 @@
 	struct tty_struct *tty;
 };
 
-static irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t winch_interrupt(int irq, void *data)
 {
 	struct winch *winch = data;
 	struct tty_struct *tty;
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 4d2bd39..8138f5e 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -23,6 +23,7 @@
 #include "user_util.h"
 #include "user.h"
 #include "os.h"
+#include "um_malloc.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index a67dcbd..d08bd03 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -74,8 +74,7 @@
 
 static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
 
-static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
 {
 	/* long to avoid size mismatch warnings from gcc */
 	long fd;
@@ -674,8 +673,9 @@
 static void sysrq_proc(void *arg)
 {
 	char *op = arg;
-
-	handle_sysrq(*op, &current->thread.regs, NULL);
+	struct pt_regs *old_regs = set_irq_regs(&current->thread.regs);
+	handle_sysrq(*op, NULL);
+	set_irq_regs(old_regs);
 }
 
 void mconsole_sysrq(struct mc_request *req)
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 9a3b5da..df3516e 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -95,7 +95,8 @@
 	.release	= mmapper_release,
 };
 
-static const struct miscdevice mmapper_dev = {
+/* No locking needed - only used (and modified) by below initcall and exitcall. */
+static struct miscdevice mmapper_dev = {
 	.minor		= MISC_DYNAMIC_MINOR,
 	.name		= "mmapper",
 	.fops		= &mmapper_fops
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index c1c5604..ec9eb8b 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -77,7 +77,7 @@
 	dev_close( (struct net_device *) dev);
 }
 
-irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t uml_net_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct uml_net_private *lp = dev->priv;
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index f3a3f8a..0ffd7ac 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -18,6 +18,7 @@
 #include "kern_util.h"
 #include "net_user.h"
 #include "os.h"
+#include "um_malloc.h"
 
 int tap_open_common(void *dev, char *gate_addr)
 {
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 2ef641d..11921a7 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -12,6 +12,7 @@
 #include "net_user.h"
 #include "pcap_user.h"
 #include "user.h"
+#include "um_malloc.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
diff --git a/arch/um/drivers/pcap_user.h b/arch/um/drivers/pcap_user.h
index 58f9f6a..96b80b5 100644
--- a/arch/um/drivers/pcap_user.h
+++ b/arch/um/drivers/pcap_user.h
@@ -15,7 +15,7 @@
 	void *dev;
 };
 
-extern struct net_user_info pcap_user_info;
+extern const struct net_user_info pcap_user_info;
 
 extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri);
 
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 73755f3..ce9f373 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -47,7 +47,7 @@
 	struct port_list *port;
 };
 
-static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t pipe_interrupt(int irq, void *data)
 {
 	struct connection *conn = data;
 	int fd;
@@ -152,7 +152,7 @@
 
 DECLARE_WORK(port_work, port_work_proc, NULL);
 
-static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t port_interrupt(int irq, void *data)
 {
 	struct port_list *port = data;
 
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index f2e8fc4..bc6afaf 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -19,6 +19,7 @@
 #include "chan_user.h"
 #include "port.h"
 #include "os.h"
+#include "um_malloc.h"
 
 struct port_chan {
 	int raw;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index abec620..829a5ec 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -13,6 +13,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
+#include "um_malloc.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 8460285..7eddacc 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -15,6 +15,7 @@
 #include "slip.h"
 #include "slip_common.h"
 #include "os.h"
+#include "um_malloc.h"
 
 void slip_user_init(void *data, void *dev)
 {
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 11de3ac..d95d643 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -11,6 +11,7 @@
 #include "user_util.h"
 #include "user.h"
 #include "os.h"
+#include "um_malloc.h"
 
 struct tty_chan {
 	char *dev;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index f0b0668..bc458f5 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -524,7 +524,7 @@
 	do_ubd_request(ubd_queue);
 }
 
-static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
+static irqreturn_t ubd_intr(int irq, void *dev)
 {
 	ubd_handler();
 	return(IRQ_HANDLED);
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 386f8b9..850221d 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -136,8 +136,6 @@
 		return(pid);
 	}
 
-	if(data->stack == 0) free_stack(stack, 0);
-
 	if (data->direct_rcv) {
 		new = os_rcv_fd(fd, &data->helper_pid);
 	} else {
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index 6036ec8..a4ce705 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -21,7 +21,7 @@
 	int new_fd;
 };
 
-static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t xterm_interrupt(int irq, void *data)
 {
 	struct xterm_wait *xterm = data;
 	int fd;
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 356390d..461175f 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -1,9 +1,16 @@
 /* for use by sys-$SUBARCH/kernel-offsets.c */
 
+DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
+#ifdef CONFIG_MODE_TT
+OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
+#endif
+
 OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
 OFFSET(HOST_TASK_PID, task_struct, pid);
+
 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
 DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
+
 DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
 DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
 DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
@@ -12,6 +19,10 @@
 DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
 DEFINE_STR(UM_KERN_INFO, KERN_INFO);
 DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
+
 DEFINE(UM_ELF_CLASS, ELF_CLASS);
 DEFINE(UM_ELFCLASS32, ELFCLASS32);
 DEFINE(UM_ELFCLASS64, ELFCLASS64);
+
+/* For crypto assembler code. */
+DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
diff --git a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h
index c222d56..4f77559 100644
--- a/arch/um/include/irq_kern.h
+++ b/arch/um/include/irq_kern.h
@@ -10,12 +10,11 @@
 #include "asm/ptrace.h"
 
 extern int um_request_irq(unsigned int irq, int fd, int type,
-			  irqreturn_t (*handler)(int, void *,
-						 struct pt_regs *),
+			  irq_handler_t handler,
 			  unsigned long irqflags,  const char * devname,
 			  void *dev_id);
 extern int init_aio_irq(int irq, char *name,
-			irqreturn_t (*handler)(int, void *, struct pt_regs *));
+			irq_handler_t handler);
 
 #endif
 
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 59cfa9e..cec9fcc 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -6,7 +6,6 @@
 #ifndef __KERN_UTIL_H__
 #define __KERN_UTIL_H__
 
-#include "linux/threads.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/faultinfo.h"
 
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index e93c6d3..e860bc5 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -12,7 +12,8 @@
 } while(0)
 
 #define UML_SETJMP(buf) ({ \
-	int n, enable;	   \
+	int n;	   \
+	volatile int enable;	\
 	enable = get_signals(); \
 	n = setjmp(*buf); \
 	if(n != 0) \
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 120ca21..6516f6d 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -201,6 +201,7 @@
 
 #ifdef UML_CONFIG_MODE_TT
 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
+extern void stop(void);
 #endif
 extern void init_new_thread_signals(void);
 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h
index 2c13de3..97ec9d8 100644
--- a/arch/um/include/sysdep-i386/kernel-offsets.h
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,6 +1,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/elf.h>
+#include <linux/crypto.h>
 #include <asm/mman.h>
 
 #define DEFINE(sym, val) \
@@ -17,9 +18,5 @@
 void foo(void)
 {
 	OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
-	DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
-#ifdef CONFIG_MODE_TT
-	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
-#endif
 #include <common-offsets.h>
 }
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index 91d129f..a307237 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -2,6 +2,7 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/elf.h>
+#include <linux/crypto.h>
 #include <asm/page.h>
 #include <asm/mman.h>
 
@@ -18,9 +19,5 @@
 
 void foo(void)
 {
-	DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
-#ifdef CONFIG_MODE_TT
-	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
-#endif
 #include <common-offsets.h>
 }
diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h
new file mode 100644
index 0000000..0363a9b
--- /dev/null
+++ b/arch/um/include/um_malloc.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_MALLOC_H__
+#define __UM_MALLOC_H__
+
+extern void *um_kmalloc(int size);
+extern void *um_kmalloc_atomic(int size);
+extern void kfree(const void *ptr);
+
+extern void *um_vmalloc(int size);
+extern void *um_vmalloc_atomic(int size);
+extern void vfree(void *ptr);
+
+#endif /* __UM_MALLOC_H__ */
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 39f8c88..acadce3 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -11,17 +11,11 @@
 extern int printk(const char *fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
 extern void schedule(void);
-extern void *um_kmalloc(int size);
-extern void *um_kmalloc_atomic(int size);
-extern void kfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
 /* These use size_t, however unsigned long is correct on both i386 and x86_64. */
 extern unsigned long strlcpy(char *, const char *, unsigned long);
 extern unsigned long strlcat(char *, const char *, unsigned long);
-extern void *um_vmalloc(int size);
-extern void *um_vmalloc_atomic(int size);
-extern void vfree(void *ptr);
 
 #endif
 
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 802d784..06625fe 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -52,7 +52,6 @@
 extern void set_cmdline(char *cmd);
 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
 extern int get_pty(void);
-extern void *um_kmalloc(int size);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void do_exec(int old_pid, int new_pid);
 extern void tracer_panic(char *msg, ...)
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index eee97bb..5c1e611 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -31,6 +31,7 @@
 #include "irq_kern.h"
 #include "os.h"
 #include "sigio.h"
+#include "um_malloc.h"
 #include "misc_constants.h"
 
 /*
@@ -355,14 +356,16 @@
  */
 unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
 {
-       irq_enter();
-       __do_IRQ(irq, (struct pt_regs *)regs);
-       irq_exit();
-       return 1;
+	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
+	irq_enter();
+	__do_IRQ(irq);
+	irq_exit();
+	set_irq_regs(old_regs);
+	return 1;
 }
 
 int um_request_irq(unsigned int irq, int fd, int type,
-		   irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		   irq_handler_t handler,
 		   unsigned long irqflags, const char * devname,
 		   void *dev_id)
 {
@@ -423,8 +426,7 @@
 	}
 }
 
-int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
-							     struct pt_regs *))
+int init_aio_irq(int irq, char *name, irq_handler_t handler)
 {
 	int fds[2], err;
 
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index fe6c64a..348b272 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -46,6 +46,7 @@
 #include "mode.h"
 #include "mode_kern.h"
 #include "choose-mode.h"
+#include "um_malloc.h"
 
 /* This is a per-cpu array.  A processor only modifies its entry and it only
  * cares about its entry, so it's OK if another processor is modifying its
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 0ad755c..2b0ab43 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -17,7 +17,7 @@
 /* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
 
-static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t sigio_interrupt(int irq, void *data)
 {
 	char c;
 
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index c17eddc..2c6d090 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -60,10 +60,7 @@
 #endif
 
 	*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
-	/* This is wrong for the code page, but it doesn't matter since the
-	 * stub is mapped by hand with the correct permissions.
-	 */
-	*pte = pte_mkwrite(*pte);
+	*pte = pte_mkread(*pte);
 	return(0);
 
  out_pmd:
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index a92965f..2e354b3 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -86,7 +86,7 @@
 	return nsecs;
 }
 
-irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t um_timer(int irq, void *dev)
 {
 	unsigned long long nsecs;
 	unsigned long flags;
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index 6c92bbc..ed1abcf 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -4,13 +4,13 @@
  * Licensed under the GPL
  */
 
-#include <setjmp.h>
 #include <string.h>
 #include "user_util.h"
 #include "uml_uaccess.h"
 #include "task.h"
 #include "kern_util.h"
 #include "os.h"
+#include "longjmp.h"
 
 int __do_copy_from_user(void *to, const void *from, int n,
 			void **fault_addr, void **fault_catcher)
@@ -80,10 +80,10 @@
 	struct tt_regs save = TASK_REGS(get_current())->tt;
 	int ret;
 	unsigned long *faddrp = (unsigned long *)fault_addr;
-	sigjmp_buf jbuf;
+	jmp_buf jbuf;
 
 	*fault_catcher = &jbuf;
-	if(sigsetjmp(jbuf, 1) == 0)
+	if(UML_SETJMP(&jbuf) == 0)
 		ret = strlen(str) + 1;
 	else ret = *faddrp - (unsigned long) str;
 
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index f559bdf..863981b 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -20,6 +20,7 @@
 #include "net_user.h"
 #include "etap.h"
 #include "os.h"
+#include "um_malloc.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
 
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index cd15b9d..d13299c 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -35,22 +35,23 @@
 	char **argv = data->argv;
 	int errval;
 
-	if(helper_pause){
+	if (helper_pause){
 		signal(SIGHUP, helper_hup);
 		pause();
 	}
-	if(data->pre_exec != NULL)
+	if (data->pre_exec != NULL)
 		(*data->pre_exec)(data->pre_data);
 	execvp(argv[0], argv);
 	errval = -errno;
 	printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
 	os_write_file(data->fd, &errval, sizeof(errval));
 	kill(os_getpid(), SIGKILL);
-	return(0);
+	return 0;
 }
 
 /* Returns either the pid of the child process we run or -E* on failure.
- * XXX The alloc_stack here breaks if this is called in the tracing thread */
+ * XXX The alloc_stack here breaks if this is called in the tracing thread, so
+ * we need to receive a preallocated stack (a local buffer is ok). */
 int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
 	       unsigned long *stack_out)
 {
@@ -58,20 +59,21 @@
 	unsigned long stack, sp;
 	int pid, fds[2], ret, n;
 
-	if((stack_out != NULL) && (*stack_out != 0))
+	if ((stack_out != NULL) && (*stack_out != 0))
 		stack = *stack_out;
-	else stack = alloc_stack(0, __cant_sleep());
-	if(stack == 0)
+	else
+		stack = alloc_stack(0, __cant_sleep());
+	if (stack == 0)
 		return -ENOMEM;
 
 	ret = os_pipe(fds, 1, 0);
-	if(ret < 0){
+	if (ret < 0) {
 		printk("run_helper : pipe failed, ret = %d\n", -ret);
 		goto out_free;
 	}
 
 	ret = os_set_exec_close(fds[1], 1);
-	if(ret < 0){
+	if (ret < 0) {
 		printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
 		       -ret);
 		goto out_close;
@@ -83,7 +85,7 @@
 	data.argv = argv;
 	data.fd = fds[1];
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
-	if(pid < 0){
+	if (pid < 0) {
 		ret = -errno;
 		printk("run_helper : clone failed, errno = %d\n", errno);
 		goto out_close;
@@ -95,10 +97,10 @@
 	/* Read the errno value from the child, if the exec failed, or get 0 if
 	 * the exec succeeded because the pipe fd was set as close-on-exec. */
 	n = os_read_file(fds[0], &ret, sizeof(ret));
-	if(n == 0)
+	if (n == 0) {
 		ret = pid;
-	else {
-		if(n < 0){
+	} else {
+		if (n < 0) {
 			printk("run_helper : read on pipe failed, ret = %d\n",
 			       -n);
 			ret = n;
@@ -112,10 +114,9 @@
 		close(fds[1]);
 	close(fds[0]);
 out_free:
-	if(stack_out == NULL)
+	if ((stack_out == NULL) || (*stack_out == 0))
 		free_stack(stack, 0);
-	else *stack_out = stack;
-	return(ret);
+	return ret;
 }
 
 int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
@@ -125,31 +126,32 @@
 	int pid, status, err;
 
 	stack = alloc_stack(stack_order, __cant_sleep());
-	if(stack == 0) return(-ENOMEM);
+	if (stack == 0)
+		return -ENOMEM;
 
 	sp = stack + (page_size() << stack_order) - sizeof(void *);
 	pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
-	if(pid < 0){
+	if (pid < 0) {
 		err = -errno;
 		printk("run_helper_thread : clone failed, errno = %d\n",
 		       errno);
 		return err;
 	}
-	if(stack_out == NULL){
+	if (stack_out == NULL) {
 		CATCH_EINTR(pid = waitpid(pid, &status, 0));
-		if(pid < 0){
+		if (pid < 0) {
 			err = -errno;
 			printk("run_helper_thread - wait failed, errno = %d\n",
 			       errno);
 			pid = err;
 		}
-		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
+		if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
 			       "0x%x\n", status);
 		free_stack(stack, stack_order);
-	}
-	else *stack_out = stack;
-	return(pid);
+	} else
+		*stack_out = stack;
+	return pid;
 }
 
 int helper_wait(int pid)
@@ -157,9 +159,9 @@
 	int ret;
 
 	CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
-	if(ret < 0){
+	if (ret < 0) {
 		ret = -errno;
 		printk("helper_wait : waitpid failed, errno = %d\n", errno);
 	}
-	return(ret);
+	return ret;
 }
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index a97206d..d46b818 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -18,6 +18,7 @@
 #include "sigio.h"
 #include "irq_user.h"
 #include "os.h"
+#include "um_malloc.h"
 
 static struct pollfd *pollfds = NULL;
 static int pollfds_num = 0;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index d1c5670..685feaa 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -23,6 +23,7 @@
 #include "choose-mode.h"
 #include "uml-config.h"
 #include "os.h"
+#include "um_malloc.h"
 
 /* Set in set_stklim, which is called from main and __wrap_malloc.
  * __wrap_malloc only calls it if main hasn't started.
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index f645776..925a652 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -19,6 +19,7 @@
 #include "user_util.h"
 #include "sigio.h"
 #include "os.h"
+#include "um_malloc.h"
 
 /* Protected by sigio_lock(), also used by sigio_cleanup, which is an
  * exitcall.
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 38be096e..2115b8b 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -16,6 +16,7 @@
 #include "process.h"
 #include "kern_constants.h"
 #include "os.h"
+#include "uml-config.h"
 
 int set_interval(int is_virtual)
 {
@@ -30,7 +31,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_MODE_TT
+#ifdef UML_CONFIG_MODE_TT
 void enable_timer(void)
 {
 	set_interval(1);
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index 5461a06..3dc3a02 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -10,7 +10,6 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <stdlib.h>
-#include <setjmp.h>
 #include <sys/time.h>
 #include <sys/ptrace.h>
 #include <linux/ptrace.h>
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 3f5b151..56b8a50 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -80,11 +80,18 @@
 	struct utsname host;
 
 	uname(&host);
-#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT)
+#ifdef UML_CONFIG_UML_X86
+# ifndef UML_CONFIG_64BIT
 	if (!strcmp(host.machine, "x86_64")) {
 		strcpy(machine_out, "i686");
 		return;
 	}
+# else
+	if (!strcmp(host.machine, "i686")) {
+		strcpy(machine_out, "x86_64");
+		return;
+	}
+# endif
 #endif
 	strcpy(machine_out, host.machine);
 }
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
index 8592738..12c5936 100644
--- a/arch/um/sys-x86_64/ksyms.c
+++ b/arch/um/sys-x86_64/ksyms.c
@@ -14,6 +14,3 @@
 
 /*XXX: we need them because they would be exported by x86_64 */
 EXPORT_SYMBOL(__memcpy);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 1c96702..652fa34 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -5,7 +5,6 @@
 
 #include <stddef.h>
 #include <signal.h>
-#include <linux/compiler.h>
 #include <asm/unistd.h>
 #include "uml-config.h"
 #include "sysdep/sigcontext.h"
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 1c0f18d..1397214 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -54,6 +54,10 @@
 cflags-y += $(call cc-option,-funit-at-a-time)
 # prevent gcc from generating any FP code by mistake
 cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+# this works around some issues with generating unwind tables in older gccs
+# newer gccs do it by default
+cflags-y += -maccumulate-outgoing-args
+
 # do binutils support CFI?
 cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
 AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 4844b54..0f5d44e 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.18-git7
-# Wed Sep 27 21:53:10 2006
+# Linux kernel version: 2.6.19-rc2-git4
+# Sat Oct 21 03:38:52 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -19,6 +19,7 @@
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_DMI=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -37,9 +38,11 @@
 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_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -47,9 +50,10 @@
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -82,6 +86,7 @@
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
@@ -252,9 +257,11 @@
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_HT_IRQ is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -309,6 +316,7 @@
 # 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
@@ -325,9 +333,10 @@
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
 # CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -429,6 +438,13 @@
 # CONFIG_ATA_OVER_ETH is not set
 
 #
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
@@ -473,6 +489,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=y
 # CONFIG_BLK_DEV_IT821X is not set
@@ -564,6 +581,7 @@
 # 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
@@ -605,7 +623,6 @@
 # CONFIG_PATA_HPT3X3 is not set
 # CONFIG_PATA_IT821X is not set
 # CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_LEGACY is not set
 # CONFIG_PATA_TRIFLEX is not set
 # CONFIG_PATA_MPIIX is not set
 # CONFIG_PATA_OLDPIIX is not set
@@ -614,7 +631,6 @@
 # CONFIG_PATA_OPTI is not set
 # CONFIG_PATA_OPTIDMA is not set
 # CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_QDI is not set
 # CONFIG_PATA_RADISYS is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
@@ -631,6 +647,7 @@
 CONFIG_MD=y
 # CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
 # CONFIG_DM_CRYPT is not set
 # CONFIG_DM_SNAPSHOT is not set
 # CONFIG_DM_MIRROR is not set
@@ -819,6 +836,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -841,6 +859,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
@@ -996,6 +1015,7 @@
 #
 # Dallas's 1-wire bus
 #
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -1008,6 +1028,7 @@
 # CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_K8TEMP is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
@@ -1034,6 +1055,7 @@
 # CONFIG_SENSORS_SMSC47M192 is not set
 CONFIG_SENSORS_SMSC47B397=m
 # 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
@@ -1045,15 +1067,9 @@
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Misc devices
-#
-# CONFIG_IBM_ASM is not set
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1159,6 +1175,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
 
 #
@@ -1212,6 +1229,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
@@ -1219,12 +1237,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
 
 #
@@ -1301,6 +1320,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
@@ -1313,6 +1333,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
@@ -1323,6 +1344,7 @@
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -1347,8 +1369,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1482,11 +1506,14 @@
 # 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_UNWIND_INFO=y
 CONFIG_STACK_UNWIND=y
 # 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
 # CONFIG_IOMMU_DEBUG is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
index d18198e..3a7561d 100644
--- a/arch/x86_64/ia32/ptrace32.c
+++ b/arch/x86_64/ia32/ptrace32.c
@@ -205,9 +205,9 @@
 static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
 {
 	int ret;
-	compat_siginfo_t *si32 = (compat_siginfo_t *)compat_ptr(data);
+	compat_siginfo_t __user *si32 = compat_ptr(data);
 	siginfo_t ssi; 
-	siginfo_t *si = compat_alloc_user_space(sizeof(siginfo_t));
+	siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
 	if (request == PTRACE_SETSIGINFO) {
 		memset(&ssi, 0, sizeof(siginfo_t));
 		ret = copy_siginfo_from_user32(&ssi, si32);
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 6472e32..4d9d5ed 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -885,14 +885,14 @@
  * value into /proc/profile.
  */
 
-void smp_local_timer_interrupt(struct pt_regs *regs)
+void smp_local_timer_interrupt(void)
 {
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #ifdef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 	if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id)
-		main_timer_handler(regs);
+		main_timer_handler();
 	/*
 	 * We take the 'long' return path, and there every subsystem
 	 * grabs the appropriate locks (kernel lock/ irq lock).
@@ -915,6 +915,8 @@
  */
 void smp_apic_timer_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
 	/*
 	 * the NMI deadlock-detector uses this.
 	 */
@@ -932,8 +934,9 @@
 	 */
 	exit_idle();
 	irq_enter();
-	smp_local_timer_interrupt(regs);
+	smp_local_timer_interrupt();
 	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 /*
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index b3f0908..a75c829 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -54,13 +54,13 @@
 
 	/* various gunk below that needed for SMP startup */
 	if (addr < 0x8000) { 
-		*addrp = 0x8000;
+		*addrp = PAGE_ALIGN(0x8000);
 		return 1; 
 	}
 
 	/* direct mapping tables of the kernel */
 	if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 
-		*addrp = table_end << PAGE_SHIFT; 
+		*addrp = PAGE_ALIGN(table_end << PAGE_SHIFT);
 		return 1;
 	} 
 
@@ -68,18 +68,18 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (LOADER_TYPE && INITRD_START && last >= INITRD_START && 
 	    addr < INITRD_START+INITRD_SIZE) { 
-		*addrp = INITRD_START + INITRD_SIZE; 
+		*addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE);
 		return 1;
 	} 
 #endif
 	/* kernel code */
-	if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
-		*addrp = __pa_symbol(&_end);
+	if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
+		*addrp = PAGE_ALIGN(__pa_symbol(&_end));
 		return 1;
 	}
 
 	if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
-		*addrp = ebda_addr + ebda_size;
+		*addrp = PAGE_ALIGN(ebda_addr + ebda_size);
 		return 1;
 	}
 
@@ -152,7 +152,7 @@
 			continue; 
 		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
 			;
-		last = addr + size;
+		last = PAGE_ALIGN(addr) + size;
 		if (last > ei->addr + ei->size)
 			continue;
 		if (last > end) 
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
index 208e38a..2b1245d 100644
--- a/arch/x86_64/kernel/early-quirks.c
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -61,10 +61,11 @@
 
 static void ati_bugs(void)
 {
-#if 1 /* for testing */
-	printk("ATI board detected\n");
-#endif
-	/* No bugs right now */
+	if (timer_over_8254 == 1) {
+		timer_over_8254 = 0;
+		printk(KERN_INFO
+	 	"ATI board detected. Disabling timer routing over 8254.\n");
+	}
 }
 
 struct chipset {
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index b8285cf..7d401b0 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -315,6 +315,8 @@
 	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	cmpq $__NR_syscall_max,%rax
+	movq $-ENOSYS,%rcx
+	cmova %rcx,%rax
 	ja  1f
 	movq %r10,%rcx	/* fixup for C */
 	call *sys_call_table(,%rax,8)
diff --git a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
index cdb90e6..73d7630 100644
--- a/arch/x86_64/kernel/genapic_cluster.c
+++ b/arch/x86_64/kernel/genapic_cluster.c
@@ -63,6 +63,13 @@
 	return cpumask_of_cpu(0);
 }
 
+static cpumask_t cluster_vector_allocation_domain(int cpu)
+{
+	cpumask_t domain = CPU_MASK_NONE;
+	cpu_set(cpu, domain);
+	return domain;
+}
+
 static void cluster_send_IPI_mask(cpumask_t mask, int vector)
 {
 	send_IPI_mask_sequence(mask, vector);
@@ -119,6 +126,7 @@
 	.int_delivery_mode = dest_Fixed,
 	.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
 	.target_cpus = cluster_target_cpus,
+	.vector_allocation_domain = cluster_vector_allocation_domain,
 	.apic_id_registered = cluster_apic_id_registered,
 	.init_apic_ldr = cluster_init_apic_ldr,
 	.send_IPI_all = cluster_send_IPI_all,
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index 50ad153..7c01db8 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -22,6 +22,20 @@
 	return cpu_online_map;
 }
 
+static cpumask_t flat_vector_allocation_domain(int cpu)
+{
+	/* Careful. Some cpus do not strictly honor the set of cpus
+	 * specified in the interrupt destination when using lowest
+	 * priority interrupt delivery mode.
+	 *
+	 * In particular there was a hyperthreading cpu observed to
+	 * deliver interrupts to the wrong hyperthread when only one
+	 * hyperthread was specified in the interrupt desitination.
+	 */
+	cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
+	return domain;
+}
+
 /*
  * Set up the logical destination ID.
  *
@@ -121,6 +135,7 @@
 	.int_delivery_mode = dest_LowestPrio,
 	.int_dest_mode = (APIC_DEST_LOGICAL != 0),
 	.target_cpus = flat_target_cpus,
+	.vector_allocation_domain = flat_vector_allocation_domain,
 	.apic_id_registered = flat_apic_id_registered,
 	.init_apic_ldr = flat_init_apic_ldr,
 	.send_IPI_all = flat_send_IPI_all,
@@ -138,9 +153,17 @@
 
 static cpumask_t physflat_target_cpus(void)
 {
-	return cpumask_of_cpu(0);
+	return cpu_online_map;
 }
 
+static cpumask_t physflat_vector_allocation_domain(int cpu)
+{
+	cpumask_t domain = CPU_MASK_NONE;
+	cpu_set(cpu, domain);
+	return domain;
+}
+
+
 static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
 {
 	send_IPI_mask_sequence(cpumask, vector);
@@ -179,6 +202,7 @@
 	.int_delivery_mode = dest_Fixed,
 	.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
 	.target_cpus = physflat_target_cpus,
+	.vector_allocation_domain = physflat_vector_allocation_domain,
 	.apic_id_registered = flat_apic_id_registered,
 	.init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
 	.send_IPI_all = physflat_send_IPI_all,
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 0612a33..c4ef801 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -178,7 +178,8 @@
 {
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
-	set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
+	set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
+				      "XT");
 	enable_irq(irq);
 }
 
@@ -431,8 +432,8 @@
 			/*
 			 * 16 old-style INTA-cycle interrupts:
 			 */
-			set_irq_chip_and_handler(i, &i8259A_chip,
-						 handle_level_irq);
+			set_irq_chip_and_handler_name(i, &i8259A_chip,
+						      handle_level_irq, "XT");
 		} else {
 			/*
 			 * 'high' PCI IRQs filled in on demand
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 91728d9..b000017 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -47,7 +47,7 @@
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 
-static int assign_irq_vector(int irq, cpumask_t mask);
+static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
 
 #define __apicdebuginit  __init
 
@@ -57,7 +57,7 @@
 
 static int disable_timer_pin_1 __initdata;
 
-int timer_over_8254 __initdata = 0;
+int timer_over_8254 __initdata = 1;
 
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -174,12 +174,10 @@
 
 	cpus_and(mask, tmp, CPU_MASK_ALL);
 
-	vector = assign_irq_vector(irq, mask);
+	vector = assign_irq_vector(irq, mask, &tmp);
 	if (vector < 0)
 		return;
 
-	cpus_clear(tmp);
-	cpu_set(vector >> 8, tmp);
 	dest = cpu_mask_to_apicid(tmp);
 
 	/*
@@ -188,7 +186,7 @@
 	dest = SET_APIC_LOGICAL_ID(dest);
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	__target_IO_APIC_irq(irq, dest, vector & 0xff);
+	__target_IO_APIC_irq(irq, dest, vector);
 	set_native_irq_info(irq, mask);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
@@ -563,9 +561,45 @@
 }
 
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-unsigned int irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_EXTERNAL_VECTOR, 0 };
+static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = {
+	[0] = FIRST_EXTERNAL_VECTOR + 0,
+	[1] = FIRST_EXTERNAL_VECTOR + 1,
+	[2] = FIRST_EXTERNAL_VECTOR + 2,
+	[3] = FIRST_EXTERNAL_VECTOR + 3,
+	[4] = FIRST_EXTERNAL_VECTOR + 4,
+	[5] = FIRST_EXTERNAL_VECTOR + 5,
+	[6] = FIRST_EXTERNAL_VECTOR + 6,
+	[7] = FIRST_EXTERNAL_VECTOR + 7,
+	[8] = FIRST_EXTERNAL_VECTOR + 8,
+	[9] = FIRST_EXTERNAL_VECTOR + 9,
+	[10] = FIRST_EXTERNAL_VECTOR + 10,
+	[11] = FIRST_EXTERNAL_VECTOR + 11,
+	[12] = FIRST_EXTERNAL_VECTOR + 12,
+	[13] = FIRST_EXTERNAL_VECTOR + 13,
+	[14] = FIRST_EXTERNAL_VECTOR + 14,
+	[15] = FIRST_EXTERNAL_VECTOR + 15,
+};
 
-static int __assign_irq_vector(int irq, cpumask_t mask)
+static cpumask_t irq_domain[NR_IRQ_VECTORS] __read_mostly = {
+	[0] = CPU_MASK_ALL,
+	[1] = CPU_MASK_ALL,
+	[2] = CPU_MASK_ALL,
+	[3] = CPU_MASK_ALL,
+	[4] = CPU_MASK_ALL,
+	[5] = CPU_MASK_ALL,
+	[6] = CPU_MASK_ALL,
+	[7] = CPU_MASK_ALL,
+	[8] = CPU_MASK_ALL,
+	[9] = CPU_MASK_ALL,
+	[10] = CPU_MASK_ALL,
+	[11] = CPU_MASK_ALL,
+	[12] = CPU_MASK_ALL,
+	[13] = CPU_MASK_ALL,
+	[14] = CPU_MASK_ALL,
+	[15] = CPU_MASK_ALL,
+};
+
+static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
 {
 	/*
 	 * NOTE! The local APIC isn't very good at handling
@@ -587,16 +621,24 @@
 
 	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
 
-	if (IO_APIC_VECTOR(irq) > 0)
-		old_vector = IO_APIC_VECTOR(irq);
-	if ((old_vector > 0) && cpu_isset(old_vector >> 8, mask)) {
-		return old_vector;
+	if (irq_vector[irq] > 0)
+		old_vector = irq_vector[irq];
+	if (old_vector > 0) {
+		cpus_and(*result, irq_domain[irq], mask);
+		if (!cpus_empty(*result))
+			return old_vector;
 	}
 
 	for_each_cpu_mask(cpu, mask) {
+		cpumask_t domain;
+		int first, new_cpu;
 		int vector, offset;
-		vector = pos[cpu].vector;
-		offset = pos[cpu].offset;
+
+		domain = vector_allocation_domain(cpu);
+		first = first_cpu(domain);
+
+		vector = pos[first].vector;
+		offset = pos[first].offset;
 next:
 		vector += 8;
 		if (vector >= FIRST_SYSTEM_VECTOR) {
@@ -604,35 +646,40 @@
 			offset = (offset + 1) % 8;
 			vector = FIRST_DEVICE_VECTOR + offset;
 		}
-		if (unlikely(pos[cpu].vector == vector))
+		if (unlikely(pos[first].vector == vector))
 			continue;
 		if (vector == IA32_SYSCALL_VECTOR)
 			goto next;
-		if (per_cpu(vector_irq, cpu)[vector] != -1)
-			goto next;
+		for_each_cpu_mask(new_cpu, domain)
+			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
+				goto next;
 		/* Found one! */
-		pos[cpu].vector = vector;
-		pos[cpu].offset = offset;
-		if (old_vector >= 0) {
-			int old_cpu = old_vector >> 8;
-			old_vector &= 0xff;
-			per_cpu(vector_irq, old_cpu)[old_vector] = -1;
+		for_each_cpu_mask(new_cpu, domain) {
+			pos[new_cpu].vector = vector;
+			pos[new_cpu].offset = offset;
 		}
-		per_cpu(vector_irq, cpu)[vector] = irq;
-		vector |= cpu << 8;
-		IO_APIC_VECTOR(irq) = vector;
+		if (old_vector >= 0) {
+			int old_cpu;
+			for_each_cpu_mask(old_cpu, irq_domain[irq])
+				per_cpu(vector_irq, old_cpu)[old_vector] = -1;
+		}
+		for_each_cpu_mask(new_cpu, domain)
+			per_cpu(vector_irq, new_cpu)[vector] = irq;
+		irq_vector[irq] = vector;
+		irq_domain[irq] = domain;
+		cpus_and(*result, domain, mask);
 		return vector;
 	}
 	return -ENOSPC;
 }
 
-static int assign_irq_vector(int irq, cpumask_t mask)
+static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
 {
 	int vector;
 	unsigned long flags;
 
 	spin_lock_irqsave(&vector_lock, flags);
-	vector = __assign_irq_vector(irq, mask);
+	vector = __assign_irq_vector(irq, mask, result);
 	spin_unlock_irqrestore(&vector_lock, flags);
 	return vector;
 }
@@ -649,11 +696,11 @@
 {
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 			trigger == IOAPIC_LEVEL)
-		set_irq_chip_and_handler(irq, &ioapic_chip,
-					 handle_fasteoi_irq);
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_fasteoi_irq, "fasteoi");
 	else
-		set_irq_chip_and_handler(irq, &ioapic_chip,
-					 handle_edge_irq);
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_edge_irq, "edge");
 }
 
 static void __init setup_IO_APIC_irqs(void)
@@ -704,14 +751,12 @@
 
 		if (IO_APIC_IRQ(irq)) {
 			cpumask_t mask;
-			vector = assign_irq_vector(irq, TARGET_CPUS);
+			vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
 			if (vector < 0)
 				continue;
 
-			cpus_clear(mask);
-			cpu_set(vector >> 8, mask);
 			entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
-			entry.vector = vector & 0xff;
+			entry.vector = vector;
 
 			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
 			if (!apic && (irq < 16))
@@ -761,7 +806,7 @@
 	 * The timer IRQ doesn't have to know that behind the
 	 * scene we have a 8259A-master in AEOI mode ...
 	 */
-	set_irq_chip_and_handler(0, &ioapic_chip, handle_edge_irq);
+	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
 
 	/*
 	 * Add it to the IO-APIC irq-routing table:
@@ -1210,12 +1255,15 @@
 {
 	cpumask_t mask;
 	unsigned vector;
+	unsigned long flags;
 
+	spin_lock_irqsave(&vector_lock, flags);
 	vector = irq_vector[irq];
 	cpus_clear(mask);
-	cpu_set(vector >> 8, mask);
+	cpu_set(first_cpu(irq_domain[irq]), mask);
 
-	send_IPI_mask(mask, vector & 0xff);
+	send_IPI_mask(mask, vector);
+	spin_unlock_irqrestore(&vector_lock, flags);
 
 	return 1;
 }
@@ -1289,7 +1337,7 @@
 	 */
 	for (irq = 0; irq < NR_IRQS ; irq++) {
 		int tmp = irq;
-		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
+		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
 			/*
 			 * Hmm.. We don't have an entry for this,
 			 * so default to an old-fashioned 8259
@@ -1430,12 +1478,13 @@
 {
 	int apic1, pin1, apic2, pin2;
 	int vector;
+	cpumask_t mask;
 
 	/*
 	 * get/set the timer IRQ vector:
 	 */
 	disable_8259A_irq(0);
-	vector = assign_irq_vector(0, TARGET_CPUS);
+	vector = assign_irq_vector(0, TARGET_CPUS, &mask);
 
 	/*
 	 * Subtle, code in do_timer_interrupt() expects an AEOI
@@ -1667,6 +1716,7 @@
 	int new;
 	int vector = 0;
 	unsigned long flags;
+	cpumask_t mask;
 
 	irq = -ENOSPC;
 	spin_lock_irqsave(&vector_lock, flags);
@@ -1675,7 +1725,7 @@
 			continue;
 		if (irq_vector[new] != 0)
 			continue;
-		vector = __assign_irq_vector(new, TARGET_CPUS);
+		vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
 		if (likely(vector > 0))
 			irq = new;
 		break;
@@ -1707,13 +1757,10 @@
 {
 	int vector;
 	unsigned dest;
+	cpumask_t tmp;
 
-	vector = assign_irq_vector(irq, TARGET_CPUS);
+	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
 	if (vector >= 0) {
-		cpumask_t tmp;
-
-		cpus_clear(tmp);
-		cpu_set(vector >> 8, tmp);
 		dest = cpu_mask_to_apicid(tmp);
 
 		msg->address_hi = MSI_ADDR_BASE_HI;
@@ -1752,12 +1799,10 @@
 
 	cpus_and(mask, tmp, CPU_MASK_ALL);
 
-	vector = assign_irq_vector(irq, mask);
+	vector = assign_irq_vector(irq, mask, &tmp);
 	if (vector < 0)
 		return;
 
-	cpus_clear(tmp);
-	cpu_set(vector >> 8, tmp);
 	dest = cpu_mask_to_apicid(tmp);
 
 	read_msi_msg(irq, &msg);
@@ -1797,7 +1842,7 @@
 
 	write_msi_msg(irq, &msg);
 
-	set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
+	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
 	return 0;
 }
@@ -1844,12 +1889,10 @@
 
 	cpus_and(mask, tmp, CPU_MASK_ALL);
 
-	vector = assign_irq_vector(irq, mask);
+	vector = assign_irq_vector(irq, mask, &tmp);
 	if (vector < 0)
 		return;
 
-	cpus_clear(tmp);
-	cpu_set(vector >> 8, tmp);
 	dest = cpu_mask_to_apicid(tmp);
 
 	target_ht_irq(irq, dest, vector & 0xff);
@@ -1857,7 +1900,7 @@
 }
 #endif
 
-static struct hw_interrupt_type ht_irq_chip = {
+static struct irq_chip ht_irq_chip = {
 	.name		= "PCI-HT",
 	.mask		= mask_ht_irq,
 	.unmask		= unmask_ht_irq,
@@ -1871,15 +1914,13 @@
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
 	int vector;
+	cpumask_t tmp;
 
-	vector = assign_irq_vector(irq, TARGET_CPUS);
+	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
 	if (vector >= 0) {
 		u32 low, high;
 		unsigned dest;
-		cpumask_t tmp;
 
-		cpus_clear(tmp);
-		cpu_set(vector >> 8, tmp);
 		dest = cpu_mask_to_apicid(tmp);
 
 		high = 	HT_IRQ_HIGH_DEST_ID(dest);
@@ -1898,7 +1939,8 @@
 		write_ht_irq_low(irq, low);
 		write_ht_irq_high(irq, high);
 
-		set_irq_chip_and_handler(irq, &ht_irq_chip, handle_edge_irq);
+		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+					      handle_edge_irq, "edge");
 	}
 	return vector;
 }
@@ -1945,13 +1987,10 @@
 		add_pin_to_irq(irq, ioapic, pin);
 
 
-	vector = assign_irq_vector(irq, TARGET_CPUS);
+	vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
 	if (vector < 0)
 		return vector;
 
-	cpus_clear(mask);
-	cpu_set(vector >> 8, mask);
-
 	/*
 	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
 	 * Note that we mask (disable) IRQs now -- these get enabled when the
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 506f27c..e46c558 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -75,7 +75,7 @@
 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %8s", irq_desc[i].chip->name);
-		seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq));
+		seq_printf(p, "-%-8s", irq_desc[i].name);
 
 		seq_printf(p, "  %s", action->name);
 		for (action=action->next; action; action = action->next)
@@ -103,7 +103,9 @@
  * handlers).
  */
 asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
-{	
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
 	/* high bit used in ret_from_ code  */
 	unsigned vector = ~regs->orig_rax;
 	unsigned irq;
@@ -112,18 +114,19 @@
 	irq_enter();
 	irq = __get_cpu_var(vector_irq)[vector];
 
-	if (unlikely(irq >= NR_IRQS)) {
-		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
-					__FUNCTION__, irq);
-		BUG();
-	}
-
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	stack_overflow_check(regs);
 #endif
-	generic_handle_irq(irq, regs);
+
+	if (likely(irq < NR_IRQS))
+		generic_handle_irq(irq);
+	else
+		printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
+			__func__, smp_processor_id(), vector);
+
 	irq_exit();
 
+	set_irq_regs(old_regs);
 	return 1;
 }
 
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index f760045..37a7708 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -2,8 +2,9 @@
  * Derived from arch/powerpc/kernel/iommu.c
  *
  * Copyright (C) IBM Corporation, 2006
+ * Copyright (C) 2006  Jon Mason <jdmason@kudzu.us>
  *
- * Author: Jon Mason <jdmason@us.ibm.com>
+ * Author: Jon Mason <jdmason@kudzu.us>
  * Author: Muli Ben-Yehuda <muli@il.ibm.com>
 
  * This program is free software; you can redistribute it and/or modify
@@ -51,7 +52,8 @@
 #define ONE_BASED_CHASSIS_NUM   1
 
 /* register offsets inside the host bridge space */
-#define PHB_CSR_OFFSET		0x0110
+#define CALGARY_CONFIG_REG	0x0108
+#define PHB_CSR_OFFSET		0x0110 /* Channel Status */
 #define PHB_PLSSR_OFFSET	0x0120
 #define PHB_CONFIG_RW_OFFSET	0x0160
 #define PHB_IOBASE_BAR_LOW	0x0170
@@ -82,6 +84,8 @@
 #define TAR_VALID		0x0000000000000008UL
 /* CSR (Channel/DMA Status Register) */
 #define CSR_AGENT_MASK		0xffe0ffff
+/* CCR (Calgary Configuration Register) */
+#define CCR_2SEC_TIMEOUT        0x000000000000000EUL
 
 #define MAX_NUM_OF_PHBS		8 /* how many PHBs in total? */
 #define MAX_NUM_CHASSIS		8 /* max number of chassis */
@@ -714,7 +718,7 @@
 
 	/* If no error, the agent ID in the CSR is not valid */
 	if (val32 & CSR_AGENT_MASK) {
-		printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, "
+		printk(KERN_EMERG "calgary_watchdog: DMA error on PHB %#x, "
 				  "CSR = %#x\n", dev->bus->number, val32);
 		writel(0, target);
 
@@ -731,6 +735,38 @@
 	}
 }
 
+static void __init calgary_increase_split_completion_timeout(void __iomem *bbar,
+	unsigned char busnum)
+{
+	u64 val64;
+	void __iomem *target;
+	unsigned long phb_shift = -1;
+	u64 mask;
+
+	switch (busno_to_phbid(busnum)) {
+	case 0: phb_shift = (63 - 19);
+		break;
+	case 1: phb_shift = (63 - 23);
+		break;
+	case 2: phb_shift = (63 - 27);
+		break;
+	case 3: phb_shift = (63 - 35);
+		break;
+	default:
+		BUG_ON(busno_to_phbid(busnum));
+	}
+
+	target = calgary_reg(bbar, CALGARY_CONFIG_REG);
+	val64 = be64_to_cpu(readq(target));
+
+	/* zero out this PHB's timer bits */
+	mask = ~(0xFUL << phb_shift);
+	val64 &= mask;
+	val64 |= (CCR_2SEC_TIMEOUT << phb_shift);
+	writeq(cpu_to_be64(val64), target);
+	readq(target); /* flush */
+}
+
 static void __init calgary_enable_translation(struct pci_dev *dev)
 {
 	u32 val32;
@@ -748,13 +784,20 @@
 	val32 = be32_to_cpu(readl(target));
 	val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE;
 
-	printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum);
+	printk(KERN_INFO "Calgary: enabling translation on PHB %#x\n", busnum);
 	printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this "
 	       "bus.\n");
 
 	writel(cpu_to_be32(val32), target);
 	readl(target); /* flush */
 
+	/*
+	 * Give split completion a longer timeout on bus 1 for aic94xx
+	 * http://bugzilla.kernel.org/show_bug.cgi?id=7180
+	 */
+	if (busnum == 1)
+		calgary_increase_split_completion_timeout(bbar, busnum);
+
 	init_timer(&tbl->watchdog_timer);
 	tbl->watchdog_timer.function = &calgary_watchdog;
 	tbl->watchdog_timer.data = (unsigned long)dev;
@@ -778,7 +821,7 @@
 	val32 = be32_to_cpu(readl(target));
 	val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE);
 
-	printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum);
+	printk(KERN_INFO "Calgary: disabling translation on PHB %#x!\n", busnum);
 	writel(cpu_to_be32(val32), target);
 	readl(target); /* flush */
 
@@ -790,7 +833,16 @@
 	int rionodeid;
 	u32 address;
 
-	rionodeid = (dev->bus->number % 15 > 4) ? 3 : 2;
+	/*
+	 * Each Calgary has four busses. The first four busses (first Calgary)
+	 * have RIO node ID 2, then the next four (second Calgary) have RIO
+	 * node ID 3, the next four (third Calgary) have node ID 2 again, etc.
+	 * We use a gross hack - relying on the dev->bus->number ordering,
+	 * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1,
+	 * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the
+	 * second (id 3), and then it repeats modulo 14.
+ 	 */
+	rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2;
 	/*
 	 * register space address calculation as follows:
 	 * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
@@ -798,7 +850,7 @@
 	 * RioNodeId is 2 for first Calgary, 3 for second Calgary
 	 */
 	address = START_ADDRESS	-
-		(0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 15)) +
+		(0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) +
 		(0x100000) * (rionodeid - CHASSIS_BASE);
 	return address;
 }
@@ -816,6 +868,8 @@
 	void __iomem *bbar;
 	int ret;
 
+	BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
+
 	address = locate_register_space(dev);
 	/* map entire 1MB of Calgary config space */
 	bbar = ioremap_nocache(address, 1024 * 1024);
@@ -842,10 +896,10 @@
 
 static int __init calgary_init(void)
 {
-	int i, ret = -ENODEV;
+	int ret = -ENODEV;
 	struct pci_dev *dev = NULL;
 
-	for (i = 0; i < MAX_PHB_BUS_NUM; i++) {
+	do {
 		dev = pci_get_device(PCI_VENDOR_ID_IBM,
 				     PCI_DEVICE_ID_IBM_CALGARY,
 				     dev);
@@ -861,12 +915,12 @@
 		ret = calgary_init_one(dev);
 		if (ret)
 			goto error;
-	}
+	} while (1);
 
 	return ret;
 
 error:
-	for (i--; i >= 0; i--) {
+	do {
 		dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
 					      PCI_DEVICE_ID_IBM_CALGARY,
 					      dev);
@@ -882,7 +936,7 @@
 		calgary_disable_translation(dev);
 		calgary_free_bus(dev);
 		pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
-	}
+	} while (1);
 
 	return ret;
 }
@@ -1052,7 +1106,7 @@
 
 			if (bridge < MAX_PHB_BUS_NUM) {
 				printk(KERN_INFO "Calgary: disabling "
-				       "translation for PHB 0x%x\n", bridge);
+				       "translation for PHB %#x\n", bridge);
 				bus_info[bridge].translation_disabled = 1;
 			}
 		}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index de10cb8..49f7fac 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -238,18 +238,26 @@
  * We execute MONITOR against need_resched and enter optimized wait state
  * through MWAIT. Whenever someone changes need_resched, we would be woken
  * up from MWAIT (without an IPI).
+ *
+ * New with Core Duo processors, MWAIT can take some hints based on CPU
+ * capability.
  */
+void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
+{
+	if (!need_resched()) {
+		__monitor((void *)&current_thread_info()->flags, 0, 0);
+		smp_mb();
+		if (!need_resched())
+			__mwait(eax, ecx);
+	}
+}
+
+/* Default MONITOR/MWAIT with no hints, used for default C1 state */
 static void mwait_idle(void)
 {
 	local_irq_enable();
-
-	while (!need_resched()) {
-		__monitor((void *)&current_thread_info()->flags, 0, 0);
-		smp_mb();
-		if (need_resched())
-			break;
-		__mwait(0, 0);
-	}
+	while (!need_resched())
+		mwait_idle_with_hints(0,0);
 }
 
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
@@ -615,6 +623,9 @@
 		prev->gsindex = gsindex;
 	}
 
+	/* Must be after DS reload */
+	unlazy_fpu(prev_p);
+
 	/* 
 	 * Switch the PDA and FPU contexts.
 	 */
@@ -622,10 +633,6 @@
 	write_pda(oldrsp, next->userrsp); 
 	write_pda(pcurrent, next_p); 
 
-	/* This must be here to ensure both math_state_restore() and
-	   kernel_fpu_begin() work consistently. 
-	   And the AMD workaround requires it to be after DS reload. */
-	unlazy_fpu(prev_p);
 	write_pda(kernelstack,
 	(unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
 #ifdef CONFIG_CC_STACKPROTECTOR
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 557e92a..88722f1 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -302,20 +302,20 @@
 }
 EXPORT_SYMBOL(monotonic_clock);
 
-static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
+static noinline void handle_lost_ticks(int lost)
 {
 	static long lost_count;
 	static int warned;
 	if (report_lost_ticks) {
 		printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
-		print_symbol("rip %s)\n", regs->rip);
+		print_symbol("rip %s)\n", get_irq_regs()->rip);
 	}
 
 	if (lost_count == 1000 && !warned) {
 		printk(KERN_WARNING "warning: many lost ticks.\n"
 		       KERN_WARNING "Your time source seems to be instable or "
 		   		"some driver is hogging interupts\n");
-		print_symbol("rip %s\n", regs->rip);
+		print_symbol("rip %s\n", get_irq_regs()->rip);
 		if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
 			printk(KERN_WARNING "Falling back to HPET\n");
 			if (hpet_use_timer)
@@ -339,7 +339,7 @@
 #endif
 }
 
-void main_timer_handler(struct pt_regs *regs)
+void main_timer_handler(void)
 {
 	static unsigned long rtc_update = 0;
 	unsigned long tsc;
@@ -411,7 +411,7 @@
 	}
 
 	if (lost > 0)
-		handle_lost_ticks(lost, regs);
+		handle_lost_ticks(lost);
 	else
 		lost = 0;
 
@@ -421,7 +421,7 @@
 
 	do_timer(lost + 1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
 
 /*
@@ -431,7 +431,7 @@
  */
 
 	if (!using_apic_timer)
-		smp_local_timer_interrupt(regs);
+		smp_local_timer_interrupt();
 
 /*
  * If we have an externally synchronized Linux clock, then update CMOS clock
@@ -450,11 +450,11 @@
 	write_sequnlock(&xtime_lock);
 }
 
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	if (apic_runs_main_timer > 1)
 		return IRQ_HANDLED;
-	main_timer_handler(regs);
+	main_timer_handler();
 	if (using_apic_timer)
 		smp_send_timer_broadcast_ipi();
 	return IRQ_HANDLED;
@@ -948,7 +948,7 @@
  	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
 #ifdef CONFIG_ACPI
 		/* But TSC doesn't tick in C3 so don't use it there */
-		if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100)
+		if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 1000)
 			return 1;
 #endif
  		return 0;
@@ -1337,7 +1337,7 @@
 	}
 	if (call_rtc_interrupt) {
 		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-		rtc_interrupt(rtc_int_flag, dev_id, regs);
+		rtc_interrupt(rtc_int_flag, dev_id);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 01f2a8d..7819022 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/kallsyms.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/nmi.h>
@@ -115,7 +116,6 @@
 #endif
 
 #ifdef CONFIG_KALLSYMS
-# include <linux/kallsyms.h>
 void printk_address(unsigned long address)
 {
 	unsigned long offset = 0, symsize;
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index b9df2ab..1283614 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -17,6 +17,7 @@
 	text PT_LOAD FLAGS(5);	/* R_E */
 	data PT_LOAD FLAGS(7);	/* RWE */
 	user PT_LOAD FLAGS(7);	/* RWE */
+	data.init PT_LOAD FLAGS(7);	/* RWE */
 	note PT_NOTE FLAGS(4);	/* R__ */
 }
 SECTIONS
@@ -131,7 +132,7 @@
   . = ALIGN(8192);		/* init_task */
   .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
 	*(.data.init_task)
-  } :data
+  }:data.init
 
   . = ALIGN(4096);
   .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
diff --git a/arch/x86_64/kernel/vsmp.c b/arch/x86_64/kernel/vsmp.c
index 044e852..414caf0 100644
--- a/arch/x86_64/kernel/vsmp.c
+++ b/arch/x86_64/kernel/vsmp.c
@@ -14,6 +14,7 @@
 #include <linux/pci_ids.h>
 #include <linux/pci_regs.h>
 #include <asm/pci-direct.h>
+#include <asm/io.h>
 
 static int __init vsmp_init(void)
 {
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 19c7252..971dc11 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -406,9 +406,12 @@
 #ifndef CONFIG_NUMA
 void __init paging_init(void)
 {
-	unsigned long max_zone_pfns[MAX_NR_ZONES] = {MAX_DMA_PFN,
-							MAX_DMA32_PFN,
-							end_pfn};
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
+	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+	max_zone_pfns[ZONE_NORMAL] = end_pfn;
+
 	memory_present(0, 0, end_pfn);
 	sparse_init();
 	free_area_init_nodes(max_zone_pfns);
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 829a008b..2ee2e00 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -338,9 +338,11 @@
 void __init paging_init(void)
 { 
 	int i;
-	unsigned long max_zone_pfns[MAX_NR_ZONES] = { MAX_DMA_PFN,
-		MAX_DMA32_PFN,
-		end_pfn};
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
+	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+	max_zone_pfns[ZONE_NORMAL] = end_pfn;
 
 	arch_sparse_init();
 
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 3cc0544..1087e15 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -207,7 +207,7 @@
 	return hotadd_percent > 0;
 }
 #else
-int update_end_of_memory(unsigned long end) {return 0;}
+int update_end_of_memory(unsigned long end) {return -1;}
 static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static inline int save_add_info(void) {return 1;}
@@ -337,7 +337,7 @@
 	push_node_boundaries(node, nd->start >> PAGE_SHIFT,
 						nd->end >> PAGE_SHIFT);
 
- 	if (ma->flags.hot_pluggable && !reserve_hotadd(node, start, end) < 0) {
+ 	if (ma->flags.hot_pluggable && (reserve_hotadd(node, start, end) < 0)) {
 		/* Ignore hotadd region. Undo damage */
 		printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
 		*nd = oldnode;
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
index 1eb18f4..149aba0 100644
--- a/arch/x86_64/pci/Makefile
+++ b/arch/x86_64/pci/Makefile
@@ -3,7 +3,7 @@
 #
 # Reuse the i386 PCI subsystem
 #
-CFLAGS += -Iarch/i386/pci
+EXTRA_CFLAGS += -Iarch/i386/pci
 
 obj-y		:= i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
diff --git a/block/elevator.c b/block/elevator.c
index 487dd3d..8ccd163 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -93,21 +93,18 @@
 
 static struct elevator_type *elevator_find(const char *name)
 {
-	struct elevator_type *e = NULL;
+	struct elevator_type *e;
 	struct list_head *entry;
 
 	list_for_each(entry, &elv_list) {
-		struct elevator_type *__e;
 
-		__e = list_entry(entry, struct elevator_type, list);
+		e = list_entry(entry, struct elevator_type, list);
 
-		if (!strcmp(__e->elevator_name, name)) {
-			e = __e;
-			break;
-		}
+		if (!strcmp(e->elevator_name, name))
+			return e;
 	}
 
-	return e;
+	return NULL;
 }
 
 static void elevator_put(struct elevator_type *e)
@@ -1088,7 +1085,7 @@
 	struct list_head *entry;
 	int len = 0;
 
-	spin_lock_irq(q->queue_lock);
+	spin_lock_irq(&elv_list_lock);
 	list_for_each(entry, &elv_list) {
 		struct elevator_type *__e;
 
@@ -1098,7 +1095,7 @@
 		else
 			len += sprintf(name+len, "%s ", __e->elevator_name);
 	}
-	spin_unlock_irq(q->queue_lock);
+	spin_unlock_irq(&elv_list_lock);
 
 	len += sprintf(len+name, "\n");
 	return len;
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index c847e17..1360665 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -56,11 +56,6 @@
  */
 static kmem_cache_t *iocontext_cachep;
 
-static wait_queue_head_t congestion_wqh[2] = {
-		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
-		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
-	};
-
 /*
  * Controlling structure to kblockd
  */
@@ -112,35 +107,6 @@
 	q->nr_congestion_off = nr;
 }
 
-/*
- * A queue has just exitted congestion.  Note this in the global counter of
- * congested queues, and wake up anyone who was waiting for requests to be
- * put back.
- */
-static void clear_queue_congested(request_queue_t *q, int rw)
-{
-	enum bdi_state bit;
-	wait_queue_head_t *wqh = &congestion_wqh[rw];
-
-	bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
-	clear_bit(bit, &q->backing_dev_info.state);
-	smp_mb__after_clear_bit();
-	if (waitqueue_active(wqh))
-		wake_up(wqh);
-}
-
-/*
- * A queue has just entered congestion.  Flag that in the queue's VM-visible
- * state flags and increment the global gounter of congested queues.
- */
-static void set_queue_congested(request_queue_t *q, int rw)
-{
-	enum bdi_state bit;
-
-	bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
-	set_bit(bit, &q->backing_dev_info.state);
-}
-
 /**
  * blk_get_backing_dev_info - get the address of a queue's backing_dev_info
  * @bdev:	device
@@ -159,7 +125,6 @@
 		ret = &q->backing_dev_info;
 	return ret;
 }
-
 EXPORT_SYMBOL(blk_get_backing_dev_info);
 
 void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data)
@@ -167,7 +132,6 @@
 	q->activity_fn = fn;
 	q->activity_data = data;
 }
-
 EXPORT_SYMBOL(blk_queue_activity_fn);
 
 /**
@@ -2067,7 +2031,7 @@
 	struct request_list *rl = &q->rq;
 
 	if (rl->count[rw] < queue_congestion_off_threshold(q))
-		clear_queue_congested(q, rw);
+		blk_clear_queue_congested(q, rw);
 
 	if (rl->count[rw] + 1 <= q->nr_requests) {
 		if (waitqueue_active(&rl->wait[rw]))
@@ -2137,7 +2101,7 @@
 				}
 			}
 		}
-		set_queue_congested(q, rw);
+		blk_set_queue_congested(q, rw);
 	}
 
 	/*
@@ -2755,41 +2719,6 @@
 }
 EXPORT_SYMBOL(blk_end_sync_rq);
 
-/**
- * blk_congestion_wait - wait for a queue to become uncongested
- * @rw: READ or WRITE
- * @timeout: timeout in jiffies
- *
- * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion.
- * If no queues are congested then just wait for the next request to be
- * returned.
- */
-long blk_congestion_wait(int rw, long timeout)
-{
-	long ret;
-	DEFINE_WAIT(wait);
-	wait_queue_head_t *wqh = &congestion_wqh[rw];
-
-	prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
-	ret = io_schedule_timeout(timeout);
-	finish_wait(wqh, &wait);
-	return ret;
-}
-
-EXPORT_SYMBOL(blk_congestion_wait);
-
-/**
- * blk_congestion_end - wake up sleepers on a congestion queue
- * @rw: READ or WRITE
- */
-void blk_congestion_end(int rw)
-{
-	wait_queue_head_t *wqh = &congestion_wqh[rw];
-
-	if (waitqueue_active(wqh))
-		wake_up(wqh);
-}
-
 /*
  * Has to be called with the request spinlock acquired
  */
@@ -3765,14 +3694,14 @@
 	blk_queue_congestion_threshold(q);
 
 	if (rl->count[READ] >= queue_congestion_on_threshold(q))
-		set_queue_congested(q, READ);
+		blk_set_queue_congested(q, READ);
 	else if (rl->count[READ] < queue_congestion_off_threshold(q))
-		clear_queue_congested(q, READ);
+		blk_clear_queue_congested(q, READ);
 
 	if (rl->count[WRITE] >= queue_congestion_on_threshold(q))
-		set_queue_congested(q, WRITE);
+		blk_set_queue_congested(q, WRITE);
 	else if (rl->count[WRITE] < queue_congestion_off_threshold(q))
-		clear_queue_congested(q, WRITE);
+		blk_clear_queue_congested(q, WRITE);
 
 	if (rl->count[READ] >= q->nr_requests) {
 		blk_set_queue_full(q, READ);
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1e2f39c..cbae839 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -27,7 +27,6 @@
 config CRYPTO_MANAGER
 	tristate "Cryptographic algorithm manager"
 	select CRYPTO_ALGAPI
-	default m
 	help
 	  Create default cryptographic template instantiations such as
 	  cbc(aes).
@@ -35,6 +34,7 @@
 config CRYPTO_HMAC
 	tristate "HMAC support"
 	select CRYPTO_HASH
+	select CRYPTO_MANAGER
 	help
 	  HMAC: Keyed-Hashing for Message Authentication (RFC2104).
 	  This is required for IPSec.
@@ -131,6 +131,7 @@
 config CRYPTO_ECB
 	tristate "ECB support"
 	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
 	default m
 	help
 	  ECB: Electronic CodeBook mode
@@ -140,6 +141,7 @@
 config CRYPTO_CBC
 	tristate "CBC support"
 	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
 	default m
 	help
 	  CBC: Cipher Block Chaining mode
diff --git a/crypto/api.c b/crypto/api.c
index 2e84d4b..4fb7fa4 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -331,7 +331,7 @@
 	tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
 	tfm = kzalloc(tfm_size, GFP_KERNEL);
 	if (tfm == NULL)
-		goto out;
+		goto out_err;
 
 	tfm->__crt_alg = alg;
 
@@ -355,6 +355,7 @@
 	crypto_exit_ops(tfm);
 out_free_tfm:
 	kfree(tfm);
+out_err:
 	tfm = ERR_PTR(err);
 out:
 	return tfm;
@@ -414,14 +415,14 @@
 		struct crypto_alg *alg;
 
 		alg = crypto_alg_mod_lookup(alg_name, type, mask);
-		err = PTR_ERR(alg);
-		tfm = ERR_PTR(err);
-		if (IS_ERR(alg))
+		if (IS_ERR(alg)) {
+			err = PTR_ERR(alg);
 			goto err;
+		}
 
 		tfm = __crypto_alloc_tfm(alg, 0);
 		if (!IS_ERR(tfm))
-			break;
+			return tfm;
 
 		crypto_mod_put(alg);
 		err = PTR_ERR(tfm);
@@ -433,9 +434,9 @@
 			err = -EINTR;
 			break;
 		}
-	};
+	}
 
-	return tfm;
+	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_base);
  
diff --git a/crypto/serpent.c b/crypto/serpent.c
index 465d091..2b0a19a 100644
--- a/crypto/serpent.c
+++ b/crypto/serpent.c
@@ -364,10 +364,10 @@
 {
 	struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
 	const u32
-		*k = ctx->expkey,
-		*s = (const u32 *)src;
-	u32	*d = (u32 *)dst,
-		r0, r1, r2, r3, r4;
+		*k = ctx->expkey;
+	const __le32 *s = (const __le32 *)src;
+	__le32	*d = (__le32 *)dst;
+	u32	r0, r1, r2, r3, r4;
 
 /*
  * Note: The conversions between u8* and u32* might cause trouble
@@ -423,10 +423,10 @@
 {
 	struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
 	const u32
-		*k = ((struct serpent_ctx *)ctx)->expkey,
-		*s = (const u32 *)src;
-	u32	*d = (u32 *)dst,
-		r0, r1, r2, r3, r4;
+		*k = ((struct serpent_ctx *)ctx)->expkey;
+	const __le32 *s = (const __le32 *)src;
+	__le32	*d = (__le32 *)dst;
+	u32	r0, r1, r2, r3, r4;
 
 	r0 = le32_to_cpu(s[0]);
 	r1 = le32_to_cpu(s[1]);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 263e86d..f394634 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -14,6 +14,10 @@
 
 source "drivers/block/Kconfig"
 
+# misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4
+
+source "drivers/misc/Kconfig"
+
 source "drivers/ide/Kconfig"
 
 source "drivers/scsi/Kconfig"
@@ -52,8 +56,6 @@
 
 source "drivers/hwmon/Kconfig"
 
-source "drivers/misc/Kconfig"
-
 source "drivers/mfd/Kconfig"
 
 source "drivers/media/Kconfig"
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 1bace29..7fde8f4 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -938,7 +938,7 @@
 	mfm_request();
 }
 
-static void mfm_interrupt_handler(int unused, void *dev_id, struct pt_regs *regs)
+static void mfm_interrupt_handler(int unused, void *dev_id)
 {
 	void (*handler) (void) = do_mfm;
 
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 98099de..6bcd9e8 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -85,6 +85,8 @@
 	struct list_head res_list;
 };
 
+static int acpi_hotmem_initialized;
+
 static acpi_status
 acpi_memory_get_resource(struct acpi_resource *resource, void *context)
 {
@@ -414,7 +416,7 @@
 	/* Set the device state */
 	mem_device->state = MEMORY_POWER_ON_STATE;
 
-	printk(KERN_INFO "%s \n", acpi_device_name(device));
+	printk(KERN_DEBUG "%s \n", acpi_device_name(device));
 
 	return result;
 }
@@ -438,6 +440,15 @@
 	struct acpi_memory_device *mem_device;
 	int result = 0;
 
+	/*
+	 * Early boot code has recognized memory area by EFI/E820.
+	 * If DSDT shows these memory devices on boot, hotplug is not necessary
+	 * for them. So, it just returns until completion of this driver's
+	 * start up.
+	 */
+	if (!acpi_hotmem_initialized)
+		return 0;
+
 	mem_device = acpi_driver_data(device);
 
 	if (!acpi_memory_check_device(mem_device)) {
@@ -537,6 +548,7 @@
 		return -ENODEV;
 	}
 
+	acpi_hotmem_initialized = 1;
 	return 0;
 }
 
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index e9ee4c5..c7ac929 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -138,6 +138,7 @@
 		S2x,		//S200 (J1 reported), Victor MP-XP7210
 		W1N,		//W1000N
 		W5A,		//W5A
+		W3V,            //W3030V
 		xxN,		//M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
 		//(Centrino)
 		END_MODEL
@@ -376,6 +377,17 @@
 	 .display_get = "\\ADVG"},
 
 	{
+	 .name = "W3V",
+	 .mt_mled = "MLED",
+	 .mt_wled = "WLED",
+	 .mt_lcd_switch = xxN_PREFIX "_Q10",
+	 .lcd_status = "\\BKLT",
+	 .brightness_set = "SPLV",
+	 .brightness_get = "GPLV",
+	 .display_set = "SDSP",
+	 .display_get = "\\INFB"},
+
+       {
 	 .name = "xxN",
 	 .mt_mled = "MLED",
 /* WLED present, but not controlled by ACPI */
@@ -555,11 +567,11 @@
 write_led(const char __user * buffer, unsigned long count,
 	  char *ledname, int ledmask, int invert)
 {
-	int value;
+	int rv, value;
 	int led_out = 0;
 
-	count = parse_arg(buffer, count, &value);
-	if (count > 0)
+	rv = parse_arg(buffer, count, &value);
+	if (rv > 0)
 		led_out = value ? 1 : 0;
 
 	hotk->status =
@@ -572,7 +584,7 @@
 		printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
 		       ledname);
 
-	return count;
+	return rv;
 }
 
 /*
@@ -607,20 +619,18 @@
 proc_write_ledd(struct file *file, const char __user * buffer,
 		unsigned long count, void *data)
 {
-	int value;
+	int rv, value;
 
-	count = parse_arg(buffer, count, &value);
-	if (count > 0) {
+	rv = parse_arg(buffer, count, &value);
+	if (rv > 0) {
 		if (!write_acpi_int
 		    (hotk->handle, hotk->methods->mt_ledd, value, NULL))
 			printk(KERN_WARNING
 			       "Asus ACPI: LED display write failed\n");
 		else
 			hotk->ledd_status = (u32) value;
-	} else if (count < 0)
-		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
-
-	return count;
+	}
+	return rv;
 }
 
 /*
@@ -761,12 +771,12 @@
 proc_write_lcd(struct file *file, const char __user * buffer,
 	       unsigned long count, void *data)
 {
-	int value;
+	int rv, value;
 
-	count = parse_arg(buffer, count, &value);
-	if (count > 0)
+	rv = parse_arg(buffer, count, &value);
+	if (rv > 0)
 		set_lcd_state(value);
-	return count;
+	return rv;
 }
 
 static int read_brightness(void)
@@ -830,18 +840,15 @@
 proc_write_brn(struct file *file, const char __user * buffer,
 	       unsigned long count, void *data)
 {
-	int value;
+	int rv, value;
 
-	count = parse_arg(buffer, count, &value);
-	if (count > 0) {
+	rv = parse_arg(buffer, count, &value);
+	if (rv > 0) {
 		value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
 		/* 0 <= value <= 15 */
 		set_brightness(value);
-	} else if (count < 0) {
-		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 	}
-
-	return count;
+	return rv;
 }
 
 static void set_display(int value)
@@ -880,15 +887,12 @@
 proc_write_disp(struct file *file, const char __user * buffer,
 		unsigned long count, void *data)
 {
-	int value;
+	int rv, value;
 
-	count = parse_arg(buffer, count, &value);
-	if (count > 0)
+	rv = parse_arg(buffer, count, &value);
+	if (rv > 0)
 		set_display(value);
-	else if (count < 0)
-		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
-
-	return count;
+	return rv;
 }
 
 typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
@@ -1097,6 +1101,8 @@
 		return A4G;
 	else if (strncmp(model, "W1N", 3) == 0)
 		return W1N;
+	else if (strncmp(model, "W3V", 3) == 0)
+		return W3V;
 	else if (strncmp(model, "W5A", 3) == 0)
 		return W5A;
 	else
@@ -1200,9 +1206,10 @@
 		hotk->methods->mt_wled = NULL;
 	/* L5D's WLED is not controlled by ACPI */
 	else if (strncmp(string, "M2N", 3) == 0 ||
+		 strncmp(string, "W3V", 3) == 0 ||
 		 strncmp(string, "S1N", 3) == 0)
 		hotk->methods->mt_wled = "WLED";
-	/* M2N and S1N have a usable WLED */
+	/* M2N, S1N and W3V have a usable WLED */
 	else if (asus_info) {
 		if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
 			hotk->methods->mled_status = NULL;
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 9810e2a..026e4075 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -64,6 +64,7 @@
 
 static int acpi_battery_add(struct acpi_device *device);
 static int acpi_battery_remove(struct acpi_device *device, int type);
+static int acpi_battery_resume(struct acpi_device *device, int status);
 
 static struct acpi_driver acpi_battery_driver = {
 	.name = ACPI_BATTERY_DRIVER_NAME,
@@ -71,6 +72,7 @@
 	.ids = ACPI_BATTERY_HID,
 	.ops = {
 		.add = acpi_battery_add,
+		.resume = acpi_battery_resume,
 		.remove = acpi_battery_remove,
 		},
 };
@@ -753,6 +755,18 @@
 	return 0;
 }
 
+/* this is needed to learn about changes made in suspended state */
+static int acpi_battery_resume(struct acpi_device *device, int state)
+{
+	struct acpi_battery *battery;
+
+	if (!device)
+		return -EINVAL;
+
+	battery = device->driver_data;
+	return acpi_battery_check(battery);
+}
+
 static int __init acpi_battery_init(void)
 {
 	int result;
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index a01ce67..4a9b7bf 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -67,7 +67,7 @@
 		lock_ac_dir_cnt--;
 	if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
 		remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
-		acpi_ac_dir = 0;
+		acpi_ac_dir = NULL;
 	}
 	mutex_unlock(&cm_sbs_mutex);
 }
@@ -99,7 +99,7 @@
 	if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
 	    && acpi_battery_dir) {
 		remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
-		acpi_battery_dir = 0;
+		acpi_battery_dir = NULL;
 	}
 	mutex_unlock(&cm_sbs_mutex);
 	return;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e5d7963..e6d4b08 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -45,206 +45,143 @@
 #define ACPI_EC_DRIVER_NAME		"ACPI Embedded Controller Driver"
 #define ACPI_EC_DEVICE_NAME		"Embedded Controller"
 #define ACPI_EC_FILE_INFO		"info"
+
+/* EC status register */
 #define ACPI_EC_FLAG_OBF	0x01	/* Output buffer full */
 #define ACPI_EC_FLAG_IBF	0x02	/* Input buffer full */
 #define ACPI_EC_FLAG_BURST	0x10	/* burst mode */
 #define ACPI_EC_FLAG_SCI	0x20	/* EC-SCI occurred */
-#define ACPI_EC_EVENT_OBF	0x01	/* Output buffer full */
-#define ACPI_EC_EVENT_IBE	0x02	/* Input buffer empty */
-#define ACPI_EC_DELAY		50	/* Wait 50ms max. during EC ops */
-#define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
-#define ACPI_EC_UDELAY         100	/* Poll @ 100us increments */
-#define ACPI_EC_UDELAY_COUNT   1000	/* Wait 10ms max. during EC ops */
+
+/* EC commands */
 #define ACPI_EC_COMMAND_READ	0x80
 #define ACPI_EC_COMMAND_WRITE	0x81
 #define ACPI_EC_BURST_ENABLE	0x82
 #define ACPI_EC_BURST_DISABLE	0x83
 #define ACPI_EC_COMMAND_QUERY	0x84
-#define EC_POLL			0xFF
-#define EC_INTR			0x00
+
+/* EC events */
+enum {
+	ACPI_EC_EVENT_OBF_1 = 1,	/* Output buffer full */
+	ACPI_EC_EVENT_IBF_0,		/* Input buffer empty */
+};
+
+#define ACPI_EC_DELAY		50	/* Wait 50ms max. during EC ops */
+#define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
+#define ACPI_EC_UDELAY         100	/* Poll @ 100us increments */
+#define ACPI_EC_UDELAY_COUNT   1000	/* Wait 10ms max. during EC ops */
+
+enum {
+	EC_INTR = 1,	/* Output buffer full */
+	EC_POLL,	/* Input buffer empty */
+};
+
 static int acpi_ec_remove(struct acpi_device *device, int type);
 static int acpi_ec_start(struct acpi_device *device);
 static int acpi_ec_stop(struct acpi_device *device, int type);
-static int acpi_ec_intr_add(struct acpi_device *device);
-static int acpi_ec_poll_add(struct acpi_device *device);
+static int acpi_ec_add(struct acpi_device *device);
 
 static struct acpi_driver acpi_ec_driver = {
 	.name = ACPI_EC_DRIVER_NAME,
 	.class = ACPI_EC_CLASS,
 	.ids = ACPI_EC_HID,
 	.ops = {
-		.add = acpi_ec_intr_add,
+		.add = acpi_ec_add,
 		.remove = acpi_ec_remove,
 		.start = acpi_ec_start,
 		.stop = acpi_ec_stop,
 		},
 };
-union acpi_ec {
-	struct {
-		u32 mode;
-		acpi_handle handle;
-		unsigned long uid;
-		unsigned long gpe_bit;
-		struct acpi_generic_address status_addr;
-		struct acpi_generic_address command_addr;
-		struct acpi_generic_address data_addr;
-		unsigned long global_lock;
-	} common;
 
-	struct {
-		u32 mode;
-		acpi_handle handle;
-		unsigned long uid;
-		unsigned long gpe_bit;
-		struct acpi_generic_address status_addr;
-		struct acpi_generic_address command_addr;
-		struct acpi_generic_address data_addr;
-		unsigned long global_lock;
-		unsigned int expect_event;
-		atomic_t leaving_burst;	/* 0 : No, 1 : Yes, 2: abort */
-		atomic_t pending_gpe;
-		struct semaphore sem;
-		wait_queue_head_t wait;
-	} intr;
-
-	struct {
-		u32 mode;
-		acpi_handle handle;
-		unsigned long uid;
-		unsigned long gpe_bit;
-		struct acpi_generic_address status_addr;
-		struct acpi_generic_address command_addr;
-		struct acpi_generic_address data_addr;
-		unsigned long global_lock;
-		struct semaphore sem;
-	} poll;
-};
-
-static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event);
-static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event);
-static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data);
-static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data);
-static void acpi_ec_gpe_poll_query(void *ec_cxt);
-static void acpi_ec_gpe_intr_query(void *ec_cxt);
-static u32 acpi_ec_gpe_poll_handler(void *data);
-static u32 acpi_ec_gpe_intr_handler(void *data);
-static acpi_status __init
-acpi_fake_ecdt_poll_callback(acpi_handle handle,
-				u32 Level, void *context, void **retval);
-
-static acpi_status __init
-acpi_fake_ecdt_intr_callback(acpi_handle handle,
-			      u32 Level, void *context, void **retval);
-
-static int __init acpi_ec_poll_get_real_ecdt(void);
-static int __init acpi_ec_intr_get_real_ecdt(void);
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
-static union acpi_ec *ec_ecdt;
+struct acpi_ec {
+	acpi_handle handle;
+	unsigned long uid;
+	unsigned long gpe_bit;
+	unsigned long command_addr;
+	unsigned long data_addr;
+	unsigned long global_lock;
+	struct semaphore sem;
+	unsigned int expect_event;
+	atomic_t leaving_burst;	/* 0 : No, 1 : Yes, 2: abort */
+	wait_queue_head_t wait;
+} *ec_ecdt;
 
 /* External interfaces use first EC only, so remember */
 static struct acpi_device *first_ec;
-static int acpi_ec_poll_mode = EC_INTR;
+static int acpi_ec_mode = EC_INTR;
 
 /* --------------------------------------------------------------------------
                              Transaction Management
    -------------------------------------------------------------------------- */
 
-static u32 acpi_ec_read_status(union acpi_ec *ec)
+static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
 {
-	u32 status = 0;
-
-	acpi_hw_low_level_read(8, &status, &ec->common.status_addr);
-	return status;
+	return inb(ec->command_addr);
 }
 
-static int acpi_ec_wait(union acpi_ec *ec, u8 event)
+static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
 {
-	if (acpi_ec_poll_mode)
-		return acpi_ec_poll_wait(ec, event);
-	else
-		return acpi_ec_intr_wait(ec, event);
+	return inb(ec->data_addr);
 }
 
-static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event)
+static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
 {
-	u32 acpi_ec_status = 0;
-	u32 i = ACPI_EC_UDELAY_COUNT;
+	outb(command, ec->command_addr);
+}
 
-	if (!ec)
-		return -EINVAL;
+static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
+{
+	outb(data, ec->data_addr);
+}
 
-	/* Poll the EC status register waiting for the event to occur. */
+static int acpi_ec_check_status(u8 status, u8 event)
+{
 	switch (event) {
-	case ACPI_EC_EVENT_OBF:
-		do {
-			acpi_hw_low_level_read(8, &acpi_ec_status,
-					       &ec->common.status_addr);
-			if (acpi_ec_status & ACPI_EC_FLAG_OBF)
-				return 0;
-			udelay(ACPI_EC_UDELAY);
-		} while (--i > 0);
+	case ACPI_EC_EVENT_OBF_1:
+		if (status & ACPI_EC_FLAG_OBF)
+			return 1;
 		break;
-	case ACPI_EC_EVENT_IBE:
-		do {
-			acpi_hw_low_level_read(8, &acpi_ec_status,
-					       &ec->common.status_addr);
-			if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
-				return 0;
-			udelay(ACPI_EC_UDELAY);
-		} while (--i > 0);
+	case ACPI_EC_EVENT_IBF_0:
+		if (!(status & ACPI_EC_FLAG_IBF))
+			return 1;
 		break;
 	default:
-		return -EINVAL;
+		break;
 	}
 
-	return -ETIME;
+	return 0;
 }
-static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event)
+
+static int acpi_ec_wait(struct acpi_ec *ec, u8 event)
 {
-	int result = 0;
+	int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0;
+	long time_left;
 
+	ec->expect_event = event;
+	if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
+		ec->expect_event = 0;
+		return 0;
+	}
 
-	ec->intr.expect_event = event;
-	smp_mb();
-
-	switch (event) {
-	case ACPI_EC_EVENT_IBE:
-		if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) {
-			ec->intr.expect_event = 0;
+	do {
+		if (acpi_ec_mode == EC_POLL) {
+			udelay(ACPI_EC_UDELAY);
+		} else {
+			time_left = wait_event_timeout(ec->wait,
+				    !ec->expect_event,
+				    msecs_to_jiffies(ACPI_EC_DELAY));
+			if (time_left > 0) {
+				ec->expect_event = 0;
+				return 0;
+			}
+		}
+		if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
+			ec->expect_event = 0;
 			return 0;
 		}
-		break;
-	default:
-		break;
-	}
+	} while (--i > 0);
 
-	result = wait_event_timeout(ec->intr.wait,
-				    !ec->intr.expect_event,
-				    msecs_to_jiffies(ACPI_EC_DELAY));
-
-	ec->intr.expect_event = 0;
-	smp_mb();
-
-	/*
-	 * Verify that the event in question has actually happened by
-	 * querying EC status. Do the check even if operation timed-out
-	 * to make sure that we did not miss interrupt.
-	 */
-	switch (event) {
-	case ACPI_EC_EVENT_OBF:
-		if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
-			return 0;
-		break;
-
-	case ACPI_EC_EVENT_IBE:
-		if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
-			return 0;
-		break;
-	}
+	ec->expect_event = 0;
 
 	return -ETIME;
 }
@@ -254,272 +191,150 @@
  * Note: samsung nv5000 doesn't work with ec burst mode.
  * http://bugzilla.kernel.org/show_bug.cgi?id=4980
  */
-int acpi_ec_enter_burst_mode(union acpi_ec *ec)
+int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
 {
-	u32 tmp = 0;
-	int status = 0;
+	u8 tmp = 0;
+	u8 status = 0;
 
 
 	status = acpi_ec_read_status(ec);
 	if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
-		status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+		status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
 		if (status)
 			goto end;
-		acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
-					&ec->common.command_addr);
-		status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
-		acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
+		acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE);
+		status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
+		tmp = acpi_ec_read_data(ec);
 		if (tmp != 0x90) {	/* Burst ACK byte */
 			return -EINVAL;
 		}
 	}
 
-	atomic_set(&ec->intr.leaving_burst, 0);
+	atomic_set(&ec->leaving_burst, 0);
 	return 0;
-      end:
-	ACPI_EXCEPTION ((AE_INFO, status, "EC wait, burst mode");
+  end:
+	ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
 	return -1;
 }
 
-int acpi_ec_leave_burst_mode(union acpi_ec *ec)
+int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
 {
-	int status = 0;
+	u8 status = 0;
 
 
 	status = acpi_ec_read_status(ec);
 	if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
-		status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+		status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
 		if(status)
 			goto end;
-		acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
-		acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
-	} 
-	atomic_set(&ec->intr.leaving_burst, 1);
+		acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE);
+		acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+	}
+	atomic_set(&ec->leaving_burst, 1);
 	return 0;
-end:
-	ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode");
+  end:
+	ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"));
 	return -1;
 }
 #endif /* ACPI_FUTURE_USAGE */
 
-static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
+					const u8 *wdata, unsigned wdata_len,
+					u8 *rdata, unsigned rdata_len)
 {
-	if (acpi_ec_poll_mode)
-		return acpi_ec_poll_read(ec, address, data);
-	else
-		return acpi_ec_intr_read(ec, address, data);
-}
-static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
-{
-	if (acpi_ec_poll_mode)
-		return acpi_ec_poll_write(ec, address, data);
-	else
-		return acpi_ec_intr_write(ec, address, data);
-}
-static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data)
-{
-	acpi_status status = AE_OK;
-	int result = 0;
-	u32 glk = 0;
+	int result;
 
+	acpi_ec_write_cmd(ec, command);
 
-	if (!ec || !data)
-		return -EINVAL;
-
-	*data = 0;
-
-	if (ec->common.global_lock) {
-		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-		if (ACPI_FAILURE(status))
-			return -ENODEV;
+	for (; wdata_len > 0; wdata_len --) {
+		result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+		if (result)
+			return result;
+		acpi_ec_write_data(ec, *(wdata++));
 	}
 
-	if (down_interruptible(&ec->poll.sem)) {
-		result = -ERESTARTSYS;
-		goto end_nosem;
+	if (command == ACPI_EC_COMMAND_WRITE) {
+		result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
+		if (result)
+			return result;
 	}
-	
-	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
-				&ec->common.command_addr);
-	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (result)
-		goto end;
 
-	acpi_hw_low_level_write(8, address, &ec->common.data_addr);
-	result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
-	if (result)
-		goto end;
+	for (; rdata_len > 0; rdata_len --) {
+		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
+		if (result)
+			return result;
 
-	acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+		*(rdata++) = acpi_ec_read_data(ec);
+	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
-			  *data, address));
-
-      end:
-	up(&ec->poll.sem);
-end_nosem:
-	if (ec->common.global_lock)
-		acpi_release_global_lock(glk);
-
-	return result;
+	return 0;
 }
 
-static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
+				const u8 *wdata, unsigned wdata_len,
+				u8 *rdata, unsigned rdata_len)
 {
-	int result = 0;
-	acpi_status status = AE_OK;
-	u32 glk = 0;
-
-
-	if (!ec)
-		return -EINVAL;
-
-	if (ec->common.global_lock) {
-		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-		if (ACPI_FAILURE(status))
-			return -ENODEV;
-	}
-
-	if (down_interruptible(&ec->poll.sem)) {
-		result = -ERESTARTSYS;
-		goto end_nosem;
-	}
-	
-	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
-				&ec->common.command_addr);
-	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (result)
-		goto end;
-
-	acpi_hw_low_level_write(8, address, &ec->common.data_addr);
-	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (result)
-		goto end;
-
-	acpi_hw_low_level_write(8, data, &ec->common.data_addr);
-	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (result)
-		goto end;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
-			  data, address));
-
-      end:
-	up(&ec->poll.sem);
-end_nosem:
-	if (ec->common.global_lock)
-		acpi_release_global_lock(glk);
-
-	return result;
-}
-
-static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data)
-{
-	int status = 0;
+	int status;
 	u32 glk;
 
-
-	if (!ec || !data)
+	if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
 		return -EINVAL;
 
-	*data = 0;
+        if (rdata)
+                memset(rdata, 0, rdata_len);
 
-	if (ec->common.global_lock) {
+	if (ec->global_lock) {
 		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
 		if (ACPI_FAILURE(status))
 			return -ENODEV;
 	}
+	down(&ec->sem);
 
-	WARN_ON(in_interrupt());
-	down(&ec->intr.sem);
-
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
 	if (status) {
 		printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
 		goto end;
 	}
-	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
-				&ec->common.command_addr);
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
-	}
 
-	acpi_hw_low_level_write(8, address, &ec->common.data_addr);
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "read EC, OB not full\n");
-		goto end;
-	}
-	acpi_hw_low_level_read(8, data, &ec->common.data_addr);
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
-			  *data, address));
+        status = acpi_ec_transaction_unlocked(ec, command,
+                                              wdata, wdata_len,
+                                              rdata, rdata_len);
 
-      end:
-	up(&ec->intr.sem);
+end:
+	up(&ec->sem);
 
-	if (ec->common.global_lock)
+	if (ec->global_lock)
 		acpi_release_global_lock(glk);
 
 	return status;
 }
 
-static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
 {
-	int status = 0;
-	u32 glk;
+	int result;
+	u8 d;
 
+	result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
+				     &address, 1, &d, 1);
+	*data = d;
+	return result;
+}
 
-	if (!ec)
-		return -EINVAL;
-
-	if (ec->common.global_lock) {
-		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-		if (ACPI_FAILURE(status))
-			return -ENODEV;
-	}
-
-	WARN_ON(in_interrupt());
-	down(&ec->intr.sem);
-
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
-	}
-	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
-				&ec->common.command_addr);
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
-	}
-
-	acpi_hw_low_level_write(8, address, &ec->common.data_addr);
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
-	}
-
-	acpi_hw_low_level_write(8, data, &ec->common.data_addr);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
-			  data, address));
-
-	up(&ec->intr.sem);
-
-	if (ec->common.global_lock)
-		acpi_release_global_lock(glk);
-
-	return status;
+static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
+{
+        u8 wdata[2] = { address, data };
+        return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
+				   wdata, 2, NULL, 0);
 }
 
 /*
  * Externally callable EC access functions. For now, assume 1 EC only
  */
-int ec_read(u8 addr, u8 * val)
+int ec_read(u8 addr, u8 *val)
 {
-	union acpi_ec *ec;
+	struct acpi_ec *ec;
 	int err;
-	u32 temp_data;
+	u8 temp_data;
 
 	if (!first_ec)
 		return -ENODEV;
@@ -539,7 +354,7 @@
 
 int ec_write(u8 addr, u8 val)
 {
-	union acpi_ec *ec;
+	struct acpi_ec *ec;
 	int err;
 
 	if (!first_ec)
@@ -554,255 +369,106 @@
 
 EXPORT_SYMBOL(ec_write);
 
-static int acpi_ec_query(union acpi_ec *ec, u32 * data)
+extern int ec_transaction(u8 command,
+                          const u8 *wdata, unsigned wdata_len,
+                          u8 *rdata, unsigned rdata_len)
 {
-	if (acpi_ec_poll_mode)
-		return acpi_ec_poll_query(ec, data);
-	else
-		return acpi_ec_intr_query(ec, data);
+	struct acpi_ec *ec;
+
+	if (!first_ec)
+		return -ENODEV;
+
+	ec = acpi_driver_data(first_ec);
+
+	return acpi_ec_transaction(ec, command, wdata,
+				   wdata_len, rdata, rdata_len);
 }
-static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data)
+
+EXPORT_SYMBOL(ec_transaction);
+
+static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
 {
-	int result = 0;
-	acpi_status status = AE_OK;
-	u32 glk = 0;
+	int result;
+        u8 d;
 
+        if (!ec || !data)
+                return -EINVAL;
 
-	if (!ec || !data)
-		return -EINVAL;
+        /*
+         * Query the EC to find out which _Qxx method we need to evaluate.
+         * Note that successful completion of the query causes the ACPI_EC_SCI
+         * bit to be cleared (and thus clearing the interrupt source).
+         */
 
-	*data = 0;
+        result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
+        if (result)
+                return result;
 
-	if (ec->common.global_lock) {
-		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-		if (ACPI_FAILURE(status))
-			return -ENODEV;
-	}
+        if (!d)
+                return -ENODATA;
 
-	/*
-	 * Query the EC to find out which _Qxx method we need to evaluate.
-	 * Note that successful completion of the query causes the ACPI_EC_SCI
-	 * bit to be cleared (and thus clearing the interrupt source).
-	 */
-	if (down_interruptible(&ec->poll.sem)) {
-		result = -ERESTARTSYS;
-		goto end_nosem;
-	}
-	
-	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
-				&ec->common.command_addr);
-	result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
-	if (result)
-		goto end;
-
-	acpi_hw_low_level_read(8, data, &ec->common.data_addr);
-	if (!*data)
-		result = -ENODATA;
-
-      end:
-	up(&ec->poll.sem);
-end_nosem:
-	if (ec->common.global_lock)
-		acpi_release_global_lock(glk);
-
-	return result;
-}
-static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data)
-{
-	int status = 0;
-	u32 glk;
-
-
-	if (!ec || !data)
-		return -EINVAL;
-	*data = 0;
-
-	if (ec->common.global_lock) {
-		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
-		if (ACPI_FAILURE(status))
-			return -ENODEV;
-	}
-
-	down(&ec->intr.sem);
-
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "query EC, IB not empty\n");
-		goto end;
-	}
-	/*
-	 * Query the EC to find out which _Qxx method we need to evaluate.
-	 * Note that successful completion of the query causes the ACPI_EC_SCI
-	 * bit to be cleared (and thus clearing the interrupt source).
-	 */
-	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
-				&ec->common.command_addr);
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
-	if (status) {
-		printk(KERN_DEBUG PREFIX "query EC, OB not full\n");
-		goto end;
-	}
-
-	acpi_hw_low_level_read(8, data, &ec->common.data_addr);
-	if (!*data)
-		status = -ENODATA;
-
-      end:
-	up(&ec->intr.sem);
-
-	if (ec->common.global_lock)
-		acpi_release_global_lock(glk);
-
-	return status;
+        *data = d;
+        return 0;
 }
 
 /* --------------------------------------------------------------------------
                                 Event Management
    -------------------------------------------------------------------------- */
 
-union acpi_ec_query_data {
+struct acpi_ec_query_data {
 	acpi_handle handle;
 	u8 data;
 };
 
 static void acpi_ec_gpe_query(void *ec_cxt)
 {
-	if (acpi_ec_poll_mode)
-		acpi_ec_gpe_poll_query(ec_cxt);
-	else
-		acpi_ec_gpe_intr_query(ec_cxt);
-}
+	struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
+	u8 value = 0;
+	static char object_name[8];
 
-static void acpi_ec_gpe_poll_query(void *ec_cxt)
-{
-	union acpi_ec *ec = (union acpi_ec *)ec_cxt;
-	u32 value = 0;
-	static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
-	const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
-		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-	};
-
-
-	if (!ec_cxt)
+	if (!ec)
 		goto end;
 
-	if (down_interruptible (&ec->poll.sem)) {
-		return;
-	}
-	acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
-	up(&ec->poll.sem);
+	value = acpi_ec_read_status(ec);
 
-	/* TBD: Implement asynch events!
-	 * NOTE: All we care about are EC-SCI's.  Other EC events are
-	 * handled via polling (yuck!).  This is because some systems
-	 * treat EC-SCIs as level (versus EDGE!) triggered, preventing
-	 *  a purely interrupt-driven approach (grumble, grumble).
-	 */
 	if (!(value & ACPI_EC_FLAG_SCI))
 		goto end;
 
 	if (acpi_ec_query(ec, &value))
 		goto end;
 
-	object_name[2] = hex[((value >> 4) & 0x0F)];
-	object_name[3] = hex[(value & 0x0F)];
+	snprintf(object_name, 8, "_Q%2.2X", value);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
 
-	acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
+	acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
 
       end:
-	acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
-}
-static void acpi_ec_gpe_intr_query(void *ec_cxt)
-{
-	union acpi_ec *ec = (union acpi_ec *)ec_cxt;
-	u32 value;
-	int result = -ENODATA;
-	static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
-	const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
-		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-	};
-
-
-	if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI)
-		result = acpi_ec_query(ec, &value);
-
-	if (result)
-		goto end;
-
-	object_name[2] = hex[((value >> 4) & 0x0F)];
-	object_name[3] = hex[(value & 0x0F)];
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
-
-	acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
-      end:
-	atomic_dec(&ec->intr.pending_gpe);
-	return;
+	acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 }
 
 static u32 acpi_ec_gpe_handler(void *data)
 {
-	if (acpi_ec_poll_mode)
-		return acpi_ec_gpe_poll_handler(data);
-	else
-		return acpi_ec_gpe_intr_handler(data);
-}
-static u32 acpi_ec_gpe_poll_handler(void *data)
-{
 	acpi_status status = AE_OK;
-	union acpi_ec *ec = (union acpi_ec *)data;
+	u8 value;
+	struct acpi_ec *ec = (struct acpi_ec *)data;
 
-	if (!ec)
-		return ACPI_INTERRUPT_NOT_HANDLED;
-
-	acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
-
-	status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec);
-
-	if (status == AE_OK)
-		return ACPI_INTERRUPT_HANDLED;
-	else
-		return ACPI_INTERRUPT_NOT_HANDLED;
-}
-static u32 acpi_ec_gpe_intr_handler(void *data)
-{
-	acpi_status status = AE_OK;
-	u32 value;
-	union acpi_ec *ec = (union acpi_ec *)data;
-
-	if (!ec)
-		return ACPI_INTERRUPT_NOT_HANDLED;
-
-	acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
+	acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR);
 	value = acpi_ec_read_status(ec);
 
-	switch (ec->intr.expect_event) {
-	case ACPI_EC_EVENT_OBF:
-		if (!(value & ACPI_EC_FLAG_OBF))
-			break;
-		ec->intr.expect_event = 0;
-		wake_up(&ec->intr.wait);
-		break;
-	case ACPI_EC_EVENT_IBE:
-		if ((value & ACPI_EC_FLAG_IBF))
-			break;
-		ec->intr.expect_event = 0;
-		wake_up(&ec->intr.wait);
-		break;
-	default:
-		break;
+	if (acpi_ec_mode == EC_INTR) {
+		if (acpi_ec_check_status(value, ec->expect_event)) {
+			ec->expect_event = 0;
+			wake_up(&ec->wait);
+		}
 	}
 
 	if (value & ACPI_EC_FLAG_SCI) {
-		atomic_add(1, &ec->intr.pending_gpe);
-		status = acpi_os_execute(OSL_EC_BURST_HANDLER,
-						     acpi_ec_gpe_query, ec);
+		status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
 		return status == AE_OK ?
 		    ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 	}
-	acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
+	acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
 	return status == AE_OK ?
 	    ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 }
@@ -833,7 +499,7 @@
 		      void *handler_context, void *region_context)
 {
 	int result = 0;
-	union acpi_ec *ec = NULL;
+	struct acpi_ec *ec = NULL;
 	u64 temp = *value;
 	acpi_integer f_v = 0;
 	int i = 0;
@@ -843,18 +509,16 @@
 		return AE_BAD_PARAMETER;
 
 	if (bit_width != 8 && acpi_strict) {
-		printk(KERN_WARNING PREFIX
-		       "acpi_ec_space_handler: bit_width should be 8\n");
 		return AE_BAD_PARAMETER;
 	}
 
-	ec = (union acpi_ec *)handler_context;
+	ec = (struct acpi_ec *)handler_context;
 
       next_byte:
 	switch (function) {
 	case ACPI_READ:
 		temp = 0;
-		result = acpi_ec_read(ec, (u8) address, (u32 *) & temp);
+		result = acpi_ec_read(ec, (u8) address, (u8 *) &temp);
 		break;
 	case ACPI_WRITE:
 		result = acpi_ec_write(ec, (u8) address, (u8) temp);
@@ -905,20 +569,20 @@
 
 static int acpi_ec_read_info(struct seq_file *seq, void *offset)
 {
-	union acpi_ec *ec = (union acpi_ec *)seq->private;
+	struct acpi_ec *ec = (struct acpi_ec *)seq->private;
 
 
 	if (!ec)
 		goto end;
 
 	seq_printf(seq, "gpe bit:                 0x%02x\n",
-		   (u32) ec->common.gpe_bit);
+		   (u32) ec->gpe_bit);
 	seq_printf(seq, "ports:                   0x%02x, 0x%02x\n",
-		   (u32) ec->common.status_addr.address,
-		   (u32) ec->common.data_addr.address);
+		   (u32) ec->command_addr,
+		   (u32) ec->data_addr);
 	seq_printf(seq, "use global lock:         %s\n",
-		   ec->common.global_lock ? "yes" : "no");
-	acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+		   ec->global_lock ? "yes" : "no");
+	acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 
       end:
 	return 0;
@@ -929,7 +593,7 @@
 	return single_open(file, acpi_ec_read_info, PDE(inode)->data);
 }
 
-static const struct file_operations acpi_ec_info_ops = {
+static struct file_operations acpi_ec_info_ops = {
 	.open = acpi_ec_info_open_fs,
 	.read = seq_read,
 	.llseek = seq_lseek,
@@ -978,31 +642,35 @@
                                Driver Interface
    -------------------------------------------------------------------------- */
 
-static int acpi_ec_poll_add(struct acpi_device *device)
+static int acpi_ec_add(struct acpi_device *device)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
-	union acpi_ec *ec = NULL;
+	struct acpi_ec *ec = NULL;
 
 
 	if (!device)
 		return -EINVAL;
 
-	ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+	ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 	if (!ec)
 		return -ENOMEM;
-	memset(ec, 0, sizeof(union acpi_ec));
+	memset(ec, 0, sizeof(struct acpi_ec));
 
-	ec->common.handle = device->handle;
-	ec->common.uid = -1;
-	init_MUTEX(&ec->poll.sem);
+	ec->handle = device->handle;
+	ec->uid = -1;
+	init_MUTEX(&ec->sem);
+	if (acpi_ec_mode == EC_INTR) {
+		atomic_set(&ec->leaving_burst, 1);
+		init_waitqueue_head(&ec->wait);
+	}
 	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_EC_CLASS);
 	acpi_driver_data(device) = ec;
 
 	/* Use the global lock for all EC transactions? */
-	acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
-			      &ec->common.global_lock);
+	acpi_evaluate_integer(ec->handle, "_GLK", NULL,
+			      &ec->global_lock);
 
 	/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
 	   http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
@@ -1011,7 +679,7 @@
 						  ACPI_ADR_SPACE_EC,
 						  &acpi_ec_space_handler);
 
-		acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+		acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
 					&acpi_ec_gpe_handler);
 
 		kfree(ec_ecdt);
@@ -1020,10 +688,10 @@
 	/* Get GPE bit assignment (EC events). */
 	/* TODO: Add support for _GPE returning a package */
 	status =
-	    acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
-				  &ec->common.gpe_bit);
+	    acpi_evaluate_integer(ec->handle, "_GPE", NULL,
+				  &ec->gpe_bit);
 	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit"));
+		ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment"));
 		result = -ENODEV;
 		goto end;
 	}
@@ -1032,84 +700,14 @@
 	if (result)
 		goto end;
 
-	printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
 	       acpi_device_name(device), acpi_device_bid(device),
-	       (u32) ec->common.gpe_bit);
+	       (u32) ec->gpe_bit));
 
 	if (!first_ec)
 		first_ec = device;
 
-      end:
-	if (result)
-		kfree(ec);
-
-	return result;
-}
-static int acpi_ec_intr_add(struct acpi_device *device)
-{
-	int result = 0;
-	acpi_status status = AE_OK;
-	union acpi_ec *ec = NULL;
-
-
-	if (!device)
-		return -EINVAL;
-
-	ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
-	if (!ec)
-		return -ENOMEM;
-	memset(ec, 0, sizeof(union acpi_ec));
-
-	ec->common.handle = device->handle;
-	ec->common.uid = -1;
-	atomic_set(&ec->intr.pending_gpe, 0);
-	atomic_set(&ec->intr.leaving_burst, 1);
-	init_MUTEX(&ec->intr.sem);
-	init_waitqueue_head(&ec->intr.wait);
-	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ACPI_EC_CLASS);
-	acpi_driver_data(device) = ec;
-
-	/* Use the global lock for all EC transactions? */
-	acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
-			      &ec->common.global_lock);
-
-	/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
-	   http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
-	if (ec_ecdt) {
-		acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
-						  ACPI_ADR_SPACE_EC,
-						  &acpi_ec_space_handler);
-
-		acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
-					&acpi_ec_gpe_handler);
-
-		kfree(ec_ecdt);
-	}
-
-	/* Get GPE bit assignment (EC events). */
-	/* TODO: Add support for _GPE returning a package */
-	status =
-	    acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
-				  &ec->common.gpe_bit);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX "Obtaining GPE bit assignment\n");
-		result = -ENODEV;
-		goto end;
-	}
-
-	result = acpi_ec_add_fs(device);
-	if (result)
-		goto end;
-
-	printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n",
-	       acpi_device_name(device), acpi_device_bid(device),
-	       (u32) ec->common.gpe_bit);
-
-	if (!first_ec)
-		first_ec = device;
-
-      end:
+  end:
 	if (result)
 		kfree(ec);
 
@@ -1118,7 +716,7 @@
 
 static int acpi_ec_remove(struct acpi_device *device, int type)
 {
-	union acpi_ec *ec = NULL;
+	struct acpi_ec *ec = NULL;
 
 
 	if (!device)
@@ -1136,8 +734,7 @@
 static acpi_status
 acpi_ec_io_ports(struct acpi_resource *resource, void *context)
 {
-	union acpi_ec *ec = (union acpi_ec *)context;
-	struct acpi_generic_address *addr;
+	struct acpi_ec *ec = (struct acpi_ec *)context;
 
 	if (resource->type != ACPI_RESOURCE_TYPE_IO) {
 		return AE_OK;
@@ -1148,26 +745,21 @@
 	 * the second address region returned is the status/command
 	 * port.
 	 */
-	if (ec->common.data_addr.register_bit_width == 0) {
-		addr = &ec->common.data_addr;
-	} else if (ec->common.command_addr.register_bit_width == 0) {
-		addr = &ec->common.command_addr;
+	if (ec->data_addr == 0) {
+		ec->data_addr = resource->data.io.minimum;
+	} else if (ec->command_addr == 0) {
+		ec->command_addr = resource->data.io.minimum;
 	} else {
 		return AE_CTRL_TERMINATE;
 	}
 
-	addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
-	addr->register_bit_width = 8;
-	addr->register_bit_offset = 0;
-	addr->address = resource->data.io.minimum;
-
 	return AE_OK;
 }
 
 static int acpi_ec_start(struct acpi_device *device)
 {
 	acpi_status status = AE_OK;
-	union acpi_ec *ec = NULL;
+	struct acpi_ec *ec = NULL;
 
 
 	if (!device)
@@ -1181,39 +773,35 @@
 	/*
 	 * Get I/O port addresses. Convert to GAS format.
 	 */
-	status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS,
+	status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
 				     acpi_ec_io_ports, ec);
-	if (ACPI_FAILURE(status)
-	    || ec->common.command_addr.register_bit_width == 0) {
-		printk(KERN_ERR PREFIX "Error getting I/O port addresses\n");
+	if (ACPI_FAILURE(status) || ec->command_addr == 0) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Error getting I/O port addresses"));
 		return -ENODEV;
 	}
 
-	ec->common.status_addr = ec->common.command_addr;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
-			  (u32) ec->common.gpe_bit,
-			  (u32) ec->common.command_addr.address,
-			  (u32) ec->common.data_addr.address));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
+			  ec->gpe_bit, ec->command_addr, ec->data_addr));
 
 	/*
 	 * Install GPE handler
 	 */
-	status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit,
+	status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
 					  ACPI_GPE_EDGE_TRIGGERED,
 					  &acpi_ec_gpe_handler, ec);
 	if (ACPI_FAILURE(status)) {
 		return -ENODEV;
 	}
-	acpi_set_gpe_type(NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-	acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+	acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+	acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 
-	status = acpi_install_address_space_handler(ec->common.handle,
+	status = acpi_install_address_space_handler(ec->handle,
 						    ACPI_ADR_SPACE_EC,
 						    &acpi_ec_space_handler,
 						    &acpi_ec_space_setup, ec);
 	if (ACPI_FAILURE(status)) {
-		acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
+		acpi_remove_gpe_handler(NULL, ec->gpe_bit,
 					&acpi_ec_gpe_handler);
 		return -ENODEV;
 	}
@@ -1224,7 +812,7 @@
 static int acpi_ec_stop(struct acpi_device *device, int type)
 {
 	acpi_status status = AE_OK;
-	union acpi_ec *ec = NULL;
+	struct acpi_ec *ec = NULL;
 
 
 	if (!device)
@@ -1232,14 +820,14 @@
 
 	ec = acpi_driver_data(device);
 
-	status = acpi_remove_address_space_handler(ec->common.handle,
+	status = acpi_remove_address_space_handler(ec->handle,
 						   ACPI_ADR_SPACE_EC,
 						   &acpi_ec_space_handler);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
 	status =
-	    acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
+	    acpi_remove_gpe_handler(NULL, ec->gpe_bit,
 				    &acpi_ec_gpe_handler);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
@@ -1251,76 +839,30 @@
 acpi_fake_ecdt_callback(acpi_handle handle,
 			u32 Level, void *context, void **retval)
 {
-
-	if (acpi_ec_poll_mode)
-		return acpi_fake_ecdt_poll_callback(handle,
-						       Level, context, retval);
-	else
-		return acpi_fake_ecdt_intr_callback(handle,
-						     Level, context, retval);
-}
-
-static acpi_status __init
-acpi_fake_ecdt_poll_callback(acpi_handle handle,
-				u32 Level, void *context, void **retval)
-{
 	acpi_status status;
 
+	init_MUTEX(&ec_ecdt->sem);
+	if (acpi_ec_mode == EC_INTR) {
+		init_waitqueue_head(&ec_ecdt->wait);
+	}
 	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
 				     acpi_ec_io_ports, ec_ecdt);
 	if (ACPI_FAILURE(status))
 		return status;
-	ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
 
-	ec_ecdt->common.uid = -1;
-	acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
+	ec_ecdt->uid = -1;
+	acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
 
 	status =
 	    acpi_evaluate_integer(handle, "_GPE", NULL,
-				  &ec_ecdt->common.gpe_bit);
+				  &ec_ecdt->gpe_bit);
 	if (ACPI_FAILURE(status))
 		return status;
-	init_MUTEX(&ec_ecdt->poll.sem);
-	ec_ecdt->common.global_lock = TRUE;
-	ec_ecdt->common.handle = handle;
+	ec_ecdt->global_lock = TRUE;
+	ec_ecdt->handle = handle;
 
-	printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
-	       (u32) ec_ecdt->common.gpe_bit,
-	       (u32) ec_ecdt->common.command_addr.address,
-	       (u32) ec_ecdt->common.data_addr.address);
-
-	return AE_CTRL_TERMINATE;
-}
-
-static acpi_status __init
-acpi_fake_ecdt_intr_callback(acpi_handle handle,
-			      u32 Level, void *context, void **retval)
-{
-	acpi_status status;
-
-	init_MUTEX(&ec_ecdt->intr.sem);
-	init_waitqueue_head(&ec_ecdt->intr.wait);
-	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
-				     acpi_ec_io_ports, ec_ecdt);
-	if (ACPI_FAILURE(status))
-		return status;
-	ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
-
-	ec_ecdt->common.uid = -1;
-	acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
-
-	status =
-	    acpi_evaluate_integer(handle, "_GPE", NULL,
-				  &ec_ecdt->common.gpe_bit);
-	if (ACPI_FAILURE(status))
-		return status;
-	ec_ecdt->common.global_lock = TRUE;
-	ec_ecdt->common.handle = handle;
-
-	printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
-	       (u32) ec_ecdt->common.gpe_bit,
-	       (u32) ec_ecdt->common.command_addr.address,
-	       (u32) ec_ecdt->common.data_addr.address);
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
+	       ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr));
 
 	return AE_CTRL_TERMINATE;
 }
@@ -1340,14 +882,14 @@
 	acpi_status status;
 	int ret = 0;
 
-	printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT"));
 
-	ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+	ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 	if (!ec_ecdt) {
 		ret = -ENOMEM;
 		goto error;
 	}
-	memset(ec_ecdt, 0, sizeof(union acpi_ec));
+	memset(ec_ecdt, 0, sizeof(struct acpi_ec));
 
 	status = acpi_get_devices(ACPI_EC_HID,
 				  acpi_fake_ecdt_callback, NULL, NULL);
@@ -1355,24 +897,16 @@
 		kfree(ec_ecdt);
 		ec_ecdt = NULL;
 		ret = -ENODEV;
+		ACPI_EXCEPTION((AE_INFO, status, "Can't make an fake ECDT"));
 		goto error;
 	}
 	return 0;
-      error:
-	printk(KERN_ERR PREFIX "Can't make an fake ECDT\n");
+  error:
 	return ret;
 }
 
 static int __init acpi_ec_get_real_ecdt(void)
 {
-	if (acpi_ec_poll_mode)
-		return acpi_ec_poll_get_real_ecdt();
-	else
-		return acpi_ec_intr_get_real_ecdt();
-}
-
-static int __init acpi_ec_poll_get_real_ecdt(void)
-{
 	acpi_status status;
 	struct acpi_table_ecdt *ecdt_ptr;
 
@@ -1382,80 +916,36 @@
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	printk(KERN_INFO PREFIX "Found ECDT\n");
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
 
 	/*
 	 * Generate a temporary ec context to use until the namespace is scanned
 	 */
-	ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+	ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 	if (!ec_ecdt)
 		return -ENOMEM;
-	memset(ec_ecdt, 0, sizeof(union acpi_ec));
+	memset(ec_ecdt, 0, sizeof(struct acpi_ec));
 
-	ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
-	ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
-	ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
-	ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
-	init_MUTEX(&ec_ecdt->poll.sem);
+	init_MUTEX(&ec_ecdt->sem);
+	if (acpi_ec_mode == EC_INTR) {
+		init_waitqueue_head(&ec_ecdt->wait);
+	}
+	ec_ecdt->command_addr = ecdt_ptr->ec_control.address;
+	ec_ecdt->data_addr = ecdt_ptr->ec_data.address;
+	ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
 	/* use the GL just to be safe */
-	ec_ecdt->common.global_lock = TRUE;
-	ec_ecdt->common.uid = ecdt_ptr->uid;
+	ec_ecdt->global_lock = TRUE;
+	ec_ecdt->uid = ecdt_ptr->uid;
 
 	status =
-	    acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+	    acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
 	if (ACPI_FAILURE(status)) {
 		goto error;
 	}
 
 	return 0;
-      error:
-	printk(KERN_ERR PREFIX "Could not use ECDT\n");
-	kfree(ec_ecdt);
-	ec_ecdt = NULL;
-
-	return -ENODEV;
-}
-
-static int __init acpi_ec_intr_get_real_ecdt(void)
-{
-	acpi_status status;
-	struct acpi_table_ecdt *ecdt_ptr;
-
-	status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
-					 (struct acpi_table_header **)
-					 &ecdt_ptr);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	printk(KERN_INFO PREFIX "Found ECDT\n");
-
-	/*
-	 * Generate a temporary ec context to use until the namespace is scanned
-	 */
-	ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
-	if (!ec_ecdt)
-		return -ENOMEM;
-	memset(ec_ecdt, 0, sizeof(union acpi_ec));
-
-	init_MUTEX(&ec_ecdt->intr.sem);
-	init_waitqueue_head(&ec_ecdt->intr.wait);
-	ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
-	ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
-	ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
-	ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
-	/* use the GL just to be safe */
-	ec_ecdt->common.global_lock = TRUE;
-	ec_ecdt->common.uid = ecdt_ptr->uid;
-
-	status =
-	    acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
-	if (ACPI_FAILURE(status)) {
-		goto error;
-	}
-
-	return 0;
-      error:
-	printk(KERN_ERR PREFIX "Could not use ECDT\n");
+  error:
+	ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
 	kfree(ec_ecdt);
 	ec_ecdt = NULL;
 
@@ -1480,14 +970,14 @@
 	/*
 	 * Install GPE handler
 	 */
-	status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+	status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
 					  ACPI_GPE_EDGE_TRIGGERED,
 					  &acpi_ec_gpe_handler, ec_ecdt);
 	if (ACPI_FAILURE(status)) {
 		goto error;
 	}
-	acpi_set_gpe_type(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-	acpi_enable_gpe(NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
+	acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+	acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
 
 	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
 						    ACPI_ADR_SPACE_EC,
@@ -1495,7 +985,7 @@
 						    &acpi_ec_space_setup,
 						    ec_ecdt);
 	if (ACPI_FAILURE(status)) {
-		acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+		acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
 					&acpi_ec_gpe_handler);
 		goto error;
 	}
@@ -1503,7 +993,7 @@
 	return 0;
 
       error:
-	printk(KERN_ERR PREFIX "Could not use ECDT\n");
+	ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
 	kfree(ec_ecdt);
 	ec_ecdt = NULL;
 
@@ -1562,13 +1052,13 @@
 		return 0;
 
 	if (intr) {
-		acpi_ec_poll_mode = EC_INTR;
-		acpi_ec_driver.ops.add = acpi_ec_intr_add;
+		acpi_ec_mode = EC_INTR;
 	} else {
-		acpi_ec_poll_mode = EC_POLL;
-		acpi_ec_driver.ops.add = acpi_ec_poll_add;
+		acpi_ec_mode = EC_POLL;
 	}
-	printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
+	acpi_ec_driver.ops.add = acpi_ec_add;
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", intr ? "interrupt" : "polling"));
+
 	return 1;
 }
 
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 6eef4ef..ee2a10b 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -342,20 +342,8 @@
 	if (acquired) {
 
 		/* Got the lock, now wake all threads waiting for it */
-
 		acpi_gbl_global_lock_acquired = TRUE;
-
-		/* Run the Global Lock thread which will signal all waiting threads */
-
-		status =
-		    acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER,
-				    acpi_ev_global_lock_thread, context);
-		if (ACPI_FAILURE(status)) {
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Could not queue Global Lock thread"));
-
-			return (ACPI_INTERRUPT_NOT_HANDLED);
-		}
+		acpi_ev_global_lock_thread(context);
 	}
 
 	return (ACPI_INTERRUPT_HANDLED);
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index 5b3c7a8..203d135 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -225,13 +225,12 @@
 				if (!
 				    (ACPI_STRNCMP
 				     (object_hID.value, PCI_ROOT_HID_STRING,
-				      sizeof(PCI_ROOT_HID_STRING))
-				     ||
-				     !(ACPI_STRNCMP
-				       (object_hID.value,
-					PCI_EXPRESS_ROOT_HID_STRING,
-					sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
-				{
+				      sizeof(PCI_ROOT_HID_STRING)))
+				    ||
+				    !(ACPI_STRNCMP
+				      (object_hID.value,
+				       PCI_EXPRESS_ROOT_HID_STRING,
+				       sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
 
 					/* Install a handler for this PCI root bridge */
 
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 3143f36..fa58c1e 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -665,8 +665,6 @@
 
 		/*
 		 * Perform a read first to preserve certain bits (per ACPI spec)
-		 *
-		 * Note: This includes SCI_EN, we never want to change this bit
 		 */
 		status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
 					       ACPI_REGISTER_PM1_CONTROL,
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 15fc124..003a987 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -1702,13 +1702,11 @@
 	 .name = "brightness",
 	 .read = brightness_read,
 	 .write = brightness_write,
-	 .experimental = 1,
 	 },
 	{
 	 .name = "volume",
 	 .read = volume_read,
 	 .write = volume_write,
-	 .experimental = 1,
 	 },
 	{
 	 .name = "fan",
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index ec6b7f9..2e17ec7 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -48,6 +48,12 @@
  * the io ports if they really know they can use it, while
  * still preventing hotplug PCI devices from using it.
  */
+
+/*
+ * When CONFIG_PNP is enabled, pnp/system.c binds to PNP0C01
+ * and PNP0C02, redundant with acpi_reserve_io_ranges().
+ * But acpi_reserve_io_ranges() is necessary for !CONFIG_PNP.
+ */
 static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
 {
 	struct resource *requested_res = NULL;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 20beea7..c84286c 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -73,6 +73,7 @@
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
+static struct workqueue_struct *kacpi_notify_wq;
 
 acpi_status acpi_os_initialize(void)
 {
@@ -91,8 +92,9 @@
 		return AE_NULL_ENTRY;
 	}
 	kacpid_wq = create_singlethread_workqueue("kacpid");
+	kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
 	BUG_ON(!kacpid_wq);
-
+	BUG_ON(!kacpi_notify_wq);
 	return AE_OK;
 }
 
@@ -104,6 +106,7 @@
 	}
 
 	destroy_workqueue(kacpid_wq);
+	destroy_workqueue(kacpi_notify_wq);
 
 	return AE_OK;
 }
@@ -237,7 +240,7 @@
 	return AE_OK;
 }
 
-static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t acpi_irq(int irq, void *dev_id)
 {
 	return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -566,10 +569,7 @@
 
 static void acpi_os_execute_deferred(void *context)
 {
-	struct acpi_os_dpc *dpc = NULL;
-
-
-	dpc = (struct acpi_os_dpc *)context;
+	struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
 	if (!dpc) {
 		printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
 		return;
@@ -604,14 +604,12 @@
 	struct acpi_os_dpc *dpc;
 	struct work_struct *task;
 
-	ACPI_FUNCTION_TRACE("os_queue_for_execution");
-
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 			  "Scheduling function [%p(%p)] for deferred execution.\n",
 			  function, context));
 
 	if (!function)
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
+		return AE_BAD_PARAMETER;
 
 	/*
 	 * Allocate/initialize DPC structure.  Note that this memory will be
@@ -624,26 +622,20 @@
 	 * from the same memory.
 	 */
 
-	dpc =
-	    kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
-		    GFP_ATOMIC);
+	dpc = kmalloc(sizeof(struct acpi_os_dpc) +
+			sizeof(struct work_struct), GFP_ATOMIC);
 	if (!dpc)
-		return_ACPI_STATUS(AE_NO_MEMORY);
-
+		return AE_NO_MEMORY;
 	dpc->function = function;
 	dpc->context = context;
-
 	task = (void *)(dpc + 1);
 	INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
-
-	if (!queue_work(kacpid_wq, task)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Call to queue_work() failed.\n"));
-		kfree(dpc);
+	if (!queue_work((type == OSL_NOTIFY_HANDLER)?
+			kacpi_notify_wq : kacpid_wq, task)) {
 		status = AE_ERROR;
+		kfree(dpc);
 	}
-
-	return_ACPI_STATUS(status);
+	return status;
 }
 
 EXPORT_SYMBOL(acpi_os_execute);
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 7f3e7e7..d53bd98 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -307,7 +307,7 @@
 	if (!link || !irq)
 		return -EINVAL;
 
-	resource = kmalloc(sizeof(*resource) + 1, GFP_ATOMIC);
+	resource = kmalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
 	if (!resource)
 		return -ENOMEM;
 
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index fec225d..fe67a8a 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -216,10 +216,8 @@
 {
 	int result = 0;
 	acpi_status status = AE_OK;
-	struct acpi_device *device = NULL;
 	struct acpi_power_resource *resource = NULL;
 
-
 	result = acpi_power_get_context(handle, &resource);
 	if (result)
 		return result;
@@ -230,13 +228,13 @@
 	if (resource->references) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Resource [%s] is still in use, dereferencing\n",
-				  device->pnp.bus_id));
+				  resource->device->pnp.bus_id));
 		return 0;
 	}
 
 	if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
-				  device->pnp.bus_id));
+				  resource->device->pnp.bus_id));
 		return 0;
 	}
 
@@ -251,8 +249,7 @@
 		return -ENOEXEC;
 
 	/* Update the power resource's _device_ power state */
-	device = resource->device;
-	device->power.state = ACPI_STATE_D3;
+	resource->device->power.state = ACPI_STATE_D3;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
 			  resource->name));
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index b13d644..1908e0d2 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -519,7 +519,7 @@
 
 static void *processor_device_array[NR_CPUS];
 
-static int acpi_processor_start(struct acpi_device *device)
+static int __cpuinit acpi_processor_start(struct acpi_device *device)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 0a395fc..65b3f05 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -219,6 +219,23 @@
 
 static atomic_t c3_cpu_count;
 
+/* Common C-state entry for C2, C3, .. */
+static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
+{
+	if (cstate->space_id == ACPI_CSTATE_FFH) {
+		/* Call into architectural FFH based C-state */
+		acpi_processor_ffh_cstate_enter(cstate);
+	} else {
+		int unused;
+		/* IO port based C-state */
+		inb(cstate->address);
+		/* Dummy wait op - must do something useless after P_LVL2 read
+		   because chipsets cannot guarantee that STPCLK# signal
+		   gets asserted in time to freeze execution properly. */
+		unused = inl(acpi_fadt.xpm_tmr_blk.address);
+	}
+}
+
 static void acpi_processor_idle(void)
 {
 	struct acpi_processor *pr = NULL;
@@ -361,11 +378,7 @@
 		/* Get start time (ticks) */
 		t1 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Invoke C2 */
-		inb(cx->address);
-		/* Dummy wait op - must do something useless after P_LVL2 read
-		   because chipsets cannot guarantee that STPCLK# signal
-		   gets asserted in time to freeze execution properly. */
-		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
+		acpi_cstate_enter(cx);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
 
@@ -401,9 +414,7 @@
 		/* Get start time (ticks) */
 		t1 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Invoke C3 */
-		inb(cx->address);
-		/* Dummy wait op (see above) */
-		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
+		acpi_cstate_enter(cx);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
 		if (pr->flags.bm_check) {
@@ -628,20 +639,16 @@
 	return 0;
 }
 
-static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr)
+static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
 {
-
-	/* Zero initialize all the C-states info. */
-	memset(pr->power.states, 0, sizeof(pr->power.states));
-
-	/* set the first C-State to C1 */
-	pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
-
-	/* the C0 state only exists as a filler in our array,
-	 * and all processors need to support C1 */
+	if (!pr->power.states[ACPI_STATE_C1].valid) {
+		/* set the first C-State to C1 */
+		/* all processors need to support C1 */
+		pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
+		pr->power.states[ACPI_STATE_C1].valid = 1;
+	}
+	/* the C0 state only exists as a filler in our array */
 	pr->power.states[ACPI_STATE_C0].valid = 1;
-	pr->power.states[ACPI_STATE_C1].valid = 1;
-
 	return 0;
 }
 
@@ -658,12 +665,7 @@
 	if (nocst)
 		return -ENODEV;
 
-	current_count = 1;
-
-	/* Zero initialize C2 onwards and prepare for fresh CST lookup */
-	for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++)
-		memset(&(pr->power.states[i]), 0, 
-				sizeof(struct acpi_processor_cx));
+	current_count = 0;
 
 	status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
 	if (ACPI_FAILURE(status)) {
@@ -718,22 +720,39 @@
 		    (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
 			continue;
 
-		cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
-		    0 : reg->address;
-
 		/* There should be an easy way to extract an integer... */
 		obj = (union acpi_object *)&(element->package.elements[1]);
 		if (obj->type != ACPI_TYPE_INTEGER)
 			continue;
 
 		cx.type = obj->integer.value;
+		/*
+		 * Some buggy BIOSes won't list C1 in _CST -
+		 * Let acpi_processor_get_power_info_default() handle them later
+		 */
+		if (i == 1 && cx.type != ACPI_STATE_C1)
+			current_count++;
 
-		if ((cx.type != ACPI_STATE_C1) &&
-		    (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
-			continue;
+		cx.address = reg->address;
+		cx.index = current_count + 1;
 
-		if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3))
-			continue;
+		cx.space_id = ACPI_CSTATE_SYSTEMIO;
+		if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
+			if (acpi_processor_ffh_cstate_probe
+					(pr->id, &cx, reg) == 0) {
+				cx.space_id = ACPI_CSTATE_FFH;
+			} else if (cx.type != ACPI_STATE_C1) {
+				/*
+				 * C1 is a special case where FIXED_HARDWARE
+				 * can be handled in non-MWAIT way as well.
+				 * In that case, save this _CST entry info.
+				 * That is, we retain space_id of SYSTEM_IO for
+				 * halt based C1.
+				 * Otherwise, ignore this info and continue.
+				 */
+				continue;
+			}
+		}
 
 		obj = (union acpi_object *)&(element->package.elements[2]);
 		if (obj->type != ACPI_TYPE_INTEGER)
@@ -938,11 +957,17 @@
 	/* NOTE: the idle thread may not be running while calling
 	 * this function */
 
-	/* Adding C1 state */
-	acpi_processor_get_power_info_default_c1(pr);
+	/* Zero initialize all the C-states info. */
+	memset(pr->power.states, 0, sizeof(pr->power.states));
+
 	result = acpi_processor_get_power_info_cst(pr);
 	if (result == -ENODEV)
-		acpi_processor_get_power_info_fadt(pr);
+		result = acpi_processor_get_power_info_fadt(pr);
+
+	if (result)
+		return result;
+
+	acpi_processor_get_power_info_default(pr);
 
 	pr->power.count = acpi_processor_power_verify(pr);
 
@@ -1083,6 +1108,7 @@
 	.release = single_release,
 };
 
+#ifdef CONFIG_SMP
 static void smp_callback(void *v)
 {
 	/* we already woke the CPU up, nothing more to do */
@@ -1104,8 +1130,9 @@
 static struct notifier_block acpi_processor_latency_notifier = {
 	.notifier_call = acpi_processor_latency_notify,
 };
+#endif
 
-int acpi_processor_power_init(struct acpi_processor *pr,
+int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 			      struct acpi_device *device)
 {
 	acpi_status status = 0;
@@ -1121,7 +1148,9 @@
 			       "ACPI: processor limited to max C-state %d\n",
 			       max_cstate);
 		first_run++;
+#ifdef CONFIG_SMP
 		register_latency_notifier(&acpi_processor_latency_notifier);
+#endif
 	}
 
 	if (!pr)
@@ -1193,7 +1222,9 @@
 		 * copies of pm_idle before proceeding.
 		 */
 		cpu_idle_wait();
+#ifdef CONFIG_SMP
 		unregister_latency_notifier(&acpi_processor_latency_notifier);
+#endif
 	}
 
 	return 0;
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 62bef0b..8908a97 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -98,11 +98,11 @@
 static int update_time = UPDATE_TIME;
 static int update_time2 = UPDATE_TIME2;
 
-module_param(capacity_mode, int, CAPACITY_UNIT);
-module_param(update_mode, int, UPDATE_MODE);
-module_param(update_info_mode, int, UPDATE_INFO_MODE);
-module_param(update_time, int, UPDATE_TIME);
-module_param(update_time2, int, UPDATE_TIME2);
+module_param(capacity_mode, int, 0);
+module_param(update_mode, int, 0);
+module_param(update_info_mode, int, 0);
+module_param(update_time, int, 0);
+module_param(update_time2, int, 0);
 
 static int acpi_sbs_add(struct acpi_device *device);
 static int acpi_sbs_remove(struct acpi_device *device, int type);
@@ -1685,10 +1685,16 @@
 
 int acpi_sbs_remove(struct acpi_device *device, int type)
 {
-	struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device);
+	struct acpi_sbs *sbs = NULL;
 	int id;
 
-	if (!device || !sbs) {
+	if (!device) {
+		return -EINVAL;
+	}
+
+	sbs = (struct acpi_sbs *)acpi_driver_data(device);
+
+	if (!sbs) {
 		return -EINVAL;
 	}
 
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 7856db7..11e2d44 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -324,7 +324,7 @@
 
 	if (header->length < sizeof(struct acpi_table_header)) {
 		ACPI_ERROR((AE_INFO,
-			    "Table length (%X) is smaller than minimum (%X)",
+			    "Table length (%X) is smaller than minimum (%zX)",
 			    header->length, sizeof(struct acpi_table_header)));
 
 		return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index 0ad3dbb..86a5fca 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -187,7 +187,7 @@
 
 	if (table_ptr->length < sizeof(struct acpi_table_header)) {
 		ACPI_ERROR((AE_INFO,
-			    "RSDT/XSDT length (%X) is smaller than minimum (%X)",
+			    "RSDT/XSDT length (%X) is smaller than minimum (%zX)",
 			    table_ptr->length,
 			    sizeof(struct acpi_table_header)));
 
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 3f4aa0c..03f6338 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -6,6 +6,7 @@
 
 config ATA
 	tristate "ATA device support"
+	depends on BLOCK
 	depends on !(M32R || M68K) || BROKEN
 	depends on !SUN4 || BROKEN
 	select SCSI
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 54e1f38..cef2e70 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -204,7 +204,7 @@
 static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
-static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t ahci_interrupt (int irq, void *dev_instance);
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
@@ -1041,7 +1041,7 @@
 	/* 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 (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS))
 		return;
 
 	/* ignore interim PIO setup fis interrupts */
@@ -1059,7 +1059,7 @@
 	/* TODO */
 }
 
-static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	struct ahci_host_priv *hpriv;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 5719704..5250187 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -432,9 +432,9 @@
 	.present_shift = 8,
 	.map = {
 		/* PM   PS   SM   SS       MAP */
-		{  P0,  NA,  P1,  NA }, /* 00b (hardwired) */
+		{  P0,  P2,  P1,  P3 }, /* 00b (hardwired when in AHCI) */
 		{  RV,  RV,  RV,  RV },
-		{  RV,  RV,  RV,  RV }, /* 10b (never) */
+		{  IDE,  IDE,  NA,  NA }, /* 10b (IDE mode) */
 		{  RV,  RV,  RV,  RV },
 	},
 };
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index dce6565..83728a9 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -870,7 +870,11 @@
 		 * the PIO timing number for the maximum. Turn it into
 		 * a mask.
 		 */
-		pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+		u8 mode = id[ATA_ID_OLD_PIO_MODES] & 0xFF;
+		if (mode < 5)	/* Valid PIO range */
+                	pio_mask = (2 << mode) - 1;
+		else
+			pio_mask = 1;
 
 		/* But wait.. there's more. Design your standards by
 		 * committee and you too can get a free iordy field to
@@ -4857,7 +4861,6 @@
  *	ata_interrupt - Default ATA host interrupt handler
  *	@irq: irq line (unused)
  *	@dev_instance: pointer to our ata_host information structure
- *	@regs: unused
  *
  *	Default interrupt handler for PCI IDE devices.  Calls
  *	ata_host_intr() for each port that is not disabled.
@@ -4869,7 +4872,7 @@
  *	IRQ_NONE or IRQ_HANDLED.
  */
 
-irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+irqreturn_t ata_interrupt (int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	unsigned int i;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b0d0cc4..7af2a4b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -164,10 +164,10 @@
 {
 	int rc = 0;
 	u8 scsi_cmd[MAX_COMMAND_SIZE];
-	u8 args[4], *argbuf = NULL;
+	u8 args[4], *argbuf = NULL, *sensebuf = NULL;
 	int argsize = 0;
-	struct scsi_sense_hdr sshdr;
 	enum dma_data_direction data_dir;
+	int cmd_result;
 
 	if (arg == NULL)
 		return -EINVAL;
@@ -175,6 +175,10 @@
 	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));
 
 	if (args[3]) {
@@ -191,7 +195,7 @@
 		data_dir = DMA_FROM_DEVICE;
 	} else {
 		scsi_cmd[1]  = (3 << 1); /* Non-data */
-		/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+		scsi_cmd[2]  = 0x20;     /* cc but no off.line or data xfer */
 		data_dir = DMA_NONE;
 	}
 
@@ -210,18 +214,46 @@
 
 	/* Good values for timeout and retries?  Values below
 	   from scsi_ioctl_send_command() for default case... */
-	if (scsi_execute_req(scsidev, scsi_cmd, data_dir, argbuf, argsize,
-			     &sshdr, (10*HZ), 5)) {
+	cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
+	                          sensebuf, (10*HZ), 5, 0);
+
+	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 a few ATA registers (same as drivers/ide) */
+		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) */
+			if (copy_to_user(arg, args, sizeof(args)))
+				rc = -EFAULT;
+		}
+	}
+
+
+	if (cmd_result) {
 		rc = -EIO;
 		goto error;
 	}
 
-	/* Need code to retrieve data from check condition? */
-
 	if ((argbuf)
 	 && copy_to_user(arg + sizeof(args), argbuf, argsize))
 		rc = -EFAULT;
 error:
+	kfree(sensebuf);
 	kfree(argbuf);
 	return rc;
 }
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 06daaa3..7645f2b 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -981,6 +981,15 @@
 		mask = (1 << 2) | (1 << 0);
 		if ((tmp8 & mask) != mask)
 			legacy_mode = (1 << 3);
+#if defined(CONFIG_NO_ATA_LEGACY)
+		/* Some platforms with PCI limits cannot address compat
+		   port space. In that case we punt if their firmware has
+		   left a device in compatibility mode */
+		if (legacy_mode) {
+			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
+			return -EOPNOTSUPP;
+		}
+#endif
 	}
 
 	rc = pci_request_regions(pdev, DRV_NAME);
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 7977f47..2c3cc0c 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -141,7 +141,7 @@
 				memcpy(&pad, buf + buflen - slop, slop);
 				outl(le32_to_cpu(pad), ap->ioaddr.data_addr);
 			} else {
-				pad = cpu_to_le16(inl(ap->ioaddr.data_addr));
+				pad = cpu_to_le32(inl(ap->ioaddr.data_addr));
 				memcpy(buf + buflen - slop, &pad, slop);
 			}
 		}
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 81f3d21..9021e34 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -124,8 +124,7 @@
 
 static int adma_ata_init_one (struct pci_dev *pdev,
 				const struct pci_device_id *ent);
-static irqreturn_t adma_intr (int irq, void *dev_instance,
-				struct pt_regs *regs);
+static irqreturn_t adma_intr (int irq, void *dev_instance);
 static int adma_port_start(struct ata_port *ap);
 static void adma_host_stop(struct ata_host *host);
 static void adma_port_stop(struct ata_port *ap);
@@ -508,7 +507,7 @@
 	return handled;
 }
 
-static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t adma_intr(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	unsigned int handled = 0;
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index e6aa1a8..1b8e0eb 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -348,8 +348,7 @@
 static void mv_qc_prep(struct ata_queued_cmd *qc);
 static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
-static irqreturn_t mv_interrupt(int irq, void *dev_instance,
-				struct pt_regs *regs);
+static irqreturn_t mv_interrupt(int irq, void *dev_instance);
 static void mv_eng_timeout(struct ata_port *ap);
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
@@ -1448,8 +1447,7 @@
  *      This routine holds the host lock while processing pending
  *      interrupts.
  */
-static irqreturn_t mv_interrupt(int irq, void *dev_instance,
-				struct pt_regs *regs)
+static irqreturn_t mv_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	unsigned int hc, handled = 0, n_hcs;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index d09d20a..323b607 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -82,12 +82,9 @@
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static void nv_ck804_host_stop(struct ata_host *host);
-static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
-					struct pt_regs *regs);
-static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
-				    struct pt_regs *regs);
-static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
-				      struct pt_regs *regs);
+static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
+static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
+static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
 static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 
@@ -276,8 +273,7 @@
 MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
-static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
-					struct pt_regs *regs)
+static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	unsigned int i;
@@ -357,8 +353,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
-				    struct pt_regs *regs)
+static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	u8 irq_stat;
@@ -372,8 +367,7 @@
 	return ret;
 }
 
-static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
-				      struct pt_regs *regs)
+static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	u8 irq_stat;
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 15c9437..72eda51 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -93,7 +93,7 @@
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t pdc_interrupt (int irq, void *dev_instance);
 static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
@@ -260,6 +260,7 @@
 #if 0
 	{ PCI_VDEVICE(PROMISE, 0x3570), board_20771 },
 #endif
+	{ PCI_VDEVICE(PROMISE, 0x3577), board_20771 },
 
 	{ }	/* terminate list */
 };
@@ -360,7 +361,7 @@
 static void pdc_pata_cbl_detect(struct ata_port *ap)
 {
 	u8 tmp;
-	void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
 
 	tmp = readb(mmio);
 
@@ -498,7 +499,7 @@
 	readl(mmio + PDC_INT_SEQMASK);
 }
 
-static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	struct ata_port *ap;
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 7f6cc3c..710909d 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -114,7 +114,7 @@
 static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t qs_intr (int irq, void *dev_instance);
 static int qs_port_start(struct ata_port *ap);
 static void qs_host_stop(struct ata_host *host);
 static void qs_port_stop(struct ata_port *ap);
@@ -454,7 +454,7 @@
 	return handled;
 }
 
-static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t qs_intr(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	unsigned int handled = 0;
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 3d9fa1c..ca8d993 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -116,8 +116,7 @@
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
-static irqreturn_t sil_interrupt(int irq, void *dev_instance,
-				 struct pt_regs *regs);
+static irqreturn_t sil_interrupt(int irq, void *dev_instance);
 static void sil_freeze(struct ata_port *ap);
 static void sil_thaw(struct ata_port *ap);
 
@@ -350,7 +349,7 @@
 
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
-	void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
+	void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		writel(val, mmio);
 }
@@ -437,8 +436,7 @@
 	ata_port_freeze(ap);
 }
 
-static irqreturn_t sil_interrupt(int irq, void *dev_instance,
-				 struct pt_regs *regs)
+static irqreturn_t sil_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	void __iomem *mmio_base = host->mmio_base;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index a951f40..169e200 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -330,7 +330,7 @@
 static void sil24_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
 static void sil24_irq_clear(struct ata_port *ap);
-static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance);
 static void sil24_freeze(struct ata_port *ap);
 static void sil24_thaw(struct ata_port *ap);
 static void sil24_error_handler(struct ata_port *ap);
@@ -870,7 +870,7 @@
 			slot_stat, ap->active_tag, ap->sactive);
 }
 
-static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	struct sil24_host_priv *hpriv = host->private_data;
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 84025a2..db32d15 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -177,7 +177,7 @@
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
 	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
@@ -205,7 +205,7 @@
 static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 8c74f2f..ae7992d 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -152,7 +152,7 @@
 
 
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance);
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
@@ -788,7 +788,7 @@
 	readl(mmio + PDC_20621_SEQMASK);
 }
 
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	struct ata_port *ap;
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 273d88f..e654b99 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -203,8 +203,7 @@
  *
  * Read the interrupt register and process for the devices that have them pending.
  */
-static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
-				       struct pt_regs *regs)
+static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
 	unsigned int i;
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index da599e6..9fffa7a 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -861,18 +861,11 @@
 
 /********** interrupt handling **********/
 
-static irqreturn_t interrupt_handler(int irq, void *dev_id,
-					struct pt_regs *pt_regs) {
-  amb_dev * dev = (amb_dev *) dev_id;
-  (void) pt_regs;
+static irqreturn_t interrupt_handler(int irq, void *dev_id) {
+  amb_dev * dev = dev_id;
   
   PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler: %p", dev_id);
   
-  if (!dev_id) {
-    PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq);
-    return IRQ_NONE;
-  }
-  
   {
     u32 interrupt = rd_plain (dev, offsetof(amb_mem, interrupt));
   
@@ -2459,8 +2452,8 @@
 static void __exit amb_module_exit (void)
 {
   PRINTD (DBG_FLOW|DBG_INIT, "cleanup_module");
-  
-  return pci_unregister_driver(&amb_driver);
+
+  pci_unregister_driver(&amb_driver);
 }
 
 module_init(amb_module_init);
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index df359a6..bc1b13c 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1488,7 +1488,7 @@
 }
 
 
-static irqreturn_t eni_int(int irq,void *dev_id,struct pt_regs *regs)
+static irqreturn_t eni_int(int irq,void *dev_id)
 {
 	struct atm_dev *dev;
 	struct eni_dev *eni_dev;
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 5f25e5e..697ad82 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1002,6 +1002,10 @@
 					r = ROUND_UP;
 				}
 				error = make_rate (pcr, r, &tmc0, NULL);
+				if (error) {
+					kfree(tc);
+					return error;
+				}
 			}
 			fs_dprintk (FS_DEBUG_OPEN, "pcr = %d.\n", pcr);
 		}
@@ -1546,7 +1550,7 @@
 
 
 
-static irqreturn_t fs_irq (int irq, void *dev_id,  struct pt_regs * pt_regs) 
+static irqreturn_t fs_irq (int irq, void *dev_id) 
 {
 	int i;
 	u32 status;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 9862213..3a7b21f 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -1328,7 +1328,7 @@
 
 
 static irqreturn_t
-fore200e_interrupt(int irq, void* dev, struct pt_regs* regs)
+fore200e_interrupt(int irq, void* dev)
 {
     struct fore200e* fore200e = FORE200E_DEV((struct atm_dev*)dev);
 
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index b22a914..c7314a7 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -109,7 +109,7 @@
 static void he_close(struct atm_vcc *vcc);
 static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
 static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg);
-static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t he_irq_handler(int irq, void *dev_id);
 static void he_tasklet(unsigned long data);
 static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
 static int he_start(struct atm_dev *dev);
@@ -2216,7 +2216,7 @@
 }
 
 static irqreturn_t
-he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+he_irq_handler(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct he_dev *he_dev = (struct he_dev * )dev_id;
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 209dba1..44268cb 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1382,24 +1382,13 @@
 
 /********** interrupt handler **********/
 
-static irqreturn_t interrupt_handler(int irq, void *dev_id,
-					struct pt_regs *pt_regs) {
+static irqreturn_t interrupt_handler(int irq, void *dev_id) {
   hrz_dev * dev = (hrz_dev *) dev_id;
   u32 int_source;
   unsigned int irq_ok;
-  (void) pt_regs;
   
   PRINTD (DBG_FLOW, "interrupt_handler: %p", dev_id);
   
-  if (!dev_id) {
-    PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq);
-    return IRQ_NONE;
-  }
-  if (irq != dev->irq) {
-    PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq);
-    return IRQ_NONE;
-  }
-  
   // definitely for us
   irq_ok = 0;
   while ((int_source = rd_regl (dev, INT_SOURCE_REG_OFF)
@@ -2943,8 +2932,8 @@
 
 static void __exit hrz_module_exit (void) {
   PRINTD (DBG_FLOW, "cleanup_module");
-  
-  return pci_unregister_driver(&hrz_driver);
+
+  pci_unregister_driver(&hrz_driver);
 }
 
 module_init(hrz_module_init);
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 7487f0a..87b17c3 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -2774,7 +2774,7 @@
 }
 
 static irqreturn_t
-idt77252_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+idt77252_interrupt(int irq, void *dev_id)
 {
 	struct idt77252_dev *card = dev_id;
 	u32 stat;
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index f20b0b2..9ed1c60 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -2195,7 +2195,7 @@
 	return -ENOMEM;
 }   
    
-static irqreturn_t ia_int(int irq, void *dev_id, struct pt_regs *regs)  
+static irqreturn_t ia_int(int irq, void *dev_id)  
 {  
    struct atm_dev *dev;  
    IADEV *iadev;  
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index b9568e1..2678255 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1890,13 +1890,11 @@
 		reg_write(lanai, ack, IntAck_Reg);
 }
 
-static irqreturn_t lanai_int(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t lanai_int(int irq, void *devid)
 {
-	struct lanai_dev *lanai = (struct lanai_dev *) devid;
+	struct lanai_dev *lanai = devid;
 	u32 reason;
 
-	(void) irq; (void) regs;	/* unused variables */
-
 #ifdef USE_POWERDOWN
 	/*
 	 * If we're powered down we shouldn't be generating any interrupts -
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index b803689..bd09045 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -214,7 +214,7 @@
 static scq_info *get_scq(int size, u32 scd);
 static void free_scq(scq_info *scq, struct atm_vcc *vcc);
 static void push_rxbufs(ns_dev *, struct sk_buff *);
-static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ns_irq_handler(int irq, void *dev_id);
 static int ns_open(struct atm_vcc *vcc);
 static void ns_close(struct atm_vcc *vcc);
 static void fill_tst(ns_dev *card, int n, vc_map *vc);
@@ -1194,7 +1194,7 @@
 
 
 
-static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ns_irq_handler(int irq, void *dev_id)
 {
    u32 stat_r;
    ns_dev *card;
@@ -2759,7 +2759,7 @@
 {
    ns_dev *card;
    pool_levels pl;
-   int btype;
+   long btype;
    unsigned long flags;
 
    card = dev->dev_data;
@@ -2859,7 +2859,7 @@
       case NS_ADJBUFLEV:
          if (!capable(CAP_NET_ADMIN))
 	    return -EPERM;
-         btype = (int) arg;	/* an int is the same size as a pointer */
+         btype = (long) arg;	/* a long is the same size as a pointer or bigger */
          switch (btype)
 	 {
 	    case NS_BUFTYPE_SMALL:
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 083c5d3..7df0f37 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -1012,7 +1012,7 @@
 /*------------------------------- interrupts --------------------------------*/
 
 
-static irqreturn_t zatm_int(int irq,void *dev_id,struct pt_regs *regs)
+static irqreturn_t zatm_int(int irq,void *dev_id)
 {
 	struct atm_dev *dev;
 	struct zatm_dev *zatm_dev;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 12173d1..7d8a7ce 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -372,19 +372,30 @@
 		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out;
+			goto out_put;
 		error = sysfs_create_link(&bus->devices.kobj,
 						&dev->kobj, dev->bus_id);
 		if (error)
-			goto out;
+			goto out_id;
 		error = sysfs_create_link(&dev->kobj,
 				&dev->bus->subsys.kset.kobj, "subsystem");
 		if (error)
-			goto out;
+			goto out_subsys;
 		error = sysfs_create_link(&dev->kobj,
 				&dev->bus->subsys.kset.kobj, "bus");
+		if (error)
+			goto out_deprecated;
 	}
-out:
+	return 0;
+
+out_deprecated:
+	sysfs_remove_link(&dev->kobj, "subsystem");
+out_subsys:
+	sysfs_remove_link(&bus->devices.kobj, dev->bus_id);
+out_id:
+	device_remove_attrs(bus, dev);
+out_put:
+	put_bus(dev->bus);
 	return error;
 }
 
@@ -428,8 +439,10 @@
 		sysfs_remove_link(&dev->kobj, "bus");
 		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
 		device_remove_attrs(dev->bus, dev);
-		dev->is_registered = 0;
-		klist_del(&dev->knode_bus);
+		if (dev->is_registered) {
+			dev->is_registered = 0;
+			klist_del(&dev->knode_bus);
+		}
 		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
 		device_release_driver(dev);
 		put_bus(dev->bus);
@@ -505,34 +518,36 @@
 	struct bus_type * bus = get_bus(drv->bus);
 	int error = 0;
 
-	if (bus) {
-		pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
-		error = kobject_set_name(&drv->kobj, "%s", drv->name);
-		if (error)
-			goto out_put_bus;
-		drv->kobj.kset = &bus->drivers;
-		if ((error = kobject_register(&drv->kobj)))
-			goto out_put_bus;
+	if (!bus)
+		return 0;
 
-		error = driver_attach(drv);
-		if (error)
-			goto out_unregister;
-		klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
-		module_add_driver(drv->owner, drv);
+	pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
+	error = kobject_set_name(&drv->kobj, "%s", drv->name);
+	if (error)
+		goto out_put_bus;
+	drv->kobj.kset = &bus->drivers;
+	if ((error = kobject_register(&drv->kobj)))
+		goto out_put_bus;
 
-		error = driver_add_attrs(bus, drv);
-		if (error) {
-			/* How the hell do we get out of this pickle? Give up */
-			printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
-				__FUNCTION__, drv->name);
-		}
-		error = add_bind_files(drv);
-		if (error) {
-			/* Ditto */
-			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
-				__FUNCTION__, drv->name);
-		}
+	error = driver_attach(drv);
+	if (error)
+		goto out_unregister;
+	klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
+	module_add_driver(drv->owner, drv);
+
+	error = driver_add_attrs(bus, drv);
+	if (error) {
+		/* How the hell do we get out of this pickle? Give up */
+		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
+			__FUNCTION__, drv->name);
 	}
+	error = add_bind_files(drv);
+	if (error) {
+		/* Ditto */
+		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+			__FUNCTION__, drv->name);
+	}
+
 	return error;
 out_unregister:
 	kobject_unregister(&drv->kobj);
@@ -552,16 +567,17 @@
 
 void bus_remove_driver(struct device_driver * drv)
 {
-	if (drv->bus) {
-		remove_bind_files(drv);
-		driver_remove_attrs(drv->bus, drv);
-		klist_remove(&drv->knode_bus);
-		pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
-		driver_detach(drv);
-		module_remove_driver(drv);
-		kobject_unregister(&drv->kobj);
-		put_bus(drv->bus);
-	}
+	if (!drv->bus)
+		return;
+
+	remove_bind_files(drv);
+	driver_remove_attrs(drv->bus, drv);
+	klist_remove(&drv->knode_bus);
+	pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
+	driver_detach(drv);
+	module_remove_driver(drv);
+	kobject_unregister(&drv->kobj);
+	put_bus(drv->bus);
 }
 
 
@@ -732,11 +748,15 @@
 
 	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
 	klist_init(&bus->klist_drivers, NULL, NULL);
-	bus_add_attrs(bus);
+	retval = bus_add_attrs(bus);
+	if (retval)
+		goto bus_attrs_fail;
 
 	pr_debug("bus type '%s' registered\n", bus->name);
 	return 0;
 
+bus_attrs_fail:
+	kset_unregister(&bus->drivers);
 bus_drivers_fail:
 	kset_unregister(&bus->devices);
 bus_devices_fail:
diff --git a/drivers/base/class.c b/drivers/base/class.c
index b32b77f..0ff267a 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -562,7 +562,10 @@
 		goto out2;
 
 	/* add the needed attributes to this device */
-	sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem");
+	error = sysfs_create_link(&class_dev->kobj,
+				  &parent_class->subsys.kset.kobj, "subsystem");
+	if (error)
+		goto out3;
 	class_dev->uevent_attr.attr.name = "uevent";
 	class_dev->uevent_attr.attr.mode = S_IWUSR;
 	class_dev->uevent_attr.attr.owner = parent_class->owner;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b224bb4..68ad11a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -44,7 +44,7 @@
 	return dev->driver ? dev->driver->name :
 			(dev->bus ? dev->bus->name : "");
 }
-EXPORT_SYMBOL_GPL(dev_driver_string);
+EXPORT_SYMBOL(dev_driver_string);
 
 #define to_dev(obj) container_of(obj, struct device, kobj)
 #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
@@ -433,14 +433,16 @@
 	if (dev->driver)
 		dev->uevent_attr.attr.owner = dev->driver->owner;
 	dev->uevent_attr.store = store_uevent;
-	device_create_file(dev, &dev->uevent_attr);
+	error = device_create_file(dev, &dev->uevent_attr);
+	if (error)
+		goto attrError;
 
 	if (MAJOR(dev->devt)) {
 		struct device_attribute *attr;
 		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
 		if (!attr) {
 			error = -ENOMEM;
-			goto PMError;
+			goto ueventattrError;
 		}
 		attr->attr.name = "dev";
 		attr->attr.mode = S_IRUGO;
@@ -450,7 +452,7 @@
 		error = device_create_file(dev, attr);
 		if (error) {
 			kfree(attr);
-			goto attrError;
+			goto ueventattrError;
 		}
 
 		dev->devt_attr = attr;
@@ -477,7 +479,8 @@
 	if ((error = bus_add_device(dev)))
 		goto BusError;
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
-	bus_attach_device(dev);
+	if ((error = bus_attach_device(dev)))
+		goto AttachError;
 	if (parent)
 		klist_add_tail(&dev->knode_parent, &parent->klist_children);
 
@@ -496,6 +499,8 @@
  	kfree(class_name);
 	put_device(dev);
 	return error;
+ AttachError:
+	bus_remove_device(dev);
  BusError:
 	device_pm_remove(dev);
  PMError:
@@ -507,6 +512,8 @@
 		device_remove_file(dev, dev->devt_attr);
 		kfree(dev->devt_attr);
 	}
+ ueventattrError:
+	device_remove_file(dev, &dev->uevent_attr);
  attrError:
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 	kobject_del(&dev->kobj);
@@ -805,8 +812,10 @@
 
 	if (dev->class) {
 		old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
-		if (!old_symlink_name)
-			return -ENOMEM;
+		if (!old_symlink_name) {
+			error = -ENOMEM;
+			goto out_free_old_class;
+		}
 		strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
 	}
 
@@ -830,9 +839,10 @@
 	}
 	put_device(dev);
 
-	kfree(old_class_name);
 	kfree(new_class_name);
 	kfree(old_symlink_name);
+ out_free_old_class:
+	kfree(old_class_name);
 
 	return error;
 }
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index b5f43c3..db01b95 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -171,6 +171,8 @@
 		 drv->bus->name, dev->bus_id, drv->name);
 
 	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 	data->drv = drv;
 	data->dev = dev;
 
@@ -178,7 +180,7 @@
 		probe_task = kthread_run(really_probe, data,
 					 "probe-%s", dev->bus_id);
 		if (IS_ERR(probe_task))
-			ret = PTR_ERR(probe_task);
+			ret = really_probe(data);
 	} else
 		ret = really_probe(data);
 
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 33c5cce..b2efbd4 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -141,11 +141,20 @@
 	init_waitqueue_head (&retval->waitq);
 
 	if (dev) {
+		int ret;
+
 		down (&pools_lock);
 		if (list_empty (&dev->dma_pools))
-			device_create_file (dev, &dev_attr_pools);
+			ret = device_create_file (dev, &dev_attr_pools);
+		else
+			ret = 0;
 		/* note:  not currently insisting "name" be unique */
-		list_add (&retval->pools, &dev->dma_pools);
+		if (!ret)
+			list_add (&retval->pools, &dev->dma_pools);
+		else {
+			kfree(retval);
+			retval = NULL;
+		}
 		up (&pools_lock);
 	} else
 		INIT_LIST_HEAD (&retval->pools);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 3ef9d51..28dccb7 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -97,8 +97,7 @@
 /* Add/Remove cpu_topology interface for CPU device */
 static int __cpuinit topology_add_dev(struct sys_device * sys_dev)
 {
-	sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
-	return 0;
+	return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
 }
 
 static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index b3f639f..742d074 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -2698,8 +2698,7 @@
 {
   struct DAC960_privdata *privdata =
 	  	(struct DAC960_privdata *)entry->driver_data;
-  irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *) =
-	  	privdata->InterruptHandler;
+  irq_handler_t InterruptHandler = privdata->InterruptHandler;
   unsigned int MemoryWindowSize = privdata->MemoryWindowSize;
   DAC960_Controller_T *Controller = NULL;
   unsigned char DeviceFunction = PCI_Device->devfn;
@@ -5253,10 +5252,9 @@
 */
 
 static irqreturn_t DAC960_GEM_InterruptHandler(int IRQ_Channel,
-				       void *DeviceIdentifier,
-				       struct pt_regs *InterruptRegisters)
+				       void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
@@ -5295,10 +5293,9 @@
 */
 
 static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
-				       void *DeviceIdentifier,
-				       struct pt_regs *InterruptRegisters)
+				       void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
@@ -5338,10 +5335,9 @@
 */
 
 static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
-				       void *DeviceIdentifier,
-				       struct pt_regs *InterruptRegisters)
+				       void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
@@ -5381,10 +5377,9 @@
 */
 
 static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
-				       void *DeviceIdentifier,
-				       struct pt_regs *InterruptRegisters)
+				       void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
@@ -5420,10 +5415,9 @@
 */
 
 static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
-				       void *DeviceIdentifier,
-				       struct pt_regs *InterruptRegisters)
+				       void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
@@ -5459,10 +5453,9 @@
 */
 
 static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
-				       void *DeviceIdentifier,
-				       struct pt_regs *InterruptRegisters)
+				       void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
@@ -5498,10 +5491,9 @@
 */
 
 static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel,
-				      void *DeviceIdentifier,
-				      struct pt_regs *InterruptRegisters)
+				      void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
   void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index f9217c3..6148073 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -2175,7 +2175,7 @@
 struct DAC960_privdata {
 	DAC960_HardwareType_T	HardwareType;
 	DAC960_FirmwareType_T	FirmwareType;
-	irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *);
+	irq_handler_t		InterruptHandler;
 	unsigned int		MemoryWindowSize;
 };
 
@@ -4379,8 +4379,8 @@
 static inline void DAC960_P_To_PD_TranslateDeviceState(void *DeviceState)
 {
   memcpy(DeviceState + 2, DeviceState + 3, 1);
-  memcpy(DeviceState + 4, DeviceState + 5, 2);
-  memcpy(DeviceState + 6, DeviceState + 8, 4);
+  memmove(DeviceState + 4, DeviceState + 5, 2);
+  memmove(DeviceState + 6, DeviceState + 8, 4);
 }
 
 static inline
@@ -4412,12 +4412,12 @@
 static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *);
 static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); 
 static void DAC960_RequestFunction(struct request_queue *);
-static irqreturn_t DAC960_BA_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_LP_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_LA_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_PG_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_PD_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_P_InterruptHandler(int, void *, struct pt_regs *);
+static irqreturn_t DAC960_BA_InterruptHandler(int, void *);
+static irqreturn_t DAC960_LP_InterruptHandler(int, void *);
+static irqreturn_t DAC960_LA_InterruptHandler(int, void *);
+static irqreturn_t DAC960_PG_InterruptHandler(int, void *);
+static irqreturn_t DAC960_PD_InterruptHandler(int, void *);
+static irqreturn_t DAC960_P_InterruptHandler(int, void *);
 static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *);
 static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *);
 static void DAC960_MonitoringTimerFunction(unsigned long);
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 0b80fbb..706cdc6 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -346,7 +346,7 @@
                         rwflag, int enable);
 static int acsi_reqsense( char *buffer, int targ, int lun);
 static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data, struct pt_regs *fp);
+static irqreturn_t acsi_interrupt (int irq, void *data);
 static void unexpected_acsi_interrupt( void );
 static void bad_rw_intr( void );
 static void read_intr( void );
@@ -726,7 +726,7 @@
  *
  *******************************************************************/
 
-static irqreturn_t acsi_interrupt(int irq, void *data, struct pt_regs *fp )
+static irqreturn_t acsi_interrupt(int irq, void *data )
 
 {	void (*acsi_irq_handler)(void) = do_acsi;
 
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 4030a8f..8e41c87 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -246,7 +246,7 @@
 static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
                          *ppos );
 static void start_print( int device );
-static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp);
+static irqreturn_t slm_interrupt(int irc, void *data);
 static void slm_test_ready( unsigned long dummy );
 static void set_dma_addr( unsigned long paddr );
 static unsigned long get_dma_addr( void );
@@ -452,7 +452,7 @@
 
 /* Only called when an error happened or at the end of a page */
 
-static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp)
+static irqreturn_t slm_interrupt(int irc, void *data)
 
 {	unsigned long	addr;
 	int				stat;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 2641597..5d65621 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -209,7 +209,7 @@
 
 /* Milliseconds timer */
 
-static irqreturn_t ms_isr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t ms_isr(int irq, void *dummy)
 {
 	ms_busy = -1;
 	wake_up(&ms_wait);
@@ -560,7 +560,7 @@
 	return (id);
 }
 
-static irqreturn_t fd_block_done(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t fd_block_done(int irq, void *dummy)
 {
 	if (block_flag)
 		custom.dsklen = 0x4000;
@@ -1709,10 +1709,13 @@
 	return get_disk(unit[drive].gendisk);
 }
 
-int __init amiga_floppy_init(void)
+static int __init amiga_floppy_init(void)
 {
 	int i, ret;
 
+	if (!MACH_IS_AMIGA)
+		return -ENXIO;
+
 	if (!AMIGAHW_PRESENT(AMI_FLOPPY))
 		return -ENXIO;
 
@@ -1809,15 +1812,9 @@
 	return ret;
 }
 
+module_init(amiga_floppy_init);
 #ifdef MODULE
 
-int init_module(void)
-{
-	if (!MACH_IS_AMIGA)
-		return -ENXIO;
-	return amiga_floppy_init();
-}
-
 #if 0 /* not safe to unload */
 void cleanup_module(void)
 {
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 6eebcb7..6d11122 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "22"
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
+#define VERSION "32"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -65,7 +65,7 @@
 struct aoe_cfghdr {
 	__be16 bufcnt;
 	__be16 fwver;
-	unsigned char res;
+	unsigned char scnt;
 	unsigned char aoeccmd;
 	unsigned char cslen[2];
 };
@@ -78,12 +78,14 @@
 	DEVFL_GDALLOC = (1<<4),	/* need to alloc gendisk */
 	DEVFL_PAUSE = (1<<5),
 	DEVFL_NEWSIZE = (1<<6),	/* need to update dev size in block layer */
+	DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */
+	DEVFL_KICKME = (1<<8),
 
 	BUFFL_FAIL = 1,
 };
 
 enum {
-	MAXATADATA = 1024,
+	DEFAULTBCNT = 2 * 512,	/* 2 sectors */
 	NPERSHELF = 16,		/* number of slots per shelf address */
 	FREETAG = -1,
 	MIN_BUFS = 8,
@@ -107,11 +109,9 @@
 	ulong waited;
 	struct buf *buf;
 	char *bufaddr;
-	int writedatalen;
-	int ndata;
-
-	/* largest possible */
-	unsigned char data[sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr)];
+	ulong bcnt;
+	sector_t lba;
+	struct sk_buff *skb;
 };
 
 struct aoedev {
@@ -121,9 +121,12 @@
 	ulong sysminor;
 	ulong aoemajor;
 	ulong aoeminor;
-	ulong nopen;		/* (bd_openers isn't available without sleeping) */
-	ulong rttavg;		/* round trip average of requests/responses */
+	u16 nopen;		/* (bd_openers isn't available without sleeping) */
+	u16 lasttag;		/* last tag sent */
+	u16 rttavg;		/* round trip average of requests/responses */
+	u16 mintimer;
 	u16 fw_ver;		/* version of blade's firmware */
+	u16 maxbcnt;
 	struct work_struct work;/* disk create work struct */
 	struct gendisk *gd;
 	request_queue_t blkq;
@@ -137,8 +140,8 @@
 	mempool_t *bufpool;	/* for deadlock-free Buf allocation */
 	struct list_head bufq;	/* queue of bios to work on */
 	struct buf *inprocess;	/* the one we're currently working on */
-	ulong lasttag;		/* last tag sent */
-	ulong nframes;		/* number of frames below */
+	ushort lostjumbo;
+	ushort nframes;		/* number of frames below */
 	struct frame *frames;
 };
 
@@ -157,6 +160,7 @@
 void aoecmd_ata_rsp(struct sk_buff *);
 void aoecmd_cfg_rsp(struct sk_buff *);
 void aoecmd_sleepwork(void *vp);
+struct sk_buff *new_skb(ulong);
 
 int aoedev_init(void);
 void aoedev_exit(void);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 393b86a..d433f27 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoeblk.c
  * block device routines
@@ -14,7 +14,6 @@
 
 static kmem_cache_t *buf_pool_cache;
 
-/* add attributes for our block devices in sysfs */
 static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
 {
 	struct aoedev *d = disk->private_data;
@@ -64,21 +63,26 @@
 	.show = aoedisk_show_fwver
 };
 
-static void
+static struct attribute *aoe_attrs[] = {
+	&disk_attr_state.attr,
+	&disk_attr_mac.attr,
+	&disk_attr_netif.attr,
+	&disk_attr_fwver.attr,
+};
+
+static const struct attribute_group attr_group = {
+	.attrs = aoe_attrs,
+};
+
+static int
 aoedisk_add_sysfs(struct aoedev *d)
 {
-	sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr);
-	sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr);
-	sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr);
-	sysfs_create_file(&d->gd->kobj, &disk_attr_fwver.attr);
+	return sysfs_create_group(&d->gd->kobj, &attr_group);
 }
 void
 aoedisk_rm_sysfs(struct aoedev *d)
 {
-	sysfs_remove_link(&d->gd->kobj, "state");
-	sysfs_remove_link(&d->gd->kobj, "mac");
-	sysfs_remove_link(&d->gd->kobj, "netif");
-	sysfs_remove_link(&d->gd->kobj, "firmware-version");
+	sysfs_remove_group(&d->gd->kobj, &attr_group);
 }
 
 static int
@@ -132,8 +136,7 @@
 	d = bio->bi_bdev->bd_disk->private_data;
 	buf = mempool_alloc(d->bufpool, GFP_NOIO);
 	if (buf == NULL) {
-		printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation "
-			"failure\n");
+		printk(KERN_INFO "aoe: buf allocation failure\n");
 		bio_endio(bio, bio->bi_size, -ENOMEM);
 		return 0;
 	}
@@ -143,14 +146,15 @@
 	buf->bio = bio;
 	buf->resid = bio->bi_size;
 	buf->sector = bio->bi_sector;
-	buf->bv = buf->bio->bi_io_vec;
+	buf->bv = &bio->bi_io_vec[bio->bi_idx];
+	WARN_ON(buf->bv->bv_len == 0);
 	buf->bv_resid = buf->bv->bv_len;
 	buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
 
 	spin_lock_irqsave(&d->lock, flags);
 
 	if ((d->flags & DEVFL_UP) == 0) {
-		printk(KERN_INFO "aoe: aoeblk_make_request: device %ld.%ld is not up\n",
+		printk(KERN_INFO "aoe: device %ld.%ld is not up\n",
 			d->aoemajor, d->aoeminor);
 		spin_unlock_irqrestore(&d->lock, flags);
 		mempool_free(buf, d->bufpool);
@@ -176,7 +180,7 @@
 	struct aoedev *d = bdev->bd_disk->private_data;
 
 	if ((d->flags & DEVFL_UP) == 0) {
-		printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
+		printk(KERN_ERR "aoe: disk not up\n");
 		return -ENODEV;
 	}
 
@@ -203,8 +207,8 @@
 
 	gd = alloc_disk(AOE_PARTITIONS);
 	if (gd == NULL) {
-		printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk "
-			"structure for %ld.%ld\n", d->aoemajor, d->aoeminor);
+		printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n",
+			d->aoemajor, d->aoeminor);
 		spin_lock_irqsave(&d->lock, flags);
 		d->flags &= ~DEVFL_GDALLOC;
 		spin_unlock_irqrestore(&d->lock, flags);
@@ -213,8 +217,8 @@
 
 	d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache);
 	if (d->bufpool == NULL) {
-		printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool "
-			"for %ld.%ld\n", d->aoemajor, d->aoeminor);
+		printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n",
+			d->aoemajor, d->aoeminor);
 		put_disk(gd);
 		spin_lock_irqsave(&d->lock, flags);
 		d->flags &= ~DEVFL_GDALLOC;
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 1bc1cf9..e22b4c9 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoechr.c
  * AoE character device driver
@@ -15,7 +15,6 @@
 	MINOR_INTERFACES,
 	MINOR_REVALIDATE,
 	MSGSZ = 2048,
-	NARGS = 10,
 	NMSG = 100,		/* message backlog to retain */
 };
 
@@ -56,9 +55,8 @@
 interfaces(const char __user *str, size_t size)
 {
 	if (set_aoe_iflist(str, size)) {
-		printk(KERN_CRIT
-		       "%s: could not set interface list: %s\n",
-		       __FUNCTION__, "too many interfaces");
+		printk(KERN_ERR
+			"aoe: could not set interface list: too many interfaces\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -81,8 +79,7 @@
 	/* should be e%d.%d format */
 	n = sscanf(buf, "e%d.%d", &major, &minor);
 	if (n != 2) {
-		printk(KERN_ERR "aoe: %s: invalid device specification\n",
-			__FUNCTION__);
+		printk(KERN_ERR "aoe: invalid device specification\n");
 		return -EINVAL;
 	}
 	d = aoedev_by_aoeaddr(major, minor);
@@ -90,6 +87,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&d->lock, flags);
+	d->flags &= ~DEVFL_MAXBCNT;
 	d->flags |= DEVFL_PAUSE;
 	spin_unlock_irqrestore(&d->lock, flags);
 	aoecmd_cfg(major, minor);
@@ -116,7 +114,7 @@
 
 	mp = kmalloc(n, GFP_ATOMIC);
 	if (mp == NULL) {
-		printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n);
+		printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n);
 		goto bail;
 	}
 
@@ -141,7 +139,7 @@
 
 	switch ((unsigned long) filp->private_data) {
 	default:
-		printk(KERN_INFO "aoe: aoechr_write: can't write to that file.\n");
+		printk(KERN_INFO "aoe: can't write to that file.\n");
 		break;
 	case MINOR_DISCOVER:
 		ret = discover();
@@ -250,7 +248,7 @@
 
 	n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
 	if (n < 0) { 
-		printk(KERN_ERR "aoe: aoechr_init: can't register char device\n");
+		printk(KERN_ERR "aoe: can't register char device\n");
 		return n;
 	}
 	sema_init(&emsgs_sema, 0);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 39da28d..8a13b1a 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoecmd.c
  * Filesystem request handling methods
@@ -15,17 +15,19 @@
 #define TIMERTICK (HZ / 10)
 #define MINTIMER (2 * TIMERTICK)
 #define MAXTIMER (HZ << 1)
-#define MAXWAIT (60 * 3)	/* After MAXWAIT seconds, give up and fail dev */
 
-static struct sk_buff *
-new_skb(struct net_device *if_dev, ulong len)
+static int aoe_deadsecs = 60 * 3;
+module_param(aoe_deadsecs, int, 0644);
+MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
+
+struct sk_buff *
+new_skb(ulong len)
 {
 	struct sk_buff *skb;
 
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (skb) {
 		skb->nh.raw = skb->mac.raw = skb->data;
-		skb->dev = if_dev;
 		skb->protocol = __constant_htons(ETH_P_AOE);
 		skb->priority = 0;
 		skb_put(skb, len);
@@ -40,29 +42,6 @@
 	return skb;
 }
 
-static struct sk_buff *
-skb_prepare(struct aoedev *d, struct frame *f)
-{
-	struct sk_buff *skb;
-	char *p;
-
-	skb = new_skb(d->ifp, f->ndata + f->writedatalen);
-	if (!skb) {
-		printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n");
-		return NULL;
-	}
-
-	p = skb->mac.raw;
-	memcpy(p, f->data, f->ndata);
-
-	if (f->writedatalen) {
-		p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
-		memcpy(p, f->bufaddr, f->writedatalen);
-	}
-
-	return skb;
-}
-
 static struct frame *
 getframe(struct aoedev *d, int tag)
 {
@@ -107,6 +86,17 @@
 	return host_tag;
 }
 
+static inline void
+put_lba(struct aoe_atahdr *ah, sector_t lba)
+{
+	ah->lba0 = lba;
+	ah->lba1 = lba >>= 8;
+	ah->lba2 = lba >>= 8;
+	ah->lba3 = lba >>= 8;
+	ah->lba4 = lba >>= 8;
+	ah->lba5 = lba >>= 8;
+}
+
 static void
 aoecmd_ata_rw(struct aoedev *d, struct frame *f)
 {
@@ -125,29 +115,27 @@
 
 	sector = buf->sector;
 	bcnt = buf->bv_resid;
-	if (bcnt > MAXATADATA)
-		bcnt = MAXATADATA;
+	if (bcnt > d->maxbcnt)
+		bcnt = d->maxbcnt;
 
 	/* initialize the headers & frame */
-	h = (struct aoe_hdr *) f->data;
+	skb = f->skb;
+	h = (struct aoe_hdr *) skb->mac.raw;
 	ah = (struct aoe_atahdr *) (h+1);
-	f->ndata = sizeof *h + sizeof *ah;
-	memset(h, 0, f->ndata);
+	skb->len = sizeof *h + sizeof *ah;
+	memset(h, 0, ETH_ZLEN);
 	f->tag = aoehdr_atainit(d, h);
 	f->waited = 0;
 	f->buf = buf;
 	f->bufaddr = buf->bufaddr;
+	f->bcnt = bcnt;
+	f->lba = sector;
 
 	/* set up ata header */
 	ah->scnt = bcnt >> 9;
-	ah->lba0 = sector;
-	ah->lba1 = sector >>= 8;
-	ah->lba2 = sector >>= 8;
-	ah->lba3 = sector >>= 8;
+	put_lba(ah, sector);
 	if (d->flags & DEVFL_EXT) {
 		ah->aflags |= AOEAFL_EXT;
-		ah->lba4 = sector >>= 8;
-		ah->lba5 = sector >>= 8;
 	} else {
 		extbit = 0;
 		ah->lba3 &= 0x0f;
@@ -155,11 +143,14 @@
 	}
 
 	if (bio_data_dir(buf->bio) == WRITE) {
+		skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
+			offset_in_page(f->bufaddr), bcnt);
 		ah->aflags |= AOEAFL_WRITE;
-		f->writedatalen = bcnt;
+		skb->len += bcnt;
+		skb->data_len = bcnt;
 	} else {
+		skb->len = ETH_ZLEN;
 		writebit = 0;
-		f->writedatalen = 0;
 	}
 
 	ah->cmdstat = WIN_READ | writebit | extbit;
@@ -168,26 +159,27 @@
 	buf->nframesout += 1;
 	buf->bufaddr += bcnt;
 	buf->bv_resid -= bcnt;
-/* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */
+/* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */
 	buf->resid -= bcnt;
 	buf->sector += bcnt >> 9;
 	if (buf->resid == 0) {
 		d->inprocess = NULL;
 	} else if (buf->bv_resid == 0) {
 		buf->bv++;
+		WARN_ON(buf->bv->bv_len == 0);
 		buf->bv_resid = buf->bv->bv_len;
 		buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
 	}
 
-	skb = skb_prepare(d, f);
-	if (skb) {
-		skb->next = NULL;
-		if (d->sendq_hd)
-			d->sendq_tl->next = skb;
-		else
-			d->sendq_hd = skb;
-		d->sendq_tl = skb;
-	}
+	skb->dev = d->ifp;
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (skb == NULL)
+		return;
+	if (d->sendq_hd)
+		d->sendq_tl->next = skb;
+	else
+		d->sendq_hd = skb;
+	d->sendq_tl = skb;
 }
 
 /* some callers cannot sleep, and they can call this function,
@@ -209,11 +201,12 @@
 		if (!is_aoe_netif(ifp))
 			continue;
 
-		skb = new_skb(ifp, sizeof *h + sizeof *ch);
+		skb = new_skb(sizeof *h + sizeof *ch);
 		if (skb == NULL) {
-			printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
+			printk(KERN_INFO "aoe: skb alloc failure\n");
 			continue;
 		}
+		skb->dev = ifp;
 		if (sl_tail == NULL)
 			sl_tail = skb;
 		h = (struct aoe_hdr *) skb->mac.raw;
@@ -237,6 +230,29 @@
 	return sl;
 }
 
+static struct frame *
+freeframe(struct aoedev *d)
+{
+	struct frame *f, *e;
+	int n = 0;
+
+	f = d->frames;
+	e = f + d->nframes;
+	for (; f<e; f++) {
+		if (f->tag != FREETAG)
+			continue;
+		if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) {
+			skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
+			return f;
+		}
+		n++;
+	}
+	if (n == d->nframes)	/* wait for network layer */
+		d->flags |= DEVFL_KICKME;
+
+	return NULL;
+}
+
 /* enters with d->lock held */
 void
 aoecmd_work(struct aoedev *d)
@@ -252,7 +268,7 @@
 	}
 
 loop:
-	f = getframe(d, FREETAG);
+	f = freeframe(d);
 	if (f == NULL)
 		return;
 	if (d->inprocess == NULL) {
@@ -260,7 +276,7 @@
 			return;
 		buf = container_of(d->bufq.next, struct buf, bufs);
 		list_del(d->bufq.next);
-/*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */
+/*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */
 		d->inprocess = buf;
 	}
 	aoecmd_ata_rw(d, f);
@@ -272,6 +288,7 @@
 {
 	struct sk_buff *skb;
 	struct aoe_hdr *h;
+	struct aoe_atahdr *ah;
 	char buf[128];
 	u32 n;
 
@@ -283,21 +300,41 @@
 		d->aoemajor, d->aoeminor, f->tag, jiffies, n);
 	aoechr_error(buf);
 
-	h = (struct aoe_hdr *) f->data;
+	skb = f->skb;
+	h = (struct aoe_hdr *) skb->mac.raw;
+	ah = (struct aoe_atahdr *) (h+1);
 	f->tag = n;
 	h->tag = cpu_to_be32(n);
 	memcpy(h->dst, d->addr, sizeof h->dst);
 	memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
 
-	skb = skb_prepare(d, f);
-	if (skb) {
-		skb->next = NULL;
-		if (d->sendq_hd)
-			d->sendq_tl->next = skb;
-		else
-			d->sendq_hd = skb;
-		d->sendq_tl = skb;
+	n = DEFAULTBCNT / 512;
+	if (ah->scnt > n) {
+		ah->scnt = n;
+		if (ah->aflags & AOEAFL_WRITE) {
+			skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
+				offset_in_page(f->bufaddr), DEFAULTBCNT);
+			skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT;
+			skb->data_len = DEFAULTBCNT;
+		}
+		if (++d->lostjumbo > (d->nframes << 1))
+		if (d->maxbcnt != DEFAULTBCNT) {
+			printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n",
+				d->aoemajor, d->aoeminor, d->ifp->name);
+			d->maxbcnt = DEFAULTBCNT;
+			d->flags |= DEVFL_MAXBCNT;
+		}
 	}
+
+	skb->dev = d->ifp;
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (skb == NULL)
+		return;
+	if (d->sendq_hd)
+		d->sendq_tl->next = skb;
+	else
+		d->sendq_hd = skb;
+	d->sendq_tl = skb;
 }
 
 static int
@@ -340,13 +377,17 @@
 		if (f->tag != FREETAG && tsince(f->tag) >= timeout) {
 			n = f->waited += timeout;
 			n /= HZ;
-			if (n > MAXWAIT) { /* waited too long.  device failure. */
+			if (n > aoe_deadsecs) { /* waited too long for response */
 				aoedev_downdev(d);
 				break;
 			}
 			rexmit(d, f);
 		}
 	}
+	if (d->flags & DEVFL_KICKME) {
+		d->flags &= ~DEVFL_KICKME;
+		aoecmd_work(d);
+	}
 
 	sl = d->sendq_hd;
 	d->sendq_hd = d->sendq_tl = NULL;
@@ -431,8 +472,8 @@
 	}
 
 	if (d->ssize != ssize)
-		printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
-			"sectors\n", (unsigned long long)mac_addr(d->addr),
+		printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n",
+			(unsigned long long)mac_addr(d->addr),
 			d->aoemajor, d->aoeminor,
 			d->fw_ver, (long long)ssize);
 	d->ssize = ssize;
@@ -442,11 +483,9 @@
 		d->flags |= DEVFL_NEWSIZE;
 	} else {
 		if (d->flags & DEVFL_GDALLOC) {
-			printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n",
-			       __FUNCTION__,
-			       "can't schedule work for",
+			printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n",
 			       d->aoemajor, d->aoeminor,
-			       "it's already on! (This really shouldn't happen).\n");
+			       "it's already on!  This shouldn't happen.\n");
 			return;
 		}
 		d->flags |= DEVFL_GDALLOC;
@@ -460,8 +499,15 @@
 	register long n;
 
 	n = rtt;
-	if (n < MINTIMER)
-		n = MINTIMER;
+	if (n < 0) {
+		n = -rtt;
+		if (n < MINTIMER)
+			n = MINTIMER;
+		else if (n > MAXTIMER)
+			n = MAXTIMER;
+		d->mintimer += (n - d->mintimer) >> 1;
+	} else if (n < d->mintimer)
+		n = d->mintimer;
 	else if (n > MAXTIMER)
 		n = MAXTIMER;
 
@@ -474,7 +520,7 @@
 aoecmd_ata_rsp(struct sk_buff *skb)
 {
 	struct aoedev *d;
-	struct aoe_hdr *hin;
+	struct aoe_hdr *hin, *hout;
 	struct aoe_atahdr *ahin, *ahout;
 	struct frame *f;
 	struct buf *buf;
@@ -497,8 +543,10 @@
 
 	spin_lock_irqsave(&d->lock, flags);
 
-	f = getframe(d, be32_to_cpu(hin->tag));
+	n = be32_to_cpu(hin->tag);
+	f = getframe(d, n);
 	if (f == NULL) {
+		calc_rttavg(d, -tsince(n));
 		spin_unlock_irqrestore(&d->lock, flags);
 		snprintf(ebuf, sizeof ebuf,
 			"%15s e%d.%d    tag=%08x@%08lx\n",
@@ -514,26 +562,27 @@
 	calc_rttavg(d, tsince(f->tag));
 
 	ahin = (struct aoe_atahdr *) (hin+1);
-	ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr));
+	hout = (struct aoe_hdr *) f->skb->mac.raw;
+	ahout = (struct aoe_atahdr *) (hout+1);
 	buf = f->buf;
 
 	if (ahout->cmdstat == WIN_IDENTIFY)
 		d->flags &= ~DEVFL_PAUSE;
 	if (ahin->cmdstat & 0xa9) {	/* these bits cleared on success */
-		printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
-			"stat=%2.2Xh from e%ld.%ld\n", 
+		printk(KERN_ERR
+			"aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n",
 			ahout->cmdstat, ahin->cmdstat,
 			d->aoemajor, d->aoeminor);
 		if (buf)
 			buf->flags |= BUFFL_FAIL;
 	} else {
+		n = ahout->scnt << 9;
 		switch (ahout->cmdstat) {
 		case WIN_READ:
 		case WIN_READ_EXT:
-			n = ahout->scnt << 9;
 			if (skb->len - sizeof *hin - sizeof *ahin < n) {
-				printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
-					"ata data size in read.  skb->len=%d\n",
+				printk(KERN_ERR
+					"aoe: runt data size in read.  skb->len=%d\n",
 					skb->len);
 				/* fail frame f?  just returning will rexmit. */
 				spin_unlock_irqrestore(&d->lock, flags);
@@ -542,22 +591,49 @@
 			memcpy(f->bufaddr, ahin+1, n);
 		case WIN_WRITE:
 		case WIN_WRITE_EXT:
+			if (f->bcnt -= n) {
+				skb = f->skb;
+				f->bufaddr += n;
+				put_lba(ahout, f->lba += ahout->scnt);
+				n = f->bcnt;
+				if (n > DEFAULTBCNT)
+					n = DEFAULTBCNT;
+				ahout->scnt = n >> 9;
+				if (ahout->aflags & AOEAFL_WRITE) {
+					skb_fill_page_desc(skb, 0,
+						virt_to_page(f->bufaddr),
+						offset_in_page(f->bufaddr), n);
+					skb->len = sizeof *hout + sizeof *ahout + n;
+					skb->data_len = n;
+				}
+				f->tag = newtag(d);
+				hout->tag = cpu_to_be32(f->tag);
+				skb->dev = d->ifp;
+				skb = skb_clone(skb, GFP_ATOMIC);
+				spin_unlock_irqrestore(&d->lock, flags);
+				if (skb)
+					aoenet_xmit(skb);
+				return;
+			}
+			if (n > DEFAULTBCNT)
+				d->lostjumbo = 0;
 			break;
 		case WIN_IDENTIFY:
 			if (skb->len - sizeof *hin - sizeof *ahin < 512) {
-				printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size "
-					"in ataid.  skb->len=%d\n", skb->len);
+				printk(KERN_INFO
+					"aoe: runt data size in ataid.  skb->len=%d\n",
+					skb->len);
 				spin_unlock_irqrestore(&d->lock, flags);
 				return;
 			}
 			ataid_complete(d, (char *) (ahin+1));
 			break;
 		default:
-			printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized "
-			       "outbound ata command %2.2Xh for %d.%d\n", 
-			       ahout->cmdstat,
-			       be16_to_cpu(hin->major),
-			       hin->minor);
+			printk(KERN_INFO
+				"aoe: unrecognized ata command %2.2Xh for %d.%d\n",
+				ahout->cmdstat,
+				be16_to_cpu(hin->major),
+				hin->minor);
 		}
 	}
 
@@ -612,33 +688,32 @@
 	struct frame *f;
 	struct sk_buff *skb;
 
-	f = getframe(d, FREETAG);
+	f = freeframe(d);
 	if (f == NULL) {
-		printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame.  "
-			"This shouldn't happen.\n");
+		printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n");
 		return NULL;
 	}
 
 	/* initialize the headers & frame */
-	h = (struct aoe_hdr *) f->data;
+	skb = f->skb;
+	h = (struct aoe_hdr *) skb->mac.raw;
 	ah = (struct aoe_atahdr *) (h+1);
-	f->ndata = sizeof *h + sizeof *ah;
-	memset(h, 0, f->ndata);
+	skb->len = ETH_ZLEN;
+	memset(h, 0, ETH_ZLEN);
 	f->tag = aoehdr_atainit(d, h);
 	f->waited = 0;
-	f->writedatalen = 0;
 
 	/* set up ata header */
 	ah->scnt = 1;
 	ah->cmdstat = WIN_IDENTIFY;
 	ah->lba3 = 0xa0;
 
-	skb = skb_prepare(d, f);
+	skb->dev = d->ifp;
 
 	d->rttavg = MAXTIMER;
 	d->timer.function = rexmit_timer;
 
-	return skb;
+	return skb_clone(skb, GFP_ATOMIC);
 }
  
 void
@@ -648,9 +723,9 @@
 	struct aoe_hdr *h;
 	struct aoe_cfghdr *ch;
 	ulong flags, sysminor, aoemajor;
-	u16 bufcnt;
 	struct sk_buff *sl;
 	enum { MAXFRAMES = 16 };
+	u16 n;
 
 	h = (struct aoe_hdr *) skb->mac.raw;
 	ch = (struct aoe_cfghdr *) (h+1);
@@ -661,26 +736,25 @@
 	 */
 	aoemajor = be16_to_cpu(h->major);
 	if (aoemajor == 0xfff) {
-		printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf "
-			"address is all ones.  Check shelf dip switches\n");
+		printk(KERN_ERR "aoe: Warning: shelf address is all ones.  "
+			"Check shelf dip switches.\n");
 		return;
 	}
 
 	sysminor = SYSMINOR(aoemajor, h->minor);
 	if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) {
-		printk(KERN_INFO
-			"aoe: e%ld.%d: minor number too large\n", 
+		printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n",
 			aoemajor, (int) h->minor);
 		return;
 	}
 
-	bufcnt = be16_to_cpu(ch->bufcnt);
-	if (bufcnt > MAXFRAMES)	/* keep it reasonable */
-		bufcnt = MAXFRAMES;
+	n = be16_to_cpu(ch->bufcnt);
+	if (n > MAXFRAMES)	/* keep it reasonable */
+		n = MAXFRAMES;
 
-	d = aoedev_by_sysminor_m(sysminor, bufcnt);
+	d = aoedev_by_sysminor_m(sysminor, n);
 	if (d == NULL) {
-		printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");
+		printk(KERN_INFO "aoe: device sysminor_m failure\n");
 		return;
 	}
 
@@ -689,6 +763,20 @@
 	/* permit device to migrate mac and network interface */
 	d->ifp = skb->dev;
 	memcpy(d->addr, h->src, sizeof d->addr);
+	if (!(d->flags & DEVFL_MAXBCNT)) {
+		n = d->ifp->mtu;
+		n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr);
+		n /= 512;
+		if (n > ch->scnt)
+			n = ch->scnt;
+		n = n ? n * 512 : DEFAULTBCNT;
+		if (n != d->maxbcnt) {
+			printk(KERN_INFO
+				"aoe: e%ld.%ld: setting %d byte data frames on %s\n",
+				d->aoemajor, d->aoeminor, n, d->ifp->name);
+			d->maxbcnt = n;
+		}
+	}
 
 	/* don't change users' perspective */
 	if (d->nopen && !(d->flags & DEVFL_PAUSE)) {
@@ -696,6 +784,7 @@
 		return;
 	}
 	d->flags |= DEVFL_PAUSE;	/* force pause */
+	d->mintimer = MINTIMER;
 	d->fw_ver = be16_to_cpu(ch->fwver);
 
 	/* check for already outstanding ataid */
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index ed4258a..6125921 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoedev.c
  * AoE device utility functions; maintains device list.
@@ -20,11 +20,8 @@
 	f = d->frames;
 	e = f + d->nframes;
 	do {
-		if (f->tag != FREETAG) {
-			printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n",
-				d->aoemajor, d->aoeminor);
+		if (f->tag != FREETAG)
 			return 1;
-		}
 	} while (++f < e);
 
 	return 0;
@@ -66,22 +63,32 @@
 	struct frame *f, *e;
 
 	d = kzalloc(sizeof *d, GFP_ATOMIC);
-	if (d == NULL)
-		return NULL;
 	f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
-	if (f == NULL) {
-		kfree(d);
+ 	switch (!d || !f) {
+ 	case 0:
+ 		d->nframes = nframes;
+ 		d->frames = f;
+ 		e = f + nframes;
+ 		for (; f<e; f++) {
+ 			f->tag = FREETAG;
+ 			f->skb = new_skb(ETH_ZLEN);
+ 			if (!f->skb)
+ 				break;
+ 		}
+ 		if (f == e)
+ 			break;
+ 		while (f > d->frames) {
+ 			f--;
+ 			dev_kfree_skb(f->skb);
+ 		}
+ 	default:
+ 		if (f)
+ 			kfree(f);
+ 		if (d)
+ 			kfree(d);
 		return NULL;
 	}
-
 	INIT_WORK(&d->work, aoecmd_sleepwork, d);
-
-	d->nframes = nframes;
-	d->frames = f;
-	e = f + nframes;
-	for (; f<e; f++)
-		f->tag = FREETAG;
-
 	spin_lock_init(&d->lock);
 	init_timer(&d->timer);
 	d->timer.data = (ulong) d;
@@ -114,6 +121,7 @@
 			mempool_free(buf, d->bufpool);
 			bio_endio(bio, bio->bi_size, -EIO);
 		}
+		skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
 	}
 	d->inprocess = NULL;
 
@@ -148,7 +156,7 @@
 		d = aoedev_newdev(bufcnt);
 	 	if (d == NULL) {
 			spin_unlock_irqrestore(&devlist_lock, flags);
-			printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
+			printk(KERN_INFO "aoe: aoedev_newdev failure.\n");
 			return NULL;
 		}
 		d->sysminor = sysminor;
@@ -163,11 +171,19 @@
 static void
 aoedev_freedev(struct aoedev *d)
 {
+	struct frame *f, *e;
+
 	if (d->gd) {
 		aoedisk_rm_sysfs(d);
 		del_gendisk(d->gd);
 		put_disk(d->gd);
 	}
+	f = d->frames;
+	e = f + d->nframes;
+	for (; f<e; f++) {
+		skb_shinfo(f->skb)->nr_frags = 0;
+		dev_kfree_skb(f->skb);
+	}
 	kfree(d->frames);
 	if (d->bufpool)
 		mempool_destroy(d->bufpool);
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
index de08491..a04b7d6 100644
--- a/drivers/block/aoe/aoemain.c
+++ b/drivers/block/aoe/aoemain.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoemain.c
  * Module initialization routines, discover timer
@@ -84,13 +84,11 @@
 		goto net_fail;
 	ret = register_blkdev(AOE_MAJOR, DEVICE_NAME);
 	if (ret < 0) {
-		printk(KERN_ERR "aoe: aoeblk_init: can't register major\n");
+		printk(KERN_ERR "aoe: can't register major\n");
 		goto blkreg_fail;
 	}
 
-	printk(KERN_INFO
-	       "aoe: aoe_init: AoE v%s initialised.\n",
-	       VERSION);
+	printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION);
 	discover_timer(TINIT);
 	return 0;
 
@@ -103,7 +101,7 @@
  chr_fail:
 	aoedev_exit();
 	
-	printk(KERN_INFO "aoe: aoe_init: initialisation failure.\n");
+	printk(KERN_INFO "aoe: initialisation failure.\n");
 	return ret;
 }
 
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index c1434ed..9626e0f 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoenet.c
  * Ethernet portion of AoE driver
@@ -74,7 +74,7 @@
 		return -EINVAL;
 
 	if (copy_from_user(aoe_iflist, user_str, size)) {
-		printk(KERN_INFO "aoe: %s: copy from user failed\n", __FUNCTION__);
+		printk(KERN_INFO "aoe: copy from user failed\n");
 		return -EFAULT;
 	}
 	aoe_iflist[size] = 0x00;
@@ -132,8 +132,7 @@
 		if (n > NECODES)
 			n = 0;
 		if (net_ratelimit())
-			printk(KERN_ERR "aoe: aoenet_rcv: error packet from %d.%d; "
-			       "ecode=%d '%s'\n",
+			printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n",
 			       be16_to_cpu(h->major), h->minor, 
 			       h->err, aoe_errlist[n]);
 		goto exit;
@@ -147,7 +146,7 @@
 		aoecmd_cfg_rsp(skb);
 		break;
 	default:
-		printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %d\n", h->cmd);
+		printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
 	}
 exit:
 	dev_kfree_skb(skb);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index c396509..14d6b94 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -342,7 +342,7 @@
 static void fd_deselect( void );
 static void fd_motor_off_timer( unsigned long dummy );
 static void check_change( unsigned long dummy );
-static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t floppy_irq (int irq, void *dummy);
 static void fd_error( void );
 static int do_format(int drive, int type, struct atari_format_descr *desc);
 static void do_fd_action( int drive );
@@ -573,7 +573,7 @@
 
 static void (*FloppyIRQHandler)( int status ) = NULL;
 
-static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t floppy_irq (int irq, void *dummy)
 {
 	unsigned char status;
 	void (*handler)( int );
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 36b88f6..bc66026 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -130,7 +130,7 @@
 static ctlr_info_t *hba[MAX_CTLR];
 
 static void do_cciss_request(request_queue_t *q);
-static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t do_cciss_intr(int irq, void *dev_id);
 static int cciss_open(struct inode *inode, struct file *filep);
 static int cciss_release(struct inode *inode, struct file *filep);
 static int cciss_ioctl(struct inode *inode, struct file *filep,
@@ -1923,7 +1923,6 @@
 {
 	int return_code;
 	unsigned long t;
-	unsigned long rem;
 
 	memset(inq_buff, 0, sizeof(InquiryData_struct));
 	if (withirq)
@@ -1939,26 +1938,23 @@
 			printk(KERN_WARNING
 			       "cciss: reading geometry failed, volume "
 			       "does not support reading geometry\n");
-			drv->block_size = block_size;
-			drv->nr_blocks = total_size;
 			drv->heads = 255;
 			drv->sectors = 32;	// Sectors per track
-			t = drv->heads * drv->sectors;
-			drv->cylinders = total_size;
-			rem = do_div(drv->cylinders, t);
 		} else {
-			drv->block_size = block_size;
-			drv->nr_blocks = total_size;
 			drv->heads = inq_buff->data_byte[6];
 			drv->sectors = inq_buff->data_byte[7];
 			drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;
 			drv->cylinders += inq_buff->data_byte[5];
 			drv->raid_level = inq_buff->data_byte[8];
-			t = drv->heads * drv->sectors;
-			if (t > 1) {
-				drv->cylinders = total_size;
-				rem = do_div(drv->cylinders, t);
-			}
+		}
+		drv->block_size = block_size;
+		drv->nr_blocks = total_size;
+		t = drv->heads * drv->sectors;
+		if (t > 1) {
+			unsigned rem = sector_div(total_size, t);
+			if (rem)
+				total_size++;
+			drv->cylinders = total_size;
 		}
 	} else {		/* Get geometry failed */
 		printk(KERN_WARNING "cciss: reading geometry failed\n");
@@ -2300,7 +2296,7 @@
 #ifdef CONFIG_CISS_SCSI_TAPE
 	/* if we saved some commands for later, process them now. */
 	if (info_p->scsi_rejects.ncompletions > 0)
-		do_cciss_intr(0, info_p, NULL);
+		do_cciss_intr(0, info_p);
 #endif
 	cmd_free(info_p, c, 1);
 	return status;
@@ -2652,7 +2648,7 @@
 #endif
 }
 
-static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_cciss_intr(int irq, void *dev_id)
 {
 	ctlr_info_t *h = dev_id;
 	CommandList_struct *c;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index ada68e6..570d2f0 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -169,7 +169,7 @@
 static inline void complete_buffers(struct bio *bio, int ok);
 static inline void complete_command(cmdlist_t *cmd, int timeout);
 
-static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t do_ida_intr(int irq, void *dev_id);
 static void ida_timer(unsigned long tdata);
 static int ida_revalidate(struct gendisk *disk);
 static int revalidate_allvol(ctlr_info_t *host);
@@ -1042,7 +1042,7 @@
  *  Find the command on the completion queue, remove it, tell the OS and
  *  try to queue up more IO
  */
-static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_ida_intr(int irq, void *dev_id)
 {
 	ctlr_info_t *h = dev_id;
 	cmdlist_t *c;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 629c576..9e6d3a8 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -221,7 +221,7 @@
 static struct completion device_release;
 
 static unsigned short virtual_dma_port = 0x3f0;
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t floppy_interrupt(int irq, void *dev_id);
 static int set_dor(int fdc, char mask, char data);
 
 #define K_64	0x10000		/* 64KB */
@@ -1726,7 +1726,7 @@
 }
 
 /* interrupt handler. Note that this can be called externally on the Sparc */
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t floppy_interrupt(int irq, void *dev_id)
 {
 	void (*handler) (void) = do_floppy;
 	int do_print;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index d6bb8da..beab6d2 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -295,7 +295,7 @@
  * and do_lo_send_write().
  */
 static int __do_lo_send_write(struct file *file,
-		u8 __user *buf, const int len, loff_t pos)
+		u8 *buf, const int len, loff_t pos)
 {
 	ssize_t bw;
 	mm_segment_t old_fs = get_fs();
@@ -324,7 +324,7 @@
 		struct bio_vec *bvec, int bsize, loff_t pos, struct page *page)
 {
 	ssize_t bw = __do_lo_send_write(lo->lo_backing_file,
-			(u8 __user *)kmap(bvec->bv_page) + bvec->bv_offset,
+			kmap(bvec->bv_page) + bvec->bv_offset,
 			bvec->bv_len, pos);
 	kunmap(bvec->bv_page);
 	cond_resched();
@@ -351,7 +351,7 @@
 			bvec->bv_offset, bvec->bv_len, pos >> 9);
 	if (likely(!ret))
 		return __do_lo_send_write(lo->lo_backing_file,
-				(u8 __user *)page_address(page), bvec->bv_len,
+				page_address(page), bvec->bv_len,
 				pos);
 	printk(KERN_ERR "loop: Transfer error at byte offset %llu, "
 			"length %i.\n", (unsigned long long)pos, bvec->bv_len);
@@ -1187,7 +1187,7 @@
  * - noinlined to reduce stack space usage in main part of driver
  */
 static noinline int
-loop_info64_from_compat(const struct compat_loop_info *arg,
+loop_info64_from_compat(const struct compat_loop_info __user *arg,
 			struct loop_info64 *info64)
 {
 	struct compat_loop_info info;
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 5537974..688a4fb 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -75,8 +75,7 @@
 
 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
 
-static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
-				      struct pt_regs *regs);
+static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id);
 static void (*current_int_handler) (u_int) = NULL;
 static void ps2esdi_normal_interrupt_handler(u_int);
 static void ps2esdi_initial_reset_int_handler(u_int);
@@ -687,8 +686,7 @@
 
 
 
-static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id)
 {
 	u_int int_ret_code;
 
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index a3f64bf..485aa87 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -432,6 +432,12 @@
 		rd_disks[i] = alloc_disk(1);
 		if (!rd_disks[i])
 			goto out;
+
+		rd_queue[i] = blk_alloc_queue(GFP_KERNEL);
+		if (!rd_queue[i]) {
+			put_disk(rd_disks[i]);
+			goto out;
+		}
 	}
 
 	if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
@@ -442,10 +448,6 @@
 	for (i = 0; i < CONFIG_BLK_DEV_RAM_COUNT; i++) {
 		struct gendisk *disk = rd_disks[i];
 
-		rd_queue[i] = blk_alloc_queue(GFP_KERNEL);
-		if (!rd_queue[i])
-			goto out_queue;
-
 		blk_queue_make_request(rd_queue[i], &rd_make_request);
 		blk_queue_hardsect_size(rd_queue[i], rd_blocksize);
 
@@ -466,8 +468,6 @@
 		CONFIG_BLK_DEV_RAM_COUNT, rd_size, rd_blocksize);
 
 	return 0;
-out_queue:
-	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
 out:
 	while (i--) {
 		put_disk(rd_disks[i]);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index fdc8f89..1a65979 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -238,8 +238,8 @@
 static void seek_timeout(unsigned long data);
 static void settle_timeout(unsigned long data);
 static void xfer_timeout(unsigned long data);
-static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-/*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);*/
+static irqreturn_t swim3_interrupt(int irq, void *dev_id);
+/*static void fd_dma_interrupt(int irq, void *dev_id);*/
 static int grab_drive(struct floppy_state *fs, enum swim_state state,
 		      int interruptible);
 static void release_drive(struct floppy_state *fs);
@@ -624,7 +624,7 @@
 	start_request(fs);
 }
 
-static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t swim3_interrupt(int irq, void *dev_id)
 {
 	struct floppy_state *fs = (struct floppy_state *) dev_id;
 	struct swim3 __iomem *sw = fs->swim3;
@@ -777,7 +777,7 @@
 }
 
 /*
-static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void fd_dma_interrupt(int irq, void *dev_id)
 {
 }
 */
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index dfda796..ed7b06c 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -94,7 +94,7 @@
 int swimiop_init(void);
 static void swimiop_init_request(struct swim_iop_req *);
 static int swimiop_send_request(struct swim_iop_req *);
-static void swimiop_receive(struct iop_msg *, struct pt_regs *);
+static void swimiop_receive(struct iop_msg *);
 static void swimiop_status_update(int, struct swim_drvstatus *);
 static int swimiop_eject(struct floppy_state *fs);
 
@@ -257,7 +257,7 @@
  * 2. An unsolicited message was received from the IOP.
  */
 
-void swimiop_receive(struct iop_msg *msg, struct pt_regs *regs)
+void swimiop_receive(struct iop_msg *msg)
 {
 	struct swim_iop_req *req;
 	struct swimmsg_status *sm;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index c6beee18..47d6975 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -1200,7 +1200,7 @@
 	host->resp_idx += work;
 }
 
-static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
+static irqreturn_t carm_interrupt(int irq, void *__host)
 {
 	struct carm_host *host = __host;
 	void __iomem *mmio;
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 45a8f40..0d5c73f 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -362,7 +362,7 @@
 static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_request *urq, struct ub_scsi_cmd *cmd);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
+static void ub_urb_complete(struct urb *urb);
 static void ub_scsi_action(unsigned long _dev);
 static void ub_scsi_dispatch(struct ub_dev *sc);
 static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -959,7 +959,7 @@
  * the sc->lock taken) and from an interrupt (while we do NOT have
  * the sc->lock taken). Therefore, bounce this off to a tasklet.
  */
-static void ub_urb_complete(struct urb *urb, struct pt_regs *pt)
+static void ub_urb_complete(struct urb *urb)
 {
 	struct ub_dev *sc = urb->context;
 
@@ -1923,7 +1923,7 @@
 
 /*
  */
-static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt)
+static void ub_probe_urb_complete(struct urb *urb)
 {
 	struct completion *cop = urb->context;
 	complete(cop);
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index cbb9d0f..30f16bd 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -571,7 +571,7 @@
 --                              mm_interrupt
 -----------------------------------------------------------------------------------
 */
-static irqreturn_t mm_interrupt(int irq, void *__card, struct pt_regs *regs)
+static irqreturn_t mm_interrupt(int irq, void *__card)
 {
 	struct cardinfo *card = (struct cardinfo *) __card;
 	unsigned int dma_status;
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index ebf3025..0d97b7e 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -48,9 +48,9 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
 
@@ -462,8 +462,7 @@
 }
 
 /* xd_interrupt_handler: interrupt service routine */
-static irqreturn_t xd_interrupt_handler(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t xd_interrupt_handler(int irq, void *dev_id)
 {
 	if (inb(XD_STATUS) & STAT_INTERRUPT) {							/* check if it was our device */
 #ifdef DEBUG_OTHER
diff --git a/drivers/block/xd.h b/drivers/block/xd.h
index 71ac2e3..82e090f 100644
--- a/drivers/block/xd.h
+++ b/drivers/block/xd.h
@@ -109,8 +109,7 @@
 static int xd_readwrite (u_char operation,XD_INFO *disk,char *buffer,u_int block,u_int count);
 static void xd_recalibrate (u_char drive);
 
-static irqreturn_t xd_interrupt_handler(int irq, void *dev_id,
-					struct pt_regs *regs);
+static irqreturn_t xd_interrupt_handler(int irq, void *dev_id);
 static u_char xd_setup_dma (u_char opcode,u_char *buffer,u_int count);
 static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control);
 static void xd_watchdog (unsigned long unused);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 82ddbdd..7cc2685 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -329,7 +329,7 @@
 
 static struct request_queue *z2_queue;
 
-int __init 
+static int __init 
 z2_init(void)
 {
     int ret;
@@ -370,26 +370,7 @@
     return ret;
 }
 
-#if defined(MODULE)
-
-MODULE_LICENSE("GPL");
-
-int
-init_module( void )
-{
-    int error;
-    
-    error = z2_init();
-    if ( error == 0 )
-    {
-	printk( KERN_INFO DEVICE_NAME ": loaded as module\n" );
-    }
-    
-    return error;
-}
-
-void
-cleanup_module( void )
+static void __exit z2_exit(void)
 {
     int i, j;
     blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
@@ -425,4 +406,7 @@
 
     return;
 } 
-#endif
+
+module_init(z2_init);
+module_exit(z2_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 13ba729..5167517 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/timer.h>
 
 #include <linux/device.h>
 #include <linux/firmware.h>
@@ -43,7 +42,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "1.0"
+#define VERSION "1.1"
 
 static int ignore = 0;
 
@@ -72,7 +71,7 @@
 
 	unsigned long		state;
 
-	struct timer_list	timer;
+	struct work_struct	work;
 
 	struct urb		*urb;
 	unsigned char		*buffer;
@@ -82,7 +81,7 @@
 	unsigned int		fw_sent;
 };
 
-static void bcm203x_complete(struct urb *urb, struct pt_regs *regs)
+static void bcm203x_complete(struct urb *urb)
 {
 	struct bcm203x_data *data = urb->context;
 	struct usb_device *udev = urb->dev;
@@ -105,7 +104,7 @@
 
 		data->state = BCM203X_SELECT_MEMORY;
 
-		mod_timer(&data->timer, jiffies + (HZ / 10));
+		schedule_work(&data->work);
 		break;
 
 	case BCM203X_SELECT_MEMORY:
@@ -158,9 +157,9 @@
 	}
 }
 
-static void bcm203x_timer(unsigned long user_data)
+static void bcm203x_work(void *user_data)
 {
-	struct bcm203x_data *data = (struct bcm203x_data *) user_data;
+	struct bcm203x_data *data = user_data;
 
 	if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
 		BT_ERR("Can't submit URB");
@@ -247,13 +246,11 @@
 
 	release_firmware(firmware);
 
-	init_timer(&data->timer);
-	data->timer.function = bcm203x_timer;
-	data->timer.data = (unsigned long) data;
+	INIT_WORK(&data->work, bcm203x_work, (void *) data);
 
 	usb_set_intfdata(intf, data);
 
-	mod_timer(&data->timer, jiffies + HZ);
+	schedule_work(&data->work);
 
 	return 0;
 }
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index efcc28e..31ade99 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -95,8 +95,8 @@
 	struct urb *urb;
 };
 
-static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs);
-static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs);
+static void bfusb_tx_complete(struct urb *urb);
+static void bfusb_rx_complete(struct urb *urb);
 
 static struct urb *bfusb_get_completed(struct bfusb_data *data)
 {
@@ -190,7 +190,7 @@
 	clear_bit(BFUSB_TX_PROCESS, &data->state);
 }
 
-static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
+static void bfusb_tx_complete(struct urb *urb)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
 	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
@@ -349,7 +349,7 @@
 	return 0;
 }
 
-static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
+static void bfusb_rx_complete(struct urb *urb)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
 	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 8eebf9c..845b868 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -497,7 +497,7 @@
 }
 
 
-static irqreturn_t bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
 {
 	bluecard_info_t *info = dev_inst;
 	unsigned int iobase;
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index e0231dc..9fca651 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -263,7 +263,7 @@
 	}
 }
 
-static void bpa10x_complete(struct urb *urb, struct pt_regs *regs)
+static void bpa10x_complete(struct urb *urb)
 {
 	struct bpa10x_data *data = urb->context;
 	unsigned char *buf = urb->transfer_buffer;
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index df7bb01..3a96a0b 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -338,7 +338,7 @@
 }
 
 
-static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
 {
 	bt3c_info_t *info = dev_inst;
 	unsigned int iobase;
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 746ccca..3b29086 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -288,7 +288,7 @@
 }
 
 
-static irqreturn_t btuart_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
 {
 	btuart_info_t *info = dev_inst;
 	unsigned int iobase;
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 0e99def..07eafbc 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -291,7 +291,7 @@
 }
 
 
-static irqreturn_t dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
 {
 	dtl1_info_t *info = dev_inst;
 	unsigned int iobase;
@@ -711,6 +711,7 @@
 
 static struct pcmcia_device_id dtl1_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
+	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
 	PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
 	PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
 	PCMCIA_DEVICE_NULL
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 0801af4..fdea58a 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -118,6 +118,9 @@
 	/* IBM/Lenovo ThinkPad with Broadcom chip */
 	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
 
+	/* ANYCOM Bluetooth USB-200 and USB-250 */
+	{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
+
 	/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
 	{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
 
@@ -176,8 +179,8 @@
 	return _urb;
 }
 
-static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs);
-static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs);
+static void hci_usb_rx_complete(struct urb *urb);
+static void hci_usb_tx_complete(struct urb *urb);
 
 #define __pending_tx(husb, type)  (&husb->pending_tx[type-1])
 #define __pending_q(husb, type)   (&husb->pending_q[type-1])
@@ -732,7 +735,7 @@
 	return 0;
 }
 
-static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs)
+static void hci_usb_rx_complete(struct urb *urb)
 {
 	struct _urb *_urb = container_of(urb, struct _urb, urb);
 	struct hci_usb *husb = (void *) urb->context;
@@ -786,7 +789,7 @@
 	read_unlock(&husb->completion_lock);
 }
 
-static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs)
+static void hci_usb_tx_complete(struct urb *urb)
 {
 	struct _urb *_urb = container_of(urb, struct _urb, urb);
 	struct hci_usb *husb = (void *) urb->context;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 2a0c50d..7ea0f48 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -703,7 +703,7 @@
 {
 	struct packet_command cgc;
 	char buffer[16];
-	__u16 *feature_code;
+	__be16 *feature_code;
 	int ret;
 
 	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
@@ -716,7 +716,7 @@
 	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
 		return ret;
 
-	feature_code = (__u16 *) &buffer[sizeof(struct feature_header)];
+	feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
 	if (be16_to_cpu(*feature_code) == CDF_HWDM)
 		return 0;
 
@@ -2963,7 +2963,7 @@
 		   how much data is available for transfer. buffer[1] is
 		   unfortunately ambigious and the only reliable way seem
 		   to be to simply skip over the block descriptor... */
-		offset = 8 + be16_to_cpu(*(unsigned short *)(buffer+6));
+		offset = 8 + be16_to_cpu(*(__be16 *)(buffer+6));
 
 		if (offset + 16 > sizeof(buffer))
 			return -E2BIG;
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index ccd91c1..2157c58 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -513,7 +513,7 @@
 	outb(cmd, sony_cd_cmd_reg);
 }
 
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
 {
 	unsigned char val;
 
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index 9b05ddd..e6d8e9e 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -359,7 +359,7 @@
    as there seems so reason for this to happen.
 */
 
-static irqreturn_t cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cm206_interrupt(int sig, void *dev_id)
 {
 	volatile ush fool;
 	cd->intr_ds = inw(r_data_status);	/* resets data_ready, data_error,
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index dcd1ab6..f574962 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -845,15 +845,11 @@
 	}
 }
 
-static irqreturn_t mcdx_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mcdx_intr(int irq, void *dev_id)
 {
 	struct s_drive_stuff *stuffp = dev_id;
 	unsigned char b;
 
-	if (stuffp == NULL) {
-		xwarn("mcdx: no device for intr %d\n", irq);
-		return IRQ_NONE;
-	}
 #ifdef AK2
 	if (!stuffp->busy && stuffp->pending)
 		stuffp->int_err = 1;
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index 30ab562..f77ada9 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -322,7 +322,7 @@
 }
 
 static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+cdu535_interrupt(int irq, void *dev_id)
 {
 	disable_interrupts();
 	if (waitqueue_active(&cdu535_irq_wait)) {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 0e6f35f..39a9f8c 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -1046,7 +1046,7 @@
 
 config TELCLOCK
 	tristate "Telecom clock driver for MPBL0010 ATCA SBC"
-	depends on EXPERIMENTAL
+	depends on EXPERIMENTAL && X86
 	default n
 	help
 	  The telecom clock device is specific to the MPBL0010 ATCA computer and
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 91b71e7..dffc193 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -27,32 +27,42 @@
 static int uninorth_rev;
 static int is_u3;
 
+static char __devinitdata *aperture = NULL;
 
 static int uninorth_fetch_size(void)
 {
-	int i;
-	u32 temp;
-	struct aper_size_info_32 *values;
+	int i, size = 0;
+	struct aper_size_info_32 *values =
+	    A_SIZE_32(agp_bridge->driver->aperture_sizes);
 
-	pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_BASE, &temp);
-	temp &= ~(0xfffff000);
-	values = A_SIZE_32(agp_bridge->driver->aperture_sizes);
+	if (aperture) {
+		char *save = aperture;
 
-	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
-		if (temp == values[i].size_value) {
-			agp_bridge->previous_size =
-			    agp_bridge->current_size = (void *) (values + i);
-			agp_bridge->aperture_size_idx = i;
-			return values[i].size;
+		size = memparse(aperture, &aperture) >> 20;
+		aperture = save;
+
+		for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
+			if (size == values[i].size)
+				break;
+
+		if (i == agp_bridge->driver->num_aperture_sizes) {
+			printk(KERN_ERR PFX "Invalid aperture size, using"
+			       " default\n");
+			size = 0;
+			aperture = NULL;
 		}
 	}
 
-	agp_bridge->previous_size =
-	    agp_bridge->current_size = (void *) (values + 1);
-	agp_bridge->aperture_size_idx = 1;
-	return values[1].size;
+	if (!size) {
+		for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
+			if (values[i].size == 32)
+				break;
+	}
 
-	return 0;
+	agp_bridge->previous_size =
+	    agp_bridge->current_size = (void *)(values + i);
+	agp_bridge->aperture_size_idx = i;
+	return values[i].size;
 }
 
 static void uninorth_tlbflush(struct agp_memory *mem)
@@ -683,5 +693,11 @@
 module_init(agp_uninorth_init);
 module_exit(agp_uninorth_cleanup);
 
+module_param(aperture, charp, 0);
+MODULE_PARM_DESC(aperture,
+		 "Aperture size, must be power of two between 4MB and an\n"
+		 "\t\tupper limit specific to the UniNorth revision.\n"
+		 "\t\tDefault: 32M");
+
 MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 486f97c..66086fa 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -447,7 +447,7 @@
 	}
 }
 
-static irqreturn_t ser_vbl_int( int irq, void *data, struct pt_regs *regs)
+static irqreturn_t ser_vbl_int( int irq, void *data)
 {
         /* vbl is just a periodic interrupt we tie into to update modem status */
 	struct async_struct * info = IRQ_ports;
@@ -460,7 +460,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ser_rx_int(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ser_rx_int(int irq, void *dev_id)
 {
 	struct async_struct * info;
 
@@ -480,7 +480,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ser_tx_int(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ser_tx_int(int irq, void *dev_id)
 {
 	struct async_struct * info;
 
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 10a389d..1f0b752 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -110,7 +110,7 @@
 static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *);
 static int ac_ioctl(struct inode *, struct file *, unsigned int,
 		    unsigned long);
-static irqreturn_t ac_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t ac_interrupt(int, void *);
 
 static const struct file_operations ac_fops = {
 	.owner = THIS_MODULE,
@@ -617,7 +617,7 @@
 	} 
 }
 
-static irqreturn_t ac_interrupt(int vec, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t ac_interrupt(int vec, void *dev_instance)
 {
 	unsigned int i;
 	unsigned int FlagInt;
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 87b2fb5..e608dad 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1057,7 +1057,7 @@
    received, out buffer empty, modem change, etc.
  */
 static irqreturn_t
-cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+cyy_interrupt(int irq, void *dev_id)
 {
   struct tty_struct *tty;
   int status;
@@ -1802,7 +1802,7 @@
 
 #ifdef CONFIG_CYZ_INTR
 static irqreturn_t
-cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+cyz_interrupt(int irq, void *dev_id)
 {
   struct cyclades_card *cinfo;
 
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 695115d..2908b72 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -38,7 +38,7 @@
 			drm_device_t	*dev	= priv->head->dev
 
 /** IRQ handler arguments and return type and values */
-#define DRM_IRQ_ARGS		int irq, void *arg, struct pt_regs *regs
+#define DRM_IRQ_ARGS		int irq, void *arg
 
 /** AGP types */
 #if __OS_HAS_AGP
diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c
index abac18b..77f58ed 100644
--- a/drivers/char/ec3104_keyb.c
+++ b/drivers/char/ec3104_keyb.c
@@ -370,7 +370,7 @@
 	}
 }
 
-static void ec3104_keyb_interrupt(int irq, void *data, struct pt_regs *regs)
+static void ec3104_keyb_interrupt(int irq, void *data)
 {
 	struct e5_struct *k = &ec3104_keyb;
 	u8 msr, lsr;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index c3f9558..706733c 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1157,6 +1157,7 @@
 	int crd;
 	struct board_info *bd;
 	unsigned char board_id = 0;
+	int err = -ENOMEM;
 
 	int pci_boards_found, pci_count;
 
@@ -1164,13 +1165,11 @@
 
 	pc_driver = alloc_tty_driver(MAX_ALLOC);
 	if (!pc_driver)
-		return -ENOMEM;
+		goto out1;
 
 	pc_info = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_info) {
-		put_tty_driver(pc_driver);
-		return -ENOMEM;
-	}
+	if (!pc_info)
+		goto out2;
 
 	/* -----------------------------------------------------------------------
 		If epca_setup has not been ran by LILO set num_cards to defaults; copy
@@ -1370,11 +1369,17 @@
 
 	} /* End for each card */
 
-	if (tty_register_driver(pc_driver))
-		panic("Couldn't register Digi PC/ driver");
+	err = tty_register_driver(pc_driver);
+	if (err) {
+		printk(KERN_ERR "Couldn't register Digi PC/ driver");
+		goto out3;
+	}
 
-	if (tty_register_driver(pc_info))
-		panic("Couldn't register Digi PC/ info ");
+	err = tty_register_driver(pc_info);
+	if (err) {
+		printk(KERN_ERR "Couldn't register Digi PC/ info ");
+		goto out4;
+	}
 
 	/* -------------------------------------------------------------------
 	   Start up the poller to check for events on all enabled boards
@@ -1385,6 +1390,15 @@
 	mod_timer(&epca_timer, jiffies + HZ/25);
 	return 0;
 
+out4:
+	tty_unregister_driver(pc_driver);
+out3:
+	put_tty_driver(pc_info);
+out2:
+	put_tty_driver(pc_driver);
+out1:
+	return err;
+
 } /* End pc_init */
 
 /* ------------------ Begin post_fep_init  ---------------------- */
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 05788c7..15a4ea8 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -615,8 +615,7 @@
 /*
  * This is the serial driver's interrupt routine
  */
-static irqreturn_t rs_interrupt_single(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
 {
 	struct esp_struct * info;
 	unsigned err_status;
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index 2165324..bbcf918 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -1243,7 +1243,7 @@
 	TRACE_EXIT 0;
 }
 
-static irqreturn_t ftape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ftape_interrupt(int irq, void *dev_id)
 {
 	void (*handler) (void) = *fdc.hook;
 	int handled = 0;
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index d69f2ad..1aa93a7 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -159,7 +159,7 @@
 		if (hangcheck_dump_tasks) {
 			printk(KERN_CRIT "Hangcheck: Task state:\n");
 #ifdef CONFIG_MAGIC_SYSRQ
-			handle_sysrq('t', NULL, NULL);
+			handle_sysrq('t', NULL);
 #endif  /* CONFIG_MAGIC_SYSRQ */
 		}
 		if (hangcheck_reboot) {
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 58b0eb5..091a11c 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -116,7 +116,7 @@
 }
 #endif
 
-static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t hpet_interrupt(int irq, void *data)
 {
 	struct hpet_dev *devp;
 	unsigned long isr;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 4053d1c..9902ffa 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -294,7 +294,7 @@
  * NOTE: This API isn't used if the console adapter doesn't support interrupts.
  * In this case the console is poll driven.
  */
-static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
 {
 	/* if hvc_poll request a repoll, then kick the hvcd thread */
 	if (hvc_poll(dev_instance))
@@ -621,7 +621,7 @@
 					sysrq_pressed = 1;
 					continue;
 				} else if (sysrq_pressed) {
-					handle_sysrq(buf[i], NULL, tty);
+					handle_sysrq(buf[i], tty);
 					sysrq_pressed = 0;
 					continue;
 				}
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 0b89bcd..8728255 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -313,8 +313,7 @@
 
 static void hvcs_unthrottle(struct tty_struct *tty);
 static void hvcs_throttle(struct tty_struct *tty);
-static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
-		struct pt_regs *regs);
+static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance);
 
 static int hvcs_write(struct tty_struct *tty,
 		const unsigned char *buf, int count);
@@ -387,8 +386,7 @@
  * handler taking any further interrupts because they are disabled which means
  * the hvcs_struct will always be valid in this handler.
  */
-static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
-		struct pt_regs *regs)
+static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)
 {
 	struct hvcs_struct *hvcsd = dev_instance;
 
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index c07dc58..2cf63e7 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -406,7 +406,7 @@
 			hp->sysrq = 1;
 			continue;
 		} else if (hp->sysrq) {
-			handle_sysrq(c, NULL, hp->tty);
+			handle_sysrq(c, hp->tty);
 			hp->sysrq = 0;
 			continue;
 		}
@@ -555,7 +555,7 @@
  * must get all pending data because we only get an irq on empty->non-empty
  * transition
  */
-static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t hvsi_interrupt(int irq, void *arg)
 {
 	struct hvsi_struct *hp = (struct hvsi_struct *)arg;
 	struct tty_struct *flip;
@@ -616,7 +616,7 @@
 	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
 
 	for (;;) {
-		hvsi_interrupt(hp->virq, (void *)hp, NULL); /* get pending data */
+		hvsi_interrupt(hp->virq, (void *)hp); /* get pending data */
 
 		if (hp->state == state)
 			return 0;
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index fc944d3..54d93f0 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -1007,7 +1007,7 @@
 // applications that one cannot break out of.
 //******************************************************************************
 static int
-i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user )
+i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
 {
 	i2eBordStrPtr pB;
 	unsigned char *pInsert;
@@ -1020,7 +1020,7 @@
 
 	int bailout = 10;
 
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, user );
+	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 );
 
 	// Ensure channel structure seems real
 	if ( !i2Validate ( pCh ) ) 
@@ -1087,12 +1087,7 @@
 			DATA_COUNT_OF(pInsert)  = amountToMove;
 
 			// Move the data
-			if ( user ) {
-				rc = copy_from_user((char*)(DATA_OF(pInsert)), pSource,
-						amountToMove );
-			} else {
-				memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
-			}
+			memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
 			// Adjust pointers and indices
 			pSource					+= amountToMove;
 			pCh->Obuf_char_count	+= amountToMove;
diff --git a/drivers/char/ip2/i2lib.h b/drivers/char/ip2/i2lib.h
index 952e113..e559e9b 100644
--- a/drivers/char/ip2/i2lib.h
+++ b/drivers/char/ip2/i2lib.h
@@ -332,7 +332,7 @@
 static int  i2GetStatus(i2ChanStrPtr, int);
 static int  i2Input(i2ChanStrPtr);
 static int  i2InputFlush(i2ChanStrPtr);
-static int  i2Output(i2ChanStrPtr, const char *, int, int);
+static int  i2Output(i2ChanStrPtr, const char *, int);
 static int  i2OutputFree(i2ChanStrPtr);
 static int  i2ServiceBoard(i2eBordStrPtr);
 static void i2DrainOutput(i2ChanStrPtr, int);
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 62ef511..a3f32d4 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -190,7 +190,7 @@
 
 static void set_irq(int, int);
 static void ip2_interrupt_bh(i2eBordStrPtr pB);
-static irqreturn_t ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t ip2_interrupt(int irq, void *dev_id);
 static void ip2_poll(unsigned long arg);
 static inline void service_all_boards(void);
 static void do_input(void *p);
@@ -1154,10 +1154,9 @@
 
 
 /******************************************************************************/
-/* Function:   ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs)    */
+/* Function:   ip2_interrupt(int irq, void *dev_id)    */
 /* Parameters: irq - interrupt number                                         */
 /*             pointer to optional device ID structure                        */
-/*             pointer to register structure                                  */
 /* Returns:    Nothing                                                        */
 /*                                                                            */
 /* Description:                                                               */
@@ -1173,7 +1172,7 @@
 /*                                                                            */
 /******************************************************************************/
 static irqreturn_t
-ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+ip2_interrupt(int irq, void *dev_id)
 {
 	int i;
 	i2eBordStrPtr  pB;
@@ -1237,7 +1236,7 @@
 	// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
 	// It will NOT poll boards handled by hard interrupts.
 	// The issue of queued BH interrups is handled in ip2_interrupt().
-	ip2_interrupt(0, NULL, NULL);
+	ip2_interrupt(0, NULL);
 
 	PollTimer.expires = POLL_TIMEOUT;
 	add_timer( &PollTimer );
@@ -1705,7 +1704,7 @@
 
 	/* This is the actual move bit. Make sure it does what we need!!!!! */
 	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
-	bytesSent = i2Output( pCh, pData, count, 0 );
+	bytesSent = i2Output( pCh, pData, count);
 	WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
 
 	ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
@@ -1765,7 +1764,7 @@
 		//
 		// We may need to restart i2Output if it does not fullfill this request
 		//
-		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 );
+		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
 		if ( strip != pCh->Pbuf_stuff ) {
 			memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
 		}
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 2455e8d..34a4fd1 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -1928,13 +1928,8 @@
 			(long long) bmc->guid[8]);
 }
 
-static void
-cleanup_bmc_device(struct kref *ref)
+static void remove_files(struct bmc_device *bmc)
 {
-	struct bmc_device *bmc;
-
-	bmc = container_of(ref, struct bmc_device, refcount);
-
 	device_remove_file(&bmc->dev->dev,
 			   &bmc->device_id_attr);
 	device_remove_file(&bmc->dev->dev,
@@ -1951,12 +1946,23 @@
 			   &bmc->manufacturer_id_attr);
 	device_remove_file(&bmc->dev->dev,
 			   &bmc->product_id_attr);
+
 	if (bmc->id.aux_firmware_revision_set)
 		device_remove_file(&bmc->dev->dev,
 				   &bmc->aux_firmware_rev_attr);
 	if (bmc->guid_set)
 		device_remove_file(&bmc->dev->dev,
 				   &bmc->guid_attr);
+}
+
+static void
+cleanup_bmc_device(struct kref *ref)
+{
+	struct bmc_device *bmc;
+
+	bmc = container_of(ref, struct bmc_device, refcount);
+
+	remove_files(bmc);
 	platform_device_unregister(bmc->dev);
 	kfree(bmc);
 }
@@ -1977,6 +1983,79 @@
 	mutex_unlock(&ipmidriver_mutex);
 }
 
+static int create_files(struct bmc_device *bmc)
+{
+	int err;
+
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->device_id_attr);
+	if (err) goto out;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->provides_dev_sdrs_attr);
+	if (err) goto out_devid;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->revision_attr);
+	if (err) goto out_sdrs;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->firmware_rev_attr);
+	if (err) goto out_rev;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->version_attr);
+	if (err) goto out_firm;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->add_dev_support_attr);
+	if (err) goto out_version;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->manufacturer_id_attr);
+	if (err) goto out_add_dev;
+	err = device_create_file(&bmc->dev->dev,
+			   &bmc->product_id_attr);
+	if (err) goto out_manu;
+	if (bmc->id.aux_firmware_revision_set) {
+		err = device_create_file(&bmc->dev->dev,
+				   &bmc->aux_firmware_rev_attr);
+		if (err) goto out_prod_id;
+	}
+	if (bmc->guid_set) {
+		err = device_create_file(&bmc->dev->dev,
+				   &bmc->guid_attr);
+		if (err) goto out_aux_firm;
+	}
+
+	return 0;
+
+out_aux_firm:
+	if (bmc->id.aux_firmware_revision_set)
+		device_remove_file(&bmc->dev->dev,
+				   &bmc->aux_firmware_rev_attr);
+out_prod_id:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->product_id_attr);
+out_manu:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->manufacturer_id_attr);
+out_add_dev:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->add_dev_support_attr);
+out_version:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->version_attr);
+out_firm:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->firmware_rev_attr);
+out_rev:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->revision_attr);
+out_sdrs:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->provides_dev_sdrs_attr);
+out_devid:
+	device_remove_file(&bmc->dev->dev,
+			   &bmc->device_id_attr);
+out:
+	return err;
+}
+
 static int ipmi_bmc_register(ipmi_smi_t intf)
 {
 	int               rv;
@@ -2051,7 +2130,6 @@
 		bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
 		bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
 
-
 		bmc->revision_attr.attr.name = "revision";
 		bmc->revision_attr.attr.owner = THIS_MODULE;
 		bmc->revision_attr.attr.mode = S_IRUGO;
@@ -2093,28 +2171,14 @@
 		bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
 		bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
 
-		device_create_file(&bmc->dev->dev,
-				   &bmc->device_id_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->provides_dev_sdrs_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->revision_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->firmware_rev_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->version_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->add_dev_support_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->manufacturer_id_attr);
-		device_create_file(&bmc->dev->dev,
-				   &bmc->product_id_attr);
-		if (bmc->id.aux_firmware_revision_set)
-			device_create_file(&bmc->dev->dev,
-					   &bmc->aux_firmware_rev_attr);
-		if (bmc->guid_set)
-			device_create_file(&bmc->dev->dev,
-					   &bmc->guid_attr);
+		rv = create_files(bmc);
+		if (rv) {
+			mutex_lock(&ipmidriver_mutex);
+			platform_device_unregister(bmc->dev);
+			mutex_unlock(&ipmidriver_mutex);
+
+			return rv;
+		}
 
 		printk(KERN_INFO
 		       "ipmi: Found new BMC (man_id: 0x%6.6x, "
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index b106c45..e5cfb1f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -872,7 +872,7 @@
 	add_timer(&(smi_info->si_timer));
 }
 
-static irqreturn_t si_irq_handler(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t si_irq_handler(int irq, void *data)
 {
 	struct smi_info *smi_info = data;
 	unsigned long   flags;
@@ -899,14 +899,14 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t si_bt_irq_handler(int irq, void *data)
 {
 	struct smi_info *smi_info = data;
 	/* We need to clear the IRQ flag for the BT interface. */
 	smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG,
 			     IPMI_BT_INTMASK_CLEAR_IRQ_BIT
 			     | IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
-	return si_irq_handler(irq, data, regs);
+	return si_irq_handler(irq, data);
 }
 
 static int smi_start_processing(void       *send_info,
@@ -1789,7 +1789,7 @@
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return ENOMEM;
+		return -ENOMEM;
 
 	info->addr_source = "PCI";
 
@@ -1810,7 +1810,7 @@
 		kfree(info);
 		printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n",
 		       pci_name(pdev), class_type);
-		return ENOMEM;
+		return -ENOMEM;
 	}
 
 	rv = pci_enable_device(pdev);
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index accaaf1..73f759e 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -903,7 +903,7 @@
 
 #ifdef HAVE_NMI_HANDLER
 static int
-ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
+ipmi_nmi(void *dev_id, int cpu, int handled)
 {
         /* If we are not expecting a timeout, ignore it. */
 	if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index ea2bbf8..e9e9bf3 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -546,7 +546,7 @@
  *	Main interrupt handler routine
  */
 
-static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t isicom_interrupt(int irq, void *dev_id)
 {
 	struct isi_board *card = dev_id;
 	struct isi_port *port;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index d6e0315..ffdf9df 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -686,37 +686,37 @@
 static void	stli_ecpinit(stlibrd_t *brdp);
 static void	stli_ecpenable(stlibrd_t *brdp);
 static void	stli_ecpdisable(stlibrd_t *brdp);
-static char	*stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_ecpreset(stlibrd_t *brdp);
 static void	stli_ecpintr(stlibrd_t *brdp);
 static void	stli_ecpeiinit(stlibrd_t *brdp);
 static void	stli_ecpeienable(stlibrd_t *brdp);
 static void	stli_ecpeidisable(stlibrd_t *brdp);
-static char	*stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_ecpeireset(stlibrd_t *brdp);
 static void	stli_ecpmcenable(stlibrd_t *brdp);
 static void	stli_ecpmcdisable(stlibrd_t *brdp);
-static char	*stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_ecpmcreset(stlibrd_t *brdp);
 static void	stli_ecppciinit(stlibrd_t *brdp);
-static char	*stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_ecppcireset(stlibrd_t *brdp);
 
 static void	stli_onbinit(stlibrd_t *brdp);
 static void	stli_onbenable(stlibrd_t *brdp);
 static void	stli_onbdisable(stlibrd_t *brdp);
-static char	*stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_onbreset(stlibrd_t *brdp);
 static void	stli_onbeinit(stlibrd_t *brdp);
 static void	stli_onbeenable(stlibrd_t *brdp);
 static void	stli_onbedisable(stlibrd_t *brdp);
-static char	*stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_onbereset(stlibrd_t *brdp);
 static void	stli_bbyinit(stlibrd_t *brdp);
-static char	*stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_bbyreset(stlibrd_t *brdp);
 static void	stli_stalinit(stlibrd_t *brdp);
-static char	*stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_stalreset(stlibrd_t *brdp);
 
 static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
@@ -1566,7 +1566,7 @@
 
 	len = MIN(len, cooksize);
 	count = 0;
-	shbuf = (char *) EBRDGETMEMPTR(brdp, portp->txoffset);
+	shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
 	buf = stli_txcookbuf;
 
 	while (len > 0) {
@@ -2948,9 +2948,9 @@
 
 /*****************************************************************************/
 
-static char *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void *ptr;
+	void __iomem *ptr;
 	unsigned char val;
 
 	if (offset > brdp->memsize) {
@@ -3022,9 +3022,9 @@
 
 /*****************************************************************************/
 
-static char *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void		*ptr;
+	void __iomem *ptr;
 	unsigned char	val;
 
 	if (offset > brdp->memsize) {
@@ -3074,9 +3074,9 @@
 
 /*****************************************************************************/
 
-static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void *ptr;
+	void __iomem *ptr;
 	unsigned char val;
 
 	if (offset > brdp->memsize) {
@@ -3119,9 +3119,9 @@
 
 /*****************************************************************************/
 
-static char *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void		*ptr;
+	void __iomem *ptr;
 	unsigned char	val;
 
 	if (offset > brdp->memsize) {
@@ -3185,9 +3185,9 @@
 
 /*****************************************************************************/
 
-static char *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void	*ptr;
+	void __iomem *ptr;
 
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
@@ -3250,9 +3250,9 @@
 
 /*****************************************************************************/
 
-static char *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void *ptr;
+	void __iomem *ptr;
 	unsigned char val;
 
 	if (offset > brdp->memsize) {
@@ -3300,9 +3300,9 @@
 
 /*****************************************************************************/
 
-static char *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void *ptr;
+	void __iomem *ptr;
 	unsigned char val;
 
 	BUG_ON(offset > brdp->memsize);
@@ -3337,7 +3337,7 @@
 
 /*****************************************************************************/
 
-static char *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
 	BUG_ON(offset > brdp->memsize);
 	return brdp->membase + (offset % STAL_PAGESIZE);
@@ -3876,7 +3876,7 @@
 			continue;
 
 		if (brdp->brdtype == BRD_ECPE) {
-			ecpsigp = (cdkecpsig_t __iomem *) stli_ecpeigetmemptr(brdp,
+			ecpsigp = stli_ecpeigetmemptr(brdp,
 				CDK_SIGADDR, __LINE__);
 			memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
 			if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
@@ -4184,7 +4184,7 @@
 static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
 {
 	unsigned long flags;
-	void *memptr;
+	void __iomem *memptr;
 	stlibrd_t *brdp;
 	int brdnr, size, n;
 	void *p;
@@ -4214,7 +4214,7 @@
 	while (size > 0) {
 		spin_lock_irqsave(&brd_lock, flags);
 		EBRDENABLE(brdp);
-		memptr = (void *) EBRDGETMEMPTR(brdp, off);
+		memptr = EBRDGETMEMPTR(brdp, off);
 		n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
 		n = MIN(n, PAGE_SIZE);
 		memcpy_fromio(p, memptr, n);
@@ -4247,7 +4247,7 @@
 static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
 {
 	unsigned long flags;
-	void *memptr;
+	void __iomem *memptr;
 	stlibrd_t *brdp;
 	char __user *chbuf;
 	int brdnr, size, n;
@@ -4287,7 +4287,7 @@
 		}
 		spin_lock_irqsave(&brd_lock, flags);
 		EBRDENABLE(brdp);
-		memptr = (void *) EBRDGETMEMPTR(brdp, off);
+		memptr = EBRDGETMEMPTR(brdp, off);
 		memcpy_toio(memptr, p, n);
 		EBRDDISABLE(brdp);
 		spin_unlock_irqrestore(&brd_lock, flags);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index e201166..20b6c8b 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -32,6 +32,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #include <linux/kbd_kern.h>
 #include <linux/kbd_diacr.h>
@@ -77,7 +78,7 @@
 	k_slock,	k_dead2,	k_brl,		k_ignore
 
 typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
-			    char up_flag, struct pt_regs *regs);
+			    char up_flag);
 static k_handler_fn K_HANDLERS;
 static k_handler_fn *k_handler[16] = { K_HANDLERS };
 
@@ -88,7 +89,7 @@
 	fn_boot_it,	fn_caps_on,	fn_compose,	fn_SAK,\
 	fn_dec_console, fn_inc_console, fn_spawn_con,	fn_bare_num
 
-typedef void (fn_handler_fn)(struct vc_data *vc, struct pt_regs *regs);
+typedef void (fn_handler_fn)(struct vc_data *vc);
 static fn_handler_fn FN_HANDLERS;
 static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
 
@@ -428,7 +429,7 @@
 /*
  * Special function handlers
  */
-static void fn_enter(struct vc_data *vc, struct pt_regs *regs)
+static void fn_enter(struct vc_data *vc)
 {
 	if (diacr) {
 		if (kbd->kbdmode == VC_UNICODE)
@@ -442,27 +443,28 @@
 		put_queue(vc, 10);
 }
 
-static void fn_caps_toggle(struct vc_data *vc, struct pt_regs *regs)
+static void fn_caps_toggle(struct vc_data *vc)
 {
 	if (rep)
 		return;
 	chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 }
 
-static void fn_caps_on(struct vc_data *vc, struct pt_regs *regs)
+static void fn_caps_on(struct vc_data *vc)
 {
 	if (rep)
 		return;
 	set_vc_kbd_led(kbd, VC_CAPSLOCK);
 }
 
-static void fn_show_ptregs(struct vc_data *vc, struct pt_regs *regs)
+static void fn_show_ptregs(struct vc_data *vc)
 {
+	struct pt_regs *regs = get_irq_regs();
 	if (regs)
 		show_regs(regs);
 }
 
-static void fn_hold(struct vc_data *vc, struct pt_regs *regs)
+static void fn_hold(struct vc_data *vc)
 {
 	struct tty_struct *tty = vc->vc_tty;
 
@@ -480,12 +482,12 @@
 		stop_tty(tty);
 }
 
-static void fn_num(struct vc_data *vc, struct pt_regs *regs)
+static void fn_num(struct vc_data *vc)
 {
 	if (vc_kbd_mode(kbd,VC_APPLIC))
 		applkey(vc, 'P', 1);
 	else
-		fn_bare_num(vc, regs);
+		fn_bare_num(vc);
 }
 
 /*
@@ -494,19 +496,19 @@
  * Bind this to NumLock if you prefer that the NumLock key always
  * changes the NumLock flag.
  */
-static void fn_bare_num(struct vc_data *vc, struct pt_regs *regs)
+static void fn_bare_num(struct vc_data *vc)
 {
 	if (!rep)
 		chg_vc_kbd_led(kbd, VC_NUMLOCK);
 }
 
-static void fn_lastcons(struct vc_data *vc, struct pt_regs *regs)
+static void fn_lastcons(struct vc_data *vc)
 {
 	/* switch to the last used console, ChN */
 	set_console(last_console);
 }
 
-static void fn_dec_console(struct vc_data *vc, struct pt_regs *regs)
+static void fn_dec_console(struct vc_data *vc)
 {
 	int i, cur = fg_console;
 
@@ -523,7 +525,7 @@
 	set_console(i);
 }
 
-static void fn_inc_console(struct vc_data *vc, struct pt_regs *regs)
+static void fn_inc_console(struct vc_data *vc)
 {
 	int i, cur = fg_console;
 
@@ -540,7 +542,7 @@
 	set_console(i);
 }
 
-static void fn_send_intr(struct vc_data *vc, struct pt_regs *regs)
+static void fn_send_intr(struct vc_data *vc)
 {
 	struct tty_struct *tty = vc->vc_tty;
 
@@ -550,37 +552,37 @@
 	con_schedule_flip(tty);
 }
 
-static void fn_scroll_forw(struct vc_data *vc, struct pt_regs *regs)
+static void fn_scroll_forw(struct vc_data *vc)
 {
 	scrollfront(vc, 0);
 }
 
-static void fn_scroll_back(struct vc_data *vc, struct pt_regs *regs)
+static void fn_scroll_back(struct vc_data *vc)
 {
 	scrollback(vc, 0);
 }
 
-static void fn_show_mem(struct vc_data *vc, struct pt_regs *regs)
+static void fn_show_mem(struct vc_data *vc)
 {
 	show_mem();
 }
 
-static void fn_show_state(struct vc_data *vc, struct pt_regs *regs)
+static void fn_show_state(struct vc_data *vc)
 {
 	show_state();
 }
 
-static void fn_boot_it(struct vc_data *vc, struct pt_regs *regs)
+static void fn_boot_it(struct vc_data *vc)
 {
 	ctrl_alt_del();
 }
 
-static void fn_compose(struct vc_data *vc, struct pt_regs *regs)
+static void fn_compose(struct vc_data *vc)
 {
 	dead_key_next = 1;
 }
 
-static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
+static void fn_spawn_con(struct vc_data *vc)
 {
 	spin_lock(&vt_spawn_con.lock);
 	if (vt_spawn_con.pid)
@@ -591,7 +593,7 @@
 	spin_unlock(&vt_spawn_con.lock);
 }
 
-static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
+static void fn_SAK(struct vc_data *vc)
 {
 	struct tty_struct *tty = vc->vc_tty;
 
@@ -604,7 +606,7 @@
 	reset_vc(vc);
 }
 
-static void fn_null(struct vc_data *vc, struct pt_regs *regs)
+static void fn_null(struct vc_data *vc)
 {
 	compute_shiftstate();
 }
@@ -612,11 +614,11 @@
 /*
  * Special key handlers
  */
-static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
 {
 }
 
-static void k_spec(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	if (up_flag)
 		return;
@@ -626,15 +628,15 @@
 	     kbd->kbdmode == VC_MEDIUMRAW) &&
 	     value != KVAL(K_SAK))
 		return;		/* SAK is allowed even in raw mode */
-	fn_handler[value](vc, regs);
+	fn_handler[value](vc);
 }
 
-static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
 }
 
-static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
+static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
 {
 	if (up_flag)
 		return;		/* no action, if this is a key release */
@@ -658,41 +660,41 @@
  * dead keys modifying the same character. Very useful
  * for Vietnamese.
  */
-static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
+static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
 {
 	if (up_flag)
 		return;
 	diacr = (diacr ? handle_diacr(vc, value) : value);
 }
 
-static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
 {
-	k_unicode(vc, value, up_flag, regs);
+	k_unicode(vc, value, up_flag);
 }
 
-static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
 {
-	k_deadunicode(vc, value, up_flag, regs);
+	k_deadunicode(vc, value, up_flag);
 }
 
 /*
  * Obsolete - for backwards compatibility only
  */
-static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
 	value = ret_diacr[value];
-	k_deadunicode(vc, value, up_flag, regs);
+	k_deadunicode(vc, value, up_flag);
 }
 
-static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	if (up_flag)
 		return;
 	set_console(value);
 }
 
-static void k_fn(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	unsigned v;
 
@@ -706,7 +708,7 @@
 		printk(KERN_ERR "k_fn called with value=%d\n", value);
 }
 
-static void k_cur(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	static const char *cur_chars = "BDCA";
 
@@ -715,7 +717,7 @@
 	applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
 }
 
-static void k_pad(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	static const char pad_chars[] = "0123456789+-*/\015,.?()#";
 	static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
@@ -733,34 +735,34 @@
 		switch (value) {
 			case KVAL(K_PCOMMA):
 			case KVAL(K_PDOT):
-				k_fn(vc, KVAL(K_REMOVE), 0, regs);
+				k_fn(vc, KVAL(K_REMOVE), 0);
 				return;
 			case KVAL(K_P0):
-				k_fn(vc, KVAL(K_INSERT), 0, regs);
+				k_fn(vc, KVAL(K_INSERT), 0);
 				return;
 			case KVAL(K_P1):
-				k_fn(vc, KVAL(K_SELECT), 0, regs);
+				k_fn(vc, KVAL(K_SELECT), 0);
 				return;
 			case KVAL(K_P2):
-				k_cur(vc, KVAL(K_DOWN), 0, regs);
+				k_cur(vc, KVAL(K_DOWN), 0);
 				return;
 			case KVAL(K_P3):
-				k_fn(vc, KVAL(K_PGDN), 0, regs);
+				k_fn(vc, KVAL(K_PGDN), 0);
 				return;
 			case KVAL(K_P4):
-				k_cur(vc, KVAL(K_LEFT), 0, regs);
+				k_cur(vc, KVAL(K_LEFT), 0);
 				return;
 			case KVAL(K_P6):
-				k_cur(vc, KVAL(K_RIGHT), 0, regs);
+				k_cur(vc, KVAL(K_RIGHT), 0);
 				return;
 			case KVAL(K_P7):
-				k_fn(vc, KVAL(K_FIND), 0, regs);
+				k_fn(vc, KVAL(K_FIND), 0);
 				return;
 			case KVAL(K_P8):
-				k_cur(vc, KVAL(K_UP), 0, regs);
+				k_cur(vc, KVAL(K_UP), 0);
 				return;
 			case KVAL(K_P9):
-				k_fn(vc, KVAL(K_PGUP), 0, regs);
+				k_fn(vc, KVAL(K_PGUP), 0);
 				return;
 			case KVAL(K_P5):
 				applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
@@ -772,7 +774,7 @@
 		put_queue(vc, 10);
 }
 
-static void k_shift(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	int old_state = shift_state;
 
@@ -813,7 +815,7 @@
 	}
 }
 
-static void k_meta(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	if (up_flag)
 		return;
@@ -825,7 +827,7 @@
 		put_queue(vc, value | 0x80);
 }
 
-static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	int base;
 
@@ -847,16 +849,16 @@
 		npadch = npadch * base + value;
 }
 
-static void k_lock(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	if (up_flag || rep)
 		return;
 	chg_vc_kbd_lock(kbd, value);
 }
 
-static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
 {
-	k_shift(vc, value, up_flag, regs);
+	k_shift(vc, value, up_flag);
 	if (up_flag || rep)
 		return;
 	chg_vc_kbd_slock(kbd, value);
@@ -876,25 +878,25 @@
 MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
 module_param(brl_nbchords, uint, 0644);
 
-static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag, struct pt_regs *regs)
+static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
 {
 	static unsigned long chords;
 	static unsigned committed;
 
 	if (!brl_nbchords)
-		k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag, regs);
+		k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
 	else {
 		committed |= pattern;
 		chords++;
 		if (chords == brl_nbchords) {
-			k_unicode(vc, BRL_UC_ROW | committed, up_flag, regs);
+			k_unicode(vc, BRL_UC_ROW | committed, up_flag);
 			chords = 0;
 			committed = 0;
 		}
 	}
 }
 
-static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
 {
 	static unsigned pressed,committing;
 	static unsigned long releasestart;
@@ -906,7 +908,7 @@
 	}
 
 	if (!value) {
-		k_unicode(vc, BRL_UC_ROW, up_flag, regs);
+		k_unicode(vc, BRL_UC_ROW, up_flag);
 		return;
 	}
 
@@ -923,13 +925,13 @@
 			pressed &= ~(1 << (value - 1));
 			if (!pressed) {
 				if (committing) {
-					k_brlcommit(vc, committing, 0, regs);
+					k_brlcommit(vc, committing, 0);
 					committing = 0;
 				}
 			}
 		} else {
 			if (committing) {
-				k_brlcommit(vc, committing, 0, regs);
+				k_brlcommit(vc, committing, 0);
 				committing = 0;
 			}
 			pressed &= ~(1 << (value - 1));
@@ -1133,8 +1135,7 @@
 		put_queue(vc, data);
 }
 
-static void kbd_keycode(unsigned int keycode, int down,
-			int hw_raw, struct pt_regs *regs)
+static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned short keysym, *key_map;
@@ -1181,7 +1182,7 @@
 	if (sysrq_down && !down && keycode == sysrq_alt_use)
 		sysrq_down = 0;
 	if (sysrq_down && down && !rep) {
-		handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
+		handle_sysrq(kbd_sysrq_xlate[keycode], tty);
 		return;
 	}
 #endif
@@ -1267,7 +1268,7 @@
 		}
 	}
 
-	(*k_handler[type])(vc, keysym & 0xff, !down, regs);
+	(*k_handler[type])(vc, keysym & 0xff, !down);
 
 	if (type != KT_SLOCK)
 		kbd->slockstate = 0;
@@ -1279,7 +1280,7 @@
 	if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
 		kbd_rawcode(value);
 	if (event_type == EV_KEY)
-		kbd_keycode(event_code, value, HW_RAW(handle->dev), handle->dev->regs);
+		kbd_keycode(event_code, value, HW_RAW(handle->dev));
 	tasklet_schedule(&keyboard_tasklet);
 	do_poke_blanked_console = 1;
 	schedule_console_callback();
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 6363547..0afb7ba 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -516,11 +516,10 @@
  * mbcs_completion_intr_handler - Primary completion handler.
  * @irq: irq
  * @arg: soft struct for device
- * @ep: regs
  *
  */
 static irqreturn_t
-mbcs_completion_intr_handler(int irq, void *arg, struct pt_regs *ep)
+mbcs_completion_intr_handler(int irq, void *arg)
 {
 	struct mbcs_soft *soft = (struct mbcs_soft *)arg;
 	void *mmr_base;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 6511012..5547337 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -26,6 +26,7 @@
 #include <linux/backing-dev.h>
 #include <linux/bootmem.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/pfn.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -292,8 +293,8 @@
 {
 	unsigned long pfn;
 
-	/* Turn a kernel-virtual address into a physical page frame */
-	pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
+	/* Turn a pfn offset into an absolute pfn */
+	pfn = PFN_DOWN(virt_to_phys((void *)PAGE_OFFSET)) + vma->vm_pgoff;
 
 	/*
 	 * RED-PEN: on some architectures there is more mapped memory
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 1f0f2b6..22b9905 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -422,7 +422,6 @@
  * mmtimer_interrupt - timer interrupt handler
  * @irq: irq received
  * @dev_id: device the irq came from
- * @regs: register state upon receipt of the interrupt
  *
  * Called when one of the comarators matches the counter, This
  * routine will send signals to processes that have requested
@@ -433,7 +432,7 @@
  * registers.
  */
 static irqreturn_t
-mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+mmtimer_interrupt(int irq, void *dev_id)
 {
 	int i;
 	unsigned long expires = 0;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index b401383..96cb1f0 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -130,6 +130,7 @@
 typedef struct _moxa_pci_devinfo {
 	ushort busNum;
 	ushort devNum;
+	struct pci_dev *pdev;
 } moxa_pci_devinfo;
 
 typedef struct _moxa_board_conf {
@@ -324,6 +325,9 @@
 	board->busType = MOXA_BUS_TYPE_PCI;
 	board->pciInfo.busNum = p->bus->number;
 	board->pciInfo.devNum = p->devfn >> 3;
+	board->pciInfo.pdev = p;
+	/* don't lose the reference in the next pci_get_device iteration */
+	pci_dev_get(p);
 
 	return (0);
 }
@@ -493,6 +497,11 @@
 	if (tty_unregister_driver(moxaDriver))
 		printk("Couldn't unregister MOXA Intellio family serial driver\n");
 	put_tty_driver(moxaDriver);
+
+	for (i = 0; i < MAX_BOARDS; i++)
+		if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI)
+			pci_dev_put(moxa_boards[i].pciInfo.pdev);
+
 	if (verbose)
 		printk("Done\n");
 }
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index cc3e54d..f282976 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -95,14 +95,14 @@
 }
 
 
-static irqreturn_t UartInterrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t UartInterrupt(int irq, void *dev_id)
 {
 	PRINTK_3(TRACE_TP3780I,
 		"tp3780i::UartInterrupt entry irq %x dev_id %p\n", irq, dev_id);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t DspInterrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t DspInterrupt(int irq, void *dev_id)
 {
 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
 	DSP_3780I_CONFIG_SETTINGS *pSettings = &pDrvData->rBDData.rDspSettings;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 8253fca..048d911 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -407,7 +407,7 @@
 static void mxser_start(struct tty_struct *);
 static void mxser_hangup(struct tty_struct *);
 static void mxser_rs_break(struct tty_struct *, int);
-static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t mxser_interrupt(int, void *);
 static void mxser_receive_chars(struct mxser_struct *, int *);
 static void mxser_transmit_chars(struct mxser_struct *);
 static void mxser_check_modem_status(struct mxser_struct *, int);
@@ -1916,7 +1916,7 @@
 /*
  * This is the serial driver's generic interrupt routine
  */
-static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mxser_interrupt(int irq, void *dev_id)
 {
 	int status, iir, i;
 	struct mxser_struct *info;
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index ea1aa77..2d26497 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -144,7 +144,7 @@
  *  increments the counter.
  */ 
 
-static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t button_handler (int irq, void *dev_id)
 {
 	if (button_press_count) {
 		del_timer (&button_timer);
diff --git a/drivers/char/nwbutton.h b/drivers/char/nwbutton.h
index ddb7b92..c3ebc16 100644
--- a/drivers/char/nwbutton.h
+++ b/drivers/char/nwbutton.h
@@ -25,7 +25,7 @@
 /* Function prototypes: */
 
 static void button_sequence_finished (unsigned long parameters);
-static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t button_handler (int irq, void *dev_id);
 int button_init (void);
 int button_add_callback (void (*callback) (void), int count);
 int button_del_callback (void (*callback) (void));
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 73e3242..1a0bc30 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -416,7 +416,7 @@
 static int  rx_alloc_buffers(MGSLPC_INFO *info);
 static void rx_free_buffers(MGSLPC_INFO *info);
 
-static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t mgslpc_isr(int irq, void *dev_id);
 
 /*
  * Bottom half interrupt handlers
@@ -1234,9 +1234,8 @@
  * 
  * irq     interrupt number that caused interrupt
  * dev_id  device ID supplied during interrupt registration
- * regs    interrupted processor context
  */
-static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t mgslpc_isr(int irq, void *dev_id)
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id;
 	unsigned short isr;
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 520d2cf..efc485e 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -269,7 +269,7 @@
 	return bytes_written;
 }
 
-static void pp_irq (int irq, void * private, struct pt_regs * unused)
+static void pp_irq (int irq, void * private)
 {
 	struct pp_struct * pp = (struct pp_struct *) private;
 
diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c
deleted file mode 100644
index 9d134e9..0000000
--- a/drivers/char/qtronix.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *	Qtronix 990P infrared keyboard driver.
- *
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
- *
- *
- *  The bottom portion of this driver was take from 
- *  pc_keyb.c  Please see that file for copyrights.
- *
- *  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.
- */
-
-
-/* 
- * NOTE:  
- *
- *	This driver has only been tested with the Consumer IR
- *	port of the ITE 8172 system controller.
- *
- *	You do not need this driver if you are using the ps/2 or
- *	USB adapter that the keyboard ships with.  You only need 
- *	this driver if your board has a IR port and the keyboard
- *	data is being sent directly to the IR.  In that case,
- *	you also need some low-level IR support. See it8172_cir.c.
- *	
- */
-
-#ifdef CONFIG_QTRONIX_KEYBOARD
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-
-#include <asm/it8172/it8172.h>
-#include <asm/it8172/it8172_int.h>
-#include <asm/it8172/it8172_cir.h>
-
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/delay.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/kbd_kern.h>
-#include <linux/smp_lock.h>
-#include <asm/io.h>
-#include <linux/pc_keyb.h>
-
-#include <asm/keyboard.h>
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#define leading1 0
-#define leading2 0xF
-
-#define KBD_CIR_PORT 0
-#define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back) in */
-
-static int data_index;
-struct cir_port *cir;
-static unsigned char kbdbytes[5];
-static unsigned char cir_data[32]; /* we only need 16 chars */
-
-static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs);
-static int handle_data(unsigned char *p_data);
-static inline void handle_mouse_event(unsigned char scancode);
-static inline void handle_keyboard_event(unsigned char scancode, int down);
-static int __init psaux_init(void);
-
-static struct aux_queue *queue;	/* Mouse data buffer. */
-static int aux_count = 0;
-
-/*
- * Keys accessed through the 'Fn' key
- * The Fn key does not produce a key-up sequence. So, the first
- * time the user presses it, it will be key-down event. The key
- * stays down until the user presses it again.
- */
-#define NUM_FN_KEYS 56
-static unsigned char fn_keys[NUM_FN_KEYS] = {
-	0,0,0,0,0,0,0,0,        /* 0 7   */
-	8,9,10,93,0,0,0,0,      /* 8 15  */
-	0,0,0,0,0,0,0,5,        /* 16 23 */
-	6,7,91,0,0,0,0,0,       /* 24 31 */
-	0,0,0,0,0,2,3,4,        /* 32 39 */
-	92,0,0,0,0,0,0,0,       /* 40 47 */
-	0,0,0,0,11,0,94,95        /* 48 55 */
-
-};
-
-void __init init_qtronix_990P_kbd(void)
-{
-	int retval;
-
-	cir = (struct cir_port *)kmalloc(sizeof(struct cir_port), GFP_KERNEL);
-	if (!cir) {
-		printk("Unable to initialize Qtronix keyboard\n");
-		return;
-	}
-
-	/* 
-	 * revisit
-	 * this should be programmable, somehow by the, by the user.
-	 */
-	cir->port = KBD_CIR_PORT;
-	cir->baud_rate = 0x1d;
-	cir->rdwos = 0;
-	cir->rxdcr = 0x3;
-	cir->hcfs = 0;
-	cir->fifo_tl = 0;
-	cir->cfq = 0x1d;
-	cir_port_init(cir);
-
-	retval = request_irq(IT8172_CIR0_IRQ, kbd_int_handler, 
-			(unsigned long )(IRQF_DISABLED|IRQF_SHARED),
-			(const char *)"Qtronix IR Keyboard", (void *)cir);
-
-	if (retval) {
-		printk("unable to allocate cir %d irq %d\n", 
-				cir->port, IT8172_CIR0_IRQ);
-	}
-#ifdef CONFIG_PSMOUSE
-	psaux_init();
-#endif
-}
-
-static inline unsigned char BitReverse(unsigned short key)
-{
-	unsigned char rkey = 0;
-	rkey |= (key & 0x1) << 7;
-	rkey |= (key & 0x2) << 5;
-	rkey |= (key & 0x4) << 3;
-	rkey |= (key & 0x8) << 1;
-	rkey |= (key & 0x10) >> 1;
-	rkey |= (key & 0x20) >> 3;
-	rkey |= (key & 0x40) >> 5;
-	rkey |= (key & 0x80) >> 7;
-	return rkey;
-
-}
-
-
-static inline u_int8_t UpperByte(u_int8_t data)
-{
-	return (data >> 4);
-}
-
-
-static inline u_int8_t LowerByte(u_int8_t data)
-{
-	return (data & 0xF);
-}
-
-
-int CheckSumOk(u_int8_t byte1, u_int8_t byte2, 
-		u_int8_t byte3, u_int8_t byte4, u_int8_t byte5)
-{
-	u_int8_t CheckSum;
-
-	CheckSum = (byte1 & 0x0F) + byte2 + byte3 + byte4 + byte5;
-	if ( LowerByte(UpperByte(CheckSum) + LowerByte(CheckSum)) != UpperByte(byte1) )
-		return 0;
-	else
-		return 1;
-}
-
-
-static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct cir_port *cir;
-	int j;
-	unsigned char int_status;
-
-	cir = (struct cir_port *)dev_id;
-	int_status = get_int_status(cir);
-	if (int_status & 0x4) {
-		clear_fifo(cir);
-		return;
-	}
-
-	while (cir_get_rx_count(cir)) {
-
-		cir_data[data_index] = cir_read_data(cir);
-
-		if (data_index == 0) {/* expecting first byte */
-			if (cir_data[data_index] != leading1) {
-				//printk("!leading byte %x\n", cir_data[data_index]);
-				set_rx_active(cir);
-				clear_fifo(cir);
-				continue;
-			}
-		}
-		if (data_index == 1) {
-			if ((cir_data[data_index] & 0xf) != leading2) {
-				set_rx_active(cir);
-				data_index = 0; /* start over */
-				clear_fifo(cir);
-				continue;
-			}
-		}
-
-		if ( (cir_data[data_index] == 0xff)) { /* last byte */
-			//printk("data_index %d\n", data_index);
-			set_rx_active(cir);
-#if 0
-			for (j=0; j<=data_index; j++) {
-				printk("rx_data %d:  %x\n", j, cir_data[j]);
-			}
-#endif
-			data_index = 0;
-			handle_data(cir_data);
-			return;
-		}
-		else if (data_index>16) {
-			set_rx_active(cir);
-#if 0
-			printk("warning: data_index %d\n", data_index);
-			for (j=0; j<=data_index; j++) {
-				printk("rx_data %d:  %x\n", j, cir_data[j]);
-			}
-#endif
-			data_index = 0;
-			clear_fifo(cir);
-			return;
-		}
-		data_index++;
-	}
-}
-
-
-#define NUM_KBD_BYTES 5
-static int handle_data(unsigned char *p_data)
-{
-	u_int32_t bit_bucket;
-	u_int32_t i, j;
-	u_int32_t got_bits, next_byte;
-	int down = 0;
-
-	/* Reorganize the bit stream */
-	for (i=0; i<16; i++)
-		p_data[i] = BitReverse(~p_data[i]);
-
-	/* 
-	 * We've already previously checked that p_data[0]
-	 * is equal to leading1 and that (p_data[1] & 0xf)
-	 * is equal to leading2. These twelve bits are the
-	 * leader code.  We can now throw them away (the 12
-	 * bits) and continue parsing the stream.
-	 */
-	bit_bucket = p_data[1] << 12;
-	got_bits = 4;
-	next_byte = 2;
-
-	/* 
-	 * Process four bits at a time
-	 */
-	for (i=0; i<NUM_KBD_BYTES; i++) {
-
-		kbdbytes[i]=0;
-
-		for (j=0; j<8; j++) /* 8 bits per byte */
-		{
-			if (got_bits < 4) {
-				bit_bucket |= (p_data[next_byte++] << (8 - got_bits));
-				got_bits += 8;
-			}
-
-			if ((bit_bucket & 0xF000) == 0x8000) { 
-				/* Convert 1000b to 1 */
-				kbdbytes[i] = 0x80 | (kbdbytes[i] >> 1);
-				got_bits -= 4;
-				bit_bucket = bit_bucket << 4;
-			}
-			else if ((bit_bucket & 0xC000) == 0x8000) {
-				/* Convert 10b to 0 */
-				kbdbytes[i] =  kbdbytes[i] >> 1;
-				got_bits -= 2;
-				bit_bucket = bit_bucket << 2;
-			}
-			else {
-				/* bad serial stream */
-				return 1;
-			}
-
-			if (next_byte > 16) {
-				//printk("error: too many bytes\n");
-				return 1;
-			}
-		}
-	}
-
-
-	if (!CheckSumOk(kbdbytes[0], kbdbytes[1], 
-				kbdbytes[2], kbdbytes[3], kbdbytes[4])) {
-		//printk("checksum failed\n");
-		return 1;
-	}
-
-	if (kbdbytes[1] & 0x08) {
-		//printk("m: %x %x %x\n", kbdbytes[1], kbdbytes[2], kbdbytes[3]);
-		handle_mouse_event(kbdbytes[1]);
-		handle_mouse_event(kbdbytes[2]);
-		handle_mouse_event(kbdbytes[3]);
-	}
-	else {
-		if (kbdbytes[2] == 0) down = 1;
-#if 0
-		if (down)
-			printk("down %d\n", kbdbytes[3]);
-		else
-			printk("up %d\n", kbdbytes[3]);
-#endif
-		handle_keyboard_event(kbdbytes[3], down);
-	}
-	return 0;
-}
-
-
-DEFINE_SPINLOCK(kbd_controller_lock);
-static unsigned char handle_kbd_event(void);
-
-
-int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
-	printk("kbd_setkeycode scancode %x keycode %x\n", scancode, keycode);
-	return 0;
-}
-
-int kbd_getkeycode(unsigned int scancode)
-{
-	return scancode;
-}
-
-
-int kbd_translate(unsigned char scancode, unsigned char *keycode,
-		    char raw_mode)
-{
-	static int prev_scancode = 0;
-
-	if (scancode == 0x00 || scancode == 0xff) {
-		prev_scancode = 0;
-		return 0;
-	}
-
-	/* todo */
-	if (!prev_scancode && scancode == 160) { /* Fn key down */
-		//printk("Fn key down\n");
-		prev_scancode = 160;
-		return 0;
-	}
-	else if (prev_scancode && scancode == 160) { /* Fn key up */
-		//printk("Fn key up\n");
-		prev_scancode = 0;
-		return 0;
-	}
-
-	/* todo */
-	if (prev_scancode == 160) {
-		if (scancode <= NUM_FN_KEYS) {
-			*keycode = fn_keys[scancode];
-			//printk("fn keycode %d\n", *keycode);
-		}
-		else
-			return 0;
-	} 
-	else if (scancode <= 127) {
-		*keycode = scancode;
-	}
-	else
-		return 0;
-
-
- 	return 1;
-}
-
-char kbd_unexpected_up(unsigned char keycode)
-{
-	//printk("kbd_unexpected_up\n");
-	return 0;
-}
-
-static unsigned char kbd_exists = 1;
-
-static inline void handle_keyboard_event(unsigned char scancode, int down)
-{
-	kbd_exists = 1;
-	handle_scancode(scancode, down);
-	tasklet_schedule(&keyboard_tasklet);
-}	
-
-
-void kbd_leds(unsigned char leds)
-{
-}
-
-/* dummy */
-void kbd_init_hw(void)
-{
-}
-
-
-
-static inline void handle_mouse_event(unsigned char scancode)
-{
-	if(scancode == AUX_RECONNECT){
-		queue->head = queue->tail = 0;  /* Flush input queue */
-	//	__aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
-		return;
-	}
-
-	if (aux_count) {
-		int head = queue->head;
-
-		queue->buf[head] = scancode;
-		head = (head + 1) & (AUX_BUF_SIZE-1);
-		if (head != queue->tail) {
-			queue->head = head;
-			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
-			wake_up_interruptible(&queue->proc_list);
-		}
-	}
-}
-
-static unsigned char get_from_queue(void)
-{
-	unsigned char result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&kbd_controller_lock, flags);
-	result = queue->buf[queue->tail];
-	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
-	spin_unlock_irqrestore(&kbd_controller_lock, flags);
-	return result;
-}
-
-
-static inline int queue_empty(void)
-{
-	return queue->head == queue->tail;
-}
-
-static int fasync_aux(int fd, struct file *filp, int on)
-{
-	int retval;
-
-	//printk("fasync_aux\n");
-	retval = fasync_helper(fd, filp, on, &queue->fasync);
-	if (retval < 0)
-		return retval;
-	return 0;
-}
-
-
-/*
- * Random magic cookie for the aux device
- */
-#define AUX_DEV ((void *)queue)
-
-static int release_aux(struct inode * inode, struct file * file)
-{
-	fasync_aux(-1, file, 0);
-	aux_count--;
-	return 0;
-}
-
-static int open_aux(struct inode * inode, struct file * file)
-{
-	if (aux_count++) {
-		return 0;
-	}
-	queue->head = queue->tail = 0;		/* Flush input queue */
-	return 0;
-}
-
-/*
- * Put bytes from input queue to buffer.
- */
-
-static ssize_t read_aux(struct file * file, char * buffer,
-			size_t count, loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	ssize_t i = count;
-	unsigned char c;
-
-	if (queue_empty()) {
-		if (file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-		add_wait_queue(&queue->proc_list, &wait);
-repeat:
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (queue_empty() && !signal_pending(current)) {
-			schedule();
-			goto repeat;
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&queue->proc_list, &wait);
-	}
-	while (i > 0 && !queue_empty()) {
-		c = get_from_queue();
-		put_user(c, buffer++);
-		i--;
-	}
-	if (count-i) {
-		struct inode *inode = file->f_dentry->d_inode;
-		inode->i_atime = current_fs_time(inode->i_sb);
-		return count-i;
-	}
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-/*
- * Write to the aux device.
- */
-
-static ssize_t write_aux(struct file * file, const char * buffer,
-			 size_t count, loff_t *ppos)
-{
-	/*
-	 * The ITE boards this was tested on did not have the
-	 * transmit wires connected.
-	 */
-	return count;
-}
-
-static unsigned int aux_poll(struct file *file, poll_table * wait)
-{
-	poll_wait(file, &queue->proc_list, wait);
-	if (!queue_empty())
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-struct file_operations psaux_fops = {
-	.read		= read_aux,
-	.write		= write_aux,
-	.poll		= aux_poll,
-	.open		= open_aux,
-	.release	= release_aux,
-	.fasync		= fasync_aux,
-};
-
-/*
- * Initialize driver.
- */
-static struct miscdevice psaux_mouse = {
-	PSMOUSE_MINOR, "psaux", &psaux_fops
-};
-
-static int __init psaux_init(void)
-{
-	int retval;
-
-	retval = misc_register(&psaux_mouse);
-	if(retval < 0)
-		return retval;
-
-	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-	if (!queue) {
-		misc_deregister(&psaux_mouse);
-		return -ENOMEM;
-	}
-		
-	memset(queue, 0, sizeof(*queue));
-	queue->head = queue->tail = 0;
-	init_waitqueue_head(&queue->proc_list);
-
-	return 0;
-}
-module_init(init_qtronix_990P_kbd);
-#endif
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 07f47a0..eb6b13f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -645,6 +645,7 @@
 	add_timer_randomness(&input_timer_state,
 			     (type << 4) ^ code ^ (code >> 4) ^ value);
 }
+EXPORT_SYMBOL_GPL(add_input_randomness);
 
 void add_interrupt_randomness(int irq)
 {
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index 6b03918..9e7283b 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -88,7 +88,7 @@
 
 /* riointr.c */
 void RIOTxEnable(char *);
-void RIOServiceHost(struct rio_info *, struct Host *, int);
+void RIOServiceHost(struct rio_info *, struct Host *);
 int riotproc(struct rio_info *, struct ttystatics *, int, int);
 
 /* rioparam.c */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index ee2ddea..23d0681 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -44,6 +44,7 @@
 **    the host.
 */
 struct Host {
+	struct pci_dev *pdev;
 	unsigned char Type;		/* RIO_EISA, RIO_MCA, ... */
 	unsigned char Ivec;		/* POLLED or ivec number */
 	unsigned char Mode;		/* Control stuff */
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 202a3b0..7ac68cb 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -363,12 +363,12 @@
 }
 
 
-static irqreturn_t rio_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t rio_interrupt(int irq, void *ptr)
 {
 	struct Host *HostP;
 	func_enter();
 
-	HostP = (struct Host *) ptr;	/* &p->RIOHosts[(long)ptr]; */
+	HostP = ptr;			/* &p->RIOHosts[(long)ptr]; */
 	rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
 
 	/* AAargh! The order in which to do these things is essential and
@@ -402,7 +402,7 @@
 		return IRQ_HANDLED;
 	}
 
-	RIOServiceHost(p, HostP, irq);
+	RIOServiceHost(p, HostP);
 
 	rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type);
 
@@ -417,7 +417,7 @@
 {
 	func_enter();
 
-	rio_interrupt(0, &p->RIOHosts[data], NULL);
+	rio_interrupt(0, &p->RIOHosts[data]);
 	p->RIOHosts[data].timer.expires = jiffies + rio_poll;
 	add_timer(&p->RIOHosts[data].timer);
 
@@ -1017,6 +1017,10 @@
 			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
 
 			fix_rio_pci(pdev);
+
+			p->RIOHosts[p->RIONumHosts].pdev = pdev;
+			pci_dev_get(pdev);
+
 			p->RIOLastPCISearch = 0;
 			p->RIONumHosts++;
 			found++;
@@ -1066,6 +1070,9 @@
 			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
 			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
 
+			p->RIOHosts[p->RIONumHosts].pdev = pdev;
+			pci_dev_get(pdev);
+
 			p->RIOLastPCISearch = 0;
 			p->RIONumHosts++;
 			found++;
@@ -1181,6 +1188,8 @@
 		}
 		/* It is safe/allowed to del_timer a non-active timer */
 		del_timer(&hp->timer);
+		if (hp->Type == RIO_PCI)
+			pci_dev_put(hp->pdev);
 	}
 
 	if (misc_deregister(&rio_fw_device) < 0) {
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index 052e812..7ce7761 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -662,7 +662,7 @@
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
-		if (portStats.port >= RIO_PORTS) {
+		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
 			return -ENXIO;
 		}
@@ -702,7 +702,7 @@
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
-		if (portStats.port >= RIO_PORTS) {
+		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
 			return -ENXIO;
 		}
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
index 0bd0904..eeda40c 100644
--- a/drivers/char/rio/riointr.c
+++ b/drivers/char/rio/riointr.c
@@ -181,7 +181,7 @@
 static int RxIntr;
 static int TxIntr;
 
-void RIOServiceHost(struct rio_info *p, struct Host *HostP, int From)
+void RIOServiceHost(struct rio_info *p, struct Host *HostP)
 {
 	rio_spin_lock(&HostP->HostLock);
 	if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index b0ab3f2..5ab32b3 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -550,7 +550,7 @@
 }
 
 /* The main interrupt processing routine */
-static irqreturn_t rc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t rc_interrupt(int irq, void * dev_id)
 {
 	unsigned char status;
 	unsigned char ack;
@@ -559,11 +559,10 @@
 	int handled = 0;
 
 	bp = IRQ_to_board[irq];
-	
-	if (!bp || !(bp->flags & RC_BOARD_ACTIVE))  {
+
+	if (!(bp->flags & RC_BOARD_ACTIVE))
 		return IRQ_NONE;
-	}
-	
+
 	while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &
 				 (RC_BSR_TOUT | RC_BSR_TINT |
 				  RC_BSR_MINT | RC_BSR_RINT))) {
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 656f8c0..66a7385 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -35,13 +35,13 @@
  *	1.09a	Pete Zaitcev: Sun SPARC
  *	1.09b	Jeff Garzik: Modularize, init cleanup
  *	1.09c	Jeff Garzik: SMP cleanup
- *	1.10    Paul Barton-Davis: add support for async I/O
+ *	1.10	Paul Barton-Davis: add support for async I/O
  *	1.10a	Andrea Arcangeli: Alpha updates
  *	1.10b	Andrew Morton: SMP lock fix
  *	1.10c	Cesar Barros: SMP locking fixes and cleanup
  *	1.10d	Paul Gortmaker: delete paranoia check in rtc_exit
  *	1.10e	Maciej W. Rozycki: Handle DECstation's year weirdness.
- *      1.11    Takashi Iwai: Kernel access functions
+ *	1.11	Takashi Iwai: Kernel access functions
  *			      rtc_register/rtc_unregister/rtc_control
  *      1.11a   Daniele Bellucci: Audit create_proc_read_entry in rtc_init
  *	1.12	Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
@@ -113,9 +113,9 @@
 #define hpet_set_rtc_irq_bit(arg) 		0
 #define hpet_rtc_timer_init() 			do { } while (0)
 #define hpet_rtc_dropped_irq() 			0
-static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {return 0;}
+static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
 #else
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif
 
 /*
@@ -229,7 +229,7 @@
  *	(See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
  */
 
-irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t rtc_interrupt(int irq, void *dev_id)
 {
 	/*
 	 *	Can be an alarm interrupt, update complete interrupt,
@@ -915,7 +915,7 @@
 };
 
 #if defined(RTC_IRQ) && !defined(__sparc__)
-static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs);
+static irq_handler_t rtc_int_handler_ptr;
 #endif
 
 static int __init rtc_init(void)
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 65c751d..4217d38 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -111,7 +111,7 @@
 
 /***************************** Prototypes ***************************/
 /* The interrupt service routine */
-static irqreturn_t a2232_vbl_inter(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t a2232_vbl_inter(int irq, void *data);
 /* Initialize the port structures */
 static void a2232_init_portstructs(void);
 /* Initialize and register TTY drivers. */
@@ -504,7 +504,7 @@
 }
 /*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
 
-static irqreturn_t a2232_vbl_inter(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t a2232_vbl_inter(int irq, void *data)
 {
 #if A2232_IOBUFLEN != 256
 #error "Re-Implement a2232_vbl_inter()!"
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index f4809c8..3af7f09 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -62,6 +62,7 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/tty_flip.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -370,7 +371,7 @@
    received, out buffer empty, modem change, etc.
  */
 static irqreturn_t
-cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_rxerr_interrupt(int irq, void *dev_id)
 {
     struct tty_struct *tty;
     struct cyclades_port *info;
@@ -427,8 +428,9 @@
 		       overflowing, we still loose
 		       the next incoming character.
 		     */
-		    tty_insert_flip_char(tty, data, TTY_NORMAL);
-		}
+		    if (tty_buffer_request_room(tty, 1) != 0){
+			tty_insert_flip_char(tty, data, TTY_FRAME);
+		    }
 		/* These two conditions may imply */
 		/* a normal read should be done. */
 		/* else if(data & CyTIMEOUT) */
@@ -437,21 +439,21 @@
 		    tty_insert_flip_char(tty, 0, TTY_NORMAL);
 		}
 	    }else{
-		    tty_insert_flip_char(tty, data, TTY_NORMAL);
+		tty_insert_flip_char(tty, data, TTY_NORMAL);
 	    }
 	}else{
 	    /* there was a software buffer overrun
 	       and nothing could be done about it!!! */
 	}
     }
-    schedule_delayed_work(&tty->flip.work, 1);
+    tty_schedule_flip(tty);
     /* end of service */
     base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
     return IRQ_HANDLED;
 } /* cy_rxerr_interrupt */
 
 static irqreturn_t
-cd2401_modem_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_modem_interrupt(int irq, void *dev_id)
 {
     struct cyclades_port *info;
     volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
@@ -506,7 +508,7 @@
 } /* cy_modem_interrupt */
 
 static irqreturn_t
-cd2401_tx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_tx_interrupt(int irq, void *dev_id)
 {
     struct cyclades_port *info;
     volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
@@ -626,7 +628,7 @@
 } /* cy_tx_interrupt */
 
 static irqreturn_t
-cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_rx_interrupt(int irq, void *dev_id)
 {
     struct tty_struct *tty;
     struct cyclades_port *info;
@@ -635,6 +637,7 @@
     char data;
     int char_count;
     int save_cnt;
+    int len;
 
     /* determine the channel and change to that context */
     channel = (u_short ) (base_addr[CyLICR] >> 2);
@@ -667,14 +670,15 @@
 	    info->mon.char_max = char_count;
 	info->mon.char_last = char_count;
 #endif
-	while(char_count--){
+	len = tty_buffer_request_room(tty, char_count);
+	while(len--){
 	    data = base_addr[CyRDR];
 	    tty_insert_flip_char(tty, data, TTY_NORMAL);
 #ifdef CYCLOM_16Y_HACK
 	    udelay(10L);
 #endif
         }
-	schedule_delayed_work(&tty->flip.work, 1);
+	tty_schedule_flip(tty);
     }
     /* end of service */
     base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
@@ -835,7 +839,7 @@
     local_irq_save(flags);
 	if (info->xmit_buf){
 	    free_page((unsigned long) info->xmit_buf);
-	    info->xmit_buf = 0;
+	    info->xmit_buf = NULL;
 	}
 
 	base_addr[CyCAR] = (u_char)channel;
@@ -1350,7 +1354,7 @@
 
 static int
 get_serial_info(struct cyclades_port * info,
-                           struct serial_struct * retinfo)
+                           struct serial_struct __user * retinfo)
 {
   struct serial_struct tmp;
 
@@ -1372,7 +1376,7 @@
 
 static int
 set_serial_info(struct cyclades_port * info,
-                           struct serial_struct * new_info)
+                           struct serial_struct __user * new_info)
 {
   struct serial_struct new_serial;
   struct cyclades_port old_info;
@@ -1422,7 +1426,6 @@
   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
   unsigned long flags;
   unsigned char status;
-  unsigned int result;
 
     channel = info->line;
 
@@ -1446,7 +1449,6 @@
   int channel;
   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
   unsigned long flags;
-  unsigned int arg;
 	  
     channel = info->line;
 
@@ -1501,7 +1503,7 @@
 } /* send_break */
 
 static int
-get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
+get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
 {
 
    if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
@@ -1514,7 +1516,7 @@
 }
 
 static int
-set_threshold(struct cyclades_port * info, unsigned long *arg)
+set_threshold(struct cyclades_port * info, unsigned long __user *arg)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    unsigned long value;
@@ -1531,7 +1533,7 @@
 }
 
 static int
-get_threshold(struct cyclades_port * info, unsigned long *value)
+get_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    int channel;
@@ -1544,7 +1546,7 @@
 }
 
 static int
-set_default_threshold(struct cyclades_port * info, unsigned long *arg)
+set_default_threshold(struct cyclades_port * info, unsigned long __user *arg)
 {
    unsigned long value;
 
@@ -1556,13 +1558,13 @@
 }
 
 static int
-get_default_threshold(struct cyclades_port * info, unsigned long *value)
+get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
    return put_user(info->default_threshold,value);
 }
 
 static int
-set_timeout(struct cyclades_port * info, unsigned long *arg)
+set_timeout(struct cyclades_port * info, unsigned long __user *arg)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    int channel;
@@ -1579,7 +1581,7 @@
 }
 
 static int
-get_timeout(struct cyclades_port * info, unsigned long *value)
+get_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    int channel;
@@ -1599,7 +1601,7 @@
 }
 
 static int
-get_default_timeout(struct cyclades_port * info, unsigned long *value)
+get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
    return put_user(info->default_timeout,value);
 }
@@ -1611,6 +1613,7 @@
   unsigned long val;
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int ret_val = 0;
+  void __user *argp = (void __user *)arg;
 
 #ifdef SERIAL_DEBUG_OTHER
     printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
@@ -1618,28 +1621,28 @@
 
     switch (cmd) {
         case CYGETMON:
-            ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
+            ret_val = get_mon_info(info, argp);
 	    break;
         case CYGETTHRESH:
-	    ret_val = get_threshold(info, (unsigned long *)arg);
+	    ret_val = get_threshold(info, argp);
  	    break;
         case CYSETTHRESH:
-            ret_val = set_threshold(info, (unsigned long *)arg);
+            ret_val = set_threshold(info, argp);
 	    break;
         case CYGETDEFTHRESH:
-	    ret_val = get_default_threshold(info, (unsigned long *)arg);
+	    ret_val = get_default_threshold(info, argp);
  	    break;
         case CYSETDEFTHRESH:
-            ret_val = set_default_threshold(info, (unsigned long *)arg);
+            ret_val = set_default_threshold(info, argp);
 	    break;
         case CYGETTIMEOUT:
-	    ret_val = get_timeout(info, (unsigned long *)arg);
+	    ret_val = get_timeout(info, argp);
  	    break;
         case CYSETTIMEOUT:
-            ret_val = set_timeout(info, (unsigned long *)arg);
+            ret_val = set_timeout(info, argp);
 	    break;
         case CYGETDEFTIMEOUT:
-	    ret_val = get_default_timeout(info, (unsigned long *)arg);
+	    ret_val = get_default_timeout(info, argp);
  	    break;
         case CYSETDEFTIMEOUT:
             ret_val = set_default_timeout(info, (unsigned long)arg);
@@ -1662,21 +1665,20 @@
 
 /* The following commands are incompletely implemented!!! */
         case TIOCGSOFTCAR:
-            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
             break;
         case TIOCSSOFTCAR:
-            ret_val = get_user(val, (unsigned long *) arg);
+            ret_val = get_user(val, (unsigned long __user *) argp);
 	    if (ret_val)
 		    break;
             tty->termios->c_cflag =
                     ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
             break;
         case TIOCGSERIAL:
-            ret_val = get_serial_info(info, (struct serial_struct *) arg);
+            ret_val = get_serial_info(info, argp);
             break;
         case TIOCSSERIAL:
-            ret_val = set_serial_info(info,
-                                   (struct serial_struct *) arg);
+            ret_val = set_serial_info(info, argp);
             break;
         default:
 	    ret_val = -ENOIOCTLCMD;
@@ -1771,7 +1773,7 @@
 	tty->driver->flush_buffer(tty);
     tty_ldisc_flush(tty);
     info->event = 0;
-    info->tty = 0;
+    info->tty = NULL;
     if (info->blocked_open) {
 	if (info->close_delay) {
 	    msleep_interruptible(jiffies_to_msecs(info->close_delay));
@@ -2248,7 +2250,7 @@
 		info->card = index;
 		info->line = port_num;
 		info->flags = STD_COM_FLAGS;
-		info->tty = 0;
+		info->tty = NULL;
 		info->xmit_fifo_size = 12;
 		info->cor1 = CyPARITY_NONE|Cy_8_BITS;
 		info->cor2 = CyETC;
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 07e0b75..52753e7 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -34,7 +34,7 @@
 #define SCDRV_TIMEOUT	1000
 
 static irqreturn_t
-scdrv_interrupt(int irq, void *subch_data, struct pt_regs *regs)
+scdrv_interrupt(int irq, void *subch_data)
 {
 	struct subch_data_s *sd = subch_data;
 	unsigned long flags;
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index 864854c..2f56e8c 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -36,7 +36,7 @@
  * destination.
  */
 static irqreturn_t
-scdrv_event_interrupt(int irq, void *subch_data, struct pt_regs *regs)
+scdrv_event_interrupt(int irq, void *subch_data)
 {
 	struct subch_data_s *sd = subch_data;
 	unsigned long flags;
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index d4e434d..c084149 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -826,7 +826,7 @@
 }
 
 /* Interrupt handler: some event is available */
-static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sonypi_irq(int irq, void *dev_id)
 {
 	u8 v1, v2, event = 0;
 	int i, j;
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 902c48d..7e1bd95 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -183,11 +183,6 @@
 
 static struct tty_driver *specialix_driver;
 
-static unsigned long baud_table[] =  {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 0,
-};
-
 static struct specialix_board sx_board[SX_NBOARD] =  {
 	{ 0, SX_IOBASE1,  9, },
 	{ 0, SX_IOBASE2, 11, },
@@ -200,7 +195,7 @@
 
 #ifdef SPECIALIX_TIMER
 static struct timer_list missed_irq_timer;
-static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static irqreturn_t sx_interrupt(int irq, void * dev_id);
 #endif
 
 
@@ -897,7 +892,7 @@
 
 
 /* The main interrupt processing routine */
-static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sx_interrupt(int irq, void *dev_id)
 {
 	unsigned char status;
 	unsigned char ack;
@@ -912,7 +907,7 @@
 	spin_lock_irqsave(&bp->lock, flags);
 
 	dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
-	if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) {
+	if (!(bp->flags & SX_BOARD_ACTIVE)) {
 		dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
 		spin_unlock_irqrestore(&bp->lock, flags);
 		func_exit();
@@ -1090,9 +1085,9 @@
 
 	if (baud == 38400) {
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud ++;
+			baud = 57600;
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud += 2;
+			baud = 115200;
 	}
 
 	if (!baud) {
@@ -1150,11 +1145,9 @@
 	sx_out(bp, CD186x_RBPRL, tmp & 0xff);
 	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
 	spin_unlock_irqrestore(&bp->lock, flags);
-	if (port->custom_divisor) {
+	if (port->custom_divisor)
 		baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
-		baud = ( baud + 5 ) / 10;
-	} else
-		baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
+	baud = (baud + 5) / 10;		/* Estimated CPS */
 
 	/* Two timer ticks seems enough to wakeup something like SLIP driver */
 	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index bd71153..522e88e 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1927,13 +1927,12 @@
  *	calls off to the approrpriate board interrupt handlers.
  */
 
-static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t stl_intr(int irq, void *dev_id)
 {
 	stlbrd_t	*brdp = (stlbrd_t *) dev_id;
 
 #ifdef DEBUG
-	printk("stl_intr(brdp=%x,irq=%d,regs=%x)\n", (int) brdp, irq,
-	    (int) regs);
+	printk("stl_intr(brdp=%x,irq=%d)\n", (int) brdp, irq);
 #endif
 
 	return IRQ_RETVAL((* brdp->isr)(brdp));
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 8fd71a5..cc10af0 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1192,7 +1192,7 @@
  * Small, elegant, clear.
  */
 
-static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sx_interrupt (int irq, void *ptr)
 {
 	struct sx_board *board = ptr;
 	struct sx_port *port;
@@ -1300,7 +1300,7 @@
 
 	func_enter ();
 
-	sx_interrupt (0, board, NULL);
+	sx_interrupt (0, board);
 
 	init_timer(&board->timer);
 
@@ -2602,7 +2602,7 @@
 		}
 	}
 	if (misc_deregister(&sx_fw_device) < 0) {
-		printk (KERN_INFO "sx: couldn't deregister firmware loader devic\n");
+		printk (KERN_INFO "sx: couldn't deregister firmware loader device\n");
 	}
 	sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized);
 	if (sx_initialized)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a4150c4..06784ad 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -133,8 +133,8 @@
 };
 
 #define SHARED_MEM_ADDRESS_SIZE 0x40000
-#define BUFFERLISTSIZE (PAGE_SIZE)
-#define DMABUFFERSIZE (PAGE_SIZE)
+#define BUFFERLISTSIZE 4096
+#define DMABUFFERSIZE 4096
 #define MAXRXFRAMES 7
 
 typedef struct _DMABUFFERENTRY
@@ -1698,11 +1698,10 @@
  * 
  * 	irq		interrupt number that caused interrupt
  * 	dev_id		device ID supplied during interrupt registration
- * 	regs		interrupted processor context
  * 	
  * Return Value: None
  */
-static irqreturn_t mgsl_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
 {
 	struct mgsl_struct * info;
 	u16 UscVector;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index bdc7cb2..d4334c7 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -491,7 +491,7 @@
 static void isr_rdma(struct slgt_info *info);
 static void isr_txeom(struct slgt_info *info, unsigned short status);
 static void isr_tdma(struct slgt_info *info);
-static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t slgt_interrupt(int irq, void *dev_id);
 
 static int  alloc_dma_bufs(struct slgt_info *info);
 static void free_dma_bufs(struct slgt_info *info);
@@ -2217,9 +2217,8 @@
  *
  * 	irq	interrupt number
  * 	dev_id	device ID supplied during interrupt registration
- * 	regs	interrupted processor context
  */
-static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t slgt_interrupt(int irq, void *dev_id)
 {
 	struct slgt_info *info;
 	unsigned int gsr;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 6eb75dc..3e932b6 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2596,8 +2596,7 @@
  * 	dev_id		device ID supplied during interrupt registration
  * 	regs		interrupted processor context
  */
-static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
 {
 	SLMP_INFO * info;
 	unsigned char status, status0, status1=0;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 6b4d4d1..5f49280 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,14 +35,15 @@
 #include <linux/vt_kern.h>
 #include <linux/workqueue.h>
 #include <linux/kexec.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
+#include <asm/irq_regs.h>
 
 /* Whether we react on sysrq keys or just ignore them */
 int sysrq_enabled = 1;
 
-static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
-				  struct tty_struct *tty)
+static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
 {
 	int i;
 	i = key - '0';
@@ -58,8 +59,7 @@
 };
 
 #ifdef CONFIG_VT
-static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
-			     struct tty_struct *tty)
+static void sysrq_handle_SAK(int key, struct tty_struct *tty)
 {
 	if (tty)
 		do_SAK(tty);
@@ -76,8 +76,7 @@
 #endif
 
 #ifdef CONFIG_VT
-static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
-			       struct tty_struct *tty)
+static void sysrq_handle_unraw(int key, struct tty_struct *tty)
 {
 	struct kbd_struct *kbd = &kbd_table[fg_console];
 
@@ -95,10 +94,9 @@
 #endif /* CONFIG_VT */
 
 #ifdef CONFIG_KEXEC
-static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
-				struct tty_struct *tty)
+static void sysrq_handle_crashdump(int key, struct tty_struct *tty)
 {
-	crash_kexec(pt_regs);
+	crash_kexec(get_irq_regs());
 }
 static struct sysrq_key_op sysrq_crashdump_op = {
 	.handler	= sysrq_handle_crashdump,
@@ -110,8 +108,7 @@
 #define sysrq_crashdump_op (*(struct sysrq_key_op *)0)
 #endif
 
-static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
-				struct tty_struct *tty)
+static void sysrq_handle_reboot(int key, struct tty_struct *tty)
 {
 	lockdep_off();
 	local_irq_enable();
@@ -124,8 +121,7 @@
 	.enable_mask	= SYSRQ_ENABLE_BOOT,
 };
 
-static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
-			      struct tty_struct *tty)
+static void sysrq_handle_sync(int key, struct tty_struct *tty)
 {
 	emergency_sync();
 }
@@ -136,8 +132,7 @@
 	.enable_mask	= SYSRQ_ENABLE_SYNC,
 };
 
-static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
-				 struct tty_struct *tty)
+static void sysrq_handle_mountro(int key, struct tty_struct *tty)
 {
 	emergency_remount();
 }
@@ -149,8 +144,7 @@
 };
 
 #ifdef CONFIG_LOCKDEP
-static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs,
-				struct tty_struct *tty)
+static void sysrq_handle_showlocks(int key, struct tty_struct *tty)
 {
 	debug_show_all_locks();
 }
@@ -164,11 +158,11 @@
 #define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
 #endif
 
-static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
-				  struct tty_struct *tty)
+static void sysrq_handle_showregs(int key, struct tty_struct *tty)
 {
-	if (pt_regs)
-		show_regs(pt_regs);
+	struct pt_regs *regs = get_irq_regs();
+	if (regs)
+		show_regs(regs);
 }
 static struct sysrq_key_op sysrq_showregs_op = {
 	.handler	= sysrq_handle_showregs,
@@ -177,8 +171,7 @@
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
 
-static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
-				   struct tty_struct *tty)
+static void sysrq_handle_showstate(int key, struct tty_struct *tty)
 {
 	show_state();
 }
@@ -189,8 +182,7 @@
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
 
-static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
-				 struct tty_struct *tty)
+static void sysrq_handle_showmem(int key, struct tty_struct *tty)
 {
 	show_mem();
 }
@@ -215,8 +207,7 @@
 	}
 }
 
-static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
-			      struct tty_struct *tty)
+static void sysrq_handle_term(int key, struct tty_struct *tty)
 {
 	send_sig_all(SIGTERM);
 	console_loglevel = 8;
@@ -236,8 +227,7 @@
 
 static DECLARE_WORK(moom_work, moom_callback, NULL);
 
-static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
-			      struct tty_struct *tty)
+static void sysrq_handle_moom(int key, struct tty_struct *tty)
 {
 	schedule_work(&moom_work);
 }
@@ -247,8 +237,7 @@
 	.action_msg	= "Manual OOM execution",
 };
 
-static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
-			      struct tty_struct *tty)
+static void sysrq_handle_kill(int key, struct tty_struct *tty)
 {
 	send_sig_all(SIGKILL);
 	console_loglevel = 8;
@@ -260,8 +249,7 @@
 	.enable_mask	= SYSRQ_ENABLE_SIGNAL,
 };
 
-static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
-				struct tty_struct *tty)
+static void sysrq_handle_unrt(int key, struct tty_struct *tty)
 {
 	normalize_rt_tasks();
 }
@@ -361,8 +349,7 @@
  * This is the non-locking version of handle_sysrq.  It must/can only be called
  * by sysrq key handlers, as they are inside of the lock
  */
-void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty,
-			int check_mask)
+void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
 {
 	struct sysrq_key_op *op_p;
 	int orig_log_level;
@@ -384,7 +371,7 @@
 		    (sysrq_enabled & op_p->enable_mask)) {
 			printk("%s\n", op_p->action_msg);
 			console_loglevel = orig_log_level;
-			op_p->handler(key, pt_regs, tty);
+			op_p->handler(key, tty);
 		} else {
 			printk("This sysrq operation is disabled.\n");
 		}
@@ -413,11 +400,11 @@
  * This function is called by the keyboard handler when SysRq is pressed
  * and any other keycode arrives.
  */
-void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+void handle_sysrq(int key, struct tty_struct *tty)
 {
 	if (!sysrq_enabled)
 		return;
-	__handle_sysrq(key, pt_regs, tty, 1);
+	__handle_sysrq(key, tty, 1);
 }
 EXPORT_SYMBOL(handle_sysrq);
 
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index d2c5ba4e..2444a0e 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -193,7 +193,7 @@
 
 static int tlclk_major = TLCLK_MAJOR;
 
-static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t tlclk_interrupt(int irq, void *dev_id);
 
 static DECLARE_WAIT_QUEUE_HEAD(wq);
 
@@ -856,7 +856,7 @@
 	wake_up(&wq);
 }
 
-static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
 {
 	unsigned long flags;
 
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index a082a2e..6ad2d3b 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1153,7 +1153,14 @@
 
 	spin_unlock(&driver_lock);
 
-	sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
+	if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
+		list_del(&chip->list);
+		put_device(dev);
+		clear_bit(chip->dev_num, dev_mask);
+		kfree(chip);
+		kfree(devname);
+		return NULL;
+	}
 
 	chip->bios_dir = tpm_bios_log_setup(devname);
 
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index ad8ffe4..1ab0896 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -184,7 +184,9 @@
 	unsigned long base;
 	struct  tpm_chip *chip;
 
-	driver_register(&atml_drv);
+	rc = driver_register(&atml_drv);
+	if (rc)
+		return rc;
 
 	if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
 		rc = -ENODEV;
@@ -195,10 +197,8 @@
 	    (atmel_request_region
 	     (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
 
-
-	if (IS_ERR
-	    (pdev =
-	     platform_device_register_simple("tpm_atmel", -1, NULL, 0))) {
+	pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
 		rc = PTR_ERR(pdev);
 		goto err_rel_reg;
 	}
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 26287aa..608f730 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -284,7 +284,7 @@
 static int __init init_nsc(void)
 {
 	int rc = 0;
-	int lo, hi;
+	int lo, hi, err;
 	int nscAddrBase = TPM_ADDR;
 	struct tpm_chip *chip;
 	unsigned long base;
@@ -297,7 +297,9 @@
 			return -ENODEV;
 	}
 
-	driver_register(&nsc_drv);
+	err = driver_register(&nsc_drv);
+	if (err)
+		return err;
 
 	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
 	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index ee7ac6f..483f3f6 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -377,7 +377,7 @@
 		    .fops = &tis_ops,},
 };
 
-static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tis_int_probe(int irq, void *dev_id)
 {
 	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
 	u32 interrupt;
@@ -397,7 +397,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tis_int_handler(int irq, void *dev_id)
 {
 	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
 	u32 interrupt;
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index a362ee9..6d2e314 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -947,7 +947,7 @@
 				 */
 				continue;
 			} else if (vio_sysrq_pressed) {
-				handle_sysrq(cevent->data[index], NULL, tty);
+				handle_sysrq(cevent->data[index], tty);
 				vio_sysrq_pressed = 0;
 				/*
 				 * continue because we don't want to add
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index c2ca31e..d0b94dd 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -81,10 +81,10 @@
                      unsigned int cmd, unsigned long arg);
 static void scc_throttle(struct tty_struct *tty);
 static void scc_unthrottle(struct tty_struct *tty);
-static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp);
-static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp);
-static irqreturn_t scc_stat_int(int irq, void *data, struct pt_regs *fp);
-static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t scc_tx_int(int irq, void *data);
+static irqreturn_t scc_rx_int(int irq, void *data);
+static irqreturn_t scc_stat_int(int irq, void *data);
+static irqreturn_t scc_spcond_int(int irq, void *data);
 static void scc_setsignals(struct scc_port *port, int dtr, int rts);
 static void scc_break_ctl(struct tty_struct *tty, int break_state);
 
@@ -419,7 +419,7 @@
  * Interrupt handlers
  *--------------------------------------------------------------------------*/
 
-static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_rx_int(int irq, void *data)
 {
 	unsigned char	ch;
 	struct scc_port *port = data;
@@ -440,7 +440,7 @@
 	 */
 	if (SCCread(INT_PENDING_REG) &
 	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
-		scc_spcond_int (irq, data, fp);
+		scc_spcond_int (irq, data);
 		return IRQ_HANDLED;
 	}
 
@@ -451,7 +451,7 @@
 }
 
 
-static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_spcond_int(int irq, void *data)
 {
 	struct scc_port *port = data;
 	struct tty_struct *tty = port->gs.tty;
@@ -496,7 +496,7 @@
 }
 
 
-static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_tx_int(int irq, void *data)
 {
 	struct scc_port *port = data;
 	SCC_ACCESS_INIT(port);
@@ -538,7 +538,7 @@
 }
 
 
-static irqreturn_t scc_stat_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_stat_int(int irq, void *data)
 {
 	struct scc_port *port = data;
 	unsigned channel = port->channel;
@@ -593,7 +593,7 @@
 	local_irq_save(flags);
 	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
 	/* restart the transmitter */
-	scc_tx_int (0, port, 0);
+	scc_tx_int (0, port);
 	local_irq_restore(flags);
 }
 
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 8116a47..8e79493 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -221,7 +221,7 @@
 	.end		= end_giuint_high_irq,
 };
 
-static int giu_get_irq(unsigned int irq, struct pt_regs *regs)
+static int giu_get_irq(unsigned int irq)
 {
 	uint16_t pendl, pendh, maskl, maskh;
 	int i;
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
index 5948863..bf25d0a 100644
--- a/drivers/char/watchdog/alim7101_wdt.c
+++ b/drivers/char/watchdog/alim7101_wdt.c
@@ -77,7 +77,8 @@
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+		 __stringify(CONFIG_WATCHDOG_NOWAYOUT) ")");
 
 /*
  *	Whack the dog
@@ -415,6 +416,16 @@
 module_init(alim7101_wdt_init);
 module_exit(alim7101_wdt_unload);
 
+static struct pci_device_id alim7101_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl);
+
 MODULE_AUTHOR("Steve Hill");
 MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
index 4f42697..e228d6e 100644
--- a/drivers/char/watchdog/eurotechwdt.c
+++ b/drivers/char/watchdog/eurotechwdt.c
@@ -153,7 +153,7 @@
  * Kernel methods.
  */
 
-static irqreturn_t eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t eurwdt_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_CRIT "timeout WDT timeout\n");
 
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
index 02d336a..3404a9c 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -64,7 +64,7 @@
  *	This is the interrupt handler.  Note that we only use this
  *	in testing mode, so don't actually do a reboot here.
  */
-static irqreturn_t mpcore_wdt_fire(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
 {
 	struct mpcore_wdt *wdt = arg;
 
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 77662cb..bda4533 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -158,7 +158,7 @@
 };
 
 
-static void usb_pcwd_intr_done(struct urb *urb, struct pt_regs *regs)
+static void usb_pcwd_intr_done(struct urb *urb)
 {
 	struct usb_pcwd_private *usb_pcwd = (struct usb_pcwd_private *)urb->context;
 	unsigned char *data = usb_pcwd->intr_buffer;
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index d54d0ef..18cb050 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -336,8 +336,7 @@
 
 /* interrupt handler code */
 
-static irqreturn_t s3c2410wdt_irq(int irqno, void *param,
-				  struct pt_regs *regs)
+static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
 {
 	printk(KERN_INFO PFX "Watchdog timer expired!\n");
 
diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
index 13f23f4..517fbd8 100644
--- a/drivers/char/watchdog/wdt.c
+++ b/drivers/char/watchdog/wdt.c
@@ -225,14 +225,13 @@
  *	wdt_interrupt:
  *	@irq:		Interrupt number
  *	@dev_id:	Unused as we don't allow multiple devices.
- *	@regs:		Unused.
  *
  *	Handle an interrupt from the board. These are raised when the status
  *	map changes in what the board considers an interesting way. That means
  *	a failure condition occurring.
  */
 
-static irqreturn_t wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wdt_interrupt(int irq, void *dev_id)
 {
 	/*
 	 *	Read the status register see what is up and
diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
index 89a249e..e4cf661 100644
--- a/drivers/char/watchdog/wdt285.c
+++ b/drivers/char/watchdog/wdt285.c
@@ -46,7 +46,7 @@
 /*
  *	If the timer expires..
  */
-static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs)
+static void watchdog_fire(int irq, void *dev_id)
 {
 	printk(KERN_CRIT "Watchdog: Would Reboot.\n");
 	*CSR_TIMER4_CNTL = 0;
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index 74d8cf8..ce1261c 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -270,14 +270,13 @@
  *	wdtpci_interrupt:
  *	@irq:		Interrupt number
  *	@dev_id:	Unused as we don't allow multiple devices.
- *	@regs:		Unused.
  *
  *	Handle an interrupt from the board. These are raised when the status
  *	map changes in what the board considers an interesting way. That means
  *	a failure condition occurring.
  */
 
-static irqreturn_t wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
 {
 	/*
 	 *	Read the status register see what is up and
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 7ad3be8..7fcb77a 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -54,8 +54,8 @@
 		v1 = read_pmtmr();
 		v2 = read_pmtmr();
 		v3 = read_pmtmr();
-	} while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
-			|| (v3 > v1 && v3 < v2));
+	} while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+			  || (v3 > v1 && v3 < v2)));
 
 	return (cycle_t)v2;
 }
@@ -138,6 +138,8 @@
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
 			acpi_pm_check_graylist);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
+			acpi_pm_check_graylist);
 #endif
 
 
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
index dbd4d6c..0358419 100644
--- a/drivers/dma/ioatdma.c
+++ b/drivers/dma/ioatdma.c
@@ -80,7 +80,7 @@
 
 static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
 	struct ioat_dma_chan *ioat_chan,
-	int flags)
+	gfp_t flags)
 {
 	struct ioat_dma_descriptor *desc;
 	struct ioat_desc_sw *desc_sw;
@@ -563,7 +563,7 @@
 	.remove	= __devexit_p(ioat_remove),
 };
 
-static irqreturn_t ioat_do_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t ioat_do_interrupt(int irq, void *data)
 {
 	struct ioat_device *instance = data;
 	unsigned long attnstatus;
@@ -686,7 +686,7 @@
 {
 	int err;
 	unsigned long mmio_start, mmio_len;
-	void *reg_base;
+	void __iomem *reg_base;
 	struct ioat_device *device;
 
 	err = pci_enable_device(pdev);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index a5d3b36..62b26a9 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -44,7 +44,7 @@
 
 struct ioat_device {
 	struct pci_dev *pdev;
-	void *reg_base;
+	void __iomem *reg_base;
 	struct pci_pool *dma_pool;
 	struct pci_pool *completion_pool;
 
@@ -73,7 +73,7 @@
 
 struct ioat_dma_chan {
 
-	void *reg_base;
+	void __iomem *reg_base;
 
 	dma_cookie_t completed_cookie;
 	unsigned long last_completion;
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 3a365e1..d944647 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -226,14 +226,26 @@
 
 static int __init eisa_register_device (struct eisa_device *edev)
 {
-	if (device_register (&edev->dev))
-		return -1;
+	int rc = device_register (&edev->dev);
+	if (rc)
+		return rc;
 
-	device_create_file (&edev->dev, &dev_attr_signature);
-	device_create_file (&edev->dev, &dev_attr_enabled);
-	device_create_file (&edev->dev, &dev_attr_modalias);
+	rc = device_create_file (&edev->dev, &dev_attr_signature);
+	if (rc) goto err_devreg;
+	rc = device_create_file (&edev->dev, &dev_attr_enabled);
+	if (rc) goto err_sig;
+	rc = device_create_file (&edev->dev, &dev_attr_modalias);
+	if (rc) goto err_enab;
 
 	return 0;
+
+err_enab:
+	device_remove_file (&edev->dev, &dev_attr_enabled);
+err_sig:
+	device_remove_file (&edev->dev, &dev_attr_signature);
+err_devreg:
+	device_unregister(&edev->dev);
+	return rc;
 }
 
 static int __init eisa_request_resources (struct eisa_root_device *root,
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
index 3b07e0c..b09dfc7 100644
--- a/drivers/fc4/soc.c
+++ b/drivers/fc4/soc.c
@@ -334,7 +334,7 @@
 	}
 }
 
-static irqreturn_t soc_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t soc_intr(int irq, void *dev_id)
 {
 	u32 cmd;
 	unsigned long flags;
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
index 2b75edc..a6b1ae2 100644
--- a/drivers/fc4/socal.c
+++ b/drivers/fc4/socal.c
@@ -404,7 +404,7 @@
 	}
 }
 
-static irqreturn_t socal_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t socal_intr(int irq, void *dev_id)
 {
 	u32 cmd;
 	unsigned long flags;
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 339f405..1865b56 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -8,7 +8,7 @@
  *
  *  See Documentation/dcdbas.txt for more information.
  *
- *  Copyright (C) 1995-2005 Dell Inc.
+ *  Copyright (C) 1995-2006 Dell Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License v2.0 as published by
@@ -40,7 +40,7 @@
 #include "dcdbas.h"
 
 #define DRIVER_NAME		"dcdbas"
-#define DRIVER_VERSION		"5.6.0-2"
+#define DRIVER_VERSION		"5.6.0-3.2"
 #define DRIVER_DESCRIPTION	"Dell Systems Management Base Driver"
 
 static struct platform_device *dcdbas_pdev;
@@ -175,6 +175,9 @@
 {
 	ssize_t ret;
 
+	if ((pos + count) > MAX_SMI_DATA_BUF_SIZE)
+		return -EINVAL;
+
 	mutex_lock(&smi_data_lock);
 
 	ret = smi_data_buf_realloc(pos + count);
@@ -559,7 +562,7 @@
 			while (--i >= 0)
 				sysfs_remove_bin_file(&dev->dev.kobj,
 						      dcdbas_bin_attrs[i]);
-			sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
+			sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
 			return error;
 		}
 	}
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index fc17599..08b1617 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -249,7 +249,7 @@
 		if ((rc = create_packet(temp, packet_length)))
 			return rc;
 
-		pr_debug("%p:%lu\n", temp, (end - temp));
+		pr_debug("%p:%td\n", temp, (end - temp));
 		temp += packet_length;
 	}
 
@@ -718,14 +718,27 @@
 		return -EIO;
 	}
 
-	sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
-	sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
-	sysfs_create_bin_file(&rbu_device->dev.kobj,
+	rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+	if (rc)
+		goto out_devreg;
+	rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+	if (rc)
+		goto out_data;
+	rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
 		&rbu_packet_size_attr);
+	if (rc)
+		goto out_imtype;
 
 	rbu_data.entry_created = 0;
-	return rc;
+	return 0;
 
+out_imtype:
+	sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+out_data:
+	sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+out_devreg:
+	platform_device_unregister(rbu_device);
+	return rc;
 }
 
 static __exit void dcdrbu_exit(void)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index b8b596d..37deee6 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -326,6 +326,26 @@
 }
 EXPORT_SYMBOL(dmi_get_system_info);
 
+
+/**
+ *	dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
+ *	@str: 	Case sensitive Name
+ */
+int dmi_name_in_vendors(char *str)
+{
+	static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
+				DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
+				DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
+	int i;
+	for (i = 0; fields[i] != DMI_NONE; i++) {
+		int f = fields[i];
+		if (dmi_ident[f] && strstr(dmi_ident[f], str))
+			return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dmi_name_in_vendors);
+
 /**
  *	dmi_find_device - find onboard device by type/name
  *	@type: device type or %DMI_DEV_TYPE_ANY to match all device types
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 8ebce1c..5ab5e39 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -639,7 +639,12 @@
 
 	kobject_set_name(&new_efivar->kobj, "%s", short_name);
 	kobj_set_kset_s(new_efivar, vars_subsys);
-	kobject_register(&new_efivar->kobj);
+	i = kobject_register(&new_efivar->kobj);
+	if (i) {
+		kfree(short_name);
+		kfree(new_efivar);
+		return 1;
+	}
 
 	kfree(short_name);
 	short_name = NULL;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 9b88b25..e76d919 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -95,11 +95,13 @@
 	  will be called adm9240.
 
 config SENSORS_K8TEMP
-	tristate "AMD K8 processor sensor"
+	tristate "AMD Athlon64/FX or Opteron temperature sensor"
 	depends on HWMON && X86 && PCI && EXPERIMENTAL
 	help
 	  If you say yes here you get support for the temperature
-	  sensor(s) inside your AMD K8 CPU.
+	  sensor(s) inside your CPU. Supported is whole AMD K8
+	  microarchitecture. Please note that you will need at least
+	  lm-sensors 2.10.1 for proper userspace support.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called k8temp.
@@ -369,8 +371,8 @@
 	help
 	  If you say yes here you get support for the integrated fan
 	  monitoring and control capabilities of the SMSC LPC47B27x,
-	  LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and
-	  LPC47M997 chips.
+	  LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x,
+	  LPC47M192 and LPC47M997 chips.
 
 	  The temperature and voltage sensor features of the LPC47M192
 	  and LPC47M997 are supported by another driver, select also
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 377961c..aad594a 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -5,7 +5,7 @@
  * Copyright (C) 1999	Frodo Looijaard <frodol@dds.nl>
  *			Philip Edelbrock <phil@netroedge.com>
  * Copyright (C) 2003	Michiel Rook <michiel@grendelproject.nl>
- * Copyright (C) 2005	Grant Coady <gcoady@gmail.com> with valuable
+ * Copyright (C) 2005	Grant Coady <gcoady.lk@gmail.com> with valuable
  * 				guidance from Jean Delvare
  *
  * Driver supports	Analog Devices		ADM9240
@@ -774,7 +774,7 @@
 }
 
 MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
-		"Grant Coady <gcoady@gmail.com> and others");
+		"Grant Coady <gcoady.lk@gmail.com> and others");
 MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index ac1b746..73bc2ff 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -815,18 +815,18 @@
 	if (res)
 		return res;
 
-	res = i2c_isa_add_driver(&lm78_isa_driver);
-	if (res) {
-		i2c_del_driver(&lm78_driver);
-		return res;
-	}
+	/* Don't exit if this one fails, we still want the I2C variants
+	   to work! */
+	if (i2c_isa_add_driver(&lm78_isa_driver))
+		isa_address = 0;
 
 	return 0;
 }
 
 static void __exit sm_lm78_exit(void)
 {
-	i2c_isa_del_driver(&lm78_isa_driver);
+	if (isa_address)
+		i2c_isa_del_driver(&lm78_isa_driver);
 	i2c_del_driver(&lm78_driver);
 }
 
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 47132fd..beb881c 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -2,8 +2,8 @@
     smsc47m1.c - Part of lm_sensors, Linux kernel modules
                  for hardware monitoring
 
-    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
-    LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
+    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
+    LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
 
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
@@ -380,8 +380,8 @@
 	val = superio_inb(SUPERIO_REG_DEVID);
 
 	/*
-	 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
-	 * 0x5F) and LPC47B27x (device id 0x51) have fan control.
+	 * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
+	 * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control.
 	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
 	 * can do much more besides (device id 0x60).
 	 * The LPC47M997 is undocumented, but seems to be compatible with
@@ -390,7 +390,8 @@
 	if (val == 0x51)
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
 	else if (val == 0x59)
-		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n");
+		printk(KERN_INFO "smsc47m1: Found SMSC "
+		       "LPC47M10x/LPC47M112/LPC47M13x\n");
 	else if (val == 0x5F)
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
 	else if (val == 0x60)
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 833faa2..2257806 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -354,6 +354,8 @@
 	case 0:
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
 		    | ((data->fan_div[0] & 0x03) << 4);
+		/* fan5 input control bit is write only, compute the value */
+		reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
 		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
 		    | ((data->fan_div[0] & 0x04) << 3);
@@ -362,6 +364,8 @@
 	case 1:
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
 		    | ((data->fan_div[1] & 0x03) << 6);
+		/* fan5 input control bit is write only, compute the value */
+		reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
 		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
 		    | ((data->fan_div[1] & 0x04) << 4);
@@ -1216,13 +1220,16 @@
 	superio_exit();
 
 	/* It looks like fan4 and fan5 pins can be alternatively used
-	   as fan on/off switches */
+	   as fan on/off switches, but fan5 control is write only :/
+	   We assume that if the serial interface is disabled, designers
+	   connected fan5 as input unless they are emitting log 1, which
+	   is not the default. */
 
 	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
 	i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
 	if ((i & (1 << 2)) && (!fan4pin))
 		data->has_fan |= (1 << 3);
-	if ((i & (1 << 0)) && (!fan5pin))
+	if (!(i & (1 << 1)) && (!fan5pin))
 		data->has_fan |= (1 << 4);
 
 	/* Register sysfs hooks */
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index a4584ec..1232171 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1099,7 +1099,8 @@
 	   bank. */
 	if (kind < 0) {
 		if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
-			dev_dbg(dev, "Detection failed at step 3\n");
+			dev_dbg(&adapter->dev, "Detection of w83781d chip "
+				"failed at step 3\n");
 			err = -ENODEV;
 			goto ERROR2;
 		}
@@ -1109,7 +1110,8 @@
 		if ((!(val1 & 0x07)) &&
 		    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
 		     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
-			dev_dbg(dev, "Detection failed at step 4\n");
+			dev_dbg(&adapter->dev, "Detection of w83781d chip "
+				"failed at step 4\n");
 			err = -ENODEV;
 			goto ERROR2;
 		}
@@ -1119,7 +1121,8 @@
 				  ((val1 & 0x80) && (val2 == 0x5c)))) {
 			if (w83781d_read_value
 			    (client, W83781D_REG_I2C_ADDR) != address) {
-				dev_dbg(dev, "Detection failed at step 5\n");
+				dev_dbg(&adapter->dev, "Detection of w83781d "
+					"chip failed at step 5\n");
 				err = -ENODEV;
 				goto ERROR2;
 			}
@@ -1141,8 +1144,8 @@
 		else if (val2 == 0x12)
 			vendid = asus;
 		else {
-			dev_dbg(dev, "Chip was made by neither "
-				"Winbond nor Asus?\n");
+			dev_dbg(&adapter->dev, "w83781d chip vendor is "
+				"neither Winbond nor Asus\n");
 			err = -ENODEV;
 			goto ERROR2;
 		}
@@ -1161,10 +1164,9 @@
 			kind = as99127f;
 		else {
 			if (kind == 0)
-				dev_warn(dev, "Ignoring 'force' "
+				dev_warn(&adapter->dev, "Ignoring 'force' "
 					 "parameter for unknown chip at "
-					 "adapter %d, address 0x%02x\n",
-					 i2c_adapter_id(adapter), address);
+					 "address 0x%02x\n", address);
 			err = -EINVAL;
 			goto ERROR2;
 		}
@@ -1685,11 +1687,10 @@
 	if (res)
 		return res;
 
-	res = i2c_isa_add_driver(&w83781d_isa_driver);
-	if (res) {
-		i2c_del_driver(&w83781d_driver);
-		return res;
-	}
+	/* Don't exit if this one fails, we still want the I2C variants
+	   to work! */
+	if (i2c_isa_add_driver(&w83781d_isa_driver))
+		isa_address = 0;
 
 	return 0;
 }
@@ -1697,7 +1698,8 @@
 static void __exit
 sensors_w83781d_exit(void)
 {
-	i2c_isa_del_driver(&w83781d_isa_driver);
+	if (isa_address)
+		i2c_isa_del_driver(&w83781d_isa_driver);
 	i2c_del_driver(&w83781d_driver);
 }
 
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 371ed4f..9e5f885 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -746,6 +746,52 @@
 
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
+#define IN_UNIT_ATTRS(X) \
+	&sda_in_input[X].dev_attr.attr, \
+	&sda_in_min[X].dev_attr.attr,   \
+	&sda_in_max[X].dev_attr.attr
+
+#define FAN_UNIT_ATTRS(X) \
+	&sda_fan_input[X].dev_attr.attr,        \
+	&sda_fan_min[X].dev_attr.attr,          \
+	&sda_fan_div[X].dev_attr.attr
+
+#define TEMP_UNIT_ATTRS(X) \
+	&sda_temp_input[X].dev_attr.attr,       \
+	&sda_temp_max[X].dev_attr.attr,         \
+	&sda_temp_max_hyst[X].dev_attr.attr
+
+static struct attribute *w83791d_attributes[] = {
+	IN_UNIT_ATTRS(0),
+	IN_UNIT_ATTRS(1),
+	IN_UNIT_ATTRS(2),
+	IN_UNIT_ATTRS(3),
+	IN_UNIT_ATTRS(4),
+	IN_UNIT_ATTRS(5),
+	IN_UNIT_ATTRS(6),
+	IN_UNIT_ATTRS(7),
+	IN_UNIT_ATTRS(8),
+	IN_UNIT_ATTRS(9),
+	FAN_UNIT_ATTRS(0),
+	FAN_UNIT_ATTRS(1),
+	FAN_UNIT_ATTRS(2),
+	FAN_UNIT_ATTRS(3),
+	FAN_UNIT_ATTRS(4),
+	TEMP_UNIT_ATTRS(0),
+	TEMP_UNIT_ATTRS(1),
+	TEMP_UNIT_ATTRS(2),
+	&dev_attr_alarms.attr,
+	&sda_beep_ctrl[0].dev_attr.attr,
+	&sda_beep_ctrl[1].dev_attr.attr,
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	NULL
+};
+
+static const struct attribute_group w83791d_group = {
+	.attrs = w83791d_attributes,
+};
+
 /* This function is called when:
      * w83791d_driver is inserted (when this module is loaded), for each
        available adapter
@@ -967,41 +1013,20 @@
 	}
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&client->dev.kobj, &w83791d_group)))
+		goto error3;
+
+	/* Everything is ready, now register the working device */
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto error3;
+		goto error4;
 	}
 
-	for (i = 0; i < NUMBER_OF_VIN; i++) {
-		device_create_file(dev, &sda_in_input[i].dev_attr);
-		device_create_file(dev, &sda_in_min[i].dev_attr);
-		device_create_file(dev, &sda_in_max[i].dev_attr);
-	}
-
-	for (i = 0; i < NUMBER_OF_FANIN; i++) {
-		device_create_file(dev, &sda_fan_input[i].dev_attr);
-		device_create_file(dev, &sda_fan_div[i].dev_attr);
-		device_create_file(dev, &sda_fan_min[i].dev_attr);
-	}
-
-	for (i = 0; i < NUMBER_OF_TEMPIN; i++) {
-		device_create_file(dev, &sda_temp_input[i].dev_attr);
-		device_create_file(dev, &sda_temp_max[i].dev_attr);
-		device_create_file(dev, &sda_temp_max_hyst[i].dev_attr);
-	}
-
-	device_create_file(dev, &dev_attr_alarms);
-
-	for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) {
-		device_create_file(dev, &sda_beep_ctrl[i].dev_attr);
-	}
-
-	device_create_file(dev, &dev_attr_cpu0_vid);
-	device_create_file(dev, &dev_attr_vrm);
-
 	return 0;
 
+error4:
+	sysfs_remove_group(&client->dev.kobj, &w83791d_group);
 error3:
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
@@ -1025,8 +1050,10 @@
 	int err;
 
 	/* main client */
-	if (data)
+	if (data) {
 		hwmon_device_unregister(data->class_dev);
+		sysfs_remove_group(&client->dev.kobj, &w83791d_group);
+	}
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index caa8e5c..a591fe6 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -131,7 +131,7 @@
 }
 
 
-static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
+static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id) {
 	spin_lock(&lock);
 	pcf_pending = 1;
 	spin_unlock(&lock);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 80d4ba1..781a99c 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -320,7 +320,7 @@
 /*
  * IIC interrupt handler
  */
-static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t iic_handler(int irq, void *dev_id)
 {
 	struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
 	volatile struct iic_regs __iomem *iic = dev->vaddr;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 4436c89..d108ab4 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -120,7 +120,7 @@
  * Then it passes the SR flags of interest to BH via adap data
  */
 static irqreturn_t 
-iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) 
+iop3xx_i2c_irq_handler(int this_irq, void *dev_id) 
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
 	u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 4380653..8ed59a2 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -91,7 +91,7 @@
 	/* Now look for clients */
 	res = driver->attach_adapter(&isa_adapter);
 	if (res) {
-		dev_err(&isa_adapter.dev,
+		dev_dbg(&isa_adapter.dev,
 			"Driver %s failed to attach adapter, unregistering\n",
 			driver->driver.name);
 		driver_unregister(&driver->driver);
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 559a62b..f7d7186 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -140,8 +140,7 @@
 }
 
 
-static irqreturn_t iic_ite_handler(int this_irq, void *dev_id,
-							struct pt_regs *regs)
+static irqreturn_t iic_ite_handler(int this_irq, void *dev_id)
 {
 	spin_lock(&lock);
 	iic_pending = 1;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 155a986..ee65aa1 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -63,7 +63,7 @@
 	writeb(x, i2c->base + MPC_I2C_CR);
 }
 
-static irqreturn_t mpc_i2c_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
 {
 	struct mpc_i2c *i2c = dev_id;
 	if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index eacbaf7..bbc8e3a 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -278,7 +278,7 @@
 }
 
 static int
-mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs)
+mv64xxx_i2c_intr(int irq, void *dev_id)
 {
 	struct mv64xxx_i2c_data	*drv_data = dev_id;
 	unsigned long	flags;
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 3e276e9..f28a76d 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -143,7 +143,7 @@
 	}
 }
 
-static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ocores_isr(int irq, void *dev_id)
 {
 	struct ocores_i2c *i2c = dev_id;
 
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 81d87d2..dec04da 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -400,7 +400,7 @@
 }
 
 static irqreturn_t
-omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+omap_i2c_rev1_isr(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
 	u16 iv, w;
@@ -452,7 +452,7 @@
 }
 
 static irqreturn_t
-omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+omap_i2c_isr(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
 	u16 bits;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index d9b4ddb..407840b 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -99,7 +99,7 @@
 	return ret;
 }
 
-static irqreturn_t pca_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
+static irqreturn_t pca_handler(int this_irq, void *dev_id) {
 	wake_up_interruptible(&pca_wait);
 	return IRQ_HANDLED;
 }
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index a508cb9..648d555 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -182,9 +182,9 @@
 };
 
 
-static int i2c_powermac_remove(struct device *dev)
+static int i2c_powermac_remove(struct platform_device *dev)
 {
-	struct i2c_adapter	*adapter = dev_get_drvdata(dev);
+	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adapter);
 	int			rc;
 
@@ -195,16 +195,16 @@
 	if (rc)
 		printk("i2c-powermac.c: Failed to remove bus %s !\n",
 		       adapter->name);
-	dev_set_drvdata(dev, NULL);
+	platform_set_drvdata(dev, NULL);
 	kfree(adapter);
 
 	return 0;
 }
 
 
-static int i2c_powermac_probe(struct device *dev)
+static int __devexit i2c_powermac_probe(struct platform_device *dev)
 {
-	struct pmac_i2c_bus *bus = dev->platform_data;
+	struct pmac_i2c_bus *bus = dev->dev.platform_data;
 	struct device_node *parent = NULL;
 	struct i2c_adapter *adapter;
 	char name[32];
@@ -246,11 +246,11 @@
 		printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n");
 		return -ENOMEM;
 	}
-	dev_set_drvdata(dev, adapter);
+	platform_set_drvdata(dev, adapter);
 	strcpy(adapter->name, name);
 	adapter->algo = &i2c_powermac_algorithm;
 	i2c_set_adapdata(adapter, bus);
-	adapter->dev.parent = dev;
+	adapter->dev.parent = &dev->dev;
 	pmac_i2c_attach_adapter(bus, adapter);
 	rc = i2c_add_adapter(adapter);
 	if (rc) {
@@ -265,23 +265,25 @@
 }
 
 
-static struct device_driver i2c_powermac_driver = {
-	.name = "i2c-powermac",
-	.bus = &platform_bus_type,
+static struct platform_driver i2c_powermac_driver = {
 	.probe = i2c_powermac_probe,
-	.remove = i2c_powermac_remove,
+	.remove = __devexit_p(i2c_powermac_remove),
+	.driver = {
+		.name = "i2c-powermac",
+		.bus = &platform_bus_type,
+	},
 };
 
 static int __init i2c_powermac_init(void)
 {
-	driver_register(&i2c_powermac_driver);
+	platform_driver_register(&i2c_powermac_driver);
 	return 0;
 }
 
 
 static void __exit i2c_powermac_cleanup(void)
 {
-	driver_unregister(&i2c_powermac_driver);
+	platform_driver_unregister(&i2c_powermac_driver);
 }
 
 module_init(i2c_powermac_init);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index cd4ad98..81050d3 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -850,7 +850,7 @@
 	ICR = icr;
 }
 
-static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 {
 	struct pxa_i2c *i2c = dev_id;
 	u32 isr = ISR;
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
index 0ebec3c..8764df0 100644
--- a/drivers/i2c/busses/i2c-rpx.c
+++ b/drivers/i2c/busses/i2c-rpx.c
@@ -55,10 +55,10 @@
 	data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
 }
 
-static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data)
+static int rpx_install_isr(int irq, void (*func)(void *), void *data)
 {
 	/* install interrupt handler */
-	cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data);
+	cpm_install_handler(irq, func, data);
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9ebe429..4ca6de2 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -423,8 +423,7 @@
  * top level IRQ servicing routine
 */
 
-static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id,
-				   struct pt_regs *regs)
+static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
 {
 	struct s3c24xx_i2c *i2c = dev_id;
 	unsigned long status;
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 182f049..ccdf3e9 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -669,7 +669,7 @@
 	dump_regs(isp, "otg->isp1301");
 }
 
-static irqreturn_t omap_otg_irq(int irq, void *_isp, struct pt_regs *regs)
+static irqreturn_t omap_otg_irq(int irq, void *_isp)
 {
 	u16		otg_irq = OTG_IRQ_SRC_REG;
 	u32		otg_ctrl;
@@ -1181,7 +1181,7 @@
 	isp->working = 0;
 }
 
-static irqreturn_t isp1301_irq(int irq, void *isp, struct pt_regs *regs)
+static irqreturn_t isp1301_irq(int irq, void *isp)
 {
 	isp1301_defer_work(isp, WORK_UPDATE_OTG);
 	return IRQ_HANDLED;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 6a75782..60bef94 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -446,7 +446,7 @@
 	mutex_unlock(&tps->lock);
 }
 
-static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs)
+static irqreturn_t tps65010_irq(int irq, void *_tps)
 {
 	struct tps65010		*tps = _tps;
 
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 69bbb62..bddfebd 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -597,7 +597,7 @@
 	struct cdrom_info *cd = drive->driver_data;
 
 	ide_init_drive_cmd(rq);
-	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+	rq->cmd_type = REQ_TYPE_ATA_PC;
 	rq->rq_disk = cd->disk;
 }
 
@@ -716,7 +716,7 @@
 		ide_error(drive, "request sense failure", stat);
 		return 1;
 
-	} else if (blk_pc_request(rq)) {
+	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
 		/* All other functions, except for READ. */
 		unsigned long flags;
 
@@ -2023,7 +2023,8 @@
 		}
 		info->last_block = block;
 		return action;
-	} else if (rq->cmd_type == REQ_TYPE_SENSE) {
+	} else if (rq->cmd_type == REQ_TYPE_SENSE ||
+		   rq->cmd_type == REQ_TYPE_ATA_PC) {
 		return cdrom_do_packet_command(drive);
 	} else if (blk_pc_request(rq)) {
 		return cdrom_do_block_pc(drive, rq);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ba6039b..2614f41 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1562,7 +1562,7 @@
  *	on the hwgroup and the process begins again.
  */
  
-irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t ide_intr (int irq, void *dev_id)
 {
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 1d0470c..30175c7 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -524,8 +524,8 @@
 	task_ioreg_t *hobsptr	= args.hobRegister;
 	int err			= 0;
 	int tasksize		= sizeof(struct ide_task_request_s);
-	int taskin		= 0;
-	int taskout		= 0;
+	unsigned int taskin	= 0;
+	unsigned int taskout	= 0;
 	u8 io_32bit		= drive->io_32bit;
 	char __user *buf = (char __user *)arg;
 
@@ -538,8 +538,13 @@
 		return -EFAULT;
 	}
 
-	taskout = (int) req_task->out_size;
-	taskin  = (int) req_task->in_size;
+	taskout = req_task->out_size;
+	taskin  = req_task->in_size;
+	
+	if (taskin > 65536 || taskout > 65536) {
+		err = -EINVAL;
+		goto abort;
+	}
 
 	if (taskout) {
 		int outtotal = tasksize;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 4ab9311..b1d5291 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -673,7 +673,7 @@
  * be forgotten about...
  */
 
-static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hd_interrupt(int irq, void *dev_id)
 {
 	void (*handler)(void) = do_hd;
 
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index d655da7..b1730d7 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -78,7 +78,7 @@
 }
 
 #ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void macide_mediabay_interrupt(int irq, void *dev_id)
 {
 	int state = baboon->mb_status & 0x04;
 
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 66f6064..09c9e79 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -4,6 +4,7 @@
  *	Author:	Manish Lachwani, mlachwani@mvista.com
  * Copyright (C) 2004  MIPS Technologies, Inc.  All rights reserved.
  *	Author: Maciej W. Rozycki <macro@mips.com>
+ * Copyright (c) 2006  Maciej W. Rozycki
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -127,6 +128,7 @@
 	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 	hwif->irq = hwif->hw.irq;
 
+	probe_hwif_init(hwif);
 	dev_set_drvdata(dev, hwif);
 
 	return 0;
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 965c436..ad418ce 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -40,6 +40,19 @@
 
 static int ide_generic_all;		/* Set to claim all devices */
 
+/*
+ * the module_param_named() was added for the modular case
+ * the __setup() is left as compatibility for existing setups
+ */
+#ifndef MODULE
+static int __init ide_generic_all_on(char *unused)
+{
+	ide_generic_all = 1;
+	printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.");
+	return 1;
+}
+__setup("all-generic-ide", ide_generic_all_on);
+#endif
 module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
 MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
 
@@ -237,10 +250,12 @@
 	if (dev->vendor == PCI_VENDOR_ID_JMICRON && PCI_FUNC(dev->devfn) != 1)
 		goto out;
 
-	pci_read_config_word(dev, PCI_COMMAND, &command);
-	if (!(command & PCI_COMMAND_IO)) {
-		printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
-		goto out;
+	if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		if (!(command & PCI_COMMAND_IO)) {
+			printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
+			goto out;
+		}
 	}
 	ret = ide_setup_pci_device(dev, d);
 out:
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index f3fe287..244f7eb 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -774,7 +774,7 @@
 	ioc4_unregister_submodule(&ioc4_ide_submodule);
 }
 
-module_init(ioc4_ide_init);
+late_initcall(ioc4_ide_init); /* Call only after IDE init is done */
 module_exit(ioc4_ide_exit);
 
 MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 3e7974c..8e7b83f 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1614,7 +1614,7 @@
 {
 	struct host_info *hi = (struct host_info *)__hi;
 	struct hpsb_host *host = hi->host;
-	unsigned int g, generation = get_hpsb_generation(host) - 1;
+	unsigned int g, generation = 0;
 	int i, reset_cycles = 0;
 
 	/* Setup our device-model entries */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 8fd0030..dea1352 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -2301,8 +2301,7 @@
 	spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
 }
 
-static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
-                             struct pt_regs *regs_are_unused)
+static irqreturn_t ohci_irq_handler(int irq, void *dev_id)
 {
 	quadlet_t event, node_id;
 	struct ti_ohci *ohci = (struct ti_ohci *)dev_id;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index b4f146f..0a7412e 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -839,8 +839,7 @@
  ********************************************************/
 
 
-static irqreturn_t lynx_irq_handler(int irq, void *dev_id,
-                             struct pt_regs *regs_are_unused)
+static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
 {
         struct ti_lynx *lynx = (struct ti_lynx *)dev_id;
         struct hpsb_host *host = lynx->host;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index f35fcc4..25b1018 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -75,6 +75,7 @@
 	struct rb_root remote_sidr_table;
 	struct idr local_id_table;
 	__be32 random_id_operand;
+	struct list_head timewait_list;
 	struct workqueue_struct *wq;
 } cm;
 
@@ -112,6 +113,7 @@
 
 struct cm_timewait_info {
 	struct cm_work work;			/* Must be first. */
+	struct list_head list;
 	struct rb_node remote_qp_node;
 	struct rb_node remote_id_node;
 	__be64 remote_ca_guid;
@@ -647,13 +649,6 @@
 
 static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
 {
-	unsigned long flags;
-
-	if (!timewait_info->inserted_remote_id &&
-	    !timewait_info->inserted_remote_qp)
-	    return;
-
-	spin_lock_irqsave(&cm.lock, flags);
 	if (timewait_info->inserted_remote_id) {
 		rb_erase(&timewait_info->remote_id_node, &cm.remote_id_table);
 		timewait_info->inserted_remote_id = 0;
@@ -663,7 +658,6 @@
 		rb_erase(&timewait_info->remote_qp_node, &cm.remote_qp_table);
 		timewait_info->inserted_remote_qp = 0;
 	}
-	spin_unlock_irqrestore(&cm.lock, flags);
 }
 
 static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
@@ -684,8 +678,12 @@
 static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
 {
 	int wait_time;
+	unsigned long flags;
 
+	spin_lock_irqsave(&cm.lock, flags);
 	cm_cleanup_timewait(cm_id_priv->timewait_info);
+	list_add_tail(&cm_id_priv->timewait_info->list, &cm.timewait_list);
+	spin_unlock_irqrestore(&cm.lock, flags);
 
 	/*
 	 * The cm_id could be destroyed by the user before we exit timewait.
@@ -701,9 +699,13 @@
 
 static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
 {
+	unsigned long flags;
+
 	cm_id_priv->id.state = IB_CM_IDLE;
 	if (cm_id_priv->timewait_info) {
+		spin_lock_irqsave(&cm.lock, flags);
 		cm_cleanup_timewait(cm_id_priv->timewait_info);
+		spin_unlock_irqrestore(&cm.lock, flags);
 		kfree(cm_id_priv->timewait_info);
 		cm_id_priv->timewait_info = NULL;
 	}
@@ -1307,6 +1309,7 @@
 	if (timewait_info) {
 		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
 					   timewait_info->work.remote_id);
+		cm_cleanup_timewait(cm_id_priv->timewait_info);
 		spin_unlock_irqrestore(&cm.lock, flags);
 		if (cur_cm_id_priv) {
 			cm_dup_req_handler(work, cur_cm_id_priv);
@@ -1315,7 +1318,8 @@
 			cm_issue_rej(work->port, work->mad_recv_wc,
 				     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
 				     NULL, 0);
-		goto error;
+		listen_cm_id_priv = NULL;
+		goto out;
 	}
 
 	/* Find matching listen request. */
@@ -1323,21 +1327,20 @@
 					   req_msg->service_id,
 					   req_msg->private_data);
 	if (!listen_cm_id_priv) {
+		cm_cleanup_timewait(cm_id_priv->timewait_info);
 		spin_unlock_irqrestore(&cm.lock, flags);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
 			     NULL, 0);
-		goto error;
+		goto out;
 	}
 	atomic_inc(&listen_cm_id_priv->refcount);
 	atomic_inc(&cm_id_priv->refcount);
 	cm_id_priv->id.state = IB_CM_REQ_RCVD;
 	atomic_inc(&cm_id_priv->work_count);
 	spin_unlock_irqrestore(&cm.lock, flags);
+out:
 	return listen_cm_id_priv;
-
-error:	cm_cleanup_timewait(cm_id_priv->timewait_info);
-	return NULL;
 }
 
 static int cm_req_handler(struct cm_work *work)
@@ -1899,6 +1902,32 @@
 }
 EXPORT_SYMBOL(ib_send_cm_drep);
 
+static int cm_issue_drep(struct cm_port *port,
+			 struct ib_mad_recv_wc *mad_recv_wc)
+{
+	struct ib_mad_send_buf *msg = NULL;
+	struct cm_dreq_msg *dreq_msg;
+	struct cm_drep_msg *drep_msg;
+	int ret;
+
+	ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
+	if (ret)
+		return ret;
+
+	dreq_msg = (struct cm_dreq_msg *) mad_recv_wc->recv_buf.mad;
+	drep_msg = (struct cm_drep_msg *) msg->mad;
+
+	cm_format_mad_hdr(&drep_msg->hdr, CM_DREP_ATTR_ID, dreq_msg->hdr.tid);
+	drep_msg->remote_comm_id = dreq_msg->local_comm_id;
+	drep_msg->local_comm_id = dreq_msg->remote_comm_id;
+
+	ret = ib_post_send_mad(msg, NULL);
+	if (ret)
+		cm_free_msg(msg);
+
+	return ret;
+}
+
 static int cm_dreq_handler(struct cm_work *work)
 {
 	struct cm_id_private *cm_id_priv;
@@ -1910,8 +1939,10 @@
 	dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
 	cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
 				   dreq_msg->local_comm_id);
-	if (!cm_id_priv)
+	if (!cm_id_priv) {
+		cm_issue_drep(work->port, work->mad_recv_wc);
 		return -EINVAL;
+	}
 
 	work->cm_event.private_data = &dreq_msg->private_data;
 
@@ -2601,28 +2632,29 @@
 {
 	struct cm_timewait_info *timewait_info;
 	struct cm_id_private *cm_id_priv;
-	unsigned long flags;
 	int ret;
 
 	timewait_info = (struct cm_timewait_info *)work;
-	cm_cleanup_timewait(timewait_info);
+	spin_lock_irq(&cm.lock);
+	list_del(&timewait_info->list);
+	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv = cm_acquire_id(timewait_info->work.local_id,
 				   timewait_info->work.remote_id);
 	if (!cm_id_priv)
 		return -EINVAL;
 
-	spin_lock_irqsave(&cm_id_priv->lock, flags);
+	spin_lock_irq(&cm_id_priv->lock);
 	if (cm_id_priv->id.state != IB_CM_TIMEWAIT ||
 	    cm_id_priv->remote_qpn != timewait_info->remote_qpn) {
-		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		spin_unlock_irq(&cm_id_priv->lock);
 		goto out;
 	}
 	cm_id_priv->id.state = IB_CM_IDLE;
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
-	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	if (ret)
 		cm_process_work(cm_id_priv, work);
@@ -3374,6 +3406,7 @@
 	idr_init(&cm.local_id_table);
 	get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
 	idr_pre_get(&cm.local_id_table, GFP_KERNEL);
+	INIT_LIST_HEAD(&cm.timewait_list);
 
 	cm.wq = create_workqueue("ib_cm");
 	if (!cm.wq)
@@ -3391,7 +3424,20 @@
 
 static void __exit ib_cm_cleanup(void)
 {
+	struct cm_timewait_info *timewait_info, *tmp;
+
+	spin_lock_irq(&cm.lock);
+	list_for_each_entry(timewait_info, &cm.timewait_list, list)
+		cancel_delayed_work(&timewait_info->work.work);
+	spin_unlock_irq(&cm.lock);
+
 	destroy_workqueue(cm.wq);
+
+	list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
+		list_del(&timewait_info->list);
+		kfree(timewait_info);
+	}
+
 	ib_unregister_client(&cm_client);
 	idr_destroy(&cm.local_id_table);
 }
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 9e9120f..9e7bd94 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -72,7 +72,7 @@
 static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 static void c2_tx_interrupt(struct net_device *netdev);
 static void c2_rx_interrupt(struct net_device *netdev);
-static irqreturn_t c2_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t c2_interrupt(int irq, void *dev_id);
 static void c2_tx_timeout(struct net_device *netdev);
 static int c2_change_mtu(struct net_device *netdev, int new_mtu);
 static void c2_reset(struct c2_port *c2_port);
@@ -544,7 +544,7 @@
 /*
  * Handle netisr0 TX & RX interrupts.
  */
-static irqreturn_t c2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t c2_interrupt(int irq, void *dev_id)
 {
 	unsigned int netisr0, dmaisr;
 	int handled = 0;
@@ -1243,7 +1243,7 @@
 
 static int __init c2_init_module(void)
 {
-	return pci_module_init(&c2_pci_driver);
+	return pci_register_driver(&c2_pci_driver);
 }
 
 static void __exit c2_exit_module(void)
diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
index 3aae497..a31439b 100644
--- a/drivers/infiniband/hw/amso1100/c2_ae.c
+++ b/drivers/infiniband/hw/amso1100/c2_ae.c
@@ -66,7 +66,6 @@
 	}
 }
 
-#ifdef DEBUG
 static const char* to_event_str(int event)
 {
 	static const char* event_str[] = {
@@ -144,7 +143,6 @@
 		return "<invalid QP state>";
 	};
 }
-#endif
 
 void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
 {
diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
index 1226113..5bcf697 100644
--- a/drivers/infiniband/hw/amso1100/c2_qp.c
+++ b/drivers/infiniband/hw/amso1100/c2_qp.c
@@ -35,6 +35,8 @@
  *
  */
 
+#include <linux/delay.h>
+
 #include "c2.h"
 #include "c2_vq.h"
 #include "c2_status.h"
@@ -705,10 +707,8 @@
 	 * cannot get on the bus and the card and system hang in a
 	 * deadlock -- thus the need for this code. [TOT]
 	 */
-	while (readl(c2dev->regs + PCI_BAR0_ADAPTER_HINT) & 0x80000000) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(0);
-	}
+	while (readl(c2dev->regs + PCI_BAR0_ADAPTER_HINT) & 0x80000000)
+		udelay(10);
 
 	__raw_writel(C2_HINT_MAKE(mq_index, shared),
 		     c2dev->regs + PCI_BAR0_ADAPTER_HINT);
@@ -766,6 +766,7 @@
 	struct c2_dev *c2dev = to_c2dev(ibqp->device);
 	struct c2_qp *qp = to_c2qp(ibqp);
 	union c2wr wr;
+	unsigned long lock_flags;
 	int err = 0;
 
 	u32 flags;
@@ -881,8 +882,10 @@
 		/*
 		 * Post the puppy!
 		 */
+		spin_lock_irqsave(&qp->lock, lock_flags);
 		err = qp_wr_post(&qp->sq_mq, &wr, qp, msg_size);
 		if (err) {
+			spin_unlock_irqrestore(&qp->lock, lock_flags);
 			break;
 		}
 
@@ -890,6 +893,7 @@
 		 * Enqueue mq index to activity FIFO.
 		 */
 		c2_activity(c2dev, qp->sq_mq.index, qp->sq_mq.hint_count);
+		spin_unlock_irqrestore(&qp->lock, lock_flags);
 
 		ib_wr = ib_wr->next;
 	}
@@ -905,6 +909,7 @@
 	struct c2_dev *c2dev = to_c2dev(ibqp->device);
 	struct c2_qp *qp = to_c2qp(ibqp);
 	union c2wr wr;
+	unsigned long lock_flags;
 	int err = 0;
 
 	if (qp->state > IB_QPS_RTS)
@@ -945,8 +950,10 @@
 			break;
 		}
 
+		spin_lock_irqsave(&qp->lock, lock_flags);
 		err = qp_wr_post(&qp->rq_mq, &wr, qp, qp->rq_mq.msg_size);
 		if (err) {
+			spin_unlock_irqrestore(&qp->lock, lock_flags);
 			break;
 		}
 
@@ -954,6 +961,7 @@
 		 * Enqueue mq index to activity FIFO
 		 */
 		c2_activity(c2dev, qp->rq_mq.index, qp->rq_mq.hint_count);
+		spin_unlock_irqrestore(&qp->lock, lock_flags);
 
 		ib_wr = ib_wr->next;
 	}
diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c
index e37c568..30409e1 100644
--- a/drivers/infiniband/hw/amso1100/c2_rnic.c
+++ b/drivers/infiniband/hw/amso1100/c2_rnic.c
@@ -150,8 +150,8 @@
 	    (struct c2wr_rnic_query_rep *) (unsigned long) (vq_req->reply_msg);
 	if (!reply)
 		err = -ENOMEM;
-
-	err = c2_errno(reply);
+	else
+		err = c2_errno(reply);
 	if (err)
 		goto bail2;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 2a65b5b..048cc44 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -360,7 +360,7 @@
 	return;
 }
 
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t ehca_interrupt_neq(int irq, void *dev_id)
 {
 	struct ehca_shca *shca = (struct ehca_shca*)dev_id;
 
@@ -393,7 +393,7 @@
 	return;
 }
 
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
 {
 	struct ehca_shca *shca = (struct ehca_shca*)dev_id;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 85bf1fe..be579cc 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -51,10 +51,10 @@
 
 int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
 
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t ehca_interrupt_neq(int irq, void *dev_id);
 void ehca_tasklet_neq(unsigned long data);
 
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
 void ehca_tasklet_eq(unsigned long data);
 
 struct ehca_cpu_comp_task {
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 29958b6..28c087b 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -67,19 +67,54 @@
 	.release = ipath_diag_release
 };
 
+static ssize_t ipath_diagpkt_write(struct file *fp,
+				   const char __user *data,
+				   size_t count, loff_t *off);
+
+static struct file_operations diagpkt_file_ops = {
+	.owner = THIS_MODULE,
+	.write = ipath_diagpkt_write,
+};
+
+static atomic_t diagpkt_count = ATOMIC_INIT(0);
+static struct cdev *diagpkt_cdev;
+static struct class_device *diagpkt_class_dev;
+
 int ipath_diag_add(struct ipath_devdata *dd)
 {
 	char name[16];
+	int ret = 0;
+
+	if (atomic_inc_return(&diagpkt_count) == 1) {
+		ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR,
+				      "ipath_diagpkt", &diagpkt_file_ops,
+				      &diagpkt_cdev, &diagpkt_class_dev);
+
+		if (ret) {
+			ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
+				      "device: %d", ret);
+			goto done;
+		}
+	}
 
 	snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit);
 
-	return ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
-			       &diag_file_ops, &dd->diag_cdev,
-			       &dd->diag_class_dev);
+	ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
+			      &diag_file_ops, &dd->diag_cdev,
+			      &dd->diag_class_dev);
+	if (ret)
+		ipath_dev_err(dd, "Couldn't create %s device: %d",
+			      name, ret);
+
+done:
+	return ret;
 }
 
 void ipath_diag_remove(struct ipath_devdata *dd)
 {
+	if (atomic_dec_and_test(&diagpkt_count))
+		ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev);
+
 	ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
 }
 
@@ -275,30 +310,6 @@
 	return ret;
 }
 
-static ssize_t ipath_diagpkt_write(struct file *fp,
-				   const char __user *data,
-				   size_t count, loff_t *off);
-
-static struct file_operations diagpkt_file_ops = {
-	.owner = THIS_MODULE,
-	.write = ipath_diagpkt_write,
-};
-
-static struct cdev *diagpkt_cdev;
-static struct class_device *diagpkt_class_dev;
-
-int __init ipath_diagpkt_add(void)
-{
-	return ipath_cdev_init(IPATH_DIAGPKT_MINOR,
-			       "ipath_diagpkt", &diagpkt_file_ops,
-			       &diagpkt_cdev, &diagpkt_class_dev);
-}
-
-void __exit ipath_diagpkt_remove(void)
-{
-	ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev);
-}
-
 /**
  * ipath_diagpkt_write - write an IB packet
  * @fp: the diag data device file pointer
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 12cefa6..b4ffaa7 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -2005,18 +2005,8 @@
 		goto bail_group;
 	}
 
-	ret = ipath_diagpkt_add();
-	if (ret < 0) {
-		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
-		       "diag data device: error %d\n", -ret);
-		goto bail_ipathfs;
-	}
-
 	goto bail;
 
-bail_ipathfs:
-	ipath_exit_ipathfs();
-
 bail_group:
 	ipath_driver_remove_group(&ipath_driver.driver);
 
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 6bee53c..d9079ee 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -839,7 +839,7 @@
 	}
 }
 
-irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
+irqreturn_t ipath_intr(int irq, void *data)
 {
 	struct ipath_devdata *dd = data;
 	u32 istat, chk0rcv = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index d7540b7..06d5020 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -606,7 +606,7 @@
 
 extern int ipath_diag_inuse;
 
-irqreturn_t ipath_intr(int irq, void *devid, struct pt_regs *regs);
+irqreturn_t ipath_intr(int irq, void *devid);
 void ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
 #if __IPATH_INFO || __IPATH_DBG
 extern const char *ipath_ibcstatus_str[];
@@ -869,9 +869,6 @@
 void ipath_device_remove_group(struct device *, struct ipath_devdata *);
 int ipath_expose_reset(struct device *);
 
-int ipath_diagpkt_add(void);
-void ipath_diagpkt_remove(void);
-
 int ipath_init_ipathfs(void);
 void ipath_exit_ipathfs(void);
 int ipathfs_add_device(struct ipath_devdata *);
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index e393681..149b369 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -39,6 +39,8 @@
 #include <linux/init.h>
 #include <linux/hardirq.h>
 
+#include <asm/io.h>
+
 #include <rdma/ib_pack.h>
 
 #include "mthca_dev.h"
@@ -210,6 +212,11 @@
 		mthca_write64(doorbell,
 			      dev->kar + MTHCA_CQ_DOORBELL,
 			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+		/*
+		 * Make sure doorbells don't leak out of CQ spinlock
+		 * and reach the HCA out of order:
+		 */
+		mmiowb();
 	}
 }
 
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index a29b1b6..e284e06 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -405,7 +405,7 @@
 	return eqes_found;
 }
 
-static irqreturn_t mthca_tavor_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
+static irqreturn_t mthca_tavor_interrupt(int irq, void *dev_ptr)
 {
 	struct mthca_dev *dev = dev_ptr;
 	u32 ecr;
@@ -432,8 +432,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mthca_tavor_msi_x_interrupt(int irq, void *eq_ptr,
-					 struct pt_regs *regs)
+static irqreturn_t mthca_tavor_msi_x_interrupt(int irq, void *eq_ptr)
 {
 	struct mthca_eq  *eq  = eq_ptr;
 	struct mthca_dev *dev = eq->dev;
@@ -446,7 +445,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mthca_arbel_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
+static irqreturn_t mthca_arbel_interrupt(int irq, void *dev_ptr)
 {
 	struct mthca_dev *dev = dev_ptr;
 	int work = 0;
@@ -467,8 +466,7 @@
 	return IRQ_RETVAL(work);
 }
 
-static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr,
-					       struct pt_regs *regs)
+static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr)
 {
 	struct mthca_eq  *eq  = eq_ptr;
 	struct mthca_dev *dev = eq->dev;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 981fe2e..fc67f78 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -179,6 +179,8 @@
 	props->max_mtu           = out_mad->data[41] & 0xf;
 	props->active_mtu        = out_mad->data[36] >> 4;
 	props->subnet_timeout    = out_mad->data[51] & 0x1f;
+	props->max_vl_num        = out_mad->data[37] >> 4;
+	props->init_type_reply   = out_mad->data[41] >> 4;
 
  out:
 	kfree(in_mad);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 5e5c58b..6a7822e 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -39,6 +39,8 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 
+#include <asm/io.h>
+
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
 #include <rdma/ib_pack.h>
@@ -1732,6 +1734,11 @@
 		mthca_write64(doorbell,
 			      dev->kar + MTHCA_SEND_DOORBELL,
 			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+		/*
+		 * Make sure doorbells don't leak out of SQ spinlock
+		 * and reach the HCA out of order:
+		 */
+		mmiowb();
 	}
 
 	qp->sq.next_ind = ind;
@@ -1851,6 +1858,12 @@
 	qp->rq.next_ind = ind;
 	qp->rq.head    += nreq;
 
+	/*
+	 * Make sure doorbells don't leak out of RQ spinlock and reach
+	 * the HCA out of order:
+	 */
+	mmiowb();
+
 	spin_unlock_irqrestore(&qp->rq.lock, flags);
 	return err;
 }
@@ -2112,6 +2125,12 @@
 			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
 	}
 
+	/*
+	 * Make sure doorbells don't leak out of SQ spinlock and reach
+	 * the HCA out of order:
+	 */
+	mmiowb();
+
 	spin_unlock_irqrestore(&qp->sq.lock, flags);
 	return err;
 }
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 0f316c8..f5d7677 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -35,6 +35,8 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
+#include <asm/io.h>
+
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
 #include "mthca_memfree.h"
@@ -201,6 +203,8 @@
 
 	if (mthca_is_memfree(dev))
 		srq->max = roundup_pow_of_two(srq->max + 1);
+	else
+		srq->max = srq->max + 1;
 
 	ds = max(64UL,
 		 roundup_pow_of_two(sizeof (struct mthca_next_seg) +
@@ -277,7 +281,7 @@
 	srq->first_free = 0;
 	srq->last_free  = srq->max - 1;
 
-	attr->max_wr    = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max;
+	attr->max_wr    = srq->max - 1;
 	attr->max_sge   = srq->max_gs;
 
 	return 0;
@@ -413,7 +417,7 @@
 		srq_attr->srq_limit = be16_to_cpu(tavor_ctx->limit_watermark);
 	}
 
-	srq_attr->max_wr  = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max;
+	srq_attr->max_wr  = srq->max - 1;
 	srq_attr->max_sge = srq->max_gs;
 
 out:
@@ -593,6 +597,12 @@
 			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
 	}
 
+	/*
+	 * Make sure doorbells don't leak out of SRQ spinlock and
+	 * reach the HCA out of order:
+	 */
+	mmiowb();
+
 	spin_unlock_irqrestore(&srq->lock, flags);
 	return err;
 }
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index f426a69..8bf5e9e 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -355,6 +355,11 @@
 	tx_req->skb = skb;
 	addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,
 			      DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(addr))) {
+		++priv->stats.tx_errors;
+		dev_kfree_skb_any(skb);
+		return;
+	}
 	pci_unmap_addr_set(tx_req, mapping, addr);
 
 	if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 44b9e5b..4b09147 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -343,29 +343,32 @@
 	 */
 	if (target->io_class == SRP_REV10_IB_IO_CLASS) {
 		memcpy(req->priv.initiator_port_id,
-		       target->srp_host->initiator_port_id + 8, 8);
+		       &target->path.sgid.global.interface_id, 8);
 		memcpy(req->priv.initiator_port_id + 8,
-		       target->srp_host->initiator_port_id, 8);
+		       &target->initiator_ext, 8);
 		memcpy(req->priv.target_port_id,     &target->ioc_guid, 8);
 		memcpy(req->priv.target_port_id + 8, &target->id_ext, 8);
 	} else {
 		memcpy(req->priv.initiator_port_id,
-		       target->srp_host->initiator_port_id, 16);
+		       &target->initiator_ext, 8);
+		memcpy(req->priv.initiator_port_id + 8,
+		       &target->path.sgid.global.interface_id, 8);
 		memcpy(req->priv.target_port_id,     &target->id_ext, 8);
 		memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
 	}
 
 	/*
 	 * Topspin/Cisco SRP targets will reject our login unless we
-	 * zero out the first 8 bytes of our initiator port ID.  The
-	 * second 8 bytes must be our local node GUID, but we always
-	 * use that anyway.
+	 * zero out the first 8 bytes of our initiator port ID and set
+	 * the second 8 bytes to the local node GUID.
 	 */
 	if (topspin_workarounds && !memcmp(&target->ioc_guid, topspin_oui, 3)) {
 		printk(KERN_DEBUG PFX "Topspin/Cisco initiator port ID workaround "
 		       "activated for target GUID %016llx\n",
 		       (unsigned long long) be64_to_cpu(target->ioc_guid));
 		memset(req->priv.initiator_port_id, 0, 8);
+		memcpy(req->priv.initiator_port_id + 8,
+		       &target->srp_host->dev->dev->node_guid, 8);
 	}
 
 	status = ib_send_cm_req(target->cm_id, &req->param);
@@ -1553,6 +1556,7 @@
 	SRP_OPT_MAX_SECT	= 1 << 5,
 	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
 	SRP_OPT_IO_CLASS	= 1 << 7,
+	SRP_OPT_INITIATOR_EXT	= 1 << 8,
 	SRP_OPT_ALL		= (SRP_OPT_ID_EXT	|
 				   SRP_OPT_IOC_GUID	|
 				   SRP_OPT_DGID		|
@@ -1569,6 +1573,7 @@
 	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
 	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
 	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
+	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
 	{ SRP_OPT_ERR,			NULL 			}
 };
 
@@ -1668,6 +1673,12 @@
 			target->io_class = token;
 			break;
 
+		case SRP_OPT_INITIATOR_EXT:
+			p = match_strdup(args);
+			target->initiator_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
+			kfree(p);
+			break;
+
 		default:
 			printk(KERN_WARNING PFX "unknown parameter or missing value "
 			       "'%s' in target creation request\n", p);
@@ -1708,7 +1719,6 @@
 	target_host->max_lun = SRP_MAX_LUN;
 
 	target = host_to_target(target_host);
-	memset(target, 0, sizeof *target);
 
 	target->io_class   = SRP_REV16A_IB_IO_CLASS;
 	target->scsi_host  = target_host;
@@ -1815,9 +1825,6 @@
 	host->dev  = device;
 	host->port = port;
 
-	host->initiator_port_id[7] = port;
-	memcpy(host->initiator_port_id + 8, &device->dev->node_guid, 8);
-
 	host->class_dev.class = &srp_class;
 	host->class_dev.dev   = device->dev->dma_device;
 	snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 5b581fb..d4e35ef 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -91,7 +91,6 @@
 };
 
 struct srp_host {
-	u8			initiator_port_id[16];
 	struct srp_device      *dev;
 	u8			port;
 	struct class_device	class_dev;
@@ -122,6 +121,7 @@
 	__be64			id_ext;
 	__be64			ioc_guid;
 	__be64			service_id;
+	__be64			initiator_ext;
 	u16			io_class;
 	struct srp_host	       *srp_host;
 	struct Scsi_Host       *scsi_host;
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 90de5af..1dec00e 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -82,17 +82,19 @@
 {
 	struct fm801_gp *gp;
 	struct gameport *port;
+	int error;
 
 	gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL);
 	port = gameport_allocate_port();
 	if (!gp || !port) {
 		printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
-		kfree(gp);
-		gameport_free_port(port);
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_out_free;
 	}
 
-	pci_enable_device(pci);
+	error = pci_enable_device(pci);
+	if (error)
+		goto err_out_free;
 
 	port->open = fm801_gp_open;
 #ifdef HAVE_COOKED
@@ -108,9 +110,8 @@
 	if (!gp->res_port) {
 		printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
 			port->io, port->io + 0x0f);
-		gameport_free_port(port);
-		kfree(gp);
-		return -EBUSY;
+		error = -EBUSY;
+		goto err_out_disable_dev;
 	}
 
 	pci_set_drvdata(pci, gp);
@@ -119,6 +120,13 @@
 	gameport_register_port(port);
 
 	return 0;
+
+ err_out_disable_dev:
+	pci_disable_device(pci);
+ err_out_free:
+	gameport_free_port(port);
+	kfree(gp);
+	return error;
 }
 
 static void __devexit fm801_gp_remove(struct pci_dev *pci)
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 3f47ae5..a0af97e 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -191,6 +191,8 @@
 
 static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
 {
+	int error;
+
 	down_write(&gameport_bus.subsys.rwsem);
 
 	gameport->dev.driver = &drv->driver;
@@ -198,8 +200,20 @@
 		gameport->dev.driver = NULL;
 		goto out;
 	}
-	device_bind_driver(&gameport->dev);
-out:
+
+	error = device_bind_driver(&gameport->dev);
+	if (error) {
+		printk(KERN_WARNING
+			"gameport: device_bind_driver() failed "
+			"for %s (%s) and %s, error: %d\n",
+			gameport->phys, gameport->name,
+			drv->description, error);
+		drv->disconnect(gameport);
+		gameport->dev.driver = NULL;
+		goto out;
+	}
+
+ out:
 	up_write(&gameport_bus.subsys.rwsem);
 }
 
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 7249d32..650acf3 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -57,7 +57,7 @@
 static struct input_dev *amijoy_dev[2];
 static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
 
-static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t amijoy_interrupt(int irq, void *dummy)
 {
 	int i, data = 0, button = 0;
 
@@ -69,8 +69,6 @@
 				case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
 			}
 
-			input_regs(amijoy_dev[i], fp);
-
 			input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
 
 			input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 8632d47..808f059 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -155,7 +155,7 @@
 	return -1;
 }
 
-void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
+void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
 {
 	struct input_dev *dev = iforce->dev;
 	int i;
@@ -183,9 +183,6 @@
 
 		case 0x01:	/* joystick position data */
 		case 0x03:	/* wheel position data */
-
-			input_regs(dev, regs);
-
 			if (HI(cmd) == 1) {
 				input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
 				input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
@@ -224,7 +221,6 @@
 			break;
 
 		case 0x02:	/* status report */
-			input_regs(dev, regs);
 			input_report_key(dev, BTN_DEAD, data[0] & 0x02);
 			input_sync(dev);
 
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 64a78c5..ca08f45 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -81,7 +81,7 @@
 }
 
 static irqreturn_t iforce_serio_irq(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct iforce *iforce = serio_get_drvdata(serio);
 
@@ -115,7 +115,7 @@
 	}
 
 	if (iforce->idx == iforce->len) {
-		iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data, regs);
+		iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);
 		iforce->pkt = 0;
 		iforce->id  = 0;
 		iforce->len = 0;
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index fe79d15..105112f 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -74,7 +74,7 @@
 	spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 }
 
-static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
+static void iforce_usb_irq(struct urb *urb)
 {
 	struct iforce *iforce = urb->context;
 	int status;
@@ -96,7 +96,7 @@
 	}
 
 	iforce_process_packet(iforce,
-		(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
+		(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1);
 
 exit:
 	status = usb_submit_urb (urb, GFP_ATOMIC);
@@ -105,7 +105,7 @@
 		     __FUNCTION__, status);
 }
 
-static void iforce_usb_out(struct urb *urb, struct pt_regs *regs)
+static void iforce_usb_out(struct urb *urb)
 {
 	struct iforce *iforce = urb->context;
 
@@ -119,7 +119,7 @@
 	wake_up(&iforce->wait);
 }
 
-static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
+static void iforce_usb_ctrl(struct urb *urb)
 {
 	struct iforce *iforce = urb->context;
 	if (urb->status) return;
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index 947df27..ffaeaef 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -160,7 +160,7 @@
 
 /* iforce-packets.c */
 int iforce_control_playback(struct iforce*, u16 id, unsigned int);
-void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs);
+void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data);
 int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data);
 void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ;
 int iforce_get_id_packet(struct iforce *iforce, char *packet);
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 168b106..e3d1944 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -82,7 +82,7 @@
 	return 0;
 }
 
-static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
+static void magellan_process_packet(struct magellan* magellan)
 {
 	struct input_dev *dev = magellan->dev;
 	unsigned char *data = magellan->data;
@@ -90,8 +90,6 @@
 
 	if (!magellan->idx) return;
 
-	input_regs(dev, regs);
-
 	switch (magellan->data[0]) {
 
 		case 'd':				/* Axis data */
@@ -115,12 +113,12 @@
 }
 
 static irqreturn_t magellan_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct magellan* magellan = serio_get_drvdata(serio);
 
 	if (data == '\r') {
-		magellan_process_packet(magellan, regs);
+		magellan_process_packet(magellan);
 		magellan->idx = 0;
 	} else {
 		if (magellan->idx < MAGELLAN_MAX_LENGTH)
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 7a19ee0..2a9808c 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -82,7 +82,7 @@
  * SpaceBall.
  */
 
-static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
+static void spaceball_process_packet(struct spaceball* spaceball)
 {
 	struct input_dev *dev = spaceball->dev;
 	unsigned char *data = spaceball->data;
@@ -90,8 +90,6 @@
 
 	if (spaceball->idx < 2) return;
 
-	input_regs(dev, regs);
-
 	switch (spaceball->data[0]) {
 
 		case 'D':					/* Ball data */
@@ -151,13 +149,13 @@
  */
 
 static irqreturn_t spaceball_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct spaceball *spaceball = serio_get_drvdata(serio);
 
 	switch (data) {
 		case 0xd:
-			spaceball_process_packet(spaceball, regs);
+			spaceball_process_packet(spaceball);
 			spaceball->idx = 0;
 			spaceball->escape = 0;
 			break;
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 3e2782e..c4db024 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -74,7 +74,7 @@
  * SpaceOrb.
  */
 
-static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
+static void spaceorb_process_packet(struct spaceorb *spaceorb)
 {
 	struct input_dev *dev = spaceorb->dev;
 	unsigned char *data = spaceorb->data;
@@ -86,8 +86,6 @@
 	for (i = 0; i < spaceorb->idx; i++) c ^= data[i];
 	if (c) return;
 
-	input_regs(dev, regs);
-
 	switch (data[0]) {
 
 		case 'R':				/* Reset packet */
@@ -131,12 +129,12 @@
 }
 
 static irqreturn_t spaceorb_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct spaceorb* spaceorb = serio_get_drvdata(serio);
 
 	if (~data & 0x80) {
-		if (spaceorb->idx) spaceorb_process_packet(spaceorb, regs);
+		if (spaceorb->idx) spaceorb_process_packet(spaceorb);
 		spaceorb->idx = 0;
 	}
 	if (spaceorb->idx < SPACEORB_MAX_LENGTH)
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 011ec48..1ffb032 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -64,15 +64,13 @@
  * Stinger. It updates the data accordingly.
  */
 
-static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
+static void stinger_process_packet(struct stinger *stinger)
 {
 	struct input_dev *dev = stinger->dev;
 	unsigned char *data = stinger->data;
 
 	if (!stinger->idx) return;
 
-	input_regs(dev, regs);
-
 	input_report_key(dev, BTN_A,	  ((data[0] & 0x20) >> 5));
 	input_report_key(dev, BTN_B,	  ((data[0] & 0x10) >> 4));
 	input_report_key(dev, BTN_C,	  ((data[0] & 0x08) >> 3));
@@ -99,7 +97,7 @@
  */
 
 static irqreturn_t stinger_interrupt(struct serio *serio,
-	unsigned char data, unsigned int flags, struct pt_regs *regs)
+	unsigned char data, unsigned int flags)
 {
 	struct stinger *stinger = serio_get_drvdata(serio);
 
@@ -109,7 +107,7 @@
 		stinger->data[stinger->idx++] = data;
 
 	if (stinger->idx == 4) {
-		stinger_process_packet(stinger, regs);
+		stinger_process_packet(stinger);
 		stinger->idx = 0;
 	}
 
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 076f237..49085df 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -104,7 +104,7 @@
  * Twiddler. It updates the data accordingly.
  */
 
-static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
+static void twidjoy_process_packet(struct twidjoy *twidjoy)
 {
 	struct input_dev *dev = twidjoy->dev;
 	unsigned char *data = twidjoy->data;
@@ -113,8 +113,6 @@
 
 	button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
 
-	input_regs(dev, regs);
-
 	for (bp = twidjoy_buttons; bp->bitmask; bp++) {
 		int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
 		int i;
@@ -141,7 +139,7 @@
  * packet processing routine.
  */
 
-static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs)
+static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
 {
 	struct twidjoy *twidjoy = serio_get_drvdata(serio);
 
@@ -158,7 +156,7 @@
 		twidjoy->data[twidjoy->idx++] = data;
 
 	if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
-		twidjoy_process_packet(twidjoy, regs);
+		twidjoy_process_packet(twidjoy);
 		twidjoy->idx = 0;
 	}
 
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index f9c1a03..35edea1 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -64,15 +64,13 @@
  * Warrior. It updates the data accordingly.
  */
 
-static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
+static void warrior_process_packet(struct warrior *warrior)
 {
 	struct input_dev *dev = warrior->dev;
 	unsigned char *data = warrior->data;
 
 	if (!warrior->idx) return;
 
-	input_regs(dev, regs);
-
 	switch ((data[0] >> 4) & 7) {
 		case 1:					/* Button data */
 			input_report_key(dev, BTN_TRIGGER,  data[3]       & 1);
@@ -101,12 +99,12 @@
  */
 
 static irqreturn_t warrior_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct warrior *warrior = serio_get_drvdata(serio);
 
 	if (data & 0x80) {
-		if (warrior->idx) warrior_process_packet(warrior, regs);
+		if (warrior->idx) warrior_process_packet(warrior);
 		warrior->idx = 0;
 		warrior->len = warrior_lengths[(data >> 4) & 7];
 	}
@@ -115,7 +113,7 @@
 		warrior->data[warrior->idx++] = data;
 
 	if (warrior->idx == warrior->len) {
-		if (warrior->idx) warrior_process_packet(warrior, regs);
+		if (warrior->idx) warrior_process_packet(warrior);
 		warrior->idx = 0;
 		warrior->len = 0;
 	}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 679bde3..81a333f 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -166,7 +166,7 @@
 
 config KEYBOARD_HIL_OLD
 	tristate "HP HIL keyboard support (simple driver)"
-	depends on GSC
+	depends on GSC || HP300
 	default y
 	help
 	  The "Human Interface Loop" is a older, 8-channel USB-like
@@ -183,7 +183,7 @@
 
 config KEYBOARD_HIL
 	tristate "HP HIL keyboard support"
-	depends on GSC
+	depends on GSC || HP300
 	default y
 	select HP_SDC
 	select HIL_MLC
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index f1f9db9..8abdbd0 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -158,7 +158,7 @@
 
 static struct input_dev *amikbd_dev;
 
-static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t amikbd_interrupt(int irq, void *dummy)
 {
 	unsigned char scancode, down;
 
@@ -171,8 +171,6 @@
 	scancode >>= 1;
 
 	if (scancode < 0x78) {		/* scancodes < 0x78 are keys */
-		input_regs(amikbd_dev, fp);
-
 		if (scancode == 98) {	/* CapsLock is a toggle switch key on Amiga */
 			input_report_key(amikbd_dev, scancode, 1);
 			input_report_key(amikbd_dev, scancode, 0);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 40244d4..cbb9366 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -221,6 +221,7 @@
 	unsigned long xl_bit;
 	unsigned int last;
 	unsigned long time;
+	unsigned long err_count;
 
 	struct work_struct event_work;
 	struct mutex event_mutex;
@@ -234,11 +235,13 @@
 #define ATKBD_DEFINE_ATTR(_name)						\
 static ssize_t atkbd_show_##_name(struct atkbd *, char *);			\
 static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t);		\
-static ssize_t atkbd_do_show_##_name(struct device *d, struct device_attribute *attr, char *b)			\
+static ssize_t atkbd_do_show_##_name(struct device *d,				\
+				struct device_attribute *attr, char *b)		\
 {										\
 	return atkbd_attr_show_helper(d, b, atkbd_show_##_name);		\
 }										\
-static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)	\
+static ssize_t atkbd_do_set_##_name(struct device *d,				\
+			struct device_attribute *attr, const char *b, size_t s)	\
 {										\
 	return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name);		\
 }										\
@@ -251,6 +254,32 @@
 ATKBD_DEFINE_ATTR(softrepeat);
 ATKBD_DEFINE_ATTR(softraw);
 
+#define ATKBD_DEFINE_RO_ATTR(_name)						\
+static ssize_t atkbd_show_##_name(struct atkbd *, char *);			\
+static ssize_t atkbd_do_show_##_name(struct device *d,				\
+				struct device_attribute *attr, char *b)		\
+{										\
+	return atkbd_attr_show_helper(d, b, atkbd_show_##_name);		\
+}										\
+static struct device_attribute atkbd_attr_##_name =				\
+	__ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL);
+
+ATKBD_DEFINE_RO_ATTR(err_count);
+
+static struct attribute *atkbd_attributes[] = {
+	&atkbd_attr_extra.attr,
+	&atkbd_attr_scroll.attr,
+	&atkbd_attr_set.attr,
+	&atkbd_attr_softrepeat.attr,
+	&atkbd_attr_softraw.attr,
+	&atkbd_attr_err_count.attr,
+	NULL
+};
+
+static struct attribute_group atkbd_attribute_group = {
+	.attrs	= atkbd_attributes,
+};
+
 static const unsigned int xl_table[] = {
 	ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK,
 	ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL,
@@ -318,7 +347,7 @@
  */
 
 static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
-			unsigned int flags, struct pt_regs *regs)
+			unsigned int flags)
 {
 	struct atkbd *atkbd = serio_get_drvdata(serio);
 	struct input_dev *dev = atkbd->dev;
@@ -396,7 +425,10 @@
 			add_release_event = 1;
 			break;
 		case ATKBD_RET_ERR:
+			atkbd->err_count++;
+#ifdef ATKBD_DEBUG
 			printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
+#endif
 			goto out;
 	}
 
@@ -458,7 +490,6 @@
 				atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
 			}
 
-			input_regs(dev, regs);
 			input_event(dev, EV_KEY, keycode, value);
 			input_sync(dev);
 
@@ -469,7 +500,6 @@
 	}
 
 	if (atkbd->scroll) {
-		input_regs(dev, regs);
 		if (click != -1)
 			input_report_key(dev, BTN_MIDDLE, click);
 		input_report_rel(dev, REL_WHEEL, scroll);
@@ -788,12 +818,7 @@
 	synchronize_sched();  /* Allow atkbd_interrupt()s to complete. */
 	flush_scheduled_work();
 
-	device_remove_file(&serio->dev, &atkbd_attr_extra);
-	device_remove_file(&serio->dev, &atkbd_attr_scroll);
-	device_remove_file(&serio->dev, &atkbd_attr_set);
-	device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
-	device_remove_file(&serio->dev, &atkbd_attr_softraw);
-
+	sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
 	input_unregister_device(atkbd->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
@@ -963,11 +988,7 @@
 	atkbd_set_keycode_table(atkbd);
 	atkbd_set_device_attrs(atkbd);
 
-	device_create_file(&serio->dev, &atkbd_attr_extra);
-	device_create_file(&serio->dev, &atkbd_attr_scroll);
-	device_create_file(&serio->dev, &atkbd_attr_set);
-	device_create_file(&serio->dev, &atkbd_attr_softrepeat);
-	device_create_file(&serio->dev, &atkbd_attr_softraw);
+	sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
 
 	atkbd_enable(atkbd);
 
@@ -1261,6 +1282,11 @@
 	return count;
 }
 
+static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
+{
+	return sprintf(buf, "%lu\n", atkbd->err_count);
+}
+
 
 static int __init atkbd_init(void)
 {
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 1e03153..befdd60 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -129,7 +129,7 @@
  */
 
 /* Scan the hardware keyboard and push any changes up through the input layer */
-static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
+static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data)
 {
 	unsigned int row, col, rowd;
 	unsigned long flags;
@@ -140,9 +140,6 @@
 
 	spin_lock_irqsave(&corgikbd_data->lock, flags);
 
-	if (regs)
-		input_regs(corgikbd_data->input, regs);
-
 	num_pressed = 0;
 	for (col = 0; col < KB_COLS; col++) {
 		/*
@@ -191,14 +188,14 @@
 /*
  * corgi keyboard interrupt handler.
  */
-static irqreturn_t corgikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t corgikbd_interrupt(int irq, void *dev_id)
 {
 	struct corgikbd *corgikbd_data = dev_id;
 
 	if (!timer_pending(&corgikbd_data->timer)) {
 		/** wait chattering delay **/
 		udelay(20);
-		corgikbd_scankeyboard(corgikbd_data, regs);
+		corgikbd_scankeyboard(corgikbd_data);
 	}
 
 	return IRQ_HANDLED;
@@ -210,7 +207,7 @@
 static void corgikbd_timer_callback(unsigned long data)
 {
 	struct corgikbd *corgikbd_data = (struct corgikbd *) data;
-	corgikbd_scankeyboard(corgikbd_data, NULL);
+	corgikbd_scankeyboard(corgikbd_data);
 }
 
 /*
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 2e4abdc..e774dd3 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -198,7 +198,7 @@
 }
 
 static irqreturn_t hil_kbd_interrupt(struct serio *serio, 
-	      unsigned char data, unsigned int flags, struct pt_regs *regs)
+	      unsigned char data, unsigned int flags)
 {
 	struct hil_kbd *kbd;
 	hil_packet packet;
@@ -328,7 +328,7 @@
 	kbd->dev->id.vendor	= PCI_VENDOR_ID_HP;
 	kbd->dev->id.product	= 0x0001; /* TODO: get from kbd->rsc */
 	kbd->dev->id.version	= 0x0100; /* TODO: get from kbd->rsc */
-	kbd->dev->dev		= &serio->dev;
+	kbd->dev->cdev.dev	= &serio->dev;
 
 	for (i = 0; i < 128; i++) {
 		set_bit(hil_kbd_set1[i], kbd->dev->keybit);
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index d22c7c6..54bc569 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -150,7 +150,7 @@
 /* 
  * Handle HIL interrupts.
  */
-static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs)
+static irqreturn_t hil_interrupt(int irq, void *handle)
 {
 	unsigned char s, c;
 	
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 5174224..708d5a1 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -453,8 +453,7 @@
  * is received.
  */
 static irqreturn_t
-lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
-		struct pt_regs *regs)
+lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags)
 {
 	struct lkkbd *lk = serio_get_drvdata (serio);
 	int i;
@@ -473,7 +472,6 @@
 
 	switch (data) {
 		case LK_ALL_KEYS_UP:
-			input_regs (lk->dev, regs);
 			for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
 				if (lk->keycode[i] != KEY_RESERVED)
 					input_report_key (lk->dev, lk->keycode[i], 0);
@@ -501,7 +499,6 @@
 
 		default:
 			if (lk->keycode[data] != KEY_RESERVED) {
-				input_regs (lk->dev, regs);
 				if (!test_bit (lk->keycode[data], lk->dev->key))
 					input_report_key (lk->dev, lk->keycode[data], 1);
 				else
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 83906f8..5788dbc 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -126,7 +126,7 @@
  */
 
 /* Scan the hardware keyboard and push any changes up through the input layer */
-static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
+static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
 {
 	unsigned int row, col, rowd, scancode;
 	unsigned long flags;
@@ -135,8 +135,6 @@
 
 	spin_lock_irqsave(&locomokbd->lock, flags);
 
-	input_regs(locomokbd->input, regs);
-
 	locomokbd_charge_all(membase);
 
 	num_pressed = 0;
@@ -171,13 +169,13 @@
 /*
  * LoCoMo keyboard interrupt handler.
  */
-static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
 {
 	struct locomokbd *locomokbd = dev_id;
 	/** wait chattering delay **/
 	udelay(100);
 
-	locomokbd_scankeyboard(locomokbd, regs);
+	locomokbd_scankeyboard(locomokbd);
 
 	return IRQ_HANDLED;
 }
@@ -188,7 +186,7 @@
 static void locomokbd_timer_callback(unsigned long data)
 {
 	struct locomokbd *locomokbd = (struct locomokbd *) data;
-	locomokbd_scankeyboard(locomokbd, NULL);
+	locomokbd_scankeyboard(locomokbd);
 }
 
 static int locomokbd_probe(struct locomo_dev *dev)
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 40a3f55..9282e4e 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -65,13 +65,12 @@
 };
 
 static irqreturn_t nkbd_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct nkbd *nkbd = serio_get_drvdata(serio);
 
 	/* invalid scan codes are probably the init sequence, so we ignore them */
 	if (nkbd->keycode[data & NKBD_KEY]) {
-		input_regs(nkbd->dev, regs);
 		input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
 		input_sync(nkbd->dev);
 	}
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index d436287..5680a6d 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -97,8 +97,7 @@
 #define		get_row_gpio_val(x)	0
 #endif
 
-static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
-				     struct pt_regs *regs)
+static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
 {
 	struct omap_kp *omap_kp = dev_id;
 
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index e385710..28b2748 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -176,7 +176,7 @@
  */
 
 /* Scan the hardware keyboard and push any changes up through the input layer */
-static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs)
+static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data)
 {
 	unsigned int row, col, rowd;
 	unsigned long flags;
@@ -187,8 +187,6 @@
 
 	spin_lock_irqsave(&spitzkbd_data->lock, flags);
 
-	input_regs(spitzkbd_data->input, regs);
-
 	num_pressed = 0;
 	for (col = 0; col < KB_COLS; col++) {
 		/*
@@ -239,14 +237,14 @@
 /*
  * spitz keyboard interrupt handler.
  */
-static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id)
 {
 	struct spitzkbd *spitzkbd_data = dev_id;
 
 	if (!timer_pending(&spitzkbd_data->timer)) {
 		/** wait chattering delay **/
 		udelay(20);
-		spitzkbd_scankeyboard(spitzkbd_data, regs);
+		spitzkbd_scankeyboard(spitzkbd_data);
 	}
 
 	return IRQ_HANDLED;
@@ -259,7 +257,7 @@
 {
 	struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
 
-	spitzkbd_scankeyboard(spitzkbd_data, NULL);
+	spitzkbd_scankeyboard(spitzkbd_data);
 }
 
 /*
@@ -267,7 +265,7 @@
  * We debounce the switches and pass them to the input system.
  */
 
-static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id)
 {
 	struct spitzkbd *spitzkbd_data = dev_id;
 
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c
index 04c54c5..e60937d 100644
--- a/drivers/input/keyboard/stowaway.c
+++ b/drivers/input/keyboard/stowaway.c
@@ -71,13 +71,12 @@
 };
 
 static irqreturn_t skbd_interrupt(struct serio *serio, unsigned char data,
-				  unsigned int flags, struct pt_regs *regs)
+				  unsigned int flags)
 {
 	struct skbd *skbd = serio_get_drvdata(serio);
 	struct input_dev *dev = skbd->dev;
 
 	if (skbd->keycode[data & SKBD_KEY_MASK]) {
-		input_regs(dev, regs);
 		input_report_key(dev, skbd->keycode[data & SKBD_KEY_MASK],
 				 !(data & SKBD_RELEASE));
 		input_sync(dev);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 9dbd7b8..cac4781 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -94,7 +94,7 @@
  */
 
 static irqreturn_t sunkbd_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct sunkbd* sunkbd = serio_get_drvdata(serio);
 
@@ -129,7 +129,6 @@
 				break;
 
 			if (sunkbd->keycode[data & SUNKBD_KEY]) {
-				input_regs(sunkbd->dev, regs);
                                 input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
 				input_sync(sunkbd->dev);
                         } else {
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 0821d53..8c11dc9 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -64,7 +64,7 @@
 };
 
 static irqreturn_t xtkbd_interrupt(struct serio *serio,
-	unsigned char data, unsigned int flags, struct pt_regs *regs)
+	unsigned char data, unsigned int flags)
 {
 	struct xtkbd *xtkbd = serio_get_drvdata(serio);
 
@@ -75,7 +75,6 @@
 		default:
 
 			if (xtkbd->keycode[data & XTKBD_KEY]) {
-				input_regs(xtkbd->dev, regs);
 				input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
 				input_sync(xtkbd->dev);
 			} else {
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index a6dfc74..ba0e88c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -73,7 +73,7 @@
 
 config HP_SDC_RTC
 	tristate "HP SDC Real Time Clock"       
-	depends on GSC
+	depends on GSC || HP300
 	select HP_SDC
 	help
 	  Say Y here if you want to support the built-in real time clock
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 1be9639..ab4da79 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -60,7 +60,7 @@
 
 static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
 
-static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
+static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos);
 
 static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
@@ -385,14 +385,14 @@
 	return 0;
 }
 
-static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
+static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos) {
 	ssize_t retval;
 
         if (count < sizeof(unsigned long))
                 return -EINVAL;
 
-	retval = put_user(68, (unsigned long *)buf);
+	retval = put_user(68, (unsigned long __user *)buf);
 	return retval;
 }
 
@@ -696,7 +696,7 @@
 	if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
 		return ret;
 	misc_register(&hp_sdc_rtc_dev);
-        create_proc_read_entry ("driver/rtc", 0, 0, 
+        create_proc_read_entry ("driver/rtc", 0, NULL,
 				hp_sdc_rtc_read_proc, NULL);
 
 	printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 805b636..105c6fc 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -79,7 +79,7 @@
 	return 0;
 }
 
-static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
 {
 	/* clear interrupt */
 	*IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 4639537..7b9d1c1 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -17,7 +17,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA.
  */
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/input.h>
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index f15ccf7..35d998c 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -119,7 +119,7 @@
 
 config MOUSE_HIL
 	tristate "HIL pointers (mice etc)."     
-	depends on GSC
+	depends on GSC || HP300
 	select HP_SDC
 	select HIL_MLC
 	help
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 450b68a..4e71a66 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -76,7 +76,7 @@
  * on a dualpoint, etc.
  */
 
-static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
+static void alps_process_packet(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
@@ -85,8 +85,6 @@
 	int x, y, z, ges, fin, left, right, middle;
 	int back = 0, forward = 0;
 
-	input_regs(dev, regs);
-
 	if ((packet[0] & 0xc8) == 0x08) {   /* 3-byte PS/2 packet */
 		input_report_key(dev2, BTN_LEFT,   packet[0] & 1);
 		input_report_key(dev2, BTN_RIGHT,  packet[0] & 2);
@@ -181,13 +179,13 @@
 	input_sync(dev);
 }
 
-static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
 
 	if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
 		if (psmouse->pktcnt == 3) {
-			alps_process_packet(psmouse, regs);
+			alps_process_packet(psmouse);
 			return PSMOUSE_FULL_PACKET;
 		}
 		return PSMOUSE_GOOD_DATA;
@@ -202,7 +200,7 @@
 		return PSMOUSE_BAD_DATA;
 
 	if (psmouse->pktcnt == 6) {
-		alps_process_packet(psmouse, regs);
+		alps_process_packet(psmouse);
 		return PSMOUSE_FULL_PACKET;
 	}
 
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index c8b2cc9..599a7b2 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -36,7 +36,7 @@
 static int amimouse_lastx, amimouse_lasty;
 static struct input_dev *amimouse_dev;
 
-static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t amimouse_interrupt(int irq, void *dummy)
 {
 	unsigned short joy0dat, potgor;
 	int nx, ny, dx, dy;
@@ -59,8 +59,6 @@
 
 	potgor = amiga_custom.potgor;
 
-	input_regs(amimouse_dev, fp);
-
 	input_report_rel(amimouse_dev, REL_X, dx);
 	input_report_rel(amimouse_dev, REL_Y, dy);
 
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index 69f0217..4f2b503 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -190,7 +190,7 @@
 }
 
 static irqreturn_t hil_ptr_interrupt(struct serio *serio, 
-        unsigned char data, unsigned int flags, struct pt_regs *regs)
+        unsigned char data, unsigned int flags)
 {
 	struct hil_ptr *ptr;
 	hil_packet packet;
@@ -375,7 +375,7 @@
 	ptr->dev->id.vendor	= PCI_VENDOR_ID_HP;
 	ptr->dev->id.product	= 0x0001; /* TODO: get from ptr->rsc */
 	ptr->dev->id.version	= 0x0100; /* TODO: get from ptr->rsc */
-	ptr->dev->dev		= &serio->dev;
+	ptr->dev->cdev.dev	= &serio->dev;
 
 	input_register_device(ptr->dev);
 	printk(KERN_INFO "input: %s (%s), ID: %d\n",
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 50f1fed..e1252fa 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -88,15 +88,13 @@
 
 static struct input_dev *inport_dev;
 
-static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t inport_interrupt(int irq, void *dev_id)
 {
 	unsigned char buttons;
 
 	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
 	outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
 
-	input_regs(inport_dev, regs);
-
 	outb(INPORT_REG_X, INPORT_CONTROL_PORT);
 	input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
 
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 5e9d250..c57e885 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -62,7 +62,7 @@
 };
 
 
-static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
 {
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = psmouse->dev;
@@ -70,8 +70,6 @@
 	if (psmouse->pktcnt != 3)
 		return PSMOUSE_GOOD_DATA;
 
-	input_regs(dev, regs);
-
 	/* calculate X and Y */
 	if ((packet[0] & 0x08) == 0x00) {
 		input_report_abs(dev, ABS_X,
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 9c7ce38..8e9c2f3 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -79,7 +79,7 @@
 
 static struct input_dev *logibm_dev;
 
-static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t logibm_interrupt(int irq, void *dev_id)
 {
 	char dx, dy;
 	unsigned char buttons;
@@ -95,7 +95,6 @@
 	dy |= (buttons & 0xf) << 4;
 	buttons = ~buttons >> 5;
 
-	input_regs(logibm_dev, regs);
 	input_report_rel(logibm_dev, REL_X, dx);
 	input_report_rel(logibm_dev, REL_Y, dy);
 	input_report_key(logibm_dev, BTN_RIGHT,  buttons & 1);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 7972eec..8a4f862 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -39,7 +39,7 @@
  * Process a PS2++ or PS2T++ packet.
  */
 
-static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
@@ -51,8 +51,6 @@
  * Full packet accumulated, process it
  */
 
-	input_regs(dev, regs);
-
 	if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
 
 		/* Logitech extended packet */
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index d284ea7..8c075aa 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -57,7 +57,7 @@
 static int pc110pad_data[3];
 static int pc110pad_count;
 
-static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t pc110pad_interrupt(int irq, void *ptr)
 {
 	int value     = inb_p(pc110pad_io);
 	int handshake = inb_p(pc110pad_io + 2);
@@ -71,7 +71,6 @@
 	if (pc110pad_count < 3)
 		return IRQ_HANDLED;
 
-	input_regs(pc110pad_dev, regs);
 	input_report_key(pc110pad_dev, BTN_TOUCH,
 		pc110pad_data[0] & 0x01);
 	input_report_abs(pc110pad_dev, ABS_X,
@@ -91,9 +90,9 @@
 
 static int pc110pad_open(struct input_dev *dev)
 {
-	pc110pad_interrupt(0, NULL, NULL);
-	pc110pad_interrupt(0, NULL, NULL);
-	pc110pad_interrupt(0, NULL, NULL);
+	pc110pad_interrupt(0, NULL);
+	pc110pad_interrupt(0, NULL);
+	pc110pad_interrupt(0, NULL);
 	outb(PC110PAD_ON, pc110pad_io + 2);
 	pc110pad_count = 0;
 
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 9fb7eb6..6f9b2c7 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -124,7 +124,7 @@
  * relevant events to the input module once full packet has arrived.
  */
 
-static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
@@ -136,8 +136,6 @@
  * Full packet accumulated, process it
  */
 
-	input_regs(dev, regs);
-
 /*
  * Scroll wheel on IntelliMice, scroll buttons on NetMice
  */
@@ -231,9 +229,9 @@
  * by calling corresponding protocol handler.
  */
 
-static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static int psmouse_handle_byte(struct psmouse *psmouse)
 {
-	psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs);
+	psmouse_ret_t rc = psmouse->protocol_handler(psmouse);
 
 	switch (rc) {
 		case PSMOUSE_BAD_DATA:
@@ -271,7 +269,7 @@
  */
 
 static irqreturn_t psmouse_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct psmouse *psmouse = serio_get_drvdata(serio);
 
@@ -327,7 +325,7 @@
  * Not a new device, try processing first byte normally
  */
 		psmouse->pktcnt = 1;
-		if (psmouse_handle_byte(psmouse, regs))
+		if (psmouse_handle_byte(psmouse))
 			goto out;
 
 		psmouse->packet[psmouse->pktcnt++] = data;
@@ -346,7 +344,7 @@
 	}
 
 	psmouse->last = jiffies;
-	psmouse_handle_byte(psmouse, regs);
+	psmouse_handle_byte(psmouse);
 
  out:
 	return IRQ_HANDLED;
@@ -940,7 +938,7 @@
 			psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 			for (i = 0; i < psmouse->pktsize; i++) {
 				psmouse->pktcnt++;
-				rc = psmouse->protocol_handler(psmouse, NULL);
+				rc = psmouse->protocol_handler(psmouse);
 				if (rc != PSMOUSE_GOOD_DATA)
 					break;
 			}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 4d9107f..1b74cae 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -62,7 +62,7 @@
 	unsigned int resync_time;
 	unsigned int smartscroll;	/* Logitech only */
 
-	psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
+	psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse);
 	void (*set_rate)(struct psmouse *psmouse, unsigned int rate);
 	void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution);
 
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 872b30b..ea04685 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -36,7 +36,7 @@
 static short rpcmouse_lastx, rpcmouse_lasty;
 static struct input_dev *rpcmouse_dev;
 
-static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rpcmouse_irq(int irq, void *dev_id)
 {
 	struct input_dev *dev = dev_id;
 	short x, y, dx, dy, b;
@@ -51,8 +51,6 @@
 	rpcmouse_lastx = x;
 	rpcmouse_lasty = y;
 
-	input_regs(dev, regs);
-
 	input_report_rel(dev, REL_X, dx);
 	input_report_rel(dev, REL_Y, -dy);
 
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 680b323..2a272c5 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -61,13 +61,11 @@
  * second, which is as good as a PS/2 or USB mouse.
  */
 
-static void sermouse_process_msc(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
+static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
 {
 	struct input_dev *dev = sermouse->dev;
 	signed char *buf = sermouse->buf;
 
-	input_regs(dev, regs);
-
 	switch (sermouse->count) {
 
 		case 0:
@@ -104,15 +102,13 @@
  * standard 3-byte packets and 1200 bps.
  */
 
-static void sermouse_process_ms(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
+static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
 {
 	struct input_dev *dev = sermouse->dev;
 	signed char *buf = sermouse->buf;
 
 	if (data & 0x40) sermouse->count = 0;
 
-	input_regs(dev, regs);
-
 	switch (sermouse->count) {
 
 		case 0:
@@ -206,7 +202,7 @@
  */
 
 static irqreturn_t sermouse_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct sermouse *sermouse = serio_get_drvdata(serio);
 
@@ -214,9 +210,9 @@
 	sermouse->last = jiffies;
 
 	if (sermouse->type > SERIO_SUN)
-		sermouse_process_ms(sermouse, data, regs);
+		sermouse_process_ms(sermouse, data);
 	else
-		sermouse_process_msc(sermouse, data, regs);
+		sermouse_process_msc(sermouse, data);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 392108c..49ac696 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -216,13 +216,13 @@
 	struct psmouse *child = serio_get_drvdata(ptport);
 
 	if (child && child->state == PSMOUSE_ACTIVATED) {
-		serio_interrupt(ptport, packet[1], 0, NULL);
-		serio_interrupt(ptport, packet[4], 0, NULL);
-		serio_interrupt(ptport, packet[5], 0, NULL);
+		serio_interrupt(ptport, packet[1], 0);
+		serio_interrupt(ptport, packet[4], 0);
+		serio_interrupt(ptport, packet[5], 0);
 		if (child->pktsize == 4)
-			serio_interrupt(ptport, packet[2], 0, NULL);
+			serio_interrupt(ptport, packet[2], 0);
 	} else
-		serio_interrupt(ptport, packet[1], 0, NULL);
+		serio_interrupt(ptport, packet[1], 0);
 }
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
@@ -469,13 +469,10 @@
 	return SYN_NEWABS_STRICT;
 }
 
-static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
 {
-	struct input_dev *dev = psmouse->dev;
 	struct synaptics_data *priv = psmouse->private;
 
-	input_regs(dev, regs);
-
 	if (psmouse->pktcnt >= 6) { /* Full packet received */
 		if (unlikely(priv->pkt_type == SYN_NEWABS))
 			priv->pkt_type = synaptics_detect_pkt_type(psmouse);
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index 47edcfd..ffdb50e 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -211,7 +211,7 @@
 }
 
 static void
-vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse)
 {
 	struct input_dev *dev = mouse->dev;
 	unsigned char *buf = mouse->buf;
@@ -258,7 +258,6 @@
 	/*
 	 * Report what we've found so far...
 	 */
-	input_regs (dev, regs);
 	input_report_key (dev, BTN_LEFT, left);
 	input_report_key (dev, BTN_MIDDLE, middle);
 	input_report_key (dev, BTN_RIGHT, right);
@@ -269,7 +268,7 @@
 }
 
 static void
-vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse)
 {
 	struct input_dev *dev = mouse->dev;
 	unsigned char *buf = mouse->buf;
@@ -312,7 +311,6 @@
 	/*
 	 * Report what we've found so far...
 	 */
-	input_regs (dev, regs);
 	input_report_key (dev, BTN_LEFT, left);
 	input_report_key (dev, BTN_MIDDLE, middle);
 	input_report_key (dev, BTN_RIGHT, right);
@@ -323,7 +321,7 @@
 }
 
 static void
-vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse)
 {
 	struct input_dev *dev = mouse->dev;
 	unsigned char *buf = mouse->buf;
@@ -367,7 +365,6 @@
 
 	if (error <= 0x1f) {
 		/* No (serious) error. Report buttons */
-		input_regs (dev, regs);
 		input_report_key (dev, BTN_LEFT, left);
 		input_report_key (dev, BTN_MIDDLE, middle);
 		input_report_key (dev, BTN_RIGHT, right);
@@ -395,7 +392,7 @@
 }
 
 static void
-vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
+vsxxxaa_parse_buffer (struct vsxxxaa *mouse)
 {
 	unsigned char *buf = mouse->buf;
 	int stray_bytes;
@@ -432,7 +429,7 @@
 				continue;
 			}
 
-			vsxxxaa_handle_REL_packet (mouse, regs);
+			vsxxxaa_handle_REL_packet (mouse);
 			continue; /* More to parse? */
 		}
 
@@ -446,7 +443,7 @@
 				continue;
 			}
 
-			vsxxxaa_handle_ABS_packet (mouse, regs);
+			vsxxxaa_handle_ABS_packet (mouse);
 			continue; /* More to parse? */
 		}
 
@@ -460,7 +457,7 @@
 				continue;
 			}
 
-			vsxxxaa_handle_POR_packet (mouse, regs);
+			vsxxxaa_handle_POR_packet (mouse);
 			continue; /* More to parse? */
 		}
 
@@ -469,13 +466,12 @@
 }
 
 static irqreturn_t
-vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
-		struct pt_regs *regs)
+vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags)
 {
 	struct vsxxxaa *mouse = serio_get_drvdata (serio);
 
 	vsxxxaa_queue_byte (mouse, data);
-	vsxxxaa_parse_buffer (mouse, regs);
+	vsxxxaa_parse_buffer (mouse);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 8cdbfec..adef447 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -112,7 +112,7 @@
 
 config HP_SDC
 	tristate "HP System Device Controller i8042 Support"
-	depends on GSC && SERIO
+	depends on (GSC || HP300) && SERIO
 	default y
 	---help---
 	  This option enables support for the "System Device
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 3df5eed..5a7b49c 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -37,14 +37,14 @@
 	unsigned int		open;
 };
 
-static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t amba_kmi_int(int irq, void *dev_id)
 {
 	struct amba_kmi_port *kmi = dev_id;
 	unsigned int status = readb(KMIIR);
 	int handled = IRQ_NONE;
 
 	while (status & KMIIR_RXINTR) {
-		serio_interrupt(kmi->io, readb(KMIDATA), 0, regs);
+		serio_interrupt(kmi->io, readb(KMIDATA), 0);
 		status = readb(KMIIR);
 		handled = IRQ_HANDLED;
 	}
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index bc6e87a..0d35018 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -71,9 +71,9 @@
  * is waiting in the 82C710.
  */
 
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id)
 {
-	return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs);
+	return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0);
 }
 
 /*
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index cde036a..74f14e0 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -82,7 +82,7 @@
 #define GSC_ID_MOUSE		1
 
 
-static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t gscps2_interrupt(int irq, void *dev);
 
 #define BUFFER_SIZE 0x0f
 
@@ -166,7 +166,7 @@
 
 	/* make sure any received data is returned as fast as possible */
 	/* this is important e.g. when we set the LEDs on the keyboard */
-	gscps2_interrupt(0, NULL, NULL);
+	gscps2_interrupt(0, NULL);
 
 	return 1;
 }
@@ -226,7 +226,7 @@
  * later.
  */
 
-static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t gscps2_interrupt(int irq, void *dev)
 {
 	struct gscps2port *ps2port;
 
@@ -267,7 +267,7 @@
 	    rxflags =	((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
 			((status & GSC_STAT_PERR) ? SERIO_PARITY  : 0 );
 
-	    serio_interrupt(ps2port->port, data, rxflags, regs);
+	    serio_interrupt(ps2port->port, data, rxflags);
 
 	  } /* while() */
 
@@ -306,7 +306,7 @@
 	/* enable it */
 	gscps2_enable(ps2port, ENABLE);
 
-	gscps2_interrupt(0, NULL, NULL);
+	gscps2_interrupt(0, NULL);
 
 	return 0;
 }
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index bbbe15e..49e11e2 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -162,10 +162,10 @@
 		if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
 			if (drv == NULL || drv->interrupt == NULL) goto skip;
 
-			drv->interrupt(serio, 0, 0, NULL);
-			drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
-			drv->interrupt(serio, HIL_PKT_CMD >> 8,  0, NULL);
-			drv->interrupt(serio, HIL_CMD_POL + cnt, 0, NULL);
+			drv->interrupt(serio, 0, 0);
+			drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
+			drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
+			drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
 		skip:
 			did = (p & HIL_PKT_ADDR_MASK) >> 8;
 			serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
@@ -174,10 +174,10 @@
 		}
 		cnt++; i++;
 		if (drv == NULL || drv->interrupt == NULL) continue;
-		drv->interrupt(serio, (p >> 24), 0, NULL);
-		drv->interrupt(serio, (p >> 16) & 0xff, 0, NULL);
-		drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0, NULL);
-		drv->interrupt(serio, p & 0xff, 0, NULL);
+		drv->interrupt(serio, (p >> 24), 0);
+		drv->interrupt(serio, (p >> 16) & 0xff, 0);
+		drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
+		drv->interrupt(serio, p & 0xff, 0);
 	}
 }
 
@@ -391,23 +391,23 @@
 }
 
 #define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
-{ HILSE_FUNC,		{ func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc },
+{ HILSE_FUNC,		{ .func = funct }, funct_arg, zero_rc, neg_rc, pos_rc },
 #define OUT(pack) \
-{ HILSE_OUT,		{ packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
+{ HILSE_OUT,		{ .packet = pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
 #define CTS \
-{ HILSE_CTS,		{ packet: 0    }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
+{ HILSE_CTS,		{ .packet = 0    }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
 #define EXPECT(comp, to, got, got_wrong, timed_out) \
-{ HILSE_EXPECT,		{ packet: comp }, to, got, got_wrong, timed_out },
+{ HILSE_EXPECT,		{ .packet = comp }, to, got, got_wrong, timed_out },
 #define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
-{ HILSE_EXPECT_LAST,	{ packet: comp }, to, got, got_wrong, timed_out },
+{ HILSE_EXPECT_LAST,	{ .packet = comp }, to, got, got_wrong, timed_out },
 #define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
-{ HILSE_EXPECT_DISC,	{ packet: comp }, to, got, got_wrong, timed_out },
+{ HILSE_EXPECT_DISC,	{ .packet = comp }, to, got, got_wrong, timed_out },
 #define IN(to, got, got_error, timed_out) \
-{ HILSE_IN,		{ packet: 0    }, to, got, got_error, timed_out },
+{ HILSE_IN,		{ .packet = 0    }, to, got, got_error, timed_out },
 #define OUT_DISC(pack) \
-{ HILSE_OUT_DISC,	{ packet: pack }, 0, 0, 0, 0 },
+{ HILSE_OUT_DISC,	{ .packet = pack }, 0, 0, 0, 0 },
 #define OUT_LAST(pack) \
-{ HILSE_OUT_LAST,	{ packet: pack }, 0, 0, 0, 0 },
+{ HILSE_OUT_LAST,	{ .packet = pack }, 0, 0, 0, 0 },
 
 struct hilse_node hil_mlc_se[HILSEN_END] = {
 
@@ -780,16 +780,16 @@
 	while ((last != idx) && (*last == 0)) last--;
 
 	while (idx != last) {
-		drv->interrupt(serio, 0, 0, NULL);
-		drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
-		drv->interrupt(serio, 0, 0, NULL);
-		drv->interrupt(serio, *idx, 0, NULL);
+		drv->interrupt(serio, 0, 0);
+		drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
+		drv->interrupt(serio, 0, 0);
+		drv->interrupt(serio, *idx, 0);
 		idx++;
 	}
-	drv->interrupt(serio, 0, 0, NULL);
-	drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
-	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
-	drv->interrupt(serio, *idx, 0, NULL);
+	drv->interrupt(serio, 0, 0);
+	drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
+	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0);
+	drv->interrupt(serio, *idx, 0);
 	
 	mlc->serio_oidx[map->didx] = 0;
 	mlc->serio_opacket[map->didx] = 0;
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index a10348b..9907ad3 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -202,7 +202,7 @@
 	}
 }
 
-static irqreturn_t hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
 	uint8_t status, data;
 
 	status = hp_sdc_status_in8();
@@ -253,7 +253,7 @@
 }
 
 
-static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) {
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
 	int status;
 	
 	status = hp_sdc_status_in8();
@@ -310,7 +310,7 @@
 				 * in tasklet/bh context.
 				 */
 				if (curr->act.irqhook) 
-					curr->act.irqhook(0, 0, 0, 0);
+					curr->act.irqhook(0, NULL, 0, 0);
 			}
 			curr->actidx = curr->idx;
 			curr->idx++;
@@ -525,7 +525,7 @@
 		up(curr->act.semaphore);
 	}
 	else if (act & HP_SDC_ACT_CALLBACK) {
-		curr->act.irqhook(0,0,0,0);
+		curr->act.irqhook(0,NULL,0,0);
 	}
 	if (curr->idx >= curr->endidx) { /* This transaction is over. */
 		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 1bb0c76..7e3141f 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -106,9 +106,10 @@
 static unsigned char i8042_mux_present;
 static unsigned char i8042_kbd_irq_registered;
 static unsigned char i8042_aux_irq_registered;
+static unsigned char i8042_suppress_kbd_ack;
 static struct platform_device *i8042_platform_device;
 
-static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t i8042_interrupt(int irq, void *dev_id);
 
 /*
  * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
@@ -271,7 +272,7 @@
  * characters later.
  */
 
-	i8042_interrupt(0, NULL, NULL);
+	i8042_interrupt(0, NULL);
 	return retval;
 }
 
@@ -309,14 +310,14 @@
  * to the upper layers.
  */
 
-static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i8042_interrupt(int irq, void *dev_id)
 {
 	struct i8042_port *port;
 	unsigned long flags;
 	unsigned char str, data;
 	unsigned int dfl;
 	unsigned int port_no;
-	int ret;
+	int ret = 1;
 
 	spin_lock_irqsave(&i8042_lock, flags);
 	str = i8042_read_status();
@@ -378,10 +379,16 @@
 	    dfl & SERIO_PARITY ? ", bad parity" : "",
 	    dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
-	if (likely(port->exists))
-		serio_interrupt(port->serio, data, dfl, regs);
+	if (unlikely(i8042_suppress_kbd_ack))
+		if (port_no == I8042_KBD_PORT_NO &&
+		    (data == 0xfa || data == 0xfe)) {
+			i8042_suppress_kbd_ack = 0;
+			goto out;
+		}
 
-	ret = 1;
+	if (likely(port->exists))
+		serio_interrupt(port->serio, data, dfl);
+
  out:
 	return IRQ_RETVAL(ret);
 }
@@ -519,7 +526,7 @@
 static struct completion i8042_aux_irq_delivered __devinitdata;
 static int i8042_irq_being_tested __devinitdata;
 
-static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id)
 {
 	unsigned long flags;
 	unsigned char str, data;
@@ -842,11 +849,13 @@
 	led ^= 0x01 | 0x04;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
+	i8042_suppress_kbd_ack = 1;
 	i8042_write_data(0xed); /* set leds */
 	DELAY;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
 	DELAY;
+	i8042_suppress_kbd_ack = 1;
 	i8042_write_data(led);
 	DELAY;
 	last_blink = count;
@@ -905,7 +914,7 @@
 	if (i8042_ports[I8042_KBD_PORT_NO].serio)
 		i8042_enable_kbd_port();
 
-	i8042_interrupt(0, NULL, NULL);
+	i8042_interrupt(0, NULL);
 
 	return 0;
 }
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index dcb16b5..e5b1b60 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -189,7 +189,7 @@
 		return -1;
 	}
 
-	mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING);
+	mutex_lock(&ps2dev->cmd_mutex);
 
 	serio_pause_rx(ps2dev->serio);
 	ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
@@ -296,6 +296,7 @@
 void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
 {
 	mutex_init(&ps2dev->cmd_mutex);
+	lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth);
 	init_waitqueue_head(&ps2dev->wait);
 	ps2dev->serio = serio;
 }
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index f08a5d0..558200e 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -72,8 +72,7 @@
 	return -1;
 }
 
-static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
-				     struct pt_regs *regs)
+static irqreturn_t maceps2_interrupt(int irq, void *dev_id)
 {
 	struct serio *dev = dev_id;
 	struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
@@ -81,7 +80,7 @@
 
 	if (port->status & PS2_STATUS_RX_FULL) {
 		byte = port->rx;
-		serio_interrupt(dev, byte & 0xff, 0, regs);
+		serio_interrupt(dev, byte & 0xff, 0);
         }
 
 	return IRQ_HANDLED;
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index a5c1fb3..688610e 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -102,7 +102,7 @@
 	return 0;
 }
 
-static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void parkbd_interrupt(int irq, void *dev_id)
 {
 
 	if (parkbd_writing) {
@@ -134,7 +134,7 @@
 		parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
 
 		if (parkbd_counter == parkbd_mode + 10)
-			serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
+			serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0);
 	}
 
 	parkbd_last = jiffies;
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index fb727c6..ea5e3c6 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -58,7 +58,7 @@
 	return 0;
 }
 
-static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t pcips2_interrupt(int irq, void *devid)
 {
 	struct pcips2_data *ps2if = devid;
 	unsigned char status, scancode;
@@ -80,7 +80,7 @@
 		if (hweight8(scancode) & 1)
 			flag ^= SERIO_PARITY;
 
-		serio_interrupt(ps2if->io, scancode, flag, regs);
+		serio_interrupt(ps2if->io, scancode, flag);
 	} while (1);
 	return IRQ_RETVAL(handled);
 }
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index d3827c5..cb89aff 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -53,14 +53,14 @@
 static struct serio *q40kbd_port;
 static struct platform_device *q40kbd_device;
 
-static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t q40kbd_interrupt(int irq, void *dev_id)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&q40kbd_lock, flags);
 
 	if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
-		serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
+		serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0);
 
 	master_outb(-1, KEYBOARD_UNLOCK_REG);
 
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 513d37f..49f8431 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -56,7 +56,7 @@
 	return 0;
 }
 
-static irqreturn_t rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rpckbd_rx(int irq, void *dev_id)
 {
 	struct serio *port = dev_id;
 	unsigned int byte;
@@ -65,13 +65,13 @@
 	while (iomd_readb(IOMD_KCTRL) & (1 << 5)) {
 		byte = iomd_readb(IOMD_KARTRX);
 
-		serio_interrupt(port, byte, 0, regs);
+		serio_interrupt(port, byte, 0);
 		handled = IRQ_HANDLED;
 	}
 	return handled;
 }
 
-static irqreturn_t rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rpckbd_tx(int irq, void *dev_id)
 {
 	return IRQ_HANDLED;
 }
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index ebd9976..5595087 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -40,7 +40,7 @@
  * at the most one, but we loop for safety.  If there was a
  * framing error, we have to manually clear the status.
  */
-static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ps2_rxint(int irq, void *dev_id)
 {
 	struct ps2if *ps2if = dev_id;
 	unsigned int scancode, flag, status;
@@ -58,7 +58,7 @@
 		if (hweight8(scancode) & 1)
 			flag ^= SERIO_PARITY;
 
-		serio_interrupt(ps2if->io, scancode, flag, regs);
+		serio_interrupt(ps2if->io, scancode, flag);
 
 		status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
         }
@@ -69,7 +69,7 @@
 /*
  * Completion of ps2 write
  */
-static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ps2_txint(int irq, void *dev_id)
 {
 	struct ps2if *ps2if = dev_id;
 	unsigned int status;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 3e76ad7..211943f 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -118,6 +118,8 @@
 
 static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
 {
+	int error;
+
 	down_write(&serio_bus.subsys.rwsem);
 
 	if (serio_match_port(drv->id_table, serio)) {
@@ -126,9 +128,19 @@
 			serio->dev.driver = NULL;
 			goto out;
 		}
-		device_bind_driver(&serio->dev);
+		error = device_bind_driver(&serio->dev);
+		if (error) {
+			printk(KERN_WARNING
+				"serio: device_bind_driver() failed "
+				"for %s (%s) and %s, error: %d\n",
+				serio->phys, serio->name,
+				drv->description, error);
+			serio_disconnect_driver(serio);
+			serio->dev.driver = NULL;
+			goto out;
+		}
 	}
-out:
+ out:
 	up_write(&serio_bus.subsys.rwsem);
 }
 
@@ -538,8 +550,12 @@
 		 "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
 	serio->dev.bus = &serio_bus;
 	serio->dev.release = serio_release_port;
-	if (serio->parent)
+	if (serio->parent) {
 		serio->dev.parent = &serio->parent->dev;
+		serio->depth = serio->parent->depth + 1;
+	} else
+		serio->depth = 0;
+	lockdep_set_subclass(&serio->lock, serio->depth);
 }
 
 /*
@@ -911,7 +927,7 @@
 }
 
 irqreturn_t serio_interrupt(struct serio *serio,
-		unsigned char data, unsigned int dfl, struct pt_regs *regs)
+		unsigned char data, unsigned int dfl)
 {
 	unsigned long flags;
 	irqreturn_t ret = IRQ_NONE;
@@ -919,7 +935,7 @@
 	spin_lock_irqsave(&serio->lock, flags);
 
         if (likely(serio->drv)) {
-                ret = serio->drv->interrupt(serio, data, dfl, regs);
+                ret = serio->drv->interrupt(serio, data, dfl);
 	} else if (!dfl && serio->registered) {
 		serio_rescan(serio);
 		ret = IRQ_HANDLED;
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 71a8eea..ba2a203 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -250,7 +250,7 @@
  *********************************************************************/
 
 static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
-					unsigned int dfl, struct pt_regs *regs)
+					unsigned int dfl)
 {
 	struct serio_raw *serio_raw = serio_get_drvdata(serio);
 	struct serio_raw_list *list;
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 54a680c..e1a3a79 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -117,9 +117,6 @@
  * serport_ldisc_receive() is called by the low level tty driver when characters
  * are ready for us. We forward the characters, one by one to the 'interrupt'
  * routine.
- *
- * FIXME: We should get pt_regs from the tty layer and forward them to
- *	  serio_interrupt here.
  */
 
 static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
@@ -134,7 +131,7 @@
 		goto out;
 
 	for (i = 0; i < count; i++)
-		serio_interrupt(serport->serio, cp[i], 0, NULL);
+		serio_interrupt(serport->serio, cp[i], 0);
 
 out:
 	spin_unlock_irqrestore(&serport->lock, flags);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 66e411b..f56d6a0 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -487,7 +487,7 @@
 	spin_unlock_irq(&ts->lock);
 }
 
-static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
+static irqreturn_t ads7846_irq(int irq, void *handle)
 {
 	struct ads7846 *ts = handle;
 	unsigned long flags;
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 9b66271..66121f6 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -173,7 +173,7 @@
 	return 1;
 }
 
-static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
+static void new_data(struct corgi_ts *corgi_ts)
 {
 	if (corgi_ts->power_mode != PWR_MODE_ACTIVE)
 		return;
@@ -181,7 +181,6 @@
 	if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
 		return;
 
-	input_regs(corgi_ts->input, regs);
 	input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x);
 	input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y);
 	input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
@@ -189,14 +188,14 @@
 	input_sync(corgi_ts->input);
 }
 
-static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
+static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
 {
 	if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
 		/* Disable Interrupt */
 		set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
 		if (read_xydata(corgi_ts)) {
 			corgi_ts->pendown = 1;
-			new_data(corgi_ts, regs);
+			new_data(corgi_ts);
 		}
 		mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
 	} else {
@@ -208,7 +207,7 @@
 
 		if (corgi_ts->pendown) {
 			corgi_ts->tc.pressure = 0;
-			new_data(corgi_ts, regs);
+			new_data(corgi_ts);
 		}
 
 		/* Enable Falling Edge */
@@ -220,13 +219,13 @@
 static void corgi_ts_timer(unsigned long data)
 {
 	struct corgi_ts *corgits_data = (struct corgi_ts *) data;
-	ts_interrupt_main(corgits_data, 1, NULL);
+	ts_interrupt_main(corgits_data, 1);
 }
 
-static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ts_interrupt(int irq, void *dev_id)
 {
 	struct corgi_ts *corgits_data = dev_id;
-	ts_interrupt_main(corgits_data, 0, regs);
+	ts_interrupt_main(corgits_data, 0);
 	return IRQ_HANDLED;
 }
 
@@ -238,7 +237,7 @@
 	if (corgi_ts->pendown) {
 		del_timer_sync(&corgi_ts->timer);
 		corgi_ts->tc.pressure = 0;
-		new_data(corgi_ts, NULL);
+		new_data(corgi_ts);
 		corgi_ts->pendown = 0;
 	}
 	corgi_ts->power_mode = PWR_MODE_SUSPEND;
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index ab56533..913e1b7 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -67,7 +67,7 @@
 	char phys[32];
 };
 
-static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_regs *regs)
+static void elo_process_data_10(struct elo *elo, unsigned char data)
 {
 	struct input_dev *dev = elo->dev;
 
@@ -95,7 +95,6 @@
 				break;
 			}
 			if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) {
-				input_regs(dev, regs);
 				input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
 				input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
 				if (elo->data[2] & ELO10_PRESSURE)
@@ -116,7 +115,7 @@
 	elo->csum += data;
 }
 
-static void elo_process_data_6(struct elo *elo, unsigned char data, struct pt_regs *regs)
+static void elo_process_data_6(struct elo *elo, unsigned char data)
 {
 	struct input_dev *dev = elo->dev;
 
@@ -134,7 +133,6 @@
 				break;
 			}
 
-			input_regs(dev, regs);
 			input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
 			input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
 
@@ -164,7 +162,7 @@
 	}
 }
 
-static void elo_process_data_3(struct elo *elo, unsigned char data, struct pt_regs *regs)
+static void elo_process_data_3(struct elo *elo, unsigned char data)
 {
 	struct input_dev *dev = elo->dev;
 
@@ -177,7 +175,6 @@
 				elo->idx = 0;
 			break;
 		case 2:
-			input_regs(dev, regs);
 			input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
 			input_report_abs(dev, ABS_X, elo->data[1]);
 			input_report_abs(dev, ABS_Y, elo->data[2]);
@@ -188,22 +185,22 @@
 }
 
 static irqreturn_t elo_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct elo *elo = serio_get_drvdata(serio);
 
 	switch(elo->id) {
 		case 0:
-			elo_process_data_10(elo, data, regs);
+			elo_process_data_10(elo, data);
 			break;
 
 		case 1:
 		case 2:
-			elo_process_data_6(elo, data, regs);
+			elo_process_data_6(elo, data);
 			break;
 
 		case 3:
-			elo_process_data_3(elo, data, regs);
+			elo_process_data_3(elo, data);
 			break;
 	}
 
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index b769b21..817c219 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -60,7 +60,7 @@
 	char phys[32];
 };
 
-static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
+static void gunze_process_packet(struct gunze* gunze)
 {
 	struct input_dev *dev = gunze->dev;
 
@@ -70,7 +70,6 @@
 		return;
 	}
 
-	input_regs(dev, regs);
 	input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10));
 	input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10));
 	input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
@@ -78,12 +77,12 @@
 }
 
 static irqreturn_t gunze_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct gunze* gunze = serio_get_drvdata(serio);
 
 	if (data == '\r') {
-		gunze_process_packet(gunze, regs);
+		gunze_process_packet(gunze);
 		gunze->idx = 0;
 	} else {
 		if (gunze->idx < GUNZE_MAX_LENGTH)
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index e2b9100..d9e61ee 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -106,19 +106,18 @@
 	char phys[32];
 };
 
-static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t action_button_handler(int irq, void *dev_id)
 {
 	int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
 	struct input_dev *dev = (struct input_dev *) dev_id;
 
-	input_regs(dev, regs);
 	input_report_key(dev, KEY_ENTER, down);
 	input_sync(dev);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t npower_button_handler(int irq, void *dev_id)
 {
 	int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
 	struct input_dev *dev = (struct input_dev *) dev_id;
@@ -127,7 +126,6 @@
 	 * This interrupt is only called when we release the key. So we have
 	 * to fake a key press.
 	 */
-	input_regs(dev, regs);
 	input_report_key(dev, KEY_SUSPEND, 1);
 	input_report_key(dev, KEY_SUSPEND, down);
 	input_sync(dev);
@@ -165,14 +163,12 @@
  * packets. Some packets coming from serial are not touchscreen related. In
  * this case we send them off to be processed elsewhere.
  */
-static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
+static void h3600ts_process_packet(struct h3600_dev *ts)
 {
 	struct input_dev *dev = ts->dev;
 	static int touched = 0;
 	int key, down = 0;
 
-	input_regs(dev, regs);
-
 	switch (ts->event) {
 		/*
 		   Buttons - returned as a single byte
@@ -301,7 +297,7 @@
 #define STATE_EOF       3       /* state where we decode checksum or EOF */
 
 static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
-                                     unsigned int flags, struct pt_regs *regs)
+                                     unsigned int flags)
 {
 	struct h3600_dev *ts = serio_get_drvdata(serio);
 
@@ -333,7 +329,7 @@
 		case STATE_EOF:
 			state = STATE_SOF;
 			if (data == CHAR_EOF || data == ts->chksum)
-				h3600ts_process_packet(ts, regs);
+				h3600ts_process_packet(ts);
 			break;
 		default:
 			printk("Error3\n");
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index ee6c2f4..58fca31 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -6,7 +6,7 @@
 #include <asm/io.h>
 #include <asm/delay.h>
 #include <asm/adc.h>
-#include <asm/hp6xx/hp6xx.h>
+#include <asm/hp6xx.h>
 
 #define MODNAME "hp680_ts_input"
 
@@ -66,7 +66,7 @@
 	enable_irq(HP680_TS_IRQ);
 }
 
-static irqreturn_t hp680_ts_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hp680_ts_interrupt(int irq, void *dev)
 {
 	disable_irq_nosync(irq);
 	schedule_delayed_work(&work, HZ / 20);
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index 3226830..4cbcaa6 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -80,7 +80,7 @@
 static struct input_dev *mk712_dev;
 static DEFINE_SPINLOCK(mk712_lock);
 
-static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mk712_interrupt(int irq, void *dev_id)
 {
 	unsigned char status;
 	static int debounce = 1;
@@ -88,7 +88,6 @@
 	static unsigned short last_y;
 
 	spin_lock(&mk712_lock);
-	input_regs(mk712_dev, regs);
 
 	status = inb(mk712_io + MK712_STATUS);
 
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index 8647a90..3b4c616 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -63,12 +63,11 @@
 	char phys[32];
 };
 
-static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
+static void mtouch_process_format_tablet(struct mtouch *mtouch)
 {
 	struct input_dev *dev = mtouch->dev;
 
 	if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
-		input_regs(dev, regs);
 		input_report_abs(dev, ABS_X, MTOUCH_GET_XC(mtouch->data));
 		input_report_abs(dev, ABS_Y, MTOUCH_MAX_YC - MTOUCH_GET_YC(mtouch->data));
 		input_report_key(dev, BTN_TOUCH, MTOUCH_GET_TOUCHED(mtouch->data));
@@ -78,7 +77,7 @@
 	}
 }
 
-static void mtouch_process_response(struct mtouch *mtouch, struct pt_regs *regs)
+static void mtouch_process_response(struct mtouch *mtouch)
 {
 	if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) {
 		/* FIXME - process response */
@@ -90,16 +89,16 @@
 }
 
 static irqreturn_t mtouch_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct mtouch* mtouch = serio_get_drvdata(serio);
 
 	mtouch->data[mtouch->idx] = data;
 
 	if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0])
-		mtouch_process_format_tablet(mtouch, regs);
+		mtouch_process_format_tablet(mtouch);
 	else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0])
-		mtouch_process_response(mtouch, regs);
+		mtouch_process_response(mtouch);
 	else
 		printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]);
 
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index f737010..6c7d0c2 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -46,7 +46,7 @@
 };
 
 static irqreturn_t pm_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct pm *pm = serio_get_drvdata(serio);
 	struct input_dev *dev = pm->dev;
@@ -55,7 +55,6 @@
 
 	if (pm->data[0] & 0x80) {
 		if (PM_MAX_LENGTH == ++pm->idx) {
-			input_regs(dev, regs);
 			input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]);
 			input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]);
 			input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 1c89fa5..c74f74e 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -56,7 +56,7 @@
 };
 
 static irqreturn_t tr_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct tr *tr = serio_get_drvdata(serio);
 	struct input_dev *dev = tr->dev;
@@ -65,7 +65,6 @@
 
 	if ((tr->data[0] & TR_FORMAT_STATUS_MASK) == TR_FORMAT_STATUS_BYTE) {
 		if (++tr->idx == TR_LENGTH) {
-			input_regs(dev, regs);
 			input_report_abs(dev, ABS_X,
 				(tr->data[1] << 5) | (tr->data[2] >> 1));
 			input_report_abs(dev, ABS_Y,
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index a7b4c75..9911820 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -60,7 +60,7 @@
 };
 
 static irqreturn_t tw_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+		unsigned char data, unsigned int flags)
 {
 	struct tw *tw = serio_get_drvdata(serio);
 	struct input_dev *dev = tw->dev;
@@ -70,7 +70,6 @@
 		tw->data[tw->idx++] = data;
 		/* verify length and that the two Y's are the same */
 		if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
-			input_regs(dev, regs);
 			input_report_abs(dev, ABS_X, tw->data[0]);
 			input_report_abs(dev, ABS_Y, tw->data[1]);
 			input_report_key(dev, BTN_TOUCH, 1);
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index bc98d77..3cac237 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -16,8 +16,6 @@
 #include "act2000_isa.h"
 #include "capi.h"
 
-static act2000_card *irq2card_map[16];
-
 /*
  * Reset Controller, then try to read the Card's signature.
  + Return:
@@ -63,16 +61,11 @@
 }
 
 static irqreturn_t
-act2000_isa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+act2000_isa_interrupt(int irq, void *dev_id)
 {
-        act2000_card *card = irq2card_map[irq];
+        act2000_card *card = dev_id;
         u_char istatus;
 
-        if (!card) {
-                printk(KERN_WARNING
-                       "act2000: Spurious interrupt!\n");
-                return IRQ_NONE;
-        }
         istatus = (inb(ISA_PORT_ISR) & 0x07);
         if (istatus & ISA_ISR_OUT) {
                 /* RX fifo has data */
@@ -139,17 +132,15 @@
 act2000_isa_config_irq(act2000_card * card, short irq)
 {
         if (card->flags & ACT2000_FLAGS_IVALID) {
-                free_irq(card->irq, NULL);
-                irq2card_map[card->irq] = NULL;
+                free_irq(card->irq, card);
         }
         card->flags &= ~ACT2000_FLAGS_IVALID;
         outb(ISA_COR_IRQOFF, ISA_PORT_COR);
         if (!irq)
                 return 0;
 
-	if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
+	if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, card)) {
 		card->irq = irq;
-		irq2card_map[card->irq] = card;
 		card->flags |= ACT2000_FLAGS_IVALID;
                 printk(KERN_WARNING
                        "act2000: Could not request irq %d\n",irq);
@@ -188,10 +179,9 @@
         unsigned long flags;
 
         spin_lock_irqsave(&card->lock, flags);
-        if (card->flags & ACT2000_FLAGS_IVALID) {
-                free_irq(card->irq, NULL);
-                irq2card_map[card->irq] = NULL;
-        }
+        if (card->flags & ACT2000_FLAGS_IVALID)
+                free_irq(card->irq, card);
+
         card->flags &= ~ACT2000_FLAGS_IVALID;
         if (card->flags & ACT2000_FLAGS_PVALID)
                 release_region(card->port, ISA_REGION);
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index d10c8b8..b6f9476 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -1907,7 +1907,8 @@
 	}
 
 	for (p=buf, count=0; count < len; p++, count++) {
-		put_user(*card->q931_read++, p);
+		if (put_user(*card->q931_read++, p))
+			return -EFAULT;
 	        if (card->q931_read > card->q931_end)
 	                card->q931_read = card->q931_buf;
 	}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 5cfbe6a..0c93732 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -454,7 +454,7 @@
  *	urb	USB request block
  *		urb->context = inbuf structure for controller state
  */
-static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
+static void read_ctrl_callback(struct urb *urb)
 {
 	struct inbuf_t *inbuf = urb->context;
 	struct cardstate *cs = inbuf->cs;
@@ -596,7 +596,7 @@
  *	urb	USB request block
  *		urb->context = controller state structure
  */
-static void read_int_callback(struct urb *urb, struct pt_regs *regs)
+static void read_int_callback(struct urb *urb)
 {
 	struct cardstate *cs = urb->context;
 	struct bas_cardstate *ucs = cs->hw.bas;
@@ -762,7 +762,7 @@
  *	urb	USB request block of completed request
  *		urb->context = bc_state structure
  */
-static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
+static void read_iso_callback(struct urb *urb)
 {
 	struct bc_state *bcs;
 	struct bas_bc_state *ubc;
@@ -827,7 +827,7 @@
  *	urb	USB request block of completed request
  *		urb->context = isow_urbctx_t structure
  */
-static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
+static void write_iso_callback(struct urb *urb)
 {
 	struct isow_urbctx_t *ucx;
 	struct bas_bc_state *ubc;
@@ -1415,7 +1415,7 @@
  *	urb	USB request block of completed request
  *		urb->context = hardware specific controller state structure
  */
-static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
+static void write_ctrl_callback(struct urb *urb)
 {
 	struct bas_cardstate *ucs = urb->context;
 	int rc;
@@ -1661,7 +1661,7 @@
  *	urb	USB request block of completed request
  *		urb->context = controller state structure
  */
-static void write_command_callback(struct urb *urb, struct pt_regs *regs)
+static void write_command_callback(struct urb *urb)
 {
 	struct cardstate *cs = urb->context;
 	struct bas_cardstate *ucs = cs->hw.bas;
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 6e05d9d..4ffa9eb 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -362,7 +362,7 @@
  *
  *	It is called if the data was received from the device.
  */
-static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
+static void gigaset_read_int_callback(struct urb *urb)
 {
 	struct inbuf_t *inbuf = urb->context;
 	struct cardstate *cs = inbuf->cs;
@@ -420,7 +420,7 @@
 
 
 /* This callback routine is called when data was transmitted to the device. */
-static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void gigaset_write_bulk_callback(struct urb *urb)
 {
 	struct cardstate *cs = urb->context;
 	unsigned long flags;
diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h
index 3b43172..d964f07 100644
--- a/drivers/isdn/hardware/avm/avmcard.h
+++ b/drivers/isdn/hardware/avm/avmcard.h
@@ -554,7 +554,7 @@
 void b1_release_appl(struct capi_ctr *ctrl, u16 appl);
 u16  b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
 void b1_parse_version(avmctrl_info *card);
-irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
+irqreturn_t b1_interrupt(int interrupt, void *devptr);
 
 int b1ctl_read_proc(char *page, char **start, off_t off,
         		int count, int *eof, struct capi_ctr *ctrl);
@@ -567,7 +567,7 @@
 int b1pciv4_detect(avmcard *card);
 int t1pci_detect(avmcard *card);
 void b1dma_reset(avmcard *card);
-irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
+irqreturn_t b1dma_interrupt(int interrupt, void *devptr);
 
 int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
 void b1dma_reset_ctr(struct capi_ctr *ctrl);
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 0c7061d..da27292 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -485,7 +485,7 @@
 
 /* ------------------------------------------------------------- */
 
-irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+irqreturn_t b1_interrupt(int interrupt, void *devptr)
 {
 	avmcard *card = devptr;
 	avmctrl_info *cinfo = &card->ctrlinfo[0];
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index a4beeb4..ddd47cd 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -628,7 +628,7 @@
 	spin_unlock(&card->lock);
 }
 
-irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+irqreturn_t b1dma_interrupt(int interrupt, void *devptr)
 {
 	avmcard *card = devptr;
 
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 6c3d5f5..2a3eb38 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -713,7 +713,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+static irqreturn_t c4_interrupt(int interrupt, void *devptr)
 {
 	avmcard *card = devptr;
 
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index 5a2f854..e47c60b 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -131,7 +131,7 @@
         return 0;
 }
 
-static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+static irqreturn_t t1isa_interrupt(int interrupt, void *devptr)
 {
 	avmcard *card = devptr;
 	avmctrl_info *cinfo = &card->ctrlinfo[0];
diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c
index 8ab8027..ffa2afa 100644
--- a/drivers/isdn/hardware/eicon/diva.c
+++ b/drivers/isdn/hardware/eicon/diva.c
@@ -71,8 +71,6 @@
 DivaIdiReqFunc(30)
 DivaIdiReqFunc(31)
 
-struct pt_regs;
-
 /*
 **  LOCALS
 */
@@ -515,7 +513,7 @@
 }
 
 
-irqreturn_t diva_os_irq_wrapper(int irq, void *context, struct pt_regs *regs)
+irqreturn_t diva_os_irq_wrapper(int irq, void *context)
 {
 	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context;
 	diva_xdi_clear_interrupts_proc_t clear_int_proc;
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index b7dadba..dae2e83 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -58,8 +58,7 @@
 static char *DEVNAME = "Divas";
 char *DRIVERRELEASE_DIVAS = "2.0";
 
-extern irqreturn_t diva_os_irq_wrapper(int irq, void *context,
-				struct pt_regs *regs);
+extern irqreturn_t diva_os_irq_wrapper(int irq, void *context);
 extern int create_divas_proc(void);
 extern void remove_divas_proc(void);
 extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index 8ae08c4..bec5901 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -733,7 +733,7 @@
 			wByteAMD(cs, 0x21, 0x82);
 			wByteAMD(cs, 0x21, 0x02);
 			spin_unlock_irqrestore(&cs->lock, flags);
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->irq_func(cs->irq, cs);
 
                         if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index 93ff941..61e69e9 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -156,7 +156,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+asuscom_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
@@ -194,7 +194,7 @@
 }
 
 static irqreturn_t
-asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+asuscom_interrupt_ipac(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista, val, icnt = 5;
diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
index 729e906..d9028e9 100644
--- a/drivers/isdn/hisax/avm_a1.c
+++ b/drivers/isdn/hisax/avm_a1.c
@@ -101,7 +101,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+avm_a1_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
index 574e252..c87fa3f 100644
--- a/drivers/isdn/hisax/avm_a1p.c
+++ b/drivers/isdn/hisax/avm_a1p.c
@@ -140,7 +140,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+avm_a1p_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 369afd3..b04a178 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -651,7 +651,7 @@
 }
 
 static irqreturn_t
-avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+avm_pcipnp_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_long flags;
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index 87a6301..871310d 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -125,7 +125,7 @@
 #include "jade_irq.c"
 
 static irqreturn_t
-bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+bkm_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val = 0;
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index dae090a..3403106 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -140,7 +140,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+bkm_interrupt_ipac(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista, val, icnt = 5;
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index e4823ab..785b085 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -631,7 +631,8 @@
 		count = cs->status_end - cs->status_read + 1;
 		if (count >= len)
 			count = len;
-		copy_to_user(p, cs->status_read, count);
+		if (copy_to_user(p, cs->status_read, count))
+			return -EFAULT;
 		cs->status_read += count;
 		if (cs->status_read > cs->status_end)
 			cs->status_read = cs->status_buf;
@@ -642,7 +643,8 @@
 				cnt = HISAX_STATUS_BUFSIZE;
 			else
 				cnt = count;
-			copy_to_user(p, cs->status_read, cnt);
+			if (copy_to_user(p, cs->status_read, cnt))
+				return -EFAULT;
 			p += cnt;
 			cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
 			count -= cnt;
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index e294fa3..3dacfff 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -289,7 +289,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+diva_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
@@ -319,7 +319,7 @@
 }
 
 static irqreturn_t
-diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
+diva_irq_ipac_isa(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista,val;
@@ -630,7 +630,7 @@
 }
 
 static irqreturn_t
-diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
+diva_irq_ipac_pci(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista,val;
@@ -685,7 +685,7 @@
 }
 
 static irqreturn_t
-diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
+diva_irq_ipacx_pci(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
@@ -716,8 +716,10 @@
 
 		*cfg = 0; /* disable INT0/1 */ 
 		*cfg = 2; /* reset pending INT0 */
-		iounmap((void *)cs->hw.diva.cfg_reg);
-		iounmap((void *)cs->hw.diva.pci_cfg);
+		if (cs->hw.diva.cfg_reg)
+			iounmap((void *)cs->hw.diva.cfg_reg);
+		if (cs->hw.diva.pci_cfg)
+			iounmap((void *)cs->hw.diva.pci_cfg);
 		return;
 	} else if (cs->subtyp != DIVA_IPAC_ISA) {
 		del_timer(&cs->hw.diva.tl);
@@ -734,6 +736,23 @@
 }
 
 static void
+iounmap_diva(struct IsdnCardState *cs)
+{
+	if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_IPACX_PCI)) {
+		if (cs->hw.diva.cfg_reg) {
+			iounmap((void *)cs->hw.diva.cfg_reg);
+			cs->hw.diva.cfg_reg = 0;
+		}
+		if (cs->hw.diva.pci_cfg) {
+			iounmap((void *)cs->hw.diva.pci_cfg);
+			cs->hw.diva.pci_cfg = 0;
+		}
+	}
+
+	return;
+}
+
+static void
 reset_diva(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == DIVA_IPAC_ISA) {
@@ -1069,11 +1088,13 @@
 
 		if (!cs->irq) {
 			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
+			iounmap_diva(cs);
 			return(0);
 		}
 
 		if (!cs->hw.diva.cfg_reg) {
 			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
+			iounmap_diva(cs);
 			return(0);
 		}
 		cs->irq_flags |= IRQF_SHARED;
@@ -1123,6 +1144,7 @@
 			       CardType[card->typ],
 			       cs->hw.diva.cfg_reg,
 			       cs->hw.diva.cfg_reg + bytecnt);
+			iounmap_diva(cs);
 			return (0);
 		}
 	}
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 3b3e318..fab3e4e 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -282,7 +282,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+elsa_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_long flags;
@@ -361,7 +361,7 @@
 }
 
 static irqreturn_t
-elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+elsa_interrupt_ipac(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_long flags;
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index 76c7d29..b45de9d 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -240,7 +240,7 @@
 }
 
 static irqreturn_t
-enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+enpci_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	unsigned char s0val, s1val, ir;
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index fe29372..3efa719 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -243,7 +243,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+gazel_interrupt(int intno, void *dev_id)
 {
 #define MAXCOUNT 5
 	struct IsdnCardState *cs = dev_id;
@@ -274,7 +274,7 @@
 
 
 static irqreturn_t
-gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+gazel_interrupt_ipac(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista, val;
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 0ca5e66..d852c9d 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1268,7 +1268,7 @@
 /* interrupt handler */
 /*********************/
 static irqreturn_t
-hfc4s8s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+hfc4s8s_interrupt(int intno, void *dev_id)
 {
 	hfc4s8s_hw *hw = dev_id;
 	u_char b, ovr;
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 1df60ca..93f60b5 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -931,7 +931,7 @@
 /* Interrupt handler */
 /*********************/
 static irqreturn_t
-hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+hfcpci_interrupt(int intno, void *dev_id)
 {
 	u_long flags;
 	struct IsdnCardState *cs = dev_id;
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index b7e8e23..954d153 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -691,7 +691,7 @@
 /* Interrupt handler */
 /*********************/
 static irqreturn_t
-hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+hfcsx_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char exval;
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 6b88ecb..7105b04 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -276,7 +276,7 @@
 /* control completion routine handling background control cmds */
 /***************************************************************/
 static void
-ctrl_complete(struct urb *urb, struct pt_regs *regs)
+ctrl_complete(struct urb *urb)
 {
 	hfcusb_data *hfc = (hfcusb_data *) urb->context;
 	ctrl_buft *buf;
@@ -603,7 +603,7 @@
 /* transmit completion routine for all ISO tx fifos */
 /*****************************************************/
 static void
-tx_iso_complete(struct urb *urb, struct pt_regs *regs)
+tx_iso_complete(struct urb *urb)
 {
 	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
 	usb_fifo *fifo = context_iso_urb->owner_fifo;
@@ -726,7 +726,7 @@
 /* receive completion routine for all ISO tx fifos   */
 /*****************************************************/
 static void
-rx_iso_complete(struct urb *urb, struct pt_regs *regs)
+rx_iso_complete(struct urb *urb)
 {
 	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
 	usb_fifo *fifo = context_iso_urb->owner_fifo;
@@ -919,7 +919,7 @@
 /* receive completion routine for all rx fifos */
 /***********************************************/
 static void
-rx_complete(struct urb *urb, struct pt_regs *regs)
+rx_complete(struct urb *urb)
 {
 	int len;
 	int status;
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 4e7f472..57670dc 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -21,7 +21,7 @@
 static const char *hfcs_revision = "$Revision: 1.10.2.4 $";
 
 static irqreturn_t
-hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+hfcs_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, stat;
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 2f9d511..159c589 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -941,7 +941,7 @@
 	int		(*cardmsg) (struct IsdnCardState *, int, void *);
 	void		(*setstack_d) (struct PStack *, struct IsdnCardState *);
 	void		(*DC_Close) (struct IsdnCardState *);
-	int		(*irq_func) (int, void *, struct pt_regs *);
+	int		(*irq_func) (int, void *);
 	int		(*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
 	struct Channel	channel[2+MAX_WAITING_CALLS];
 	struct BCState	bcs[2+MAX_WAITING_CALLS];
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 881a416..f6db55a 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -651,7 +651,7 @@
 // ----------------------------------------------------------------------
 
 static irqreturn_t
-fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
+fcpci2_irq(int intno, void *dev)
 {
 	struct fritz_adapter *adapter = dev;
 	unsigned char val;
@@ -671,7 +671,7 @@
 }
 
 static irqreturn_t
-fcpci_irq(int intno, void *dev, struct pt_regs *regs)
+fcpci_irq(int intno, void *dev)
 {
 	struct fritz_adapter *adapter = dev;
 	unsigned char sval;
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index 2cf7b66..da70692 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -608,7 +608,7 @@
 				debugl1(cs, "D-Channel Busy no skb");
 			}
 			cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->irq_func(cs->irq, cs);
 		}
 	}
 }
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 565b789..282f349 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -609,7 +609,7 @@
 				debugl1(cs, "D-Channel Busy no skb");
 			}
 			cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->irq_func(cs->irq, cs);
 		}
 	}
 }
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
index 715a1a8..55de069 100644
--- a/drivers/isdn/hisax/isurf.c
+++ b/drivers/isdn/hisax/isurf.c
@@ -83,7 +83,7 @@
 }
 
 static irqreturn_t
-isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+isurf_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index 3971750..252d79d 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -125,7 +125,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+ix1micro_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index 8c82519..a81d175 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -120,7 +120,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+mic_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h
index 1080508..4d89d3e 100644
--- a/drivers/isdn/hisax/netjet.h
+++ b/drivers/isdn/hisax/netjet.h
@@ -66,7 +66,7 @@
 void write_tiger(struct IsdnCardState *cs);
 
 void netjet_fill_dma(struct BCState *bcs);
-void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs);
+void netjet_interrupt(int intno, void *dev_id);
 void inittiger(struct IsdnCardState *cs);
 void release_io_netjet(struct IsdnCardState *cs);
 
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index 0945336..e5918c6 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -122,8 +122,7 @@
 
 #include "hscx_irq.c"
 
-static irqreturn_t niccy_interrupt(int intno, void *dev_id,
-		struct pt_regs *regs)
+static irqreturn_t niccy_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index 80025fd..c09ffb1 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -26,7 +26,7 @@
 }
 
 static irqreturn_t
-netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+netjet_s_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, s1val, s0val;
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 3749716..8202cf3 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -26,7 +26,7 @@
 }
 
 static irqreturn_t
-netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+netjet_u_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index e76042d..150ef68 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -141,7 +141,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+s0box_interrupt(int intno, void *dev_id)
 {
 #define MAXCOUNT 5
 	struct IsdnCardState *cs = dev_id;
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index d943d36..c99b166 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -117,7 +117,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+saphir_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 8d8e8a2..9522141 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -260,7 +260,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+sedlbauer_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
@@ -306,7 +306,7 @@
 }
 
 static irqreturn_t
-sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+sedlbauer_interrupt_ipac(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista, val, icnt = 5;
@@ -353,7 +353,7 @@
 }
 
 static irqreturn_t
-sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
+sedlbauer_interrupt_isar(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index a49b694..0220950 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -99,7 +99,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+sportster_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index aca2a39..75d0f248 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -161,7 +161,7 @@
 	st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, leds, NULL, NULL);
 }
 
-static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs)
+static void usb_b_out_complete(struct urb *urb)
 {
 	struct st5481_bcs *bcs = urb->context;
 	struct st5481_b_out *b_out = &bcs->b_out;
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 98adec4..1d8c261 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -370,7 +370,7 @@
 	FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL);
 }
 
-static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs)
+static void usb_d_out_complete(struct urb *urb)
 {
 	struct st5481_adapter *adapter = urb->context;
 	struct st5481_d_out *d_out = &adapter->d_out;
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index b096b64..ff15951 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -125,7 +125,7 @@
  * Call the user provided completion routine and try
  * to send the next request.
  */
-static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs)
+static void usb_ctrl_complete(struct urb *urb)
 {
 	struct st5481_adapter *adapter = urb->context;
 	struct st5481_ctrl *ctrl = &adapter->ctrl;
@@ -179,7 +179,7 @@
  * Decode the register values and schedule a private event.
  * Called at interrupt.
  */
-static void usb_int_complete(struct urb *urb, struct pt_regs *regs)
+static void usb_int_complete(struct urb *urb)
 {
 	u8 *data = urb->transfer_buffer;
 	u8 irqbyte;
@@ -483,7 +483,7 @@
  * called 50 times per second with 20 ISOC descriptors. 
  * Called at interrupt.
  */
-static void usb_in_complete(struct urb *urb, struct pt_regs *regs)
+static void usb_in_complete(struct urb *urb)
 {
 	struct st5481_in *in = urb->context;
 	unsigned char *ptr;
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index e94dc6f..0909662 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -157,7 +157,7 @@
 }
 
 static irqreturn_t
-TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+TeleInt_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index f94af09..4858133 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -144,7 +144,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+teles0_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index 5cb7124..6a5e379 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -101,7 +101,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+teles3_interrupt(int intno, void *dev_id)
 {
 #define MAXCOUNT 5
 	struct IsdnCardState *cs = dev_id;
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index dca4468..d09f6d0 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -226,7 +226,7 @@
 #include "hscx_irq.c"
 
 static irqreturn_t
-telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+telespci_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char hval, ival;
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index 0595293..1655341 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -400,7 +400,7 @@
 }
 
 static irqreturn_t
-W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+W6692_interrupt(int intno, void *dev_id)
 {
 	struct IsdnCardState	*cs = dev_id;
 	u_char			val, exval, v1;
@@ -715,7 +715,7 @@
 			}
 			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);	/* Transmitter reset */
 			spin_unlock_irqrestore(&cs->lock, flags);
-			cs->irq_func(cs->irq, cs, NULL);
+			cs->irq_func(cs->irq, cs);
 			return;
 		}
 	}
diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c
index 73afebd..82e42a8 100644
--- a/drivers/isdn/hysdn/boardergo.c
+++ b/drivers/isdn/hysdn/boardergo.c
@@ -33,7 +33,7 @@
 /* The cards interrupt handler. Called from system */
 /***************************************************/
 static irqreturn_t
-ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+ergo_interrupt(int intno, void *dev_id)
 {
 	hysdn_card *card = dev_id;	/* parameter from irq */
 	tErgDpram *dpr;
@@ -45,11 +45,10 @@
 	if (!card->irq_enabled)
 		return IRQ_NONE;		/* other device interrupting or irq switched off */
 
-	save_flags(flags);
-	cli();			/* no further irqs allowed */
+	spin_lock_irqsave(&card->hysdn_lock, flags); /* no further irqs allowed */
 
 	if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {
-		restore_flags(flags);	/* restore old state */
+		spin_unlock_irqrestore(&card->hysdn_lock, flags);	/* restore old state */
 		return IRQ_NONE;		/* no interrupt requested by E1 */
 	}
 	/* clear any pending ints on the board */
@@ -61,7 +60,7 @@
 	/* start kernel task immediately after leaving all interrupts */
 	if (!card->hw_lock)
 		schedule_work(&card->irq_queue);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->hysdn_lock, flags);
 	return IRQ_HANDLED;
 }				/* ergo_interrupt */
 
@@ -83,10 +82,9 @@
 
 	dpr = card->dpram;	/* point to DPRAM */
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->hysdn_lock, flags);
 	if (card->hw_lock) {
-		restore_flags(flags);	/* hardware currently unavailable */
+		spin_unlock_irqrestore(&card->hysdn_lock, flags);	/* hardware currently unavailable */
 		return;
 	}
 	card->hw_lock = 1;	/* we now lock the hardware */
@@ -120,7 +118,7 @@
 			card->hw_lock = 0;	/* free hardware again */
 	} while (again);	/* until nothing more to do */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->hysdn_lock, flags);
 }				/* ergo_irq_bh */
 
 
@@ -137,8 +135,7 @@
 #ifdef CONFIG_HYSDN_CAPI
 	hycapi_capi_stop(card);
 #endif /* CONFIG_HYSDN_CAPI */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->hysdn_lock, flags);
 	val = bytein(card->iobase + PCI9050_INTR_REG);	/* get actual value */
 	val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1);	/* mask irq */
 	byteout(card->iobase + PCI9050_INTR_REG, val);
@@ -147,7 +144,7 @@
 	card->state = CARD_STATE_UNUSED;
 	card->err_log_state = ERRLOG_STATE_OFF;		/* currently no log active */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->hysdn_lock, flags);
 }				/* ergo_stopcard */
 
 /**************************************************************************/
@@ -162,12 +159,11 @@
 		card->err_log_state = ERRLOG_STATE_OFF;		/* must be off */
 		return;
 	}
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->hysdn_lock, flags);
 
 	if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||
 	    ((card->err_log_state == ERRLOG_STATE_ON) && on)) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->hysdn_lock, flags);
 		return;		/* nothing to do */
 	}
 	if (on)
@@ -175,7 +171,7 @@
 	else
 		card->err_log_state = ERRLOG_STATE_STOP;	/* request stop */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->hysdn_lock, flags);
 	schedule_work(&card->irq_queue);
 }				/* ergo_set_errlog_state */
 
@@ -356,8 +352,7 @@
 
 			if (card->debug_flags & LOG_POF_RECORD)
 				hysdn_addlog(card, "ERGO: pof boot success");
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&card->hysdn_lock, flags);
 
 			card->state = CARD_STATE_RUN;	/* now card is running */
 			/* enable the cards interrupt */
@@ -370,7 +365,7 @@
 			dpr->ToHyInt = 1;
 			dpr->ToPcInt = 1;	/* interrupt to E1 for all cards */
 
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->hysdn_lock, flags);
 			if ((hynet_enable & (1 << card->myid)) 
 			    && (i = hysdn_net_create(card))) 
 			{
@@ -408,7 +403,7 @@
 	free_irq(card->irq, card);	/* release interrupt */
 	release_region(card->iobase + PCI9050_INTR_REG, 1);	/* release all io ports */
 	release_region(card->iobase + PCI9050_USER_IO, 1);
-	vfree(card->dpram);
+	iounmap(card->dpram);
 	card->dpram = NULL;	/* release shared mem */
 }				/* ergo_releasehardware */
 
@@ -448,6 +443,7 @@
 	card->waitpofready = ergo_waitpofready;
 	card->set_errlog_state = ergo_set_errlog_state;
 	INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card);
+	card->hysdn_lock = SPIN_LOCK_UNLOCKED;
 
 	return (0);
 }				/* ergo_inithardware */
diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h
index 461e831..729df40 100644
--- a/drivers/isdn/hysdn/hysdn_defs.h
+++ b/drivers/isdn/hysdn/hysdn_defs.h
@@ -188,6 +188,8 @@
 	/* init and deinit stopcard for booting, too */
 	void (*stopcard) (struct HYSDN_CARD *);
 	void (*releasehardware) (struct HYSDN_CARD *);
+
+	spinlock_t hysdn_lock;
 #ifdef CONFIG_HYSDN_CAPI
 	struct hycapictrl_info {
 		char cardname[32];
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index c4301e8..fcd4992 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -116,8 +116,7 @@
 	strcpy(ib->log_start, cp);	/* set output string */
 	ib->next = NULL;
 	ib->proc_ctrl = pd;	/* point to own control structure */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->hysdn_lock, flags);
 	ib->usage_cnt = pd->if_used;
 	if (!pd->log_head)
 		pd->log_head = ib;	/* new head */
@@ -125,7 +124,7 @@
 		pd->log_tail->next = ib;	/* follows existing messages */
 	pd->log_tail = ib;	/* new tail */
 	i = pd->del_lock++;	/* get lock state */
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->hysdn_lock, flags);
 
 	/* delete old entrys */
 	if (!i)
@@ -270,14 +269,13 @@
 	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
 
 		/* read access -> log/debug read */
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->hysdn_lock, flags);
 		pd->if_used++;
 		if (pd->log_head)
 			filep->private_data = &pd->log_tail->next;
 		else
 			filep->private_data = &pd->log_head;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->hysdn_lock, flags);
 	} else {		/* simultaneous read/write access forbidden ! */
 		unlock_kernel();
 		return (-EPERM);	/* no permission this time */
@@ -301,7 +299,7 @@
 	hysdn_card *card;
 	int retval = 0;
 	unsigned long flags;
-
+	spinlock_t hysdn_lock = SPIN_LOCK_UNLOCKED;
 
 	lock_kernel();
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
@@ -311,8 +309,7 @@
 		/* read access -> log/debug read, mark one further file as closed */
 
 		pd = NULL;
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&hysdn_lock, flags);
 		inf = *((struct log_data **) filep->private_data);	/* get first log entry */
 		if (inf)
 			pd = (struct procdata *) inf->proc_ctrl;	/* still entries there */
@@ -335,7 +332,7 @@
 			inf->usage_cnt--;	/* decrement usage count for buffers */
 			inf = inf->next;
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&hysdn_lock, flags);
 
 		if (pd)
 			if (pd->if_used <= 0)	/* delete buffers if last file closed */
diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c
index 1c0d54a..1fadf01 100644
--- a/drivers/isdn/hysdn/hysdn_sched.c
+++ b/drivers/isdn/hysdn/hysdn_sched.c
@@ -155,8 +155,7 @@
 	if (card->debug_flags & LOG_SCHED_ASYN)
 		hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->hysdn_lock, flags);
 	while (card->async_busy) {
 		sti();
 
@@ -165,7 +164,7 @@
 
 		msleep_interruptible(20);		/* Timeout 20ms */
 		if (!--cnt) {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->hysdn_lock, flags);
 			return (-ERR_ASYNC_TIME);	/* timed out */
 		}
 		cli();
@@ -194,13 +193,13 @@
 
 		msleep_interruptible(20);		/* Timeout 20ms */
 		if (!--cnt) {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->hysdn_lock, flags);
 			return (-ERR_ASYNC_TIME);	/* timed out */
 		}
 		cli();
 	}			/* wait for buffer to become free again */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->hysdn_lock, flags);
 
 	if (card->debug_flags & LOG_SCHED_ASYN)
 		hysdn_addlog(card, "async tx-cfg data send");
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index c3d79ee..69aee26 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1134,9 +1134,12 @@
 		if (dev->drv[drvidx]->interface->readstat) {
 			if (count > dev->drv[drvidx]->stavail)
 				count = dev->drv[drvidx]->stavail;
-			len = dev->drv[drvidx]->interface->
-				readstat(buf, count, drvidx,
-					 isdn_minor2chan(minor));
+			len = dev->drv[drvidx]->interface->readstat(buf, count,
+						drvidx, isdn_minor2chan(minor));
+			if (len < 0) {
+				retval = len;
+				goto out;
+			}
 		} else {
 			len = 0;
 		}
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 6649f8b..730bbd0 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1010,7 +1010,8 @@
 	for (p = buf, count = 0; count < len; p++, count++) {
 		if (card->msg_buf_read == card->msg_buf_write)
 			return count;
-		put_user(*card->msg_buf_read++, p);
+		if (put_user(*card->msg_buf_read++, p))
+			return -EFAULT;
 		if (card->msg_buf_read > card->msg_buf_end)
 			card->msg_buf_read = card->msg_buf;
 	}
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index fabbd46..c3ae2ed 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -100,12 +100,11 @@
 		isdnloop_bchan_send(card, 1);
 	if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) {
 		/* schedule b-channel polling again */
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->isdnloop_lock, flags);
 		card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
 		add_timer(&card->rb_timer);
 		card->flags |= ISDNLOOP_FLAGS_RBTIMER;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 	} else
 		card->flags &= ~ISDNLOOP_FLAGS_RBTIMER;
 }
@@ -281,8 +280,7 @@
 {
 	ulong flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	*card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
 	if (card->msg_buf_write == card->msg_buf_read) {
 		if (++card->msg_buf_read > card->msg_buf_end)
@@ -290,7 +288,7 @@
 	}
 	if (card->msg_buf_write > card->msg_buf_end)
 		card->msg_buf_write = card->msg_buf;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 }
 
 /*
@@ -372,21 +370,19 @@
 		if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) {
 			/* schedule b-channel polling */
 			card->flags |= ISDNLOOP_FLAGS_RBTIMER;
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&card->isdnloop_lock, flags);
 			del_timer(&card->rb_timer);
 			card->rb_timer.function = isdnloop_pollbchan;
 			card->rb_timer.data = (unsigned long) card;
 			card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
 			add_timer(&card->rb_timer);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 		}
 	/* schedule again */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
 	add_timer(&card->st_timer);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 }
 
 /*
@@ -416,8 +412,7 @@
 			return 0;
 		if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE)
 			return 0;
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->isdnloop_lock, flags);
 		nskb = dev_alloc_skb(skb->len);
 		if (nskb) {
 			memcpy(skb_put(nskb, len), skb->data, len);
@@ -426,7 +421,7 @@
 		} else
 			len = 0;
 		card->sndcount[channel] += len;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 	}
 	return len;
 }
@@ -451,7 +446,8 @@
 	for (p = buf, count = 0; count < len; p++, count++) {
 		if (card->msg_buf_read == card->msg_buf_write)
 			return count;
-		put_user(*card->msg_buf_read++, p);
+		if (put_user(*card->msg_buf_read++, p))
+			return -EFAULT;
 		if (card->msg_buf_read > card->msg_buf_end)
 			card->msg_buf_read = card->msg_buf;
 	}
@@ -576,8 +572,7 @@
 	unsigned long flags;
 	char buf[60];
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	if (card->rcard) {
 		isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1);
 		card->rcard[ch]->rcard[card->rch[ch]] = NULL;
@@ -587,7 +582,7 @@
 	/* No user responding */
 	sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3));
 	isdnloop_fake(card, buf, ch + 1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 }
 
 /*
@@ -622,8 +617,7 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	init_timer(&card->c_timer[ch]);
 	card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT;
 	if (ch)
@@ -632,7 +626,7 @@
 		card->c_timer[ch].function = isdnloop_atimeout0;
 	card->c_timer[ch].data = (unsigned long) card;
 	add_timer(&card->c_timer[ch]);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 }
 
 /*
@@ -647,10 +641,9 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	del_timer(&card->c_timer[ch]);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 }
 
 static u_char si2bit[] =
@@ -706,13 +699,12 @@
 					}
 			}
 			if (num_match) {
-				save_flags(flags);
-				cli();
+				spin_lock_irqsave(&card->isdnloop_lock, flags);
 				/* channel idle? */
 				if (!(cc->rcard[ch])) {
 					/* Check SI */
 					if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) {
-						restore_flags(flags);
+						spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 						return 3;
 					}
 					/* ch is idle, si and number matches */
@@ -720,10 +712,10 @@
 					cc->rch[ch] = lch;
 					card->rcard[lch] = cc;
 					card->rch[lch] = ch;
-					restore_flags(flags);
+					spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 					return 0;
 				} else {
-					restore_flags(flags);
+					spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 					/* num matches, but busy */
 					if (ch == 1)
 						return 1;
@@ -1027,8 +1019,7 @@
 	unsigned long flags;
 	isdn_ctrl cmd;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	if (card->flags & ISDNLOOP_FLAGS_RUNNING) {
 		card->flags &= ~ISDNLOOP_FLAGS_RUNNING;
 		del_timer(&card->st_timer);
@@ -1039,7 +1030,7 @@
 		cmd.driver = card->myid;
 		card->interface.statcallb(&cmd);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 }
 
 /*
@@ -1078,18 +1069,17 @@
 		return -EBUSY;
 	if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
 		return -EFAULT;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->isdnloop_lock, flags);
 	switch (sdef.ptype) {
 		case ISDN_PTYPE_EURO:
 			if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96",
 					  -1)) {
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 				return -ENOMEM;
 			}
 			card->sil[0] = card->sil[1] = 4;
 			if (isdnloop_fake(card, "TEI OK", 0)) {
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 				return -ENOMEM;
 			}
 			for (i = 0; i < 3; i++)
@@ -1098,12 +1088,12 @@
 		case ISDN_PTYPE_1TR6:
 			if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
 					  -1)) {
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 				return -ENOMEM;
 			}
 			card->sil[0] = card->sil[1] = 4;
 			if (isdnloop_fake(card, "TEI OK", 0)) {
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 				return -ENOMEM;
 			}
 			strcpy(card->s0num[0], sdef.num[0]);
@@ -1111,7 +1101,7 @@
 			card->s0num[2][0] = '\0';
 			break;
 		default:
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 			printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n",
 			       sdef.ptype);
 			return -EINVAL;
@@ -1122,7 +1112,7 @@
 	card->st_timer.data = (unsigned long) card;
 	add_timer(&card->st_timer);
 	card->flags |= ISDNLOOP_FLAGS_RUNNING;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
 	return 0;
 }
 
@@ -1472,6 +1462,7 @@
 		skb_queue_head_init(&card->bqueue[i]);
 	}
 	skb_queue_head_init(&card->dqueue);
+	card->isdnloop_lock = SPIN_LOCK_UNLOCKED;
 	card->next = cards;
 	cards = card;
 	if (!register_isdn(&card->interface)) {
diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h
index d699fe5..0d458a8 100644
--- a/drivers/isdn/isdnloop/isdnloop.h
+++ b/drivers/isdn/isdnloop/isdnloop.h
@@ -94,6 +94,7 @@
 	struct sk_buff_head
 	 bqueue[ISDNLOOP_BCH];  /* B-Channel queues                 */
 	struct sk_buff_head dqueue;	/* D-Channel queue                  */
+	spinlock_t isdnloop_lock;
 } isdnloop_card;
 
 /*
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 94f2148..6ead5e1 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -725,23 +725,27 @@
 
 	if (stat_st < stat_end)
 	{
-		copy_to_user(buf, statbuf + stat_st, len);
+		if (copy_to_user(buf, statbuf + stat_st, len))
+			return -EFAULT;
 		stat_st += len;	   
 	}
 	else
 	{
 		if (len > STATBUF_LEN - stat_st)
 		{
-			copy_to_user(buf, statbuf + stat_st, 
-				       STATBUF_LEN - stat_st);
-			copy_to_user(buf, statbuf, 
-				       len - (STATBUF_LEN - stat_st));
+			if (copy_to_user(buf, statbuf + stat_st,
+				       STATBUF_LEN - stat_st))
+				return -EFAULT;
+			if (copy_to_user(buf, statbuf,
+				       len - (STATBUF_LEN - stat_st)))
+				return -EFAULT;
 
 			stat_st = len - (STATBUF_LEN - stat_st);
 		}
 		else
 		{
-			copy_to_user(buf, statbuf + stat_st, len);
+			if (copy_to_user(buf, statbuf + stat_st, len))
+				return -EFAULT;
 
 			stat_st += len;
 			
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index ba76693..937fd21 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -311,6 +311,7 @@
 		dev->read_queue = frame->next;
 		spin_unlock_irqrestore(&dev->lock, flags);
 
+		msg = 0;
 		SET_MSG_CPU(msg, 0);
 		SET_MSG_PROC(msg, 0);
 		SET_MSG_CMD(msg, frame->skb->data[2]);
@@ -512,7 +513,7 @@
 }
 
 irqreturn_t
-pcbit_irq_handler(int interrupt, void *devptr, struct pt_regs *regs)
+pcbit_irq_handler(int interrupt, void *devptr)
 {
 	struct pcbit_dev *dev;
 	u_char info,
diff --git a/drivers/isdn/pcbit/layer2.h b/drivers/isdn/pcbit/layer2.h
index 0d99da3..2ac295e 100644
--- a/drivers/isdn/pcbit/layer2.h
+++ b/drivers/isdn/pcbit/layer2.h
@@ -124,7 +124,7 @@
 extern int pcbit_l2_write(struct pcbit_dev * dev, ulong msg, ushort refnum, 
                           struct sk_buff *skb, unsigned short hdr_len);
 
-extern irqreturn_t pcbit_irq_handler(int interrupt, void *, struct pt_regs *regs);
+extern irqreturn_t pcbit_irq_handler(int interrupt, void *);
 
 extern struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS];
 
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index a627e68..06c9872 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -35,7 +35,7 @@
 module_param_array(ram, int, NULL, 0);
 module_param(do_reset, bool, 0);
 
-extern irqreturn_t interrupt_handler(int, void *, struct pt_regs *);
+extern irqreturn_t interrupt_handler(int, void *);
 extern int sndpkt(int, int, int, struct sk_buff *);
 extern int command(isdn_ctrl *);
 extern int indicate_status(int, int, ulong, char*);
@@ -98,13 +98,14 @@
 			 * Confirm the I/O Address with a test
 			 */
 			if(io[b] == 0) {
-				pr_debug("I/O Address 0x%x is in use.\n");
+				pr_debug("I/O Address invalid.\n");
 				continue;
 			}
 
 			outb(0x18, io[b] + 0x400 * EXP_PAGE0);
 			if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) {
-				pr_debug("I/O Base 0x%x fails test\n");
+				pr_debug("I/O Base 0x%x fails test\n",
+					 io[b] + 0x400 * EXP_PAGE0);
 				continue;
 			}
 		}
@@ -158,8 +159,8 @@
 			outb(0xFF, io[b] + RESET_OFFSET);
 			msleep_interruptible(10000);
 		}
-		pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b],
-			ram[b] == 0 ? "will" : "won't");
+		pr_debug("RAM Base for board %d is 0x%lx, %s probe\n", b,
+			ram[b], ram[b] == 0 ? "will" : "won't");
 
 		if(ram[b]) {
 			/*
@@ -168,7 +169,7 @@
 			 * board model
 			 */
 			if(request_region(ram[b], SRAM_PAGESIZE, "sc test")) {
-				pr_debug("request_region for RAM base 0x%x succeeded\n", ram[b]);
+				pr_debug("request_region for RAM base 0x%lx succeeded\n", ram[b]);
 			 	model = identify_board(ram[b], io[b]);
 				release_region(ram[b], SRAM_PAGESIZE);
 			}
@@ -204,7 +205,7 @@
 			 * Nope, there was no place in RAM for the
 			 * board, or it couldn't be identified
 			 */
-			 pr_debug("Failed to find an adapter at 0x%x\n", ram[b]);
+			 pr_debug("Failed to find an adapter at 0x%lx\n", ram[b]);
 			 continue;
 		}
 
@@ -451,7 +452,7 @@
 	HWConfig_pl hwci;
 	int x;
 
-	pr_debug("Attempting to identify adapter @ 0x%x io 0x%x\n",
+	pr_debug("Attempting to identify adapter @ 0x%lx io 0x%x\n",
 		rambase, iobase);
 
 	/*
@@ -490,7 +491,7 @@
 	outb(PRI_BASEPG_VAL, pgport);
 	msleep_interruptible(1000);
 	sig = readl(rambase + SIG_OFFSET);
-	pr_debug("Looking for a signature, got 0x%x\n", sig);
+	pr_debug("Looking for a signature, got 0x%lx\n", sig);
 	if(sig == SIGNATURE)
 		return PRI_BOARD;
 
@@ -500,7 +501,7 @@
 	outb(BRI_BASEPG_VAL, pgport);
 	msleep_interruptible(1000);
 	sig = readl(rambase + SIG_OFFSET);
-	pr_debug("Looking for a signature, got 0x%x\n", sig);
+	pr_debug("Looking for a signature, got 0x%lx\n", sig);
 	if(sig == SIGNATURE)
 		return BRI_BOARD;
 
@@ -510,7 +511,7 @@
 	 * Try to spot a card
 	 */
 	sig = readl(rambase + SIG_OFFSET);
-	pr_debug("Looking for a signature, got 0x%x\n", sig);
+	pr_debug("Looking for a signature, got 0x%lx\n", sig);
 	if(sig != SIGNATURE)
 		return -1;
 
@@ -540,7 +541,7 @@
 	memcpy_fromio(&rcvmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN);
 	pr_debug("Got HWConfig response, status = 0x%x\n", rcvmsg.rsp_status);
 	memcpy(&hwci, &(rcvmsg.msg_data.HWCresponse), sizeof(HWConfig_pl));
-	pr_debug("Hardware Config: Interface: %s, RAM Size: %d, Serial: %s\n"
+	pr_debug("Hardware Config: Interface: %s, RAM Size: %ld, Serial: %s\n"
 		 "                 Part: %s, Rev: %s\n",
 		 hwci.st_u_sense ? "S/T" : "U", hwci.ram_size,
 		 hwci.serial_no, hwci.part_no, hwci.rev_no);
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index ae62631..cd17de1 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -45,7 +45,7 @@
 /*
  * 
  */
-irqreturn_t interrupt_handler(int interrupt, void *cardptr, struct pt_regs *regs)
+irqreturn_t interrupt_handler(int interrupt, void *cardptr)
 {
 
 	RspMessage rcvmsg;
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index f50defc..1e04676 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -44,7 +44,7 @@
 		return -ENODEV;
 	}
 
-	pr_debug("%s: sndpkt: frst = 0x%x nxt = %d  f = %d n = %d\n",
+	pr_debug("%s: sndpkt: frst = 0x%lx nxt = %d  f = %d n = %d\n",
 		sc_adapter[card]->devicename,
 		sc_adapter[card]->channel[channel].first_sendbuf,
 		sc_adapter[card]->channel[channel].next_sendbuf,
@@ -66,7 +66,7 @@
 	ReqLnkWrite.buff_offset = sc_adapter[card]->channel[channel].next_sendbuf *
 		BUFFER_SIZE + sc_adapter[card]->channel[channel].first_sendbuf;
 	ReqLnkWrite.msg_len = data->len; /* sk_buff size */
-	pr_debug("%s: writing %d bytes to buffer offset 0x%x\n",
+	pr_debug("%s: writing %d bytes to buffer offset 0x%lx\n",
 			sc_adapter[card]->devicename,
 			ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset);
 	memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len);
@@ -74,7 +74,7 @@
 	/*
 	 * sendmessage
 	 */
-	pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n",
+	pr_debug("%s: sndpkt size=%d, buf_offset=0x%lx buf_indx=%d\n",
 		sc_adapter[card]->devicename,
 		ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset,
 		sc_adapter[card]->channel[channel].next_sendbuf);
@@ -124,7 +124,7 @@
 			return;
 		}
 		skb_put(skb, rcvmsg->msg_data.response.msg_len);
-		pr_debug("%s: getting data from offset: 0x%x\n",
+		pr_debug("%s: getting data from offset: 0x%lx\n",
 			sc_adapter[card]->devicename,
 			rcvmsg->msg_data.response.buff_offset);
 		memcpy_fromshmem(card,
@@ -143,7 +143,7 @@
 /*		memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */
 		newll.buff_offset = rcvmsg->msg_data.response.buff_offset;
 		newll.msg_len = BUFFER_SIZE;
-		pr_debug("%s: recycled buffer at offset 0x%x size %d\n",
+		pr_debug("%s: recycled buffer at offset 0x%lx size %d\n",
 			sc_adapter[card]->devicename,
 			newll.buff_offset, newll.msg_len);
 		sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
@@ -186,7 +186,7 @@
 	sc_adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2;
 	sc_adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2;
 	sc_adapter[card]->channel[c-1].next_sendbuf = 0;
-	pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n",
+	pr_debug("%s: send buffer setup complete: first=0x%lx n=%d f=%d, nxt=%d\n",
 				sc_adapter[card]->devicename,
 				sc_adapter[card]->channel[c-1].first_sendbuf,
 				sc_adapter[card]->channel[c-1].num_sendbufs,
@@ -203,7 +203,7 @@
 			((sc_adapter[card]->channel[c-1].first_sendbuf +
 			(nBuffers / 2) * buffer_size) + (buffer_size * i));
 		RcvBuffOffset.msg_len = buffer_size;
-		pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n",
+		pr_debug("%s: adding RcvBuffer #%d offset=0x%lx sz=%d bufsz:%d\n",
 				sc_adapter[card]->devicename,
 				i + 1, RcvBuffOffset.buff_offset, 
 				RcvBuffOffset.msg_len,buffer_size);
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 2485482..6f58862 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -61,7 +61,7 @@
 	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
 		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
-	pr_debug("%s: copying %d bytes from %#x to %#x\n",
+	pr_debug("%s: copying %d bytes from %#lx to %#lx\n",
 		sc_adapter[card]->devicename, n,
 		(unsigned long) src,
 		sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index aecbbe2..3c17112 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -91,6 +91,8 @@
  */
 int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 {
+	int rc;
+
 	led_cdev->class_dev = class_device_create(leds_class, NULL, 0,
 						parent, "%s", led_cdev->name);
 	if (unlikely(IS_ERR(led_cdev->class_dev)))
@@ -99,8 +101,10 @@
 	class_set_devdata(led_cdev->class_dev, led_cdev);
 
 	/* register the attributes */
-	class_device_create_file(led_cdev->class_dev,
-				&class_device_attr_brightness);
+	rc = class_device_create_file(led_cdev->class_dev,
+				      &class_device_attr_brightness);
+	if (rc)
+		goto err_out;
 
 	/* add to the list of leds */
 	write_lock(&leds_list_lock);
@@ -110,16 +114,28 @@
 #ifdef CONFIG_LEDS_TRIGGERS
 	rwlock_init(&led_cdev->trigger_lock);
 
-	led_trigger_set_default(led_cdev);
+	rc = class_device_create_file(led_cdev->class_dev,
+				      &class_device_attr_trigger);
+	if (rc)
+		goto err_out_led_list;
 
-	class_device_create_file(led_cdev->class_dev,
-				&class_device_attr_trigger);
+	led_trigger_set_default(led_cdev);
 #endif
 
 	printk(KERN_INFO "Registered led device: %s\n",
 			led_cdev->class_dev->class_id);
 
 	return 0;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+err_out_led_list:
+	class_device_remove_file(led_cdev->class_dev,
+				&class_device_attr_brightness);
+	list_del(&led_cdev->node);
+#endif
+err_out:
+	class_device_unregister(led_cdev->class_dev);
+	return rc;
 }
 EXPORT_SYMBOL_GPL(led_classdev_register);
 
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index 179c287..29a8818a 100644
--- a/drivers/leds/ledtrig-timer.c
+++ b/drivers/leds/ledtrig-timer.c
@@ -123,6 +123,7 @@
 static void timer_trig_activate(struct led_classdev *led_cdev)
 {
 	struct timer_trig_data *timer_data;
+	int rc;
 
 	timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL);
 	if (!timer_data)
@@ -134,10 +135,21 @@
 	timer_data->timer.function = led_timer_function;
 	timer_data->timer.data = (unsigned long) led_cdev;
 
-	class_device_create_file(led_cdev->class_dev,
+	rc = class_device_create_file(led_cdev->class_dev,
 				&class_device_attr_delay_on);
-	class_device_create_file(led_cdev->class_dev,
+	if (rc) goto err_out;
+	rc = class_device_create_file(led_cdev->class_dev,
 				&class_device_attr_delay_off);
+	if (rc) goto err_out_delayon;
+
+	return;
+
+err_out_delayon:
+	class_device_remove_file(led_cdev->class_dev,
+				&class_device_attr_delay_on);
+err_out:
+	led_cdev->trigger_data = NULL;
+	kfree(timer_data);
 }
 
 static void timer_trig_deactivate(struct led_classdev *led_cdev)
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index d56d400..17ef5d3 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -30,7 +30,7 @@
 
 /*#define DEBUG_ADB_IOP*/
 
-extern void iop_ism_irq(int, void *, struct pt_regs *);
+extern void iop_ism_irq(int, void *);
 
 static struct adb_request *current_req;
 static struct adb_request *last_req;
@@ -78,7 +78,7 @@
  * This will be called when a packet has been successfully sent.
  */
 
-static void adb_iop_complete(struct iop_msg *msg, struct pt_regs *regs)
+static void adb_iop_complete(struct iop_msg *msg)
 {
 	struct adb_request *req;
 	uint flags;
@@ -100,7 +100,7 @@
  * commands or autopoll packets) are received.
  */
 
-static void adb_iop_listen(struct iop_msg *msg, struct pt_regs *regs)
+static void adb_iop_listen(struct iop_msg *msg)
 {
 	struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message;
 	struct adb_request *req;
@@ -143,7 +143,7 @@
 			req->reply_len = amsg->count + 1;
 			memcpy(req->reply, &amsg->cmd, req->reply_len);
 		} else {
-			adb_input(&amsg->cmd, amsg->count + 1, regs,
+			adb_input(&amsg->cmd, amsg->count + 1,
 				  amsg->flags & ADB_IOP_AUTOPOLL);
 		}
 		memcpy(msg->reply, msg->message, IOP_MSG_LEN);
@@ -266,7 +266,7 @@
 void adb_iop_poll(void)
 {
 	if (adb_iop_state == idle) adb_iop_start();
-	iop_ism_irq(0, (void *) ADB_IOP, NULL);
+	iop_ism_irq(0, (void *) ADB_IOP);
 }
 
 int adb_iop_reset_bus(void)
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 360f93f..be0bd34 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -103,7 +103,7 @@
 static int try_handler_change(int, int);
 
 static struct adb_handler {
-	void (*handler)(unsigned char *, int, struct pt_regs *, int);
+	void (*handler)(unsigned char *, int, int);
 	int original_address;
 	int handler_id;
 	int busy;
@@ -522,7 +522,7 @@
     the handler_id id it doesn't match. */
 int
 adb_register(int default_id, int handler_id, struct adb_ids *ids,
-	     void (*handler)(unsigned char *, int, struct pt_regs *, int))
+	     void (*handler)(unsigned char *, int, int))
 {
 	int i;
 
@@ -570,13 +570,13 @@
 }
 
 void
-adb_input(unsigned char *buf, int nb, struct pt_regs *regs, int autopoll)
+adb_input(unsigned char *buf, int nb, int autopoll)
 {
 	int i, id;
 	static int dump_adb_input = 0;
 	unsigned long flags;
 	
-	void (*handler)(unsigned char *, int, struct pt_regs *, int);
+	void (*handler)(unsigned char *, int, int);
 
 	/* We skip keystrokes and mouse moves when the sleep process
 	 * has been started. We stop autopoll, but this is another security
@@ -597,7 +597,7 @@
 		adb_handler[id].busy = 1;
 	write_unlock_irqrestore(&adb_handler_lock, flags);
 	if (handler != NULL) {
-		(*handler)(buf, nb, regs, autopoll);
+		(*handler)(buf, nb, autopoll);
 		wmb();
 		adb_handler[id].busy = 0;
 	}
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index b7fb367..5066e7a 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -222,7 +222,7 @@
 
 static void adbhid_probe(void);
 
-static void adbhid_input_keycode(int, int, int, struct pt_regs *);
+static void adbhid_input_keycode(int, int, int);
 
 static void init_trackpad(int id);
 static void init_trackball(int id);
@@ -253,7 +253,7 @@
 #define ADBMOUSE_MACALLY2	9	/* MacAlly 2-button mouse */
 
 static void
-adbhid_keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll)
+adbhid_keyboard_input(unsigned char *data, int nb, int apoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
 
@@ -266,13 +266,13 @@
 	/* first check this is from register 0 */
 	if (nb != 3 || (data[0] & 3) != KEYB_KEYREG)
 		return;		/* ignore it */
-	adbhid_input_keycode(id, data[1], 0, regs);
+	adbhid_input_keycode(id, data[1], 0);
 	if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f)))
-		adbhid_input_keycode(id, data[2], 0, regs);
+		adbhid_input_keycode(id, data[2], 0);
 }
 
 static void
-adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
+adbhid_input_keycode(int id, int keycode, int repeat)
 {
 	struct adbhid *ahid = adbhid[id];
 	int up_flag;
@@ -282,7 +282,6 @@
 
 	switch (keycode) {
 	case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
-		input_regs(ahid->input, regs);
 		input_report_key(ahid->input, KEY_CAPSLOCK, 1);
 		input_report_key(ahid->input, KEY_CAPSLOCK, 0);
 		input_sync(ahid->input);
@@ -338,7 +337,6 @@
 	}
 
 	if (adbhid[id]->keycode[keycode]) {
-		input_regs(adbhid[id]->input, regs);
 		input_report_key(adbhid[id]->input,
 				 adbhid[id]->keycode[keycode], !up_flag);
 		input_sync(adbhid[id]->input);
@@ -349,7 +347,7 @@
 }
 
 static void
-adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
+adbhid_mouse_input(unsigned char *data, int nb, int autopoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
 
@@ -432,8 +430,6 @@
                 break;
 	}
 
-	input_regs(adbhid[id]->input, regs);
-
 	input_report_key(adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
 	input_report_key(adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
 
@@ -449,7 +445,7 @@
 }
 
 static void
-adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
+adbhid_buttons_input(unsigned char *data, int nb, int autopoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
 
@@ -458,8 +454,6 @@
 		return;
 	}
 
-	input_regs(adbhid[id]->input, regs);
-
 	switch (adbhid[id]->original_handler_id) {
 	default:
 	case 0x02: /* Adjustable keyboard button device */
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index 4b08852..797cef7 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -64,7 +64,7 @@
 
 static int macio_probe(void);
 static int macio_init(void);
-static irqreturn_t macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t macio_adb_interrupt(int irq, void *arg);
 static int macio_send_request(struct adb_request *req, int sync);
 static int macio_adb_autopoll(int devs);
 static void macio_adb_poll(void);
@@ -189,8 +189,7 @@
 	return 0;
 }
 
-static irqreturn_t macio_adb_interrupt(int irq, void *arg,
-				       struct pt_regs *regs)
+static irqreturn_t macio_adb_interrupt(int irq, void *arg)
 {
 	int i, n, err;
 	struct adb_request *req = NULL;
@@ -260,7 +259,7 @@
 		(*done)(req);
 	}
 	if (ibuf_len)
-		adb_input(ibuf, ibuf_len, regs, autopoll);
+		adb_input(ibuf, ibuf_len, autopoll);
 
 	return IRQ_RETVAL(handled);
 }
@@ -271,6 +270,6 @@
 
 	local_irq_save(flags);
 	if (in_8(&adb->intr.r) != 0)
-		macio_adb_interrupt(0, NULL, NULL);
+		macio_adb_interrupt(0, NULL);
 	local_irq_restore(flags);
 }
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index c0f9d82..ade25b3 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -145,7 +145,7 @@
 }
 
 
-static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t smu_db_intr(int irq, void *arg)
 {
 	unsigned long flags;
 	struct smu_cmd *cmd;
@@ -224,7 +224,7 @@
 }
 
 
-static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t smu_msg_intr(int irq, void *arg)
 {
 	/* I don't quite know what to do with this one, we seem to never
 	 * receive it, so I suspect we have to arm it someway in the SMU
@@ -309,7 +309,7 @@
 
 	gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
 	if ((gpio & 7) == 7)
-		smu_db_intr(smu->db_irq, smu, NULL);
+		smu_db_intr(smu->db_irq, smu);
 }
 EXPORT_SYMBOL(smu_poll);
 
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 7512d1c..df66291 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -98,8 +98,8 @@
 
 static int cuda_init_via(void);
 static void cuda_start(void);
-static irqreturn_t cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
-static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs);
+static irqreturn_t cuda_interrupt(int irq, void *arg);
+static void cuda_input(unsigned char *buf, int nb);
 void cuda_poll(void);
 static int cuda_write(struct adb_request *req);
 
@@ -437,12 +437,12 @@
      * disable_irq(), would that work on m68k ? --BenH
      */
     local_irq_save(flags);
-    cuda_interrupt(0, NULL, NULL);
+    cuda_interrupt(0, NULL);
     local_irq_restore(flags);
 }
 
 static irqreturn_t
-cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
+cuda_interrupt(int irq, void *arg)
 {
     int status;
     struct adb_request *req = NULL;
@@ -594,12 +594,12 @@
 		(*done)(req);
     }
     if (ibuf_len)
-	cuda_input(ibuf, ibuf_len, regs);
+	cuda_input(ibuf, ibuf_len);
     return IRQ_HANDLED;
 }
 
 static void
-cuda_input(unsigned char *buf, int nb, struct pt_regs *regs)
+cuda_input(unsigned char *buf, int nb)
 {
     int i;
 
@@ -615,7 +615,7 @@
 	}
 #endif /* CONFIG_XMON */
 #ifdef CONFIG_ADB
-	adb_input(buf+2, nb-2, regs, buf[1] & 0x40);
+	adb_input(buf+2, nb-2, buf[1] & 0x40);
 #endif /* CONFIG_ADB */
 	break;
 
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 2a2ffe0..5d88d5b 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -77,7 +77,7 @@
 
 static int  macii_init_via(void);
 static void macii_start(void);
-static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t macii_interrupt(int irq, void *arg);
 static void macii_retransmit(int);
 static void macii_queue_poll(void);
 
@@ -295,7 +295,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	if (via[IFR] & SR_INT) macii_interrupt(0, NULL, NULL);
+	if (via[IFR] & SR_INT) macii_interrupt(0, NULL);
 	local_irq_restore(flags);
 }
 
@@ -410,7 +410,7 @@
  * Note: As of 21/10/97, the MacII ADB part works including timeout detection
  * and retransmit (Talk to the last active device).
  */
-static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t macii_interrupt(int irq, void *arg)
 {
 	int x, adbdir;
 	unsigned long flags;
@@ -602,8 +602,7 @@
 				current_req = req->next;
 				if (req->done) (*req->done)(req);
 			} else {
-				adb_input(reply_buf, reply_ptr - reply_buf,
-					  regs, 0);
+				adb_input(reply_buf, reply_ptr - reply_buf, 0);
 			}
 
 			/*
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 0129fcc..1f0aa5d 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -84,8 +84,8 @@
 static int maciisi_send_request(struct adb_request* req, int sync);
 static void maciisi_sync(struct adb_request *req);
 static int maciisi_write(struct adb_request* req);
-static irqreturn_t maciisi_interrupt(int irq, void* arg, struct pt_regs* regs);
-static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs);
+static irqreturn_t maciisi_interrupt(int irq, void* arg);
+static void maciisi_input(unsigned char *buf, int nb);
 static int maciisi_init_via(void);
 static void maciisi_poll(void);
 static int maciisi_start(void);
@@ -421,7 +421,7 @@
 
 	local_irq_save(flags);
 	if (via[IFR] & SR_INT) {
-		maciisi_interrupt(0, NULL, NULL);
+		maciisi_interrupt(0, NULL);
 	}
 	else /* avoid calling this function too quickly in a loop */
 		udelay(ADB_DELAY);
@@ -433,7 +433,7 @@
    register is either full or empty. In practice, I have no idea what
    it means :( */
 static irqreturn_t
-maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
+maciisi_interrupt(int irq, void* arg)
 {
 	int status;
 	struct adb_request *req;
@@ -612,7 +612,7 @@
 			/* Obviously, we got it */
 			reading_reply = 0;
 		} else {
-			maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf, regs);
+			maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf);
 		}
 		maciisi_state = idle;
 		status = via[B] & (TIP|TREQ);
@@ -657,7 +657,7 @@
 }
 
 static void
-maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs)
+maciisi_input(unsigned char *buf, int nb)
 {
 #ifdef DEBUG_MACIISI_ADB
     int i;
@@ -665,7 +665,7 @@
 
     switch (buf[0]) {
     case ADB_PACKET:
-	    adb_input(buf+2, nb-2, regs, buf[1] & 0x40);
+	    adb_input(buf+2, nb-2, buf[1] & 0x40);
 	    break;
     default:
 #ifdef DEBUG_MACIISI_ADB
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4f04fd0..e63ea1c 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -191,8 +191,8 @@
 
 static int init_pmu(void);
 static void pmu_start(void);
-static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
-static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t via_pmu_interrupt(int irq, void *arg);
+static irqreturn_t gpio1_interrupt(int irq, void *arg);
 static int proc_get_info(char *page, char **start, off_t off,
 			  int count, int *eof, void *data);
 static int proc_get_irqstats(char *page, char **start, off_t off,
@@ -555,7 +555,7 @@
 		}
 		if (pmu_state == idle)
 			adb_int_pending = 1;
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 		udelay(10);
 	}
 
@@ -1215,7 +1215,7 @@
 		return;
 	if (disable_poll)
 		return;
-	via_pmu_interrupt(0, NULL, NULL);
+	via_pmu_interrupt(0, NULL);
 }
 
 void
@@ -1228,7 +1228,7 @@
 	/* Kicks ADB read when PMU is suspended */
 	adb_int_pending = 1;
 	do {
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 	} while (pmu_suspended && (adb_int_pending || pmu_state != idle
 		|| req_awaiting_reply));
 }
@@ -1239,7 +1239,7 @@
 	if (!via)
 		return;
 	while((pmu_state != idle && pmu_state != locked) || !req->complete)
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 }
 
 /* This function loops until the PMU is idle and prevents it from
@@ -1268,7 +1268,7 @@
 		spin_unlock_irqrestore(&pmu_lock, flags);
 		if (req_awaiting_reply)
 			adb_int_pending = 1;
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 		spin_lock_irqsave(&pmu_lock, flags);
 		if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) {
 #ifdef SUSPEND_USES_PMU
@@ -1318,7 +1318,7 @@
 
 /* Interrupt data could be the result data from an ADB cmd */
 static void
-pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
+pmu_handle_data(unsigned char *data, int len)
 {
 	unsigned char ints, pirq;
 	int i = 0;
@@ -1393,7 +1393,7 @@
 			if (!(pmu_kind == PMU_OHARE_BASED && len == 4
 			      && data[1] == 0x2c && data[3] == 0xff
 			      && (data[2] & ~1) == 0xf4))
-				adb_input(data+1, len-1, regs, 1);
+				adb_input(data+1, len-1, 1);
 #endif /* CONFIG_ADB */		
 		}
 	}
@@ -1431,7 +1431,7 @@
 }
 
 static struct adb_request*
-pmu_sr_intr(struct pt_regs *regs)
+pmu_sr_intr(void)
 {
 	struct adb_request *req;
 	int bite = 0;
@@ -1537,7 +1537,7 @@
 }
 
 static irqreturn_t
-via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
+via_pmu_interrupt(int irq, void *arg)
 {
 	unsigned long flags;
 	int intr;
@@ -1567,7 +1567,7 @@
 			pmu_irq_stats[0]++;
 		}
 		if (intr & SR_INT) {
-			req = pmu_sr_intr(regs);
+			req = pmu_sr_intr();
 			if (req)
 				break;
 		}
@@ -1613,7 +1613,7 @@
 		
 	/* Deal with interrupt datas outside of the lock */
 	if (int_data >= 0) {
-		pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data], regs);
+		pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data]);
 		spin_lock_irqsave(&pmu_lock, flags);
 		++disable_poll;
 		int_data_state[int_data] = int_data_empty;
@@ -1638,7 +1638,7 @@
 
 
 static irqreturn_t
-gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
+gpio1_interrupt(int irq, void *arg)
 {
 	unsigned long flags;
 
@@ -1651,7 +1651,7 @@
 		pmu_irq_stats[1]++;
 		adb_int_pending = 1;
 		spin_unlock_irqrestore(&pmu_lock, flags);
-		via_pmu_interrupt(0, NULL, NULL);
+		via_pmu_interrupt(0, NULL);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
@@ -2116,7 +2116,7 @@
 
 	/* Force a poll of ADB interrupts */
 	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL, NULL);
+	via_pmu_interrupt(0, NULL);
 
 	/* Restart jiffies & scheduling */
 	wakeup_decrementer();
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 9f4eff1..d9986f3 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -107,7 +107,7 @@
 static int pmu_probe(void);
 static int pmu_init(void);
 static void pmu_start(void);
-static irqreturn_t pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t pmu_interrupt(int irq, void *arg);
 static int pmu_send_request(struct adb_request *req, int sync);
 static int pmu_autopoll(int devs);
 void pmu_poll(void);
@@ -118,8 +118,7 @@
 static void send_byte(int x);
 static void recv_byte(void);
 static void pmu_done(struct adb_request *req);
-static void pmu_handle_data(unsigned char *data, int len,
-			    struct pt_regs *regs);
+static void pmu_handle_data(unsigned char *data, int len);
 static void set_volume(int level);
 static void pmu_enable_backlight(int on);
 static void pmu_set_brightness(int level);
@@ -222,7 +221,7 @@
 		}
 		if (pmu_state == idle) {
 			adb_int_pending = 1;
-			pmu_interrupt(0, NULL, NULL);
+			pmu_interrupt(0, NULL);
 		}
 		pmu_poll();
 		udelay(10);
@@ -563,17 +562,17 @@
 	local_irq_save(flags);
 	if (via1[IFR] & SR_INT) {
 		via1[IFR] = SR_INT;
-		pmu_interrupt(IRQ_MAC_ADB_SR, NULL, NULL);
+		pmu_interrupt(IRQ_MAC_ADB_SR, NULL);
 	}
 	if (via1[IFR] & CB1_INT) {
 		via1[IFR] = CB1_INT;
-		pmu_interrupt(IRQ_MAC_ADB_CL, NULL, NULL);
+		pmu_interrupt(IRQ_MAC_ADB_CL, NULL);
 	}
 	local_irq_restore(flags);
 }
 
 static irqreturn_t
-pmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+pmu_interrupt(int irq, void *dev_id)
 {
 	struct adb_request *req;
 	int timeout, bite = 0;	/* to prevent compiler warning */
@@ -657,7 +656,7 @@
 			}
 
 			if (pmu_state == reading_intr) {
-				pmu_handle_data(interrupt_data, data_index, regs);
+				pmu_handle_data(interrupt_data, data_index);
 			} else {
 				req = current_req;
 				current_req = req->next;
@@ -701,7 +700,7 @@
 
 /* Interrupt data could be the result data from an ADB cmd */
 static void 
-pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
+pmu_handle_data(unsigned char *data, int len)
 {
 	static int show_pmu_ints = 1;
 
@@ -726,7 +725,7 @@
 			}
 			pmu_done(req);
 		} else {
-			adb_input(data+1, len-1, regs, 1);
+			adb_input(data+1, len-1, 1);
 		}
 	} else {
 		if (data[0] == 0x08 && len == 3) {
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
index ef66bf2..fa4b13f 100644
--- a/drivers/macintosh/windfarm_pm112.c
+++ b/drivers/macintosh/windfarm_pm112.c
@@ -650,24 +650,26 @@
 	.notifier_call = pm112_wf_notify,
 };
 
-static int wf_pm112_probe(struct device *dev)
+static int wf_pm112_probe(struct platform_device *dev)
 {
 	wf_register_client(&pm112_events);
 	return 0;
 }
 
-static int wf_pm112_remove(struct device *dev)
+static int __devexit wf_pm112_remove(struct platform_device *dev)
 {
 	wf_unregister_client(&pm112_events);
 	/* should release all sensors and controls */
 	return 0;
 }
 
-static struct device_driver wf_pm112_driver = {
-	.name = "windfarm",
-	.bus = &platform_bus_type,
+static struct platform_driver wf_pm112_driver = {
 	.probe = wf_pm112_probe,
-	.remove = wf_pm112_remove,
+	.remove = __devexit_p(wf_pm112_remove),
+	.driver = {
+		.name = "windfarm",
+		.bus = &platform_bus_type,
+	},
 };
 
 static int __init wf_pm112_init(void)
@@ -683,13 +685,13 @@
 		++nr_cores;
 
 	printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n");
-	driver_register(&wf_pm112_driver);
+	platform_driver_register(&wf_pm112_driver);
 	return 0;
 }
 
 static void __exit wf_pm112_exit(void)
 {
-	driver_unregister(&wf_pm112_driver);
+	platform_driver_unregister(&wf_pm112_driver);
 }
 
 module_init(wf_pm112_init);
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index 2ff546e..2a94485 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -131,8 +131,6 @@
 
 static int wf_smu_mach_model;	/* machine model id */
 
-static struct device *wf_smu_dev;
-
 /* Controls & sensors */
 static struct wf_sensor	*sensor_cpu_power;
 static struct wf_sensor	*sensor_cpu_temp;
@@ -717,16 +715,14 @@
 	return 0;
 }
 
-static int wf_smu_probe(struct device *ddev)
+static int wf_smu_probe(struct platform_device *ddev)
 {
-	wf_smu_dev = ddev;
-
 	wf_register_client(&wf_smu_events);
 
 	return 0;
 }
 
-static int wf_smu_remove(struct device *ddev)
+static int __devexit wf_smu_remove(struct platform_device *ddev)
 {
 	wf_unregister_client(&wf_smu_events);
 
@@ -766,16 +762,16 @@
 	if (wf_smu_cpu_fans)
 		kfree(wf_smu_cpu_fans);
 
-	wf_smu_dev = NULL;
-
 	return 0;
 }
 
-static struct device_driver wf_smu_driver = {
-        .name = "windfarm",
-        .bus = &platform_bus_type,
+static struct platform_driver wf_smu_driver = {
         .probe = wf_smu_probe,
-        .remove = wf_smu_remove,
+        .remove = __devexit_p(wf_smu_remove),
+	.driver = {
+		.name = "windfarm",
+		.bus = &platform_bus_type,
+	},
 };
 
 
@@ -794,7 +790,7 @@
 		request_module("windfarm_lm75_sensor");
 
 #endif /* MODULE */
-		driver_register(&wf_smu_driver);
+		platform_driver_register(&wf_smu_driver);
 	}
 
 	return rc;
@@ -803,7 +799,7 @@
 static void __exit wf_smu_exit(void)
 {
 
-	driver_unregister(&wf_smu_driver);
+	platform_driver_unregister(&wf_smu_driver);
 }
 
 
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index 59e9ffe..9961a67 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -63,8 +63,6 @@
  */
 #undef HACKED_OVERTEMP
 
-static struct device *wf_smu_dev;
-
 /* Controls & sensors */
 static struct wf_sensor	*sensor_cpu_power;
 static struct wf_sensor	*sensor_cpu_temp;
@@ -641,16 +639,14 @@
 	return 0;
 }
 
-static int wf_smu_probe(struct device *ddev)
+static int wf_smu_probe(struct platform_device *ddev)
 {
-	wf_smu_dev = ddev;
-
 	wf_register_client(&wf_smu_events);
 
 	return 0;
 }
 
-static int wf_smu_remove(struct device *ddev)
+static int __devexit wf_smu_remove(struct platform_device *ddev)
 {
 	wf_unregister_client(&wf_smu_events);
 
@@ -698,16 +694,16 @@
 	if (wf_smu_cpu_fans)
 		kfree(wf_smu_cpu_fans);
 
-	wf_smu_dev = NULL;
-
 	return 0;
 }
 
-static struct device_driver wf_smu_driver = {
-        .name = "windfarm",
-        .bus = &platform_bus_type,
+static struct platform_driver wf_smu_driver = {
         .probe = wf_smu_probe,
-        .remove = wf_smu_remove,
+        .remove = __devexit_p(wf_smu_remove),
+	.driver = {
+		.name = "windfarm",
+		.bus = &platform_bus_type,
+	},
 };
 
 
@@ -725,7 +721,7 @@
 		request_module("windfarm_lm75_sensor");
 
 #endif /* MODULE */
-		driver_register(&wf_smu_driver);
+		platform_driver_register(&wf_smu_driver);
 	}
 
 	return rc;
@@ -734,7 +730,7 @@
 static void __exit wf_smu_exit(void)
 {
 
-	driver_unregister(&wf_smu_driver);
+	platform_driver_unregister(&wf_smu_driver);
 }
 
 
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index 09baa43..da862e4 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -100,6 +100,7 @@
 int __init mca_register_device(int bus, struct mca_device *mca_dev)
 {
 	struct mca_bus *mca_bus = mca_root_busses[bus];
+	int rc;
 
 	mca_dev->dev.parent = &mca_bus->dev;
 	mca_dev->dev.bus = &mca_bus_type;
@@ -108,13 +109,23 @@
 	mca_dev->dev.dma_mask = &mca_dev->dma_mask;
 	mca_dev->dev.coherent_dma_mask = mca_dev->dma_mask;
 
-	if (device_register(&mca_dev->dev))
-		return 0;
+	rc = device_register(&mca_dev->dev);
+	if (rc)
+		goto err_out;
 
-	device_create_file(&mca_dev->dev, &dev_attr_id);
-	device_create_file(&mca_dev->dev, &dev_attr_pos);
+	rc = device_create_file(&mca_dev->dev, &dev_attr_id);
+	if (rc) goto err_out_devreg;
+	rc = device_create_file(&mca_dev->dev, &dev_attr_pos);
+	if (rc) goto err_out_id;
 
 	return 1;
+
+err_out_id:
+	device_remove_file(&mca_dev->dev, &dev_attr_id);
+err_out_devreg:
+	device_unregister(&mca_dev->dev);
+err_out:
+	return 0;
 }
 
 /* */
@@ -130,13 +141,16 @@
 		return NULL;
 	}
 
-	mca_bus = kmalloc(sizeof(struct mca_bus), GFP_KERNEL);
+	mca_bus = kzalloc(sizeof(struct mca_bus), GFP_KERNEL);
 	if (!mca_bus)
 		return NULL;
-	memset(mca_bus, 0, sizeof(struct mca_bus));
+
 	sprintf(mca_bus->dev.bus_id,"mca%d",bus);
 	sprintf(mca_bus->name,"Host %s MCA Bridge", bus ? "Secondary" : "Primary");
-	device_register(&mca_bus->dev);
+	if (device_register(&mca_bus->dev)) {
+		kfree(mca_bus);
+		return NULL;
+	}
 
 	mca_root_busses[bus] = mca_bus;
 
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 8e67634..d6f6147 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -536,7 +536,7 @@
 		printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) "
 			"-- forcing full recovery\n", bmname(bitmap), events,
 			(unsigned long long) bitmap->mddev->events);
-		sb->state |= BITMAP_STALE;
+		sb->state |= cpu_to_le32(BITMAP_STALE);
 	}
 success:
 	/* assign fields using values from superblock */
@@ -544,11 +544,11 @@
 	bitmap->daemon_sleep = daemon_sleep;
 	bitmap->daemon_lastrun = jiffies;
 	bitmap->max_write_behind = write_behind;
-	bitmap->flags |= sb->state;
+	bitmap->flags |= le32_to_cpu(sb->state);
 	if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
 		bitmap->flags |= BITMAP_HOSTENDIAN;
 	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
-	if (sb->state & BITMAP_STALE)
+	if (sb->state & cpu_to_le32(BITMAP_STALE))
 		bitmap->events_cleared = bitmap->mddev->events;
 	err = 0;
 out:
@@ -578,9 +578,9 @@
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 	switch (op) {
-		case MASK_SET: sb->state |= bits;
+		case MASK_SET: sb->state |= cpu_to_le32(bits);
 				break;
-		case MASK_UNSET: sb->state &= ~bits;
+		case MASK_UNSET: sb->state &= cpu_to_le32(~bits);
 				break;
 		default: BUG();
 	}
@@ -1413,7 +1413,7 @@
 	int err;
 	sector_t start;
 
-	BUG_ON(sizeof(bitmap_super_t) != 256);
+	BUILD_BUG_ON(sizeof(bitmap_super_t) != 256);
 
 	if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */
 		return 0;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 655d816..a625576 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/crypto.h>
 #include <linux/workqueue.h>
+#include <linux/backing-dev.h>
 #include <asm/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
@@ -602,7 +603,7 @@
 
 		/* out of memory -> run queues */
 		if (remaining)
-			blk_congestion_wait(bio_data_dir(clone), HZ/100);
+			congestion_wait(bio_data_dir(clone), HZ/100);
 	}
 }
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index cb82816..7daa7b1 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -974,12 +974,13 @@
  * version 1 superblock
  */
 
-static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
+static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb)
 {
-	unsigned int disk_csum, csum;
+	__le32 disk_csum;
+	u32 csum;
 	unsigned long long newcsum;
 	int size = 256 + le32_to_cpu(sb->max_dev)*2;
-	unsigned int *isuper = (unsigned int*)sb;
+	__le32 *isuper = (__le32*)sb;
 	int i;
 
 	disk_csum = sb->sb_csum;
@@ -989,7 +990,7 @@
 		newcsum += le32_to_cpu(*isuper++);
 
 	if (size == 2)
-		newcsum += le16_to_cpu(*(unsigned short*) isuper);
+		newcsum += le16_to_cpu(*(__le16*) isuper);
 
 	csum = (newcsum & 0xffffffff) + (newcsum >> 32);
 	sb->sb_csum = disk_csum;
@@ -1106,7 +1107,7 @@
 	if (le32_to_cpu(sb->chunksize))
 		rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1);
 
-	if (le32_to_cpu(sb->size) > rdev->size*2)
+	if (le64_to_cpu(sb->size) > rdev->size*2)
 		return -EINVAL;
 	return ret;
 }
@@ -1228,7 +1229,7 @@
 	else
 		sb->resync_offset = cpu_to_le64(0);
 
-	sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors);
+	sb->cnt_corrected_read = cpu_to_le32(atomic_read(&rdev->corrected_errors));
 
 	sb->raid_disks = cpu_to_le32(mddev->raid_disks);
 	sb->size = cpu_to_le64(mddev->size<<1);
@@ -3849,6 +3850,7 @@
 	}
 	clear_bit(In_sync, &rdev->flags);
 	rdev->desc_nr = -1;
+	rdev->saved_raid_disk = -1;
 	err = bind_rdev_to_array(rdev, mddev);
 	if (err)
 		goto abort_export;
@@ -4911,6 +4913,7 @@
 }
 
 static struct file_operations md_seq_fops = {
+	.owner		= THIS_MODULE,
 	.open           = md_seq_open,
 	.read           = seq_read,
 	.llseek         = seq_lseek,
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 171ff41..a6260f0 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -501,7 +501,7 @@
 			mdname(mddev));
 		goto out_free_conf;
 	}
-	mddev->degraded = conf->raid_disks = conf->working_disks;
+	mddev->degraded = conf->raid_disks - conf->working_disks;
 
 	conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS,
 						 sizeof(struct multipath_bh));
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1250f0e..74f17a9 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -2079,7 +2079,7 @@
 		disk = conf->mirrors + i;
 
 		if (!disk->rdev ||
-		    !test_bit(In_sync, &rdev->flags)) {
+		    !test_bit(In_sync, &disk->rdev->flags)) {
 			disk->head_position = 0;
 			mddev->degraded++;
 		}
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index b88451e..86cbdbc 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -230,7 +230,7 @@
 
 /********************************************************************************/
 /* interrupt handler */
-static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t interrupt_hw(int irq, void *dev_id)
 {
 	struct saa7146_dev *dev = dev_id;
 	u32 isr = 0;
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index eb2e643..0689324 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -122,7 +122,7 @@
 /* When PID filtering is turned on, we use the timer IRQ, because small amounts
  * of data need to be passed to the user space instantly as well. When PID
  * filtering is turned off, we use the page-change-IRQ */
-static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
 {
 	struct flexcop_pci *fc_pci = dev_id;
 	struct flexcop_device *fc = fc_pci->fc_dev;
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 515954f..2853ea1 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -328,7 +328,7 @@
 	fc_usb->tmp_buffer_length = l;
 }
 
-static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+static void flexcop_usb_urb_complete(struct urb *urb)
 {
 	struct flexcop_usb *fc_usb = urb->context;
 	int i;
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 755822e..329a51c 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -266,7 +266,7 @@
 /* Interrupt service routine */
 /*****************************/
 
-static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bt878_irq(int irq, void *dev_id)
 {
 	u32 stat, astat, mask;
 	int count;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index fb6c4cc..14e69a7 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -665,6 +665,10 @@
 	case BTTV_BOARD_TWINHAN_DST:
 		/*	DST is not a frontend driver !!!		*/
 		state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+		if (!state) {
+			printk("dvb_bt8xx: No memory\n");
+			break;
+		}
 		/*	Setup the Card					*/
 		state->config = &dst_config;
 		state->i2c = card->i2c_adapter;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 410fa6d..ff7d4f5 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -238,7 +238,7 @@
 	cinergyt2->sleeping = sleep;
 }
 
-static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs);
+static void cinergyt2_stream_irq (struct urb *urb);
 
 static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb)
 {
@@ -258,7 +258,7 @@
 	return err;
 }
 
-static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs)
+static void cinergyt2_stream_irq (struct urb *urb)
 {
 	struct cinergyt2 *cinergyt2 = urb->context;
 
diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig
index e46eae3..1990eda 100644
--- a/drivers/media/dvb/dvb-core/Kconfig
+++ b/drivers/media/dvb/dvb-core/Kconfig
@@ -19,6 +19,6 @@
 	  allow the card drivers to only load the frontend modules
 	  they require. This saves several KBytes of memory.
 
-	  Note: You will need moudule-init-tools v3.2 or later for this feature.
+	  Note: You will need module-init-tools v3.2 or later for this feature.
 
 	  If unsure say Y.
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index fd3a990..5143e42 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -169,7 +169,7 @@
 // Config Adjacent channels  Perf -cal22
 static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
 	.band_caps = BAND_VHF | BAND_UHF,
-	.setup     = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
+	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
 
 	.agc1_max = 48497,
 	.agc1_min = 23593,
@@ -196,10 +196,14 @@
 	.ln_adc_level = 0x1cc7,
 
 	.output_mpeg2_in_188_bytes = 1,
+
+	.agc_command1 = 1,
+	.agc_command2 = 1,
 };
 
 static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
-	.setup    = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
+	.band_caps = BAND_VHF | BAND_UHF,
+	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
 
 	.agc1_max = 56361,
 	.agc1_min = 22282,
@@ -226,6 +230,9 @@
 	.ln_adc_level = 0x1cc7,
 
 	.output_mpeg2_in_188_bytes = 1,
+
+	.agc_command1 = 1,
+	.agc_command2 = 1,
 };
 
 int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
index 5153fb9..b607810 100644
--- a/drivers/media/dvb/dvb-usb/dibusb.h
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -99,7 +99,9 @@
 struct dibusb_state {
 	struct dib_fe_xfer_ops ops;
 	int mt2060_present;
+};
 
+struct dibusb_device_state {
 	/* for RC5 remote control */
 	int old_toggle;
 	int last_repeat_count;
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index a9219bf..a58874c 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -75,7 +75,7 @@
 	u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
 	u16 raw;
 	int i;
-	struct dibusb_state *st = d->priv;
+	struct dibusb_device_state *st = d->priv;
 
 	dvb_usb_generic_rw(d,cmd,2,key,5,0);
 
@@ -184,6 +184,7 @@
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
+	.size_of_priv     = sizeof(struct dibusb_device_state),
 
 	.power_ctrl       = dibusb2_0_power_ctrl,
 	.read_mac_address = nova_t_read_mac_address,
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c
index 572b2d9..78035ee 100644
--- a/drivers/media/dvb/dvb-usb/usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/usb-urb.c
@@ -11,7 +11,7 @@
 #include "dvb-usb-common.h"
 
 /* URB stuff for streaming */
-static void usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+static void usb_urb_complete(struct urb *urb)
 {
 	struct usb_data_stream *stream = urb->context;
 	int ptype = usb_pipetype(urb->pipe);
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index ccc813b..3561a77 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -345,7 +345,7 @@
 
 	/* agc */
 	dib3000mc_write_word(state, 36, state->cfg->max_time);
-	dib3000mc_write_word(state, 37, agc->setup);
+	dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
 	dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
 	dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
 
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
index b198cd5..0d6fdef 100644
--- a/drivers/media/dvb/frontends/dib3000mc.h
+++ b/drivers/media/dvb/frontends/dib3000mc.h
@@ -28,6 +28,9 @@
 	u16 max_time;
 	u16 ln_adc_level;
 
+	u8 agc_command1 :1;
+	u8 agc_command2 :1;
+
 	u8 mobile_mode;
 
 	u8 output_mpeg2_in_188_bytes;
diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
index e8061db..18457ad 100644
--- a/drivers/media/dvb/frontends/tda10086.h
+++ b/drivers/media/dvb/frontends/tda10086.h
@@ -35,7 +35,16 @@
 	u8 invert;
 };
 
+#if defined(CONFIG_DVB_TDA10086) || defined(CONFIG_DVB_TDA10086_MODULE)
 extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
 					    struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+						   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA10086
 
 #endif // TDA10086_H
diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h
index 3307607..83998c0 100644
--- a/drivers/media/dvb/frontends/tda826x.h
+++ b/drivers/media/dvb/frontends/tda826x.h
@@ -35,6 +35,19 @@
  * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector.
  * @return FE pointer on success, NULL on failure.
  */
-extern struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough);
+#if defined(CONFIG_DVB_TDA826X) || defined(CONFIG_DVB_TDA826X_MODULE)
+extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr,
+					   struct i2c_adapter *i2c,
+					   int has_loopthrough);
+#else
+static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
+						  int addr,
+						  struct i2c_adapter *i2c,
+						  int has_loopthrough)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA826X
 
-#endif
+#endif // __DVB_TDA826X_H__
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 2310b2b..8e4ce10 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -306,7 +306,7 @@
 			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
 }
 
-static irqreturn_t pluto_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pluto_irq(int irq, void *dev_id)
 {
 	struct pluto *pluto = dev_id;
 	u32 tscr;
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 2341998..60820de 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -732,7 +732,7 @@
 	}
 }
 
-static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
+static void ttusb_iso_irq(struct urb *urb)
 {
 	struct ttusb *ttusb = urb->context;
 
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index de077a7..a1c9fa9 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -203,7 +203,7 @@
 static void ttusb_dec_set_model(struct ttusb_dec *dec,
 				enum ttusb_dec_model model);
 
-static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
+static void ttusb_dec_handle_irq( struct urb *urb)
 {
 	struct ttusb_dec * dec = urb->context;
 	char *buffer = dec->irq_buffer;
@@ -755,7 +755,7 @@
 	}
 }
 
-static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
+static void ttusb_dec_process_urb(struct urb *urb)
 {
 	struct ttusb_dec *dec = urb->context;
 
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index afb734d..fbe5b61 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -677,6 +677,8 @@
 menu "V4L USB devices"
 	depends on USB && VIDEO_DEV
 
+source "drivers/media/video/pvrusb2/Kconfig"
+
 source "drivers/media/video/em28xx/Kconfig"
 
 source "drivers/media/video/usbvideo/Kconfig"
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 5c5e682..4861799 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -549,7 +549,7 @@
 /*
  * Interrupt handler
  */
-static void ar_interrupt(int irq, void *dev, struct pt_regs *regs)
+static void ar_interrupt(int irq, void *dev)
 {
 	struct ar_device *ar = dev;
 	unsigned int line_count;
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 50dde82..6e1ddad 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3753,7 +3753,7 @@
 	spin_unlock(&btv->s_lock);
 }
 
-static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t bttv_irq(int irq, void *dev_id)
 {
 	u32 stat,astat;
 	u32 dstat;
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
index f4da029..28dc6a1 100644
--- a/drivers/media/video/cpia2/cpia2_usb.c
+++ b/drivers/media/video/cpia2/cpia2_usb.c
@@ -49,7 +49,7 @@
 #define FRAME_SIZE_PER_DESC   frame_sizes[cam->cur_alt]
 
 static void process_frame(struct camera_data *cam);
-static void cpia2_usb_complete(struct urb *urb, struct pt_regs *);
+static void cpia2_usb_complete(struct urb *urb);
 static int cpia2_usb_probe(struct usb_interface *intf,
 			   const struct usb_device_id *id);
 static void cpia2_usb_disconnect(struct usb_interface *intf);
@@ -199,7 +199,7 @@
  *
  *  callback when incoming packet is received
  *****************************************************************************/
-static void cpia2_usb_complete(struct urb *urb, struct pt_regs *regs)
+static void cpia2_usb_complete(struct urb *urb)
 {
 	int i;
 	unsigned char *cdata;
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 2ee34a3..9da4726 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -109,7 +109,7 @@
 static LIST_HEAD(cam_list);
 static spinlock_t cam_list_lock_usb;
 
-static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
+static void cpia_usb_complete(struct urb *urb)
 {
 	int i;
 	char *cdata;
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 48014a2..f85f208 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -235,6 +235,7 @@
 			0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
 			0, 0, 0, 0
 		};
+		int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
 		int i;
 
 		fmt = arg;
@@ -246,13 +247,25 @@
 		if ((cx25840_read(client, 0x404) & 0x10) == 0)
 			break;
 
-		for (i = 7; i <= 23; i++) {
-			u8 v = cx25840_read(client, 0x424 + i - 7);
+		if (is_pal) {
+			for (i = 7; i <= 23; i++) {
+				u8 v = cx25840_read(client, 0x424 + i - 7);
 
-			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-			svbi->service_set |=
-				 svbi->service_lines[0][i] | svbi->service_lines[1][i];
+				svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+				svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+				svbi->service_set |=
+					svbi->service_lines[0][i] | svbi->service_lines[1][i];
+			}
+		}
+		else {
+			for (i = 10; i <= 21; i++) {
+				u8 v = cx25840_read(client, 0x424 + i - 10);
+
+				svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+				svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+				svbi->service_set |=
+					svbi->service_lines[0][i] | svbi->service_lines[1][i];
+			}
 		}
 		break;
 	}
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index f034066..e4355fd 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -262,7 +262,7 @@
 /*
  * BOARD Specific: Handles IRQ calls
  */
-static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cx8801_irq(int irq, void *dev_id)
 {
 	snd_cx88_card_t *chip = dev_id;
 	struct cx88_core *core = chip->core;
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index af71d42..f764a57 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1230,6 +1230,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x84bf,
 		}},
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_NORWOOD_MICRO] = {
 		.name           = "Norwood Micro TV Tuner",
@@ -1590,6 +1591,18 @@
 		.subvendor = 0x0070,
 		.subdevice = 0x9000,
 		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1400,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1401,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1402,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
 	},
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -1633,7 +1646,15 @@
 	/* Make sure we support the board model */
 	switch (tv.model)
 	{
+	case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
+	case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
+	case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
+	case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */
+	case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */
+	case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */
 	case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
+	case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */
+	case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
 	case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
 	case 34519: /* WinTV-PCI-FM */
 	case 90002: /* Nova-T-PCI (9002) */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index bd0c879..0ef13e7 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -315,15 +315,22 @@
 	.demod_address = 0x43,
 	.output_mode   = CX22702_SERIAL_OUTPUT,
 };
+
 static struct cx22702_config hauppauge_hvr1100_config = {
 	.demod_address = 0x63,
 	.output_mode   = CX22702_SERIAL_OUTPUT,
 };
+
 static struct cx22702_config hauppauge_hvr1300_config = {
 	.demod_address = 0x63,
 	.output_mode   = CX22702_SERIAL_OUTPUT,
 };
 
+static struct cx22702_config hauppauge_hvr3000_config = {
+	.demod_address = 0x63,
+	.output_mode = CX22702_SERIAL_OUTPUT,
+};
+
 static int or51132_set_ts_param(struct dvb_frontend* fe,
 				int is_punctured)
 {
@@ -558,6 +565,16 @@
 				   &dvb_pll_fmd1216me);
 		}
 		break;
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+		dev->dvb.frontend = dvb_attach(cx22702_attach,
+					       &hauppauge_hvr3000_config,
+					       &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+				   &dev->core->i2c_adap,
+				   &dvb_pll_fmd1216me);
+		}
+		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
 		dev->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv,
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 83ebf7a..ee48995 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -196,6 +196,7 @@
 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
 	case CX88_BOARD_HAUPPAUGE_HVR1100:
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
 		ir_codes = ir_codes_hauppauge_new;
 		ir_type = IR_TYPE_RC5;
 		ir->sampling = 1;
@@ -419,6 +420,7 @@
 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
 	case CX88_BOARD_HAUPPAUGE_HVR1100:
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
 		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
 		ir_dprintk("biphase decoded: %x\n", ircode);
 		if ((ircode & 0xfffff000) != 0x3000)
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index d6d9807..6b23a4e 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -376,7 +376,7 @@
 
 #define MAX_IRQ_LOOP 10
 
-static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cx8802_irq(int irq, void *dev_id)
 {
 	struct cx8802_dev *dev = dev_id;
 	struct cx88_core *core = dev->core;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index cb0c0ee..90e298d 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1744,7 +1744,7 @@
 	}
 }
 
-static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cx8800_irq(int irq, void *dev_id)
 {
 	struct cx8800_dev *dev = dev_id;
 	struct cx88_core *core = dev->core;
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index b9ba95f..b1012e9 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -166,7 +166,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-static void dabusb_iso_complete (struct urb *purb, struct pt_regs *regs)
+static void dabusb_iso_complete (struct urb *purb)
 {
 	pbuff_t b = purb->context;
 	pdabusb_t s = b->s;
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 4350cc7..255a47d 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -382,7 +382,7 @@
 /******************* isoc transfer handling ****************************/
 
 #ifdef ENABLE_DEBUG_ISOC_FRAMES
-static void em28xx_isoc_dump(struct urb *urb, struct pt_regs *regs)
+static void em28xx_isoc_dump(struct urb *urb)
 {
 	int len = 0;
 	int ntrans = 0;
@@ -534,7 +534,7 @@
  * em28xx_isoIrq()
  * handles the incoming isoc urbs and fills the frames from our inqueue
  */
-static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
+static void em28xx_isocIrq(struct urb *urb)
 {
 	struct em28xx *dev = urb->context;
 	int i, status;
@@ -545,7 +545,7 @@
 		return;
 #ifdef ENABLE_DEBUG_ISOC_FRAMES
 	if (isoc_debug>1)
-		em28xx_isoc_dump(urb, regs);
+		em28xx_isoc_dump(urb);
 #endif
 
 	if (urb->status == -ENOENT)
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 20df657..2a461dde4 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -174,7 +174,7 @@
 
 	route.input = INPUT(dev->ctl_input)->vmux;
 	route.output = 0;
-	em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, 0);
+	em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
 	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 	em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
 
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 8992b6e..f786ab1 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -398,7 +398,7 @@
 
 /*****************************************************************************/
 
-static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
+static void et61x251_urb_complete(struct urb *urb)
 {
 	struct et61x251_device* cam = urb->context;
 	struct et61x251_frame_t** f;
@@ -973,16 +973,32 @@
 			 et61x251_show_i2c_val, et61x251_store_i2c_val);
 
 
-static void et61x251_create_sysfs(struct et61x251_device* cam)
+static int et61x251_create_sysfs(struct et61x251_device* cam)
 {
 	struct video_device *v4ldev = cam->v4ldev;
+	int rc;
 
-	video_device_create_file(v4ldev, &class_device_attr_reg);
-	video_device_create_file(v4ldev, &class_device_attr_val);
+	rc = video_device_create_file(v4ldev, &class_device_attr_reg);
+	if (rc) goto err;
+	rc = video_device_create_file(v4ldev, &class_device_attr_val);
+	if (rc) goto err_reg;
 	if (cam->sensor.sysfs_ops) {
-		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-		video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+		if (rc) goto err_val;
+		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+		if (rc) goto err_i2c_reg;
 	}
+
+	return 0;
+
+err_i2c_reg:
+	video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
+err_val:
+	video_device_remove_file(v4ldev, &class_device_attr_val);
+err_reg:
+	video_device_remove_file(v4ldev, &class_device_attr_reg);
+err:
+	return rc;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -2534,7 +2550,9 @@
 	dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	et61x251_create_sysfs(cam);
+	err = et61x251_create_sysfs(cam);
+	if (err)
+		goto fail2;
 	DBG(2, "Optional device control through 'sysfs' interface ready");
 #endif
 
@@ -2544,6 +2562,13 @@
 
 	return 0;
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+fail2:
+	video_nr[dev_nr] = -1;
+	dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+	mutex_unlock(&cam->dev_mutex);
+	video_unregister_device(cam->v4ldev);
+#endif
 fail:
 	if (cam) {
 		kfree(cam->control_buffer);
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index e278753..b083338 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -786,7 +786,7 @@
 /* Interrupt handling                                                       */
 /****************************************************************************/
 
-static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t meye_irq(int irq, void *dev_id)
 {
 	u32 v;
 	int reqnr;
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 5d8cd28..b4db2cb 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -3503,7 +3503,7 @@
 }
 
 static void
-ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs)
+ov51x_isoc_irq(struct urb *urb)
 {
 	int i;
 	struct usb_ov511 *ov;
@@ -5648,17 +5648,49 @@
 }
 static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
 
-static void ov_create_sysfs(struct video_device *vdev)
+static int ov_create_sysfs(struct video_device *vdev)
 {
-	video_device_create_file(vdev, &class_device_attr_custom_id);
-	video_device_create_file(vdev, &class_device_attr_model);
-	video_device_create_file(vdev, &class_device_attr_bridge);
-	video_device_create_file(vdev, &class_device_attr_sensor);
-	video_device_create_file(vdev, &class_device_attr_brightness);
-	video_device_create_file(vdev, &class_device_attr_saturation);
-	video_device_create_file(vdev, &class_device_attr_contrast);
-	video_device_create_file(vdev, &class_device_attr_hue);
-	video_device_create_file(vdev, &class_device_attr_exposure);
+	int rc;
+
+	rc = video_device_create_file(vdev, &class_device_attr_custom_id);
+	if (rc) goto err;
+	rc = video_device_create_file(vdev, &class_device_attr_model);
+	if (rc) goto err_id;
+	rc = video_device_create_file(vdev, &class_device_attr_bridge);
+	if (rc) goto err_model;
+	rc = video_device_create_file(vdev, &class_device_attr_sensor);
+	if (rc) goto err_bridge;
+	rc = video_device_create_file(vdev, &class_device_attr_brightness);
+	if (rc) goto err_sensor;
+	rc = video_device_create_file(vdev, &class_device_attr_saturation);
+	if (rc) goto err_bright;
+	rc = video_device_create_file(vdev, &class_device_attr_contrast);
+	if (rc) goto err_sat;
+	rc = video_device_create_file(vdev, &class_device_attr_hue);
+	if (rc) goto err_contrast;
+	rc = video_device_create_file(vdev, &class_device_attr_exposure);
+	if (rc) goto err_hue;
+
+	return 0;
+
+err_hue:
+	video_device_remove_file(vdev, &class_device_attr_hue);
+err_contrast:
+	video_device_remove_file(vdev, &class_device_attr_contrast);
+err_sat:
+	video_device_remove_file(vdev, &class_device_attr_saturation);
+err_bright:
+	video_device_remove_file(vdev, &class_device_attr_brightness);
+err_sensor:
+	video_device_remove_file(vdev, &class_device_attr_sensor);
+err_bridge:
+	video_device_remove_file(vdev, &class_device_attr_bridge);
+err_model:
+	video_device_remove_file(vdev, &class_device_attr_model);
+err_id:
+	video_device_remove_file(vdev, &class_device_attr_custom_id);
+err:
+	return rc;
 }
 
 /****************************************************************************
@@ -5817,7 +5849,11 @@
 	     ov->vdev->minor);
 
 	usb_set_intfdata(intf, ov);
-	ov_create_sysfs(ov->vdev);
+	if (ov_create_sysfs(ov->vdev)) {
+		err("ov_create_sysfs failed");
+		goto error;
+	}
+
 	return 0;
 
 error:
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 3484e36..368d6e2 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -91,7 +91,7 @@
 static int planb_ioctl(struct video_device *, unsigned int, void *);
 static int planb_init_done(struct video_device *);
 static int planb_mmap(struct video_device *, const char *, unsigned long);
-static void planb_irq(int, void *, struct pt_regs *);
+static void planb_irq(int, void *);
 static void release_planb(void);
 int init_planbs(struct video_init *);
 
@@ -1316,7 +1316,7 @@
 	return c1;
 }
 
-static void planb_irq(int irq, void *dev_id, struct pt_regs * regs)
+static void planb_irq(int irq, void *dev_id)
 {
 	unsigned int stat, astat;
 	struct planb *pb = (struct planb *)dev_id;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 3d8cd0d..f920e0c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -2552,7 +2552,7 @@
 }
 
 
-static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
+static void pvr2_ctl_write_complete(struct urb *urb)
 {
 	struct pvr2_hdw *hdw = urb->context;
 	hdw->ctl_write_pend_flag = 0;
@@ -2561,7 +2561,7 @@
 }
 
 
-static void pvr2_ctl_read_complete(struct urb *urb, struct pt_regs *regs)
+static void pvr2_ctl_read_complete(struct urb *urb)
 {
 	struct pvr2_hdw *hdw = urb->context;
 	hdw->ctl_read_pend_flag = 0;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 1e39376..70aa63e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -429,7 +429,7 @@
 	} while (0); mutex_unlock(&sp->mutex);
 }
 
-static void buffer_complete(struct urb *urb, struct pt_regs *regs)
+static void buffer_complete(struct urb *urb)
 {
 	struct pvr2_buffer *bp = urb->context;
 	struct pvr2_stream *sp;
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 53c4b57..46c1148 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -682,7 +682,7 @@
 /* This gets called for the Isochronous pipe (video). This is done in
  * interrupt time, so it has to be fast, not crash, and not stall. Neat.
  */
-static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
+static void pwc_isoc_handler(struct urb *urb)
 {
 	struct pwc_device *pdev;
 	int i, fst, flen;
@@ -1024,12 +1024,25 @@
 static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
 			 NULL);
 
-static void pwc_create_sysfs_files(struct video_device *vdev)
+static int pwc_create_sysfs_files(struct video_device *vdev)
 {
 	struct pwc_device *pdev = video_get_drvdata(vdev);
-	if (pdev->features & FEATURE_MOTOR_PANTILT)
-		video_device_create_file(vdev, &class_device_attr_pan_tilt);
-	video_device_create_file(vdev, &class_device_attr_button);
+	int rc;
+
+	rc = video_device_create_file(vdev, &class_device_attr_button);
+	if (rc)
+		goto err;
+	if (pdev->features & FEATURE_MOTOR_PANTILT) {
+		rc = video_device_create_file(vdev,&class_device_attr_pan_tilt);
+		if (rc) goto err_button;
+	}
+
+	return 0;
+
+err_button:
+	video_device_remove_file(vdev, &class_device_attr_button);
+err:
+	return rc;
 }
 
 static void pwc_remove_sysfs_files(struct video_device *vdev)
@@ -1408,7 +1421,7 @@
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct pwc_device *pdev = NULL;
 	int vendor_id, product_id, type_id;
-	int i, hint;
+	int i, hint, rc;
 	int features = 0;
 	int video_nr = -1; /* default: use next available device */
 	char serial_number[30], *name;
@@ -1709,9 +1722,8 @@
 	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
 	if (i < 0) {
 		PWC_ERROR("Failed to register as video device (%d).\n", i);
-		video_device_release(pdev->vdev); /* Drip... drip... drip... */
-		kfree(pdev); /* Oops, no memory leaks please */
-		return -EIO;
+		rc = i;
+		goto err;
 	}
 	else {
 		PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
@@ -1723,13 +1735,24 @@
 
 	PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
 	usb_set_intfdata (intf, pdev);
-	pwc_create_sysfs_files(pdev->vdev);
+	rc = pwc_create_sysfs_files(pdev->vdev);
+	if (rc)
+		goto err_unreg;
 
 	/* Set the leds off */
 	pwc_set_leds(pdev, 0, 0);
 	pwc_camera_power(pdev, 0);
 
 	return 0;
+
+err_unreg:
+	if (hint < MAX_DEV_HINTS)
+		device_hint[hint].pdev = NULL;
+	video_unregister_device(pdev->vdev);
+err:
+	video_device_release(pdev->vdev); /* Drip... drip... drip... */
+	kfree(pdev); /* Oops, no memory leaks please */
+	return rc;
 }
 
 /* The user janked out the cable... */
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 974179d..c5719f7 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -960,6 +960,8 @@
 			reg |= 0x10;
 		} else if (std == V4L2_STD_NTSC_M_JP) {
 			reg |= 0x40;
+		} else if (std == V4L2_STD_SECAM) {
+			reg |= 0x50;
 		}
 		saa711x_write(client, R_0E_CHROMA_CNTL_1, reg);
 	} else {
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index a39e013..4abf5c0 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -212,7 +212,7 @@
  *
  */
 
-static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id)
 {
 	struct saa7134_dmasound *dmasound = dev_id;
 	struct saa7134_dev *dev = dmasound->priv_data;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 09aa62f..5c9e63d 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -495,7 +495,7 @@
 	printk("\n");
 }
 
-static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t saa7134_irq(int irq, void *dev_id)
 {
 	struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
 	unsigned long report,status;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 2e3ba5f..bfcb860 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -814,7 +814,7 @@
 
 /* ------------------------------------------------------------------ */
 
-static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t saa7134_oss_irq(int irq, void *dev_id)
 {
 	struct saa7134_dmasound *dmasound = dev_id;
 	struct saa7134_dev *dev = dmasound->priv_data;
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 203302f..830617e 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -2248,7 +2248,11 @@
 		t->type = V4L2_TUNER_RADIO;
 
 		saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
-
+		if (dev->input->amux == TV) {
+			t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11);
+			t->rxsubchans = (saa_readb(0x529) & 0x08) ?
+					V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
+		}
 		return 0;
 	}
 	case VIDIOC_S_TUNER:
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index 67987ba..7aeec57 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -282,7 +282,7 @@
 }
 
 /* irq handler for snapshot button */
-static void se401_button_irq(struct urb *urb, struct pt_regs *regs)
+static void se401_button_irq(struct urb *urb)
 {
 	struct usb_se401 *se401 = urb->context;
 	int status;
@@ -318,7 +318,7 @@
 		     __FUNCTION__, status);
 }
 
-static void se401_video_irq(struct urb *urb, struct pt_regs *regs)
+static void se401_video_irq(struct urb *urb)
 {
 	struct usb_se401 *se401 = urb->context;
 	int length = urb->actual_length;
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 48d138a..a4702d3 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -518,7 +518,7 @@
 }
 
 
-static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
+static void sn9c102_urb_complete(struct urb *urb)
 {
 	struct sn9c102_device* cam = urb->context;
 	struct sn9c102_frame_t** f;
@@ -1240,23 +1240,53 @@
 			 sn9c102_show_frame_header, NULL);
 
 
-static void sn9c102_create_sysfs(struct sn9c102_device* cam)
+static int sn9c102_create_sysfs(struct sn9c102_device* cam)
 {
 	struct video_device *v4ldev = cam->v4ldev;
+	int rc;
 
-	video_device_create_file(v4ldev, &class_device_attr_reg);
-	video_device_create_file(v4ldev, &class_device_attr_val);
-	video_device_create_file(v4ldev, &class_device_attr_frame_header);
-	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-		video_device_create_file(v4ldev, &class_device_attr_green);
-	else if (cam->bridge == BRIDGE_SN9C103) {
-		video_device_create_file(v4ldev, &class_device_attr_blue);
-		video_device_create_file(v4ldev, &class_device_attr_red);
-	}
+	rc = video_device_create_file(v4ldev, &class_device_attr_reg);
+	if (rc) goto err;
+	rc = video_device_create_file(v4ldev, &class_device_attr_val);
+	if (rc) goto err_reg;
+	rc = video_device_create_file(v4ldev, &class_device_attr_frame_header);
+	if (rc) goto err_val;
+
 	if (cam->sensor.sysfs_ops) {
-		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-		video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+		if (rc) goto err_frhead;
+		rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+		if (rc) goto err_i2c_reg;
 	}
+
+	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
+		rc = video_device_create_file(v4ldev, &class_device_attr_green);
+		if (rc) goto err_i2c_val;
+	} else if (cam->bridge == BRIDGE_SN9C103) {
+		rc = video_device_create_file(v4ldev, &class_device_attr_blue);
+		if (rc) goto err_i2c_val;
+		rc = video_device_create_file(v4ldev, &class_device_attr_red);
+		if (rc) goto err_blue;
+	}
+
+	return 0;
+
+err_blue:
+	video_device_remove_file(v4ldev, &class_device_attr_blue);
+err_i2c_val:
+	if (cam->sensor.sysfs_ops)
+		video_device_remove_file(v4ldev, &class_device_attr_i2c_val);
+err_i2c_reg:
+	if (cam->sensor.sysfs_ops)
+		video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
+err_frhead:
+	video_device_remove_file(v4ldev, &class_device_attr_frame_header);
+err_val:
+	video_device_remove_file(v4ldev, &class_device_attr_val);
+err_reg:
+	video_device_remove_file(v4ldev, &class_device_attr_reg);
+err:
+	return rc;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -2809,10 +2839,7 @@
 		DBG(1, "V4L2 device registration failed");
 		if (err == -ENFILE && video_nr[dev_nr] == -1)
 			DBG(1, "Free /dev/videoX node not found");
-		video_nr[dev_nr] = -1;
-		dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-		mutex_unlock(&cam->dev_mutex);
-		goto fail;
+		goto fail2;
 	}
 
 	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
@@ -2823,7 +2850,9 @@
 	dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	sn9c102_create_sysfs(cam);
+	err = sn9c102_create_sysfs(cam);
+	if (err)
+		goto fail3;
 	DBG(2, "Optional device control through 'sysfs' interface ready");
 #endif
 
@@ -2833,6 +2862,14 @@
 
 	return 0;
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+fail3:
+	video_unregister_device(cam->v4ldev);
+#endif
+fail2:
+	video_nr[dev_nr] = -1;
+	dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+	mutex_unlock(&cam->dev_mutex);
 fail:
 	if (cam) {
 		kfree(cam->control_buffer);
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 5686547..525d812 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -406,7 +406,7 @@
 	}
 }
 
-static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t saa7146_irq(int irq, void *dev_id)
 {
 	struct saa7146 *saa = dev_id;
 	u32 stat, astat;
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 2ba2991..6d1ef1e 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -516,16 +516,45 @@
 stv680_file(packets_dropped, dropped, "%d\n");
 stv680_file(decoding_errors, error, "%d\n");
 
-static void stv680_create_sysfs_files(struct video_device *vdev)
+static int stv680_create_sysfs_files(struct video_device *vdev)
 {
-	video_device_create_file(vdev, &class_device_attr_model);
-	video_device_create_file(vdev, &class_device_attr_in_use);
-	video_device_create_file(vdev, &class_device_attr_streaming);
-	video_device_create_file(vdev, &class_device_attr_palette);
-	video_device_create_file(vdev, &class_device_attr_frames_total);
-	video_device_create_file(vdev, &class_device_attr_frames_read);
-	video_device_create_file(vdev, &class_device_attr_packets_dropped);
-	video_device_create_file(vdev, &class_device_attr_decoding_errors);
+	int rc;
+
+	rc = video_device_create_file(vdev, &class_device_attr_model);
+	if (rc) goto err;
+	rc = video_device_create_file(vdev, &class_device_attr_in_use);
+	if (rc) goto err_model;
+	rc = video_device_create_file(vdev, &class_device_attr_streaming);
+	if (rc) goto err_inuse;
+	rc = video_device_create_file(vdev, &class_device_attr_palette);
+	if (rc) goto err_stream;
+	rc = video_device_create_file(vdev, &class_device_attr_frames_total);
+	if (rc) goto err_pal;
+	rc = video_device_create_file(vdev, &class_device_attr_frames_read);
+	if (rc) goto err_framtot;
+	rc = video_device_create_file(vdev, &class_device_attr_packets_dropped);
+	if (rc) goto err_framread;
+	rc = video_device_create_file(vdev, &class_device_attr_decoding_errors);
+	if (rc) goto err_dropped;
+
+	return 0;
+
+err_dropped:
+	video_device_remove_file(vdev, &class_device_attr_packets_dropped);
+err_framread:
+	video_device_remove_file(vdev, &class_device_attr_frames_read);
+err_framtot:
+	video_device_remove_file(vdev, &class_device_attr_frames_total);
+err_pal:
+	video_device_remove_file(vdev, &class_device_attr_palette);
+err_stream:
+	video_device_remove_file(vdev, &class_device_attr_streaming);
+err_inuse:
+	video_device_remove_file(vdev, &class_device_attr_in_use);
+err_model:
+	video_device_remove_file(vdev, &class_device_attr_model);
+err:
+	return rc;
 }
 
 static void stv680_remove_sysfs_files(struct video_device *vdev)
@@ -582,7 +611,7 @@
 	return 0;
 }
 
-static void stv680_video_irq (struct urb *urb, struct pt_regs *regs)
+static void stv680_video_irq (struct urb *urb)
 {
 	struct usb_stv *stv680 = urb->context;
 	int length = urb->actual_length;
@@ -1418,9 +1447,13 @@
 	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor);
 
 	usb_set_intfdata (intf, stv680);
-	stv680_create_sysfs_files(stv680->vdev);
+	retval = stv680_create_sysfs_files(stv680->vdev);
+	if (retval)
+		goto error_unreg;
 	return 0;
 
+error_unreg:
+	video_unregister_device(stv680->vdev);
 error_vdev:
 	video_device_release(stv680->vdev);
 error:
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index 8fff642..7816823 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -1046,7 +1046,6 @@
 		.type   = TUNER_PARAM_TYPE_NTSC,
 		.ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
 		.count  = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
-		.has_tda9887 = 1,
 	},
 };
 
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index 4eee8be..abe2146 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -387,7 +387,7 @@
 }
 
 
-static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs)
+static void konicawc_isoc_irq(struct urb *urb)
 {
 	struct uvd *uvd = urb->context;
 	struct konicawc *cam = (struct konicawc *)uvd->user_data;
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index 56e01b6..9a26b94 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -125,7 +125,7 @@
 	}
 }
 
-static void qcm_int_irq(struct urb *urb, struct pt_regs *regs)
+static void qcm_int_irq(struct urb *urb)
 {
 	int ret;
 	struct uvd *uvd = urb->context;
@@ -606,7 +606,7 @@
 		err("usb_submit_urb error (%d)", ret);
 }
 
-static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs)
+static void qcm_isoc_irq(struct urb *urb)
 {
 	int len;
 	struct uvd *uvd = urb->context;
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 13b37c8..d8b8802 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -1680,7 +1680,7 @@
 	return totlen;
 }
 
-static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs)
+static void usbvideo_IsocIrq(struct urb *urb)
 {
 	int i, ret, len;
 	struct uvd *uvd = urb->context;
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 479a067..d424a41 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -17,10 +17,11 @@
  */
 
 #define dbgarg(cmd, fmt, arg...) \
-		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)			\
+		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {		\
 			printk (KERN_DEBUG "%s: ",  vfd->name);		\
 			v4l_printk_ioctl(cmd);				\
-			printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+			printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
+		}
 
 #define dbgarg2(fmt, arg...) \
 		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)			\
@@ -1287,6 +1288,7 @@
 			ret=vfd->vidioc_g_parm(file, fh, p);
 		} else {
 			struct v4l2_standard s;
+			int i;
 
 			if (!vfd->tvnormsize) {
 				printk (KERN_WARNING "%s: no TV norms defined!\n",
@@ -1297,8 +1299,14 @@
 			if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 				return -EINVAL;
 
-			v4l2_video_std_construct(&s, vfd->tvnorms[vfd->current_norm].id,
-						 vfd->tvnorms[vfd->current_norm].name);
+			for (i = 0; i < vfd->tvnormsize; i++)
+				if (vfd->tvnorms[i].id == vfd->current_norm)
+					break;
+			if (i >= vfd->tvnormsize)
+				return -EINVAL;
+
+			v4l2_video_std_construct(&s, vfd->current_norm,
+						 vfd->tvnorms[i].name);
 
 			memset(p,0,sizeof(*p));
 
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index d1e04f7..6b6dff4 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -2325,7 +2325,7 @@
 	}
 }
 
-static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t vino_interrupt(int irq, void *dev_id)
 {
 	u32 ctrl, intr;
 	unsigned int fc_a, fc_b;
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index e7c01d5..3c8dc72 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -272,7 +272,7 @@
 
 	/* Get first addr pointed to pixel position */
 	oldpg=get_addr_pos(pos,pages,to_addr);
-	pg=pfn_to_page(to_addr[oldpg].sg->dma_address >> PAGE_SHIFT);
+	pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT);
 	basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
 
 	/* We will just duplicate the second pixel at the packet */
@@ -287,7 +287,7 @@
 		for (color=0;color<4;color++) {
 			pgpos=get_addr_pos(pos,pages,to_addr);
 			if (pgpos!=oldpg) {
-				pg=pfn_to_page(to_addr[pgpos].sg->dma_address >> PAGE_SHIFT);
+				pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT);
 				kunmap_atomic(basep, KM_BOUNCE_READ);
 				basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset;
 				oldpg=pgpos;
@@ -339,8 +339,8 @@
 				for (color=0;color<4;color++) {
 					pgpos=get_addr_pos(pos,pages,to_addr);
 					if (pgpos!=oldpg) {
-						pg=pfn_to_page(to_addr[pgpos].
-								sg->dma_address
+						pg=pfn_to_page(sg_dma_address(
+								to_addr[pgpos].sg)
 								>> PAGE_SHIFT);
 						kunmap_atomic(basep,
 								KM_BOUNCE_READ);
@@ -386,7 +386,7 @@
 	struct timeval ts;
 
 	/* Test if DMA mapping is ready */
-	if (!vb->dma.sglist[0].dma_address)
+	if (!sg_dma_address(&vb->dma.sglist[0]))
 		return;
 
 	prep_to_addr(to_addr,vb);
@@ -783,7 +783,7 @@
 	for (i = 0; i < nents; i++ ) {
 		BUG_ON(!sg[i].page);
 
-		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+		sg_dma_address(&sg[i]) = page_to_phys(sg[i].page) + sg[i].offset;
 	}
 
 	return nents;
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 2912326..ddce2fb 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -417,7 +417,7 @@
 static int w9968cf_write_sb(struct w9968cf_device*, u16 value);
 static int w9968cf_read_sb(struct w9968cf_device*);
 static int w9968cf_upload_quantizationtables(struct w9968cf_device*);
-static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs);
+static void w9968cf_urb_complete(struct urb *urb);
 
 /* Low-level I2C (SMBus) I/O */
 static int w9968cf_smbus_start(struct w9968cf_device*);
@@ -781,7 +781,7 @@
   If there are no requested frames in the FIFO list, packets are collected into
   a temporary buffer.
   --------------------------------------------------------------------------*/
-static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
+static void w9968cf_urb_complete(struct urb *urb)
 {
 	struct w9968cf_device* cam = (struct w9968cf_device*)urb->context;
 	struct w9968cf_frame_t** f;
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 1b2be2d..5b55634 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -303,7 +303,7 @@
 
 /*****************************************************************************/
 
-static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
+static void zc0301_urb_complete(struct urb *urb)
 {
 	struct zc0301_device* cam = urb->context;
 	struct zc0301_frame_t** f;
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 3cbac2e..168e431 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -1408,15 +1408,14 @@
 
 irqreturn_t
 zoran_irq (int             irq,
-	   void           *dev_id,
-	   struct pt_regs *regs)
+	   void           *dev_id)
 {
 	u32 stat, astat;
 	int count;
 	struct zoran *zr;
 	unsigned long flags;
 
-	zr = (struct zoran *) dev_id;
+	zr = dev_id;
 	count = 0;
 
 	if (zr->testing) {
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran_device.h
index f19705c..37fa86a 100644
--- a/drivers/media/video/zoran_device.h
+++ b/drivers/media/video/zoran_device.h
@@ -64,9 +64,7 @@
 /* interrupts */
 extern void print_interrupts(struct zoran *zr);
 extern void clear_interrupt_counters(struct zoran *zr);
-extern irqreturn_t zoran_irq(int irq,
-			     void *dev_id,
-			     struct pt_regs *regs);
+extern irqreturn_t zoran_irq(int irq, void *dev_id);
 
 /* JPEG codec access */
 extern void jpeg_start(struct zoran *zr);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index b5ffe53..0cbf564 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -335,13 +335,13 @@
 }
 
 static
-void zoran_irq(int irq, void *dev_id, struct pt_regs * regs)
+void zoran_irq(int irq, void *dev_id)
 {
 	u32 stat,estat;
 	int count = 0;
 	struct zoran *ztv = dev_id;
 
-	UNUSED(irq); UNUSED(regs);
+	UNUSED(irq);
 	for (;;) {
 		/* get/clear interrupt status bits */
 		stat=zrread(ZORAN_ISR);
diff --git a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h
index 048b5b8..bb2bf5a 100644
--- a/drivers/message/fusion/linux_compat.h
+++ b/drivers/message/fusion/linux_compat.h
@@ -6,13 +6,4 @@
 #include <linux/version.h>
 #include <scsi/scsi_device.h>
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6))
-static int inline scsi_device_online(struct scsi_device *sdev)
-{
-	return sdev->online;
-}
-#endif
-
-
-/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #endif /* _LINUX_COMPAT_H */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 29d0635..e5c7271 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -122,7 +122,7 @@
 /*
  *  Forward protos...
  */
-static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
+static irqreturn_t mpt_interrupt(int irq, void *bus_id);
 static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 static int	mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
 			u32 *req, int replyBytes, u16 *u16reply, int maxwait,
@@ -351,7 +351,6 @@
  *	mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
  *	@irq: irq number (not used)
  *	@bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
- *	@r: pt_regs pointer (not used)
  *
  *	This routine is registered via the request_irq() kernel API call,
  *	and handles all interrupts generated from a specific MPT adapter
@@ -365,7 +364,7 @@
  *	the protocol-specific details of the MPT request completion.
  */
 static irqreturn_t
-mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
+mpt_interrupt(int irq, void *bus_id)
 {
 	MPT_ADAPTER *ioc = bus_id;
 	u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c
index ac06f10..d96c687 100644
--- a/drivers/message/i2o/bus-osm.c
+++ b/drivers/message/i2o/bus-osm.c
@@ -80,18 +80,26 @@
  *	@dev: device to verify if it is a I2O Bus Adapter device
  *
  *	Because we want all Bus Adapters always return 0.
+ *	Except when we fail.  Then we are sad.
  *
- *	Returns 0.
+ *	Returns 0, except when we fail to excel.
  */
 static int i2o_bus_probe(struct device *dev)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(get_device(dev));
+	int rc;
 
-	device_create_file(dev, &dev_attr_scan);
+	rc = device_create_file(dev, &dev_attr_scan);
+	if (rc)
+		goto err_out;
 
 	osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid);
 
 	return 0;
+
+err_out:
+	put_device(dev);
+	return rc;
 };
 
 /**
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 7bd4d85..01a5a70 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -127,7 +127,7 @@
 	DECLARE_WAIT_QUEUE_HEAD(wq);
 	struct i2o_exec_wait *wait;
 	static u32 tcntxt = 0x80000000;
-	long flags;
+	unsigned long flags;
 	int rc = 0;
 
 	wait = i2o_exec_wait_alloc();
@@ -325,13 +325,24 @@
 static int i2o_exec_probe(struct device *dev)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	int rc;
 
-	i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+	rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+	if (rc) goto err_out;
 
-	device_create_file(dev, &dev_attr_vendor_id);
-	device_create_file(dev, &dev_attr_product_id);
+	rc = device_create_file(dev, &dev_attr_vendor_id);
+	if (rc) goto err_evtreg;
+	rc = device_create_file(dev, &dev_attr_product_id);
+	if (rc) goto err_vid;
 
 	return 0;
+
+err_vid:
+	device_remove_file(dev, &dev_attr_vendor_id);
+err_evtreg:
+	i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
+err_out:
+	return rc;
 };
 
 /**
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index dec41cc..62f1ac0 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -224,12 +224,11 @@
  *	i2o_pci_interrupt - Interrupt handler for I2O controller
  *	@irq: interrupt line
  *	@dev_id: pointer to the I2O controller
- *	@r: pointer to registers
  *
  *	Handle an interrupt from a PCI based I2O controller. This turns out
  *	to be rather simple. We keep the controller pointer in the cookie.
  */
-static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
+static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id)
 {
 	struct i2o_controller *c = dev_id;
 	u32 m;
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 2bf3272..149810a 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -203,7 +203,7 @@
  * SIBCLK to talk to the chip.  We leave the clock running until
  * we have finished processing all interrupts from the chip.
  */
-static irqreturn_t ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
+static irqreturn_t ucb1x00_irq(int irqnr, void *devid)
 {
 	struct ucb1x00 *ucb = devid;
 	struct ucb1x00_irq *irq;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3df0e7a..b6c045d 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -28,6 +28,17 @@
 
 	  If unsure, say N.
 
+config SGI_IOC4
+	tristate "SGI IOC4 Base IO support"
+	---help---
+	  This option enables basic support for the IOC4 chip on certain
+	  SGI IO controller cards (IO9, IO10, and PCI-RT).  This option
+	  does not enable any specific functions on such a card, but provides
+	  necessary infrastructure for other drivers to utilize.
+
+	  If you have an SGI Altix with an IOC4-based card say Y.
+	  Otherwise say N.
+
 config TIFM_CORE
 	tristate "TI Flash Media interface support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -57,4 +68,23 @@
           To compile this driver as a module, choose M here: the module will
 	  be called tifm_7xx1.
 
+config MSI_LAPTOP
+        tristate "MSI Laptop Extras"
+        depends on X86
+        depends on ACPI_EC
+        depends on BACKLIGHT_CLASS_DEVICE
+        ---help---
+	  This is a driver for laptops built by MSI (MICRO-STAR
+	  INTERNATIONAL):
+
+	  MSI MegaBook S270 (MS-1013)
+	  Cytron/TCM/Medion/Tchibo MD96100/SAM2000
+
+	  It adds support for Bluetooth, WLAN and LCD brightness control.
+
+	  More information about this driver is available at
+	  <http://0pointer.de/lennart/tchibo.html>.
+
+	  If you have an MSI S270 laptop, say Y or M here.
+
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index d65ece7..c9e98ab 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -5,6 +5,8 @@
 
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
+obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
+obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 634d538..48d5abe 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -196,10 +196,10 @@
 
 /* low level message processing */
 extern int ibmasm_send_i2o_message(struct service_processor *sp);
-extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs);
+extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
 
 /* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp, struct pt_regs *regs);
+extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
 extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
 extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
 
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index 47949a2..a3c589b 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -54,7 +54,7 @@
 	return 0;
 }
 
-irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs)
+irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id)
 {
 	u32	mfa;
 	struct service_processor *sp = (struct service_processor *)dev_id;
@@ -67,7 +67,7 @@
 	dbg("respond to interrupt at %s\n", get_timestamp(tsbuf));
 
 	if (mouse_interrupt_pending(sp)) {
-		ibmasm_handle_mouse_interrupt(sp, regs);
+		ibmasm_handle_mouse_interrupt(sp);
 		clear_mouse_interrupt(sp);
 	}
 
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index 0f9e3aa..a40fda6 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -158,12 +158,10 @@
 	}
 }
 
-static void send_mouse_event(struct input_dev *dev, struct pt_regs *regs,
-		struct remote_input *input)
+static void send_mouse_event(struct input_dev *dev, struct remote_input *input)
 {
 	unsigned char buttons = input->mouse_buttons;
 
-	input_regs(dev, regs);
 	input_report_abs(dev, ABS_X, input->data.mouse.x);
 	input_report_abs(dev, ABS_Y, input->data.mouse.y);
 	input_report_key(dev, BTN_LEFT, buttons & REMOTE_BUTTON_LEFT);
@@ -172,7 +170,7 @@
 	input_sync(dev);
 }
 
-static void send_keyboard_event(struct input_dev *dev, struct pt_regs *regs,
+static void send_keyboard_event(struct input_dev *dev,
 		struct remote_input *input)
 {
 	unsigned int key;
@@ -182,13 +180,11 @@
 		key = xlate_high[code & 0xff];
 	else
 		key = xlate[code];
-	input_regs(dev, regs);
 	input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
 	input_sync(dev);
 }
 
-void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
-		struct pt_regs *regs)
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp)
 {
 	unsigned long reader;
 	unsigned long writer;
@@ -203,9 +199,9 @@
 
 		print_input(&input);
 		if (input.type == INPUT_TYPE_MOUSE) {
-			send_mouse_event(sp->remote.mouse_dev, regs, &input);
+			send_mouse_event(sp->remote.mouse_dev, &input);
 		} else if (input.type == INPUT_TYPE_KEYBOARD) {
-			send_keyboard_event(sp->remote.keybd_dev, regs, &input);
+			send_keyboard_event(sp->remote.keybd_dev, &input);
 		} else
 			break;
 
diff --git a/drivers/sn/ioc4.c b/drivers/misc/ioc4.c
similarity index 92%
rename from drivers/sn/ioc4.c
rename to drivers/misc/ioc4.c
index 8562821..1c3c14a 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2005-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 /* This file contains the master driver module for use by SGI IOC4 subdrivers.
@@ -29,12 +29,9 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ioc4.h>
-#include <linux/mmtimer.h>
-#include <linux/rtc.h>
+#include <linux/ktime.h>
 #include <linux/mutex.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/clksupport.h>
-#include <asm/sn/shub_mmr.h>
+#include <linux/time.h>
 
 /***************
  * Definitions *
@@ -43,7 +40,7 @@
 /* Tweakable values */
 
 /* PCI bus speed detection/calibration */
-#define IOC4_CALIBRATE_COUNT 63	/* Calibration cycle period */
+#define IOC4_CALIBRATE_COUNT 63		/* Calibration cycle period */
 #define IOC4_CALIBRATE_CYCLES 256	/* Average over this many cycles */
 #define IOC4_CALIBRATE_DISCARD 2	/* Discard first few cycles */
 #define IOC4_CALIBRATE_LOW_MHZ 25	/* Lower bound on bus speed sanity */
@@ -143,11 +140,11 @@
 static void
 ioc4_clock_calibrate(struct ioc4_driver_data *idd)
 {
-	extern unsigned long sn_rtc_cycles_per_second;
 	union ioc4_int_out int_out;
 	union ioc4_gpcr gpcr;
 	unsigned int state, last_state = 1;
-	uint64_t start = 0, end, period;
+	struct timespec start_ts, end_ts;
+	uint64_t start, end, period;
 	unsigned int count = 0;
 
 	/* Enable output */
@@ -175,30 +172,28 @@
 		if (!last_state && state) {
 			count++;
 			if (count == IOC4_CALIBRATE_END) {
-				end = rtc_time();
+				ktime_get_ts(&end_ts);
 				break;
 			} else if (count == IOC4_CALIBRATE_DISCARD)
-				start = rtc_time();
+				ktime_get_ts(&start_ts);
 		}
 		last_state = state;
 	} while (1);
 
 	/* Calculation rearranged to preserve intermediate precision.
 	 * Logically:
-	 * 1. "end - start" gives us number of RTC cycles over all the
-	 *    square wave cycles measured.
-	 * 2. Divide by number of square wave cycles to get number of
-	 *    RTC cycles per square wave cycle.
+	 * 1. "end - start" gives us the measurement period over all
+	 *    the square wave cycles.
+	 * 2. Divide by number of square wave cycles to get the period
+	 *    of a square wave cycle.
 	 * 3. Divide by 2*(int_out.fields.count+1), which is the formula
 	 *    by which the IOC4 generates the square wave, to get the
-	 *    number of RTC cycles per IOC4 INT_OUT count.
-	 * 4. Divide by sn_rtc_cycles_per_second to get seconds per
-	 *    count.
-	 * 5. Multiply by 1E9 to get nanoseconds per count.
+	 *    period of an IOC4 INT_OUT count.
 	 */
-	period = ((end - start) * 1000000000) /
-	    (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)
-	     * sn_rtc_cycles_per_second);
+	end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec;
+	start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec;
+	period = (end - start) /
+		(IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
 
 	/* Bounds check the result. */
 	if (period > IOC4_CALIBRATE_LOW_LIMIT ||
@@ -210,10 +205,12 @@
 		       IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
 		period = IOC4_CALIBRATE_DEFAULT;
 	} else {
+		u64 ns = period;
+
+		do_div(ns, IOC4_EXTINT_COUNT_DIVISOR);
 		printk(KERN_DEBUG
-		       "IOC4 %s: PCI clock is %ld ns.\n",
-		       pci_name(idd->idd_pdev),
-		       period / IOC4_EXTINT_COUNT_DIVISOR);
+		       "IOC4 %s: PCI clock is %lld ns.\n",
+		       pci_name(idd->idd_pdev), ns);
 	}
 
 	/* Remember results.  We store the extint clock period rather
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index e689ee94..bbdba7b 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -127,15 +127,14 @@
 MODULE_PARM_DESC(cpoint_count, "Crash Point Count, number of times the \
 				crash point is to be hit to trigger action");
 
-unsigned int jp_do_irq(unsigned int irq, struct pt_regs *regs)
+unsigned int jp_do_irq(unsigned int irq)
 {
 	lkdtm_handler();
 	jprobe_return();
 	return 0;
 }
 
-irqreturn_t jp_handle_irq_event(unsigned int irq, struct pt_regs *regs,
-			struct irqaction *action)
+irqreturn_t jp_handle_irq_event(unsigned int irq, struct irqaction *action)
 {
 	lkdtm_handler();
 	jprobe_return();
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
new file mode 100644
index 0000000..fdb7153
--- /dev/null
+++ b/drivers/misc/msi-laptop.c
@@ -0,0 +1,395 @@
+/*-*-linux-c-*-*/
+
+/*
+  Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+  02110-1301, USA.
+ */
+
+/*
+ * msi-laptop.c - MSI S270 laptop support. This laptop is sold under
+ * various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
+ *
+ * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
+ *
+ *   lcd_level - Screen brightness: contains a single integer in the
+ *   range 0..8. (rw)
+ *
+ *   auto_brightness - Enable automatic brightness control: contains
+ *   either 0 or 1. If set to 1 the hardware adjusts the screen
+ *   brightness automatically when the power cord is
+ *   plugged/unplugged. (rw)
+ *
+ *   wlan - WLAN subsystem enabled: contains either 0 or 1. (ro)
+ *
+ *   bluetooth - Bluetooth subsystem enabled: contains either 0 or 1
+ *   Please note that this file is constantly 0 if no Bluetooth
+ *   hardware is available. (ro)
+ *
+ * In addition to these platform device attributes the driver
+ * registers itself in the Linux backlight control subsystem and is
+ * available to userspace under /sys/class/backlight/msi-laptop-bl/.
+ *
+ * This driver might work on other laptops produced by MSI. If you
+ * want to try it you can pass force=1 as argument to the module which
+ * will force it to load even when the DMI data doesn't identify the
+ * laptop as MSI S270. YMMV.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/autoconf.h>
+
+#define MSI_DRIVER_VERSION "0.5"
+
+#define MSI_LCD_LEVEL_MAX 9
+
+#define MSI_EC_COMMAND_WIRELESS 0x10
+#define MSI_EC_COMMAND_LCD_LEVEL 0x11
+
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
+
+static int auto_brightness;
+module_param(auto_brightness, int, 0);
+MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
+
+/* Hardware access */
+
+static int set_lcd_level(int level)
+{
+	u8 buf[2];
+
+	if (level < 0 || level >= MSI_LCD_LEVEL_MAX)
+		return -EINVAL;
+
+	buf[0] = 0x80;
+	buf[1] = (u8) (level*31);
+
+	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0);
+}
+
+static int get_lcd_level(void)
+{
+	u8 wdata = 0, rdata;
+	int result;
+
+	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1);
+	if (result < 0)
+		return result;
+
+	return (int) rdata / 31;
+}
+
+static int get_auto_brightness(void)
+{
+	u8 wdata = 4, rdata;
+	int result;
+
+	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1);
+	if (result < 0)
+		return result;
+
+	return !!(rdata & 8);
+}
+
+static int set_auto_brightness(int enable)
+{
+	u8 wdata[2], rdata;
+	int result;
+
+	wdata[0] = 4;
+
+	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1);
+	if (result < 0)
+		return result;
+
+	wdata[0] = 0x84;
+	wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0);
+
+	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0);
+}
+
+static int get_wireless_state(int *wlan, int *bluetooth)
+{
+	u8 wdata = 0, rdata;
+	int result;
+
+	result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1);
+	if (result < 0)
+		return -1;
+
+	if (wlan)
+		*wlan = !!(rdata & 8);
+
+	if (bluetooth)
+		*bluetooth = !!(rdata & 128);
+
+	return 0;
+}
+
+/* Backlight device stuff */
+
+static int bl_get_brightness(struct backlight_device *b)
+{
+	return get_lcd_level();
+}
+
+
+static int bl_update_status(struct backlight_device *b)
+{
+	return set_lcd_level(b->props->brightness);
+}
+
+static struct backlight_properties msibl_props = {
+	.owner		= THIS_MODULE,
+	.get_brightness = bl_get_brightness,
+	.update_status  = bl_update_status,
+	.max_brightness = MSI_LCD_LEVEL_MAX-1,
+};
+
+static struct backlight_device *msibl_device;
+
+/* Platform device */
+
+static ssize_t show_wlan(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+
+	int ret, enabled;
+
+	ret = get_wireless_state(&enabled, NULL);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", enabled);
+}
+
+static ssize_t show_bluetooth(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+
+	int ret, enabled;
+
+	ret = get_wireless_state(NULL, &enabled);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", enabled);
+}
+
+static ssize_t show_lcd_level(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+
+	int ret;
+
+	ret = get_lcd_level();
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", ret);
+}
+
+static ssize_t store_lcd_level(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+
+	int level, ret;
+
+	if (sscanf(buf, "%i", &level) != 1 || (level < 0 || level >= MSI_LCD_LEVEL_MAX))
+		return -EINVAL;
+
+	ret = set_lcd_level(level);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t show_auto_brightness(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+
+	int ret;
+
+	ret = get_auto_brightness();
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", ret);
+}
+
+static ssize_t store_auto_brightness(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+
+	int enable, ret;
+
+	if (sscanf(buf, "%i", &enable) != 1 || (enable != (enable & 1)))
+		return -EINVAL;
+
+	ret = set_auto_brightness(enable);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
+static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness);
+static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL);
+static DEVICE_ATTR(wlan, 0444, show_wlan, NULL);
+
+static struct attribute *msipf_attributes[] = {
+	&dev_attr_lcd_level.attr,
+	&dev_attr_auto_brightness.attr,
+	&dev_attr_bluetooth.attr,
+	&dev_attr_wlan.attr,
+	NULL
+};
+
+static struct attribute_group msipf_attribute_group = {
+	.attrs = msipf_attributes
+};
+
+static struct platform_driver msipf_driver = {
+	.driver = {
+		.name = "msi-laptop-pf",
+		.owner = THIS_MODULE,
+	}
+};
+
+static struct platform_device *msipf_device;
+
+/* Initialization */
+
+static struct dmi_system_id __initdata msi_dmi_table[] = {
+	{
+		.ident = "MSI S270",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
+		}
+	},
+	{
+		.ident = "Medion MD96100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
+		}
+	},
+	{ }
+};
+
+
+static int __init msi_init(void)
+{
+	int ret;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	if (!force && !dmi_check_system(msi_dmi_table))
+		return -ENODEV;
+
+	if (auto_brightness < 0 || auto_brightness > 2)
+		return -EINVAL;
+
+	/* Register backlight stuff */
+
+	msibl_device = backlight_device_register("msi-laptop-bl", NULL, &msibl_props);
+	if (IS_ERR(msibl_device))
+		return PTR_ERR(msibl_device);
+
+	ret = platform_driver_register(&msipf_driver);
+	if (ret)
+		goto fail_backlight;
+
+	/* Register platform stuff */
+
+	msipf_device = platform_device_alloc("msi-laptop-pf", -1);
+	if (!msipf_device) {
+		ret = -ENOMEM;
+		goto fail_platform_driver;
+	}
+
+	ret = platform_device_add(msipf_device);
+	if (ret)
+		goto fail_platform_device1;
+
+	ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group);
+	if (ret)
+		goto fail_platform_device2;
+
+	/* Disable automatic brightness control by default because
+	 * this module was probably loaded to do brightness control in
+	 * software. */
+
+	if (auto_brightness != 2)
+		set_auto_brightness(auto_brightness);
+
+	printk(KERN_INFO "msi-laptop: driver "MSI_DRIVER_VERSION" successfully loaded.\n");
+
+	return 0;
+
+fail_platform_device2:
+
+	platform_device_del(msipf_device);
+
+fail_platform_device1:
+
+	platform_device_put(msipf_device);
+
+fail_platform_driver:
+
+	platform_driver_unregister(&msipf_driver);
+
+fail_backlight:
+
+	backlight_device_unregister(msibl_device);
+
+	return ret;
+}
+
+static void __exit msi_cleanup(void)
+{
+
+	sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
+	platform_device_unregister(msipf_device);
+	platform_driver_unregister(&msipf_driver);
+	backlight_device_unregister(msibl_device);
+
+	/* Enable automatic brightness control again */
+	if (auto_brightness != 2)
+		set_auto_brightness(1);
+
+	printk(KERN_INFO "msi-laptop: driver unloaded.\n");
+}
+
+module_init(msi_init);
+module_exit(msi_cleanup);
+
+MODULE_AUTHOR("Lennart Poettering");
+MODULE_DESCRIPTION("MSI Laptop Support");
+MODULE_VERSION(MSI_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index a7ed304..1ba8754 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -48,7 +48,7 @@
 			printk(KERN_INFO DRIVER_NAME
 			       ": demand removing card from socket %d\n", cnt);
 			sock = fm->sockets[cnt];
-			fm->sockets[cnt] = 0;
+			fm->sockets[cnt] = NULL;
 			fm->remove_mask &= ~(1 << cnt);
 
 			writel(0x0e00, sock->addr + SOCK_CONTROL);
@@ -67,7 +67,7 @@
 	class_device_put(&fm->cdev);
 }
 
-static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
 {
 	struct tifm_adapter *fm = dev_id;
 	unsigned int irq_status;
@@ -118,7 +118,7 @@
 	return IRQ_HANDLED;
 }
 
-static tifm_media_id tifm_7xx1_toggle_sock_power(char *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;
@@ -163,7 +163,8 @@
 	return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
 }
 
-inline static char *tifm_7xx1_sock_addr(char *base_addr, unsigned int sock_num)
+inline static char __iomem *
+tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
 {
 	return base_addr + ((sock_num + 1) << 10);
 }
@@ -176,7 +177,7 @@
 	char *card_name = "xx";
 	int cnt, ok_to_register;
 	unsigned int insert_mask;
-	struct tifm_dev *new_sock = 0;
+	struct tifm_dev *new_sock = NULL;
 
 	if (!class_device_get(&fm->cdev))
 		return;
@@ -230,7 +231,7 @@
 				if (!ok_to_register ||
 					    device_register(&new_sock->dev)) {
 					spin_lock_irqsave(&fm->lock, flags);
-					fm->sockets[cnt] = 0;
+					fm->sockets[cnt] = NULL;
 					spin_unlock_irqrestore(&fm->lock,
 								flags);
 					tifm_free_device(&new_sock->dev);
@@ -390,7 +391,7 @@
 
 	tifm_remove_adapter(fm);
 
-	pci_set_drvdata(dev, 0);
+	pci_set_drvdata(dev, NULL);
 
 	iounmap(fm->addr);
 	pci_intx(dev, 0);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index cca5f85..ee32613 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -157,7 +157,7 @@
 		dev->wq = create_singlethread_workqueue(dev->wq_name);
 		if (!dev->wq) {
 			kfree(dev);
-			return 0;
+			return NULL;
 		}
 		dev->dev.parent = fm->dev;
 		dev->dev.bus = &tifm_bus_type;
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index cb142a6..494b23f 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -661,7 +661,7 @@
 /*
  * Handle an interrupt
  */
-static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t at91_mci_irq(int irq, void *devid)
 {
 	struct at91mci_host *host = devid;
 	int completed = 0;
@@ -754,7 +754,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs)
+static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
 {
 	struct at91mci_host *host = _host;
 	int present = !at91_get_gpio_value(irq);
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 61268da..53ffcbb 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -750,7 +750,7 @@
 #define STATUS_DATA_IN  (SD_STATUS_NE)
 #define STATUS_DATA_OUT (SD_STATUS_TH)
 
-static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
 {
 
 	u32 status;
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 1b79dd2..659d4a8 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -635,7 +635,7 @@
 	return trans_done;
 }
 
-static void imxmci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+static void imxmci_dma_irq(int dma, void *devid)
 {
 	struct imxmci_host *host = devid;
 	uint32_t stat = MMC_STATUS;
@@ -646,7 +646,7 @@
 	tasklet_schedule(&host->tasklet);
 }
 
-static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t imxmci_irq(int irq, void *devid)
 {
 	struct imxmci_host *host = devid;
 	uint32_t stat = MMC_STATUS;
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index c1293f1..f9027c8 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -28,6 +28,7 @@
 #include <linux/kdev_t.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
+#include <linux/scatterlist.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -154,6 +155,71 @@
 	return stat;
 }
 
+static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
+{
+	int err;
+	u32 blocks;
+
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	unsigned int timeout_us;
+
+	struct scatterlist sg;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_APP_CMD;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD))
+		return (u32)-1;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	data.timeout_ns = card->csd.tacc_ns * 100;
+	data.timeout_clks = card->csd.tacc_clks * 100;
+
+	timeout_us = data.timeout_ns / 1000;
+	timeout_us += data.timeout_clks * 1000 /
+		(card->host->ios.clock / 1000);
+
+	if (timeout_us > 100000) {
+		data.timeout_ns = 100000000;
+		data.timeout_clks = 0;
+	}
+
+	data.blksz = 4;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	sg_init_one(&sg, &blocks, 4);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE)
+		return (u32)-1;
+
+	blocks = ntohl(blocks);
+
+	return blocks;
+}
+
 static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 {
 	struct mmc_blk_data *md = mq->data;
@@ -184,10 +250,13 @@
 
 		/*
 		 * If the host doesn't support multiple block writes, force
-		 * block writes to single block.
+		 * block writes to single block. SD cards are excepted from
+		 * this rule as they support querying the number of
+		 * successfully written sectors.
 		 */
 		if (rq_data_dir(req) != READ &&
-		    !(card->host->caps & MMC_CAP_MULTIWRITE))
+		    !(card->host->caps & MMC_CAP_MULTIWRITE) &&
+		    !mmc_card_sd(card))
 			brq.data.blocks = 1;
 
 		if (brq.data.blocks > 1) {
@@ -276,24 +345,41 @@
 	return 1;
 
  cmd_err:
-	mmc_card_release_host(card);
-
 	ret = 1;
 
-	/*
-	 * For writes and where the host claims to support proper
-	 * error reporting, we first ok the successful blocks.
+ 	/*
+ 	 * If this is an SD card and we're writing, we can first
+ 	 * mark the known good sectors as ok.
+ 	 *
+	 * If the card is not SD, we can still ok written sectors
+	 * if the controller can do proper error reporting.
 	 *
 	 * For reads we just fail the entire chunk as that should
 	 * be safe in all cases.
 	 */
-	if (rq_data_dir(req) != READ &&
-	    (card->host->caps & MMC_CAP_MULTIWRITE)) {
+ 	if (rq_data_dir(req) != READ && mmc_card_sd(card)) {
+		u32 blocks;
+		unsigned int bytes;
+
+		blocks = mmc_sd_num_wr_blocks(card);
+		if (blocks != (u32)-1) {
+			if (card->csd.write_partial)
+				bytes = blocks << md->block_bits;
+			else
+				bytes = blocks << 9;
+			spin_lock_irq(&md->lock);
+			ret = end_that_request_chunk(req, 1, bytes);
+			spin_unlock_irq(&md->lock);
+		}
+	} else if (rq_data_dir(req) != READ &&
+		   (card->host->caps & MMC_CAP_MULTIWRITE)) {
 		spin_lock_irq(&md->lock);
 		ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
 		spin_unlock_irq(&md->lock);
 	}
 
+	mmc_card_release_host(card);
+
 	spin_lock_irq(&md->lock);
 	while (ret) {
 		ret = end_that_request_chunk(req, 0,
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 2b5a0cc..828503c 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -261,7 +261,7 @@
 /*
  * PIO data transfer IRQ handler.
  */
-static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 {
 	struct mmci_host *host = dev_id;
 	void __iomem *base = host->base;
@@ -347,7 +347,7 @@
 /*
  * Handle completion of command and data transfers.
  */
-static irqreturn_t mmci_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mmci_irq(int irq, void *dev_id)
 {
 	struct mmci_host *host = dev_id;
 	u32 status;
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index 52c9e52..762fa28 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -377,7 +377,7 @@
 		}
 }
 
-static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 {
 	struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
 	u16 status;
@@ -514,7 +514,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id)
 {
 	struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
 
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index ef35090..a526698 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -299,7 +299,7 @@
 	return 1;
 }
 
-static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t pxamci_irq(int irq, void *devid)
 {
 	struct pxamci_host *host = devid;
 	unsigned int ireg;
@@ -399,13 +399,13 @@
 	.set_ios	= pxamci_set_ios,
 };
 
-static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+static void pxamci_dma_irq(int dma, void *devid)
 {
 	printk(KERN_ERR "DMA%d: IRQ???\n", dma);
 	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
 }
 
-static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t pxamci_detect_irq(int irq, void *devid)
 {
 	struct pxamci_host *host = mmc_priv(devid);
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 20711ac..9a7d39b 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -985,7 +985,7 @@
 	}
 }
 
-static irqreturn_t sdhci_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sdhci_irq(int irq, void *dev_id)
 {
 	irqreturn_t result;
 	struct sdhci_host* host = dev_id;
@@ -1329,7 +1329,7 @@
 	tasklet_init(&host->finish_tasklet,
 		sdhci_tasklet_finish, (unsigned long)host);
 
-	setup_timer(&host->timer, sdhci_timeout_timer, (long)host);
+	setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
 
 	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
 		host->slot_descr, host);
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
index 6d23dc0..2bacff6 100644
--- a/drivers/mmc/tifm_sd.c
+++ b/drivers/mmc/tifm_sd.c
@@ -501,13 +501,13 @@
 	struct tifm_dev *sock = host->dev;
 	struct mmc_host *mmc = tifm_get_drvdata(sock);
 	struct mmc_request *mrq;
-	struct mmc_data *r_data = 0;
+	struct mmc_data *r_data = NULL;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sock->lock, flags);
 
 	mrq = host->req;
-	host->req = 0;
+	host->req = NULL;
 	host->state = IDLE;
 
 	if (!mrq) {
@@ -546,7 +546,7 @@
 	struct tifm_dev *sock = host->dev;
 	unsigned long flags;
 	struct mmc_data *r_data = mrq->cmd->data;
-	char *t_buffer = 0;
+	char *t_buffer = NULL;
 
 	if (r_data) {
 		t_buffer = kmap(r_data->sg->page);
@@ -613,13 +613,13 @@
 	struct tifm_dev *sock = host->dev;
 	struct mmc_host *mmc = tifm_get_drvdata(sock);
 	struct mmc_request *mrq;
-	struct mmc_data *r_data = 0;
+	struct mmc_data *r_data = NULL;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sock->lock, flags);
 
 	mrq = host->req;
-	host->req = 0;
+	host->req = NULL;
 	host->state = IDLE;
 
 	if (!mrq) {
@@ -644,7 +644,7 @@
 			r_data->bytes_xfered += r_data->blksz -
 				readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
 		}
-		host->buffer = 0;
+		host->buffer = NULL;
 		host->buffer_pos = 0;
 		host->buffer_size = 0;
 	}
@@ -895,7 +895,7 @@
 		sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
 	writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
 
-	tifm_set_drvdata(sock, 0);
+	tifm_set_drvdata(sock, NULL);
 	mmc_free_host(mmc);
 }
 
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 88c6f0b..ced309b 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1256,7 +1256,7 @@
  * Interrupt handling
  */
 
-static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wbsd_irq(int irq, void *dev_id)
 {
 	struct wbsd_host *host = dev_id;
 	int isr;
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index bc7cc71..d171776 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -62,7 +62,7 @@
 	}
 
 	if (info->map.virt != NULL)
-		iounmap((void *)info->map.virt);
+		iounmap(info->map.virt);
 
 	if (info->res != NULL) {
 		release_resource(info->res);
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index e0a1d38..94924d5 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -249,7 +249,7 @@
 	goto out;
 
 out_ior:
-	iounmap((void *)this->IO_ADDR_R);
+	iounmap(this->IO_ADDR_R);
 out_mtd:
 	kfree(new_mtd);
 out:
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 1b82bcc..11d170a 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -496,7 +496,6 @@
  * el_interrupt:
  * @irq: Interrupt number
  * @dev_id: The 3c501 that burped
- * @regs: Register data (surplus to our requirements)
  *
  * Handle the ether interface interrupts. The 3c501 needs a lot more
  * hand holding than most cards. In particular we get a transmit interrupt
@@ -515,7 +514,7 @@
  * TCP window.
  */
 
-static irqreturn_t el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
diff --git a/drivers/net/3c501.h b/drivers/net/3c501.h
index 39d3324..c56a2c6 100644
--- a/drivers/net/3c501.h
+++ b/drivers/net/3c501.h
@@ -7,7 +7,7 @@
 static int  el_open(struct net_device *dev);
 static void el_timeout(struct net_device *dev);
 static int  el_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el_interrupt(int irq, void *dev_id);
 static void el_receive(struct net_device *dev);
 static void el_reset(struct net_device *dev);
 static int  el1_close(struct net_device *dev);
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index ab8230a..458cb9c 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -649,7 +649,7 @@
  *
  ******************************************************/
 
-static irqreturn_t elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+static irqreturn_t elp_interrupt(int irq, void *dev_id)
 {
 	int len;
 	int dlen;
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 8205a53..aa43563 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -286,7 +286,7 @@
 static int	el16_probe1(struct net_device *dev, int ioaddr);
 static int	el16_open(struct net_device *dev);
 static int	el16_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el16_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el16_interrupt(int irq, void *dev_id);
 static void el16_rx(struct net_device *dev);
 static int	el16_close(struct net_device *dev);
 static struct net_device_stats *el16_get_stats(struct net_device *dev);
@@ -543,7 +543,7 @@
 
 /*	The typical workload of the driver:
 	Handle the network interface interrupts. */
-static irqreturn_t el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el16_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index b936373..f791bf0 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -191,7 +191,7 @@
 static ushort read_eeprom(int ioaddr, int index);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
@@ -910,18 +910,13 @@
 
 /* The EL3 interrupt handler. */
 static irqreturn_t
-el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+el3_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *)dev_id;
+	struct net_device *dev = dev_id;
 	struct el3_private *lp;
 	int ioaddr, status;
 	int i = max_interrupt_work;
 
-	if (dev == NULL) {
-		printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
 	lp = netdev_priv(dev);
 	spin_lock(&lp->lock);
 
@@ -1006,7 +1001,7 @@
 static void el3_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	el3_interrupt(dev->irq, dev, NULL);
+	el3_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 91f2232..c307ce6 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -373,8 +373,7 @@
 static int corkscrew_rx(struct net_device *dev);
 static void corkscrew_timeout(struct net_device *dev);
 static int boomerang_rx(struct net_device *dev);
-static irqreturn_t corkscrew_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs);
+static irqreturn_t corkscrew_interrupt(int irq, void *dev_id);
 static int corkscrew_close(struct net_device *dev);
 static void update_stats(int addr, struct net_device *dev);
 static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
@@ -1116,8 +1115,7 @@
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 
-static irqreturn_t corkscrew_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs)
+static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
 {
 	/* Use the now-standard shared IRQ implementation. */
 	struct net_device *dev = dev_id;
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index cf8a0bc..9184946 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -180,7 +180,7 @@
       	dev->name,__LINE__); \
       elmc_id_reset586(); } } }
 
-static irqreturn_t elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
+static irqreturn_t elmc_interrupt(int irq, void *dev_id);
 static int elmc_open(struct net_device *dev);
 static int elmc_close(struct net_device *dev);
 static int elmc_send_packet(struct sk_buff *, struct net_device *);
@@ -900,16 +900,13 @@
  */
 
 static irqreturn_t
-elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+elmc_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	unsigned short stat;
 	struct priv *p;
 
-	if (dev == NULL) {
-		printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
-		return IRQ_NONE;
-	} else if (!netif_running(dev)) {
+	if (!netif_running(dev)) {
 		/* The 3c523 has this habit of generating interrupts during the
 		   reset.  I'm not sure if the ni52 has this same problem, but it's
 		   really annoying if we haven't finished initializing it.  I was
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 625e57d..f4aca53 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -217,7 +217,7 @@
 static int	mc32_open(struct net_device *dev);
 static void	mc32_timeout(struct net_device *dev);
 static int	mc32_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mc32_interrupt(int irq, void *dev_id);
 static int	mc32_close(struct net_device *dev);
 static struct	net_device_stats *mc32_get_stats(struct net_device *dev);
 static void	mc32_set_multicast_list(struct net_device *dev);
@@ -1316,7 +1316,7 @@
  *
  */
 
-static irqreturn_t mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t mc32_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct mc32_local *lp;
@@ -1324,11 +1324,6 @@
 	int rx_event = 0;
 	int tx_event = 0;
 
-	if (dev == NULL) {
-		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
-		return IRQ_NONE;
-	}
-
 	ioaddr = dev->base_addr;
 	lp = netdev_priv(dev);
 
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index df42e28..80bdcf8 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -717,8 +717,8 @@
 static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int vortex_rx(struct net_device *dev);
 static int boomerang_rx(struct net_device *dev);
-static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t vortex_interrupt(int irq, void *dev_id);
+static irqreturn_t boomerang_interrupt(int irq, void *dev_id);
 static int vortex_close(struct net_device *dev);
 static void dump_tx_ring(struct net_device *dev);
 static void update_stats(void __iomem *ioaddr, struct net_device *dev);
@@ -794,7 +794,7 @@
 	unsigned long flags;
 	local_save_flags(flags);
 	local_irq_disable();
-	(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev,NULL);
+	(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev);
 	local_irq_restore(flags);
 }
 #endif
@@ -1849,9 +1849,9 @@
 			unsigned long flags;
 			local_irq_save(flags);
 			if (vp->full_bus_master_tx)
-				boomerang_interrupt(dev->irq, dev, NULL);
+				boomerang_interrupt(dev->irq, dev);
 			else
-				vortex_interrupt(dev->irq, dev, NULL);
+				vortex_interrupt(dev->irq, dev);
 			local_irq_restore(flags);
 		}
 	}
@@ -2149,7 +2149,7 @@
  */
 
 static irqreturn_t
-vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+vortex_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct vortex_private *vp = netdev_priv(dev);
@@ -2254,7 +2254,7 @@
  */
 
 static irqreturn_t
-boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+boomerang_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct vortex_private *vp = netdev_priv(dev);
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index db7b19a..7733697 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -438,7 +438,7 @@
 }
 
 static irqreturn_t
-lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+lance_interrupt (int irq, void *dev_id)
 {
         struct net_device *dev = (struct net_device *)dev_id;
         struct lance_private *lp = netdev_priv(dev);
@@ -674,7 +674,7 @@
 	WRITERAP(lp, LE_CSR0);
 	WRITERDP(lp, LE_C0_STRT);
 	spin_unlock (&lp->devlock);
-	lance_interrupt(dev->irq, dev, NULL);
+	lance_interrupt(dev->irq, dev);
 }
 #endif
 
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 5a4990a..458dd9f 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -631,8 +631,7 @@
 	return 1;		/* not done */
 }
 
-static irqreturn_t
-cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t cp_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct cp_private *cp;
@@ -696,7 +695,7 @@
 static void cp_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	cp_interrupt(dev->irq, dev, NULL);
+	cp_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index dbc5c0b..d02ed51 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -629,8 +629,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void rtl8139_poll_controller(struct net_device *dev);
 #endif
-static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
-			       struct pt_regs *regs);
+static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance);
 static int rtl8139_close (struct net_device *dev);
 static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
@@ -2146,8 +2145,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
-			       struct pt_regs *regs)
+static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct rtl8139_private *tp = netdev_priv(dev);
@@ -2219,7 +2217,7 @@
 static void rtl8139_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	rtl8139_interrupt(dev->irq, dev, NULL);
+	rtl8139_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index c9e4dca..8236f26 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -357,7 +357,7 @@
 
 static int i596_open(struct net_device *dev);
 static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
 static int i596_close(struct net_device *dev);
 static struct net_device_stats *i596_get_stats(struct net_device *dev);
 static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
@@ -501,7 +501,7 @@
 
 
 #if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static irqreturn_t i596_error(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i596_error(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 #ifdef ENABLE_MVME16x_NET
@@ -1283,7 +1283,7 @@
 	return ERR_PTR(err);
 }
 
-static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct i596_private *lp;
@@ -1294,7 +1294,7 @@
 #ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) {
-			i596_error(irq, dev_id, regs);
+			i596_error(irq, dev_id);
 			return IRQ_HANDLED;
 		}
 	}
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 9d34056..3d1c599 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -391,7 +391,6 @@
  * ei_interrupt - handle the interrupts from an 8390
  * @irq: interrupt number
  * @dev_id: a pointer to the net_device
- * @regs: unused
  *
  * Handle the ether interface interrupts. We pull packets from
  * the 8390 via the card specific functions and fire them at the networking
@@ -400,21 +399,15 @@
  * needed.
  */
 
-irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t ei_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	long e8390_base;
 	int interrupts, nr_serviced = 0;
 	struct ei_device *ei_local;
 
-	if (dev == NULL)
-	{
-		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
 	e8390_base = dev->base_addr;
-	ei_local = (struct ei_device *) netdev_priv(dev);
+	ei_local = netdev_priv(dev);
 
 	/*
 	 *	Protect the irq test too.
@@ -506,7 +499,7 @@
 void ei_poll(struct net_device *dev)
 {
 	disable_irq_lockdep(dev->irq);
-	ei_interrupt(dev->irq, dev, NULL);
+	ei_interrupt(dev->irq, dev);
 	enable_irq_lockdep(dev->irq);
 }
 #endif
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index ca4eb0c..f44f122 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -35,7 +35,7 @@
 extern void NS8390_init(struct net_device *dev, int startp);
 extern int ei_open(struct net_device *dev);
 extern int ei_close(struct net_device *dev);
-extern irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t ei_interrupt(int irq, void *dev_id);
 extern struct net_device *__alloc_ei_netdev(int size);
 static inline struct net_device *alloc_ei_netdev(void)
 {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ab92cc7..e2ed249 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2288,7 +2288,7 @@
 
 config UGETH_HAS_GIGA
 	bool
-	depends on UCC_GETH && MPC836x
+	depends on UCC_GETH && PPC_MPC836x
 
 config MV643XX_ETH
 	tristate "MV-643XX Ethernet support"
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 5f7258f..d76548e 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -425,8 +425,7 @@
 	return 0;
 }
 
-static irqreturn_t
-lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t lance_interrupt (int irq, void *dev_id)
 {
 	struct net_device *dev;
 	struct lance_private *lp;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 71a4f60..33c6645 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -2144,7 +2144,7 @@
 }
 
 
-static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t ace_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct ace_private *ap = netdev_priv(dev);
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index efb14b9..8ca8534 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -769,7 +769,7 @@
 static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs);
 static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs);
 static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs);
-static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ace_interrupt(int irq, void *dev_id);
 static int ace_load_firmware(struct net_device *dev);
 static int ace_open(struct net_device *dev);
 static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev);
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 28855a0..ef65e59 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1257,7 +1257,7 @@
 /*
 This is device interrupt function. It handles transmit, receive,link change and hardware timer interrupts.
 */
-static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
 {
 
 	struct net_device * dev = (struct net_device *) dev_id;
@@ -1336,7 +1336,7 @@
 	unsigned long flags;
 	local_save_flags(flags);
 	local_irq_disable();
-	amd8111e_interrupt(0, dev, NULL);
+	amd8111e_interrupt(0, dev);
 	local_irq_restore(flags);
 }
 #endif
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index 643b08c..9164d8c 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -88,7 +88,7 @@
 								struct sk_buff *skb, int ring_offset);
 static void apne_block_output(struct net_device *dev, const int count,
 							const unsigned char *buf, const int start_page);
-static irqreturn_t apne_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t apne_interrupt(int irq, void *dev_id);
 
 static int init_pcmcia(void);
 
@@ -543,7 +543,7 @@
     return;
 }
 
-static irqreturn_t apne_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t apne_interrupt(int irq, void *dev_id)
 {
     unsigned char pcmcia_intreq;
 
@@ -559,7 +559,7 @@
     if (ei_debug > 3)
         printk("pcmcia intreq = %x\n", pcmcia_intreq);
     pcmcia_disable_irq();			/* to get rid of the sti() within ei_interrupt */
-    ei_interrupt(irq, dev_id, regs);
+    ei_interrupt(irq, dev_id);
     pcmcia_ack_int(pcmcia_get_intreq());
     pcmcia_enable_irq();
     return IRQ_HANDLED;
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index ae7f828..cc1a27e 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -188,7 +188,7 @@
 static void cops_load (struct net_device *dev);
 static int  cops_nodeid (struct net_device *dev, int nodeid);
 
-static irqreturn_t cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t cops_interrupt (int irq, void *dev_id);
 static void cops_poll (unsigned long ltdev);
 static void cops_timeout(struct net_device *dev);
 static void cops_rx (struct net_device *dev);
@@ -721,7 +721,7 @@
  *      The typical workload of the driver:
  *      Handle the network interface interrupts.
  */
-static irqreturn_t cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t cops_interrupt(int irq, void *dev_id)
 {
         struct net_device *dev = dev_id;
         struct cops_local *lp;
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index d5666c3..2ea44ce 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -790,7 +790,7 @@
 /* the handler for the board interrupt */
  
 static irqreturn_t
-ltpc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+ltpc_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 5a95005..4e91dab 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -752,7 +752,7 @@
  * interrupts. Establish which device needs attention, and call the correct
  * chipset interrupt handler.
  */
-irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t arcnet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct arcnet_local *lp;
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 3aef3c1..9dfc09b 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -120,7 +120,7 @@
 static void ariadne_tx_timeout(struct net_device *dev);
 static int ariadne_rx(struct net_device *dev);
 static void ariadne_reset(struct net_device *dev);
-static irqreturn_t ariadne_interrupt(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t ariadne_interrupt(int irq, void *data);
 static int ariadne_close(struct net_device *dev);
 static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
 #ifdef HAVE_MULTICAST
@@ -416,7 +416,7 @@
 }
 
 
-static irqreturn_t ariadne_interrupt(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t ariadne_interrupt(int irq, void *data)
 {
     struct net_device *dev = (struct net_device *)data;
     volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 09d5c3f..ddd12d4 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -38,7 +38,7 @@
 #include "am79c961a.h"
 
 static irqreturn_t
-am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+am79c961_interrupt (int irq, void *dev_id);
 
 static unsigned int net_debug = NET_DEBUG;
 
@@ -596,7 +596,7 @@
 }
 
 static irqreturn_t
-am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+am79c961_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct dev_priv *priv = netdev_priv(dev);
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 3ecf2cc..b54b857 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -196,7 +196,7 @@
 /*
  * Handle interrupts from the PHY
  */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct at91_private *lp = (struct at91_private *) dev->priv;
@@ -888,7 +888,7 @@
 /*
  * MAC interrupt handler
  */
-static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct at91_private *lp = (struct at91_private *) dev->priv;
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index d231efa..127561c 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -435,7 +435,7 @@
 		netif_wake_queue(dev);
 }
 
-static irqreturn_t ep93xx_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ep93xx_irq(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct ep93xx_priv *ep = netdev_priv(dev);
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index 312955d..f3478a3 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -68,7 +68,7 @@
 
 static int ether1_open(struct net_device *dev);
 static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ether1_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ether1_interrupt(int irq, void *dev_id);
 static int ether1_close(struct net_device *dev);
 static struct net_device_stats *ether1_getstats(struct net_device *dev);
 static void ether1_setmulticastlist(struct net_device *dev);
@@ -908,7 +908,7 @@
 }
 
 static irqreturn_t
-ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+ether1_interrupt (int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	int status;
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 0810741..84686c8 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -81,7 +81,7 @@
 static void	ether3_tx(struct net_device *dev);
 static int	ether3_open (struct net_device *dev);
 static int	ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ether3_interrupt (int irq, void *dev_id);
 static int	ether3_close (struct net_device *dev);
 static struct net_device_stats *ether3_getstats (struct net_device *dev);
 static void	ether3_setmulticastlist (struct net_device *dev);
@@ -568,7 +568,7 @@
 }
 
 static irqreturn_t
-ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ether3_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	unsigned int status, handled = IRQ_NONE;
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 4aeca11..8620a5b 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -161,7 +161,7 @@
 static int read_eeprom(long ioaddr, int location);
 static int net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void net_rx(struct net_device *dev);
 static int net_close(struct net_device *dev);
 static struct net_device_stats *net_get_stats(struct net_device *dev);
@@ -648,8 +648,7 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static irqreturn_t
-net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index 92b5213..4e3bf6a 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -220,7 +220,7 @@
 }
 
 static irqreturn_t
-bionet_intr(int irq, void *data, struct pt_regs *fp) {
+bionet_intr(int irq, void *data) {
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index a102625..3b54361 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -163,7 +163,7 @@
 static struct net_device_stats *net_get_stats(struct net_device *dev);
 static void pamsnet_tick(unsigned long);
 
-static irqreturn_t pamsnet_intr(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t pamsnet_intr(int irq, void *data);
 
 static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
 
@@ -494,7 +494,6 @@
 pamsnet_intr(irq, data, fp)
 	int irq;
 	void *data;
-	struct pt_regs *fp;
 {
 	return IRQ_HANDLED;
 }
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index b6570ca..d79489e 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -344,7 +344,7 @@
 static int lance_open( struct net_device *dev );
 static void lance_init_ring( struct net_device *dev );
 static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
+static irqreturn_t lance_interrupt( int irq, void *dev_id );
 static int lance_rx( struct net_device *dev );
 static int lance_close( struct net_device *dev );
 static struct net_device_stats *lance_get_stats( struct net_device *dev );
@@ -866,7 +866,7 @@
 
 /* The LANCE interrupt handler. */
 
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t lance_interrupt( int irq, void *dev_id )
 {
 	struct net_device *dev = dev_id;
 	struct lance_private *lp;
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index f2c8e0d..2d306fc 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -203,7 +203,7 @@
 static void write_packet(long ioaddr, int length, unsigned char *packet, int pad, int mode);
 static void trigger_send(long ioaddr, int length);
 static int	atp_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t atp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t atp_interrupt(int irq, void *dev_id);
 static void net_rx(struct net_device *dev);
 static void read_block(long ioaddr, int length, unsigned char *buffer, int data_mode);
 static int net_close(struct net_device *dev);
@@ -596,20 +596,15 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static irqreturn_t
-atp_interrupt(int irq, void *dev_instance, struct pt_regs * regs)
+static irqreturn_t atp_interrupt(int irq, void *dev_instance)
 {
-	struct net_device *dev = (struct net_device *)dev_instance;
+	struct net_device *dev = dev_instance;
 	struct net_local *lp;
 	long ioaddr;
 	static int num_tx_since_rx;
 	int boguscount = max_interrupt_work;
 	int handled = 0;
 
-	if (dev == NULL) {
-		printk(KERN_ERR "ATP_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
 	ioaddr = dev->base_addr;
 	lp = netdev_priv(dev);
 
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index ac33b1b..4873dc6 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -89,7 +89,7 @@
 static int au1000_close(struct net_device *);
 static int au1000_tx(struct sk_buff *, struct net_device *);
 static int au1000_rx(struct net_device *);
-static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t au1000_interrupt(int, void *);
 static void au1000_tx_timeout(struct net_device *);
 static void set_rx_mode(struct net_device *);
 static struct net_device_stats *au1000_get_stats(struct net_device *);
@@ -1253,7 +1253,7 @@
 /*
  * Au1000 interrupt service routine.
  */
-static irqreturn_t au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t au1000_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index e891ea2..1ec2174 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -896,7 +896,7 @@
 	return (done ? 0 : 1);
 }
 
-static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t b44_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct b44 *bp = netdev_priv(dev);
@@ -1461,7 +1461,7 @@
 static void b44_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	b44_interrupt(dev->irq, dev, NULL);
+	b44_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -1706,14 +1706,15 @@
 
 		__b44_set_mac_addr(bp);
 
-		if (dev->flags & IFF_ALLMULTI)
+		if ((dev->flags & IFF_ALLMULTI) ||
+		    (dev->mc_count > B44_MCAST_TABLE_SIZE))
 			val |= RXCONFIG_ALLMULTI;
 		else
 			i = __b44_load_mcast(bp, dev);
 
-		for (; i < 64; i++) {
+		for (; i < 64; i++)
 			__b44_cam_write(bp, zero, i);
-		}
+
 		bw32(bp, B44_RXCONFIG, val);
         	val = br32(bp, B44_CAM_CTRL);
 	        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
@@ -2055,7 +2056,7 @@
 	u16 *ptr = (u16 *) data;
 
 	for (i = 0; i < 128; i += 2)
-		ptr[i / 2] = readw(bp->regs + 4096 + i);
+		ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
 
 	return 0;
 }
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 4adfe7b..4528ce9 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -152,9 +152,9 @@
 static void bmac_init_registers(struct net_device *dev);
 static void bmac_enable_and_reset_chip(struct net_device *dev);
 static int bmac_set_address(struct net_device *dev, void *addr);
-static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t bmac_misc_intr(int irq, void *dev_id);
+static irqreturn_t bmac_txdma_intr(int irq, void *dev_id);
+static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id);
 static void bmac_set_timeout(struct net_device *dev);
 static void bmac_tx_timeout(unsigned long data);
 static int bmac_output(struct sk_buff *skb, struct net_device *dev);
@@ -688,7 +688,7 @@
 
 static int rxintcount;
 
-static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = netdev_priv(dev);
@@ -765,7 +765,7 @@
 
 static int txintcount;
 
-static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = netdev_priv(dev);
@@ -1082,7 +1082,7 @@
 
 static int miscintcount;
 
-static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bmac_misc_intr(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = netdev_priv(dev);
@@ -1091,7 +1091,7 @@
 		XXDEBUG(("bmac_misc_intr\n"));
 	}
 	/* XXDEBUG(("bmac_misc_intr, status=%#08x\n", status)); */
-	/*     bmac_txdma_intr_inner(irq, dev_id, regs); */
+	/*     bmac_txdma_intr_inner(irq, dev_id); */
 	/*   if (status & FrameReceived) bp->stats.rx_dropped++; */
 	if (status & RxErrorMask) bp->stats.rx_errors++;
 	if (status & RxCRCCntExp) bp->stats.rx_crc_errors++;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 6b4edb6..01b76d3 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -1888,7 +1888,7 @@
  * is that the MSI interrupt is always serviced.
  */
 static irqreturn_t
-bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
+bnx2_msi(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct bnx2 *bp = netdev_priv(dev);
@@ -1908,7 +1908,7 @@
 }
 
 static irqreturn_t
-bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+bnx2_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct bnx2 *bp = netdev_priv(dev);
@@ -5554,7 +5554,7 @@
 	struct bnx2 *bp = netdev_priv(dev);
 
 	disable_irq(bp->pdev->irq);
-	bnx2_interrupt(bp->pdev->irq, dev, NULL);
+	bnx2_interrupt(bp->pdev->irq, dev);
 	enable_irq(bp->pdev->irq);
 }
 #endif
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index e83bc82..3292316 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1433,7 +1433,7 @@
 		 * write lock to protect from other code that also
 		 * sets the promiscuity.
 		 */
-		write_lock(&bond->curr_slave_lock);
+		write_lock_bh(&bond->curr_slave_lock);
 
 		if (bond_info->primary_is_promisc &&
 		    (++bond_info->rlb_promisc_timeout_counter >= RLB_PROMISC_TIMEOUT)) {
@@ -1448,7 +1448,7 @@
 			bond_info->primary_is_promisc = 0;
 		}
 
-		write_unlock(&bond->curr_slave_lock);
+		write_unlock_bh(&bond->curr_slave_lock);
 
 		if (bond_info->rlb_rebalance) {
 			bond_info->rlb_rebalance = 0;
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 7694365..521c5b7 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2469,7 +2469,7 @@
 		cas_post_rxcs_ringN(dev, cp, ring);
 }
 
-static irqreturn_t cas_interruptN(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cas_interruptN(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct cas *cp = netdev_priv(dev);
@@ -2522,7 +2522,7 @@
 }
 
 /* ring 2 handles a few more events than 3 and 4 */
-static irqreturn_t cas_interrupt1(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cas_interrupt1(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct cas *cp = netdev_priv(dev);
@@ -2574,7 +2574,7 @@
 		cas_post_rxcs_ringN(dev, cp, 0);
 }
 
-static irqreturn_t cas_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cas_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct cas *cp = netdev_priv(dev);
@@ -2689,7 +2689,7 @@
 	struct cas *cp = netdev_priv(dev);
 
 	cas_disable_irq(cp, 0);
-	cas_interrupt(cp->pdev->irq, dev, NULL);
+	cas_interrupt(cp->pdev->irq, dev);
 	cas_enable_irq(cp, 0);
 
 #ifdef USE_PCI_INTB
diff --git a/drivers/net/chelsio/cpl5_cmd.h b/drivers/net/chelsio/cpl5_cmd.h
index 27925e4..5b357d9 100644
--- a/drivers/net/chelsio/cpl5_cmd.h
+++ b/drivers/net/chelsio/cpl5_cmd.h
@@ -108,7 +108,7 @@
 	u8 iff:4;
 #endif
 	u16 vlan;
-	u32 len;
+	__be32 len;
 
 	u32 rsvd2;
 	u8 rsvd3;
@@ -119,7 +119,7 @@
 	u8 ip_hdr_words:4;
 	u8 tcp_hdr_words:4;
 #endif
-	u16 eth_type_mss;
+	__be16 eth_type_mss;
 };
 
 struct cpl_rx_pkt {
@@ -138,7 +138,7 @@
 	u8 iff:4;
 #endif
 	u16 csum;
-	u16 vlan;
+	__be16 vlan;
 	u16 len;
 };
 
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 5f1b067..ad7ff96 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -918,7 +918,7 @@
 	struct adapter *adapter = dev->priv;
 
 	local_irq_save(flags);
-        t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter, NULL);
+        t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
 	local_irq_restore(flags);
 }
 #endif
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index ddd0bdb..9799c12 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1217,7 +1217,7 @@
 /*
  * NAPI version of the main interrupt handler.
  */
-static irqreturn_t t1_interrupt_napi(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t t1_interrupt_napi(int irq, void *data)
 {
 	int handled;
 	struct adapter *adapter = data;
@@ -1279,7 +1279,7 @@
  * 5. If we took an interrupt, but no valid respQ descriptors was found we
  *      let the slow_intr_handler run and do error handling.
  */
-static irqreturn_t t1_interrupt(int irq, void *cookie, struct pt_regs *regs)
+static irqreturn_t t1_interrupt(int irq, void *cookie)
 {
 	int work_done;
 	struct respQ_e *e;
@@ -1312,7 +1312,7 @@
 	return IRQ_RETVAL(work_done != 0);
 }
 
-intr_handler_t t1_select_intr_handler(adapter_t *adapter)
+irq_handler_t t1_select_intr_handler(adapter_t *adapter)
 {
 	return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt;
 }
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 6d0d24a..91af47b 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -43,13 +43,6 @@
 #include <linux/interrupt.h>
 #include <asm/byteorder.h>
 
-#ifndef IRQ_RETVAL
-#define IRQ_RETVAL(x)
-typedef void irqreturn_t;
-#endif
-
-typedef irqreturn_t (*intr_handler_t)(int, void *, struct pt_regs *);
-
 struct sge_intr_counts {
 	unsigned int respQ_empty;      /* # times respQ empty */
 	unsigned int respQ_overflow;   /* # respQ overflow (fatal) */
@@ -88,7 +81,7 @@
 int t1_sge_configure(struct sge *, struct sge_params *);
 int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
 void t1_sge_destroy(struct sge *);
-intr_handler_t t1_select_intr_handler(adapter_t *adapter);
+irq_handler_t t1_select_intr_handler(adapter_t *adapter);
 int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
 void t1_set_vlan_accel(struct adapter *adapter, int on_off);
 void t1_sge_start(struct sge *);
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index f1501b6..966b563 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -403,8 +403,8 @@
 static int e100_open(struct net_device *dev);
 static int e100_set_mac_address(struct net_device *dev, void *addr);
 static int e100_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t e100rxtx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t e100nw_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t e100rxtx_interrupt(int irq, void *dev_id);
+static irqreturn_t e100nw_interrupt(int irq, void *dev_id);
 static void e100_rx(struct net_device *dev);
 static int e100_close(struct net_device *dev);
 static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -1197,7 +1197,7 @@
  */
 
 static irqreturn_t
-e100rxtx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+e100rxtx_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct net_local *np = (struct net_local *)dev->priv;
@@ -1264,7 +1264,7 @@
 }
 
 static irqreturn_t
-e100nw_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+e100nw_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct net_local *np = (struct net_local *)dev->priv;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index e4d50f0..4ffc9b4 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -249,7 +249,7 @@
 static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
 static int net_open(struct net_device *dev);
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void set_multicast_list(struct net_device *dev);
 static void net_timeout(struct net_device *dev);
 static void net_rx(struct net_device *dev);
@@ -495,7 +495,7 @@
 static void net_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	net_interrupt(dev->irq, dev, NULL);
+	net_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -1573,7 +1573,7 @@
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
 
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index 0b930da..690bb40 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -258,19 +258,13 @@
  * Handle the network interface interrupts.
  */
 
-static irqreturn_t de600_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t de600_interrupt(int irq, void *dev_id)
 {
 	struct net_device	*dev = dev_id;
 	u8		irq_status;
 	int		retrig = 0;
 	int		boguscount = 0;
 
-	/* This might just as well be deleted now, no crummy drivers present :-) */
-	if ((dev == NULL) || (DE600_IRQ != irq)) {
-		printk(KERN_ERR "%s: bogus interrupt %d\n", dev?dev->name:"DE-600", irq);
-		return IRQ_NONE;
-	}
-
 	spin_lock(&de600_lock);
 
 	select_nic();
diff --git a/drivers/net/de600.h b/drivers/net/de600.h
index e407301..1288e48 100644
--- a/drivers/net/de600.h
+++ b/drivers/net/de600.h
@@ -125,7 +125,7 @@
 static int	de600_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* Dispatch from interrupts. */
-static irqreturn_t de600_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t de600_interrupt(int irq, void *dev_id);
 static int	de600_tx_intr(struct net_device *dev, int irq_status);
 static void	de600_rx_intr(struct net_device *dev);
 
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index a18d4d1..b6ad0cb 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -221,7 +221,7 @@
 static int	de620_start_xmit(struct sk_buff *, struct net_device *);
 
 /* Dispatch from interrupts. */
-static irqreturn_t de620_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t de620_interrupt(int, void *);
 static int	de620_rx_intr(struct net_device *);
 
 /* Initialization */
@@ -591,7 +591,7 @@
  *
  */
 static irqreturn_t
-de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
+de620_interrupt(int irq_in, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	byte irq_status;
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index bbccd74..00e2a8a 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -694,19 +694,17 @@
 	spin_unlock(&lp->lock);
 }
 
-static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 
 	printk("%s: DMA error\n", dev->name);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t lance_interrupt(const int irq, void *dev_id,
-				   struct pt_regs *regs)
+static irqreturn_t lance_interrupt(const int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
 	int csr0;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index ae96805..8f514cc 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -248,8 +248,7 @@
 static void		dfx_int_pr_halt_id(DFX_board_t *bp);
 static void		dfx_int_type_0_process(DFX_board_t *bp);
 static void		dfx_int_common(struct net_device *dev);
-static irqreturn_t	dfx_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs);
+static irqreturn_t	dfx_interrupt(int irq, void *dev_id);
 
 static struct		net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
 static void		dfx_ctl_set_multicast_list(struct net_device *dev);
@@ -1693,7 +1692,6 @@
  * Arguments:
  *   irq	- interrupt vector
  *   dev_id	- pointer to device information
- *	 regs	- pointer to registers structure
  *
  * Functional Description:
  *   This routine calls the interrupt processing routine for this adapter.  It
@@ -1716,7 +1714,7 @@
  *   Interrupts are disabled, then reenabled at the adapter.
  */
 
-static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dfx_interrupt(int irq, void *dev_id)
 {
 	struct net_device	*dev = dev_id;
 	DFX_board_t		*bp;	/* private board structure pointer */
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index af59466..f87f6e3 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -518,7 +518,7 @@
 */
 static int depca_open(struct net_device *dev);
 static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t depca_interrupt(int irq, void *dev_id);
 static int depca_close(struct net_device *dev);
 static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void depca_tx_timeout(struct net_device *dev);
@@ -965,7 +965,7 @@
 /*
 ** The DEPCA interrupt handler.
 */
-static irqreturn_t depca_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t depca_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct depca_private *lp;
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index d084252..a795202 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -895,10 +895,10 @@
  *	dev, priv will always refer to the 0th device in Multi-NIC mode.
  */
 
-static irqreturn_t dgrs_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dgrs_intr(int irq, void *dev_id)
 {
-	struct net_device	*dev0 = (struct net_device *) dev_id;
-	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
+	struct net_device	*dev0 = dev_id;
+	DGRS_PRIV	*priv0 = dev0->priv;
 	I596_CB		*cbp;
 	int		cmd;
 	int		i;
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 7e95cf1..9d446a0 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -60,7 +60,7 @@
 static void rio_tx_timeout (struct net_device *dev);
 static void alloc_list (struct net_device *dev);
 static int start_xmit (struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t rio_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t rio_interrupt (int irq, void *dev_instance);
 static void rio_free_tx (struct net_device *dev, int irq);
 static void tx_error (struct net_device *dev, int tx_status);
 static int receive_packet (struct net_device *dev);
@@ -665,7 +665,7 @@
 }
 
 static irqreturn_t
-rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
+rio_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct netdev_private *np;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index a860ebb..615d2b1 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -159,7 +159,7 @@
 
 static struct net_device_stats *dm9000_get_stats(struct net_device *);
 
-static irqreturn_t dm9000_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t dm9000_interrupt(int, void *);
 
 static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
 static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
@@ -346,7 +346,7 @@
 static void dm9000_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	dm9000_interrupt(dev->irq,dev,NULL);
+	dm9000_interrupt(dev->irq,dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -804,7 +804,7 @@
 }
 
 static irqreturn_t
-dm9000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+dm9000_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	board_info_t *db;
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 26073c3..a3a08a5 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1949,7 +1949,7 @@
 	return 0;
 }
 
-static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t e100_intr(int irq, void *dev_id)
 {
 	struct net_device *netdev = dev_id;
 	struct nic *nic = netdev_priv(netdev);
@@ -2005,7 +2005,7 @@
 	struct nic *nic = netdev_priv(netdev);
 
 	e100_disable_irq(nic);
-	e100_intr(nic->pdev->irq, netdev, NULL);
+	e100_intr(nic->pdev->irq, netdev);
 	e100_tx_clean(nic);
 	e100_enable_irq(nic);
 }
@@ -2039,7 +2039,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
 static int e100_asf(struct nic *nic)
 {
 	/* ASF can be enabled from eeprom */
@@ -2048,7 +2047,6 @@
 	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
 	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
 }
-#endif
 
 static int e100_up(struct nic *nic)
 {
@@ -2715,34 +2713,32 @@
 	}
 }
 
+#ifdef CONFIG_PM
 static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
 
-	if (netif_running(netdev))
-		e100_down(nic);
-	e100_hw_reset(nic);
-	netif_device_detach(netdev);
+	netif_poll_disable(nic->netdev);
+	del_timer_sync(&nic->watchdog);
+	netif_carrier_off(nic->netdev);
 
-#ifdef CONFIG_PM
 	pci_save_state(pdev);
-	if (nic->flags & (wol_magic | e100_asf(nic)))
-#else
-	if (nic->flags & (wol_magic))
-#endif
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-	else
-		/* disable PME */
-		pci_enable_wake(pdev, 0, 0);
+
+	if ((nic->flags & wol_magic) | e100_asf(nic)) {
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+	} else {
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);
+	}
 
 	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	pci_set_power_state(pdev, PCI_D3hot);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
 static int e100_resume(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
@@ -2764,7 +2760,23 @@
 
 static void e100_shutdown(struct pci_dev *pdev)
 {
-	e100_suspend(pdev, PMSG_SUSPEND);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev_priv(netdev);
+
+	netif_poll_disable(nic->netdev);
+	del_timer_sync(&nic->watchdog);
+	netif_carrier_off(nic->netdev);
+
+	if ((nic->flags & wol_magic) | e100_asf(nic)) {
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+	} else {
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);
+	}
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
 }
 
 /* ------------------ PCI Error Recovery infrastructure  -------------- */
@@ -2848,9 +2860,9 @@
 	.id_table =     e100_id_table,
 	.probe =        e100_probe,
 	.remove =       __devexit_p(e100_remove),
+#ifdef CONFIG_PM
 	/* Power Management hooks */
 	.suspend =      e100_suspend,
-#ifdef CONFIG_PM
 	.resume =       e100_resume,
 #endif
 	.shutdown =     e100_shutdown,
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 778ede3..773821e 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -883,8 +883,7 @@
 
 static irqreturn_t
 e1000_test_intr(int irq,
-		void *data,
-		struct pt_regs *regs)
+		void *data)
 {
 	struct net_device *netdev = (struct net_device *) data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 7dca38f..fa84983 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -153,7 +153,7 @@
 static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
 static int e1000_set_mac(struct net_device *netdev, void *p);
-static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
+static irqreturn_t e1000_intr(int irq, void *data);
 static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
                                     struct e1000_tx_ring *tx_ring);
 #ifdef CONFIG_E1000_NAPI
@@ -3436,11 +3436,10 @@
  * e1000_intr - Interrupt Handler
  * @irq: interrupt number
  * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
  **/
 
 static irqreturn_t
-e1000_intr(int irq, void *data, struct pt_regs *regs)
+e1000_intr(int irq, void *data)
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -4862,7 +4861,7 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
 	disable_irq(adapter->pdev->irq);
-	e1000_intr(adapter->pdev->irq, netdev, NULL);
+	e1000_intr(adapter->pdev->irq, netdev);
 	e1000_clean_tx_irq(adapter, adapter->tx_ring);
 #ifndef CONFIG_E1000_NAPI
 	adapter->clean_rx(adapter, adapter->rx_ring);
@@ -4915,10 +4914,6 @@
 	pci_enable_wake(pdev, PCI_D3hot, 0);
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
-	/* Perform card reset only on one instance of the card */
-	if (PCI_FUNC (pdev->devfn) != 0)
-		return PCI_ERS_RESULT_RECOVERED;
-
 	e1000_reset(adapter);
 	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
 
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 09ff9b9..a4eb0dc 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -311,7 +311,7 @@
 static int	eepro_probe1(struct net_device *dev, int autoprobe);
 static int	eepro_open(struct net_device *dev);
 static int	eepro_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t eepro_interrupt(int irq, void *dev_id);
 static void 	eepro_rx(struct net_device *dev);
 static void 	eepro_transmit_interrupt(struct net_device *dev);
 static int	eepro_close(struct net_device *dev);
@@ -994,16 +994,6 @@
 		return -EAGAIN;
 	}
 
-#ifdef irq2dev_map
-	if  (((irq2dev_map[dev->irq] != 0)
-		|| (irq2dev_map[dev->irq] = dev) == 0) &&
-		(irq2dev_map[dev->irq]!=dev)) {
-		/* printk("%s: IRQ map wrong\n", dev->name); */
-	        free_irq(dev->irq, dev);
-		return -EAGAIN;
-	}
-#endif
-
 	/* Initialize the 82595. */
 
 	eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
@@ -1196,19 +1186,13 @@
 	Handle the network interface interrupts. */
 
 static irqreturn_t
-eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+eepro_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev =  (struct net_device *)dev_id;
-	                      /* (struct net_device *)(irq2dev_map[irq]);*/
+	struct net_device *dev = dev_id;
 	struct eepro_local *lp;
 	int ioaddr, status, boguscount = 20;
 	int handled = 0;
 
-	if (dev == NULL) {
-                printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
-                return IRQ_NONE;
-        }
-
 	lp = netdev_priv(dev);
 
         spin_lock(&lp->lock);
@@ -1288,10 +1272,6 @@
 	/* release the interrupt */
 	free_irq(dev->irq, dev);
 
-#ifdef irq2dev_map
-	irq2dev_map[dev->irq] = 0;
-#endif
-
 	/* Update the statistics here. What statistics? */
 
 	return 0;
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 499e93b..e28bb1e 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -488,7 +488,7 @@
 static void speedo_refill_rx_buffers(struct net_device *dev, int force);
 static int speedo_rx(struct net_device *dev);
 static void speedo_tx_buffer_gc(struct net_device *dev);
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t speedo_interrupt(int irq, void *dev_instance);
 static int speedo_close(struct net_device *dev);
 static struct net_device_stats *speedo_get_stats(struct net_device *dev);
 static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -606,7 +606,7 @@
 	/* disable_irq is not very nice, but with the funny lockless design
 	   we have no other choice. */
 	disable_irq(dev->irq);
-	speedo_interrupt (dev->irq, dev, NULL);
+	speedo_interrupt (dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -1541,7 +1541,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t speedo_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *)dev_instance;
 	struct speedo_private *sp;
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 9cb05d9..e14be02 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -249,7 +249,7 @@
 static struct net_device_stats *eexp_stats(struct net_device *dev);
 static int eexp_xmit(struct sk_buff *buf, struct net_device *dev);
 
-static irqreturn_t eexp_irq(int irq, void *dev_addr, struct pt_regs *regs);
+static irqreturn_t eexp_irq(int irq, void *dev_addr);
 static void eexp_set_multicast(struct net_device *dev);
 
 /*
@@ -789,20 +789,13 @@
 	}
 }
 
-static irqreturn_t eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
+static irqreturn_t eexp_irq(int irq, void *dev_info)
 {
 	struct net_device *dev = dev_info;
 	struct net_local *lp;
 	unsigned short ioaddr,status,ack_cmd;
 	unsigned short old_read_ptr, old_write_ptr;
 
-	if (dev==NULL)
-	{
-		printk(KERN_WARNING "eexpress: irq %d for unknown device\n",
-		       irq);
-		return IRQ_NONE;
-	}
-
 	lp = netdev_priv(dev);
 	ioaddr = dev->base_addr;
 
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 23b451a..b40724f 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_0028"
+#define DRV_VERSION	"EHEA_0034"
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
 	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -50,6 +50,7 @@
 #define EHEA_MAX_ENTRIES_SQ  32767
 #define EHEA_MIN_ENTRIES_QP  127
 
+#define EHEA_SMALL_QUEUES
 #define EHEA_NUM_TX_QP 1
 
 #ifdef EHEA_SMALL_QUEUES
@@ -59,11 +60,11 @@
 #define EHEA_DEF_ENTRIES_RQ2    1023
 #define EHEA_DEF_ENTRIES_RQ3    1023
 #else
-#define EHEA_MAX_CQE_COUNT     32000
-#define EHEA_DEF_ENTRIES_SQ    16000
-#define EHEA_DEF_ENTRIES_RQ1   32080
-#define EHEA_DEF_ENTRIES_RQ2    4020
-#define EHEA_DEF_ENTRIES_RQ3    4020
+#define EHEA_MAX_CQE_COUNT      4080
+#define EHEA_DEF_ENTRIES_SQ     4080
+#define EHEA_DEF_ENTRIES_RQ1    8160
+#define EHEA_DEF_ENTRIES_RQ2    2040
+#define EHEA_DEF_ENTRIES_RQ3    2040
 #endif
 
 #define EHEA_MAX_ENTRIES_EQ 20
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 263d1c5..eb7d44d 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -536,16 +536,14 @@
 		tasklet_hi_schedule(&pr->send_comp_task);
 }
 
-static irqreturn_t ehea_send_irq_handler(int irq, void *param,
-					 struct pt_regs *regs)
+static irqreturn_t ehea_send_irq_handler(int irq, void *param)
 {
 	struct ehea_port_res *pr = param;
 	tasklet_hi_schedule(&pr->send_comp_task);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ehea_recv_irq_handler(int irq, void *param,
-					 struct pt_regs *regs)
+static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
 {
 	struct ehea_port_res *pr = param;
 	struct ehea_port *port = pr->port;
@@ -553,8 +551,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param,
-					   struct pt_regs *regs)
+static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
 {
 	struct ehea_port *port = param;
 	struct ehea_eqe *eqe;
@@ -769,7 +766,7 @@
 		if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) {
 			if (!netif_carrier_ok(port->netdev)) {
 				ret = ehea_sense_port_attr(
-					adapter->port[portnum]);
+					port);
 				if (ret) {
 					ehea_error("failed resensing port "
 						   "attributes");
@@ -821,7 +818,7 @@
 		netif_stop_queue(port->netdev);
 		break;
 	default:
-		ehea_error("unknown event code %x", ec);
+		ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe);
 		break;
 	}
 }
@@ -850,8 +847,7 @@
 			    adapter->neq->fw_handle, event_mask);
 }
 
-static irqreturn_t ehea_interrupt_neq(int irq, void *param,
-				      struct pt_regs *regs)
+static irqreturn_t ehea_interrupt_neq(int irq, void *param)
 {
 	struct ehea_adapter *adapter = param;
 	tasklet_hi_schedule(&adapter->neq_tasklet);
@@ -1845,7 +1841,7 @@
 
 	if (netif_msg_tx_queued(port)) {
 		ehea_info("post swqe on QP %d", pr->qp->init_attr.qp_nr);
-		ehea_dump(swqe, sizeof(*swqe), "swqe");
+		ehea_dump(swqe, 512, "swqe");
 	}
 
 	ehea_post_swqe(pr->qp, swqe);
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 4a85aca..0b51a8c 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -44,71 +44,99 @@
 #define H_ALL_RES_TYPE_MR        5
 #define H_ALL_RES_TYPE_MW        6
 
-static long ehea_hcall_9arg_9ret(unsigned long opcode,
-         			 unsigned long arg1, unsigned long arg2,
-         			 unsigned long arg3, unsigned long arg4,
-         			 unsigned long arg5, unsigned long arg6,
-         			 unsigned long arg7, unsigned long arg8,
-         			 unsigned long arg9, unsigned long *out1,
-         			 unsigned long *out2,unsigned long *out3,
-         			 unsigned long *out4,unsigned long *out5,
-         			 unsigned long *out6,unsigned long *out7,
-         			 unsigned long *out8,unsigned long *out9)
+static long ehea_plpar_hcall_norets(unsigned long opcode,
+				    unsigned long arg1,
+				    unsigned long arg2,
+				    unsigned long arg3,
+				    unsigned long arg4,
+				    unsigned long arg5,
+				    unsigned long arg6,
+				    unsigned long arg7)
 {
-	long hret;
+	long ret;
 	int i, sleep_msecs;
 
 	for (i = 0; i < 5; i++) {
-		hret = plpar_hcall_9arg_9ret(opcode,arg1, arg2, arg3, arg4,
-					     arg5, arg6, arg7, arg8, arg9, out1,
-					     out2, out3, out4, out5, out6, out7,
-					     out8, out9);
-		if (H_IS_LONG_BUSY(hret)) {
-			sleep_msecs = get_longbusy_msecs(hret);
+		ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
+					 arg5, arg6, arg7);
+
+		if (H_IS_LONG_BUSY(ret)) {
+			sleep_msecs = get_longbusy_msecs(ret);
 			msleep_interruptible(sleep_msecs);
 			continue;
 		}
 
-		if (hret < H_SUCCESS)
-			ehea_error("op=%lx hret=%lx "
-				   "i1=%lx i2=%lx i3=%lx i4=%lx i5=%lx i6=%lx "
-				   "i7=%lx i8=%lx i9=%lx "
-				   "o1=%lx o2=%lx o3=%lx o4=%lx o5=%lx o6=%lx "
-				   "o7=%lx o8=%lx o9=%lx",
-				   opcode, hret, arg1, arg2, arg3, arg4, arg5,
-				   arg6, arg7, arg8, arg9, *out1, *out2, *out3,
-				   *out4, *out5, *out6, *out7, *out8, *out9);
-		return hret;
+		if (ret < H_SUCCESS)
+			ehea_error("opcode=%lx ret=%lx"
+				   " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
+				   " arg5=%lx arg6=%lx arg7=%lx ",
+				   opcode, ret,
+				   arg1, arg2, arg3, arg4, arg5,
+				   arg6, arg7);
+
+		return ret;
 	}
+
+	return H_BUSY;
+}
+
+static long ehea_plpar_hcall9(unsigned long opcode,
+			      unsigned long *outs, /* array of 9 outputs */
+			      unsigned long arg1,
+			      unsigned long arg2,
+			      unsigned long arg3,
+			      unsigned long arg4,
+			      unsigned long arg5,
+			      unsigned long arg6,
+			      unsigned long arg7,
+			      unsigned long arg8,
+			      unsigned long arg9)
+{
+	long ret;
+	int i, sleep_msecs;
+
+	for (i = 0; i < 5; i++) {
+		ret = plpar_hcall9(opcode, outs,
+				   arg1, arg2, arg3, arg4, arg5,
+				   arg6, arg7, arg8, arg9);
+
+		if (H_IS_LONG_BUSY(ret)) {
+			sleep_msecs = get_longbusy_msecs(ret);
+			msleep_interruptible(sleep_msecs);
+			continue;
+		}
+
+		if (ret < H_SUCCESS)
+			ehea_error("opcode=%lx ret=%lx"
+				   " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
+				   " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
+				   " arg9=%lx"
+				   " out1=%lx out2=%lx out3=%lx out4=%lx"
+				   " out5=%lx out6=%lx out7=%lx out8=%lx"
+				   " out9=%lx",
+				   opcode, ret,
+				   arg1, arg2, arg3, arg4, arg5,
+				   arg6, arg7, arg8, arg9,
+				   outs[0], outs[1], outs[2], outs[3],
+				   outs[4], outs[5], outs[6], outs[7],
+				   outs[8]);
+
+		return ret;
+	}
+
 	return H_BUSY;
 }
 
 u64 ehea_h_query_ehea_qp(const u64 adapter_handle, const u8 qp_category,
 			 const u64 qp_handle, const u64 sel_mask, void *cb_addr)
 {
-	u64 dummy;
-
-	if ((((u64)cb_addr) & (PAGE_SIZE - 1)) != 0) {
-		ehea_error("not on pageboundary");
-		return H_PARAMETER;
-	}
-
-	return ehea_hcall_9arg_9ret(H_QUERY_HEA_QP,
-				    adapter_handle,	        /* R4 */
-				    qp_category,	        /* R5 */
-				    qp_handle,	                /* R6 */
-				    sel_mask,	                /* R7 */
-				    virt_to_abs(cb_addr),	/* R8 */
-				    0, 0, 0, 0,	                /* R9-R12 */
-				    &dummy,                     /* R4 */
-				    &dummy,                     /* R5 */
-				    &dummy,	                /* R6 */
-				    &dummy,	                /* R7 */
-				    &dummy,	                /* R8 */
-				    &dummy,	                /* R9 */
-				    &dummy,	                /* R10 */
-				    &dummy,	                /* R11 */
-				    &dummy);	                /* R12 */
+	return ehea_plpar_hcall_norets(H_QUERY_HEA_QP,
+				       adapter_handle,	        /* R4 */
+				       qp_category,	        /* R5 */
+				       qp_handle,               /* R6 */
+				       sel_mask,                /* R7 */
+				       virt_to_abs(cb_addr),	/* R8 */
+				       0, 0);
 }
 
 /* input param R5 */
@@ -180,6 +208,7 @@
 			     u64 *qp_handle, struct h_epas *h_epas)
 {
 	u64 hret;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
 	u64 allocate_controls =
 	    EHEA_BMASK_SET(H_ALL_RES_QP_EQPO, init_attr->low_lat_rq1 ? 1 : 0)
@@ -219,45 +248,29 @@
 	    EHEA_BMASK_SET(H_ALL_RES_QP_TH_RQ2, init_attr->rq2_threshold)
 	    | EHEA_BMASK_SET(H_ALL_RES_QP_TH_RQ3, init_attr->rq3_threshold);
 
-	u64 r5_out = 0;
-	u64 r6_out = 0;
-	u64 r7_out = 0;
-	u64 r8_out = 0;
-	u64 r9_out = 0;
-	u64 g_la_user_out = 0;
-	u64 r11_out = 0;
-	u64 r12_out = 0;
+	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
+				 outs,
+				 adapter_handle,		/* R4 */
+				 allocate_controls,		/* R5 */
+				 init_attr->send_cq_handle,	/* R6 */
+				 init_attr->recv_cq_handle,	/* R7 */
+				 init_attr->aff_eq_handle,	/* R8 */
+				 r9_reg,			/* R9 */
+				 max_r10_reg,			/* R10 */
+				 r11_in,			/* R11 */
+				 threshold);			/* R12 */
 
-	hret = ehea_hcall_9arg_9ret(H_ALLOC_HEA_RESOURCE,
-				    adapter_handle,		/* R4 */
-				    allocate_controls,		/* R5 */
-				    init_attr->send_cq_handle,	/* R6 */
-				    init_attr->recv_cq_handle,	/* R7 */
-				    init_attr->aff_eq_handle,	/* R8 */
-				    r9_reg,			/* R9 */
-				    max_r10_reg,		/* R10 */
-				    r11_in,			/* R11 */
-				    threshold,			/* R12 */
-				    qp_handle,			/* R4 */
-				    &r5_out,			/* R5 */
-				    &r6_out,			/* R6 */
-				    &r7_out,			/* R7 */
-				    &r8_out,			/* R8 */
-				    &r9_out,			/* R9 */
-				    &g_la_user_out,		/* R10 */
-				    &r11_out,			/* R11 */
-				    &r12_out);			/* R12 */
-
-	init_attr->qp_nr = (u32)r5_out;
+	*qp_handle = outs[0];
+	init_attr->qp_nr = (u32)outs[1];
 
 	init_attr->act_nr_send_wqes =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_SWQE, r6_out);
+	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_SWQE, outs[2]);
 	init_attr->act_nr_rwqes_rq1 =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R1WQE, r6_out);
+	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R1WQE, outs[2]);
 	init_attr->act_nr_rwqes_rq2 =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R2WQE, r6_out);
+	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R2WQE, outs[2]);
 	init_attr->act_nr_rwqes_rq3 =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R3WQE, r6_out);
+	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R3WQE, outs[2]);
 
 	init_attr->act_wqe_size_enc_sq = init_attr->wqe_size_enc_sq;
 	init_attr->act_wqe_size_enc_rq1 = init_attr->wqe_size_enc_rq1;
@@ -265,25 +278,25 @@
 	init_attr->act_wqe_size_enc_rq3 = init_attr->wqe_size_enc_rq3;
 
 	init_attr->nr_sq_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_SQ, r8_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_SQ, outs[4]);
 	init_attr->nr_rq1_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ1, r8_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ1, outs[4]);
 	init_attr->nr_rq2_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ2, r9_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ2, outs[5]);
 	init_attr->nr_rq3_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ3, r9_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ3, outs[5]);
 
 	init_attr->liobn_sq =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_SQ, r11_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_SQ, outs[7]);
 	init_attr->liobn_rq1 =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ1, r11_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ1, outs[7]);
 	init_attr->liobn_rq2 =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ2, r12_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ2, outs[8]);
 	init_attr->liobn_rq3 =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ3, r12_out);
+	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ3, outs[8]);
 
 	if (!hret)
-		hcp_epas_ctor(h_epas, g_la_user_out, g_la_user_out);
+		hcp_epas_ctor(h_epas, outs[6], outs[6]);
 
 	return hret;
 }
@@ -292,31 +305,24 @@
 			     struct ehea_cq_attr *cq_attr,
 			     u64 *cq_handle, struct h_epas *epas)
 {
-	u64 hret, dummy, act_nr_of_cqes_out, act_pages_out;
-	u64 g_la_privileged_out, g_la_user_out;
+	u64 hret;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
-	hret = ehea_hcall_9arg_9ret(H_ALLOC_HEA_RESOURCE,
-				    adapter_handle,		/* R4 */
-				    H_ALL_RES_TYPE_CQ,		/* R5 */
-				    cq_attr->eq_handle,		/* R6 */
-				    cq_attr->cq_token,		/* R7 */
-				    cq_attr->max_nr_of_cqes,	/* R8 */
-				    0, 0, 0, 0,			/* R9-R12 */
-				    cq_handle,			/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &act_nr_of_cqes_out,	/* R7 */
-				    &act_pages_out,		/* R8 */
-				    &g_la_privileged_out,	/* R9 */
-				    &g_la_user_out,		/* R10 */
-				    &dummy,	                /* R11 */
-				    &dummy);	                /* R12 */
+	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
+				 outs,
+				 adapter_handle,		/* R4 */
+				 H_ALL_RES_TYPE_CQ,		/* R5 */
+				 cq_attr->eq_handle,		/* R6 */
+				 cq_attr->cq_token,		/* R7 */
+				 cq_attr->max_nr_of_cqes,	/* R8 */
+				 0, 0, 0, 0);			/* R9-R12 */
 
-	cq_attr->act_nr_of_cqes = act_nr_of_cqes_out;
-	cq_attr->nr_pages = act_pages_out;
+	*cq_handle = outs[0];
+	cq_attr->act_nr_of_cqes = outs[3];
+	cq_attr->nr_pages = outs[4];
 
 	if (!hret)
-		hcp_epas_ctor(epas, g_la_privileged_out, g_la_user_out);
+		hcp_epas_ctor(epas, outs[5], outs[6]);
 
 	return hret;
 }
@@ -361,9 +367,8 @@
 u64 ehea_h_alloc_resource_eq(const u64 adapter_handle,
 			     struct ehea_eq_attr *eq_attr, u64 *eq_handle)
 {
-	u64 hret, dummy, eq_liobn, allocate_controls;
-	u64 ist1_out, ist2_out, ist3_out, ist4_out;
-	u64 act_nr_of_eqes_out, act_pages_out;
+	u64 hret, allocate_controls;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
 	/* resource type */
 	allocate_controls =
@@ -372,27 +377,20 @@
 	    | EHEA_BMASK_SET(H_ALL_RES_EQ_INH_EQE_GEN, !eq_attr->eqe_gen)
 	    | EHEA_BMASK_SET(H_ALL_RES_EQ_NON_NEQ_ISN, 1);
 
-	hret = ehea_hcall_9arg_9ret(H_ALLOC_HEA_RESOURCE,
-				    adapter_handle,		/* R4 */
-				    allocate_controls,		/* R5 */
-				    eq_attr->max_nr_of_eqes,	/* R6 */
-				    0, 0, 0, 0, 0, 0,		/* R7-R10 */
-				    eq_handle,			/* R4 */
-				    &dummy,			/* R5 */
-				    &eq_liobn,			/* R6 */
-				    &act_nr_of_eqes_out,	/* R7 */
-				    &act_pages_out,		/* R8 */
-				    &ist1_out,			/* R9 */
-				    &ist2_out,			/* R10 */
-				    &ist3_out,			/* R11 */
-				    &ist4_out);			/* R12 */
+	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
+				 outs,
+				 adapter_handle,		/* R4 */
+				 allocate_controls,		/* R5 */
+				 eq_attr->max_nr_of_eqes,	/* R6 */
+				 0, 0, 0, 0, 0, 0);		/* R7-R10 */
 
-	eq_attr->act_nr_of_eqes = act_nr_of_eqes_out;
-	eq_attr->nr_pages = act_pages_out;
-	eq_attr->ist1 = ist1_out;
-	eq_attr->ist2 = ist2_out;
-	eq_attr->ist3 = ist3_out;
-	eq_attr->ist4 = ist4_out;
+	*eq_handle = outs[0];
+	eq_attr->act_nr_of_eqes = outs[3];
+	eq_attr->nr_pages = outs[4];
+	eq_attr->ist1 = outs[5];
+	eq_attr->ist2 = outs[6];
+	eq_attr->ist3 = outs[7];
+	eq_attr->ist4 = outs[8];
 
 	return hret;
 }
@@ -402,31 +400,22 @@
 			  void *cb_addr, u64 *inv_attr_id, u64 *proc_mask,
 			  u16 *out_swr, u16 *out_rwr)
 {
-	u64 hret, dummy, act_out_swr, act_out_rwr;
+	u64 hret;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
-	if ((((u64)cb_addr) & (PAGE_SIZE - 1)) != 0) {
-		ehea_error("not on page boundary");
-		return H_PARAMETER;
-	}
+	hret = ehea_plpar_hcall9(H_MODIFY_HEA_QP,
+				 outs,
+				 adapter_handle,		/* R4 */
+				 (u64) cat,			/* R5 */
+				 qp_handle,			/* R6 */
+				 sel_mask,			/* R7 */
+				 virt_to_abs(cb_addr),		/* R8 */
+				 0, 0, 0, 0);			/* R9-R12 */
 
-	hret = ehea_hcall_9arg_9ret(H_MODIFY_HEA_QP,
-				    adapter_handle,		/* R4 */
-				    (u64) cat,			/* R5 */
-				    qp_handle,			/* R6 */
-				    sel_mask,			/* R7 */
-				    virt_to_abs(cb_addr),	/* R8 */
-				    0, 0, 0, 0,			/* R9-R12 */
-				    inv_attr_id,		/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &act_out_swr,		/* R7 */
-				    &act_out_rwr,		/* R8 */
-				    proc_mask,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,			/* R11 */
-				    &dummy);			/* R12 */
-	*out_swr = act_out_swr;
-	*out_rwr = act_out_rwr;
+	*inv_attr_id = outs[0];
+	*out_swr = outs[3];
+	*out_rwr = outs[4];
+	*proc_mask = outs[5];
 
 	return hret;
 }
@@ -435,122 +424,81 @@
 			  const u8 queue_type, const u64 resource_handle,
 			  const u64 log_pageaddr, u64 count)
 {
-	u64 dummy, reg_control;
+	u64  reg_control;
 
 	reg_control = EHEA_BMASK_SET(H_REG_RPAGE_PAGE_SIZE, pagesize)
 		    | EHEA_BMASK_SET(H_REG_RPAGE_QT, queue_type);
 
-	return ehea_hcall_9arg_9ret(H_REGISTER_HEA_RPAGES,
-				    adapter_handle,		/* R4 */
-				    reg_control,		/* R5 */
-				    resource_handle,		/* R6 */
-				    log_pageaddr,		/* R7 */
-				    count,			/* R8 */
-				    0, 0, 0, 0,			/* R9-R12 */
-				    &dummy,			/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &dummy,			/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,	                /* R11 */
-				    &dummy);	                /* R12 */
+	return ehea_plpar_hcall_norets(H_REGISTER_HEA_RPAGES,
+				       adapter_handle,		/* R4 */
+				       reg_control,		/* R5 */
+				       resource_handle,		/* R6 */
+				       log_pageaddr,		/* R7 */
+				       count,			/* R8 */
+				       0, 0);			/* R9-R10 */
 }
 
 u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
 			const u64 vaddr_in, const u32 access_ctrl, const u32 pd,
 			struct ehea_mr *mr)
 {
-	u64 hret, dummy, lkey_out;
+	u64 hret;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
-	hret = ehea_hcall_9arg_9ret(H_REGISTER_SMR,
-				    adapter_handle       ,          /* R4 */
-				    orig_mr_handle,                 /* R5 */
-				    vaddr_in,                       /* R6 */
-				    (((u64)access_ctrl) << 32ULL),  /* R7 */
-				    pd,                             /* R8 */
-				    0, 0, 0, 0,			    /* R9-R12 */
-				    &mr->handle,                    /* R4 */
-				    &dummy,                         /* R5 */
-				    &lkey_out,                      /* R6 */
-				    &dummy,                         /* R7 */
-				    &dummy,                         /* R8 */
-				    &dummy,                         /* R9 */
-				    &dummy,                         /* R10 */
-				    &dummy,                         /* R11 */
-				    &dummy);                        /* R12 */
-	mr->lkey = (u32)lkey_out;
+	hret = ehea_plpar_hcall9(H_REGISTER_SMR,
+				 outs,
+				 adapter_handle       ,        	 /* R4 */
+				 orig_mr_handle,                 /* R5 */
+				 vaddr_in,                       /* R6 */
+				 (((u64)access_ctrl) << 32ULL),  /* R7 */
+				 pd,                             /* R8 */
+				 0, 0, 0, 0);	   		 /* R9-R12 */
+
+	mr->handle = outs[0];
+	mr->lkey = (u32)outs[2];
 
 	return hret;
 }
 
 u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle)
 {
-	u64 hret, dummy, ladr_next_sq_wqe_out;
-	u64 ladr_next_rq1_wqe_out, ladr_next_rq2_wqe_out, ladr_next_rq3_wqe_out;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
-	hret = ehea_hcall_9arg_9ret(H_DISABLE_AND_GET_HEA,
-				    adapter_handle,		/* R4 */
-				    H_DISABLE_GET_EHEA_WQE_P,	/* R5 */
-				    qp_handle,			/* R6 */
-				    0, 0, 0, 0, 0, 0,		/* R7-R12 */
-				    &ladr_next_sq_wqe_out,	/* R4 */
-				    &ladr_next_rq1_wqe_out,	/* R5 */
-				    &ladr_next_rq2_wqe_out,	/* R6 */
-				    &ladr_next_rq3_wqe_out,	/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,                     /* R11 */
-				    &dummy);                    /* R12 */
-	return hret;
+	return ehea_plpar_hcall9(H_DISABLE_AND_GET_HEA,
+       				 outs,
+				 adapter_handle,		/* R4 */
+				 H_DISABLE_GET_EHEA_WQE_P,	/* R5 */
+				 qp_handle,			/* R6 */
+				 0, 0, 0, 0, 0, 0);             /* R7-R12 */
 }
 
 u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle)
 {
-	u64 dummy;
-
-	return ehea_hcall_9arg_9ret(H_FREE_RESOURCE,
-				    adapter_handle,	   /* R4 */
-				    res_handle,            /* R5 */
-				    0, 0, 0, 0, 0, 0, 0,   /* R6-R12 */
-				    &dummy,                /* R4 */
-				    &dummy,                /* R5 */
-				    &dummy,                /* R6 */
-				    &dummy,                /* R7 */
-				    &dummy,                /* R8 */
-				    &dummy,                /* R9 */
-				    &dummy,		   /* R10 */
-				    &dummy,                /* R11 */
-				    &dummy);               /* R12 */
+	return ehea_plpar_hcall_norets(H_FREE_RESOURCE,
+				       adapter_handle,	   /* R4 */
+				       res_handle,         /* R5 */
+				       0, 0, 0, 0, 0);     /* R6-R10 */
 }
 
 u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
 			     const u64 length, const u32 access_ctrl,
 			     const u32 pd, u64 *mr_handle, u32 *lkey)
 {
-	u64 hret, dummy, lkey_out;
+	u64 hret;
+ 	u64 outs[PLPAR_HCALL9_BUFSIZE];
 
-	hret = ehea_hcall_9arg_9ret(H_ALLOC_HEA_RESOURCE,
-				    adapter_handle,		   /* R4 */
-				    5,				   /* R5 */
-				    vaddr,			   /* R6 */
-				    length,			   /* R7 */
-				    (((u64) access_ctrl) << 32ULL),/* R8 */
-				    pd,				   /* R9 */
-				    0, 0, 0,			   /* R10-R12 */
-				    mr_handle,			   /* R4 */
-				    &dummy,			   /* R5 */
-				    &lkey_out,			   /* R6 */
-				    &dummy,			   /* R7 */
-				    &dummy,			   /* R8 */
-				    &dummy,			   /* R9 */
-				    &dummy,			   /* R10 */
-				    &dummy,                        /* R11 */
-				    &dummy);                       /* R12 */
-	*lkey = (u32) lkey_out;
+	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
+				 outs,
+				 adapter_handle,		   /* R4 */
+				 5,				   /* R5 */
+				 vaddr,			           /* R6 */
+				 length,			   /* R7 */
+				 (((u64) access_ctrl) << 32ULL),   /* R8 */
+				 pd,				   /* R9 */
+				 0, 0, 0);			   /* R10-R12 */
 
+	*mr_handle = outs[0];
+	*lkey = (u32)outs[2];
 	return hret;
 }
 
@@ -570,23 +518,14 @@
 
 u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr)
 {
-	u64 hret, dummy, cb_logaddr;
+	u64 hret, cb_logaddr;
 
 	cb_logaddr = virt_to_abs(cb_addr);
 
-	hret = ehea_hcall_9arg_9ret(H_QUERY_HEA,
-				    adapter_handle,		/* R4 */
-				    cb_logaddr,			/* R5 */
-				    0, 0, 0, 0, 0, 0, 0,	/* R6-R12 */
-				    &dummy,			/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &dummy,			/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,             	/* R11 */
-				    &dummy);            	/* R12 */
+	hret = ehea_plpar_hcall_norets(H_QUERY_HEA,
+				       adapter_handle,		/* R4 */
+				       cb_logaddr,		/* R5 */
+				       0, 0, 0, 0, 0);		/* R6-R10 */
 #ifdef DEBUG
 	ehea_dmp(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
 #endif
@@ -597,36 +536,28 @@
 			   const u8 cb_cat, const u64 select_mask,
 			   void *cb_addr)
 {
-	u64 port_info, dummy;
+	u64 port_info;
 	u64 cb_logaddr = virt_to_abs(cb_addr);
 	u64 arr_index = 0;
 
 	port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
 		  | EHEA_BMASK_SET(H_MEHEAPORT_PN, port_num);
 
-	return ehea_hcall_9arg_9ret(H_QUERY_HEA_PORT,
-				    adapter_handle,		/* R4 */
-				    port_info,			/* R5 */
-				    select_mask,		/* R6 */
-				    arr_index,			/* R7 */
-				    cb_logaddr,			/* R8 */
-				    0, 0, 0, 0,			/* R9-R12 */
-				    &dummy,			/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &dummy,			/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,                     /* R11 */
-				    &dummy);                    /* R12 */
+	return ehea_plpar_hcall_norets(H_QUERY_HEA_PORT,
+				       adapter_handle,		/* R4 */
+				       port_info,		/* R5 */
+				       select_mask,		/* R6 */
+				       arr_index,		/* R7 */
+				       cb_logaddr,		/* R8 */
+				       0, 0);			/* R9-R10 */
 }
 
 u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
 			    const u8 cb_cat, const u64 select_mask,
 			    void *cb_addr)
 {
-	u64 port_info, dummy, inv_attr_ident, proc_mask;
+	u64 outs[PLPAR_HCALL9_BUFSIZE];
+	u64 port_info;
 	u64 arr_index = 0;
 	u64 cb_logaddr = virt_to_abs(cb_addr);
 
@@ -635,29 +566,21 @@
 #ifdef DEBUG
 	ehea_dump(cb_addr, sizeof(struct hcp_ehea_port_cb0), "Before HCALL");
 #endif
-	return ehea_hcall_9arg_9ret(H_MODIFY_HEA_PORT,
-				    adapter_handle,		/* R4 */
-				    port_info,			/* R5 */
-				    select_mask,		/* R6 */
-				    arr_index,			/* R7 */
-				    cb_logaddr,			/* R8 */
-				    0, 0, 0, 0,			/* R9-R12 */
-				    &inv_attr_ident,		/* R4 */
-				    &proc_mask,			/* R5 */
-				    &dummy,			/* R6 */
-				    &dummy,			/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,                     /* R11 */
-				    &dummy);                    /* R12 */
+	return ehea_plpar_hcall9(H_MODIFY_HEA_PORT,
+				 outs,
+				 adapter_handle,		/* R4 */
+				 port_info,			/* R5 */
+				 select_mask,			/* R6 */
+				 arr_index,			/* R7 */
+				 cb_logaddr,			/* R8 */
+				 0, 0, 0, 0);			/* R9-R12 */
 }
 
 u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
 			  const u8 reg_type, const u64 mc_mac_addr,
 			  const u16 vlan_id, const u32 hcall_id)
 {
-	u64 r5_port_num, r6_reg_type, r7_mc_mac_addr, r8_vlan_id, dummy;
+	u64 r5_port_num, r6_reg_type, r7_mc_mac_addr, r8_vlan_id;
 	u64 mac_addr = mc_mac_addr >> 16;
 
 	r5_port_num = EHEA_BMASK_SET(H_REGBCMC_PN, port_num);
@@ -665,41 +588,21 @@
 	r7_mc_mac_addr = EHEA_BMASK_SET(H_REGBCMC_MACADDR, mac_addr);
 	r8_vlan_id = EHEA_BMASK_SET(H_REGBCMC_VLANID, vlan_id);
 
-	return ehea_hcall_9arg_9ret(hcall_id,
-				    adapter_handle,		/* R4 */
-				    r5_port_num,		/* R5 */
-				    r6_reg_type,		/* R6 */
-				    r7_mc_mac_addr,		/* R7 */
-				    r8_vlan_id,			/* R8 */
-				    0, 0, 0, 0,			/* R9-R12 */
-				    &dummy,			/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &dummy,			/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,                     /* R11 */
-				    &dummy);                    /* R12 */
+	return ehea_plpar_hcall_norets(hcall_id,
+				       adapter_handle,		/* R4 */
+				       r5_port_num,		/* R5 */
+				       r6_reg_type,		/* R6 */
+				       r7_mc_mac_addr,		/* R7 */
+				       r8_vlan_id,		/* R8 */
+				       0, 0);			/* R9-R12 */
 }
 
 u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
 			const u64 event_mask)
 {
-	u64 dummy;
-
-	return ehea_hcall_9arg_9ret(H_RESET_EVENTS,
-				    adapter_handle,		/* R4 */
-				    neq_handle,			/* R5 */
-				    event_mask,			/* R6 */
-				    0, 0, 0, 0, 0, 0,		/* R7-R12 */
-				    &dummy,			/* R4 */
-				    &dummy,			/* R5 */
-				    &dummy,			/* R6 */
-				    &dummy,			/* R7 */
-				    &dummy,			/* R8 */
-				    &dummy,			/* R9 */
-				    &dummy,			/* R10 */
-				    &dummy,                     /* R11 */
-				    &dummy);                    /* R12 */
+	return ehea_plpar_hcall_norets(H_RESET_EVENTS,
+				       adapter_handle,		/* R4 */
+				       neq_handle,		/* R5 */
+				       event_mask,		/* R6 */
+				       0, 0, 0, 0);		/* R7-R12 */
 }
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index ba2565e..3a6a83d 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -297,7 +297,7 @@
 static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int epic_rx(struct net_device *dev, int budget);
 static int epic_poll(struct net_device *dev, int *budget);
-static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t epic_interrupt(int irq, void *dev_instance);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static const struct ethtool_ops netdev_ethtool_ops;
 static int epic_close(struct net_device *dev);
@@ -1081,7 +1081,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t epic_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct epic_private *ep = dev->priv;
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index f16b6a5..b7b8bc2 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -162,9 +162,9 @@
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
+#include <linux/io.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/dma.h>
 
 
@@ -410,7 +410,7 @@
 static int     eth16i_tx(struct sk_buff *skb, struct net_device *dev);
 static void    eth16i_rx(struct net_device *dev);
 static void    eth16i_timeout(struct net_device *dev);
-static irqreturn_t eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t eth16i_interrupt(int irq, void *dev_id);
 static void    eth16i_reset(struct net_device *dev);
 static void    eth16i_timeout(struct net_device *dev);
 static void    eth16i_skip_packet(struct net_device *dev);
@@ -1226,7 +1226,7 @@
 	} /* while */
 }
 
-static irqreturn_t eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t eth16i_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct eth16i_local *lp;
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 75a43f7..c8c41f0 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -300,7 +300,7 @@
  */
 static int ewrk3_open(struct net_device *dev);
 static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id);
 static int ewrk3_close(struct net_device *dev);
 static struct net_device_stats *ewrk3_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -884,7 +884,7 @@
 /*
    ** The EWRK3 interrupt handler.
  */
-static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct ewrk3_private *lp;
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 191bd42..38a13f4 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -434,7 +434,7 @@
 static void tx_timeout(struct net_device *dev);
 static void init_ring(struct net_device *dev);
 static int start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
 static int netdev_rx(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static void __set_rx_mode(struct net_device *dev);
@@ -1453,7 +1453,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 55d86bc..6764281 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -229,7 +229,7 @@
 static int fec_enet_open(struct net_device *dev);
 static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void fec_enet_mii(struct net_device *dev);
-static irqreturn_t fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
 static void fec_enet_tx(struct net_device *dev);
 static void fec_enet_rx(struct net_device *dev);
 static int fec_enet_close(struct net_device *dev);
@@ -450,7 +450,7 @@
  * This is called from the MPC core interrupt.
  */
 static irqreturn_t
-fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+fec_enet_interrupt(int irq, void * dev_id)
 {
 	struct	net_device *dev = dev_id;
 	volatile fec_t	*fecp;
@@ -1236,7 +1236,7 @@
 mii_link_interrupt(void *dev_id);
 #else
 static irqreturn_t
-mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+mii_link_interrupt(int irq, void * dev_id);
 #endif
 #endif
 
@@ -1251,7 +1251,7 @@
 	static const struct idesc {
 		char *name;
 		unsigned short irq;
-		irqreturn_t (*handler)(int, void *, struct pt_regs *);
+		irq_handler_t handler;
 	} *idp, id[] = {
 		{ "fec(RX)", 86, fec_enet_interrupt },
 		{ "fec(TX)", 87, fec_enet_interrupt },
@@ -2117,7 +2117,7 @@
 mii_link_interrupt(void *dev_id)
 #else
 static irqreturn_t
-mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+mii_link_interrupt(int irq, void * dev_id)
 #endif
 {
 	struct	net_device *dev = dev_id;
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index e17a144..8e7a56f 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -708,7 +708,7 @@
  * This is called from the MPC core interrupt.
  */
 static irqreturn_t
-fec_enet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+fec_enet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct fec_enet_private *fep;
@@ -768,7 +768,7 @@
 
 /* This interrupt occurs when the PHY detects a link change. */
 static irqreturn_t
-fec_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+fec_mii_link_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct fec_enet_private *fep;
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index eea1d66..c5ed635 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -2397,7 +2397,7 @@
 	dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name);
 }
 
-static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t nv_nic_irq(int foo, void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct fe_priv *np = netdev_priv(dev);
@@ -2490,13 +2490,14 @@
 	return IRQ_RETVAL(i);
 }
 
-static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t nv_nic_irq_tx(int foo, void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	u32 events;
 	int i;
+	unsigned long flags;
 
 	dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);
 
@@ -2508,16 +2509,16 @@
 		if (!(events & np->irqmask))
 			break;
 
-		spin_lock_irq(&np->lock);
+		spin_lock_irqsave(&np->lock, flags);
 		nv_tx_done(dev);
-		spin_unlock_irq(&np->lock);
+		spin_unlock_irqrestore(&np->lock, flags);
 
 		if (events & (NVREG_IRQ_TX_ERR)) {
 			dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
 						dev->name, events);
 		}
 		if (i > max_interrupt_work) {
-			spin_lock_irq(&np->lock);
+			spin_lock_irqsave(&np->lock, flags);
 			/* disable interrupts on the nic */
 			writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
 			pci_push(base);
@@ -2527,7 +2528,7 @@
 				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
 			}
 			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
-			spin_unlock_irq(&np->lock);
+			spin_unlock_irqrestore(&np->lock, flags);
 			break;
 		}
 
@@ -2576,7 +2577,7 @@
 #endif
 
 #ifdef CONFIG_FORCEDETH_NAPI
-static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t nv_nic_irq_rx(int foo, void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	u8 __iomem *base = get_hwbase(dev);
@@ -2594,13 +2595,14 @@
 	return IRQ_HANDLED;
 }
 #else
-static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t nv_nic_irq_rx(int foo, void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	u32 events;
 	int i;
+	unsigned long flags;
 
 	dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name);
 
@@ -2614,14 +2616,14 @@
 
 		nv_rx_process(dev, dev->weight);
 		if (nv_alloc_rx(dev)) {
-			spin_lock_irq(&np->lock);
+			spin_lock_irqsave(&np->lock, flags);
 			if (!np->in_shutdown)
 				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
-			spin_unlock_irq(&np->lock);
+			spin_unlock_irqrestore(&np->lock, flags);
 		}
 
 		if (i > max_interrupt_work) {
-			spin_lock_irq(&np->lock);
+			spin_lock_irqsave(&np->lock, flags);
 			/* disable interrupts on the nic */
 			writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
 			pci_push(base);
@@ -2631,7 +2633,7 @@
 				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
 			}
 			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
-			spin_unlock_irq(&np->lock);
+			spin_unlock_irqrestore(&np->lock, flags);
 			break;
 		}
 	}
@@ -2641,13 +2643,14 @@
 }
 #endif
 
-static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t nv_nic_irq_other(int foo, void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	u32 events;
 	int i;
+	unsigned long flags;
 
 	dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name);
 
@@ -2660,14 +2663,14 @@
 			break;
 
 		if (events & NVREG_IRQ_LINK) {
-			spin_lock_irq(&np->lock);
+			spin_lock_irqsave(&np->lock, flags);
 			nv_link_irq(dev);
-			spin_unlock_irq(&np->lock);
+			spin_unlock_irqrestore(&np->lock, flags);
 		}
 		if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
-			spin_lock_irq(&np->lock);
+			spin_lock_irqsave(&np->lock, flags);
 			nv_linkchange(dev);
-			spin_unlock_irq(&np->lock);
+			spin_unlock_irqrestore(&np->lock, flags);
 			np->link_timeout = jiffies + LINK_TIMEOUT;
 		}
 		if (events & (NVREG_IRQ_UNKNOWN)) {
@@ -2675,7 +2678,7 @@
 						dev->name, events);
 		}
 		if (i > max_interrupt_work) {
-			spin_lock_irq(&np->lock);
+			spin_lock_irqsave(&np->lock, flags);
 			/* disable interrupts on the nic */
 			writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
 			pci_push(base);
@@ -2685,7 +2688,7 @@
 				mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
 			}
 			printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
-			spin_unlock_irq(&np->lock);
+			spin_unlock_irqrestore(&np->lock, flags);
 			break;
 		}
 
@@ -2695,7 +2698,7 @@
 	return IRQ_RETVAL(i);
 }
 
-static irqreturn_t nv_nic_irq_test(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t nv_nic_irq_test(int foo, void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct fe_priv *np = netdev_priv(dev);
@@ -2905,22 +2908,22 @@
 	pci_push(base);
 
 	if (!using_multi_irqs(dev)) {
-		nv_nic_irq(0, dev, NULL);
+		nv_nic_irq(0, dev);
 		if (np->msi_flags & NV_MSI_X_ENABLED)
 			enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
 		else
 			enable_irq_lockdep(dev->irq);
 	} else {
 		if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
-			nv_nic_irq_rx(0, dev, NULL);
+			nv_nic_irq_rx(0, dev);
 			enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
 		}
 		if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
-			nv_nic_irq_tx(0, dev, NULL);
+			nv_nic_irq_tx(0, dev);
 			enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
 		}
 		if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
-			nv_nic_irq_other(0, dev, NULL);
+			nv_nic_irq_other(0, dev);
 			enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
 		}
 	}
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index d018706..cb39587 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -441,7 +441,7 @@
  * This is called from the MPC core interrupt.
  */
 static irqreturn_t
-fs_enet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+fs_enet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct fs_enet_private *fep;
@@ -667,7 +667,7 @@
 }
 
 static int fs_request_irq(struct net_device *dev, int irq, const char *name,
-		irqreturn_t (*irqf)(int irq, void *dev_id, struct pt_regs *regs))
+		irq_handler_t irqf)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 280b114..a06d8d1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -119,9 +119,9 @@
 static struct net_device_stats *gfar_get_stats(struct net_device *dev);
 static int gfar_set_mac_address(struct net_device *dev);
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
-static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t gfar_error(int irq, void *dev_id);
+static irqreturn_t gfar_transmit(int irq, void *dev_id);
+static irqreturn_t gfar_interrupt(int irq, void *dev_id);
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
@@ -1173,7 +1173,7 @@
 }
 
 /* Interrupt Handler for Transmit complete */
-static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gfar_transmit(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct gfar_private *priv = netdev_priv(dev);
@@ -1305,7 +1305,7 @@
 	}
 }
 
-irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t gfar_receive(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct gfar_private *priv = netdev_priv(dev);
@@ -1537,7 +1537,7 @@
 #endif
 
 /* The interrupt handler for devices with one interrupt */
-static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gfar_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct gfar_private *priv = netdev_priv(dev);
@@ -1550,11 +1550,11 @@
 
 	/* Check for reception */
 	if ((events & IEVENT_RXF0) || (events & IEVENT_RXB0))
-		gfar_receive(irq, dev_id, regs);
+		gfar_receive(irq, dev_id);
 
 	/* Check for transmit completion */
 	if ((events & IEVENT_TXF) || (events & IEVENT_TXB))
-		gfar_transmit(irq, dev_id, regs);
+		gfar_transmit(irq, dev_id);
 
 	/* Update error statistics */
 	if (events & IEVENT_TXE) {
@@ -1578,7 +1578,7 @@
 		priv->stats.rx_errors++;
 		priv->extra_stats.rx_bsy++;
 
-		gfar_receive(irq, dev_id, regs);
+		gfar_receive(irq, dev_id);
 
 #ifndef CONFIG_GFAR_NAPI
 		/* Clear the halt bit in RSTAT */
@@ -1857,7 +1857,7 @@
 }
 
 /* GFAR error interrupt handler */
-static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gfar_error(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct gfar_private *priv = netdev_priv(dev);
@@ -1898,7 +1898,7 @@
 		priv->stats.rx_errors++;
 		priv->extra_stats.rx_bsy++;
 
-		gfar_receive(irq, dev_id, regs);
+		gfar_receive(irq, dev_id);
 
 #ifndef CONFIG_GFAR_NAPI
 		/* Clear the halt bit in RSTAT */
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index c35d47c..9e81a50 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -754,7 +754,7 @@
 	out_be32(addr, val);
 }
 
-extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t gfar_receive(int irq, void *dev_id);
 extern int startup_gfar(struct net_device *dev);
 extern void stop_gfar(struct net_device *dev);
 extern void gfar_halt(struct net_device *dev);
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 5c89ae7..c3c0d67 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -556,7 +556,7 @@
 static void hamachi_tx_timeout(struct net_device *dev);
 static void hamachi_init_ring(struct net_device *dev);
 static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t hamachi_interrupt(int irq, void *dev_instance);
 static int hamachi_rx(struct net_device *dev);
 static inline int hamachi_tx(struct net_device *dev);
 static void hamachi_error(struct net_device *dev, int intr_status);
@@ -1376,7 +1376,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t hamachi_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct hamachi_private *hmp = netdev_priv(dev);
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 9220de9..1ed9ccc 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -323,7 +323,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-static void epp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void epp_interrupt(int irq, void *dev_id)
 {
 }
 
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 77411a0..5930aeb 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -270,7 +270,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void par96_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = netdev_priv(dev);
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 55906c7..59214e7 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -279,7 +279,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static irqreturn_t ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ser12_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = netdev_priv(dev);
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index de95de8..3bcc57a 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -373,7 +373,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static irqreturn_t ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ser12_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = netdev_priv(dev);
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index c9a46b8..0f8b9af 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -249,7 +249,7 @@
 static inline unsigned char random(void);
 
 static inline void z8530_isr(struct scc_info *info);
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t scc_isr(int irq, void *dev_id);
 static void rx_isr(struct scc_priv *priv);
 static void special_condition(struct scc_priv *priv, int rc);
 static void rx_bh(void *arg);
@@ -1142,7 +1142,7 @@
 }
 
 
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t scc_isr(int irq, void *dev_id)
 {
 	struct scc_info *info = dev_id;
 
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index df4b681..ec9b6d9 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -200,7 +200,7 @@
 
 static void init_channel(struct scc_channel *scc);
 static void scc_key_trx (struct scc_channel *scc, char tx);
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t scc_isr(int irq, void *dev_id);
 static void scc_init_timer(struct scc_channel *scc);
 
 static int scc_net_alloc(const char *name, struct scc_channel *scc);
@@ -626,7 +626,7 @@
 
 #define SCC_IRQTIMEOUT 30000
 
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t scc_isr(int irq, void *dev_id)
 {
 	unsigned char vector;	
 	struct scc_channel *scc;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index f98f577..3c4455b 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -702,7 +702,7 @@
 * ISR routine
 ************************************************************************************/
 
-static irqreturn_t yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t yam_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev;
 	struct yam_port *yp;
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index ae8ad4f..844c136 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -249,7 +249,7 @@
 static void hp100_update_stats(struct net_device *dev);
 static void hp100_clear_stats(struct hp100_private *lp, int ioaddr);
 static void hp100_set_multicast_list(struct net_device *dev);
-static irqreturn_t hp100_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t hp100_interrupt(int irq, void *dev_id);
 static void hp100_start_interface(struct net_device *dev);
 static void hp100_stop_interface(struct net_device *dev);
 static void hp100_load_eeprom(struct net_device *dev, u_short ioaddr);
@@ -2187,7 +2187,7 @@
  *  hardware interrupt handling
  */
 
-static irqreturn_t hp100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hp100_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct hp100_private *lp = netdev_priv(dev);
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index d52e3bd..ffeafb2 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -184,7 +184,7 @@
 	"tx_errors"
 };
 
-static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t emac_irq(int irq, void *dev_instance);
 static void emac_clean_tx_ring(struct ocp_enet_private *dev);
 
 static inline int emac_phy_supports_gige(int phy_mode)
@@ -1515,7 +1515,7 @@
 }
 
 /* Hard IRQ */
-static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t emac_irq(int irq, void *dev_instance)
 {
 	struct ocp_enet_private *dev = dev_instance;
 	struct emac_regs __iomem *p = dev->emacp;
diff --git a/drivers/net/ibm_emac/ibm_emac_debug.c b/drivers/net/ibm_emac/ibm_emac_debug.c
index c364590..92f970d 100644
--- a/drivers/net/ibm_emac/ibm_emac_debug.c
+++ b/drivers/net/ibm_emac/ibm_emac_debug.c
@@ -179,8 +179,7 @@
 }
 
 #if defined(CONFIG_MAGIC_SYSRQ)
-static void emac_sysrq_handler(int key, struct pt_regs *pt_regs,
-			       struct tty_struct *tty)
+static void emac_sysrq_handler(int key, struct tty_struct *tty)
 {
 	emac_dbg_dump_all();
 }
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index af50e7b..6c0f071 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -168,7 +168,7 @@
 	MAL_DBG2("%d: disable_irq" NL, mal->def->index);
 }
 
-static irqreturn_t mal_serr(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t mal_serr(int irq, void *dev_instance)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
 	u32 esr = get_mal_dcrn(mal, MAL_ESR);
@@ -216,7 +216,7 @@
 		MAL_DBG2("%d: already in poll" NL, mal->def->index);
 }
 
-static irqreturn_t mal_txeob(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t mal_txeob(int irq, void *dev_instance)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
 	u32 r = get_mal_dcrn(mal, MAL_TXEOBISR);
@@ -226,7 +226,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mal_rxeob(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t mal_rxeob(int irq, void *dev_instance)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
 	u32 r = get_mal_dcrn(mal, MAL_RXEOBISR);
@@ -236,7 +236,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mal_txde(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t mal_txde(int irq, void *dev_instance)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
 	u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);
@@ -252,7 +252,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mal_rxde(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t mal_rxde(int irq, void *dev_instance)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
 	struct list_head *l;
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 2a95d72..3f946c8 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -705,7 +705,7 @@
 
 /* general interrupt entry */
 
-static irqreturn_t irq_handler(int irq, void *device, struct pt_regs *regs)
+static irqreturn_t irq_handler(int irq, void *device)
 {
 	struct net_device *dev = (struct net_device *) device;
 	u16 ival;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 767203d..44c9f99 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -93,7 +93,7 @@
 static void ibmveth_proc_unregister_driver(void);
 static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
-static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance);
 static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
 static struct kobj_type ktype_veth_pool;
 
@@ -212,7 +212,8 @@
 			break;
 		}
 
-		free_index = pool->consumer_index++ % pool->size;
+		free_index = pool->consumer_index;
+		pool->consumer_index = (pool->consumer_index + 1) % pool->size;
 		index = pool->free_map[free_index];
 
 		ibmveth_assert(index != IBM_VETH_INVALID_MAP);
@@ -238,7 +239,10 @@
 		if(lpar_rc != H_SUCCESS) {
 			pool->free_map[free_index] = index;
 			pool->skbuff[index] = NULL;
-			pool->consumer_index--;
+			if (pool->consumer_index == 0)
+				pool->consumer_index = pool->size - 1;
+			else
+				pool->consumer_index--;
 			dma_unmap_single(&adapter->vdev->dev,
 					pool->dma_addr[index], pool->buff_size,
 					DMA_FROM_DEVICE);
@@ -325,7 +329,10 @@
 			 adapter->rx_buff_pool[pool].buff_size,
 			 DMA_FROM_DEVICE);
 
-	free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size;
+	free_index = adapter->rx_buff_pool[pool].producer_index;
+	adapter->rx_buff_pool[pool].producer_index
+		= (adapter->rx_buff_pool[pool].producer_index + 1)
+		% adapter->rx_buff_pool[pool].size;
 	adapter->rx_buff_pool[pool].free_map[free_index] = index;
 
 	mb();
@@ -437,6 +444,31 @@
 						 &adapter->rx_buff_pool[i]);
 }
 
+static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
+        union ibmveth_buf_desc rxq_desc, u64 mac_address)
+{
+	int rc, try_again = 1;
+
+	/* After a kexec the adapter will still be open, so our attempt to
+	* open it will fail. So if we get a failure we free the adapter and
+	* try again, but only once. */
+retry:
+	rc = h_register_logical_lan(adapter->vdev->unit_address,
+				    adapter->buffer_list_dma, rxq_desc.desc,
+				    adapter->filter_list_dma, mac_address);
+
+	if (rc != H_SUCCESS && try_again) {
+		do {
+			rc = h_free_logical_lan(adapter->vdev->unit_address);
+		} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
+
+		try_again = 0;
+		goto retry;
+	}
+
+	return rc;
+}
+
 static int ibmveth_open(struct net_device *netdev)
 {
 	struct ibmveth_adapter *adapter = netdev->priv;
@@ -502,12 +534,9 @@
 	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
 	ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
 
+	h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
 
-	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
-					 adapter->buffer_list_dma,
-					 rxq_desc.desc,
-					 adapter->filter_list_dma,
-					 mac_address);
+	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
 
 	if(lpar_rc != H_SUCCESS) {
 		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
@@ -543,7 +572,7 @@
 	}
 
 	ibmveth_debug_printk("initial replenish cycle\n");
-	ibmveth_interrupt(netdev->irq, netdev, NULL);
+	ibmveth_interrupt(netdev->irq, netdev);
 
 	netif_start_queue(netdev);
 
@@ -816,7 +845,7 @@
 	return 0;
 }
 
-static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *netdev = dev_instance;
 	struct ibmveth_adapter *adapter = netdev->priv;
@@ -905,6 +934,14 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ibmveth_poll_controller(struct net_device *dev)
+{
+	ibmveth_replenish_task(dev->priv);
+	ibmveth_interrupt(dev->irq, dev);
+}
+#endif
+
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
 	int rc, i;
@@ -977,6 +1014,9 @@
 	netdev->ethtool_ops           = &netdev_ethtool_ops;
 	netdev->change_mtu         = ibmveth_change_mtu;
 	SET_NETDEV_DEV(netdev, &dev->dev);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = ibmveth_poll_controller;
+#endif
  	netdev->features |= NETIF_F_LLTX;
 	spin_lock_init(&adapter->stats_lock);
 
@@ -1132,7 +1172,9 @@
 {
 	struct proc_dir_entry *entry;
 	if (ibmveth_proc_dir) {
-		entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir);
+		char u_addr[10];
+		sprintf(u_addr, "%x", adapter->vdev->unit_address);
+		entry = create_proc_entry(u_addr, S_IFREG, ibmveth_proc_dir);
 		if (!entry) {
 			ibmveth_error_printk("Cannot create adapter proc entry");
 		} else {
@@ -1147,7 +1189,9 @@
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
 {
 	if (ibmveth_proc_dir) {
-		remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir);
+		char u_addr[10];
+		sprintf(u_addr, "%x", adapter->vdev->unit_address);
+		remove_proc_entry(u_addr, ibmveth_proc_dir);
 	}
 }
 
@@ -1261,7 +1305,7 @@
 	}
 
 	/* kick the interrupt handler to allocate/deallocate pools */
-	ibmveth_interrupt(netdev->irq, netdev, NULL);
+	ibmveth_interrupt(netdev->irq, netdev);
 	return count;
 }
 
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 8765023..f56b00e 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -750,7 +750,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread.  */
-static irqreturn_t ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
+static irqreturn_t ioc3_interrupt(int irq, void *_dev)
 {
 	struct net_device *dev = (struct net_device *)_dev;
 	struct ioc3_private *ip = netdev_priv(dev);
@@ -1017,7 +1017,7 @@
 	struct ioc3_private *ip = netdev_priv(dev);
 	struct ioc3 *ioc3 = ip->regs;
 
-	del_timer(&ip->ioc3_timer);		/* Kill if running	*/
+	del_timer_sync(&ip->ioc3_timer);	/* Kill if running	*/
 
 	ioc3_w_emcr(EMCR_RST);			/* Reset		*/
 	(void) ioc3_r_emcr();			/* Flush WB		*/
@@ -1081,7 +1081,7 @@
 {
 	struct ioc3_private *ip = netdev_priv(dev);
 
-	del_timer(&ip->ioc3_timer);
+	del_timer_sync(&ip->ioc3_timer);
 
 	netif_stop_queue(dev);
 
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 68d4c41..cebf8c3 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -660,22 +660,15 @@
  *    An interrupt from the chip has arrived. Time to do some work
  *
  */
-static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct ali_ircc_cb *self;
 	int ret;
 		
 	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
 		
- 	if (!dev) {
-		IRDA_WARNING("%s: irq %d for unknown device.\n",
-			     ALI_IRCC_DRIVER_NAME, irq);
-		return IRQ_NONE;
-	}	
-	
-	self = (struct ali_ircc_cb *) dev->priv;
+	self = dev->priv;
 	
 	spin_lock(&self->lock);
 	
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index 7b2b413..37914dc 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -51,7 +51,7 @@
 static int au1k_irda_stop(struct net_device *dev);
 static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
 static int au1k_irda_rx(struct net_device *);
-static void au1k_irda_interrupt(int, void *, struct pt_regs *);
+static void au1k_irda_interrupt(int, void *);
 static void au1k_tx_timeout(struct net_device *);
 static struct net_device_stats *au1k_irda_stats(struct net_device *);
 static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
@@ -627,7 +627,7 @@
 }
 
 
-void au1k_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+void au1k_irda_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 33c07d5..16620bd 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -657,12 +657,6 @@
   return xbofs;
 }
 
-static int toshoboe_invalid_dev(int irq)
-{
-  printk (KERN_WARNING DRIVER_NAME ": irq %d for unknown device.\n", irq);
-  return 1;
-}
-
 #ifdef USE_PROBE
 /***********************************************************************/
 /* Probe code */
@@ -709,14 +703,11 @@
 }
 
 static irqreturn_t
-toshoboe_probeinterrupt (int irq, void *dev_id, struct pt_regs *regs)
+toshoboe_probeinterrupt (int irq, void *dev_id)
 {
-  struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
+  struct toshoboe_cb *self = dev_id;
   __u8 irqstat;
 
-  if (self == NULL && toshoboe_invalid_dev(irq))
-    return IRQ_NONE;
-
   irqstat = INB (OBOE_ISR);
 
 /* was it us */
@@ -1161,15 +1152,12 @@
 
 /*interrupt handler */
 static irqreturn_t
-toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+toshoboe_interrupt (int irq, void *dev_id)
 {
-  struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
+  struct toshoboe_cb *self = dev_id;
   __u8 irqstat;
   struct sk_buff *skb = NULL;
 
-  if (self == NULL && toshoboe_invalid_dev(irq))
-    return IRQ_NONE;
-
   irqstat = INB (OBOE_ISR);
 
 /* was it us */
@@ -1357,13 +1345,11 @@
 {
   struct toshoboe_cb *self;
   unsigned long flags;
+  int rc;
 
   IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
 
-  IRDA_ASSERT (dev != NULL, return -1; );
-  self = (struct toshoboe_cb *) dev->priv;
-
-  IRDA_ASSERT (self != NULL, return 0; );
+  self = netdev_priv(dev);
 
   if (self->async)
     return -EBUSY;
@@ -1371,11 +1357,10 @@
   if (self->stopped)
     return 0;
 
-  if (request_irq (self->io.irq, toshoboe_interrupt,
-                   IRQF_SHARED | IRQF_DISABLED, dev->name, (void *) self))
-    {
-      return -EAGAIN;
-    }
+  rc = request_irq (self->io.irq, toshoboe_interrupt,
+                    IRQF_SHARED | IRQF_DISABLED, dev->name, self);
+  if (rc)
+  	return rc;
 
   spin_lock_irqsave(&self->spinlock, flags);
   toshoboe_startchip (self);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 383cef1..14bda76 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -114,9 +114,9 @@
 static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int irda_usb_open(struct irda_usb_cb *self);
 static void irda_usb_close(struct irda_usb_cb *self);
-static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs);
-static void write_bulk_callback(struct urb *urb, struct pt_regs *regs);
-static void irda_usb_receive(struct urb *urb, struct pt_regs *regs);
+static void speed_bulk_callback(struct urb *urb);
+static void write_bulk_callback(struct urb *urb);
+static void irda_usb_receive(struct urb *urb);
 static void irda_usb_rx_defer_expired(unsigned long data);
 static int irda_usb_net_open(struct net_device *dev);
 static int irda_usb_net_close(struct net_device *dev);
@@ -343,7 +343,7 @@
  * Speed URB callback
  * Now, we can only get called for the speed URB.
  */
-static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void speed_bulk_callback(struct urb *urb)
 {
 	struct irda_usb_cb *self = urb->context;
 	
@@ -562,7 +562,7 @@
 /*
  * Note : this function will be called only for tx_urb...
  */
-static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void write_bulk_callback(struct urb *urb)
 {
 	unsigned long flags;
 	struct sk_buff *skb = urb->context;
@@ -809,7 +809,7 @@
  *     Called by the USB subsystem when a frame has been received
  *
  */
-static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
+static void irda_usb_receive(struct urb *urb)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
 	struct irda_usb_cb *self; 
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index ba4f3eb..654a68b 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -87,8 +87,7 @@
 static int irport_change_speed_complete(struct irda_task *task);
 static void irport_timeout(struct net_device *dev);
 
-static irqreturn_t irport_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs);
+static irqreturn_t irport_interrupt(int irq, void *dev_id);
 static int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static void irport_change_speed(void *priv, __u32 speed);
 static int irport_net_open(struct net_device *dev);
@@ -761,25 +760,20 @@
 }
 
 /*
- * Function irport_interrupt (irq, dev_id, regs)
+ * Function irport_interrupt (irq, dev_id)
  *
  *    Interrupt handler
  */
-static irqreturn_t irport_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs) 
+static irqreturn_t irport_interrupt(int irq, void *dev_id) 
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct irport_cb *self;
 	int boguscount = 0;
 	int iobase;
 	int iir, lsr;
 	int handled = 0;
 
-	if (!dev) {
-		IRDA_WARNING("%s() irq %d for unknown device.\n", __FUNCTION__, irq);
-		return IRQ_NONE;
-	}
-	self = (struct irport_cb *) dev->priv;
+	self = dev->priv;
 
 	spin_lock(&self->lock);
 
diff --git a/drivers/net/irda/irport.h b/drivers/net/irda/irport.h
index fc89c8c..3f46b84 100644
--- a/drivers/net/irda/irport.h
+++ b/drivers/net/irda/irport.h
@@ -74,7 +74,7 @@
 	/* For piggyback drivers */
 	void *priv;                
 	void (*change_speed)(void *priv, __u32 speed);
-	int (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
+	irqreturn_t (*interrupt)(int irq, void *dev_id);
 };
 
 #endif /* IRPORT_H */
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 415ba8d..b32c52e 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -764,7 +764,7 @@
 }
 
 /* Receive callback function.  */
-static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs)
+static void mcs_receive_irq(struct urb *urb)
 {
 	__u8 *bytes;
 	struct mcs_cb *mcs = urb->context;
@@ -813,7 +813,7 @@
 }
 
 /* Transmit callback funtion.  */
-static void mcs_send_irq(struct urb *urb, struct pt_regs *regs)
+static void mcs_send_irq(struct urb *urb)
 {
 	struct mcs_cb *mcs = urb->context;
 	struct net_device *ndev = mcs->netdev;
diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h
index 1a723d7..b18148c 100644
--- a/drivers/net/irda/mcs7780.h
+++ b/drivers/net/irda/mcs7780.h
@@ -156,8 +156,8 @@
 static int mcs_net_open(struct net_device *netdev);
 static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev);
 
-static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs);
-static void mcs_send_irq(struct urb *urb, struct pt_regs *regs);
+static void mcs_receive_irq(struct urb *urb);
+static void mcs_send_irq(struct urb *urb);
 static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev);
 
 static int mcs_probe(struct usb_interface *intf,
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 7185a4e..29b5ccd 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -2066,20 +2066,14 @@
  *    An interrupt from the chip has arrived. Time to do some work
  *
  */
-static irqreturn_t nsc_ircc_interrupt(int irq, void *dev_id,
-				struct pt_regs *regs)
+static irqreturn_t nsc_ircc_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct nsc_ircc_cb *self;
 	__u8 bsr, eir;
 	int iobase;
 
-	if (!dev) {
-		IRDA_WARNING("%s: irq %d for unknown device.\n",
-			     driver_name, irq);
-		return IRQ_NONE;
-	}
-	self = (struct nsc_ircc_cb *) dev->priv;
+	self = dev->priv;
 
 	spin_lock(&self->lock);	
 
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index afb19e8..f9a1c88 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -199,7 +199,7 @@
 }
 
 /* SIR interrupt service routine. */
-static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct pxa_irda *si = netdev_priv(dev);
@@ -281,7 +281,7 @@
 }
 
 /* FIR Receive DMA interrupt handler */
-static void pxa_irda_fir_dma_rx_irq(int channel, void *data, struct pt_regs *regs)
+static void pxa_irda_fir_dma_rx_irq(int channel, void *data)
 {
 	int dcsr = DCSR(channel);
 
@@ -291,7 +291,7 @@
 }
 
 /* FIR Transmit DMA interrupt handler */
-static void pxa_irda_fir_dma_tx_irq(int channel, void *data, struct pt_regs *regs)
+static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
 {
 	struct net_device *dev = data;
 	struct pxa_irda *si = netdev_priv(dev);
@@ -388,7 +388,7 @@
 }
 
 /* FIR interrupt handler */
-static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct pxa_irda *si = netdev_priv(dev);
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 8d5a288..937372d 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -579,7 +579,7 @@
 	sa1100_irda_rx_dma_start(si);
 }
 
-static irqreturn_t sa1100_irda_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	if (IS_FIR(((struct sa1100_irda *)dev->priv)))
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 22358ff..31c6233 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -196,7 +196,7 @@
 static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self);
 static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed);
 static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, u32 speed);
-static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id);
 static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev);
 static void smsc_ircc_sir_start(struct smsc_ircc_cb *self);
 #if SMSC_IRCC2_C_SIR_STOP
@@ -1455,7 +1455,7 @@
  *    An interrupt from the chip has arrived. Time to do some work
  *
  */
-static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct smsc_ircc_cb *self;
@@ -1520,7 +1520,7 @@
 }
 
 /*
- * Function irport_interrupt_sir (irq, dev_id, regs)
+ * Function irport_interrupt_sir (irq, dev_id)
  *
  *    Interrupt handler for SIR modes
  */
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 12103c9..be8a66e 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -804,7 +804,7 @@
  * Wakes up every ms (usb round trip) with wrapped 
  * data.
  */
-static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs)
+static void stir_rcv_irq(struct urb *urb)
 {
 	struct stir_cb *stir = urb->context;
 	int err;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index d916e12..c3ed9b3 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -93,8 +93,7 @@
 				  struct net_device *dev);
 static void via_hw_init(struct via_ircc_cb *self);
 static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 baud);
-static irqreturn_t via_ircc_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs);
+static irqreturn_t via_ircc_interrupt(int irq, void *dev_id);
 static int via_ircc_is_receiving(struct via_ircc_cb *self);
 static int via_ircc_read_dongle_id(int iobase);
 
@@ -1345,13 +1344,12 @@
 
 
 /*
- * Function via_ircc_interrupt (irq, dev_id, regs)
+ * Function via_ircc_interrupt (irq, dev_id)
  *
  *    An interrupt from the chip has arrived. Time to do some work
  *
  */
-static irqreturn_t via_ircc_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t via_ircc_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct via_ircc_cb *self;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 92d646c..18c6819 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -1455,8 +1455,7 @@
 
 /********************************************************/
 
-static irqreturn_t vlsi_interrupt(int irq, void *dev_instance,
-					struct pt_regs *regs)
+static irqreturn_t vlsi_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *ndev = dev_instance;
 	vlsi_irda_dev_t *idev = ndev->priv;
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 7de1afde..4212657 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -1111,20 +1111,14 @@
  *    An interrupt from the chip has arrived. Time to do some work
  *
  */
-static irqreturn_t w83977af_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t w83977af_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct w83977af_ir *self;
 	__u8 set, icr, isr;
 	int iobase;
 
-	if (!dev) {
-		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
-			driver_name, irq);
-		return IRQ_NONE;
-	}
-	self = (struct w83977af_ir *) dev->priv;
+	self = dev->priv;
 
 	iobase = self->io.fir_base;
 
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index 984c31d..0343f12 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -107,7 +107,7 @@
 static int	netcard_probe1(struct net_device *dev, int ioaddr);
 static int	net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void	net_rx(struct net_device *dev);
 static int	net_close(struct net_device *dev);
 static struct	net_device_stats *net_get_stats(struct net_device *dev);
@@ -504,7 +504,7 @@
  * The typical workload of the driver:
  * Handle the network interface interrupts.
  */
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *np;
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 41b1d08..2284e2c 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -586,7 +586,7 @@
 	};
 }
 
-static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
+static void veth_handle_event(struct HvLpEvent *event)
 {
 	struct veth_lpevent *veth_event = (struct veth_lpevent *)event;
 
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index cfde7c2..e09f575 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -93,7 +93,7 @@
 static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
 static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
 static int ixgb_set_mac(struct net_device *netdev, void *p);
-static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
+static irqreturn_t ixgb_intr(int irq, void *data);
 static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
 
 #ifdef CONFIG_IXGB_NAPI
@@ -1687,11 +1687,10 @@
  * ixgb_intr - Interrupt Handler
  * @irq: interrupt number
  * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
  **/
 
 static irqreturn_t
-ixgb_intr(int irq, void *data, struct pt_regs *regs)
+ixgb_intr(int irq, void *data)
 {
 	struct net_device *netdev = data;
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
@@ -2213,7 +2212,7 @@
 	struct ixgb_adapter *adapter = netdev_priv(dev);
 
 	disable_irq(adapter->pdev->irq);
-	ixgb_intr(adapter->pdev->irq, dev, NULL);
+	ixgb_intr(adapter->pdev->irq, dev);
 	enable_irq(adapter->pdev->irq);
 }
 #endif
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 6eeb965..a4eccb1 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -188,7 +188,7 @@
 	}
 }
 
-static irqreturn_t ixpdev_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
 {
 	u32 status;
 
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index f349e88..6efbd49 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -301,7 +301,7 @@
 static void lance_init_ring(struct net_device *dev, gfp_t mode);
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lance_rx(struct net_device *dev);
-static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t lance_interrupt(int irq, void *dev_id);
 static int lance_close(struct net_device *dev);
 static struct net_device_stats *lance_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -1012,19 +1012,13 @@
 }
 
 /* The LANCE interrupt handler. */
-static irqreturn_t
-lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct lance_private *lp;
 	int csr0, ioaddr, boguscnt=10;
 	int must_restart;
 
-	if (dev == NULL) {
-		printk ("lance_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
 	ioaddr = dev->base_addr;
 	lp = dev->priv;
 
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index da1eede..f4d815b 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -403,7 +403,7 @@
 
 static int i596_open(struct net_device *dev);
 static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
 static int i596_close(struct net_device *dev);
 static struct net_device_stats *i596_get_stats(struct net_device *dev);
 static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
@@ -527,7 +527,7 @@
 
 
 #if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
+static void i596_error(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
@@ -1252,12 +1252,12 @@
 static void i596_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	i596_interrupt(dev->irq, dev, NULL);
+	i596_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
 
-static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct i596_private *lp;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 4178b4b1..82c10de 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -58,7 +58,11 @@
 #include <linux/tcp.h>
 #include <linux/percpu.h>
 
-static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
+struct pcpu_lstats {
+	unsigned long packets;
+	unsigned long bytes;
+};
+static DEFINE_PER_CPU(struct pcpu_lstats, pcpu_lstats);
 
 #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
 
@@ -128,7 +132,7 @@
  */
 static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *lb_stats;
+	struct pcpu_lstats *lb_stats;
 
 	skb_orphan(skb);
 
@@ -149,16 +153,14 @@
 #endif
 	dev->last_rx = jiffies;
 
-	lb_stats = &per_cpu(loopback_stats, get_cpu());
-	lb_stats->rx_bytes += skb->len;
-	lb_stats->tx_bytes = lb_stats->rx_bytes;
-	lb_stats->rx_packets++;
-	lb_stats->tx_packets = lb_stats->rx_packets;
-	put_cpu();
+	/* it's OK to use __get_cpu_var() because BHs are off */
+	lb_stats = &__get_cpu_var(pcpu_lstats);
+	lb_stats->bytes += skb->len;
+	lb_stats->packets++;
 
 	netif_rx(skb);
 
-	return(0);
+	return 0;
 }
 
 static struct net_device_stats loopback_stats;
@@ -166,20 +168,21 @@
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
 	struct net_device_stats *stats = &loopback_stats;
+	unsigned long bytes = 0;
+	unsigned long packets = 0;
 	int i;
 
-	memset(stats, 0, sizeof(struct net_device_stats));
-
 	for_each_possible_cpu(i) {
-		struct net_device_stats *lb_stats;
+		const struct pcpu_lstats *lb_stats;
 
-		lb_stats = &per_cpu(loopback_stats, i);
-		stats->rx_bytes   += lb_stats->rx_bytes;
-		stats->tx_bytes   += lb_stats->tx_bytes;
-		stats->rx_packets += lb_stats->rx_packets;
-		stats->tx_packets += lb_stats->tx_packets;
+		lb_stats = &per_cpu(pcpu_lstats, i);
+		bytes   += lb_stats->bytes;
+		packets += lb_stats->packets;
 	}
-
+	stats->rx_packets = packets;
+	stats->tx_packets = packets;
+	stats->rx_bytes = bytes;
+	stats->tx_bytes = bytes;
 	return stats;
 }
 
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 0258aac..b833016 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -379,7 +379,7 @@
 
 static int i596_open(struct net_device *dev);
 static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
 static int i596_close(struct net_device *dev);
 static struct net_device_stats *i596_get_stats(struct net_device *dev);
 static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
@@ -1151,7 +1151,7 @@
 }
 
 static irqreturn_t
-i596_interrupt (int irq, void *dev_instance, struct pt_regs *regs) {
+i596_interrupt (int irq, void *dev_instance) {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct i596_private *lp;
 	unsigned short status, ack_cmd = 0;
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index 8472b71..e960138 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -129,7 +129,7 @@
 #endif
 static int net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void set_multicast_list(struct net_device *dev);
 static void net_rx(struct net_device *dev);
 static int net_close(struct net_device *dev);
@@ -431,7 +431,7 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 27c24ea..2907cfb 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -82,9 +82,9 @@
 static void mace_set_multicast(struct net_device *dev);
 static void mace_reset(struct net_device *dev);
 static int mace_set_address(struct net_device *dev, void *addr);
-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_interrupt(int irq, void *dev_id);
+static irqreturn_t mace_txdma_intr(int irq, void *dev_id);
+static irqreturn_t mace_rxdma_intr(int irq, void *dev_id);
 static void mace_set_timeout(struct net_device *dev);
 static void mace_tx_timeout(unsigned long data);
 static inline void dbdma_reset(volatile struct dbdma_regs __iomem *dma);
@@ -678,7 +678,7 @@
 	    printk(KERN_DEBUG "mace: jabbering transceiver\n");
 }
 
-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = (struct net_device *) dev_id;
     struct mace_data *mp = (struct mace_data *) dev->priv;
@@ -890,12 +890,12 @@
     spin_unlock_irqrestore(&mp->lock, flags);
 }
 
-static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_txdma_intr(int irq, void *dev_id)
 {
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
 {
     struct net_device *dev = (struct net_device *) dev_id;
     struct mace_data *mp = (struct mace_data *) dev->priv;
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 696d551..464e4a6 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -77,8 +77,8 @@
 static struct net_device_stats *mace_stats(struct net_device *dev);
 static void mace_set_multicast(struct net_device *dev);
 static int mace_set_address(struct net_device *dev, void *addr);
-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_interrupt(int irq, void *dev_id);
+static irqreturn_t mace_dma_intr(int irq, void *dev_id);
 static void mace_tx_timeout(struct net_device *dev);
 
 /* Bit-reverse one byte of an ethernet hardware address. */
@@ -573,7 +573,7 @@
  * Process the chip interrupt
  */
 
-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct mace_data *mp = (struct mace_data *) dev->priv;
@@ -645,7 +645,7 @@
  * The PSC has passed us a DMA interrupt event.
  */
 
-static irqreturn_t mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_dma_intr(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct mace_data *mp = (struct mace_data *) dev->priv;
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 55b1495..c1aa60b 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -92,7 +92,7 @@
 };
 
 static void meth_tx_timeout(struct net_device *dev);
-static irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs);
+static irqreturn_t meth_interrupt(int irq, void *dev_id);
 
 /* global, initialized in ip32-setup.c */
 char o2meth_eaddr[8]={0,0,0,0,0,0,0,0};
@@ -569,7 +569,7 @@
 /*
  * The typical interrupt entry point
  */
-static irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
+static irqreturn_t meth_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct meth_private *priv = (struct meth_private *) dev->priv;
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 07e58f4..c946998 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -116,8 +116,7 @@
 	return count;
 }
 
-static irqreturn_t
-mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 7f8e5ad..9997081 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -507,8 +507,7 @@
  * Output :	N/A
  */
 
-static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
-						struct pt_regs *regs)
+static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct mv643xx_private *mp = netdev_priv(dev);
@@ -1252,7 +1251,7 @@
 	/* wait for previous write to complete */
 	mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
 
-	mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
+	mv643xx_eth_int_handler(netdev->irq, netdev);
 
 	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
 }
@@ -2156,7 +2155,7 @@
 	for (offset = ETH_MIB_BAD_OCTETS_RECEIVED;
 			offset <= ETH_MIB_FRAMES_1024_TO_MAX_OCTETS;
 			offset += 4)
-		*(u32 *)((char *)p + offset) = read_mib(mp, offset);
+		*(u32 *)((char *)p + offset) += read_mib(mp, offset);
 
 	p->good_octets_sent += read_mib(mp, ETH_MIB_GOOD_OCTETS_SENT_LOW);
 	p->good_octets_sent +=
@@ -2165,7 +2164,7 @@
 	for (offset = ETH_MIB_GOOD_FRAMES_SENT;
 			offset <= ETH_MIB_LATE_COLLISION;
 			offset += 4)
-		*(u32 *)((char *)p + offset) = read_mib(mp, offset);
+		*(u32 *)((char *)p + offset) += read_mib(mp, offset);
 }
 
 /*
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 4330197..fdbb0d7 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1148,7 +1148,7 @@
 	return 1;
 }
 
-static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t myri10ge_intr(int irq, void *arg)
 {
 	struct myri10ge_priv *mgp = arg;
 	struct mcp_irq_data *stats = mgp->fw_stats;
diff --git a/drivers/net/myri_code.h b/drivers/net/myri_code.h
index e21ec9b..ba7b865 100644
--- a/drivers/net/myri_code.h
+++ b/drivers/net/myri_code.h
@@ -1,8 +1,8 @@
 /* This is the Myrinet MCP code for LANai4.x */
 /* Generated by  cat $MYRI_HOME/lib/lanai/mcp4.dat > myri_code4.h */
 
-static unsigned int lanai4_code_off = 0x0000; /* half-word offset */
-static unsigned char lanai4_code[76256] __initdata = {
+static unsigned int __devinitdata lanai4_code_off = 0x0000; /* half-word offset */
+static unsigned char __devinitdata lanai4_code[76256] = {
 0xF2,0x0E,
 0xFE,0x00, 0xC2,0x90, 0x00,0x00, 0x07,0x88, 0x00,0x08, 0xE0,0x01, 0x01,0x4C, 0x97,0x93,
 0xFF,0xFC, 0xE0,0x00, 0x00,0x14, 0x00,0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x92,0x93,
@@ -4774,8 +4774,8 @@
 
 /* This is the LANai data */
 
-static unsigned int lanai4_data_off = 0x94F0; /* half-word offset */
-static unsigned char lanai4_data[20472] __initdata;
+static unsigned int __devinitdata lanai4_data_off = 0x94F0; /* half-word offset */
+static unsigned char __devinitdata lanai4_data[20472];
 
 
 #ifdef SYMBOL_DEFINES_COMPILED
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index a925bc9..7747bfd 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -168,7 +168,7 @@
 	return 0;
 }
 
-static int myri_load_lanai(struct myri_eth *mp)
+static int __devinit myri_load_lanai(struct myri_eth *mp)
 {
 	struct net_device	*dev = mp->dev;
 	struct myri_shmem __iomem *shmem = mp->shmem;
@@ -536,7 +536,7 @@
 	}
 }
 
-static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t myri_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev		= (struct net_device *) dev_id;
 	struct myri_eth *mp		= (struct myri_eth *) dev->priv;
@@ -891,7 +891,7 @@
 }
 #endif
 
-static int __init myri_ether_init(struct sbus_dev *sdev)
+static int __devinit myri_ether_init(struct sbus_dev *sdev)
 {
 	static int num;
 	static unsigned version_printed;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index d7b241f..ffa0afd 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -623,7 +623,7 @@
 static void reinit_ring(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
 static void netdev_error(struct net_device *dev, int intr_status);
 static int natsemi_poll(struct net_device *dev, int *budget);
 static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do);
@@ -2088,7 +2088,7 @@
 
 /* The interrupt handler doesn't actually handle interrupts itself, it
  * schedules a NAPI poll if there is anything to do. */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
@@ -2373,7 +2373,7 @@
 static void natsemi_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	intr_handler(dev->irq, dev, NULL);
+	intr_handler(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index 30ed9a5..a53644f 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -176,7 +176,7 @@
 }
 
 static irqreturn_t
-netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+netx_eth_interrupt(int irq, void *dev_id)
 {
 	struct net_device *ndev = dev_id;
 	struct netx_eth_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 383c690..8be0d03 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -99,7 +99,7 @@
 static int	ni5010_probe1(struct net_device *dev, int ioaddr);
 static int	ni5010_open(struct net_device *dev);
 static int	ni5010_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ni5010_interrupt(int irq, void *dev_id);
 static void	ni5010_rx(struct net_device *dev);
 static void	ni5010_timeout(struct net_device *dev);
 static int	ni5010_close(struct net_device *dev);
@@ -468,7 +468,7 @@
  * The typical workload of the driver:
  * Handle the network interface interrupts.
  */
-static irqreturn_t ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ni5010_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct ni5010_local *lp;
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index e888923..26e42f6 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -195,7 +195,7 @@
 #define NI52_ADDR2 0x01
 
 static int     ni52_probe1(struct net_device *dev,int ioaddr);
-static irqreturn_t ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
+static irqreturn_t ni52_interrupt(int irq,void *dev_id);
 static int     ni52_open(struct net_device *dev);
 static int     ni52_close(struct net_device *dev);
 static int     ni52_send_packet(struct sk_buff *,struct net_device *);
@@ -837,7 +837,7 @@
  * Interrupt Handler ...
  */
 
-static irqreturn_t ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
+static irqreturn_t ni52_interrupt(int irq,void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	unsigned short stat;
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index fab3c859..340ad0d 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -248,7 +248,7 @@
 };
 
 static int  ni65_probe1(struct net_device *dev,int);
-static irqreturn_t ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
+static irqreturn_t ni65_interrupt(int irq, void * dev_id);
 static void ni65_recv_intr(struct net_device *dev,int);
 static void ni65_xmit_intr(struct net_device *dev,int);
 static int  ni65_open(struct net_device *dev);
@@ -871,7 +871,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t ni65_interrupt(int irq, void * dev_id)
 {
 	int csr0 = 0;
 	struct net_device *dev = dev_id;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index e10da1a..b0127c7 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1288,7 +1288,7 @@
 }
 
 static void ns83820_do_isr(struct net_device *ndev, u32 isr);
-static irqreturn_t ns83820_irq(int foo, void *data, struct pt_regs *regs)
+static irqreturn_t ns83820_irq(int foo, void *data)
 {
 	struct net_device *ndev = data;
 	struct ns83820 *dev = PRIV(ndev);
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 2687e74..00ca0fd 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -502,8 +502,7 @@
 static void netdrv_init_ring (struct net_device *dev);
 static int netdrv_start_xmit (struct sk_buff *skb,
 			       struct net_device *dev);
-static irqreturn_t netdrv_interrupt (int irq, void *dev_instance,
-			       struct pt_regs *regs);
+static irqreturn_t netdrv_interrupt (int irq, void *dev_instance);
 static int netdrv_close (struct net_device *dev);
 static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 static struct net_device_stats *netdrv_get_stats (struct net_device *dev);
@@ -1654,8 +1653,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t netdrv_interrupt (int irq, void *dev_instance,
-			       struct pt_regs *regs)
+static irqreturn_t netdrv_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct netdrv_private *tp = dev->priv;
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 2418cdb..0460099 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -238,7 +238,7 @@
 static void media_check(unsigned long arg);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev, int worklimit);
@@ -817,7 +817,7 @@
 }
 
 /* The EL3 interrupt handler. */
-static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el3_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct el3_private *lp = netdev_priv(dev);
@@ -927,7 +927,7 @@
 	if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
 		if (!lp->fast_poll)
 			printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-		el3_interrupt(dev->irq, lp, NULL);
+		el3_interrupt(dev->irq, lp);
 		lp->fast_poll = HZ;
 	}
 	if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index a0e2b01..231fa2c 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -151,7 +151,7 @@
 static int el3_config(struct net_device *dev, struct ifmap *map);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
@@ -645,7 +645,7 @@
 }
 
 /* The EL3 interrupt handler. */
-static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el3_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = (struct net_device *) dev_id;
     struct el3_private *lp = netdev_priv(dev);
@@ -748,7 +748,7 @@
 	(inb(ioaddr + EL3_TIMER) == 0xff)) {
 	if (!lp->fast_poll)
 	    printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
-	el3_interrupt(dev->irq, lp, NULL);
+	el3_interrupt(dev->irq, lp);
 	lp->fast_poll = HZ;
     }
     if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index a8891a9..5ddd574 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -92,7 +92,7 @@
 static int axnet_close(struct net_device *dev);
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static const struct ethtool_ops netdev_ethtool_ops;
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
 static void ei_watchdog(u_long arg);
 static void axnet_reset_8390(struct net_device *dev);
 
@@ -112,7 +112,7 @@
 static void AX88190_init(struct net_device *dev, int startp);
 static int ax_open(struct net_device *dev);
 static int ax_close(struct net_device *dev);
-static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ax_interrupt(int irq, void *dev_id);
 
 /*====================================================================*/
 
@@ -599,11 +599,11 @@
 
 /*====================================================================*/
 
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
 {
     struct net_device *dev = dev_id;
     PRIV(dev)->stale = 0;
-    return ax_interrupt(irq, dev_id, regs);
+    return ax_interrupt(irq, dev_id);
 }
 
 static void ei_watchdog(u_long arg)
@@ -621,7 +621,7 @@
     if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
 	if (!info->fast_poll)
 	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-	ei_irq_wrapper(dev->irq, dev, NULL);
+	ei_irq_wrapper(dev->irq, dev);
 	info->fast_poll = HZ;
     }
     if (info->fast_poll) {
@@ -1193,7 +1193,7 @@
  * needed.
  */
 
-static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ax_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	long e8390_base;
@@ -1201,14 +1201,8 @@
 	struct ei_device *ei_local;
     	int handled = 0;
 
-	if (dev == NULL) 
-	{
-		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-    
 	e8390_base = dev->base_addr;
-	ei_local = (struct ei_device *) netdev_priv(dev);
+	ei_local = netdev_priv(dev);
 
 	/*
 	 *	Protect the irq test too.
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index d682f30..65f6fdf 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -97,7 +97,7 @@
 static int fjn_open(struct net_device *dev);
 static int fjn_close(struct net_device *dev);
 static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t fjn_interrupt(int irq, void *dev_id);
 static void fjn_rx(struct net_device *dev);
 static void fjn_reset(struct net_device *dev);
 static struct net_device_stats *fjn_get_stats(struct net_device *dev);
@@ -733,7 +733,7 @@
 
 /*====================================================================*/
 
-static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fjn_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = dev_id;
     local_info_t *lp = netdev_priv(dev);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 7d5687e..e77110e 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -426,7 +426,7 @@
 static int mace_close(struct net_device *dev);
 static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void mace_tx_timeout(struct net_device *dev);
-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_interrupt(int irq, void *dev_id);
 static struct net_device_stats *mace_get_stats(struct net_device *dev);
 static int mace_rx(struct net_device *dev, unsigned char RxCnt);
 static void restore_multicast_list(struct net_device *dev);
@@ -1002,7 +1002,7 @@
 mace_interrupt
 	The interrupt handler.
 ---------------------------------------------------------------------------- */
-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
 {
   struct net_device *dev = (struct net_device *) dev_id;
   mace_private *lp = netdev_priv(dev);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index a09c228..0c00d18 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -109,7 +109,7 @@
 static int pcnet_close(struct net_device *dev);
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static const struct ethtool_ops netdev_ethtool_ops;
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
 static void ei_watchdog(u_long arg);
 static void pcnet_reset_8390(struct net_device *dev);
 static int set_config(struct net_device *dev, struct ifmap *map);
@@ -1071,11 +1071,11 @@
 
 /*====================================================================*/
 
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
 {
     struct net_device *dev = dev_id;
     pcnet_dev_t *info;
-    irqreturn_t ret = ei_interrupt(irq, dev_id, regs);
+    irqreturn_t ret = ei_interrupt(irq, dev_id);
 
     if (ret == IRQ_HANDLED) {
 	    info = PRIV(dev);
@@ -1100,7 +1100,7 @@
     if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
 	if (!info->fast_poll)
 	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-	ei_irq_wrapper(dev->irq, dev, NULL);
+	ei_irq_wrapper(dev->irq, dev);
 	info->fast_poll = HZ;
     }
     if (info->fast_poll) {
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index a2f3a0e..20fcc35 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -287,7 +287,7 @@
 static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void smc_tx_timeout(struct net_device *dev);
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t smc_interrupt(int irq, void *dev_id);
 static void smc_rx(struct net_device *dev);
 static struct net_device_stats *smc_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
@@ -1545,7 +1545,7 @@
 
 /*====================================================================*/
 
-static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smc_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = dev_id;
     struct smc_private *smc = netdev_priv(dev);
@@ -1966,7 +1966,7 @@
     if (smc->watchdog++ && ((i>>8) & i)) {
 	if (!smc->fast_poll)
 	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-	smc_interrupt(dev->irq, smc, NULL);
+	smc_interrupt(dev->irq, smc);
 	smc->fast_poll = HZ;
     }
     if (smc->fast_poll) {
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 62664c0..f3914f5 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -308,7 +308,7 @@
  * less on other parts of the kernel.
  */
 
-static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
 
 /****************
  * A linked list of "instances" of the device.  Each actual
@@ -1121,7 +1121,7 @@
  * This is the Interrupt service route.
  */
 static irqreturn_t
-xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+xirc2ps_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = (struct net_device *)dev_id;
     local_info_t *lp = netdev_priv(dev);
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index a43e242..36f9d98 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -304,7 +304,7 @@
 static int pcnet32_init_ring(struct net_device *);
 static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
 static void pcnet32_tx_timeout(struct net_device *dev);
-static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t pcnet32_interrupt(int, void *);
 static int pcnet32_close(struct net_device *);
 static struct net_device_stats *pcnet32_get_stats(struct net_device *);
 static void pcnet32_load_multicast(struct net_device *dev);
@@ -674,7 +674,7 @@
 static void pcnet32_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	pcnet32_interrupt(0, dev, NULL);
+	pcnet32_interrupt(0, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -2561,7 +2561,7 @@
 
 /* The PCNET32 interrupt handler. */
 static irqreturn_t
-pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+pcnet32_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct pcnet32_private *lp;
@@ -2569,13 +2569,6 @@
 	u16 csr0;
 	int boguscnt = max_interrupt_work;
 
-	if (!dev) {
-		if (pcnet32_debug & NETIF_MSG_INTR)
-			printk(KERN_DEBUG "%s(): irq %d for unknown device\n",
-			       __FUNCTION__, irq);
-		return IRQ_NONE;
-	}
-
 	ioaddr = dev->base_addr;
 	lp = dev->priv;
 
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f5aad77..3af9fcf 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -480,7 +480,7 @@
  * description: When a PHY interrupt occurs, the handler disables
  * interrupts, and schedules a work task to clear the interrupt.
  */
-static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs)
+static irqreturn_t phy_interrupt(int irq, void *phy_dat)
 {
 	struct phy_device *phydev = phy_dat;
 
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index d4f54e9..71afb27 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -143,7 +143,7 @@
 static void plip_timer_bh(struct net_device *dev);
 
 /* Interrupt handler */
-static void plip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void plip_interrupt(int irq, void *dev_id);
 
 /* Functions for DEV methods */
 static int plip_tx_packet(struct sk_buff *skb, struct net_device *dev);
@@ -385,7 +385,7 @@
 	struct net_local *nl = netdev_priv(dev);
 
 	if (!(atomic_read (&nl->kill_timer))) {
-		plip_interrupt (-1, dev, NULL);
+		plip_interrupt (-1, dev);
 
 		schedule_delayed_work(&nl->timer, 1);
 	}
@@ -902,18 +902,13 @@
 
 /* Handle the parallel port interrupts. */
 static void
-plip_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+plip_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *nl;
 	struct plip_local *rcv;
 	unsigned char c0;
 
-	if (dev == NULL) {
-		printk(KERN_DEBUG "plip_interrupt: irq %d for unknown device.\n", irq);
-		return;
-	}
-
 	nl = netdev_priv(dev);
 	rcv = &nl->rcv_data;
 
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 1574718..ec640f6 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1965,7 +1965,7 @@
 	return 1;
 }
 
-static irqreturn_t ql3xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
 {
 
 	struct net_device *ndev = dev_id;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 4c47c5b..d132fe7 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -214,6 +214,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8168), 0, 0, RTL_CFG_2 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8169), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK,	0x4300), 0, 0, RTL_CFG_0 },
+	{ PCI_DEVICE(0x1259,			0xc107), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(0x16ec,			0x0116), 0, 0, RTL_CFG_0 },
 	{ PCI_VENDOR_ID_LINKSYS,		0x1032,
 		PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
@@ -473,8 +474,7 @@
 
 static int rtl8169_open(struct net_device *dev);
 static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance,
-			      struct pt_regs *regs);
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
 static int rtl8169_init_ring(struct net_device *dev);
 static void rtl8169_hw_start(struct net_device *dev);
 static int rtl8169_close(struct net_device *dev);
@@ -1392,7 +1392,7 @@
 	struct pci_dev *pdev = tp->pci_dev;
 
 	disable_irq(pdev->irq);
-	rtl8169_interrupt(pdev->irq, dev, NULL);
+	rtl8169_interrupt(pdev->irq, dev);
 	enable_irq(pdev->irq);
 }
 #endif
@@ -2592,7 +2592,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
 static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+rtl8169_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -2701,6 +2701,7 @@
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned int poll_locked = 0;
+	unsigned int intrmask;
 
 	rtl8169_delete_timer(dev);
 
@@ -2739,8 +2740,11 @@
 	 * 2) dev->change_mtu
 	 *    -> rtl8169_poll can not be issued again and re-enable the
 	 *       interruptions. Let's simply issue the IRQ down sequence again.
+	 *
+	 * No loop if hotpluged or major error (0xffff).
 	 */
-	if (RTL_R16(IntrMask))
+	intrmask = RTL_R16(IntrMask);
+	if (intrmask && (intrmask != 0xffff))
 		goto core_down;
 
 	rtl8169_tx_clear(tp);
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 6108bac..d81536f 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1053,7 +1053,7 @@
 }
 
 
-static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t rr_interrupt(int irq, void *dev_id)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs __iomem *regs;
diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h
index 99451b5..9f3e050 100644
--- a/drivers/net/rrunner.h
+++ b/drivers/net/rrunner.h
@@ -829,7 +829,7 @@
  */
 static int rr_init(struct net_device *dev);
 static int rr_init1(struct net_device *dev);
-static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t rr_interrupt(int irq, void *dev_id);
 
 static int rr_open(struct net_device *dev);
 static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 1bf23e4..a231ab7 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -4029,8 +4029,7 @@
 	return 0;
 }
 
-static irqreturn_t
-s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_msi_handle(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	nic_t *sp = dev->priv;
@@ -4063,8 +4062,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
 {
 	ring_info_t *ring = (ring_info_t *)dev_id;
 	nic_t *sp = ring->nic;
@@ -4078,8 +4076,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id)
 {
 	fifo_info_t *fifo = (fifo_info_t *)dev_id;
 	nic_t *sp = fifo->nic;
@@ -4155,7 +4152,6 @@
  *  s2io_isr - ISR handler of the device .
  *  @irq: the irq of the device.
  *  @dev_id: a void pointer to the dev structure of the NIC.
- *  @pt_regs: pointer to the registers pushed on the stack.
  *  Description:  This function is the ISR handler of the device. It
  *  identifies the reason for the interrupt and calls the relevant
  *  service routines. As a contongency measure, this ISR allocates the
@@ -4165,7 +4161,7 @@
  *   IRQ_HANDLED: will be returned if IRQ was handled by this routine
  *   IRQ_NONE: will be returned if interrupt is not from our device
  */
-static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_isr(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	nic_t *sp = dev->priv;
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 3afd912..12b719f 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -116,179 +116,179 @@
 /* The statistics block of Xena */
 typedef struct stat_block {
 /* Tx MAC statistics counters. */
-	u32 tmac_data_octets;
-	u32 tmac_frms;
-	u64 tmac_drop_frms;
-	u32 tmac_bcst_frms;
-	u32 tmac_mcst_frms;
-	u64 tmac_pause_ctrl_frms;
-	u32 tmac_ucst_frms;
-	u32 tmac_ttl_octets;
-	u32 tmac_any_err_frms;
-	u32 tmac_nucst_frms;
-	u64 tmac_ttl_less_fb_octets;
-	u64 tmac_vld_ip_octets;
-	u32 tmac_drop_ip;
-	u32 tmac_vld_ip;
-	u32 tmac_rst_tcp;
-	u32 tmac_icmp;
-	u64 tmac_tcp;
-	u32 reserved_0;
-	u32 tmac_udp;
+	__le32 tmac_data_octets;
+	__le32 tmac_frms;
+	__le64 tmac_drop_frms;
+	__le32 tmac_bcst_frms;
+	__le32 tmac_mcst_frms;
+	__le64 tmac_pause_ctrl_frms;
+	__le32 tmac_ucst_frms;
+	__le32 tmac_ttl_octets;
+	__le32 tmac_any_err_frms;
+	__le32 tmac_nucst_frms;
+	__le64 tmac_ttl_less_fb_octets;
+	__le64 tmac_vld_ip_octets;
+	__le32 tmac_drop_ip;
+	__le32 tmac_vld_ip;
+	__le32 tmac_rst_tcp;
+	__le32 tmac_icmp;
+	__le64 tmac_tcp;
+	__le32 reserved_0;
+	__le32 tmac_udp;
 
 /* Rx MAC Statistics counters. */
-	u32 rmac_data_octets;
-	u32 rmac_vld_frms;
-	u64 rmac_fcs_err_frms;
-	u64 rmac_drop_frms;
-	u32 rmac_vld_bcst_frms;
-	u32 rmac_vld_mcst_frms;
-	u32 rmac_out_rng_len_err_frms;
-	u32 rmac_in_rng_len_err_frms;
-	u64 rmac_long_frms;
-	u64 rmac_pause_ctrl_frms;
-	u64 rmac_unsup_ctrl_frms;
-	u32 rmac_accepted_ucst_frms;
-	u32 rmac_ttl_octets;
-	u32 rmac_discarded_frms;
-	u32 rmac_accepted_nucst_frms;
-	u32 reserved_1;
-	u32 rmac_drop_events;
-	u64 rmac_ttl_less_fb_octets;
-	u64 rmac_ttl_frms;
-	u64 reserved_2;
-	u32 rmac_usized_frms;
-	u32 reserved_3;
-	u32 rmac_frag_frms;
-	u32 rmac_osized_frms;
-	u32 reserved_4;
-	u32 rmac_jabber_frms;
-	u64 rmac_ttl_64_frms;
-	u64 rmac_ttl_65_127_frms;
-	u64 reserved_5;
-	u64 rmac_ttl_128_255_frms;
-	u64 rmac_ttl_256_511_frms;
-	u64 reserved_6;
-	u64 rmac_ttl_512_1023_frms;
-	u64 rmac_ttl_1024_1518_frms;
-	u32 rmac_ip;
-	u32 reserved_7;
-	u64 rmac_ip_octets;
-	u32 rmac_drop_ip;
-	u32 rmac_hdr_err_ip;
-	u32 reserved_8;
-	u32 rmac_icmp;
-	u64 rmac_tcp;
-	u32 rmac_err_drp_udp;
-	u32 rmac_udp;
-	u64 rmac_xgmii_err_sym;
-	u64 rmac_frms_q0;
-	u64 rmac_frms_q1;
-	u64 rmac_frms_q2;
-	u64 rmac_frms_q3;
-	u64 rmac_frms_q4;
-	u64 rmac_frms_q5;
-	u64 rmac_frms_q6;
-	u64 rmac_frms_q7;
-	u16 rmac_full_q3;
-	u16 rmac_full_q2;
-	u16 rmac_full_q1;
-	u16 rmac_full_q0;
-	u16 rmac_full_q7;
-	u16 rmac_full_q6;
-	u16 rmac_full_q5;
-	u16 rmac_full_q4;
-	u32 reserved_9;
-	u32 rmac_pause_cnt;
-	u64 rmac_xgmii_data_err_cnt;
-	u64 rmac_xgmii_ctrl_err_cnt;
-	u32 rmac_err_tcp;
-	u32 rmac_accepted_ip;
+	__le32 rmac_data_octets;
+	__le32 rmac_vld_frms;
+	__le64 rmac_fcs_err_frms;
+	__le64 rmac_drop_frms;
+	__le32 rmac_vld_bcst_frms;
+	__le32 rmac_vld_mcst_frms;
+	__le32 rmac_out_rng_len_err_frms;
+	__le32 rmac_in_rng_len_err_frms;
+	__le64 rmac_long_frms;
+	__le64 rmac_pause_ctrl_frms;
+	__le64 rmac_unsup_ctrl_frms;
+	__le32 rmac_accepted_ucst_frms;
+	__le32 rmac_ttl_octets;
+	__le32 rmac_discarded_frms;
+	__le32 rmac_accepted_nucst_frms;
+	__le32 reserved_1;
+	__le32 rmac_drop_events;
+	__le64 rmac_ttl_less_fb_octets;
+	__le64 rmac_ttl_frms;
+	__le64 reserved_2;
+	__le32 rmac_usized_frms;
+	__le32 reserved_3;
+	__le32 rmac_frag_frms;
+	__le32 rmac_osized_frms;
+	__le32 reserved_4;
+	__le32 rmac_jabber_frms;
+	__le64 rmac_ttl_64_frms;
+	__le64 rmac_ttl_65_127_frms;
+	__le64 reserved_5;
+	__le64 rmac_ttl_128_255_frms;
+	__le64 rmac_ttl_256_511_frms;
+	__le64 reserved_6;
+	__le64 rmac_ttl_512_1023_frms;
+	__le64 rmac_ttl_1024_1518_frms;
+	__le32 rmac_ip;
+	__le32 reserved_7;
+	__le64 rmac_ip_octets;
+	__le32 rmac_drop_ip;
+	__le32 rmac_hdr_err_ip;
+	__le32 reserved_8;
+	__le32 rmac_icmp;
+	__le64 rmac_tcp;
+	__le32 rmac_err_drp_udp;
+	__le32 rmac_udp;
+	__le64 rmac_xgmii_err_sym;
+	__le64 rmac_frms_q0;
+	__le64 rmac_frms_q1;
+	__le64 rmac_frms_q2;
+	__le64 rmac_frms_q3;
+	__le64 rmac_frms_q4;
+	__le64 rmac_frms_q5;
+	__le64 rmac_frms_q6;
+	__le64 rmac_frms_q7;
+	__le16 rmac_full_q3;
+	__le16 rmac_full_q2;
+	__le16 rmac_full_q1;
+	__le16 rmac_full_q0;
+	__le16 rmac_full_q7;
+	__le16 rmac_full_q6;
+	__le16 rmac_full_q5;
+	__le16 rmac_full_q4;
+	__le32 reserved_9;
+	__le32 rmac_pause_cnt;
+	__le64 rmac_xgmii_data_err_cnt;
+	__le64 rmac_xgmii_ctrl_err_cnt;
+	__le32 rmac_err_tcp;
+	__le32 rmac_accepted_ip;
 
 /* PCI/PCI-X Read transaction statistics. */
-	u32 new_rd_req_cnt;
-	u32 rd_req_cnt;
-	u32 rd_rtry_cnt;
-	u32 new_rd_req_rtry_cnt;
+	__le32 new_rd_req_cnt;
+	__le32 rd_req_cnt;
+	__le32 rd_rtry_cnt;
+	__le32 new_rd_req_rtry_cnt;
 
 /* PCI/PCI-X Write/Read transaction statistics. */
-	u32 wr_req_cnt;
-	u32 wr_rtry_rd_ack_cnt;
-	u32 new_wr_req_rtry_cnt;
-	u32 new_wr_req_cnt;
-	u32 wr_disc_cnt;
-	u32 wr_rtry_cnt;
+	__le32 wr_req_cnt;
+	__le32 wr_rtry_rd_ack_cnt;
+	__le32 new_wr_req_rtry_cnt;
+	__le32 new_wr_req_cnt;
+	__le32 wr_disc_cnt;
+	__le32 wr_rtry_cnt;
 
 /*	PCI/PCI-X Write / DMA Transaction statistics. */
-	u32 txp_wr_cnt;
-	u32 rd_rtry_wr_ack_cnt;
-	u32 txd_wr_cnt;
-	u32 txd_rd_cnt;
-	u32 rxd_wr_cnt;
-	u32 rxd_rd_cnt;
-	u32 rxf_wr_cnt;
-	u32 txf_rd_cnt;
+	__le32 txp_wr_cnt;
+	__le32 rd_rtry_wr_ack_cnt;
+	__le32 txd_wr_cnt;
+	__le32 txd_rd_cnt;
+	__le32 rxd_wr_cnt;
+	__le32 rxd_rd_cnt;
+	__le32 rxf_wr_cnt;
+	__le32 txf_rd_cnt;
 
 /* Tx MAC statistics overflow counters. */
-	u32 tmac_data_octets_oflow;
-	u32 tmac_frms_oflow;
-	u32 tmac_bcst_frms_oflow;
-	u32 tmac_mcst_frms_oflow;
-	u32 tmac_ucst_frms_oflow;
-	u32 tmac_ttl_octets_oflow;
-	u32 tmac_any_err_frms_oflow;
-	u32 tmac_nucst_frms_oflow;
-	u64 tmac_vlan_frms;
-	u32 tmac_drop_ip_oflow;
-	u32 tmac_vld_ip_oflow;
-	u32 tmac_rst_tcp_oflow;
-	u32 tmac_icmp_oflow;
-	u32 tpa_unknown_protocol;
-	u32 tmac_udp_oflow;
-	u32 reserved_10;
-	u32 tpa_parse_failure;
+	__le32 tmac_data_octets_oflow;
+	__le32 tmac_frms_oflow;
+	__le32 tmac_bcst_frms_oflow;
+	__le32 tmac_mcst_frms_oflow;
+	__le32 tmac_ucst_frms_oflow;
+	__le32 tmac_ttl_octets_oflow;
+	__le32 tmac_any_err_frms_oflow;
+	__le32 tmac_nucst_frms_oflow;
+	__le64 tmac_vlan_frms;
+	__le32 tmac_drop_ip_oflow;
+	__le32 tmac_vld_ip_oflow;
+	__le32 tmac_rst_tcp_oflow;
+	__le32 tmac_icmp_oflow;
+	__le32 tpa_unknown_protocol;
+	__le32 tmac_udp_oflow;
+	__le32 reserved_10;
+	__le32 tpa_parse_failure;
 
 /* Rx MAC Statistics overflow counters. */
-	u32 rmac_data_octets_oflow;
-	u32 rmac_vld_frms_oflow;
-	u32 rmac_vld_bcst_frms_oflow;
-	u32 rmac_vld_mcst_frms_oflow;
-	u32 rmac_accepted_ucst_frms_oflow;
-	u32 rmac_ttl_octets_oflow;
-	u32 rmac_discarded_frms_oflow;
-	u32 rmac_accepted_nucst_frms_oflow;
-	u32 rmac_usized_frms_oflow;
-	u32 rmac_drop_events_oflow;
-	u32 rmac_frag_frms_oflow;
-	u32 rmac_osized_frms_oflow;
-	u32 rmac_ip_oflow;
-	u32 rmac_jabber_frms_oflow;
-	u32 rmac_icmp_oflow;
-	u32 rmac_drop_ip_oflow;
-	u32 rmac_err_drp_udp_oflow;
-	u32 rmac_udp_oflow;
-	u32 reserved_11;
-	u32 rmac_pause_cnt_oflow;
-	u64 rmac_ttl_1519_4095_frms;
-	u64 rmac_ttl_4096_8191_frms;
-	u64 rmac_ttl_8192_max_frms;
-	u64 rmac_ttl_gt_max_frms;
-	u64 rmac_osized_alt_frms;
-	u64 rmac_jabber_alt_frms;
-	u64 rmac_gt_max_alt_frms;
-	u64 rmac_vlan_frms;
-	u32 rmac_len_discard;
-	u32 rmac_fcs_discard;
-	u32 rmac_pf_discard;
-	u32 rmac_da_discard;
-	u32 rmac_red_discard;
-	u32 rmac_rts_discard;
-	u32 reserved_12;
-	u32 rmac_ingm_full_discard;
-	u32 reserved_13;
-	u32 rmac_accepted_ip_oflow;
-	u32 reserved_14;
-	u32 link_fault_cnt;
+	__le32 rmac_data_octets_oflow;
+	__le32 rmac_vld_frms_oflow;
+	__le32 rmac_vld_bcst_frms_oflow;
+	__le32 rmac_vld_mcst_frms_oflow;
+	__le32 rmac_accepted_ucst_frms_oflow;
+	__le32 rmac_ttl_octets_oflow;
+	__le32 rmac_discarded_frms_oflow;
+	__le32 rmac_accepted_nucst_frms_oflow;
+	__le32 rmac_usized_frms_oflow;
+	__le32 rmac_drop_events_oflow;
+	__le32 rmac_frag_frms_oflow;
+	__le32 rmac_osized_frms_oflow;
+	__le32 rmac_ip_oflow;
+	__le32 rmac_jabber_frms_oflow;
+	__le32 rmac_icmp_oflow;
+	__le32 rmac_drop_ip_oflow;
+	__le32 rmac_err_drp_udp_oflow;
+	__le32 rmac_udp_oflow;
+	__le32 reserved_11;
+	__le32 rmac_pause_cnt_oflow;
+	__le64 rmac_ttl_1519_4095_frms;
+	__le64 rmac_ttl_4096_8191_frms;
+	__le64 rmac_ttl_8192_max_frms;
+	__le64 rmac_ttl_gt_max_frms;
+	__le64 rmac_osized_alt_frms;
+	__le64 rmac_jabber_alt_frms;
+	__le64 rmac_gt_max_alt_frms;
+	__le64 rmac_vlan_frms;
+	__le32 rmac_len_discard;
+	__le32 rmac_fcs_discard;
+	__le32 rmac_pf_discard;
+	__le32 rmac_da_discard;
+	__le32 rmac_red_discard;
+	__le32 rmac_rts_discard;
+	__le32 reserved_12;
+	__le32 rmac_ingm_full_discard;
+	__le32 reserved_13;
+	__le32 rmac_accepted_ip_oflow;
+	__le32 reserved_14;
+	__le32 link_fault_cnt;
 	u8  buffer[20];
 	swStat_t sw_stat;
 	xpakStat_t xpak_stat;
@@ -992,12 +992,12 @@
 static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
 static void s2io_alarm_handle(unsigned long data);
 static int s2io_enable_msi(nic_t *nic);
-static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t s2io_msi_handle(int irq, void *dev_id);
 static irqreturn_t
-s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
+s2io_msix_ring_handle(int irq, void *dev_id);
 static irqreturn_t
-s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
+s2io_msix_fifo_handle(int irq, void *dev_id);
+static irqreturn_t s2io_isr(int irq, void *dev_id);
 static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static const struct ethtool_ops netdev_ethtool_ops;
 static void s2io_set_link(unsigned long data);
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index c479b07..b269513 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -745,10 +745,9 @@
 	return 0;
 }
 
-static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id,
-				  struct pt_regs *regs)
+static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	if (lan_saa9730_debug > 5)
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index a1789ae..b9fa4fb 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -84,7 +84,7 @@
 static int sb1000_open(struct net_device *dev);
 static int sb1000_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
 static int sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t sb1000_interrupt(int irq, void *dev_id);
 static struct net_device_stats *sb1000_stats(struct net_device *dev);
 static int sb1000_close(struct net_device *dev);
 
@@ -1079,24 +1079,18 @@
 }
 
 /* SB1000 interrupt handler. */
-static irqreturn_t sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sb1000_interrupt(int irq, void *dev_id)
 {
 	char *name;
 	unsigned char st;
 	int ioaddr[2];
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct sb1000_private *lp = netdev_priv(dev);
 
 	const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
 	const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
 	const int MaxRxErrorCount = 6;
 
-	if (dev == NULL) {
-		printk(KERN_ERR "sb1000_interrupt(): irq %d for unknown device.\n",
-			irq);
-		return IRQ_NONE;
-	}
-
 	ioaddr[0] = dev->base_addr;
 	/* mem_start holds the second I/O address */
 	ioaddr[1] = dev->mem_start;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index e4c8896..1eae16b 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -294,7 +294,7 @@
 static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t);
 static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff);
 static uint64_t sbmac_addr2reg(unsigned char *ptr);
-static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
+static irqreturn_t sbmac_intr(int irq,void *dev_instance);
 static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
 static void sbmac_setmulti(struct sbmac_softc *sc);
 static int sbmac_init(struct net_device *dev, int idx);
@@ -2049,7 +2049,7 @@
  *  Return value:
  *  	   nothing
  ********************************************************************* */
-static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
+static irqreturn_t sbmac_intr(int irq,void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct sbmac_softc *sc = netdev_priv(dev);
@@ -2903,7 +2903,7 @@
 
 		dev = alloc_etherdev(sizeof(struct sbmac_softc));
 		if (!dev)
-			return -ENOMEM;	/* return ENOMEM */
+			return -ENOMEM;
 
 		printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
 
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index 20afdc7..d9d0a3a 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -83,7 +83,7 @@
 static int seeq8005_open(struct net_device *dev);
 static void seeq8005_timeout(struct net_device *dev);
 static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t seeq8005_interrupt(int irq, void *dev_id);
 static void seeq8005_rx(struct net_device *dev);
 static int seeq8005_close(struct net_device *dev);
 static struct net_device_stats *seeq8005_get_stats(struct net_device *dev);
@@ -437,7 +437,7 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static irqreturn_t seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t seeq8005_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index f95a5b0..a833e7f 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -432,7 +432,7 @@
 	}
 }
 
-static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct sgiseeq_private *sp = netdev_priv(dev);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index e8f26b7..aaba458 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -713,7 +713,7 @@
  * The interrupt handler does all of the Rx thread work and cleans up after
  * the Tx thread.
  */
-static irqreturn_t sis190_interrupt(int irq, void *__dev, struct pt_regs *regs)
+static irqreturn_t sis190_interrupt(int irq, void *__dev)
 {
 	struct net_device *dev = __dev;
 	struct sis190_private *tp = netdev_priv(dev);
@@ -758,7 +758,7 @@
 	struct pci_dev *pdev = tp->pci_dev;
 
 	disable_irq(pdev->irq);
-	sis190_interrupt(pdev->irq, dev, NULL);
+	sis190_interrupt(pdev->irq, dev);
 	enable_irq(pdev->irq);
 }
 #endif
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 28606e2..fb2b530 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -218,7 +218,7 @@
 static int sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
 static int sis900_rx(struct net_device *net_dev);
 static void sis900_finish_xmit (struct net_device *net_dev);
-static irqreturn_t sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t sis900_interrupt(int irq, void *dev_instance);
 static int sis900_close(struct net_device *net_dev);
 static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd);
 static struct net_device_stats *sis900_get_stats(struct net_device *net_dev);
@@ -988,7 +988,7 @@
 static void sis900_poll(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	sis900_interrupt(dev->irq, dev, NULL);
+	sis900_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -1642,7 +1642,7 @@
  *	and cleans up after the Tx thread
  */
 
-static irqreturn_t sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *net_dev = dev_instance;
 	struct sis900_private *sis_priv = net_dev->priv;
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 99e9262..d4913c3 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -196,8 +196,8 @@
 static void	BoardFreeMem(SK_AC *pAC);
 static void	BoardInitMem(SK_AC *pAC);
 static void	SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
-static SkIsrRetVar	SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
-static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
+static SkIsrRetVar	SkGeIsr(int irq, void *dev_id);
+static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id);
 static int	SkGeOpen(struct SK_NET_DEVICE *dev);
 static int	SkGeClose(struct SK_NET_DEVICE *dev);
 static int	SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
@@ -880,7 +880,7 @@
  * Returns: N/A
  *
  */
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
+static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
 {
 struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
 DEV_NET		*pNet;
@@ -1029,7 +1029,7 @@
  * Returns: N/A
  *
  */
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
+static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
 {
 struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
 DEV_NET		*pNet;
@@ -1140,7 +1140,7 @@
 static void SkGePollController(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	SkGeIsr(dev->irq, dev, NULL);
+	SkGeIsr(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
index 37b88da..96e06c5 100644
--- a/drivers/net/sk_mca.c
+++ b/drivers/net/sk_mca.c
@@ -732,7 +732,7 @@
 
 /* general interrupt entry */
 
-static irqreturn_t irq_handler(int irq, void *device, struct pt_regs *regs)
+static irqreturn_t irq_handler(int irq, void *device)
 {
 	struct net_device *dev = (struct net_device *) device;
 	u16 csr0val;
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 8e4d184..9733a11 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -101,7 +101,7 @@
 static int skfp_driver_init(struct net_device *dev);
 static int skfp_open(struct net_device *dev);
 static int skfp_close(struct net_device *dev);
-static irqreturn_t skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t skfp_interrupt(int irq, void *dev_id);
 static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev);
 static void skfp_ctl_set_multicast_list(struct net_device *dev);
 static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);
@@ -593,7 +593,6 @@
  * Arguments:
  *   irq        - interrupt vector
  *   dev_id     - pointer to device information
- *       regs   - pointer to registers structure
  *
  * Functional Description:
  *   This routine calls the interrupt processing routine for this adapter.  It
@@ -615,17 +614,12 @@
  *   Interrupts are disabled, then reenabled at the adapter.
  */
 
-irqreturn_t skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t skfp_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct s_smc *smc;	/* private board structure pointer */
 	skfddi_priv *bp;
 
-	if (dev == NULL) {
-		printk("%s: irq %d for unknown device\n", dev->name, irq);
-		return IRQ_NONE;
-	}
-
 	smc = netdev_priv(dev);
 	bp = &smc->os;
 
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 705e9a8..e7e4149 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -43,7 +43,7 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"1.8"
+#define DRV_VERSION		"1.9"
 #define PFX			DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE	128
@@ -197,8 +197,8 @@
 		else if (hw->chip_id == CHIP_ID_YUKON)
 			supported &= ~SUPPORTED_1000baseT_Half;
 	} else
-		supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
-			| SUPPORTED_Autoneg;
+		supported = SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half
+			| SUPPORTED_FIBRE | SUPPORTED_Autoneg;
 
 	return supported;
 }
@@ -487,31 +487,37 @@
 {
 	struct skge_port *skge = netdev_priv(dev);
 
-	ecmd->tx_pause = (skge->flow_control == FLOW_MODE_LOC_SEND)
-		|| (skge->flow_control == FLOW_MODE_SYMMETRIC);
-	ecmd->rx_pause = (skge->flow_control == FLOW_MODE_REM_SEND)
-		|| (skge->flow_control == FLOW_MODE_SYMMETRIC);
+	ecmd->rx_pause = (skge->flow_control == FLOW_MODE_SYMMETRIC)
+		|| (skge->flow_control == FLOW_MODE_SYM_OR_REM);
+	ecmd->tx_pause = ecmd->rx_pause || (skge->flow_control == FLOW_MODE_LOC_SEND);
 
-	ecmd->autoneg = skge->autoneg;
+	ecmd->autoneg = ecmd->rx_pause || ecmd->tx_pause;
 }
 
 static int skge_set_pauseparam(struct net_device *dev,
 			       struct ethtool_pauseparam *ecmd)
 {
 	struct skge_port *skge = netdev_priv(dev);
+	struct ethtool_pauseparam old;
 
-	skge->autoneg = ecmd->autoneg;
-	if (ecmd->rx_pause && ecmd->tx_pause)
-		skge->flow_control = FLOW_MODE_SYMMETRIC;
-	else if (ecmd->rx_pause && !ecmd->tx_pause)
-		skge->flow_control = FLOW_MODE_REM_SEND;
-	else if (!ecmd->rx_pause && ecmd->tx_pause)
-		skge->flow_control = FLOW_MODE_LOC_SEND;
-	else
-		skge->flow_control = FLOW_MODE_NONE;
+	skge_get_pauseparam(dev, &old);
+
+	if (ecmd->autoneg != old.autoneg)
+		skge->flow_control = ecmd->autoneg ? FLOW_MODE_NONE : FLOW_MODE_SYMMETRIC;
+	else {
+		if (ecmd->rx_pause && ecmd->tx_pause)
+			skge->flow_control = FLOW_MODE_SYMMETRIC;
+		else if (ecmd->rx_pause && !ecmd->tx_pause)
+			skge->flow_control = FLOW_MODE_SYM_OR_REM;
+		else if (!ecmd->rx_pause && ecmd->tx_pause)
+			skge->flow_control = FLOW_MODE_LOC_SEND;
+		else
+			skge->flow_control = FLOW_MODE_NONE;
+	}
 
 	if (netif_running(dev))
 		skge_phy_reset(skge);
+
 	return 0;
 }
 
@@ -854,6 +860,23 @@
 	return 0;
 }
 
+static const char *skge_pause(enum pause_status status)
+{
+	switch(status) {
+	case FLOW_STAT_NONE:
+		return "none";
+	case FLOW_STAT_REM_SEND:
+		return "rx only";
+	case FLOW_STAT_LOC_SEND:
+		return "tx_only";
+	case FLOW_STAT_SYMMETRIC:		/* Both station may send PAUSE */
+		return "both";
+	default:
+		return "indeterminated";
+	}
+}
+
+
 static void skge_link_up(struct skge_port *skge)
 {
 	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
@@ -862,16 +885,13 @@
 	netif_carrier_on(skge->netdev);
 	netif_wake_queue(skge->netdev);
 
-	if (netif_msg_link(skge))
+	if (netif_msg_link(skge)) {
 		printk(KERN_INFO PFX
 		       "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
 		       skge->netdev->name, skge->speed,
 		       skge->duplex == DUPLEX_FULL ? "full" : "half",
-		       (skge->flow_control == FLOW_MODE_NONE) ? "none" :
-		       (skge->flow_control == FLOW_MODE_LOC_SEND) ? "tx only" :
-		       (skge->flow_control == FLOW_MODE_REM_SEND) ? "rx only" :
-		       (skge->flow_control == FLOW_MODE_SYMMETRIC) ? "tx and rx" :
-		       "unknown");
+		       skge_pause(skge->flow_status));
+	}
 }
 
 static void skge_link_down(struct skge_port *skge)
@@ -884,6 +904,29 @@
 		printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
 }
 
+
+static void xm_link_down(struct skge_hw *hw, int port)
+{
+	struct net_device *dev = hw->dev[port];
+	struct skge_port *skge = netdev_priv(dev);
+	u16 cmd, msk;
+
+	if (hw->phy_type == SK_PHY_XMAC) {
+		msk = xm_read16(hw, port, XM_IMSK);
+		msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND;
+		xm_write16(hw, port, XM_IMSK, msk);
+	}
+
+	cmd = xm_read16(hw, port, XM_MMU_CMD);
+	cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+	xm_write16(hw, port, XM_MMU_CMD, cmd);
+	/* dummy read to ensure writing */
+	(void) xm_read16(hw, port, XM_MMU_CMD);
+
+	if (netif_carrier_ok(dev))
+		skge_link_down(skge);
+}
+
 static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
 {
 	int i;
@@ -992,7 +1035,15 @@
 	[FLOW_MODE_NONE] =	0,
 	[FLOW_MODE_LOC_SEND] =	PHY_AN_PAUSE_ASYM,
 	[FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP,
-	[FLOW_MODE_REM_SEND]  = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM,
+	[FLOW_MODE_SYM_OR_REM]  = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM,
+};
+
+/* special defines for FIBER (88E1011S only) */
+static const u16 fiber_pause_map[] = {
+	[FLOW_MODE_NONE]	= PHY_X_P_NO_PAUSE,
+	[FLOW_MODE_LOC_SEND]	= PHY_X_P_ASYM_MD,
+	[FLOW_MODE_SYMMETRIC]	= PHY_X_P_SYM_MD,
+	[FLOW_MODE_SYM_OR_REM]	= PHY_X_P_BOTH_MD,
 };
 
 
@@ -1008,14 +1059,7 @@
 	status = xm_phy_read(hw, port, PHY_BCOM_STAT);
 
 	if ((status & PHY_ST_LSYNC) == 0) {
-		u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
-		cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-		xm_write16(hw, port, XM_MMU_CMD, cmd);
-		/* dummy read to ensure writing */
-		(void) xm_read16(hw, port, XM_MMU_CMD);
-
-		if (netif_carrier_ok(dev))
-			skge_link_down(skge);
+		xm_link_down(hw, port);
 		return;
 	}
 
@@ -1048,20 +1092,19 @@
 			return;
 		}
 
-
 		/* We are using IEEE 802.3z/D5.0 Table 37-4 */
 		switch (aux & PHY_B_AS_PAUSE_MSK) {
 		case PHY_B_AS_PAUSE_MSK:
-			skge->flow_control = FLOW_MODE_SYMMETRIC;
+			skge->flow_status = FLOW_STAT_SYMMETRIC;
 			break;
 		case PHY_B_AS_PRR:
-			skge->flow_control = FLOW_MODE_REM_SEND;
+			skge->flow_status = FLOW_STAT_REM_SEND;
 			break;
 		case PHY_B_AS_PRT:
-			skge->flow_control = FLOW_MODE_LOC_SEND;
+			skge->flow_status = FLOW_STAT_LOC_SEND;
 			break;
 		default:
-			skge->flow_control = FLOW_MODE_NONE;
+			skge->flow_status = FLOW_STAT_NONE;
 		}
 		skge->speed = SPEED_1000;
 	}
@@ -1191,17 +1234,7 @@
 		if (skge->advertising & ADVERTISED_1000baseT_Full)
 			ctrl |= PHY_X_AN_FD;
 
-		switch(skge->flow_control) {
-		case FLOW_MODE_NONE:
-			ctrl |= PHY_X_P_NO_PAUSE;
-			break;
-		case FLOW_MODE_LOC_SEND:
-			ctrl |= PHY_X_P_ASYM_MD;
-			break;
-		case FLOW_MODE_SYMMETRIC:
-			ctrl |= PHY_X_P_BOTH_MD;
-			break;
-		}
+		ctrl |= fiber_pause_map[skge->flow_control];
 
 		xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl);
 
@@ -1235,14 +1268,7 @@
 	status = xm_phy_read(hw, port, PHY_XMAC_STAT);
 
 	if ((status & PHY_ST_LSYNC) == 0) {
-		u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
-		cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-		xm_write16(hw, port, XM_MMU_CMD, cmd);
-		/* dummy read to ensure writing */
-		(void) xm_read16(hw, port, XM_MMU_CMD);
-
-		if (netif_carrier_ok(dev))
-			skge_link_down(skge);
+		xm_link_down(hw, port);
 		return;
 	}
 
@@ -1276,15 +1302,20 @@
 		}
 
 		/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-		if (lpa & PHY_X_P_SYM_MD)
-			skge->flow_control = FLOW_MODE_SYMMETRIC;
-		else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD)
-			skge->flow_control = FLOW_MODE_REM_SEND;
-		else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD)
-			skge->flow_control = FLOW_MODE_LOC_SEND;
+		if ((skge->flow_control == FLOW_MODE_SYMMETRIC ||
+		     skge->flow_control == FLOW_MODE_SYM_OR_REM) &&
+		    (lpa & PHY_X_P_SYM_MD))
+			skge->flow_status = FLOW_STAT_SYMMETRIC;
+		else if (skge->flow_control == FLOW_MODE_SYM_OR_REM &&
+			 (lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD)
+			/* Enable PAUSE receive, disable PAUSE transmit */
+			skge->flow_status  = FLOW_STAT_REM_SEND;
+		else if (skge->flow_control == FLOW_MODE_LOC_SEND &&
+			 (lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD)
+			/* Disable PAUSE receive, enable PAUSE transmit */
+			skge->flow_status = FLOW_STAT_LOC_SEND;
 		else
-			skge->flow_control = FLOW_MODE_NONE;
-
+			skge->flow_status = FLOW_STAT_NONE;
 
 		skge->speed = SPEED_1000;
 	}
@@ -1568,6 +1599,10 @@
 		printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
 		       skge->netdev->name, status);
 
+	if (hw->phy_type == SK_PHY_XMAC &&
+	    (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC)))
+		xm_link_down(hw, port);
+
 	if (status & XM_IS_TXF_UR) {
 		xm_write32(hw, port, XM_MODE, XM_MD_FTF);
 		++skge->net_stats.tx_fifo_errors;
@@ -1582,7 +1617,7 @@
 {
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
-	u16 cmd;
+	u16 cmd, msk;
 	u32 mode;
 
 	cmd = xm_read16(hw, port, XM_MMU_CMD);
@@ -1591,8 +1626,8 @@
 	 * enabling pause frame reception is required for 1000BT
 	 * because the XMAC is not reset if the link is going down
 	 */
-	if (skge->flow_control == FLOW_MODE_NONE ||
-	    skge->flow_control == FLOW_MODE_LOC_SEND)
+	if (skge->flow_status == FLOW_STAT_NONE ||
+	    skge->flow_status == FLOW_STAT_LOC_SEND)
 		/* Disable Pause Frame Reception */
 		cmd |= XM_MMU_IGN_PF;
 	else
@@ -1602,8 +1637,8 @@
 	xm_write16(hw, port, XM_MMU_CMD, cmd);
 
 	mode = xm_read32(hw, port, XM_MODE);
-	if (skge->flow_control == FLOW_MODE_SYMMETRIC ||
-	    skge->flow_control == FLOW_MODE_LOC_SEND) {
+	if (skge->flow_status== FLOW_STAT_SYMMETRIC ||
+	    skge->flow_status == FLOW_STAT_LOC_SEND) {
 		/*
 		 * Configure Pause Frame Generation
 		 * Use internal and external Pause Frame Generation.
@@ -1631,7 +1666,11 @@
 	}
 
 	xm_write32(hw, port, XM_MODE, mode);
-	xm_write16(hw, port, XM_IMSK, XM_DEF_MSK);
+	msk = XM_DEF_MSK;
+	if (hw->phy_type != SK_PHY_XMAC)
+		msk |= XM_IS_INP_ASS;	/* disable GP0 interrupt bit */
+
+	xm_write16(hw, port, XM_IMSK, msk);
 	xm_read16(hw, port, XM_ISRC);
 
 	/* get MMU Command Reg. */
@@ -1779,11 +1818,17 @@
 				adv |= PHY_M_AN_10_FD;
 			if (skge->advertising & ADVERTISED_10baseT_Half)
 				adv |= PHY_M_AN_10_HD;
-		} else	/* special defines for FIBER (88E1011S only) */
-			adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
 
-		/* Set Flow-control capabilities */
-		adv |= phy_pause_map[skge->flow_control];
+			/* Set Flow-control capabilities */
+			adv |= phy_pause_map[skge->flow_control];
+		} else {
+			if (skge->advertising & ADVERTISED_1000baseT_Full)
+				adv |= PHY_M_AN_1000X_AFD;
+			if (skge->advertising & ADVERTISED_1000baseT_Half)
+				adv |= PHY_M_AN_1000X_AHD;
+
+			adv |= fiber_pause_map[skge->flow_control];
+		}
 
 		/* Restart Auto-negotiation */
 		ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
@@ -1917,6 +1962,11 @@
 	case FLOW_MODE_LOC_SEND:
 		/* disable Rx flow-control */
 		reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+		break;
+	case FLOW_MODE_SYMMETRIC:
+	case FLOW_MODE_SYM_OR_REM:
+		/* enable Tx & Rx flow-control */
+		break;
 	}
 
 	gma_write16(hw, port, GM_GP_CTRL, reg);
@@ -2111,13 +2161,11 @@
 	ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
 	gma_write16(hw, port, GM_GP_CTRL, ctrl);
 
-	if (skge->flow_control == FLOW_MODE_REM_SEND) {
+	if (skge->flow_status == FLOW_STAT_REM_SEND) {
+		ctrl = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
+		ctrl |= PHY_M_AN_ASP;
 		/* restore Asymmetric Pause bit */
-		gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
-				  gm_phy_read(hw, port,
-						   PHY_MARV_AUNE_ADV)
-				  | PHY_M_AN_ASP);
-
+		gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl);
 	}
 
 	yukon_reset(hw, port);
@@ -2164,19 +2212,19 @@
 		/* We are using IEEE 802.3z/D5.0 Table 37-4 */
 		switch (phystat & PHY_M_PS_PAUSE_MSK) {
 		case PHY_M_PS_PAUSE_MSK:
-			skge->flow_control = FLOW_MODE_SYMMETRIC;
+			skge->flow_status = FLOW_STAT_SYMMETRIC;
 			break;
 		case PHY_M_PS_RX_P_EN:
-			skge->flow_control = FLOW_MODE_REM_SEND;
+			skge->flow_status = FLOW_STAT_REM_SEND;
 			break;
 		case PHY_M_PS_TX_P_EN:
-			skge->flow_control = FLOW_MODE_LOC_SEND;
+			skge->flow_status = FLOW_STAT_LOC_SEND;
 			break;
 		default:
-			skge->flow_control = FLOW_MODE_NONE;
+			skge->flow_status = FLOW_STAT_NONE;
 		}
 
-		if (skge->flow_control == FLOW_MODE_NONE ||
+		if (skge->flow_status == FLOW_STAT_NONE ||
 		    (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF))
 			skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
 		else
@@ -3051,7 +3099,7 @@
 	spin_unlock_irq(&hw->hw_lock);
 }
 
-static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t skge_intr(int irq, void *dev_id)
 {
 	struct skge_hw *hw = dev_id;
 	u32 status;
@@ -3125,7 +3173,7 @@
 	struct skge_port *skge = netdev_priv(dev);
 
 	disable_irq(dev->irq);
-	skge_intr(dev->irq, skge->hw, NULL);
+	skge_intr(dev->irq, skge->hw);
 	enable_irq(dev->irq);
 }
 #endif
@@ -3399,7 +3447,7 @@
 
 	/* Auto speed and flow control */
 	skge->autoneg = AUTONEG_ENABLE;
-	skge->flow_control = FLOW_MODE_SYMMETRIC;
+	skge->flow_control = FLOW_MODE_SYM_OR_REM;
 	skge->duplex = -1;
 	skge->speed = -1;
 	skge->advertising = skge_supported_modes(hw);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index d0b47d4..537c0aa 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2195,7 +2195,8 @@
 	XM_IS_RX_COMP	= 1<<0,	/* Bit  0:	Frame Rx Complete */
 };
 
-#define XM_DEF_MSK	(~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR))
+#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | \
+			   XM_IS_RXF_OV | XM_IS_TXF_UR))
 
 
 /*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
@@ -2426,13 +2427,24 @@
 	struct mutex	     phy_mutex;
 };
 
-enum {
-	FLOW_MODE_NONE 		= 0, /* No Flow-Control */
-	FLOW_MODE_LOC_SEND	= 1, /* Local station sends PAUSE */
-	FLOW_MODE_REM_SEND	= 2, /* Symmetric or just remote */
+enum pause_control {
+	FLOW_MODE_NONE 		= 1, /* No Flow-Control */
+	FLOW_MODE_LOC_SEND	= 2, /* Local station sends PAUSE */
 	FLOW_MODE_SYMMETRIC	= 3, /* Both stations may send PAUSE */
+	FLOW_MODE_SYM_OR_REM	= 4, /* Both stations may send PAUSE or
+				      * just the remote station may send PAUSE
+				      */
 };
 
+enum pause_status {
+	FLOW_STAT_INDETERMINATED=0,	/* indeterminated */
+	FLOW_STAT_NONE,			/* No Flow Control */
+	FLOW_STAT_REM_SEND,		/* Remote Station sends PAUSE */
+	FLOW_STAT_LOC_SEND,		/* Local station sends PAUSE */
+	FLOW_STAT_SYMMETRIC,		/* Both station may send PAUSE */
+};
+
+
 struct skge_port {
 	u32		     msg_enable;
 	struct skge_hw	     *hw;
@@ -2445,9 +2457,10 @@
 	struct net_device_stats net_stats;
 
 	struct work_struct   link_thread;
+	enum pause_control   flow_control;
+	enum pause_status    flow_status;
 	u8		     rx_csum;
 	u8		     blink_on;
-	u8		     flow_control;
 	u8		     wol;
 	u8		     autoneg;	/* AUTONEG_ENABLE, AUTONEG_DISABLE */
 	u8		     duplex;	/* DUPLEX_HALF, DUPLEX_FULL */
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 396e7df..95efdb5 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.9"
+#define DRV_VERSION		"1.10"
 #define PFX			DRV_NAME " "
 
 /*
@@ -96,9 +96,9 @@
 module_param(disable_msi, int, 0);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
-static int idle_timeout = 100;
+static int idle_timeout = 0;
 module_param(idle_timeout, int, 0);
-MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)");
+MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
 
 static const struct pci_device_id sky2_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
@@ -284,6 +284,31 @@
 	gma_write16(hw, port, GM_RX_CTRL, reg);
 }
 
+/* flow control to advertise bits */
+static const u16 copper_fc_adv[] = {
+	[FC_NONE]	= 0,
+	[FC_TX]		= PHY_M_AN_ASP,
+	[FC_RX]		= PHY_M_AN_PC,
+	[FC_BOTH]	= PHY_M_AN_PC | PHY_M_AN_ASP,
+};
+
+/* flow control to advertise bits when using 1000BaseX */
+static const u16 fiber_fc_adv[] = {
+	[FC_BOTH] = PHY_M_P_BOTH_MD_X,
+	[FC_TX]   = PHY_M_P_ASYM_MD_X,
+	[FC_RX]	  = PHY_M_P_SYM_MD_X,
+	[FC_NONE] = PHY_M_P_NO_PAUSE_X,
+};
+
+/* flow control to GMA disable bits */
+static const u16 gm_fc_disable[] = {
+	[FC_NONE] = GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS,
+	[FC_TX]	  = GM_GPCR_FC_RX_DIS,
+	[FC_RX]	  = GM_GPCR_FC_TX_DIS,
+	[FC_BOTH] = 0,
+};
+
+
 static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 {
 	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -356,16 +381,7 @@
 		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
 	}
 
-	ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
-	if (sky2->autoneg == AUTONEG_DISABLE)
-		ctrl &= ~PHY_CT_ANE;
-	else
-		ctrl |= PHY_CT_ANE;
-
-	ctrl |= PHY_CT_RESET;
-	gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
-
-	ctrl = 0;
+	ctrl = PHY_CT_RESET;
 	ct1000 = 0;
 	adv = PHY_AN_CSMA;
 	reg = 0;
@@ -384,20 +400,16 @@
 				adv |= PHY_M_AN_10_FD;
 			if (sky2->advertising & ADVERTISED_10baseT_Half)
 				adv |= PHY_M_AN_10_HD;
+
+			adv |= copper_fc_adv[sky2->flow_mode];
 		} else {	/* special defines for FIBER (88E1040S only) */
 			if (sky2->advertising & ADVERTISED_1000baseT_Full)
 				adv |= PHY_M_AN_1000X_AFD;
 			if (sky2->advertising & ADVERTISED_1000baseT_Half)
 				adv |= PHY_M_AN_1000X_AHD;
-		}
 
-		/* Set Flow-control capabilities */
-		if (sky2->tx_pause && sky2->rx_pause)
-			adv |= PHY_AN_PAUSE_CAP;	/* symmetric */
-		else if (sky2->rx_pause && !sky2->tx_pause)
-			adv |= PHY_AN_PAUSE_ASYM | PHY_AN_PAUSE_CAP;
-		else if (!sky2->rx_pause && sky2->tx_pause)
-			adv |= PHY_AN_PAUSE_ASYM;	/* local */
+			adv |= fiber_fc_adv[sky2->flow_mode];
+		}
 
 		/* Restart Auto-negotiation */
 		ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
@@ -422,25 +434,17 @@
 		if (sky2->duplex == DUPLEX_FULL) {
 			reg |= GM_GPCR_DUP_FULL;
 			ctrl |= PHY_CT_DUP_MD;
-		} else if (sky2->speed != SPEED_1000 && hw->chip_id != CHIP_ID_YUKON_EC_U) {
-			/* Turn off flow control for 10/100mbps */
-			sky2->rx_pause = 0;
-			sky2->tx_pause = 0;
-		}
+		} else if (sky2->speed < SPEED_1000)
+			sky2->flow_mode = FC_NONE;
 
-		if (!sky2->rx_pause)
-			reg |= GM_GPCR_FC_RX_DIS;
 
-		if (!sky2->tx_pause)
-			reg |= GM_GPCR_FC_TX_DIS;
+ 		reg |= gm_fc_disable[sky2->flow_mode];
 
 		/* Forward pause packets to GMAC? */
-		if (sky2->tx_pause || sky2->rx_pause)
+		if (sky2->flow_mode & FC_RX)
 			sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
 		else
 			sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
-
-		ctrl |= PHY_CT_RESET;
 	}
 
 	gma_write16(hw, port, GM_GP_CTRL, reg);
@@ -683,7 +687,7 @@
 	sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
 
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
-		sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
+		sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 512/8);
 		sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
 		if (hw->dev[port]->mtu > ETH_DATA_LEN) {
 			/* set Tx GMAC FIFO Almost Empty Threshold */
@@ -695,16 +699,10 @@
 
 }
 
-/* Assign Ram Buffer allocation.
- * start and end are in units of 4k bytes
- * ram registers are in units of 64bit words
- */
-static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
+/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end)
 {
-	u32 start, end;
-
-	start = startk * 4096/8;
-	end = (endk * 4096/8) - 1;
+	pr_debug(PFX "q %d %#x %#x\n", q, start, end);
 
 	sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
 	sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -713,7 +711,7 @@
 	sky2_write32(hw, RB_ADDR(q, RB_RP), start);
 
 	if (q == Q_R1 || q == Q_R2) {
-		u32 space = (endk - startk) * 4096/8;
+		u32 space = end - start + 1;
 		u32 tp = space - space/4;
 
 		/* On receive queue's set the thresholds
@@ -1195,19 +1193,16 @@
 
 	sky2_mac_init(hw, port);
 
-	/* Determine available ram buffer space (in 4K blocks).
-	 * Note: not sure about the FE setting below yet
-	 */
-	if (hw->chip_id == CHIP_ID_YUKON_FE)
-		ramsize = 4;
+	/* Determine available ram buffer space in qwords.  */
+	ramsize = sky2_read8(hw, B2_E_0) * 4096/8;
+
+	if (ramsize > 6*1024/8)
+		rxspace = ramsize - (ramsize + 2) / 3;
 	else
-		ramsize = sky2_read8(hw, B2_E_0);
+		rxspace = ramsize / 2;
 
-	/* Give transmitter one third (rounded up) */
-	rxspace = ramsize - (ramsize + 2) / 3;
-
-	sky2_ramset(hw, rxqaddr[port], 0, rxspace);
-	sky2_ramset(hw, txqaddr[port], rxspace, ramsize);
+	sky2_ramset(hw, rxqaddr[port], 0, rxspace-1);
+	sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1);
 
 	/* Make sure SyncQ is disabled */
 	sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
@@ -1499,6 +1494,11 @@
 	/* Stop more packets from being queued */
 	netif_stop_queue(dev);
 
+	/* Disable port IRQ */
+	imask = sky2_read32(hw, B0_IMSK);
+	imask &= ~portirq_msk[port];
+	sky2_write32(hw, B0_IMSK, imask);
+
 	sky2_gmac_reset(hw, port);
 
 	/* Stop transmitter */
@@ -1549,11 +1549,6 @@
 	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
 	sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
 
-	/* Disable port IRQ */
-	imask = sky2_read32(hw, B0_IMSK);
-	imask &= ~portirq_msk[port];
-	sky2_write32(hw, B0_IMSK, imask);
-
 	sky2_phy_power(hw, port, 0);
 
 	/* turn off LED's */
@@ -1605,6 +1600,12 @@
 	struct sky2_hw *hw = sky2->hw;
 	unsigned port = sky2->port;
 	u16 reg;
+	static const char *fc_name[] = {
+		[FC_NONE]	= "none",
+		[FC_TX]		= "tx",
+		[FC_RX]		= "rx",
+		[FC_BOTH]	= "both",
+	};
 
 	/* enable Rx/Tx */
 	reg = gma_read16(hw, port, GM_GP_CTRL);
@@ -1648,8 +1649,7 @@
 		       "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
 		       sky2->netdev->name, sky2->speed,
 		       sky2->duplex == DUPLEX_FULL ? "full" : "half",
-		       (sky2->tx_pause && sky2->rx_pause) ? "both" :
-		       sky2->tx_pause ? "tx" : sky2->rx_pause ? "rx" : "none");
+		       fc_name[sky2->flow_status]);
 }
 
 static void sky2_link_down(struct sky2_port *sky2)
@@ -1664,7 +1664,7 @@
 	reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
 	gma_write16(hw, port, GM_GP_CTRL, reg);
 
-	if (sky2->rx_pause && !sky2->tx_pause) {
+	if (sky2->flow_status == FC_RX) {
 		/* restore Asymmetric Pause bit */
 		gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
 			     gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
@@ -1683,6 +1683,14 @@
 	sky2_phy_init(hw, port);
 }
 
+static enum flow_control sky2_flow(int rx, int tx)
+{
+	if (rx)
+		return tx ? FC_BOTH : FC_RX;
+	else
+		return tx ? FC_TX : FC_NONE;
+}
+
 static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
 {
 	struct sky2_hw *hw = sky2->hw;
@@ -1703,39 +1711,20 @@
 	}
 
 	sky2->speed = sky2_phy_speed(hw, aux);
-	if (sky2->speed == SPEED_1000) {
-		u16 ctl2 = gm_phy_read(hw, port, PHY_MARV_1000T_CTRL);
-		u16 lpa2 = gm_phy_read(hw, port, PHY_MARV_1000T_STAT);
-		if (lpa2  & PHY_B_1000S_MSF) {
-			printk(KERN_ERR PFX "%s: master/slave fault",
-			       sky2->netdev->name);
-			return -1;
-		}
-
-		if ((ctl2 & PHY_M_1000C_AFD) && (lpa2 & PHY_B_1000S_LP_FD))
-			sky2->duplex = DUPLEX_FULL;
-		else
-			sky2->duplex = DUPLEX_HALF;
-	} else {
-		u16 adv = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
-		if ((aux & adv) & PHY_AN_FULL)
-			sky2->duplex = DUPLEX_FULL;
-		else
-			sky2->duplex = DUPLEX_HALF;
-	}
+	sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
 
 	/* Pause bits are offset (9..8) */
 	if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)
 		aux >>= 6;
 
-	sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
-	sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0;
+	sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN,
+				      aux & PHY_M_PS_TX_P_EN);
 
-	if (sky2->duplex == DUPLEX_HALF && sky2->speed != SPEED_1000
+	if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
 	    && hw->chip_id != CHIP_ID_YUKON_EC_U)
-		sky2->rx_pause = sky2->tx_pause = 0;
+		sky2->flow_status = FC_NONE;
 
-	if (sky2->rx_pause || sky2->tx_pause)
+	if (aux & PHY_M_PS_RX_P_EN)
 		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
 	else
 		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1750,13 +1739,13 @@
 	struct sky2_port *sky2 = netdev_priv(dev);
 	u16 istatus, phystat;
 
+	if (!netif_running(dev))
+		return;
+
 	spin_lock(&sky2->phy_lock);
 	istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
 	phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
 
-	if (!netif_running(dev))
-		goto out;
-
 	if (netif_msg_intr(sky2))
 		printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
 		       sky2->netdev->name, istatus, phystat);
@@ -1907,7 +1896,7 @@
 		pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
 					       length, PCI_DMA_FROMDEVICE);
 		re->skb->ip_summed = CHECKSUM_NONE;
-		__skb_put(skb, length);
+		skb_put(skb, length);
 	}
 	return skb;
 }
@@ -1970,7 +1959,7 @@
 	if (skb_shinfo(skb)->nr_frags)
 		skb_put_frags(skb, hdr_space, length);
 	else
-		skb_put(skb, hdr_space);
+		skb_put(skb, length);
 	return skb;
 }
 
@@ -2016,6 +2005,10 @@
 
 error:
 	++sky2->net_stats.rx_errors;
+	if (status & GMR_FS_RX_FF_OV) {
+		sky2->net_stats.rx_fifo_errors++;
+		goto resubmit;
+	}
 
 	if (netif_msg_rx_err(sky2) && net_ratelimit())
 		printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
@@ -2027,8 +2020,6 @@
 		sky2->net_stats.rx_frame_errors++;
 	if (status & GMR_FS_CRC_ERR)
 		sky2->net_stats.rx_crc_errors++;
-	if (status & GMR_FS_RX_FF_OV)
-		sky2->net_stats.rx_fifo_errors++;
 
 	goto resubmit;
 }
@@ -2220,8 +2211,7 @@
 		/* PCI-Express uncorrectable Error occurred */
 		u32 pex_err;
 
-		pex_err = sky2_pci_read32(hw,
-					  hw->err_cap + PCI_ERR_UNCOR_STATUS);
+		pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT);
 
 		if (net_ratelimit())
 			printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
@@ -2229,20 +2219,15 @@
 
 		/* clear the interrupt */
 		sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-		sky2_pci_write32(hw,
-				 hw->err_cap + PCI_ERR_UNCOR_STATUS,
-				 0xffffffffUL);
+		sky2_pci_write32(hw, PEX_UNC_ERR_STAT,
+				       0xffffffffUL);
 		sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
-
-		/* In case of fatal error mask off to keep from getting stuck */
-		if (pex_err & (PCI_ERR_UNC_POISON_TLP | PCI_ERR_UNC_FCP
-			       | PCI_ERR_UNC_DLP)) {
+		if (pex_err & PEX_FATAL_ERRORS) {
 			u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
 			hwmsk &= ~Y2_IS_PCI_EXP;
 			sky2_write32(hw, B0_HWE_IMSK, hwmsk);
 		}
-
 	}
 
 	if (status & Y2_HWE_L1_MASK)
@@ -2364,7 +2349,7 @@
 	}
 }
 
-static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sky2_intr(int irq, void *dev_id)
 {
 	struct sky2_hw *hw = dev_id;
 	struct net_device *dev0 = hw->dev[0];
@@ -2423,7 +2408,6 @@
 	u16 status;
 	u8 t8;
 	int i;
-	u32 msk;
 
 	sky2_write8(hw, B0_CTST, CS_RST_CLR);
 
@@ -2464,13 +2448,9 @@
 	sky2_write8(hw, B0_CTST, CS_MRST_CLR);
 
 	/* clear any PEX errors */
-	if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) {
-		hw->err_cap = pci_find_ext_capability(hw->pdev, PCI_EXT_CAP_ID_ERR);
-		if (hw->err_cap)
-			sky2_pci_write32(hw,
-					 hw->err_cap + PCI_ERR_UNCOR_STATUS,
-					 0xffffffffUL);
-	}
+	if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+		sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL);
+
 
 	hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
 	hw->ports = 1;
@@ -2527,10 +2507,7 @@
 		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
 	}
 
-	msk = Y2_HWE_ALL_MASK;
-	if (!hw->err_cap)
-		msk &= ~Y2_IS_PCI_EXP;
-	sky2_write32(hw, B0_HWE_IMSK, msk);
+	sky2_write32(hw, B0_HWE_IMSK, Y2_HWE_ALL_MASK);
 
 	for (i = 0; i < hw->ports; i++)
 		sky2_gmac_reset(hw, i);
@@ -2762,7 +2739,7 @@
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 
-	if (sky2->autoneg != AUTONEG_ENABLE)
+	if (!netif_running(dev) || sky2->autoneg != AUTONEG_ENABLE)
 		return -EINVAL;
 
 	sky2_phy_reinit(sky2);
@@ -2864,6 +2841,14 @@
 	return 0;
 }
 
+static void inline sky2_add_filter(u8 filter[8], const u8 *addr)
+{
+	u32 bit;
+
+	bit = ether_crc(ETH_ALEN, addr) & 63;
+	filter[bit >> 3] |= 1 << (bit & 7);
+}
+
 static void sky2_set_multicast(struct net_device *dev)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
@@ -2872,7 +2857,10 @@
 	struct dev_mc_list *list = dev->mc_list;
 	u16 reg;
 	u8 filter[8];
+	int rx_pause;
+	static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
 
+	rx_pause = (sky2->flow_status == FC_RX || sky2->flow_status == FC_BOTH);
 	memset(filter, 0, sizeof(filter));
 
 	reg = gma_read16(hw, port, GM_RX_CTRL);
@@ -2880,18 +2868,19 @@
 
 	if (dev->flags & IFF_PROMISC)	/* promiscuous */
 		reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16)	/* all multicast */
+	else if (dev->flags & IFF_ALLMULTI)
 		memset(filter, 0xff, sizeof(filter));
-	else if (dev->mc_count == 0)	/* no multicast */
+	else if (dev->mc_count == 0 && !rx_pause)
 		reg &= ~GM_RXCR_MCF_ENA;
 	else {
 		int i;
 		reg |= GM_RXCR_MCF_ENA;
 
-		for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
-			u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
-			filter[bit / 8] |= 1 << (bit % 8);
-		}
+		if (rx_pause)
+			sky2_add_filter(filter, pause_mc_addr);
+
+		for (i = 0; list && i < dev->mc_count; i++, list = list->next)
+			sky2_add_filter(filter, list->dmi_addr);
 	}
 
 	gma_write16(hw, port, GM_MC_ADDR_H1,
@@ -3004,8 +2993,20 @@
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 
-	ecmd->tx_pause = sky2->tx_pause;
-	ecmd->rx_pause = sky2->rx_pause;
+	switch (sky2->flow_mode) {
+	case FC_NONE:
+		ecmd->tx_pause = ecmd->rx_pause = 0;
+		break;
+	case FC_TX:
+		ecmd->tx_pause = 1, ecmd->rx_pause = 0;
+		break;
+	case FC_RX:
+		ecmd->tx_pause = 0, ecmd->rx_pause = 1;
+		break;
+	case FC_BOTH:
+		ecmd->tx_pause = ecmd->rx_pause = 1;
+	}
+
 	ecmd->autoneg = sky2->autoneg;
 }
 
@@ -3015,10 +3016,10 @@
 	struct sky2_port *sky2 = netdev_priv(dev);
 
 	sky2->autoneg = ecmd->autoneg;
-	sky2->tx_pause = ecmd->tx_pause != 0;
-	sky2->rx_pause = ecmd->rx_pause != 0;
+	sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause);
 
-	sky2_phy_reinit(sky2);
+	if (netif_running(dev))
+		sky2_phy_reinit(sky2);
 
 	return 0;
 }
@@ -3248,8 +3249,8 @@
 
 	/* Auto speed and flow control */
 	sky2->autoneg = AUTONEG_ENABLE;
-	sky2->tx_pause = 1;
-	sky2->rx_pause = 1;
+	sky2->flow_mode = FC_BOTH;
+
 	sky2->duplex = -1;
 	sky2->speed = -1;
 	sky2->advertising = sky2_supported_modes(hw);
@@ -3298,8 +3299,7 @@
 }
 
 /* Handle software interrupt used during MSI test */
-static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id,
-					    struct pt_regs *regs)
+static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
 {
 	struct sky2_hw *hw = dev_id;
 	u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
@@ -3341,9 +3341,8 @@
 
 	if (!hw->msi_detected) {
 		/* MSI test failed, go back to INTx mode */
-		printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
-		       "switching to INTx mode. Please report this failure to "
-		       "the PCI maintainer and include system chipset information.\n",
+		printk(KERN_INFO PFX "%s: No interrupt generated using MSI, "
+		       "switching to INTx mode.\n",
 		       pci_name(pdev));
 
 		err = -EOPNOTSUPP;
@@ -3351,6 +3350,7 @@
 	}
 
 	sky2_write32(hw, B0_IMSK, 0);
+	sky2_read32(hw, B0_IMSK);
 
 	free_irq(pdev->irq, hw);
 
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index f66109a..6d2a23f 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -6,15 +6,24 @@
 
 #define ETH_JUMBO_MTU		9000	/* Maximum MTU supported */
 
-/* PCI device specific config registers */
+/* PCI config registers */
 enum {
 	PCI_DEV_REG1	= 0x40,
 	PCI_DEV_REG2	= 0x44,
+	PCI_DEV_STATUS  = 0x7c,
 	PCI_DEV_REG3	= 0x80,
 	PCI_DEV_REG4	= 0x84,
 	PCI_DEV_REG5    = 0x88,
 };
 
+enum {
+	PEX_DEV_CAP	= 0xe4,
+	PEX_DEV_CTRL	= 0xe8,
+	PEX_DEV_STA	= 0xea,
+	PEX_LNK_STAT	= 0xf2,
+	PEX_UNC_ERR_STAT= 0x104,
+};
+
 /* Yukon-2 */
 enum pci_dev_reg_1 {
 	PCI_Y2_PIG_ENA	 = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
@@ -63,6 +72,39 @@
 			       PCI_STATUS_REC_MASTER_ABORT | \
 			       PCI_STATUS_REC_TARGET_ABORT | \
 			       PCI_STATUS_PARITY)
+
+enum pex_dev_ctrl {
+	PEX_DC_MAX_RRS_MSK	= 7<<12, /* Bit 14..12:	Max. Read Request Size */
+	PEX_DC_EN_NO_SNOOP	= 1<<11,/* Enable No Snoop */
+	PEX_DC_EN_AUX_POW	= 1<<10,/* Enable AUX Power */
+	PEX_DC_EN_PHANTOM	= 1<<9,	/* Enable Phantom Functions */
+	PEX_DC_EN_EXT_TAG	= 1<<8,	/* Enable Extended Tag Field */
+	PEX_DC_MAX_PLS_MSK	= 7<<5,	/* Bit  7.. 5:	Max. Payload Size Mask */
+	PEX_DC_EN_REL_ORD	= 1<<4,	/* Enable Relaxed Ordering */
+	PEX_DC_EN_UNS_RQ_RP	= 1<<3,	/* Enable Unsupported Request Reporting */
+	PEX_DC_EN_FAT_ER_RP	= 1<<2,	/* Enable Fatal Error Reporting */
+	PEX_DC_EN_NFA_ER_RP	= 1<<1,	/* Enable Non-Fatal Error Reporting */
+	PEX_DC_EN_COR_ER_RP	= 1<<0,	/* Enable Correctable Error Reporting */
+};
+#define  PEX_DC_MAX_RD_RQ_SIZE(x) (((x)<<12) & PEX_DC_MAX_RRS_MSK)
+
+/* PEX_UNC_ERR_STAT	 PEX Uncorrectable Errors Status Register (Yukon-2) */
+enum pex_err {
+	PEX_UNSUP_REQ 	= 1<<20, /* Unsupported Request Error */
+
+	PEX_MALFOR_TLP	= 1<<18, /* Malformed TLP */
+
+	PEX_UNEXP_COMP	= 1<<16, /* Unexpected Completion */
+
+	PEX_COMP_TO	= 1<<14, /* Completion Timeout */
+	PEX_FLOW_CTRL_P	= 1<<13, /* Flow Control Protocol Error */
+	PEX_POIS_TLP	= 1<<12, /* Poisoned TLP */
+
+	PEX_DATA_LINK_P = 1<<4,	/* Data Link Protocol Error */
+	PEX_FATAL_ERRORS= (PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P),
+};
+
+
 enum csr_regs {
 	B0_RAP		= 0x0000,
 	B0_CTST		= 0x0004,
@@ -1534,7 +1576,7 @@
 
 	GMR_FS_ANY_ERR	= GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
 			  GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
-		  	  GMR_FS_MII_ERR | GMR_FS_BAD_FC |
+		  	  GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC |
 			  GMR_FS_UN_SIZE | GMR_FS_JABBER,
 };
 
@@ -1786,6 +1828,13 @@
 	dma_addr_t	frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT];
 };
 
+enum flow_control {
+	FC_NONE	= 0,
+	FC_TX	= 1,
+	FC_RX	= 2,
+	FC_BOTH	= 3,
+};
+
 struct sky2_port {
 	struct sky2_hw	     *hw;
 	struct net_device    *netdev;
@@ -1818,13 +1867,13 @@
 
 	dma_addr_t	     rx_le_map;
 	dma_addr_t	     tx_le_map;
-	u32		     advertising;	/* ADVERTISED_ bits */
+	u16		     advertising;	/* ADVERTISED_ bits */
 	u16		     speed;	/* SPEED_1000, SPEED_100, ... */
 	u8		     autoneg;	/* AUTONEG_ENABLE, AUTONEG_DISABLE */
 	u8		     duplex;	/* DUPLEX_HALF, DUPLEX_FULL */
-	u8		     rx_pause;
-	u8		     tx_pause;
 	u8		     rx_csum;
+ 	enum flow_control    flow_mode;
+ 	enum flow_control    flow_status;
 
 	struct net_device_stats net_stats;
 
@@ -1836,7 +1885,6 @@
 	struct net_device    *dev[2];
 
 	int		     pm_cap;
-	int		     err_cap;
 	u8	     	     chip_id;
 	u8		     chip_rev;
 	u8		     pmd_type;
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 7986514..889ef0d 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -127,7 +127,7 @@
 static void ultra_poll(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	ei_interrupt(dev->irq, dev, NULL);
+	ei_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index a621b17..2c43433 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -1074,7 +1074,7 @@
  * This is the main routine of the driver, to handle the device when
  * it needs some attention.
  */
-static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smc911x_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	unsigned long ioaddr = dev->base_addr;
@@ -1251,7 +1251,7 @@
 
 #ifdef SMC_USE_DMA
 static void
-smc911x_tx_dma_irq(int dma, void *data, struct pt_regs *regs)
+smc911x_tx_dma_irq(int dma, void *data)
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct smc911x_local *lp = netdev_priv(dev);
@@ -1285,7 +1285,7 @@
 		"%s: TX DMA irq completed\n", dev->name);
 }
 static void
-smc911x_rx_dma_irq(int dma, void *data, struct pt_regs *regs)
+smc911x_rx_dma_irq(int dma, void *data)
 {
 	struct net_device *dev = (struct net_device *)data;
 	unsigned long ioaddr = dev->base_addr;
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 5506a0d..c0d13d6 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -270,7 +270,7 @@
 /*
  . Handles the actual interrupt
 */
-static irqreturn_t smc_interrupt(int irq, void *, struct pt_regs *regs);
+static irqreturn_t smc_interrupt(int irq, void *);
 /*
  . This is a separate procedure to handle the receipt of a packet, to
  . leave the interrupt code looking slightly cleaner
@@ -1391,7 +1391,7 @@
  .
  ---------------------------------------------------------------------*/
 
-static irqreturn_t smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
+static irqreturn_t smc_interrupt(int irq, void * dev_id)
 {
 	struct net_device *dev 	= dev_id;
 	int ioaddr 		= dev->base_addr;
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index d7e5643..95b6478 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1284,7 +1284,7 @@
  * This is the main routine of the driver, to handle the device when
  * it needs some attention.
  */
-static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smc_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct smc_local *lp = netdev_priv(dev);
@@ -1400,7 +1400,7 @@
 static void smc_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	smc_interrupt(dev->irq, dev, NULL);
+	smc_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index fedd1a3..a864016 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -398,6 +398,42 @@
 
 #define SMC_IRQ_FLAGS		(0)
 
+#elif	defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	1
+#define SMC_NOWAIT		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS		(0)
+
+#elif	defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	1
+#define SMC_NOWAIT		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS		(0)
+
 #else
 
 #define SMC_CAN_USE_8BIT	1
@@ -507,7 +543,7 @@
 #endif
 
 static void
-smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
+smc_pxa_dma_irq(int dma, void *dummy)
 {
 	DCSR(dma) = 0;
 }
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index 870cf6b..ed7aa0a 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -293,17 +293,12 @@
  * The typical workload of the driver:
  * Handle the network interface interrupts.
  */
-static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sonic_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_device *dev = dev_id;
 	struct sonic_local *lp = netdev_priv(dev);
 	int status;
 
-	if (dev == NULL) {
-		printk(KERN_ERR "sonic_interrupt: irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
 	if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
 		return IRQ_NONE;
 
diff --git a/drivers/net/sonic.h b/drivers/net/sonic.h
index 7f886e8..7db13e4 100644
--- a/drivers/net/sonic.h
+++ b/drivers/net/sonic.h
@@ -328,7 +328,7 @@
 
 static int sonic_open(struct net_device *dev);
 static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t sonic_interrupt(int irq, void *dev_id);
 static void sonic_rx(struct net_device *dev);
 static int sonic_close(struct net_device *dev);
 static struct net_device_stats *sonic_get_stats(struct net_device *dev);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 1397fc5..418138d 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -55,12 +55,13 @@
 	      "<Jens.Osterkamp@de.ibm.com>");
 MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);
 
 static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
 static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;
 
-module_param(rx_descriptors, int, 0644);
-module_param(tx_descriptors, int, 0644);
+module_param(rx_descriptors, int, 0444);
+module_param(tx_descriptors, int, 0444);
 
 MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \
 		 "in rx chains");
@@ -300,7 +301,7 @@
 spider_net_init_chain(struct spider_net_card *card,
 		       struct spider_net_descr_chain *chain,
 		       struct spider_net_descr *start_descr,
-		       int direction, int no)
+		       int no)
 {
 	int i;
 	struct spider_net_descr *descr;
@@ -315,7 +316,7 @@
 
 		buf = pci_map_single(card->pdev, descr,
 				     SPIDER_NET_DESCR_SIZE,
-				     direction);
+				     PCI_DMA_BIDIRECTIONAL);
 
 		if (pci_dma_mapping_error(buf))
 			goto iommu_error;
@@ -329,11 +330,6 @@
 	(descr-1)->next = start_descr;
 	start_descr->prev = descr-1;
 
-	descr = start_descr;
-	if (direction == PCI_DMA_FROMDEVICE)
-		for (i=0; i < no; i++, descr++)
-			descr->next_descr_addr = descr->next->bus_addr;
-
 	spin_lock_init(&chain->lock);
 	chain->head = start_descr;
 	chain->tail = start_descr;
@@ -346,7 +342,7 @@
 		if (descr->bus_addr)
 			pci_unmap_single(card->pdev, descr->bus_addr,
 					 SPIDER_NET_DESCR_SIZE,
-					 direction);
+					 PCI_DMA_BIDIRECTIONAL);
 	return -ENOMEM;
 }
 
@@ -362,15 +358,15 @@
 	struct spider_net_descr *descr;
 
 	descr = card->rx_chain.head;
-	while (descr->next != card->rx_chain.head) {
+	do {
 		if (descr->skb) {
 			dev_kfree_skb(descr->skb);
 			pci_unmap_single(card->pdev, descr->buf_addr,
 					 SPIDER_NET_MAX_FRAME,
-					 PCI_DMA_FROMDEVICE);
+					 PCI_DMA_BIDIRECTIONAL);
 		}
 		descr = descr->next;
-	}
+	} while (descr != card->rx_chain.head);
 }
 
 /**
@@ -645,26 +641,41 @@
 spider_net_prepare_tx_descr(struct spider_net_card *card,
 			    struct sk_buff *skb)
 {
-	struct spider_net_descr *descr = card->tx_chain.head;
+	struct spider_net_descr *descr;
 	dma_addr_t buf;
+	unsigned long flags;
+	int length;
 
-	buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	length = skb->len;
+	if (length < ETH_ZLEN) {
+		if (skb_pad(skb, ETH_ZLEN-length))
+			return 0;
+		length = ETH_ZLEN;
+	}
+
+	buf = pci_map_single(card->pdev, skb->data, length, PCI_DMA_TODEVICE);
 	if (pci_dma_mapping_error(buf)) {
 		if (netif_msg_tx_err(card) && net_ratelimit())
 			pr_err("could not iommu-map packet (%p, %i). "
-				  "Dropping packet\n", skb->data, skb->len);
+				  "Dropping packet\n", skb->data, length);
 		card->spider_stats.tx_iommu_map_error++;
 		return -ENOMEM;
 	}
 
+	spin_lock_irqsave(&card->tx_chain.lock, flags);
+	descr = card->tx_chain.head;
+	card->tx_chain.head = descr->next;
+
 	descr->buf_addr = buf;
-	descr->buf_size = skb->len;
+	descr->buf_size = length;
 	descr->next_descr_addr = 0;
 	descr->skb = skb;
 	descr->data_status = 0;
 
 	descr->dmac_cmd_status =
 			SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+
 	if (skb->protocol == htons(ETH_P_IP))
 		switch (skb->nh.iph->protocol) {
 		case IPPROTO_TCP:
@@ -675,32 +686,51 @@
 			break;
 		}
 
+	/* Chain the bus address, so that the DMA engine finds this descr. */
 	descr->prev->next_descr_addr = descr->bus_addr;
 
+	card->netdev->trans_start = jiffies; /* set netdev watchdog timer */
 	return 0;
 }
 
-/**
- * spider_net_release_tx_descr - processes a used tx descriptor
- * @card: card structure
- * @descr: descriptor to release
- *
- * releases a used tx descriptor (unmapping, freeing of skb)
- */
-static inline void
-spider_net_release_tx_descr(struct spider_net_card *card)
+static int
+spider_net_set_low_watermark(struct spider_net_card *card)
 {
+	unsigned long flags;
+	int status;
+	int cnt=0;
+	int i;
 	struct spider_net_descr *descr = card->tx_chain.tail;
-	struct sk_buff *skb;
 
-	card->tx_chain.tail = card->tx_chain.tail->next;
-	descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+	/* Measure the length of the queue. Measurement does not
+	 * need to be precise -- does not need a lock. */
+	while (descr != card->tx_chain.head) {
+		status = descr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
+		if (status == SPIDER_NET_DESCR_NOT_IN_USE)
+			break;
+		descr = descr->next;
+		cnt++;
+	}
 
-	/* unmap the skb */
-	skb = descr->skb;
-	pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
-			PCI_DMA_TODEVICE);
-	dev_kfree_skb_any(skb);
+	/* If TX queue is short, don't even bother with interrupts */
+	if (cnt < card->num_tx_desc/4)
+		return cnt;
+
+	/* Set low-watermark 3/4th's of the way into the queue. */
+	descr = card->tx_chain.tail;
+	cnt = (cnt*3)/4;
+	for (i=0;i<cnt; i++)
+		descr = descr->next;
+
+	/* Set the new watermark, clear the old watermark */
+	spin_lock_irqsave(&card->tx_chain.lock, flags);
+	descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
+	if (card->low_watermark && card->low_watermark != descr)
+		card->low_watermark->dmac_cmd_status =
+		     card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
+	card->low_watermark = descr;
+	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+	return cnt;
 }
 
 /**
@@ -719,21 +749,29 @@
 spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
 {
 	struct spider_net_descr_chain *chain = &card->tx_chain;
+	struct spider_net_descr *descr;
+	struct sk_buff *skb;
+	u32 buf_addr;
+	unsigned long flags;
 	int status;
 
-	spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);
-
 	while (chain->tail != chain->head) {
-		status = spider_net_get_descr_status(chain->tail);
+		spin_lock_irqsave(&chain->lock, flags);
+		descr = chain->tail;
+
+		status = spider_net_get_descr_status(descr);
 		switch (status) {
 		case SPIDER_NET_DESCR_COMPLETE:
 			card->netdev_stats.tx_packets++;
-			card->netdev_stats.tx_bytes += chain->tail->skb->len;
+			card->netdev_stats.tx_bytes += descr->skb->len;
 			break;
 
 		case SPIDER_NET_DESCR_CARDOWNED:
-			if (!brutal)
+			if (!brutal) {
+				spin_unlock_irqrestore(&chain->lock, flags);
 				return 1;
+			}
+
 			/* fallthrough, if we release the descriptors
 			 * brutally (then we don't care about
 			 * SPIDER_NET_DESCR_CARDOWNED) */
@@ -750,11 +788,25 @@
 
 		default:
 			card->netdev_stats.tx_dropped++;
-			return 1;
+			if (!brutal) {
+				spin_unlock_irqrestore(&chain->lock, flags);
+				return 1;
+			}
 		}
-		spider_net_release_tx_descr(card);
-	}
 
+		chain->tail = descr->next;
+		descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+		skb = descr->skb;
+		buf_addr = descr->buf_addr;
+		spin_unlock_irqrestore(&chain->lock, flags);
+
+		/* unmap the skb */
+		if (skb) {
+			int len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+			pci_unmap_single(card->pdev, buf_addr, len, PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
+		}
+	}
 	return 0;
 }
 
@@ -763,8 +815,12 @@
  * @card: card structure
  * @descr: descriptor address to enable TX processing at
  *
- * spider_net_kick_tx_dma writes the current tx chain head as start address
- * of the tx descriptor chain and enables the transmission DMA engine
+ * This routine will start the transmit DMA running if
+ * it is not already running. This routine ned only be
+ * called when queueing a new packet to an empty tx queue.
+ * Writes the current tx chain head as start address
+ * of the tx descriptor chain and enables the transmission
+ * DMA engine.
  */
 static inline void
 spider_net_kick_tx_dma(struct spider_net_card *card)
@@ -804,65 +860,43 @@
 static int
 spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
+	int cnt;
 	struct spider_net_card *card = netdev_priv(netdev);
 	struct spider_net_descr_chain *chain = &card->tx_chain;
-	struct spider_net_descr *descr = chain->head;
-	unsigned long flags;
-	int result;
-
-	spin_lock_irqsave(&chain->lock, flags);
 
 	spider_net_release_tx_chain(card, 0);
 
-	if (chain->head->next == chain->tail->prev) {
+	if ((chain->head->next == chain->tail->prev) ||
+	   (spider_net_prepare_tx_descr(card, skb) != 0)) {
+
 		card->netdev_stats.tx_dropped++;
-		result = NETDEV_TX_LOCKED;
-		goto out;
+		netif_stop_queue(netdev);
+		return NETDEV_TX_BUSY;
 	}
 
-	if (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) {
-		card->netdev_stats.tx_dropped++;
-		result = NETDEV_TX_LOCKED;
-		goto out;
-	}
-
-	if (spider_net_prepare_tx_descr(card, skb) != 0) {
-		card->netdev_stats.tx_dropped++;
-		result = NETDEV_TX_BUSY;
-		goto out;
-	}
-
-	result = NETDEV_TX_OK;
-
-	spider_net_kick_tx_dma(card);
-	card->tx_chain.head = card->tx_chain.head->next;
-
-out:
-	spin_unlock_irqrestore(&chain->lock, flags);
-	netif_wake_queue(netdev);
-	return result;
+	cnt = spider_net_set_low_watermark(card);
+	if (cnt < 5)
+		spider_net_kick_tx_dma(card);
+	return NETDEV_TX_OK;
 }
 
 /**
  * spider_net_cleanup_tx_ring - cleans up the TX ring
  * @card: card structure
  *
- * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
- * interrupts to cleanup our TX ring) and returns sent packets to the stack
- * by freeing them
+ * spider_net_cleanup_tx_ring is called by either the tx_timer
+ * or from the NAPI polling routine.
+ * This routine releases resources associted with transmitted
+ * packets, including updating the queue tail pointer.
  */
 static void
 spider_net_cleanup_tx_ring(struct spider_net_card *card)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->tx_chain.lock, flags);
-
 	if ((spider_net_release_tx_chain(card, 0) != 0) &&
-	    (card->netdev->flags & IFF_UP))
+	    (card->netdev->flags & IFF_UP)) {
 		spider_net_kick_tx_dma(card);
-
-	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+		netif_wake_queue(card->netdev);
+	}
 }
 
 /**
@@ -1053,6 +1087,7 @@
 	int packets_to_do, packets_done = 0;
 	int no_more_packets = 0;
 
+	spider_net_cleanup_tx_ring(card);
 	packets_to_do = min(*budget, netdev->quota);
 
 	while (packets_to_do) {
@@ -1243,12 +1278,15 @@
 	case SPIDER_NET_PHYINT:
 	case SPIDER_NET_GMAC2INT:
 	case SPIDER_NET_GMAC1INT:
-	case SPIDER_NET_GIPSINT:
 	case SPIDER_NET_GFIFOINT:
 	case SPIDER_NET_DMACINT:
 	case SPIDER_NET_GSYSINT:
 		break; */
 
+	case SPIDER_NET_GIPSINT:
+		show_error = 0;
+		break;
+
 	case SPIDER_NET_GPWOPCMPINT:
 		/* PHY write operation completed */
 		show_error = 0;
@@ -1307,9 +1345,10 @@
 	case SPIDER_NET_GDTDCEINT:
 		/* chain end. If a descriptor should be sent, kick off
 		 * tx dma
-		if (card->tx_chain.tail == card->tx_chain.head)
+		if (card->tx_chain.tail != card->tx_chain.head)
 			spider_net_kick_tx_dma(card);
-		show_error = 0; */
+		*/
+		show_error = 0;
 		break;
 
 	/* case SPIDER_NET_G1TMCNTINT: not used. print a message */
@@ -1354,7 +1393,7 @@
 		if (netif_msg_intr(card))
 			pr_err("got descriptor chain end interrupt, "
 			       "restarting DMAC %c.\n",
-			       'D'+i-SPIDER_NET_GDDDCEINT);
+			       'D'-(i-SPIDER_NET_GDDDCEINT)/3);
 		spider_net_refill_rx_chain(card);
 		spider_net_enable_rxdmac(card);
 		show_error = 0;
@@ -1423,8 +1462,9 @@
 	}
 
 	if ((show_error) && (netif_msg_intr(card)))
-		pr_err("Got error interrupt, GHIINT0STS = 0x%08x, "
+		pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
 		       "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
+		       card->netdev->name,
 		       status_reg, error_reg1, error_reg2);
 
 	/* clear interrupt sources */
@@ -1445,7 +1485,7 @@
  * interrupts for this device and makes the stack poll the driver
  */
 static irqreturn_t
-spider_net_interrupt(int irq, void *ptr, struct pt_regs *regs)
+spider_net_interrupt(int irq, void *ptr)
 {
 	struct net_device *netdev = ptr;
 	struct spider_net_card *card = netdev_priv(netdev);
@@ -1460,6 +1500,8 @@
 		spider_net_rx_irq_off(card);
 		netif_rx_schedule(netdev);
 	}
+	if (status_reg & SPIDER_NET_TXINT)
+		netif_rx_schedule(netdev);
 
 	if (status_reg & SPIDER_NET_ERRINT )
 		spider_net_handle_error_irq(card, status_reg);
@@ -1481,7 +1523,7 @@
 spider_net_poll_controller(struct net_device *netdev)
 {
 	disable_irq(netdev->irq);
-	spider_net_interrupt(netdev->irq, netdev, NULL);
+	spider_net_interrupt(netdev->irq, netdev);
 	enable_irq(netdev->irq);
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -1599,7 +1641,7 @@
 			     SPIDER_NET_INT2_MASK_VALUE);
 
 	spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
-			     SPIDER_NET_GDTDCEIDIS);
+			     SPIDER_NET_GDTBSTA | SPIDER_NET_GDTDCEIDIS);
 }
 
 /**
@@ -1615,17 +1657,26 @@
 spider_net_open(struct net_device *netdev)
 {
 	struct spider_net_card *card = netdev_priv(netdev);
-	int result;
+	struct spider_net_descr *descr;
+	int i, result;
 
 	result = -ENOMEM;
 	if (spider_net_init_chain(card, &card->tx_chain, card->descr,
-			PCI_DMA_TODEVICE, card->tx_desc))
+	                          card->num_tx_desc))
 		goto alloc_tx_failed;
+
+	card->low_watermark = NULL;
+
+	/* rx_chain is after tx_chain, so offset is descr + tx_count */
 	if (spider_net_init_chain(card, &card->rx_chain,
-			card->descr + card->rx_desc,
-			PCI_DMA_FROMDEVICE, card->rx_desc))
+	                          card->descr + card->num_tx_desc,
+	                          card->num_rx_desc))
 		goto alloc_rx_failed;
 
+	descr = card->rx_chain.head;
+	for (i=0; i < card->num_rx_desc; i++, descr++)
+		descr->next_descr_addr = descr->next->bus_addr;
+
 	/* allocate rx skbs */
 	if (spider_net_alloc_rx_skbs(card))
 		goto alloc_skbs_failed;
@@ -1878,10 +1929,7 @@
 	spider_net_disable_rxdmac(card);
 
 	/* release chains */
-	if (spin_trylock(&card->tx_chain.lock)) {
-		spider_net_release_tx_chain(card, 1);
-		spin_unlock(&card->tx_chain.lock);
-	}
+	spider_net_release_tx_chain(card, 1);
 
 	spider_net_free_chain(card, &card->tx_chain);
 	spider_net_free_chain(card, &card->rx_chain);
@@ -2012,8 +2060,8 @@
 
 	card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
 
-	card->tx_desc = tx_descriptors;
-	card->rx_desc = rx_descriptors;
+	card->num_tx_desc = tx_descriptors;
+	card->num_rx_desc = rx_descriptors;
 
 	spider_net_setup_netdev_ops(netdev);
 
@@ -2252,6 +2300,8 @@
  */
 static int __init spider_net_init(void)
 {
+	printk(KERN_INFO "Spidernet version %s.\n", VERSION);
+
 	if (rx_descriptors < SPIDER_NET_RX_DESCRIPTORS_MIN) {
 		rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MIN;
 		pr_info("adjusting rx descriptors to %i.\n", rx_descriptors);
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index a59deda..b3b4611 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -24,6 +24,8 @@
 #ifndef _SPIDER_NET_H
 #define _SPIDER_NET_H
 
+#define VERSION "1.1 A"
+
 #include "sungem_phy.h"
 
 extern int spider_net_stop(struct net_device *netdev);
@@ -47,7 +49,7 @@
 #define SPIDER_NET_TX_DESCRIPTORS_MIN		16
 #define SPIDER_NET_TX_DESCRIPTORS_MAX		512
 
-#define SPIDER_NET_TX_TIMER			20
+#define SPIDER_NET_TX_TIMER			(HZ/5)
 
 #define SPIDER_NET_RX_CSUM_DEFAULT		1
 
@@ -189,7 +191,9 @@
 #define SPIDER_NET_MACMODE_VALUE	0x00000001
 #define SPIDER_NET_BURSTLMT_VALUE	0x00000200 /* about 16 us */
 
-/* 1(0)					enable r/tx dma
+/* DMAC control register GDMACCNTR
+ *
+ * 1(0)				enable r/tx dma
  *  0000000				fixed to 0
  *
  *         000000			fixed to 0
@@ -198,6 +202,7 @@
  *
  *                 000000		fixed to 0
  *                       00		burst alignment: 128 bytes
+ *                       11		burst alignment: 1024 bytes
  *
  *                         00000	fixed to 0
  *                              0	descr writeback size 32 bytes
@@ -208,10 +213,13 @@
 #define SPIDER_NET_DMA_RX_VALUE		0x80000000
 #define SPIDER_NET_DMA_RX_FEND_VALUE	0x00030003
 /* to set TX_DMA_EN */
-#define SPIDER_NET_TX_DMA_EN		0x80000000
-#define SPIDER_NET_GDTDCEIDIS		0x00000002
-#define SPIDER_NET_DMA_TX_VALUE		SPIDER_NET_TX_DMA_EN | \
-					SPIDER_NET_GDTDCEIDIS
+#define SPIDER_NET_TX_DMA_EN           0x80000000
+#define SPIDER_NET_GDTBSTA             0x00000300
+#define SPIDER_NET_GDTDCEIDIS          0x00000002
+#define SPIDER_NET_DMA_TX_VALUE        SPIDER_NET_TX_DMA_EN | \
+                                       SPIDER_NET_GDTBSTA | \
+                                       SPIDER_NET_GDTDCEIDIS
+
 #define SPIDER_NET_DMA_TX_FEND_VALUE	0x00030003
 
 /* SPIDER_NET_UA_DESCR_VALUE is OR'ed with the unicast address */
@@ -320,13 +328,10 @@
 	SPIDER_NET_GRISPDNGINT
 };
 
-#define SPIDER_NET_TXINT	( (1 << SPIDER_NET_GTTEDINT) | \
-				  (1 << SPIDER_NET_GDTDCEINT) | \
-				  (1 << SPIDER_NET_GDTFDCINT) )
+#define SPIDER_NET_TXINT	( (1 << SPIDER_NET_GDTFDCINT) )
 
-/* we rely on flagged descriptor interrupts*/
-#define SPIDER_NET_RXINT	( (1 << SPIDER_NET_GDAFDCINT) | \
-				  (1 << SPIDER_NET_GRMFLLINT) )
+/* We rely on flagged descriptor interrupts */
+#define SPIDER_NET_RXINT	( (1 << SPIDER_NET_GDAFDCINT) )
 
 #define SPIDER_NET_ERRINT	( 0xffffffff & \
 				  (~SPIDER_NET_TXINT) & \
@@ -349,6 +354,7 @@
 #define SPIDER_NET_DESCR_FORCE_END		0x50000000 /* used in rx and tx */
 #define SPIDER_NET_DESCR_CARDOWNED		0xA0000000 /* used in rx and tx */
 #define SPIDER_NET_DESCR_NOT_IN_USE		0xF0000000
+#define SPIDER_NET_DESCR_TXDESFLG		0x00800000
 
 struct spider_net_descr {
 	/* as defined by the hardware */
@@ -433,6 +439,7 @@
 
 	struct spider_net_descr_chain tx_chain;
 	struct spider_net_descr_chain rx_chain;
+	struct spider_net_descr *low_watermark;
 
 	struct net_device_stats netdev_stats;
 
@@ -448,8 +455,8 @@
 
 	/* for ethtool */
 	int msg_enable;
-	int rx_desc;
-	int tx_desc;
+	int num_rx_desc;
+	int num_tx_desc;
 	struct spider_net_extra_stats spider_stats;
 
 	struct spider_net_descr descr[0];
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index 589e436..91b9951 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -76,7 +76,7 @@
 	/* clear and fill out info */
 	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
 	strncpy(drvinfo->driver, spider_net_driver_name, 32);
-	strncpy(drvinfo->version, "0.1", 32);
+	strncpy(drvinfo->version, VERSION, 32);
 	strcpy(drvinfo->fw_version, "no information");
 	strncpy(drvinfo->bus_info, pci_name(card->pdev), 32);
 }
@@ -158,9 +158,9 @@
 	struct spider_net_card *card = netdev->priv;
 
 	ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
-	ering->tx_pending = card->tx_desc;
+	ering->tx_pending = card->num_tx_desc;
 	ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX;
-	ering->rx_pending = card->rx_desc;
+	ering->rx_pending = card->num_rx_desc;
 }
 
 static int spider_net_get_stats_count(struct net_device *netdev)
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 3d617e8..7a0aee6 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -632,7 +632,7 @@
 static void	tx_timeout(struct net_device *dev);
 static void	init_ring(struct net_device *dev);
 static int	start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
 static void	netdev_error(struct net_device *dev, int intr_status);
 static int	__netdev_rx(struct net_device *dev, int *quota);
 static void	refill_rx_ring(struct net_device *dev);
@@ -1307,7 +1307,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index 0605461..a3220a9 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -122,7 +122,7 @@
      DELAY_16(); DELAY_16(); } }
 
 static int     sun3_82586_probe1(struct net_device *dev,int ioaddr);
-static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
+static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id);
 static int     sun3_82586_open(struct net_device *dev);
 static int     sun3_82586_close(struct net_device *dev);
 static int     sun3_82586_send_packet(struct sk_buff *,struct net_device *);
@@ -330,7 +330,7 @@
 out1:
 	free_netdev(dev);
 out:
-	iounmap((void *)ioaddr);
+	iounmap((void __iomem *)ioaddr);
 	return ERR_PTR(err);
 }
 
@@ -678,7 +678,7 @@
  * Interrupt Handler ...
  */
 
-static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
+static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	unsigned short stat;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 61a832c..b865db3 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -237,7 +237,7 @@
 static int lance_open( struct net_device *dev );
 static void lance_init_ring( struct net_device *dev );
 static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
+static irqreturn_t lance_interrupt( int irq, void *dev_id);
 static int lance_rx( struct net_device *dev );
 static int lance_close( struct net_device *dev );
 static struct net_device_stats *lance_get_stats( struct net_device *dev );
@@ -286,7 +286,7 @@
 
 out1:
 #ifdef CONFIG_SUN3
-	iounmap((void *)dev->base_addr);
+	iounmap((void __iomem *)dev->base_addr);
 #endif
 out:
 	free_netdev(dev);
@@ -326,7 +326,7 @@
 		ioaddr_probe[1] = tmp2;
 
 #ifdef CONFIG_SUN3
-		iounmap((void *)ioaddr);
+		iounmap((void __iomem *)ioaddr);
 #endif
 		return 0;
 	}
@@ -642,7 +642,7 @@
 
 /* The LANCE interrupt handler. */
 
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t lance_interrupt( int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct lance_private *lp = netdev_priv(dev);
@@ -956,7 +956,7 @@
 {
 	unregister_netdev(sun3lance_dev);
 #ifdef CONFIG_SUN3
-	iounmap((void *)sun3lance_dev->base_addr);
+	iounmap((void __iomem *)sun3lance_dev->base_addr);
 #endif
 	free_netdev(sun3lance_dev);
 }
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 9e4be86..18f8885 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -42,7 +42,7 @@
 #define DRV_RELDATE	"11/24/03"
 #define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
 
-static char version[] __initdata =
+static char version[] =
 	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
 
 MODULE_VERSION(DRV_VERSION);
@@ -888,7 +888,7 @@
 		printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", bp->dev->name);
 }
 
-static irqreturn_t bigmac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bigmac_interrupt(int irq, void *dev_id)
 {
 	struct bigmac *bp = (struct bigmac *) dev_id;
 	u32 qec_status, bmac_status;
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 6b8f4ba..41c503d 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -420,7 +420,7 @@
 static void init_ring(struct net_device *dev);
 static int  start_tx(struct sk_buff *skb, struct net_device *dev);
 static int reset_tx (struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
 static void rx_poll(unsigned long data);
 static void tx_poll(unsigned long data);
 static void refill_rx (struct net_device *dev);
@@ -1102,7 +1102,7 @@
 
 /* The interrupt handler cleans up after the Tx thread,
    and schedule a Rx thread work */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *)dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 0975695..253e96e 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -932,7 +932,7 @@
 	return 0;
 }
 
-static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gem_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct gem *gp = dev->priv;
@@ -975,7 +975,7 @@
 	/* gem_interrupt is safe to reentrance so no need
 	 * to disable_irq here.
 	 */
-	gem_interrupt(dev->irq, dev, NULL);
+	gem_interrupt(dev->irq, dev);
 }
 #endif
 
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index f05eea5..9d7cd13 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2093,10 +2093,10 @@
 	RXD((">"));
 }
 
-static irqreturn_t happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t happy_meal_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct happy_meal *hp  = dev->priv;
+	struct net_device *dev = dev_id;
+	struct happy_meal *hp  = netdev_priv(dev);
 	u32 happy_status       = hme_read32(hp, hp->gregs + GREG_STAT);
 
 	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
@@ -2132,7 +2132,7 @@
 }
 
 #ifdef CONFIG_SBUS
-static irqreturn_t quattro_sbus_interrupt(int irq, void *cookie, struct pt_regs *ptregs)
+static irqreturn_t quattro_sbus_interrupt(int irq, void *cookie)
 {
 	struct quattro *qp = (struct quattro *) cookie;
 	int i;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index feb42db..5b00d79 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -820,9 +820,9 @@
 	spin_unlock(&lp->lock);
 }
 
-static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *)dev_id;
+	struct net_device *dev = dev_id;
 	struct lance_private *lp = netdev_priv(dev);
 	int csr0;
 
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 9202a1c..7874eb1 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -466,9 +466,9 @@
  * so we just run through each qe and check to see who is signaling
  * and thus needs to be serviced.
  */
-static irqreturn_t qec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t qec_interrupt(int irq, void *dev_id)
 {
-	struct sunqec *qecp = (struct sunqec *) dev_id;
+	struct sunqec *qecp = dev_id;
 	u32 qec_status;
 	int channel = 0;
 
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 60f0265..81ed82f0 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -453,7 +453,7 @@
 static int	tc35815_open(struct net_device *dev);
 static int	tc35815_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void     tc35815_tx_timeout(struct net_device *dev);
-static irqreturn_t tc35815_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t tc35815_interrupt(int irq, void *dev_id);
 static void	tc35815_rx(struct net_device *dev);
 static void	tc35815_txdone(struct net_device *dev);
 static int	tc35815_close(struct net_device *dev);
@@ -1044,7 +1044,7 @@
  * The typical workload of the driver:
  *   Handle the network interface interrupts.
  */
-static irqreturn_t tc35815_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct tc35815_regs *tr;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index c25ba27..8e39849 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.66"
-#define DRV_MODULE_RELDATE	"September 23, 2006"
+#define DRV_MODULE_VERSION	"3.67"
+#define DRV_MODULE_RELDATE	"October 18, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -129,7 +129,7 @@
 #define RX_JUMBO_PKT_BUF_SZ	(9046 + tp->rx_offset + 64)
 
 /* minimum number of free TX descriptors required to wake up TX process */
-#define TG3_TX_WAKEUP_THRESH		(TG3_TX_RING_SIZE / 4)
+#define TG3_TX_WAKEUP_THRESH(tp)		((tp)->tx_pending / 4)
 
 /* number of ETHTOOL_GSTATS u64's */
 #define TG3_NUM_STATS		(sizeof(struct tg3_ethtool_stats)/sizeof(u64))
@@ -3075,10 +3075,10 @@
 	smp_mb();
 
 	if (unlikely(netif_queue_stopped(tp->dev) &&
-		     (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) {
+		     (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) {
 		netif_tx_lock(tp->dev);
 		if (netif_queue_stopped(tp->dev) &&
-		    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))
+		    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))
 			netif_wake_queue(tp->dev);
 		netif_tx_unlock(tp->dev);
 	}
@@ -3481,7 +3481,7 @@
 /* One-shot MSI handler - Chip automatically disables interrupt
  * after sending MSI so driver doesn't have to do it.
  */
-static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
@@ -3499,7 +3499,7 @@
  * flush status block and interrupt mailbox. PCI ordering rules
  * guarantee that MSI will arrive after the status block.
  */
-static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_msi(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
@@ -3520,7 +3520,7 @@
 	return IRQ_RETVAL(1);
 }
 
-static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
@@ -3563,7 +3563,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
@@ -3606,8 +3606,7 @@
 }
 
 /* ISR for interrupt test */
-static irqreturn_t tg3_test_isr(int irq, void *dev_id,
-		struct pt_regs *regs)
+static irqreturn_t tg3_test_isr(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
@@ -3651,7 +3650,7 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	tg3_interrupt(tp->pdev->irq, dev, NULL);
+	tg3_interrupt(tp->pdev->irq, dev);
 }
 #endif
 
@@ -3929,7 +3928,7 @@
 	tp->tx_prod = entry;
 	if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
 		netif_stop_queue(dev);
-		if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
+		if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
 			netif_wake_queue(tp->dev);
 	}
 
@@ -4144,7 +4143,7 @@
 	tp->tx_prod = entry;
 	if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
 		netif_stop_queue(dev);
-		if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
+		if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
 			netif_wake_queue(tp->dev);
 	}
 
@@ -6838,7 +6837,7 @@
 
 static int tg3_request_irq(struct tg3 *tp)
 {
-	irqreturn_t (*fn)(int, void *, struct pt_regs *);
+	irq_handler_t fn;
 	unsigned long flags;
 	struct net_device *dev = tp->dev;
 
@@ -8107,7 +8106,10 @@
 
 	if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
 	    (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
-	    (ering->tx_pending > TG3_TX_RING_SIZE - 1))
+	    (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
+	    (ering->tx_pending <= MAX_SKB_FRAGS) ||
+	    ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) &&
+	     (ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
 		return -EINVAL;
 
 	if (netif_running(dev)) {
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 8d807bf..e14f5a0 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -289,7 +289,7 @@
 static int      TLan_Init( struct net_device * );
 static int	TLan_Open( struct net_device *dev );
 static int	TLan_StartTx( struct sk_buff *, struct net_device *);
-static irqreturn_t TLan_HandleInterrupt( int, void *, struct pt_regs *);
+static irqreturn_t TLan_HandleInterrupt( int, void *);
 static int	TLan_Close( struct net_device *);
 static struct	net_device_stats *TLan_GetStats( struct net_device *);
 static void	TLan_SetMulticastList( struct net_device *);
@@ -824,7 +824,7 @@
 static void TLan_Poll(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	TLan_HandleInterrupt(dev->irq, dev, NULL);
+	TLan_HandleInterrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -1151,7 +1151,6 @@
 	 *			occurred.
 	 *		dev_id	A pointer to the device assigned to
 	 *			this irq line.
-	 *		regs	???
 	 *
 	 *	This function handles an interrupt generated by its
 	 *	assigned TLAN adapter.  The function deactivates
@@ -1162,7 +1161,7 @@
 	 *
 	 **************************************************************/
 
-static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id)
 {
 	u32		ack;
 	struct net_device	*dev;
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index 412390b..7580bde 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -130,7 +130,7 @@
 static void xl_dn_comp(struct net_device *dev); 
 static int xl_close(struct net_device *dev);
 static void xl_set_rx_mode(struct net_device *dev);
-static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t xl_interrupt(int irq, void *dev_id);
 static struct net_device_stats * xl_get_stats(struct net_device *dev);
 static int xl_set_mac_address(struct net_device *dev, void *addr) ; 
 static void xl_arb_cmd(struct net_device *dev);
@@ -1042,7 +1042,7 @@
 	return  ; 
 }
 
-static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+static irqreturn_t xl_interrupt(int irq, void *dev_id) 
 {
 	struct net_device *dev = (struct net_device *)dev_id;
  	struct xl_private *xl_priv =(struct xl_private *)dev->priv;
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 4470025..bfe5986 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -197,7 +197,7 @@
 static void 	tok_set_multicast_list(struct net_device *dev);
 static int 	tok_send_packet(struct sk_buff *skb, struct net_device *dev);
 static int 	tok_close(struct net_device *dev);
-static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t tok_interrupt(int irq, void *dev_id);
 static void 	initial_tok_int(struct net_device *dev);
 static void 	tr_tx(struct net_device *dev);
 static void 	tr_rx(struct net_device *dev);
@@ -1166,7 +1166,7 @@
 
 /******************************************************************************/
 
-static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tok_interrupt(int irq, void *dev_id)
 {
 	unsigned char status;
 	/*  unsigned char status_even ; */
@@ -1178,7 +1178,7 @@
 
 	dev = dev_id;
 #if TR_VERBOSE
-	DPRINTK("Int from tok_driver, dev : %p irq%d regs=%p\n", dev,irq,regs);
+	DPRINTK("Int from tok_driver, dev : %p irq%d\n", dev,irq);
 #endif
 	ti = (struct tok_info *) dev->priv;
 	if (ti->sram_phys & 1)
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index bfc8c3e..e999feb 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -206,8 +206,7 @@
 static int streamer_xmit(struct sk_buff *skb, struct net_device *dev);
 static int streamer_close(struct net_device *dev);
 static void streamer_set_rx_mode(struct net_device *dev);
-static irqreturn_t streamer_interrupt(int irq, void *dev_id,
-			       struct pt_regs *regs);
+static irqreturn_t streamer_interrupt(int irq, void *dev_id);
 static struct net_device_stats *streamer_get_stats(struct net_device *dev);
 static int streamer_set_mac_address(struct net_device *dev, void *addr);
 static void streamer_arb_cmd(struct net_device *dev);
@@ -1028,7 +1027,7 @@
 	}			/* end for all completed rx descriptors */
 }
 
-static irqreturn_t streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t streamer_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct streamer_private *streamer_priv =
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 666bbaa..ed274d6 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -70,7 +70,7 @@
 static void madgemc_setsifsel(struct net_device *dev, int val);
 static void madgemc_setint(struct net_device *dev, int val);
 
-static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t madgemc_interrupt(int irq, void *dev_id);
 
 /*
  * These work around paging, however they don't guarentee you're on the
@@ -417,7 +417,7 @@
  * exhausted all contiguous interrupts.
  *
  */
-static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t madgemc_interrupt(int irq, void *dev_id)
 {
 	int pending,reg1;
 	struct net_device *dev;
@@ -451,7 +451,7 @@
 			outb(reg1, dev->base_addr + MC_CONTROL_REG1);
 
 			/* Continue handling as normal */
-			tms380tr_interrupt(irq, dev_id, regs);
+			tms380tr_interrupt(irq, dev_id);
 
 			pending = SIFREADW(SIFSTS); /* restart - the SIF way */
 
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 8583148..cd142d0 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -185,7 +185,7 @@
 static int olympic_close(struct net_device *dev);
 static void olympic_set_rx_mode(struct net_device *dev);
 static void olympic_freemem(struct net_device *dev) ;  
-static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t olympic_interrupt(int irq, void *dev_id);
 static struct net_device_stats * olympic_get_stats(struct net_device *dev);
 static int olympic_set_mac_address(struct net_device *dev, void *addr) ; 
 static void olympic_arb_cmd(struct net_device *dev);
@@ -925,7 +925,7 @@
 	return ; 
 }
  
-static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+static irqreturn_t olympic_interrupt(int irq, void *dev_id) 
 {
 	struct net_device *dev= (struct net_device *)dev_id;
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 85a7f79..46dabdb 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -141,7 +141,7 @@
 static int smctr_init_tx_bdbs(struct net_device *dev);
 static int smctr_init_tx_fcbs(struct net_device *dev);
 static int smctr_internal_self_test(struct net_device *dev);
-static irqreturn_t smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t smctr_interrupt(int irq, void *dev_id);
 static int smctr_issue_enable_int_cmd(struct net_device *dev,
         __u16 interrupt_enable_mask);
 static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
@@ -1980,7 +1980,7 @@
 /*
  * The typical workload of the driver: Handle the network interface interrupts.
  */
-static irqreturn_t smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smctr_interrupt(int irq, void *dev_id)
 {
         struct net_device *dev = dev_id;
         struct net_local *tp;
@@ -1990,15 +1990,8 @@
         __u8 isb_type, isb_subtype;
         __u16 isb_index;
 
-        if(dev == NULL)
-        {
-                printk(KERN_CRIT "%s: irq %d for unknown device.\n", dev->name, irq);
-                return IRQ_NONE;
-        }
-
         ioaddr = dev->base_addr;
         tp = netdev_priv(dev);
-        
 
         if(tp->status == NOT_INITIALIZED)
                 return IRQ_NONE;
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index c192559..ea797ca 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -744,18 +744,13 @@
 /*
  * The typical workload of the driver: Handle the network interface interrupts.
  */
-irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t tms380tr_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *tp;
 	unsigned short irq_type;
 	int handled = 0;
 
-	if(dev == NULL) {
-		printk(KERN_INFO "%s: irq %d for unknown device.\n", dev->name, irq);
-		return IRQ_NONE;
-	}
-
 	tp = netdev_priv(dev);
 
 	irq_type = SIFREADW(SIFSTS);
diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h
index 30452c6..2a16078 100644
--- a/drivers/net/tokenring/tms380tr.h
+++ b/drivers/net/tokenring/tms380tr.h
@@ -16,7 +16,7 @@
 /* module prototypes */
 int tms380tr_open(struct net_device *dev);
 int tms380tr_close(struct net_device *dev);
-irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t tms380tr_interrupt(int irq, void *dev_id);
 int tmsdev_init(struct net_device *dev, struct device *pdev);
 void tmsdev_term(struct net_device *dev);
 void tms380tr_wait(unsigned long time);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index e1b48bd..f6b3a94 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -484,7 +484,7 @@
 	de->rx_tail = rx_tail;
 }
 
-static irqreturn_t de_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t de_interrupt (int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct de_private *de = dev->priv;
@@ -1730,7 +1730,7 @@
 }
 
 /* Note: this routine returns extra data bits for size detection. */
-static unsigned __init tulip_read_eeprom(void __iomem *regs, int location, int addr_len)
+static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, int addr_len)
 {
 	int i;
 	unsigned retval = 0;
@@ -1926,7 +1926,7 @@
 	goto fill_defaults;
 }
 
-static int __init de_init_one (struct pci_dev *pdev,
+static int __devinit de_init_one (struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
 	struct net_device *dev;
@@ -2082,7 +2082,7 @@
 	return rc;
 }
 
-static void __exit de_remove_one (struct pci_dev *pdev)
+static void __devexit de_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct de_private *de = dev->priv;
@@ -2164,7 +2164,7 @@
 	.name		= DRV_NAME,
 	.id_table	= de_pci_tbl,
 	.probe		= de_init_one,
-	.remove		= __exit_p(de_remove_one),
+	.remove		= __devexit_p(de_remove_one),
 #ifdef CONFIG_PM
 	.suspend	= de_suspend,
 	.resume		= de_resume,
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index fb5fa7d..3f4b640 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -896,7 +896,7 @@
 */
 static int     de4x5_open(struct net_device *dev);
 static int     de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t de4x5_interrupt(int irq, void *dev_id);
 static int     de4x5_close(struct net_device *dev);
 static struct  net_device_stats *de4x5_get_stats(struct net_device *dev);
 static void    de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len);
@@ -1538,18 +1538,14 @@
 ** interrupt is asserted and this routine entered.
 */
 static irqreturn_t
-de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+de4x5_interrupt(int irq, void *dev_id)
 {
-    struct net_device *dev = (struct net_device *)dev_id;
+    struct net_device *dev = dev_id;
     struct de4x5_private *lp;
     s32 imr, omr, sts, limit;
     u_long iobase;
     unsigned int handled = 0;
 
-    if (dev == NULL) {
-	printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq);
-	return IRQ_NONE;
-    }
     lp = netdev_priv(dev);
     spin_lock(&lp->lock);
     iobase = dev->base_addr;
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index ccf2c225..4dd8a0b 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -300,7 +300,7 @@
 static void dmfe_set_filter_mode(struct DEVICE *);
 static const struct ethtool_ops netdev_ethtool_ops;
 static u16 read_srom_word(long ,int);
-static irqreturn_t dmfe_interrupt(int , void *, struct pt_regs *);
+static irqreturn_t dmfe_interrupt(int , void *);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void poll_dmfe (struct net_device *dev);
 #endif
@@ -735,7 +735,7 @@
  *	receive the packet to upper layer, free the transmitted packet
  */
 
-static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dmfe_interrupt(int irq, void *dev_id)
 {
 	struct DEVICE *dev = dev_id;
 	struct dmfe_board_info *db = netdev_priv(dev);
@@ -806,7 +806,7 @@
 	/* disable_irq here is not very nice, but with the lockless
 	   interrupt handler we have no other choice. */
 	disable_irq(dev->irq);
-	dmfe_interrupt (dev->irq, dev, NULL);
+	dmfe_interrupt (dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 7f8f5d4..e3488d7 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -496,7 +496,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+irqreturn_t tulip_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *)dev_instance;
 	struct tulip_private *tp = netdev_priv(dev);
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 25668dd..ad107f4 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -424,7 +424,7 @@
 /* interrupt.c */
 extern unsigned int tulip_max_interrupt_work;
 extern int tulip_rx_copybreak;
-irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+irqreturn_t tulip_interrupt(int irq, void *dev_instance);
 int tulip_refill_rx(struct net_device *dev);
 #ifdef CONFIG_TULIP_NAPI
 int tulip_poll(struct net_device *dev, int *budget);
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 831919a..0aee618 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1823,7 +1823,7 @@
 	/* disable_irq here is not very nice, but with the lockless
 	   interrupt handler we have no other choice. */
 	disable_irq(dev->irq);
-	tulip_interrupt (dev->irq, dev, NULL);
+	tulip_interrupt (dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 0b176be..229158e 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -224,7 +224,7 @@
 static void uli526x_set_filter_mode(struct net_device *);
 static const struct ethtool_ops netdev_ethtool_ops;
 static u16 read_srom_word(long, int);
-static irqreturn_t uli526x_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t uli526x_interrupt(int, void *);
 static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
 static void allocate_rx_buffer(struct uli526x_board_info *);
 static void update_cr6(u32, unsigned long);
@@ -659,7 +659,7 @@
  *	receive the packet to upper layer, free the transmitted packet
  */
 
-static irqreturn_t uli526x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct uli526x_board_info *db = netdev_priv(dev);
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 2fca1ee..002a05e 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -332,7 +332,7 @@
 static int alloc_ringdesc(struct net_device *dev);
 static void free_ringdesc(struct netdev_private *np);
 static int  start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
 static void netdev_error(struct net_device *dev, int intr_status);
 static int  netdev_rx(struct net_device *dev);
 static u32 __set_rx_mode(struct net_device *dev);
@@ -1110,7 +1110,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *)dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 629eac6..61d3130 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -114,7 +114,7 @@
 /* Function prototypes */
 static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id);
 static void xircom_remove(struct pci_dev *pdev);
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t xircom_interrupt(int irq, void *dev_instance);
 static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int xircom_open(struct net_device *dev);
 static int xircom_close(struct net_device *dev);
@@ -334,7 +334,7 @@
 	leave("xircom_remove");
 }
 
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct xircom_private *card = netdev_priv(dev);
@@ -513,7 +513,7 @@
 static void xircom_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	xircom_interrupt(dev->irq, dev, NULL);
+	xircom_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index 312788c..a998c5d 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -328,7 +328,7 @@
 static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int xircom_rx(struct net_device *dev);
 static void xircom_media_change(struct net_device *dev);
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t xircom_interrupt(int irq, void *dev_instance);
 static int xircom_close(struct net_device *dev);
 static struct net_device_stats *xircom_get_stats(struct net_device *dev);
 static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -1044,7 +1044,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct xircom_private *tp = netdev_priv(dev);
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index d5c32e9..3bf9e63 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1826,7 +1826,7 @@
 }
 
 static irqreturn_t
-typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+typhoon_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct typhoon *tp = dev->priv;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 700ebd7..b378880 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2,14 +2,11 @@
  * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
  *
  * Author: Shlomi Gridish <gridish@freescale.com>
+ *	   Li Yang <leoli@freescale.com>
  *
  * Description:
  * QE UCC Gigabit Ethernet Driver
  *
- * Changelog:
- * Jul 6, 2006 Li Yang <LeoLi@freescale.com>
- * - Rearrange code and style fixes
- *
  * 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
@@ -31,9 +28,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/fsl_devices.h>
 #include <linux/ethtool.h>
-#include <linux/platform_device.h>
 #include <linux/mii.h>
 
+#include <asm/of_device.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -70,7 +67,7 @@
 
 static DEFINE_SPINLOCK(ugeth_lock);
 
-static ucc_geth_info_t ugeth_primary_info = {
+static struct ucc_geth_info ugeth_primary_info = {
 	.uf_info = {
 		    .bd_mem_part = MEM_PART_SYSTEM,
 		    .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
@@ -163,7 +160,7 @@
 	.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
 };
 
-static ucc_geth_info_t ugeth_info[8];
+static struct ucc_geth_info ugeth_info[8];
 
 #ifdef DEBUG
 static void mem_disp(u8 *addr, int size)
@@ -219,8 +216,8 @@
 	}
 }
 
-static int get_interface_details(enet_interface_e enet_interface,
-				 enet_speed_e *speed,
+static int get_interface_details(enum enet_interface enet_interface,
+				 enum enet_speed *speed,
 				 int *r10m,
 				 int *rmm,
 				 int *rpm,
@@ -283,7 +280,7 @@
 	return 0;
 }
 
-static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd)
+static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd)
 {
 	struct sk_buff *skb = NULL;
 
@@ -303,21 +300,19 @@
 
 	skb->dev = ugeth->dev;
 
-	BD_BUFFER_SET(bd,
+	out_be32(&((struct qe_bd *)bd)->buf,
 		      dma_map_single(NULL,
 				     skb->data,
 				     ugeth->ug_info->uf_info.max_rx_buf_length +
 				     UCC_GETH_RX_DATA_BUF_ALIGNMENT,
 				     DMA_FROM_DEVICE));
 
-	BD_STATUS_AND_LENGTH_SET(bd,
-				 (R_E | R_I |
-				  (BD_STATUS_AND_LENGTH(bd) & R_W)));
+	out_be32((u32 *)bd, (R_E | R_I | (in_be32((u32 *)bd) & R_W)));
 
 	return skb;
 }
 
-static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ)
+static int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ)
 {
 	u8 *bd;
 	u32 bd_status;
@@ -328,7 +323,7 @@
 	i = 0;
 
 	do {
-		bd_status = BD_STATUS_AND_LENGTH(bd);
+		bd_status = in_be32((u32*)bd);
 		skb = get_new_skb(ugeth, bd);
 
 		if (!skb)	/* If can not allocate data buffer,
@@ -338,19 +333,19 @@
 		ugeth->rx_skbuff[rxQ][i] = skb;
 
 		/* advance the BD pointer */
-		bd += UCC_GETH_SIZE_OF_BD;
+		bd += sizeof(struct qe_bd);
 		i++;
 	} while (!(bd_status & R_W));
 
 	return 0;
 }
 
-static int fill_init_enet_entries(ucc_geth_private_t *ugeth,
+static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
 				  volatile u32 *p_start,
 				  u8 num_entries,
 				  u32 thread_size,
 				  u32 thread_alignment,
-				  qe_risc_allocation_e risc,
+				  enum qe_risc_allocation risc,
 				  int skip_page_for_first_entry)
 {
 	u32 init_enet_offset;
@@ -383,10 +378,10 @@
 	return 0;
 }
 
-static int return_init_enet_entries(ucc_geth_private_t *ugeth,
+static int return_init_enet_entries(struct ucc_geth_private *ugeth,
 				    volatile u32 *p_start,
 				    u8 num_entries,
-				    qe_risc_allocation_e risc,
+				    enum qe_risc_allocation risc,
 				    int skip_page_for_first_entry)
 {
 	u32 init_enet_offset;
@@ -416,11 +411,11 @@
 }
 
 #ifdef DEBUG
-static int dump_init_enet_entries(ucc_geth_private_t *ugeth,
+static int dump_init_enet_entries(struct ucc_geth_private *ugeth,
 				  volatile u32 *p_start,
 				  u8 num_entries,
 				  u32 thread_size,
-				  qe_risc_allocation_e risc,
+				  enum qe_risc_allocation risc,
 				  int skip_page_for_first_entry)
 {
 	u32 init_enet_offset;
@@ -456,14 +451,14 @@
 #endif
 
 #ifdef CONFIG_UGETH_FILTERING
-static enet_addr_container_t *get_enet_addr_container(void)
+static struct enet_addr_container *get_enet_addr_container(void)
 {
-	enet_addr_container_t *enet_addr_cont;
+	struct enet_addr_container *enet_addr_cont;
 
 	/* allocate memory */
-	enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL);
+	enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL);
 	if (!enet_addr_cont) {
-		ugeth_err("%s: No memory for enet_addr_container_t object.",
+		ugeth_err("%s: No memory for enet_addr_container object.",
 			  __FUNCTION__);
 		return NULL;
 	}
@@ -472,45 +467,43 @@
 }
 #endif /* CONFIG_UGETH_FILTERING */
 
-static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont)
+static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont)
 {
 	kfree(enet_addr_cont);
 }
 
-#ifdef CONFIG_UGETH_FILTERING
-static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth,
-				enet_addr_t *p_enet_addr, u8 paddr_num)
+static int set_mac_addr(__be16 __iomem *reg, u8 *mac)
 {
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	out_be16(&reg[0], ((u16)mac[5] << 8) | mac[4]);
+	out_be16(&reg[1], ((u16)mac[3] << 8) | mac[2]);
+	out_be16(&reg[2], ((u16)mac[1] << 8) | mac[0]);
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth,
+                                u8 *p_enet_addr, u8 paddr_num)
+{
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
 
 	if (!(paddr_num < NUM_OF_PADDRS)) {
-		ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+		ugeth_warn("%s: Illegal paddr_num.", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	p_82xx_addr_filt =
-	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
 	    addressfiltering;
 
 	/* Ethernet frames are defined in Little Endian mode,    */
 	/* therefore to insert the address we reverse the bytes. */
-	out_be16(&p_82xx_addr_filt->paddr[paddr_num].h,
-		 (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
-			(u16) (*p_enet_addr)[4]));
-	out_be16(&p_82xx_addr_filt->paddr[paddr_num].m,
-		 (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
-			(u16) (*p_enet_addr)[2]));
-	out_be16(&p_82xx_addr_filt->paddr[paddr_num].l,
-		 (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
-			(u16) (*p_enet_addr)[0]));
-
+	set_mac_addr(&p_82xx_addr_filt->paddr[paddr_num].h, p_enet_addr);
 	return 0;
 }
 #endif /* CONFIG_UGETH_FILTERING */
 
-static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num)
+static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num)
 {
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
 
 	if (!(paddr_num < NUM_OF_PADDRS)) {
 		ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
@@ -518,7 +511,7 @@
 	}
 
 	p_82xx_addr_filt =
-	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
 	    addressfiltering;
 
 	/* Writing address ff.ff.ff.ff.ff.ff disables address
@@ -530,14 +523,14 @@
 	return 0;
 }
 
-static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth,
-				enet_addr_t *p_enet_addr)
+static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,
+                                u8 *p_enet_addr)
 {
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
 	u32 cecr_subblock;
 
 	p_82xx_addr_filt =
-	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
 	    addressfiltering;
 
 	cecr_subblock =
@@ -546,25 +539,18 @@
 	/* Ethernet frames are defined in Little Endian mode,
 	therefor to insert */
 	/* the address to the hash (Big Endian mode), we reverse the bytes.*/
-	out_be16(&p_82xx_addr_filt->taddr.h,
-		 (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
-			(u16) (*p_enet_addr)[4]));
-	out_be16(&p_82xx_addr_filt->taddr.m,
-		 (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
-			(u16) (*p_enet_addr)[2]));
-	out_be16(&p_82xx_addr_filt->taddr.l,
-		 (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
-			(u16) (*p_enet_addr)[0]));
+
+	set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr);
 
 	qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
-		     (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+		     QE_CR_PROTOCOL_ETHERNET, 0);
 }
 
 #ifdef CONFIG_UGETH_MAGIC_PACKET
-static void magic_packet_detection_enable(ucc_geth_private_t *ugeth)
+static void magic_packet_detection_enable(struct ucc_geth_private *ugeth)
 {
-	ucc_fast_private_t *uccf;
-	ucc_geth_t *ug_regs;
+	struct ucc_fast_private *uccf;
+	struct ucc_geth *ug_regs;
 	u32 maccfg2, uccm;
 
 	uccf = ugeth->uccf;
@@ -581,10 +567,10 @@
 	out_be32(&ug_regs->maccfg2, maccfg2);
 }
 
-static void magic_packet_detection_disable(ucc_geth_private_t *ugeth)
+static void magic_packet_detection_disable(struct ucc_geth_private *ugeth)
 {
-	ucc_fast_private_t *uccf;
-	ucc_geth_t *ug_regs;
+	struct ucc_fast_private *uccf;
+	struct ucc_geth *ug_regs;
 	u32 maccfg2, uccm;
 
 	uccf = ugeth->uccf;
@@ -602,26 +588,26 @@
 }
 #endif /* MAGIC_PACKET */
 
-static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2)
+static inline int compare_addr(u8 **addr1, u8 **addr2)
 {
 	return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
 }
 
 #ifdef DEBUG
-static void get_statistics(ucc_geth_private_t *ugeth,
-			   ucc_geth_tx_firmware_statistics_t *
+static void get_statistics(struct ucc_geth_private *ugeth,
+			   struct ucc_geth_tx_firmware_statistics *
 			   tx_firmware_statistics,
-			   ucc_geth_rx_firmware_statistics_t *
+			   struct ucc_geth_rx_firmware_statistics *
 			   rx_firmware_statistics,
-			   ucc_geth_hardware_statistics_t *hardware_statistics)
+			   struct ucc_geth_hardware_statistics *hardware_statistics)
 {
-	ucc_fast_t *uf_regs;
-	ucc_geth_t *ug_regs;
-	ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
-	ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+	struct ucc_fast *uf_regs;
+	struct ucc_geth *ug_regs;
+	struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram;
+	struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram;
 
 	ug_regs = ugeth->ug_regs;
-	uf_regs = (ucc_fast_t *) ug_regs;
+	uf_regs = (struct ucc_fast *) ug_regs;
 	p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
 	p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;
 
@@ -727,7 +713,7 @@
 	}
 }
 
-static void dump_bds(ucc_geth_private_t *ugeth)
+static void dump_bds(struct ucc_geth_private *ugeth)
 {
 	int i;
 	int length;
@@ -736,7 +722,7 @@
 		if (ugeth->p_tx_bd_ring[i]) {
 			length =
 			    (ugeth->ug_info->bdRingLenTx[i] *
-			     UCC_GETH_SIZE_OF_BD);
+			     sizeof(struct qe_bd));
 			ugeth_info("TX BDs[%d]", i);
 			mem_disp(ugeth->p_tx_bd_ring[i], length);
 		}
@@ -745,14 +731,14 @@
 		if (ugeth->p_rx_bd_ring[i]) {
 			length =
 			    (ugeth->ug_info->bdRingLenRx[i] *
-			     UCC_GETH_SIZE_OF_BD);
+			     sizeof(struct qe_bd));
 			ugeth_info("RX BDs[%d]", i);
 			mem_disp(ugeth->p_rx_bd_ring[i], length);
 		}
 	}
 }
 
-static void dump_regs(ucc_geth_private_t *ugeth)
+static void dump_regs(struct ucc_geth_private *ugeth)
 {
 	int i;
 
@@ -893,7 +879,7 @@
 			ugeth_info("Base address: 0x%08x",
 				   (u32) & ugeth->p_thread_data_tx[i]);
 			mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
-				 sizeof(ucc_geth_thread_data_tx_t));
+				 sizeof(struct ucc_geth_thread_data_tx));
 		}
 	}
 	if (ugeth->p_thread_data_rx) {
@@ -927,7 +913,7 @@
 			ugeth_info("Base address: 0x%08x",
 				   (u32) & ugeth->p_thread_data_rx[i]);
 			mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
-				 sizeof(ucc_geth_thread_data_rx_t));
+				 sizeof(struct ucc_geth_thread_data_rx));
 		}
 	}
 	if (ugeth->p_exf_glbl_param) {
@@ -1105,7 +1091,7 @@
 			ugeth_info("Base address: 0x%08x",
 				   (u32) & ugeth->p_send_q_mem_reg->sqqd[i]);
 			mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
-				 sizeof(ucc_geth_send_queue_qd_t));
+				 sizeof(struct ucc_geth_send_queue_qd));
 		}
 	}
 	if (ugeth->p_scheduler) {
@@ -1187,7 +1173,7 @@
 				 qe_muram_addr(in_be32
 					       (&ugeth->p_rx_bd_qs_tbl[i].
 						bdbaseptr)),
-				 sizeof(ucc_geth_rx_prefetched_bds_t));
+				 sizeof(struct ucc_geth_rx_prefetched_bds));
 		}
 	}
 	if (ugeth->p_init_enet_param_shadow) {
@@ -1198,7 +1184,7 @@
 		mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
 			 sizeof(*ugeth->p_init_enet_param_shadow));
 
-		size = sizeof(ucc_geth_thread_rx_pram_t);
+		size = sizeof(struct ucc_geth_thread_rx_pram);
 		if (ugeth->ug_info->rxExtendedFiltering) {
 			size +=
 			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
@@ -1216,7 +1202,7 @@
 				       &(ugeth->p_init_enet_param_shadow->
 					 txthread[0]),
 				       ENET_INIT_PARAM_MAX_ENTRIES_TX,
-				       sizeof(ucc_geth_thread_tx_pram_t),
+				       sizeof(struct ucc_geth_thread_tx_pram),
 				       ugeth->ug_info->riscTx, 0);
 		dump_init_enet_entries(ugeth,
 				       &(ugeth->p_init_enet_param_shadow->
@@ -1578,12 +1564,12 @@
 	return 0;
 }
 
-static int adjust_enet_interface(ucc_geth_private_t *ugeth)
+static int adjust_enet_interface(struct ucc_geth_private *ugeth)
 {
-	ucc_geth_info_t *ug_info;
-	ucc_geth_t *ug_regs;
-	ucc_fast_t *uf_regs;
-	enet_speed_e speed;
+	struct ucc_geth_info *ug_info;
+	struct ucc_geth *ug_regs;
+	struct ucc_fast *uf_regs;
+	enum enet_speed speed;
 	int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm =
 	    0, limited_to_full_duplex = 0;
 	u32 upsmr, maccfg2, utbipar, tbiBaseAddress;
@@ -1691,8 +1677,8 @@
  */
 static void adjust_link(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
-	ucc_geth_t *ug_regs;
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_geth *ug_regs;
 	u32 tempval;
 	struct ugeth_mii_info *mii_info = ugeth->mii_info;
 
@@ -1722,7 +1708,7 @@
 		if (mii_info->speed != ugeth->oldspeed) {
 			switch (mii_info->speed) {
 			case 1000:
-#ifdef CONFIG_MPC836x
+#ifdef CONFIG_PPC_MPC836x
 /* FIXME: This code is for 100Mbs BUG fixing,
 remove this when it is fixed!!! */
 				if (ugeth->ug_info->enet_interface ==
@@ -1768,7 +1754,7 @@
 				break;
 			case 100:
 			case 10:
-#ifdef CONFIG_MPC836x
+#ifdef CONFIG_PPC_MPC836x
 /* FIXME: This code is for 100Mbs BUG fixing,
 remove this lines when it will be fixed!!! */
 				ugeth->ug_info->enet_interface = ENET_100_RGMII;
@@ -1827,9 +1813,9 @@
  */
 static int init_phy(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	struct phy_info *curphy;
-	ucc_mii_mng_t *mii_regs;
+	struct ucc_mii_mng *mii_regs;
 	struct ugeth_mii_info *mii_info;
 	int err;
 
@@ -1914,17 +1900,17 @@
 }
 
 #ifdef CONFIG_UGETH_TX_ON_DEMOND
-static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth)
+static int ugeth_transmit_on_demand(struct ucc_geth_private *ugeth)
 {
-	ucc_fast_transmit_on_demand(ugeth->uccf);
+	struct ucc_fastransmit_on_demand(ugeth->uccf);
 
 	return 0;
 }
 #endif
 
-static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth)
+static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
 {
-	ucc_fast_private_t *uccf;
+	struct ucc_fast_private *uccf;
 	u32 cecr_subblock;
 	u32 temp;
 
@@ -1940,7 +1926,7 @@
 	cecr_subblock =
 	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
 	qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
-		     (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+		     QE_CR_PROTOCOL_ETHERNET, 0);
 
 	/* Wait for command to complete */
 	do {
@@ -1952,9 +1938,9 @@
 	return 0;
 }
 
-static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth)
+static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth)
 {
-	ucc_fast_private_t *uccf;
+	struct ucc_fast_private *uccf;
 	u32 cecr_subblock;
 	u8 temp;
 
@@ -1973,7 +1959,7 @@
 		    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
 						ucc_num);
 		qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
-			     (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+			     QE_CR_PROTOCOL_ETHERNET, 0);
 
 		temp = ugeth->p_rx_glbl_pram->rxgstpack;
 	} while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
@@ -1983,41 +1969,40 @@
 	return 0;
 }
 
-static int ugeth_restart_tx(ucc_geth_private_t *ugeth)
+static int ugeth_restart_tx(struct ucc_geth_private *ugeth)
 {
-	ucc_fast_private_t *uccf;
+	struct ucc_fast_private *uccf;
 	u32 cecr_subblock;
 
 	uccf = ugeth->uccf;
 
 	cecr_subblock =
 	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
-	qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
-		     0);
+	qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0);
 	uccf->stopped_tx = 0;
 
 	return 0;
 }
 
-static int ugeth_restart_rx(ucc_geth_private_t *ugeth)
+static int ugeth_restart_rx(struct ucc_geth_private *ugeth)
 {
-	ucc_fast_private_t *uccf;
+	struct ucc_fast_private *uccf;
 	u32 cecr_subblock;
 
 	uccf = ugeth->uccf;
 
 	cecr_subblock =
 	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
-	qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+	qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
 		     0);
 	uccf->stopped_rx = 0;
 
 	return 0;
 }
 
-static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode)
+static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
 {
-	ucc_fast_private_t *uccf;
+	struct ucc_fast_private *uccf;
 	int enabled_tx, enabled_rx;
 
 	uccf = ugeth->uccf;
@@ -2044,9 +2029,9 @@
 
 }
 
-static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode)
+static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode)
 {
-	ucc_fast_private_t *uccf;
+	struct ucc_fast_private *uccf;
 
 	uccf = ugeth->uccf;
 
@@ -2069,7 +2054,7 @@
 	return 0;
 }
 
-static void ugeth_dump_regs(ucc_geth_private_t *ugeth)
+static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
 {
 #ifdef DEBUG
 	ucc_fast_dump_regs(ugeth->uccf);
@@ -2079,9 +2064,9 @@
 }
 
 #ifdef CONFIG_UGETH_FILTERING
-static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t *
+static int ugeth_ext_filtering_serialize_tad(struct ucc_geth_tad_params *
 					     p_UccGethTadParams,
-					     qe_fltr_tad_t *qe_fltr_tad)
+					     struct qe_fltr_tad *qe_fltr_tad)
 {
 	u16 temp;
 
@@ -2119,11 +2104,11 @@
 	return 0;
 }
 
-static enet_addr_container_t
-    *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth,
-						 enet_addr_t *p_enet_addr)
+static struct enet_addr_container_t
+    *ugeth_82xx_filtering_get_match_addr_in_hash(struct ucc_geth_private *ugeth,
+						 struct enet_addr *p_enet_addr)
 {
-	enet_addr_container_t *enet_addr_cont;
+	struct enet_addr_container *enet_addr_cont;
 	struct list_head *p_lh;
 	u16 i, num;
 	int32_t j;
@@ -2144,7 +2129,7 @@
 
 	for (i = 0; i < num; i++) {
 		enet_addr_cont =
-		    (enet_addr_container_t *)
+		    (struct enet_addr_container *)
 		    ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
 		for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
 			if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
@@ -2157,11 +2142,11 @@
 	return NULL;
 }
 
-static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth,
-						 enet_addr_t *p_enet_addr)
+static int ugeth_82xx_filtering_add_addr_in_hash(struct ucc_geth_private *ugeth,
+						 struct enet_addr *p_enet_addr)
 {
-	ucc_geth_enet_address_recognition_location_e location;
-	enet_addr_container_t *enet_addr_cont;
+	enum ucc_geth_enet_address_recognition_location location;
+	struct enet_addr_container *enet_addr_cont;
 	struct list_head *p_lh;
 	u8 i;
 	u32 limit;
@@ -2196,18 +2181,17 @@
 	enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */
 	++(*p_counter);
 
-	hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
-
+	hw_add_addr_in_hash(ugeth, enet_addr_cont->address);
 	return 0;
 }
 
-static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth,
-						   enet_addr_t *p_enet_addr)
+static int ugeth_82xx_filtering_clear_addr_in_hash(struct ucc_geth_private *ugeth,
+						   struct enet_addr *p_enet_addr)
 {
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
-	enet_addr_container_t *enet_addr_cont;
-	ucc_fast_private_t *uccf;
-	comm_dir_e comm_dir;
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
+	struct enet_addr_container *enet_addr_cont;
+	struct ucc_fast_private *uccf;
+	enum comm_dir comm_dir;
 	u16 i, num;
 	struct list_head *p_lh;
 	u32 *addr_h, *addr_l;
@@ -2216,7 +2200,7 @@
 	uccf = ugeth->uccf;
 
 	p_82xx_addr_filt =
-	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
 	    addressfiltering;
 
 	if (!
@@ -2256,9 +2240,9 @@
 	num = --(*p_counter);
 	for (i = 0; i < num; i++) {
 		enet_addr_cont =
-		    (enet_addr_container_t *)
+		    (struct enet_addr_container *)
 		    ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
-		hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+		hw_add_addr_in_hash(ugeth, enet_addr_cont->address);
 		enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */
 	}
 
@@ -2269,14 +2253,14 @@
 }
 #endif /* CONFIG_UGETH_FILTERING */
 
-static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t *
+static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
 						       ugeth,
-						       enet_addr_type_e
+						       enum enet_addr_type
 						       enet_addr_type)
 {
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
-	ucc_fast_private_t *uccf;
-	comm_dir_e comm_dir;
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
+	struct ucc_fast_private *uccf;
+	enum comm_dir comm_dir;
 	struct list_head *p_lh;
 	u16 i, num;
 	u32 *addr_h, *addr_l;
@@ -2285,7 +2269,7 @@
 	uccf = ugeth->uccf;
 
 	p_82xx_addr_filt =
-	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
 	    addressfiltering;
 
 	if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
@@ -2331,8 +2315,8 @@
 }
 
 #ifdef CONFIG_UGETH_FILTERING
-static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth,
-						  enet_addr_t *p_enet_addr,
+static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth,
+						  struct enet_addr *p_enet_addr,
 						  u8 paddr_num)
 {
 	int i;
@@ -2352,14 +2336,14 @@
 }
 #endif /* CONFIG_UGETH_FILTERING */
 
-static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth,
+static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth,
 						    u8 paddr_num)
 {
 	ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
 	return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
 }
 
-static void ucc_geth_memclean(ucc_geth_private_t *ugeth)
+static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
 {
 	u16 i, j;
 	u8 *bd;
@@ -2433,8 +2417,8 @@
 		for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
 			if (ugeth->tx_skbuff[i][j]) {
 				dma_unmap_single(NULL,
-						 BD_BUFFER_ARG(bd),
-						 (BD_STATUS_AND_LENGTH(bd) &
+						 ((qe_bd_t *)bd)->buf,
+						 (in_be32((u32 *)bd) &
 						  BD_LENGTH_MASK),
 						 DMA_TO_DEVICE);
 				dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
@@ -2460,18 +2444,17 @@
 			bd = ugeth->p_rx_bd_ring[i];
 			for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
 				if (ugeth->rx_skbuff[i][j]) {
-					dma_unmap_single(NULL, BD_BUFFER(bd),
-						 ugeth->ug_info->
-						 uf_info.
-						 max_rx_buf_length +
-						 UCC_GETH_RX_DATA_BUF_ALIGNMENT,
-						 DMA_FROM_DEVICE);
-
-					dev_kfree_skb_any(ugeth->
-							  rx_skbuff[i][j]);
+					dma_unmap_single(NULL,
+						((struct qe_bd *)bd)->buf,
+						ugeth->ug_info->
+						uf_info.max_rx_buf_length +
+						UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+						DMA_FROM_DEVICE);
+					dev_kfree_skb_any(
+						ugeth->rx_skbuff[i][j]);
 					ugeth->rx_skbuff[i][j] = NULL;
 				}
-				bd += UCC_GETH_SIZE_OF_BD;
+				bd += sizeof(struct qe_bd);
 			}
 
 			kfree(ugeth->rx_skbuff[i]);
@@ -2496,11 +2479,11 @@
 
 static void ucc_geth_set_multi(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth;
+	struct ucc_geth_private *ugeth;
 	struct dev_mc_list *dmi;
-	ucc_fast_t *uf_regs;
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
-	enet_addr_t tempaddr;
+	struct ucc_fast *uf_regs;
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
+	u8 tempaddr[6];
 	u8 *mcptr, *tdptr;
 	int i, j;
 
@@ -2517,7 +2500,7 @@
 		uf_regs->upsmr &= ~UPSMR_PRO;
 
 		p_82xx_addr_filt =
-		    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+		    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->
 		    p_rx_glbl_pram->addressfiltering;
 
 		if (dev->flags & IFF_ALLMULTI) {
@@ -2546,23 +2529,22 @@
 				 * copy bytes MSB first from dmi_addr.
 				 */
 				mcptr = (u8 *) dmi->dmi_addr + 5;
-				tdptr = (u8 *) & tempaddr;
+				tdptr = (u8 *) tempaddr;
 				for (j = 0; j < 6; j++)
 					*tdptr++ = *mcptr--;
 
 				/* Ask CPM to run CRC and set bit in
 				 * filter mask.
 				 */
-				hw_add_addr_in_hash(ugeth, &tempaddr);
-
+				hw_add_addr_in_hash(ugeth, tempaddr);
 			}
 		}
 	}
 }
 
-static void ucc_geth_stop(ucc_geth_private_t *ugeth)
+static void ucc_geth_stop(struct ucc_geth_private *ugeth)
 {
-	ucc_geth_t *ug_regs = ugeth->ug_regs;
+	struct ucc_geth *ug_regs = ugeth->ug_regs;
 	u32 tempval;
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
@@ -2605,15 +2587,15 @@
 	ucc_geth_memclean(ugeth);
 }
 
-static int ucc_geth_startup(ucc_geth_private_t *ugeth)
+static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 {
-	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
-	ucc_geth_init_pram_t *p_init_enet_pram;
-	ucc_fast_private_t *uccf;
-	ucc_geth_info_t *ug_info;
-	ucc_fast_info_t *uf_info;
-	ucc_fast_t *uf_regs;
-	ucc_geth_t *ug_regs;
+	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
+	struct ucc_geth_init_pram *p_init_enet_pram;
+	struct ucc_fast_private *uccf;
+	struct ucc_geth_info *ug_info;
+	struct ucc_fast_info *uf_info;
+	struct ucc_fast *uf_regs;
+	struct ucc_geth *ug_regs;
 	int ret_val = -EINVAL;
 	u32 remoder = UCC_GETH_REMODER_INIT;
 	u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
@@ -2788,7 +2770,7 @@
 		UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
 
 	uf_regs = uccf->uf_regs;
-	ug_regs = (ucc_geth_t *) (uccf->uf_regs);
+	ug_regs = (struct ucc_geth *) (uccf->uf_regs);
 	ugeth->ug_regs = ug_regs;
 
 	init_default_reg_vals(&uf_regs->upsmr,
@@ -2869,10 +2851,10 @@
 		/* Allocate in multiple of
 		   UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
 		   according to spec */
-		length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD)
+		length = ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd))
 			  / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
 		    * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
-		if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) %
+		if ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) %
 		    UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
 			length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
 		if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
@@ -2904,13 +2886,13 @@
 		}
 		/* Zero unused end of bd ring, according to spec */
 		memset(ugeth->p_tx_bd_ring[j] +
-		       ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0,
-		       length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD);
+		       ug_info->bdRingLenTx[j] * sizeof(struct qe_bd), 0,
+		       length - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd));
 	}
 
 	/* Allocate Rx bds */
 	for (j = 0; j < ug_info->numQueuesRx; j++) {
-		length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD;
+		length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd);
 		if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
 			u32 align = 4;
 			if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
@@ -2960,12 +2942,15 @@
 		ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
 		bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
 		for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
-			BD_BUFFER_CLEAR(bd);
-			BD_STATUS_AND_LENGTH_SET(bd, 0);
-			bd += UCC_GETH_SIZE_OF_BD;
+			/* clear bd buffer */
+			out_be32(&((struct qe_bd *)bd)->buf, 0);
+			/* set bd status and length */
+			out_be32((u32 *)bd, 0);
+			bd += sizeof(struct qe_bd);
 		}
-		bd -= UCC_GETH_SIZE_OF_BD;
-		BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */
+		bd -= sizeof(struct qe_bd);
+		/* set bd status and length */
+		out_be32((u32 *)bd, T_W);	/* for last BD set Wrap bit */
 	}
 
 	/* Init Rx bds */
@@ -2989,12 +2974,15 @@
 		ugeth->skb_currx[j] = 0;
 		bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
 		for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
-			BD_STATUS_AND_LENGTH_SET(bd, R_I);
-			BD_BUFFER_CLEAR(bd);
-			bd += UCC_GETH_SIZE_OF_BD;
+			/* set bd status and length */
+			out_be32((u32 *)bd, R_I);
+			/* clear bd buffer */
+			out_be32(&((struct qe_bd *)bd)->buf, 0);
+			bd += sizeof(struct qe_bd);
 		}
-		bd -= UCC_GETH_SIZE_OF_BD;
-		BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */
+		bd -= sizeof(struct qe_bd);
+		/* set bd status and length */
+		out_be32((u32 *)bd, R_W); /* for last BD set Wrap bit */
 	}
 
 	/*
@@ -3003,7 +2991,7 @@
 	/* Tx global PRAM */
 	/* Allocate global tx parameter RAM page */
 	ugeth->tx_glbl_pram_offset =
-	    qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t),
+	    qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram),
 			   UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) {
 		ugeth_err
@@ -3013,10 +3001,10 @@
 		return -ENOMEM;
 	}
 	ugeth->p_tx_glbl_pram =
-	    (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth->
+	    (struct ucc_geth_tx_global_pram *) qe_muram_addr(ugeth->
 							tx_glbl_pram_offset);
 	/* Zero out p_tx_glbl_pram */
-	memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t));
+	memset(ugeth->p_tx_glbl_pram, 0, sizeof(struct ucc_geth_tx_global_pram));
 
 	/* Fill global PRAM */
 
@@ -3024,7 +3012,7 @@
 	/* Size varies with number of Tx threads */
 	ugeth->thread_dat_tx_offset =
 	    qe_muram_alloc(numThreadsTxNumerical *
-			   sizeof(ucc_geth_thread_data_tx_t) +
+			   sizeof(struct ucc_geth_thread_data_tx) +
 			   32 * (numThreadsTxNumerical == 1),
 			   UCC_GETH_THREAD_DATA_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) {
@@ -3036,7 +3024,7 @@
 	}
 
 	ugeth->p_thread_data_tx =
-	    (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth->
+	    (struct ucc_geth_thread_data_tx *) qe_muram_addr(ugeth->
 							thread_dat_tx_offset);
 	out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
 
@@ -3053,7 +3041,7 @@
 	/* Size varies with number of Tx queues */
 	ugeth->send_q_mem_reg_offset =
 	    qe_muram_alloc(ug_info->numQueuesTx *
-			   sizeof(ucc_geth_send_queue_qd_t),
+			   sizeof(struct ucc_geth_send_queue_qd),
 			   UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) {
 		ugeth_err
@@ -3064,7 +3052,7 @@
 	}
 
 	ugeth->p_send_q_mem_reg =
-	    (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth->
+	    (struct ucc_geth_send_queue_mem_region *) qe_muram_addr(ugeth->
 			send_q_mem_reg_offset);
 	out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
 
@@ -3073,7 +3061,7 @@
 	for (i = 0; i < ug_info->numQueuesTx; i++) {
 		endOfRing =
 		    ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
-					      1) * UCC_GETH_SIZE_OF_BD;
+					      1) * sizeof(struct qe_bd);
 		if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
 			out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
 				 (u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
@@ -3096,7 +3084,7 @@
 	if (ug_info->numQueuesTx > 1) {
 	/* scheduler exists only if more than 1 tx queue */
 		ugeth->scheduler_offset =
-		    qe_muram_alloc(sizeof(ucc_geth_scheduler_t),
+		    qe_muram_alloc(sizeof(struct ucc_geth_scheduler),
 				   UCC_GETH_SCHEDULER_ALIGNMENT);
 		if (IS_MURAM_ERR(ugeth->scheduler_offset)) {
 			ugeth_err
@@ -3107,12 +3095,12 @@
 		}
 
 		ugeth->p_scheduler =
-		    (ucc_geth_scheduler_t *) qe_muram_addr(ugeth->
+		    (struct ucc_geth_scheduler *) qe_muram_addr(ugeth->
 							   scheduler_offset);
 		out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
 			 ugeth->scheduler_offset);
 		/* Zero out p_scheduler */
-		memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t));
+		memset(ugeth->p_scheduler, 0, sizeof(struct ucc_geth_scheduler));
 
 		/* Set values in scheduler */
 		out_be32(&ugeth->p_scheduler->mblinterval,
@@ -3144,7 +3132,7 @@
 	    statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
 		ugeth->tx_fw_statistics_pram_offset =
 		    qe_muram_alloc(sizeof
-				   (ucc_geth_tx_firmware_statistics_pram_t),
+				   (struct ucc_geth_tx_firmware_statistics_pram),
 				   UCC_GETH_TX_STATISTICS_ALIGNMENT);
 		if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) {
 			ugeth_err
@@ -3154,11 +3142,11 @@
 			return -ENOMEM;
 		}
 		ugeth->p_tx_fw_statistics_pram =
-		    (ucc_geth_tx_firmware_statistics_pram_t *)
+		    (struct ucc_geth_tx_firmware_statistics_pram *)
 		    qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
 		/* Zero out p_tx_fw_statistics_pram */
 		memset(ugeth->p_tx_fw_statistics_pram,
-		       0, sizeof(ucc_geth_tx_firmware_statistics_pram_t));
+		       0, sizeof(struct ucc_geth_tx_firmware_statistics_pram));
 	}
 
 	/* temoder */
@@ -3183,7 +3171,7 @@
 	/* Rx global PRAM */
 	/* Allocate global rx parameter RAM page */
 	ugeth->rx_glbl_pram_offset =
-	    qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t),
+	    qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram),
 			   UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) {
 		ugeth_err
@@ -3193,10 +3181,10 @@
 		return -ENOMEM;
 	}
 	ugeth->p_rx_glbl_pram =
-	    (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth->
+	    (struct ucc_geth_rx_global_pram *) qe_muram_addr(ugeth->
 							rx_glbl_pram_offset);
 	/* Zero out p_rx_glbl_pram */
-	memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t));
+	memset(ugeth->p_rx_glbl_pram, 0, sizeof(struct ucc_geth_rx_global_pram));
 
 	/* Fill global PRAM */
 
@@ -3204,7 +3192,7 @@
 	/* Size varies with number of Rx threads */
 	ugeth->thread_dat_rx_offset =
 	    qe_muram_alloc(numThreadsRxNumerical *
-			   sizeof(ucc_geth_thread_data_rx_t),
+			   sizeof(struct ucc_geth_thread_data_rx),
 			   UCC_GETH_THREAD_DATA_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) {
 		ugeth_err
@@ -3215,7 +3203,7 @@
 	}
 
 	ugeth->p_thread_data_rx =
-	    (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth->
+	    (struct ucc_geth_thread_data_rx *) qe_muram_addr(ugeth->
 							thread_dat_rx_offset);
 	out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
 
@@ -3227,7 +3215,7 @@
 	    statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
 		ugeth->rx_fw_statistics_pram_offset =
 		    qe_muram_alloc(sizeof
-				   (ucc_geth_rx_firmware_statistics_pram_t),
+				   (struct ucc_geth_rx_firmware_statistics_pram),
 				   UCC_GETH_RX_STATISTICS_ALIGNMENT);
 		if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) {
 			ugeth_err
@@ -3237,11 +3225,11 @@
 			return -ENOMEM;
 		}
 		ugeth->p_rx_fw_statistics_pram =
-		    (ucc_geth_rx_firmware_statistics_pram_t *)
+		    (struct ucc_geth_rx_firmware_statistics_pram *)
 		    qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
 		/* Zero out p_rx_fw_statistics_pram */
 		memset(ugeth->p_rx_fw_statistics_pram, 0,
-		       sizeof(ucc_geth_rx_firmware_statistics_pram_t));
+		       sizeof(struct ucc_geth_rx_firmware_statistics_pram));
 	}
 
 	/* intCoalescingPtr */
@@ -3249,7 +3237,7 @@
 	/* Size varies with number of Rx queues */
 	ugeth->rx_irq_coalescing_tbl_offset =
 	    qe_muram_alloc(ug_info->numQueuesRx *
-			   sizeof(ucc_geth_rx_interrupt_coalescing_entry_t),
+			   sizeof(struct ucc_geth_rx_interrupt_coalescing_entry),
 			   UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) {
 		ugeth_err
@@ -3260,7 +3248,7 @@
 	}
 
 	ugeth->p_rx_irq_coalescing_tbl =
-	    (ucc_geth_rx_interrupt_coalescing_table_t *)
+	    (struct ucc_geth_rx_interrupt_coalescing_table *)
 	    qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
 	out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
 		 ugeth->rx_irq_coalescing_tbl_offset);
@@ -3300,7 +3288,7 @@
 		l3qt = 0;
 		for (i = 0; i < 8; i++)
 			l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
-		out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt);
+		out_be32(&ugeth->p_rx_glbl_pram->l3qt[j/8], l3qt);
 	}
 
 	/* vlantype */
@@ -3316,8 +3304,8 @@
 	/* Size varies with number of Rx queues */
 	ugeth->rx_bd_qs_tbl_offset =
 	    qe_muram_alloc(ug_info->numQueuesRx *
-			   (sizeof(ucc_geth_rx_bd_queues_entry_t) +
-			    sizeof(ucc_geth_rx_prefetched_bds_t)),
+			   (sizeof(struct ucc_geth_rx_bd_queues_entry) +
+			    sizeof(struct ucc_geth_rx_prefetched_bds)),
 			   UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
 	if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) {
 		ugeth_err
@@ -3328,14 +3316,14 @@
 	}
 
 	ugeth->p_rx_bd_qs_tbl =
-	    (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth->
+	    (struct ucc_geth_rx_bd_queues_entry *) qe_muram_addr(ugeth->
 				    rx_bd_qs_tbl_offset);
 	out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
 	/* Zero out p_rx_bd_qs_tbl */
 	memset(ugeth->p_rx_bd_qs_tbl,
 	       0,
-	       ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) +
-				       sizeof(ucc_geth_rx_prefetched_bds_t)));
+	       ug_info->numQueuesRx * (sizeof(struct ucc_geth_rx_bd_queues_entry) +
+				       sizeof(struct ucc_geth_rx_prefetched_bds)));
 
 	/* Setup the table */
 	/* Assume BD rings are already established */
@@ -3406,7 +3394,7 @@
 		/* Allocate memory for extended filtering Mode Global
 		Parameters */
 		ugeth->exf_glbl_param_offset =
-		    qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t),
+		    qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram),
 		UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
 		if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) {
 			ugeth_err
@@ -3417,7 +3405,7 @@
 		}
 
 		ugeth->p_exf_glbl_param =
-		    (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth->
+		    (struct ucc_geth_exf_global_pram *) qe_muram_addr(ugeth->
 				 exf_glbl_param_offset);
 		out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam,
 			 ugeth->exf_glbl_param_offset);
@@ -3439,7 +3427,7 @@
 			INIT_LIST_HEAD(&ugeth->ind_hash_q);
 		}
 		p_82xx_addr_filt =
-		    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+		    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->
 		    p_rx_glbl_pram->addressfiltering;
 
 		ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
@@ -3462,7 +3450,7 @@
 	 * allocated resources can be released when the channel is freed.
 	 */
 	if (!(ugeth->p_init_enet_param_shadow =
-	     (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t),
+	     (struct ucc_geth_init_pram *) kmalloc(sizeof(struct ucc_geth_init_pram),
 					      GFP_KERNEL))) {
 		ugeth_err
 		    ("%s: Can not allocate memory for"
@@ -3472,7 +3460,7 @@
 	}
 	/* Zero out *p_init_enet_param_shadow */
 	memset((char *)ugeth->p_init_enet_param_shadow,
-	       0, sizeof(ucc_geth_init_pram_t));
+	       0, sizeof(struct ucc_geth_init_pram));
 
 	/* Fill shadow InitEnet command parameter structure */
 
@@ -3506,7 +3494,7 @@
 	}
 	ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
 	    ug_info->largestexternallookupkeysize;
-	size = sizeof(ucc_geth_thread_rx_pram_t);
+	size = sizeof(struct ucc_geth_thread_rx_pram);
 	if (ug_info->rxExtendedFiltering) {
 		size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
 		if (ug_info->largestexternallookupkeysize ==
@@ -3537,7 +3525,7 @@
 	     fill_init_enet_entries(ugeth,
 				    &(ugeth->p_init_enet_param_shadow->
 				      txthread[0]), numThreadsTxNumerical,
-				    sizeof(ucc_geth_thread_tx_pram_t),
+				    sizeof(struct ucc_geth_thread_tx_pram),
 				    UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
 				    ug_info->riscTx, 0)) != 0) {
 		ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
@@ -3557,7 +3545,7 @@
 	}
 
 	/* Allocate InitEnet command parameter structure */
-	init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4);
+	init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4);
 	if (IS_MURAM_ERR(init_enet_pram_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
@@ -3566,7 +3554,7 @@
 		return -ENOMEM;
 	}
 	p_init_enet_pram =
-	    (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset);
+	    (struct ucc_geth_init_pram *) qe_muram_addr(init_enet_pram_offset);
 
 	/* Copy shadow InitEnet command parameter structure into PRAM */
 	p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1;
@@ -3591,7 +3579,7 @@
 	/* Issue QE command */
 	cecr_subblock =
 	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
-	qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+	qe_issue_cmd(command, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
 		     init_enet_pram_offset);
 
 	/* Free InitEnet command parameter */
@@ -3603,7 +3591,7 @@
 /* returns a net_device_stats structure pointer */
 static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 
 	return &(ugeth->stats);
 }
@@ -3614,7 +3602,7 @@
  * starting over will fix the problem. */
 static void ucc_geth_timeout(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
 
@@ -3634,7 +3622,7 @@
 /* It is pointed to by the dev->hard_start_xmit function pointer */
 static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	u8 *bd;			/* BD pointer */
 	u32 bd_status;
 	u8 txQ = 0;
@@ -3647,7 +3635,7 @@
 
 	/* Start from the next BD that should be filled */
 	bd = ugeth->txBd[txQ];
-	bd_status = BD_STATUS_AND_LENGTH(bd);
+	bd_status = in_be32((u32 *)bd);
 	/* Save the skb pointer so we can free it later */
 	ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb;
 
@@ -3657,20 +3645,21 @@
 	     1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
 
 	/* set up the buffer descriptor */
-	BD_BUFFER_SET(bd,
+	out_be32(&((struct qe_bd *)bd)->buf,
 		      dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE));
 
-	//printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data);
+	/* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */
 
 	bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len;
 
-	BD_STATUS_AND_LENGTH_SET(bd, bd_status);
+	/* set bd status and length */
+	out_be32((u32 *)bd, bd_status);
 
 	dev->trans_start = jiffies;
 
 	/* Move to next BD in the ring */
 	if (!(bd_status & T_W))
-		ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD;
+		ugeth->txBd[txQ] = bd + sizeof(struct qe_bd);
 	else
 		ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ];
 
@@ -3695,7 +3684,7 @@
 	return 0;
 }
 
-static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit)
+static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit)
 {
 	struct sk_buff *skb;
 	u8 *bd;
@@ -3709,11 +3698,11 @@
 	/* collect received buffers */
 	bd = ugeth->rxBd[rxQ];
 
-	bd_status = BD_STATUS_AND_LENGTH(bd);
+	bd_status = in_be32((u32 *)bd);
 
 	/* while there are received buffers and BD is full (~R_E) */
 	while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) {
-		bdBuffer = (u8 *) BD_BUFFER(bd);
+		bdBuffer = (u8 *) in_be32(&((struct qe_bd *)bd)->buf);
 		length = (u16) ((bd_status & BD_LENGTH_MASK) - 4);
 		skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]];
 
@@ -3768,9 +3757,9 @@
 		if (bd_status & R_W)
 			bd = ugeth->p_rx_bd_ring[rxQ];
 		else
-			bd += UCC_GETH_SIZE_OF_BD;
+			bd += sizeof(struct qe_bd);
 
-		bd_status = BD_STATUS_AND_LENGTH(bd);
+		bd_status = in_be32((u32 *)bd);
 	}
 
 	ugeth->rxBd[rxQ] = bd;
@@ -3781,12 +3770,12 @@
 static int ucc_geth_tx(struct net_device *dev, u8 txQ)
 {
 	/* Start from the next BD that should be filled */
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	u8 *bd;			/* BD pointer */
 	u32 bd_status;
 
 	bd = ugeth->confBd[txQ];
-	bd_status = BD_STATUS_AND_LENGTH(bd);
+	bd_status = in_be32((u32 *)bd);
 
 	/* Normal processing. */
 	while ((bd_status & T_R) == 0) {
@@ -3813,7 +3802,7 @@
 
 		/* Advance the confirmation BD pointer */
 		if (!(bd_status & T_W))
-			ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD;
+			ugeth->confBd[txQ] += sizeof(struct qe_bd);
 		else
 			ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ];
 	}
@@ -3823,7 +3812,7 @@
 #ifdef CONFIG_UGETH_NAPI
 static int ucc_geth_poll(struct net_device *dev, int *budget)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	int howmany;
 	int rx_work_limit = *budget;
 	u8 rxQ = 0;
@@ -3844,13 +3833,12 @@
 }
 #endif				/* CONFIG_UGETH_NAPI */
 
-static irqreturn_t ucc_geth_irq_handler(int irq, void *info,
-					struct pt_regs *regs)
+static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
 {
 	struct net_device *dev = (struct net_device *)info;
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
-	ucc_fast_private_t *uccf;
-	ucc_geth_info_t *ug_info;
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_fast_private *uccf;
+	struct ucc_geth_info *ug_info;
 	register u32 ucce = 0;
 	register u32 bit_mask = UCCE_RXBF_SINGLE_MASK;
 	register u32 tx_mask = UCCE_TXBF_SINGLE_MASK;
@@ -3910,10 +3898,10 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t phy_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
 
@@ -3933,8 +3921,8 @@
 static void ugeth_phy_change(void *data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
-	ucc_geth_t *ug_regs;
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_geth *ug_regs;
 	int result = 0;
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
@@ -3964,7 +3952,7 @@
 static void ugeth_phy_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 
 	schedule_work(&ugeth->tq);
 
@@ -3980,7 +3968,7 @@
 static void ugeth_phy_startup_timer(unsigned long data)
 {
 	struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
-	ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev);
+	struct ucc_geth_private *ugeth = netdev_priv(mii_info->dev);
 	static int secondary = UGETH_AN_TIMEOUT;
 	int result;
 
@@ -4035,7 +4023,7 @@
 /* Returns 0 for success. */
 static int ucc_geth_open(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	int err;
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
@@ -4112,7 +4100,7 @@
 /* Stops the kernel queue, and halts the controller */
 static int ucc_geth_close(struct net_device *dev)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
 
@@ -4131,30 +4119,53 @@
 
 const struct ethtool_ops ucc_geth_ethtool_ops = { };
 
-static int ucc_geth_probe(struct device *device)
+static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match)
 {
-	struct platform_device *pdev = to_platform_device(device);
-	struct ucc_geth_platform_data *ugeth_pdata;
+	struct device *device = &ofdev->dev;
+	struct device_node *np = ofdev->node;
 	struct net_device *dev = NULL;
 	struct ucc_geth_private *ugeth = NULL;
 	struct ucc_geth_info *ug_info;
-	int err;
+	struct resource res;
+	struct device_node *phy;
+	int err, ucc_num, phy_interface;
 	static int mii_mng_configured = 0;
+	const phandle *ph;
+	const unsigned int *prop;
 
 	ugeth_vdbg("%s: IN", __FUNCTION__);
 
-	ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data;
+	prop = get_property(np, "device-id", NULL);
+	ucc_num = *prop - 1;
+	if ((ucc_num < 0) || (ucc_num > 7))
+		return -ENODEV;
 
-	ug_info = &ugeth_info[pdev->id];
-	ug_info->uf_info.ucc_num = pdev->id;
-	ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock;
-	ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock;
-	ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr;
-	ug_info->uf_info.irq = platform_get_irq(pdev, 0);
-	ug_info->phy_address = ugeth_pdata->phy_id;
-	ug_info->enet_interface = ugeth_pdata->phy_interface;
-	ug_info->board_flags = ugeth_pdata->board_flags;
-	ug_info->phy_interrupt = ugeth_pdata->phy_interrupt;
+	ug_info = &ugeth_info[ucc_num];
+	ug_info->uf_info.ucc_num = ucc_num;
+	prop = get_property(np, "rx-clock", NULL);
+	ug_info->uf_info.rx_clock = *prop;
+	prop = get_property(np, "tx-clock", NULL);
+	ug_info->uf_info.tx_clock = *prop;
+	err = of_address_to_resource(np, 0, &res);
+	if (err)
+		return -EINVAL;
+
+	ug_info->uf_info.regs = res.start;
+	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
+
+	ph = get_property(np, "phy-handle", NULL);
+	phy = of_find_node_by_phandle(*ph);
+
+	if (phy == NULL)
+		return -ENODEV;
+
+	prop = get_property(phy, "reg", NULL);
+	ug_info->phy_address = *prop;
+	prop = get_property(phy, "interface", NULL);
+	ug_info->enet_interface = *prop;
+	ug_info->phy_interrupt = irq_of_parse_and_map(phy, 0);
+	ug_info->board_flags = (ug_info->phy_interrupt == NO_IRQ)?
+			0:FSL_UGETH_BRD_HAS_PHY_INTR;
 
 	printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n",
 		ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs,
@@ -4162,12 +4173,44 @@
 
 	if (ug_info == NULL) {
 		ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__,
-			  pdev->id);
+			  ucc_num);
 		return -ENODEV;
 	}
 
+	/* FIXME: Work around for early chip rev.               */
+	/* There's a bug in initial chip rev(s) in the RGMII ac */
+	/* timing.						*/
+	/* The following compensates by writing to the reserved */
+	/* QE Port Output Hold Registers (CPOH1?).              */
+	prop = get_property(phy, "interface", NULL);
+	phy_interface = *prop;
+	if ((phy_interface == ENET_1000_RGMII) ||
+			(phy_interface == ENET_100_RGMII) ||
+			(phy_interface == ENET_10_RGMII)) {
+		struct device_node *soc;
+		phys_addr_t immrbase = -1;
+		u32 *tmp_reg;
+		u32 tmp_val;
+
+		soc = of_find_node_by_type(NULL, "soc");
+		if (soc) {
+			unsigned int size;
+			const void *prop = get_property(soc, "reg", &size);
+			immrbase = of_translate_address(soc, prop);
+			of_node_put(soc);
+		};
+
+		tmp_reg = (u32 *) ioremap(immrbase + 0x14A8, 0x4);
+		tmp_val = in_be32(tmp_reg);
+		if (ucc_num == 1)
+			out_be32(tmp_reg, tmp_val | 0x00003000);
+		else if (ucc_num == 2)
+			out_be32(tmp_reg, tmp_val | 0x0c000000);
+		iounmap(tmp_reg);
+	}
+
 	if (!mii_mng_configured) {
-		ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num);
+		ucc_set_qe_mux_mii_mng(ucc_num);
 		mii_mng_configured = 1;
 	}
 
@@ -4214,13 +4257,14 @@
 
 	ugeth->ug_info = ug_info;
 	ugeth->dev = dev;
-	memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6);
+	memcpy(dev->dev_addr, get_property(np, "mac-address", NULL), 6);
 
 	return 0;
 }
 
-static int ucc_geth_remove(struct device *device)
+static int ucc_geth_remove(struct of_device* ofdev)
 {
+	struct device *device = &ofdev->dev;
 	struct net_device *dev = dev_get_drvdata(device);
 	struct ucc_geth_private *ugeth = netdev_priv(dev);
 
@@ -4231,28 +4275,38 @@
 	return 0;
 }
 
-/* Structure for a device driver */
-static struct device_driver ucc_geth_driver = {
-	.name = DRV_NAME,
-	.bus = &platform_bus_type,
-	.probe = ucc_geth_probe,
-	.remove = ucc_geth_remove,
+static struct of_device_id ucc_geth_match[] = {
+	{
+		.type = "network",
+		.compatible = "ucc_geth",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, ucc_geth_match);
+
+static struct of_platform_driver ucc_geth_driver = {
+	.name		= DRV_NAME,
+	.match_table	= ucc_geth_match,
+	.probe		= ucc_geth_probe,
+	.remove		= ucc_geth_remove,
 };
 
 static int __init ucc_geth_init(void)
 {
 	int i;
+
 	printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
 	for (i = 0; i < 8; i++)
 		memcpy(&(ugeth_info[i]), &ugeth_primary_info,
 		       sizeof(ugeth_primary_info));
 
-	return driver_register(&ucc_geth_driver);
+	return of_register_driver(&ucc_geth_driver);
 }
 
 static void __exit ucc_geth_exit(void)
 {
-	driver_unregister(&ucc_geth_driver);
+	of_unregister_driver(&ucc_geth_driver);
 }
 
 module_init(ucc_geth_init);
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index 005965f..a665612 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -36,24 +36,24 @@
 #define ENET_INIT_PARAM_MAX_ENTRIES_RX  9
 #define ENET_INIT_PARAM_MAX_ENTRIES_TX  8
 
-typedef struct ucc_mii_mng {
+struct ucc_mii_mng {
 	u32 miimcfg;		/* MII management configuration reg */
 	u32 miimcom;		/* MII management command reg */
 	u32 miimadd;		/* MII management address reg */
 	u32 miimcon;		/* MII management control reg */
 	u32 miimstat;		/* MII management status reg */
 	u32 miimind;		/* MII management indication reg */
-} __attribute__ ((packed)) ucc_mii_mng_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth {
-	ucc_fast_t uccf;
+struct ucc_geth {
+	struct ucc_fast uccf;
 
 	u32 maccfg1;		/* mac configuration reg. 1 */
 	u32 maccfg2;		/* mac configuration reg. 2 */
 	u32 ipgifg;		/* interframe gap reg.  */
 	u32 hafdup;		/* half-duplex reg.  */
 	u8 res1[0x10];
-	ucc_mii_mng_t miimng;	/* MII management structure */
+	struct ucc_mii_mng miimng;	/* MII management structure */
 	u32 ifctl;		/* interface control reg */
 	u32 ifstat;		/* interface statux reg */
 	u32 macstnaddr1;	/* mac station address part 1 reg */
@@ -111,7 +111,7 @@
 	u32 scar;		/* Statistics carry register */
 	u32 scam;		/* Statistics caryy mask register */
 	u8 res5[0x200 - 0x1c4];
-} __attribute__ ((packed)) ucc_geth_t;
+} __attribute__ ((packed));
 
 /* UCC GETH TEMODR Register */
 #define TEMODER_TX_RMON_STATISTICS_ENABLE       0x0100	/* enable Tx statistics
@@ -508,39 +508,39 @@
 /* UCC GETH UDSR (Data Synchronization Register) */
 #define UDSR_MAGIC                              0x067E
 
-typedef struct ucc_geth_thread_data_tx {
+struct ucc_geth_thread_data_tx {
 	u8 res0[104];
-} __attribute__ ((packed)) ucc_geth_thread_data_tx_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_thread_data_rx {
+struct ucc_geth_thread_data_rx {
 	u8 res0[40];
-} __attribute__ ((packed)) ucc_geth_thread_data_rx_t;
+} __attribute__ ((packed));
 
 /* Send Queue Queue-Descriptor */
-typedef struct ucc_geth_send_queue_qd {
+struct ucc_geth_send_queue_qd {
 	u32 bd_ring_base;	/* pointer to BD ring base address */
 	u8 res0[0x8];
 	u32 last_bd_completed_address;/* initialize to last entry in BD ring */
 	u8 res1[0x30];
-} __attribute__ ((packed)) ucc_geth_send_queue_qd_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_send_queue_mem_region {
-	ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES];
-} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t;
+struct ucc_geth_send_queue_mem_region {
+	struct ucc_geth_send_queue_qd sqqd[NUM_TX_QUEUES];
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_thread_tx_pram {
+struct ucc_geth_thread_tx_pram {
 	u8 res0[64];
-} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_thread_rx_pram {
+struct ucc_geth_thread_rx_pram {
 	u8 res0[128];
-} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t;
+} __attribute__ ((packed));
 
 #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING        64
 #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8      64
 #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16     96
 
-typedef struct ucc_geth_scheduler {
+struct ucc_geth_scheduler {
 	u16 cpucount0;		/* CPU packet counter */
 	u16 cpucount1;		/* CPU packet counter */
 	u16 cecount0;		/* QE packet counter */
@@ -574,9 +574,9 @@
 				      /**< weight factor for queues   */
 	u32 minw;		/* temporary variable handled by QE */
 	u8 res1[0x70 - 0x64];
-} __attribute__ ((packed)) ucc_geth_scheduler_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_tx_firmware_statistics_pram {
+struct ucc_geth_tx_firmware_statistics_pram {
 	u32 sicoltx;		/* single collision */
 	u32 mulcoltx;		/* multiple collision */
 	u32 latecoltxfr;	/* late collision */
@@ -596,9 +596,9 @@
 				   and 1518 octets */
 	u32 txpktsjumbo;	/* total packets (including bad) between 1024
 				   and MAXLength octets */
-} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_rx_firmware_statistics_pram {
+struct ucc_geth_rx_firmware_statistics_pram {
 	u32 frrxfcser;		/* frames with crc error */
 	u32 fraligner;		/* frames with alignment error */
 	u32 inrangelenrxer;	/* in range length error */
@@ -630,33 +630,33 @@
 				   replaced */
 	u32 insertvlan;		/* total frames that had their VLAN tag
 				   inserted */
-} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_rx_interrupt_coalescing_entry {
+struct ucc_geth_rx_interrupt_coalescing_entry {
 	u32 interruptcoalescingmaxvalue;	/* interrupt coalescing max
 						   value */
 	u32 interruptcoalescingcounter;	/* interrupt coalescing counter,
 					   initialize to
 					   interruptcoalescingmaxvalue */
-} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_rx_interrupt_coalescing_table {
-	ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES];
+struct ucc_geth_rx_interrupt_coalescing_table {
+	struct ucc_geth_rx_interrupt_coalescing_entry coalescingentry[NUM_RX_QUEUES];
 				       /**< interrupt coalescing entry */
-} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_rx_prefetched_bds {
-	qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS];	/* prefetched bd */
-} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t;
+struct ucc_geth_rx_prefetched_bds {
+	struct qe_bd bd[NUM_BDS_IN_PREFETCHED_BDS];	/* prefetched bd */
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_rx_bd_queues_entry {
+struct ucc_geth_rx_bd_queues_entry {
 	u32 bdbaseptr;		/* BD base pointer */
 	u32 bdptr;		/* BD pointer */
 	u32 externalbdbaseptr;	/* external BD base pointer */
 	u32 externalbdptr;	/* external BD pointer */
-} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_tx_global_pram {
+struct ucc_geth_tx_global_pram {
 	u16 temoder;
 	u8 res0[0x38 - 0x02];
 	u32 sqptr;		/* a base pointer to send queue memory region */
@@ -670,15 +670,15 @@
 	u32 tqptr;		/* a base pointer to the Tx Queues Memory
 				   Region */
 	u8 res2[0x80 - 0x74];
-} __attribute__ ((packed)) ucc_geth_tx_global_pram_t;
+} __attribute__ ((packed));
 
 /* structure representing Extended Filtering Global Parameters in PRAM */
-typedef struct ucc_geth_exf_global_pram {
+struct ucc_geth_exf_global_pram {
 	u32 l2pcdptr;		/* individual address filter, high */
 	u8 res0[0x10 - 0x04];
-} __attribute__ ((packed)) ucc_geth_exf_global_pram_t;
+} __attribute__ ((packed));
 
-typedef struct ucc_geth_rx_global_pram {
+struct ucc_geth_rx_global_pram {
 	u32 remoder;		/* ethernet mode reg. */
 	u32 rqptr;		/* base pointer to the Rx Queues Memory Region*/
 	u32 res0[0x1];
@@ -710,12 +710,12 @@
 	u32 exfGlobalParam;	/* base address for extended filtering global
 				   parameters */
 	u8 res6[0x100 - 0xC4];	/* Initialize to zero */
-} __attribute__ ((packed)) ucc_geth_rx_global_pram_t;
+} __attribute__ ((packed));
 
 #define GRACEFUL_STOP_ACKNOWLEDGE_RX            0x01
 
 /* structure representing InitEnet command */
-typedef struct ucc_geth_init_pram {
+struct ucc_geth_init_pram {
 	u8 resinit1;
 	u8 resinit2;
 	u8 resinit3;
@@ -729,7 +729,7 @@
 	u32 txglobal;		/* tx global */
 	u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX];	/* tx threads */
 	u8 res3[0x1];
-} __attribute__ ((packed)) ucc_geth_init_pram_t;
+} __attribute__ ((packed));
 
 #define ENET_INIT_PARAM_RGF_SHIFT               (32 - 4)
 #define ENET_INIT_PARAM_TGF_SHIFT               (32 - 8)
@@ -746,27 +746,27 @@
 #define ENET_INIT_PARAM_MAGIC_RES_INIT5         0x0400
 
 /* structure representing 82xx Address Filtering Enet Address in PRAM */
-typedef struct ucc_geth_82xx_enet_address {
+struct ucc_geth_82xx_enet_address {
 	u8 res1[0x2];
 	u16 h;			/* address (MSB) */
 	u16 m;			/* address */
 	u16 l;			/* address (LSB) */
-} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t;
+} __attribute__ ((packed));
 
 /* structure representing 82xx Address Filtering PRAM */
-typedef struct ucc_geth_82xx_address_filtering_pram {
+struct ucc_geth_82xx_address_filtering_pram {
 	u32 iaddr_h;		/* individual address filter, high */
 	u32 iaddr_l;		/* individual address filter, low */
 	u32 gaddr_h;		/* group address filter, high */
 	u32 gaddr_l;		/* group address filter, low */
-	ucc_geth_82xx_enet_address_t taddr;
-	ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS];
+	struct ucc_geth_82xx_enet_address taddr;
+	struct ucc_geth_82xx_enet_address paddr[NUM_OF_PADDRS];
 	u8 res0[0x40 - 0x38];
-} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t;
+} __attribute__ ((packed));
 
 /* GETH Tx firmware statistics structure, used when calling
    UCC_GETH_GetStatistics. */
-typedef struct ucc_geth_tx_firmware_statistics {
+struct ucc_geth_tx_firmware_statistics {
 	u32 sicoltx;		/* single collision */
 	u32 mulcoltx;		/* multiple collision */
 	u32 latecoltxfr;	/* late collision */
@@ -786,11 +786,11 @@
 				   and 1518 octets */
 	u32 txpktsjumbo;	/* total packets (including bad) between 1024
 				   and MAXLength octets */
-} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t;
+} __attribute__ ((packed));
 
 /* GETH Rx firmware statistics structure, used when calling
    UCC_GETH_GetStatistics. */
-typedef struct ucc_geth_rx_firmware_statistics {
+struct ucc_geth_rx_firmware_statistics {
 	u32 frrxfcser;		/* frames with crc error */
 	u32 fraligner;		/* frames with alignment error */
 	u32 inrangelenrxer;	/* in range length error */
@@ -822,11 +822,11 @@
 				   replaced */
 	u32 insertvlan;		/* total frames that had their VLAN tag
 				   inserted */
-} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t;
+} __attribute__ ((packed));
 
 /* GETH hardware statistics structure, used when calling
    UCC_GETH_GetStatistics. */
-typedef struct ucc_geth_hardware_statistics {
+struct ucc_geth_hardware_statistics {
 	u32 tx64;		/* Total number of frames (including bad
 				   frames) transmitted that were exactly of the
 				   minimal length (64 for un tagged, 68 for
@@ -871,7 +871,7 @@
 	u32 rbca;		/* Total number of frames received succesfully
 				   that had destination address equal to the
 				   broadcast address */
-} __attribute__ ((packed)) ucc_geth_hardware_statistics_t;
+} __attribute__ ((packed));
 
 /* UCC GETH Tx errors returned via TxConf callback */
 #define TX_ERRORS_DEF      0x0200
@@ -1013,21 +1013,21 @@
 				(MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112)
 
 /* Ethernet speed */
-typedef enum enet_speed {
+enum enet_speed {
 	ENET_SPEED_10BT,	/* 10 Base T */
 	ENET_SPEED_100BT,	/* 100 Base T */
 	ENET_SPEED_1000BT	/* 1000 Base T */
-} enet_speed_e;
+};
 
 /* Ethernet Address Type. */
-typedef enum enet_addr_type {
+enum enet_addr_type {
 	ENET_ADDR_TYPE_INDIVIDUAL,
 	ENET_ADDR_TYPE_GROUP,
 	ENET_ADDR_TYPE_BROADCAST
-} enet_addr_type_e;
+};
 
 /* TBI / MII Set Register */
-typedef enum enet_tbi_mii_reg {
+enum enet_tbi_mii_reg {
 	ENET_TBI_MII_CR = 0x00,	/* Control (CR ) */
 	ENET_TBI_MII_SR = 0x01,	/* Status (SR ) */
 	ENET_TBI_MII_ANA = 0x04,	/* AN advertisement (ANA ) */
@@ -1040,10 +1040,10 @@
 	ENET_TBI_MII_EXST = 0x0F,	/* Extended status (EXST ) */
 	ENET_TBI_MII_JD = 0x10,	/* Jitter diagnostics (JD ) */
 	ENET_TBI_MII_TBICON = 0x11	/* TBI control (TBICON ) */
-} enet_tbi_mii_reg_e;
+};
 
 /* UCC GETH 82xx Ethernet Address Recognition Location */
-typedef enum ucc_geth_enet_address_recognition_location {
+enum ucc_geth_enet_address_recognition_location {
 	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station
 								      address */
 	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST,	/* additional
@@ -1065,10 +1065,10 @@
 	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH,	/* group hash */
 	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual
 								      hash */
-} ucc_geth_enet_address_recognition_location_e;
+};
 
 /* UCC GETH vlan operation tagged */
-typedef enum ucc_geth_vlan_operation_tagged {
+enum ucc_geth_vlan_operation_tagged {
 	UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0,	/* Tagged - nop */
 	UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG
 		= 0x1,	/* Tagged - replace vid portion of q tag */
@@ -1076,18 +1076,18 @@
 		= 0x2,	/* Tagged - if vid0 replace vid with default value  */
 	UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME
 		= 0x3	/* Tagged - extract q tag from frame */
-} ucc_geth_vlan_operation_tagged_e;
+};
 
 /* UCC GETH vlan operation non-tagged */
-typedef enum ucc_geth_vlan_operation_non_tagged {
+enum ucc_geth_vlan_operation_non_tagged {
 	UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0,	/* Non tagged - nop */
 	UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1	/* Non tagged -
 								   q tag insert
 								 */
-} ucc_geth_vlan_operation_non_tagged_e;
+};
 
 /* UCC GETH Rx Quality of Service Mode */
-typedef enum ucc_geth_qos_mode {
+enum ucc_geth_qos_mode {
 	UCC_GETH_QOS_MODE_DEFAULT = 0x0,	/* default queue */
 	UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1,	/* queue
 								   determined
@@ -1097,11 +1097,11 @@
 								   determined
 								   by L3
 								   criteria */
-} ucc_geth_qos_mode_e;
+};
 
 /* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together
    for combined functionality */
-typedef enum ucc_geth_statistics_gathering_mode {
+enum ucc_geth_statistics_gathering_mode {
 	UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000,	/* No
 								   statistics
 								   gathering */
@@ -1122,10 +1122,10 @@
 								      statistics
 								      gathering
 								    */
-} ucc_geth_statistics_gathering_mode_e;
+};
 
 /* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */
-typedef enum ucc_geth_maccfg2_pad_and_crc_mode {
+enum ucc_geth_maccfg2_pad_and_crc_mode {
 	UCC_GETH_PAD_AND_CRC_MODE_NONE
 		= MACCFG2_PAD_AND_CRC_MODE_NONE,	/* Neither Padding
 							   short frames
@@ -1135,61 +1135,59 @@
 							   CRC only */
 	UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC =
 	    MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC
-} ucc_geth_maccfg2_pad_and_crc_mode_e;
+};
 
 /* UCC GETH upsmr Flow Control Mode */
-typedef enum ucc_geth_flow_control_mode {
+enum ucc_geth_flow_control_mode {
 	UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000,	/* No automatic
 								   flow control
 								 */
 	UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY
 		= 0x00004000	/* Send pause frame when RxFIFO reaches its
 				   emergency threshold */
-} ucc_geth_flow_control_mode_e;
+};
 
 /* UCC GETH number of threads */
-typedef enum ucc_geth_num_of_threads {
+enum ucc_geth_num_of_threads {
 	UCC_GETH_NUM_OF_THREADS_1 = 0x1,	/* 1 */
 	UCC_GETH_NUM_OF_THREADS_2 = 0x2,	/* 2 */
 	UCC_GETH_NUM_OF_THREADS_4 = 0x0,	/* 4 */
 	UCC_GETH_NUM_OF_THREADS_6 = 0x3,	/* 6 */
 	UCC_GETH_NUM_OF_THREADS_8 = 0x4	/* 8 */
-} ucc_geth_num_of_threads_e;
+};
 
 /* UCC GETH number of station addresses */
-typedef enum ucc_geth_num_of_station_addresses {
+enum ucc_geth_num_of_station_addresses {
 	UCC_GETH_NUM_OF_STATION_ADDRESSES_1,	/* 1 */
 	UCC_GETH_NUM_OF_STATION_ADDRESSES_5	/* 5 */
-} ucc_geth_num_of_station_addresses_e;
-
-typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS];
+};
 
 /* UCC GETH 82xx Ethernet Address Container */
-typedef struct enet_addr_container {
-	enet_addr_t address;	/* ethernet address */
-	ucc_geth_enet_address_recognition_location_e location;	/* location in
+struct enet_addr_container {
+	u8 address[ENET_NUM_OCTETS_PER_ADDRESS];	/* ethernet address */
+	enum ucc_geth_enet_address_recognition_location location;	/* location in
 								   82xx address
 								   recognition
 								   hardware */
 	struct list_head node;
-} enet_addr_container_t;
+};
 
-#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node)
+#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, struct enet_addr_container, node)
 
 /* UCC GETH Termination Action Descriptor (TAD) structure. */
-typedef struct ucc_geth_tad_params {
+struct ucc_geth_tad_params {
 	int rx_non_dynamic_extended_features_mode;
 	int reject_frame;
-	ucc_geth_vlan_operation_tagged_e vtag_op;
-	ucc_geth_vlan_operation_non_tagged_e vnontag_op;
-	ucc_geth_qos_mode_e rqos;
+	enum ucc_geth_vlan_operation_tagged vtag_op;
+	enum ucc_geth_vlan_operation_non_tagged vnontag_op;
+	enum ucc_geth_qos_mode rqos;
 	u8 vpri;
 	u16 vid;
-} ucc_geth_tad_params_t;
+};
 
 /* GETH protocol initialization structure */
-typedef struct ucc_geth_info {
-	ucc_fast_info_t uf_info;
+struct ucc_geth_info {
+	struct ucc_fast_info uf_info;
 	u8 numQueuesTx;
 	u8 numQueuesRx;
 	int ipCheckSumCheck;
@@ -1251,51 +1249,51 @@
 	u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
 	u16 bdRingLenTx[NUM_TX_QUEUES];
 	u16 bdRingLenRx[NUM_RX_QUEUES];
-	enet_interface_e enet_interface;
-	ucc_geth_num_of_station_addresses_e numStationAddresses;
-	 qe_fltr_largest_external_tbl_lookup_key_size_e
+	enum enet_interface enet_interface;
+	enum ucc_geth_num_of_station_addresses numStationAddresses;
+	enum qe_fltr_largest_external_tbl_lookup_key_size
 	    largestexternallookupkeysize;
-	ucc_geth_statistics_gathering_mode_e statisticsMode;
-	ucc_geth_vlan_operation_tagged_e vlanOperationTagged;
-	ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged;
-	ucc_geth_qos_mode_e rxQoSMode;
-	ucc_geth_flow_control_mode_e aufc;
-	ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc;
-	ucc_geth_num_of_threads_e numThreadsTx;
-	ucc_geth_num_of_threads_e numThreadsRx;
-	qe_risc_allocation_e riscTx;
-	qe_risc_allocation_e riscRx;
-} ucc_geth_info_t;
+	enum ucc_geth_statistics_gathering_mode statisticsMode;
+	enum ucc_geth_vlan_operation_tagged vlanOperationTagged;
+	enum ucc_geth_vlan_operation_non_tagged vlanOperationNonTagged;
+	enum ucc_geth_qos_mode rxQoSMode;
+	enum ucc_geth_flow_control_mode aufc;
+	enum ucc_geth_maccfg2_pad_and_crc_mode padAndCrc;
+	enum ucc_geth_num_of_threads numThreadsTx;
+	enum ucc_geth_num_of_threads numThreadsRx;
+	enum qe_risc_allocation riscTx;
+	enum qe_risc_allocation riscRx;
+};
 
 /* structure representing UCC GETH */
-typedef struct ucc_geth_private {
-	ucc_geth_info_t *ug_info;
-	ucc_fast_private_t *uccf;
+struct ucc_geth_private {
+	struct ucc_geth_info *ug_info;
+	struct ucc_fast_private *uccf;
 	struct net_device *dev;
 	struct net_device_stats stats;	/* linux network statistics */
-	ucc_geth_t *ug_regs;
-	ucc_geth_init_pram_t *p_init_enet_param_shadow;
-	ucc_geth_exf_global_pram_t *p_exf_glbl_param;
+	struct ucc_geth *ug_regs;
+	struct ucc_geth_init_pram *p_init_enet_param_shadow;
+	struct ucc_geth_exf_global_pram *p_exf_glbl_param;
 	u32 exf_glbl_param_offset;
-	ucc_geth_rx_global_pram_t *p_rx_glbl_pram;
+	struct ucc_geth_rx_global_pram *p_rx_glbl_pram;
 	u32 rx_glbl_pram_offset;
-	ucc_geth_tx_global_pram_t *p_tx_glbl_pram;
+	struct ucc_geth_tx_global_pram *p_tx_glbl_pram;
 	u32 tx_glbl_pram_offset;
-	ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg;
+	struct ucc_geth_send_queue_mem_region *p_send_q_mem_reg;
 	u32 send_q_mem_reg_offset;
-	ucc_geth_thread_data_tx_t *p_thread_data_tx;
+	struct ucc_geth_thread_data_tx *p_thread_data_tx;
 	u32 thread_dat_tx_offset;
-	ucc_geth_thread_data_rx_t *p_thread_data_rx;
+	struct ucc_geth_thread_data_rx *p_thread_data_rx;
 	u32 thread_dat_rx_offset;
-	ucc_geth_scheduler_t *p_scheduler;
+	struct ucc_geth_scheduler *p_scheduler;
 	u32 scheduler_offset;
-	ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+	struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram;
 	u32 tx_fw_statistics_pram_offset;
-	ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+	struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram;
 	u32 rx_fw_statistics_pram_offset;
-	ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl;
+	struct ucc_geth_rx_interrupt_coalescing_table *p_rx_irq_coalescing_tbl;
 	u32 rx_irq_coalescing_tbl_offset;
-	ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl;
+	struct ucc_geth_rx_bd_queues_entry *p_rx_bd_qs_tbl;
 	u32 rx_bd_qs_tbl_offset;
 	u8 *p_tx_bd_ring[NUM_TX_QUEUES];
 	u32 tx_bd_ring_offset[NUM_TX_QUEUES];
@@ -1308,7 +1306,7 @@
 	u16 cpucount[NUM_TX_QUEUES];
 	volatile u16 *p_cpucount[NUM_TX_QUEUES];
 	int indAddrRegUsed[NUM_OF_PADDRS];
-	enet_addr_t paddr[NUM_OF_PADDRS];
+	u8 paddr[NUM_OF_PADDRS][ENET_NUM_OCTETS_PER_ADDRESS];	/* ethernet address */
 	u8 numGroupAddrInHash;
 	u8 numIndAddrInHash;
 	u8 numIndAddrInReg;
@@ -1334,6 +1332,6 @@
 	int oldspeed;
 	int oldduplex;
 	int oldlink;
-} ucc_geth_private_t;
+};
 
 #endif				/* __UCC_GETH_H__ */
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
index 67260eb..5360ec0 100644
--- a/drivers/net/ucc_geth_phy.c
+++ b/drivers/net/ucc_geth_phy.c
@@ -42,7 +42,6 @@
 
 #include "ucc_geth.h"
 #include "ucc_geth_phy.h"
-#include <platforms/83xx/mpc8360e_pb.h>
 
 #define ugphy_printk(level, format, arg...)  \
         printk(level format "\n", ## arg)
@@ -72,16 +71,14 @@
 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 u8 *bcsr_regs = NULL;
-
 /* Write value to the PHY for this device to the register at regnum, */
 /* waiting until the write is done before it returns.  All PHY */
 /* configuration has to be done through the TSEC1 MIIM regs */
 void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
-	ucc_mii_mng_t *mii_regs;
-	enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_mii_mng *mii_regs;
+	enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg) regnum;
 	u32 tmp_reg;
 
 	ugphy_vdbg("%s: IN", __FUNCTION__);
@@ -116,9 +113,9 @@
 /* configuration has to be done through the TSEC1 MIIM regs */
 int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
 {
-	ucc_geth_private_t *ugeth = netdev_priv(dev);
-	ucc_mii_mng_t *mii_regs;
-	enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_mii_mng *mii_regs;
+	enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg) regnum;
 	u32 tmp_reg;
 	u16 value;
 
@@ -634,11 +631,6 @@
 
 static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
 {
-/* FIXME: This lines are for BUG fixing in the mpc8325.
-Remove this from here when it's fixed */
-	if (bcsr_regs == NULL)
-		bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
-	bcsr_regs[14] |= 0x40;
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	/* Clear the interrupts by reading the reg */
@@ -650,12 +642,6 @@
 
 static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
 {
-/* FIXME: This lines are for BUG fixing in the mpc8325.
-Remove this from here when it's fixed */
-	if (bcsr_regs == NULL) {
-		bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
-		bcsr_regs[14] &= ~0x40;
-	}
 	ugphy_vdbg("%s: IN", __FUNCTION__);
 
 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h
index 2f98b8f..f574078 100644
--- a/drivers/net/ucc_geth_phy.h
+++ b/drivers/net/ucc_geth_phy.h
@@ -126,7 +126,7 @@
 	/* And management functions */
 	struct phy_info *phyinfo;
 
-	ucc_mii_mng_t *mii_regs;
+	struct ucc_mii_mng *mii_regs;
 
 	/* forced speed & duplex (no autoneg)
 	 * partner speed & duplex & pause (autoneg)
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index cbebf1b..ebbda1d 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -404,7 +404,7 @@
 static int  rhine_open(struct net_device *dev);
 static void rhine_tx_timeout(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
 static void rhine_tx(struct net_device *dev);
 static int rhine_rx(struct net_device *dev, int limit);
 static void rhine_error(struct net_device *dev, int intr_status);
@@ -569,7 +569,7 @@
 static void rhine_poll(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	rhine_interrupt(dev->irq, (void *)dev, NULL);
+	rhine_interrupt(dev->irq, (void *)dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -1290,7 +1290,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct rhine_private *rp = netdev_priv(dev);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 7d8808c..74f8947 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -236,7 +236,7 @@
 static int velocity_open(struct net_device *dev);
 static int velocity_change_mtu(struct net_device *dev, int mtu);
 static int velocity_xmit(struct sk_buff *skb, struct net_device *dev);
-static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs);
+static int velocity_intr(int irq, void *dev_instance);
 static void velocity_set_multi(struct net_device *dev);
 static struct net_device_stats *velocity_get_stats(struct net_device *dev);
 static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -2036,7 +2036,6 @@
  *	velocity_intr		-	interrupt callback
  *	@irq: interrupt number
  *	@dev_instance: interrupting device
- *	@pt_regs: CPU register state at interrupt
  *
  *	Called whenever an interrupt is generated by the velocity
  *	adapter IRQ line. We may not be the source of the interrupt
@@ -2044,7 +2043,7 @@
  *	efficiently as possible.
  */
 
-static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
+static int velocity_intr(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct velocity_info *vptr = netdev_priv(dev);
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 1f95b48..e1bf8b9 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -345,7 +345,7 @@
 static void put_driver_status_nolock(struct cosa_data *cosa);
 
 /* Interrupt handling */
-static irqreturn_t cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
+static irqreturn_t cosa_interrupt(int irq, void *cosa);
 
 /* I/O ops debugging */
 #ifdef DEBUG_IO
@@ -1972,7 +1972,7 @@
 	spin_unlock_irqrestore(&cosa->lock, flags);
 }
 
-static irqreturn_t cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
+static irqreturn_t cosa_interrupt(int irq, void *cosa_)
 {
 	unsigned status;
 	int count = 0;
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index a5e7ce1..6e5f1c8 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -74,7 +74,7 @@
 static int cycx_wan_shutdown(struct wan_device *wandev);
 
 /* Miscellaneous functions */
-static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t cycx_isr(int irq, void *dev_id);
 
 /* Global Data
  * Note: All data must be explicitly initialized!!!
@@ -301,11 +301,11 @@
  * o acknowledge Cyclom 2X hardware interrupt.
  * o call protocol-specific interrupt service routine, if any.
  */
-static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cycx_isr(int irq, void *dev_id)
 {
-	struct cycx_device *card = (struct cycx_device *)dev_id;
+	struct cycx_device *card = dev_id;
 
-	if (!card || card->wandev.state == WAN_UNCONFIGURED)
+	if (card->wandev.state == WAN_UNCONFIGURED)
 		goto out;
 
 	if (card->in_isr) {
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index af4d415..25021a7 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -365,7 +365,7 @@
 static void dscc4_release_ring(struct dscc4_dev_priv *);
 static void dscc4_timer(unsigned long);
 static void dscc4_tx_timeout(struct net_device *);
-static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
+static irqreturn_t dscc4_irq(int irq, void *dev_id);
 static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
 #ifdef DSCC4_POLLING
@@ -1476,7 +1476,7 @@
 	return ret;
 }
 
-static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs)
+static irqreturn_t dscc4_irq(int irq, void *token)
 {
 	struct dscc4_dev_priv *root = token;
 	struct dscc4_pci_priv *priv;
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 564351a..c45d6a8 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -1498,7 +1498,7 @@
  *      Dev_id is our fst_card_info pointer
  */
 static irqreturn_t
-fst_intr(int irq, void *dev_id, struct pt_regs *regs)
+fst_intr(int irq, void *dev_id)
 {
 	struct fst_card_info *card;
 	struct fst_port_info *port;
diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
index dce2bb3..8d0a1f2 100644
--- a/drivers/net/wan/hd6457x.c
+++ b/drivers/net/wan/hd6457x.c
@@ -424,7 +424,7 @@
 
 
 
-static irqreturn_t sca_intr(int irq, void* dev_id, struct pt_regs *regs)
+static irqreturn_t sca_intr(int irq, void* dev_id)
 {
 	card_t *card = dev_id;
 	int i;
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 7b5d81d..2b54f1b 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -100,7 +100,7 @@
 static int lmc_open(struct net_device *dev);
 static int lmc_close(struct net_device *dev);
 static struct net_device_stats *lmc_get_stats(struct net_device *dev);
-static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t lmc_interrupt(int irq, void *dev_instance);
 static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
 static void lmc_softreset(lmc_softc_t * const);
 static void lmc_running_reset(struct net_device *dev);
@@ -1273,7 +1273,7 @@
 /* Interrupt handling routine.  This will take an incoming packet, or clean
  * up after a trasmit.
  */
-static irqreturn_t lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
+static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/
 {
     struct net_device *dev = (struct net_device *) dev_instance;
     lmc_softc_t *sc;
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 8d9b959..36d1c3f 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -284,7 +284,7 @@
 static void rx_dma_buf_init(pc300_t *, int);
 static void tx_dma_buf_check(pc300_t *, int);
 static void rx_dma_buf_check(pc300_t *, int);
-static irqreturn_t cpc_intr(int, void *, struct pt_regs *);
+static irqreturn_t cpc_intr(int, void *);
 static struct net_device_stats *cpc_get_stats(struct net_device *);
 static int clock_rate_calc(uclong, uclong, int *);
 static uclong detect_ram(pc300_t *);
@@ -2363,7 +2363,7 @@
 	}
 }
 
-static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpc_intr(int irq, void *dev_id)
 {
 	pc300_t *card;
 	volatile ucchar plx_status;
@@ -2867,7 +2867,6 @@
 	uclong clktype = chan->conf.phys_settings.clock_type;
 	ucshort encoding = chan->conf.proto_settings.encoding;
 	ucshort parity = chan->conf.proto_settings.parity;   
-	int tmc, br;
 	ucchar md0, md2;
     
 	/* Reset the channel */
@@ -2940,8 +2939,12 @@
 		case PC300_RSV:
 		case PC300_X21:
 			if (clktype == CLOCK_INT || clktype == CLOCK_TXINT) {
+				int tmc, br;
+
 				/* Calculate the clkrate parameters */
 				tmc = clock_rate_calc(clkrate, card->hw.clock, &br);
+				if (tmc < 0)
+					return -EIO;
 				cpc_writeb(scabase + M_REG(TMCT, ch), tmc);
 				cpc_writeb(scabase + M_REG(TXS, ch),
 					   (TXS_DTRXC | TXS_IBRG | br));
@@ -3097,14 +3100,16 @@
 	return 0;
 }
 
-static void cpc_opench(pc300dev_t * d)
+static int cpc_opench(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	int ch = chan->channel;
+	int ch = chan->channel, rc;
 	void __iomem *scabase = card->hw.scabase;
 
-	ch_config(d);
+	rc = ch_config(d);
+	if (rc)
+		return rc;
 
 	rx_config(d);
 
@@ -3113,6 +3118,8 @@
 	/* Assert RTS and DTR */
 	cpc_writeb(scabase + M_REG(CTL, ch),
 		   cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
+
+	return 0;
 }
 
 static void cpc_closech(pc300dev_t * d)
@@ -3168,9 +3175,16 @@
 	}
 
 	sprintf(ifr.ifr_name, "%s", dev->name);
-	cpc_opench(d);
+	result = cpc_opench(d);
+	if (result)
+		goto err_out;
+
 	netif_start_queue(dev);
 	return 0;
+
+err_out:
+	hdlc_close(dev);
+	return result;
 }
 
 static int cpc_close(struct net_device *dev)
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index fc75bec..fc5c0c6 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -119,7 +119,7 @@
 static struct net_device_stats  *sbni_get_stats( struct net_device * );
 static void  set_multicast_list( struct net_device * );
 
-static irqreturn_t sbni_interrupt( int, void *, struct pt_regs * );
+static irqreturn_t sbni_interrupt( int, void * );
 static void  handle_channel( struct net_device * );
 static int   recv_frame( struct net_device * );
 static void  send_frame( struct net_device * );
@@ -501,7 +501,7 @@
  */ 
 
 static irqreturn_t
-sbni_interrupt( int  irq,  void  *dev_id,  struct pt_regs  *regs )
+sbni_interrupt( int  irq,  void  *dev_id )
 {
 	struct net_device	  *dev = (struct net_device *) dev_id;
 	struct net_local  *nl  = (struct net_local *) dev->priv;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 0ba018f..6a485f0 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -867,7 +867,7 @@
 	spin_unlock_irqrestore(&sdla_lock, flags);
 }
 
-static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t sdla_isr(int irq, void *dev_id)
 {
 	struct net_device     *dev;
 	struct frad_local *flp;
@@ -875,13 +875,7 @@
 
 	dev = dev_id;
 
-	if (dev == NULL)
-	{
-		printk(KERN_WARNING "sdla_isr(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
-	flp = dev->priv;
+	flp = netdev_priv(dev);
 
 	if (!flp->initialized)
 	{
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index ec68f7d..c736015 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -244,7 +244,7 @@
 
 
 
-static irqreturn_t wanxl_intr(int irq, void* dev_id, struct pt_regs *regs)
+static irqreturn_t wanxl_intr(int irq, void* dev_id)
 {
         card_t *card = dev_id;
         int i;
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index caa48f1..59ddd21 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -728,7 +728,7 @@
  *	channel). c->lock for both channels points to dev->lock
  */
 
-irqreturn_t z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t z8530_interrupt(int irq, void *dev_id)
 {
 	struct z8530_dev *dev=dev_id;
 	u8 intr;
diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h
index 77e5320..158aea7 100644
--- a/drivers/net/wan/z85230.h
+++ b/drivers/net/wan/z85230.h
@@ -396,7 +396,7 @@
 extern u8 z8530_dead_port[];
 extern u8 z8530_hdlc_kilostream_85230[];
 extern u8 z8530_hdlc_kilostream[];
-extern irqreturn_t z8530_interrupt(int, void *, struct pt_regs *);
+extern irqreturn_t z8530_interrupt(int, void *);
 extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io);
 extern int z8530_init(struct z8530_dev *);
 extern int z8530_shutdown(struct z8530_dev *);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 39d0934..efcdaf1 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1120,8 +1120,7 @@
 static void mpi_receive_802_11(struct airo_info *ai);
 static int waitbusy (struct airo_info *ai);
 
-static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
-			    *regs);
+static irqreturn_t airo_interrupt( int irq, void* dev_id);
 static int airo_thread(void *data);
 static void timer_func( struct net_device *dev );
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -2898,6 +2897,8 @@
 		goto err_out_map;
 	}
 	ai->wifidev = init_wifidev(ai, dev);
+	if (!ai->wifidev)
+		goto err_out_reg;
 
 	set_bit(FLAG_REGISTERED,&ai->flags);
 	airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
@@ -2909,11 +2910,18 @@
 		for( i = 0; i < MAX_FIDS; i++ )
 			ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
-	setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
+	if (setup_proc_entry(dev, dev->priv) < 0)
+		goto err_out_wifi;
+
 	netif_start_queue(dev);
 	SET_MODULE_OWNER(dev);
 	return dev;
 
+err_out_wifi:
+	unregister_netdev(ai->wifidev);
+	free_netdev(ai->wifidev);
+err_out_reg:
+	unregister_netdev(dev);
 err_out_map:
 	if (test_bit(FLAG_MPI,&ai->flags) && pci) {
 		pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
@@ -3090,7 +3098,8 @@
 						set_bit(JOB_AUTOWEP, &ai->jobs);
 						break;
 					}
-					if (!kthread_should_stop()) {
+					if (!kthread_should_stop() &&
+					    !freezing(current)) {
 						unsigned long wake_at;
 						if (!ai->expires || !ai->scan_timeout) {
 							wake_at = max(ai->expires,
@@ -3102,7 +3111,8 @@
 						schedule_timeout(wake_at - jiffies);
 						continue;
 					}
-				} else if (!kthread_should_stop()) {
+				} else if (!kthread_should_stop() &&
+					   !freezing(current)) {
 					schedule();
 					continue;
 				}
@@ -3151,7 +3161,7 @@
 	return 0;
 }
 
-static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
+static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
 	struct net_device *dev = (struct net_device *)dev_id;
 	u16 status;
 	u16 fid;
@@ -4496,91 +4506,128 @@
 	apriv->proc_entry = create_proc_entry(apriv->proc_name,
 					      S_IFDIR|airo_perm,
 					      airo_entry);
-        apriv->proc_entry->uid = proc_uid;
-        apriv->proc_entry->gid = proc_gid;
-        apriv->proc_entry->owner = THIS_MODULE;
+	if (!apriv->proc_entry)
+		goto fail;
+	apriv->proc_entry->uid = proc_uid;
+	apriv->proc_entry->gid = proc_gid;
+	apriv->proc_entry->owner = THIS_MODULE;
 
 	/* Setup the StatsDelta */
 	entry = create_proc_entry("StatsDelta",
 				  S_IFREG | (S_IRUGO&proc_perm),
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_stats_delta;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_statsdelta_ops);
 
 	/* Setup the Stats */
 	entry = create_proc_entry("Stats",
 				  S_IFREG | (S_IRUGO&proc_perm),
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_stats;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_stats_ops);
 
 	/* Setup the Status */
 	entry = create_proc_entry("Status",
 				  S_IFREG | (S_IRUGO&proc_perm),
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_status;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_status_ops);
 
 	/* Setup the Config */
 	entry = create_proc_entry("Config",
 				  S_IFREG | proc_perm,
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_config;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_config_ops);
 
 	/* Setup the SSID */
 	entry = create_proc_entry("SSID",
 				  S_IFREG | proc_perm,
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_ssid;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_SSID_ops);
 
 	/* Setup the APList */
 	entry = create_proc_entry("APList",
 				  S_IFREG | proc_perm,
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_aplist;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_APList_ops);
 
 	/* Setup the BSSList */
 	entry = create_proc_entry("BSSList",
 				  S_IFREG | proc_perm,
 				  apriv->proc_entry);
+	if (!entry)
+		goto fail_bsslist;
 	entry->uid = proc_uid;
 	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_BSSList_ops);
 
 	/* Setup the WepKey */
 	entry = create_proc_entry("WepKey",
 				  S_IFREG | proc_perm,
 				  apriv->proc_entry);
-        entry->uid = proc_uid;
-        entry->gid = proc_gid;
+	if (!entry)
+		goto fail_wepkey;
+	entry->uid = proc_uid;
+	entry->gid = proc_gid;
 	entry->data = dev;
-        entry->owner = THIS_MODULE;
+	entry->owner = THIS_MODULE;
 	SETPROC_OPS(entry, proc_wepkey_ops);
 
 	return 0;
+
+fail_wepkey:
+	remove_proc_entry("BSSList", apriv->proc_entry);
+fail_bsslist:
+	remove_proc_entry("APList", apriv->proc_entry);
+fail_aplist:
+	remove_proc_entry("SSID", apriv->proc_entry);
+fail_ssid:
+	remove_proc_entry("Config", apriv->proc_entry);
+fail_config:
+	remove_proc_entry("Status", apriv->proc_entry);
+fail_status:
+	remove_proc_entry("Stats", apriv->proc_entry);
+fail_stats:
+	remove_proc_entry("StatsDelta", apriv->proc_entry);
+fail_stats_delta:
+	remove_proc_entry(apriv->proc_name, airo_entry);
+fail:
+	return -ENOMEM;
 }
 
 static int takedown_proc_entry( struct net_device *dev,
@@ -5925,7 +5972,6 @@
 
 	/* Get the current SSID */
 	memcpy(extra, status_rid.SSID, status_rid.SSIDlen);
-	extra[status_rid.SSIDlen] = '\0';
 	/* If none, we may want to get the one that was set */
 
 	/* Push it out ! */
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index bb6bea4..4688e56 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -78,7 +78,7 @@
 
 static  int 	arlan_open(struct net_device *dev);
 static  int 	arlan_tx(struct sk_buff *skb, struct net_device *dev);
-static  irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static  irqreturn_t arlan_interrupt(int irq, void *dev_id);
 static  int 	arlan_close(struct net_device *dev);
 static  struct net_device_stats *
 		arlan_statistics		(struct net_device *dev);
@@ -1651,7 +1651,7 @@
 	return;
 }
 
-static irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t arlan_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct arlan_private *priv = netdev_priv(dev);
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 0fc267d..0c07b8b 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1145,7 +1145,7 @@
 	}
 }
 
-static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t service_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct atmel_private *priv = netdev_priv(dev);
@@ -1678,11 +1678,9 @@
 	/* Get the current SSID */
 	if (priv->new_SSID_size != 0) {
 		memcpy(extra, priv->new_SSID, priv->new_SSID_size);
-		extra[priv->new_SSID_size] = '\0';
 		dwrq->length = priv->new_SSID_size;
 	} else {
 		memcpy(extra, priv->SSID, priv->SSID_size);
-		extra[priv->SSID_size] = '\0';
 		dwrq->length = priv->SSID_size;
 	}
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 76e3aed..978ed09 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -705,11 +705,30 @@
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
 	int dma64 = 0;
-	u32 sbtmstatehi;
+	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
+	int nobits;
 
-	sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-	if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT)
+	if (mask == DMA_64BIT_MASK) {
 		dma64 = 1;
+		nobits = 64;
+	} else if (mask == DMA_32BIT_MASK)
+		nobits = 32;
+	else
+		nobits = 30;
+	err = pci_set_dma_mask(bcm->pci_dev, mask);
+	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
+	if (err) {
+#ifdef CONFIG_BCM43XX_PIO
+		printk(KERN_WARNING PFX "DMA not supported on this device."
+					" Falling back to PIO.\n");
+		bcm->__using_pio = 1;
+		return -ENOSYS;
+#else
+		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+				    "Please recompile the driver with PIO support.\n");
+		return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
+	}
 
 	/* setup TX DMA channels. */
 	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -755,8 +774,7 @@
 		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "%s DMA initialized\n",
-			dma64 ? "64-bit" : "32-bit");
+	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
 	err = 0;
 out:
 	return err;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index e04bcad..ea16078 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -314,6 +314,23 @@
 		   struct ieee80211_txb *txb);
 void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
 
+/* Helper function that returns the dma mask for this device. */
+static inline
+u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
+{
+	int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
+				   BCM43xx_SBTMSTATEHIGH_DMA64BIT;
+	u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
+	u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
+
+	if (dma64)
+		return DMA_64BIT_MASK;
+	bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
+	if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
+		return DMA_32BIT_MASK;
+	return DMA_30BIT_MASK;
+}
+
 #else /* CONFIG_BCM43XX_DMA */
 
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
index c3f90c8..2ddbec6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -242,7 +242,7 @@
 			//TODO
 			break;
 		case BCM43xx_LED_ASSOC:
-			if (bcm->softmac->associated)
+			if (bcm->softmac->associnfo.associated)
 				turn_on = 1;
 			break;
 #ifdef CONFIG_BCM43XX_DEBUG
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index eb65db7..a94c6d8 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -1834,7 +1834,7 @@
 }
 
 /* Interrupt handler top-half */
-static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
 {
 	irqreturn_t ret = IRQ_HANDLED;
 	struct bcm43xx_private *bcm = dev_id;
@@ -2925,10 +2925,13 @@
 		bcm43xx_write16(bcm, 0x043C, 0x000C);
 
 	if (active_wlcore) {
-		if (bcm43xx_using_pio(bcm))
+		if (bcm43xx_using_pio(bcm)) {
 			err = bcm43xx_pio_init(bcm);
-		else
+		} else {
 			err = bcm43xx_dma_init(bcm);
+			if (err == -ENOSYS)
+				err = bcm43xx_pio_init(bcm);
+		}
 		if (err)
 			goto err_chip_cleanup;
 	}
@@ -3164,12 +3167,12 @@
 	u32 savedirqs = 0;
 	int badness;
 
+	mutex_lock(&bcm->mutex);
 	badness = estimate_periodic_work_badness(bcm->periodic_state);
 	if (badness > BADNESS_LIMIT) {
 		/* Periodic work will take a long time, so we want it to
 		 * be preemtible.
 		 */
-		mutex_lock(&bcm->mutex);
 		netif_tx_disable(bcm->net_dev);
 		spin_lock_irqsave(&bcm->irq_lock, flags);
 		bcm43xx_mac_suspend(bcm);
@@ -3182,7 +3185,6 @@
 		/* Periodic work should take short time, so we want low
 		 * locking overhead.
 		 */
-		mutex_lock(&bcm->mutex);
 		spin_lock_irqsave(&bcm->irq_lock, flags);
 	}
 
@@ -3963,7 +3965,7 @@
 
 	local_irq_save(flags);
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
-		bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
+		bcm43xx_interrupt_handler(bcm->irq, bcm);
 	local_irq_restore(flags);
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -3993,8 +3995,6 @@
 				struct net_device *net_dev,
 				struct pci_dev *pci_dev)
 {
-	int err;
-
 	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
 	bcm->ieee = netdev_priv(net_dev);
 	bcm->softmac = ieee80211_priv(net_dev);
@@ -4012,22 +4012,8 @@
 		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
 		     (unsigned long)bcm);
 	tasklet_disable_nosync(&bcm->isr_tasklet);
-	if (modparam_pio) {
+	if (modparam_pio)
 		bcm->__using_pio = 1;
-	} else {
-		err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
-		err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
-		if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-			printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
-			bcm->__using_pio = 1;
-#else
-			printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-					    "Recompile the driver with PIO support, please.\n");
-			return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-		}
-	}
 	bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
 
 	/* default to sw encryption for now */
@@ -4208,7 +4194,11 @@
 	dprintk(KERN_INFO PFX "Resuming...\n");
 
 	pci_set_power_state(pdev, 0);
-	pci_enable_device(pdev);
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
+		return err;
+	}
 	pci_restore_state(pdev);
 
 	bcm43xx_chipset_attach(bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 9b7b15c..d27016f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -847,7 +847,7 @@
 	unsigned long flags;
 
 	wstats = &bcm->stats.wstats;
-	if (!mac->associated) {
+	if (!mac->associnfo.associated) {
 		wstats->miss.beacon = 0;
 //		bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
 		wstats->discard.retries = 0;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index d500012..ed00ebb 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2622,7 +2622,7 @@
 
 
 /* Called only from hardware IRQ */
-static irqreturn_t prism2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t prism2_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct hostap_interface *iface;
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 599e2fe..4e4eaa2 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -3255,7 +3255,7 @@
 	IPW_DEBUG_ISR("exit\n");
 }
 
-static irqreturn_t ipw2100_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t ipw2100_interrupt(int irq, void *data)
 {
 	struct ipw2100_priv *priv = data;
 	u32 inta, inta_mask;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 5685d7b..1f74281 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -10467,7 +10467,7 @@
 	.set_eeprom = ipw_ethtool_set_eeprom,
 };
 
-static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t ipw_isr(int irq, void *data)
 {
 	struct ipw_priv *priv = data;
 	u32 inta, inta_mask;
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 36b5e00..6714e0d 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -207,7 +207,7 @@
 static int netwave_rx( struct net_device *dev);
 
 /* Interrupt routines */
-static irqreturn_t netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t netwave_interrupt(int irq, void *dev_id);
 static void netwave_watchdog(struct net_device *);
 
 /* Statistics */
@@ -1072,7 +1072,7 @@
 } /* netwave_start_xmit */
 
 /*
- * Function netwave_interrupt (irq, dev_id, regs)
+ * Function netwave_interrupt (irq, dev_id)
  *
  *    This function is the interrupt handler for the Netwave card. This
  *    routine will be called whenever: 
@@ -1081,7 +1081,7 @@
  *	     ready to transmit another packet.
  *	  3. A command has completed execution.
  */
-static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs)
+static irqreturn_t netwave_interrupt(int irq, void* dev_id)
 {
     kio_addr_t iobase;
     u_char __iomem *ramBase;
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 9e19a96..336caba 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1952,9 +1952,9 @@
 	       dev->name);
 }
 
-irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t orinoco_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *)dev_id;
+	struct net_device *dev = dev_id;
 	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
 	int count = MAX_IRQLOOPS_PER_IRQ;
@@ -2457,6 +2457,7 @@
 /* Wireless extensions                                              */
 /********************************************************************/
 
+/* Return : < 0 -> error code ; >= 0 -> length */
 static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
 				char buf[IW_ESSID_MAX_SIZE+1])
 {
@@ -2501,9 +2502,9 @@
 	len = le16_to_cpu(essidbuf.len);
 	BUG_ON(len > IW_ESSID_MAX_SIZE);
 
-	memset(buf, 0, IW_ESSID_MAX_SIZE+1);
+	memset(buf, 0, IW_ESSID_MAX_SIZE);
 	memcpy(buf, p, len);
-	buf[len] = '\0';
+	err = len;
 
  fail_unlock:
 	orinoco_unlock(priv, &flags);
@@ -3027,17 +3028,18 @@
 
 	if (netif_running(dev)) {
 		err = orinoco_hw_get_essid(priv, &active, essidbuf);
-		if (err)
+		if (err < 0)
 			return err;
+		erq->length = err;
 	} else {
 		if (orinoco_lock(priv, &flags) != 0)
 			return -EBUSY;
-		memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1);
+		memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
+		erq->length = strlen(priv->desired_essid);
 		orinoco_unlock(priv, &flags);
 	}
 
 	erq->flags = 1;
-	erq->length = strlen(essidbuf);
 
 	return 0;
 }
@@ -3075,10 +3077,10 @@
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
 
-	memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
+	memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE);
 	orinoco_unlock(priv, &flags);
 
-	nrq->length = strlen(nickbuf);
+	nrq->length = strlen(priv->nick);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index fb5700d..4720fb2 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -128,7 +128,7 @@
 extern int __orinoco_up(struct net_device *dev);
 extern int __orinoco_down(struct net_device *dev);
 extern int orinoco_reinit_firmware(struct net_device *dev);
-extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
+extern irqreturn_t orinoco_interrupt(int irq, void * dev_id);
 
 /********************************************************************/
 /* Locking and synchronization functions                            */
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index ab3c5a2..ec1c00f 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -182,7 +182,7 @@
 ******************************************************************************/
 
 irqreturn_t
-islpci_interrupt(int irq, void *config, struct pt_regs *regs)
+islpci_interrupt(int irq, void *config)
 {
 	u32 reg;
 	islpci_private *priv = config;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 5049f37..2f7e525 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -198,7 +198,7 @@
 
 #define ISLPCI_TX_TIMEOUT               (2*HZ)
 
-irqreturn_t islpci_interrupt(int, void *, struct pt_regs *);
+irqreturn_t islpci_interrupt(int, void *);
 
 int prism54_post_setup(islpci_private *, int);
 int islpci_reset(islpci_private *, int);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index e82548e..7fbfc9e 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -130,7 +130,7 @@
 static void verify_dl_startup(u_long);
 
 /* Prototypes for interrpt time functions **********************************/
-static irqreturn_t ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ray_interrupt (int reg, void *dev_id);
 static void clear_interrupt(ray_dev_t *local);
 static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, 
                        unsigned int pkt_addr, int rx_len);
@@ -1198,7 +1198,6 @@
 
 	/* Get the essid that was set */
 	memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE);
-	extra[IW_ESSID_MAX_SIZE] = '\0';
 
 	/* Push it out ! */
 	dwrq->length = strlen(extra);
@@ -1940,7 +1939,7 @@
 /*=============================================================================
  * All routines below here are run at interrupt time.
 =============================================================================*/
-static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ray_interrupt(int irq, void *dev_id)
 {
     struct net_device *dev = (struct net_device *)dev_id;
     struct pcmcia_device *link;
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 5b69bef..24221e4 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -3768,7 +3768,7 @@
  * This function is the interrupt handler for the WaveLAN card. This
  * routine will be called whenever: 
  */
-static irqreturn_t wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wavelan_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev;
 	unsigned long ioaddr;
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 5cb0bc8..72b646c 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -642,8 +642,7 @@
 /* ---------------------- INTERRUPT HANDLING ---------------------- */
 static irqreturn_t
 	wavelan_interrupt(int,		/* interrupt handler */
-			  void *,
-			  struct pt_regs *);
+			  void *);
 static void
 	wavelan_watchdog(struct net_device *);	/* transmission watchdog */
 /* ------------------- CONFIGURATION CALLBACKS ------------------- */
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 0065f05..aafb301 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4117,24 +4117,14 @@
  */
 static irqreturn_t
 wavelan_interrupt(int		irq,
-		  void *	dev_id,
-		  struct pt_regs * regs)
+		  void *	dev_id)
 {
-  struct net_device *	dev;
+  struct net_device *	dev = dev_id;
   net_local *	lp;
   kio_addr_t	base;
   int		status0;
   u_int		tx_status;
 
-  if ((dev = dev_id) == NULL)
-    {
-#ifdef DEBUG_INTERRUPT_ERROR
-      printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n",
-	     irq);
-#endif
-      return IRQ_NONE;
-    }
-
 #ifdef DEBUG_INTERRUPT_TRACE
   printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
 #endif
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index f34a36b..4d1c490 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -738,8 +738,7 @@
 /* ---------------------- INTERRUPT HANDLING ---------------------- */
 static irqreturn_t
 	wavelan_interrupt(int,	/* Interrupt handler */
-			  void *,
-			  struct pt_regs *);
+			  void *);
 static void
 	wavelan_watchdog(struct net_device *);	/* Transmission watchdog */
 /* ------------------- CONFIGURATION CALLBACKS ------------------- */
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index e3ae5f6..5b98a78 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1145,7 +1145,6 @@
  * wl3501_interrupt - Hardware interrupt from card.
  * @irq - Interrupt number
  * @dev_id - net_device
- * @regs - registers
  *
  * We must acknowledge the interrupt as soon as possible, and block the
  * interrupt from the same card immediately to prevent re-entry.
@@ -1154,27 +1153,20 @@
  * On the other hand, to prevent SUTRO from malfunctioning, we must
  * unlock the SUTRO as soon as possible.
  */
-static irqreturn_t wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wl3501_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *)dev_id;
+	struct net_device *dev = dev_id;
 	struct wl3501_card *this;
-	int handled = 1;
 
-	if (!dev)
-		goto unknown;
-	this = dev->priv;
+	this = netdev_priv(dev);
 	spin_lock(&this->lock);
 	wl3501_ack_interrupt(this);
 	wl3501_block_interrupt(this);
 	wl3501_rx_interrupt(dev);
 	wl3501_unblock_interrupt(this);
 	spin_unlock(&this->lock);
-out:
-	return IRQ_RETVAL(handled);
-unknown:
-	handled = 0;
-	printk(KERN_ERR "%s: irq %d for unknown device.\n", __FUNCTION__, irq);
-	goto out;
+
+	return IRQ_HANDLED;
 }
 
 static int wl3501_reset_board(struct wl3501_card *this)
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 80af9a9..36b29ff 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -112,7 +112,7 @@
 	return err;
 }
 
-static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
+static void zd1201_usbfree(struct urb *urb)
 {
 	struct zd1201 *zd = urb->context;
 
@@ -177,7 +177,7 @@
 }
 
 /* Callback after sending out a packet */
-static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
+static void zd1201_usbtx(struct urb *urb)
 {
 	struct zd1201 *zd = urb->context;
 	netif_wake_queue(zd->dev);
@@ -185,7 +185,7 @@
 }
 
 /* Incoming data */
-static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
+static void zd1201_usbrx(struct urb *urb)
 {
 	struct zd1201 *zd = urb->context;
 	int free = 0;
@@ -193,10 +193,8 @@
 	struct sk_buff *skb;
 	unsigned char type;
 
-	if (!zd) {
-		free = 1;
-		goto exit;
-	}
+	if (!zd)
+		return;
 
 	switch(urb->status) {
 		case -EILSEQ:
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 2d12837..a7d29bd 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1099,7 +1099,7 @@
 	int r;
 
 	spin_lock_irq(&mac->lock);
-	is_associated = sm->associated != 0;
+	is_associated = sm->associnfo.associated != 0;
 	spin_unlock_irq(&mac->lock);
 
 	r = zd_chip_control_leds(chip,
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 5c265ad..3faaeb2 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -408,7 +408,7 @@
 }
 
 
-static void int_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+static void int_urb_complete(struct urb *urb)
 {
 	int r;
 	struct usb_int_header *hdr;
@@ -609,7 +609,7 @@
 	}
 }
 
-static void rx_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+static void rx_urb_complete(struct urb *urb)
 {
 	struct zd_usb *usb;
 	struct zd_usb_rx *rx;
@@ -779,7 +779,7 @@
 	spin_unlock_irqrestore(&rx->lock, flags);
 }
 
-static void tx_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+static void tx_urb_complete(struct urb *urb)
 {
 	int r;
 
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index a4c4953..2412ce4 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -350,7 +350,7 @@
 static void yellowfin_tx_timeout(struct net_device *dev);
 static void yellowfin_init_ring(struct net_device *dev);
 static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance);
 static int yellowfin_rx(struct net_device *dev);
 static void yellowfin_error(struct net_device *dev, int intr_status);
 static int yellowfin_close(struct net_device *dev);
@@ -888,7 +888,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct yellowfin_private *yp;
@@ -896,13 +896,6 @@
 	int boguscnt = max_interrupt_work;
 	unsigned int handled = 0;
 
-#ifndef final_version			/* Can never occur. */
-	if (dev == NULL) {
-		printk (KERN_ERR "yellowfin_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-#endif
-
 	yp = netdev_priv(dev);
 	ioaddr = yp->base;
 
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index 656d5a0..b24b072 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -158,7 +158,7 @@
 
 static int	znet_open(struct net_device *dev);
 static int	znet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t znet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t znet_interrupt(int irq, void *dev_id);
 static void	znet_rx(struct net_device *dev);
 static int	znet_close(struct net_device *dev);
 static struct net_device_stats *net_get_stats(struct net_device *dev);
@@ -602,7 +602,7 @@
 }
 
 /* The ZNET interrupt handler. */
-static irqreturn_t znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t znet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct znet_private *znet = dev->priv;
@@ -610,11 +610,6 @@
 	int boguscnt = 20;
 	int handled = 0;
 
-	if (dev == NULL) {
-		printk(KERN_WARNING "znet_interrupt(): IRQ %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
 	spin_lock (&znet->lock);
 
 	ioaddr = dev->base_addr;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 0d96c50..03c763c 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -368,8 +368,7 @@
  * ilr_loop counter is a kluge to prevent a "stuck" IRQ line from
  * wedging the CPU. Could be removed or made optional at some point.
  */
-static irqreturn_t
-dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
+static irqreturn_t dino_isr(int irq, void *intr_dev)
 {
 	struct dino_device *dino_dev = intr_dev;
 	u32 mask;
@@ -390,7 +389,7 @@
 		int irq = dino_dev->global_irq[local_irq];
 		DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
 			__FUNCTION__, irq, intr_dev, mask);
-		__do_IRQ(irq, regs);
+		__do_IRQ(irq);
 		mask &= ~(1 << local_irq);
 	} while (mask);
 
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 884965c..e97cecb 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -199,7 +199,7 @@
 	.end =		no_end_irq,
 };
 
-static irqreturn_t eisa_irq(int wax_irq, void *intr_dev, struct pt_regs *regs)
+static irqreturn_t eisa_irq(int wax_irq, void *intr_dev)
 {
 	int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
 	unsigned long flags;
@@ -234,7 +234,7 @@
 	}
 	spin_unlock_irqrestore(&eisa_irq_lock, flags);
 
-	__do_IRQ(irq, regs);
+	__do_IRQ(irq);
    
 	spin_lock_irqsave(&eisa_irq_lock, flags);
 	/* unmask */
@@ -249,7 +249,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t dummy_irq2_handler(int _, void *dev, struct pt_regs *regs)
+static irqreturn_t dummy_irq2_handler(int _, void *dev)
 {
 	printk(KERN_ALERT "eisa: uhh, irq2?\n");
 	return IRQ_HANDLED;
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index b45aa5c..1b3e3fd 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -73,7 +73,7 @@
 EXPORT_SYMBOL(gsc_claim_irq);
 
 /* Common interrupt demultiplexer used by Asp, Lasi & Wax.  */
-irqreturn_t gsc_asic_intr(int gsc_asic_irq, void *dev, struct pt_regs *regs)
+irqreturn_t gsc_asic_intr(int gsc_asic_irq, void *dev)
 {
 	unsigned long irr;
 	struct gsc_asic *gsc_asic = dev;
@@ -87,7 +87,7 @@
 	do {
 		int local_irq = __ffs(irr);
 		unsigned int irq = gsc_asic->global_irq[local_irq];
-		__do_IRQ(irq, regs);
+		__do_IRQ(irq);
 		irr &= ~(1 << local_irq);
 	} while (irr);
 
diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h
index a3dc456..762a1ba 100644
--- a/drivers/parisc/gsc.h
+++ b/drivers/parisc/gsc.h
@@ -44,4 +44,4 @@
 		void (*choose)(struct parisc_device *child, void *ctrl));
 void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp);
 
-irqreturn_t gsc_asic_intr(int irq, void *dev, struct pt_regs *regs);
+irqreturn_t gsc_asic_intr(int irq, void *dev);
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 2eb3577..97e9dc0 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -188,7 +188,7 @@
  * powerfail interruption handler (irq IRQ_FROM_REGION(CPU_IRQ_REGION)+2) 
  */
 #if 0
-static void powerfail_interrupt(int code, void *x, struct pt_regs *regs)
+static void powerfail_interrupt(int code, void *x)
 {
 	printk(KERN_CRIT "POWERFAIL INTERRUPTION !\n");
 	poweroff();
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 294c111..f1e7ccd 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1320,12 +1320,12 @@
 	** the GART code to handshake on.
 	*/
 	klist_iter_init(&sba->dev.klist_children, &i);
-	while (dev = next_device(&i)) {
+	while ((dev = next_device(&i))) {
 		struct parisc_device *lba = to_parisc_device(dev);
 		if (IS_QUICKSILVER(lba))
 			agp_found = 1;
 	}
-	klist_iter_exit(&sba->dev.klist_children, &i);
+	klist_iter_exit(&i);
 
 	if (agp_found && sba_reserve_agpgart) {
 		printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n",
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 4ee26a6..1fd97f7 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -94,7 +94,7 @@
 #define PFX	SUPERIO ": "
 
 static irqreturn_t
-superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
+superio_interrupt(int parent_irq, void *devp)
 {
 	u8 results;
 	u8 local_irq;
@@ -138,7 +138,7 @@
 	}
 
 	/* Call the appropriate device's interrupt */
-	__do_IRQ(local_irq, regs);
+	__do_IRQ(local_irq);
 
 	/* set EOI - forces a new interrupt if a lower priority device
 	 * still needs service.
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 83ee095..ff9f344 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -216,7 +216,7 @@
 
 struct pardevice *parport_open(int devnum, const char *name,
 				int (*pf) (void *), void (*kf) (void *),
-				void (*irqf) (int, void *, struct pt_regs *),
+				void (*irqf) (int, void *),
 				int flags, void *handle)
 {
 	struct daisydev *p = topology;
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index 7ff09f0..5accaa7 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -571,7 +571,7 @@
 #endif /* IEEE1284 support */
 
 /* Handle an interrupt. */
-void parport_ieee1284_interrupt (int which, void *handle, struct pt_regs *regs)
+void parport_ieee1284_interrupt (int which, void *handle)
 {
 	struct parport *port = handle;
 	parport_ieee1284_wakeup (port);
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index 5126e74..a0afaee 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -138,9 +138,9 @@
 }
 
 /* as this ports irq handling is already done, we use a generic funktion */
-static irqreturn_t amiga_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t amiga_interrupt(int irq, void *dev_id)
 {
-	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	parport_generic_irq(irq, (struct parport *) dev_id);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index 78c3f34..6ea9929 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -104,9 +104,9 @@
 }
 
 static irqreturn_t
-parport_atari_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+parport_atari_interrupt(int irq, void *dev_id)
 {
-	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	parport_generic_irq(irq, (struct parport *) dev_id);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
index 1850632..74f4e97 100644
--- a/drivers/parport/parport_ax88796.c
+++ b/drivers/parport/parport_ax88796.c
@@ -233,9 +233,9 @@
 }
 
 static irqreturn_t
-parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+parport_ax88796_interrupt(int irq, void *dev_id)
 {
-        parport_generic_irq(irq, dev_id, regs);
+        parport_generic_irq(irq, dev_id);
         return IRQ_HANDLED;
 }
 
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 7352104..a7c5ead 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -81,9 +81,9 @@
  * of these are in parport_gsc.h.
  */
 
-static irqreturn_t parport_gsc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t parport_gsc_interrupt(int irq, void *dev_id)
 {
-	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	parport_generic_irq(irq, (struct parport *) dev_id);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
index 46e06e5..e3e1927 100644
--- a/drivers/parport/parport_ip32.c
+++ b/drivers/parport/parport_ip32.c
@@ -548,10 +548,8 @@
  * parport_ip32_dma_interrupt - DMA interrupt handler
  * @irq:	interrupt number
  * @dev_id:	unused
- * @regs:	pointer to &struct pt_regs
  */
-static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id,
-					      struct pt_regs *regs)
+static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id)
 {
 	if (parport_ip32_dma.left)
 		pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx);
@@ -560,8 +558,7 @@
 }
 
 #if DEBUG_PARPORT_IP32
-static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id,
-					       struct pt_regs *regs)
+static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id)
 {
 	pr_trace1(NULL, "(%d)", irq);
 	return IRQ_HANDLED;
@@ -772,13 +769,11 @@
  * parport_ip32_interrupt - interrupt handler
  * @irq:	interrupt number
  * @dev_id:	pointer to &struct parport
- * @regs:	pointer to &struct pt_regs
  *
  * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is
  * %PARPORT_IP32_IRQ_FWD.
  */
-static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id,
-					  struct pt_regs *regs)
+static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id)
 {
 	struct parport * const p = dev_id;
 	struct parport_ip32_private * const priv = p->physport->private_data;
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
index b2b8092..e5b0a54 100644
--- a/drivers/parport/parport_mfc3.c
+++ b/drivers/parport/parport_mfc3.c
@@ -211,7 +211,7 @@
 
 static int use_cnt = 0;
 
-static irqreturn_t mfc3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mfc3_interrupt(int irq, void *dev_id)
 {
 	int i;
 
@@ -219,7 +219,7 @@
 		if (this_port[i] != NULL)
 			if (pia(this_port[i])->crb & 128) { /* Board caused interrupt */
 				dummy = pia(this_port[i])->pprb; /* clear irq bit */
-				parport_generic_irq(irq, this_port[i], regs);
+				parport_generic_irq(irq, this_port[i]);
 			}
 	return IRQ_HANDLED;
 }
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index fe800dc..39c9664 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -270,9 +270,9 @@
  * of these are in parport_pc.h.
  */
 
-static irqreturn_t parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t parport_pc_interrupt(int irq, void *dev_id)
 {
-	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	parport_generic_irq(irq, (struct parport *) dev_id);
 	/* FIXME! Was it really ours? */
 	return IRQ_HANDLED;
 }
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index fac333b..9793533 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -46,9 +46,9 @@
 #define dprintk(x)
 #endif
 
-static irqreturn_t parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t parport_sunbpp_interrupt(int irq, void *dev_id)
 {
-	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	parport_generic_irq(irq, (struct parport *) dev_id);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 94dc506..fd9129e 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -519,7 +519,7 @@
 struct pardevice *
 parport_register_device(struct parport *port, const char *name,
 			int (*pf)(void *), void (*kf)(void *),
-			void (*irq_func)(int, void *, struct pt_regs *), 
+			void (*irq_func)(int, void *), 
 			int flags, void *handle)
 {
 	struct pardevice *tmp;
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 3029412..ecc50db 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -55,7 +55,7 @@
 config HT_IRQ
 	bool "Interrupts on hypertransport devices"
 	default y
-	depends on X86_LOCAL_APIC && X86_IO_APIC
+	depends on PCI && X86_LOCAL_APIC && X86_IO_APIC
 	help
 	   This allows native hypertransport devices to use interrupts.
 
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 51cb9f8..270a33c 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -29,10 +29,10 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
-#include "pci_hotplug.h"
 
 #define MY_NAME	"acpi_pcihp"
 
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 7fff07e..59c5b24 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -38,7 +38,7 @@
 #include <linux/acpi.h>
 #include <linux/kobject.h>	/* for KOBJ_NAME_LEN */
 #include <linux/mutex.h>
-#include "pci_hotplug.h"
+#include <linux/pci_hotplug.h>
 
 #define dbg(format, arg...)					\
 	do {							\
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index e2fef60..c57d9d5 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -37,10 +37,10 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include "pci_hotplug.h"
 #include "acpiphp.h"
 
 #define MY_NAME	"acpiphp"
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 83e8e44..c44311a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -45,11 +45,11 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
 #include "../pci.h"
-#include "pci_hotplug.h"
 #include "acpiphp.h"
 
 static LIST_HEAD(bridge_list);
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index d0a07d9..bd40aee 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -35,7 +35,6 @@
 #include <linux/moduleparam.h>
 
 #include "acpiphp.h"
-#include "pci_hotplug.h"
 
 #define DRIVER_VERSION	"1.0.1"
 #define DRIVER_AUTHOR	"Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index d5df587..6845515 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -29,12 +29,12 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <asm/atomic.h>
 #include <linux/delay.h>
-#include "pci_hotplug.h"
 #include "cpci_hotplug.h"
 
 #define DRIVER_AUTHOR	"Scott Murray <scottm@somanetworks.com>"
@@ -342,7 +342,7 @@
 
 /* This is the interrupt mode interrupt handler */
 static irqreturn_t
-cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
+cpci_hp_intr(int irq, void *data)
 {
 	dbg("entered cpci_hp_intr");
 
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 4afcaff..7b1beaa 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -26,9 +26,9 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/proc_fs.h>
 #include "../pci.h"
-#include "pci_hotplug.h"
 #include "cpci_hotplug.h"
 
 #define MY_NAME	"cpci_hotplug"
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
index e847f0d..f3852a6 100644
--- a/drivers/pci/hotplug/cpcihp_generic.c
+++ b/drivers/pci/hotplug/cpcihp_generic.c
@@ -84,7 +84,7 @@
 
 	if(!bridge) {
 		info("not configured, disabling.");
-		return 1;
+		return -EINVAL;
 	}
 	str = bridge;
 	if(!*str)
@@ -147,7 +147,7 @@
 
 	info(DRIVER_DESC " version: " DRIVER_VERSION);
 	status = validate_parameters();
-	if(status != 0)
+	if (status)
 		return status;
 
 	r = request_region(port, 1, "#ENUM hotswap signal register");
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index c74e9e3..298ad7f 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -28,7 +28,6 @@
 #ifndef _CPQPHP_H
 #define _CPQPHP_H
 
-#include "pci_hotplug.h"
 #include <linux/interrupt.h>
 #include <asm/io.h>		/* for read? and write? functions */
 #include <linux/delay.h>	/* for delays */
@@ -409,7 +408,7 @@
 
 /* controller functions */
 extern void	cpqhp_pushbutton_thread		(unsigned long event_pointer);
-extern irqreturn_t cpqhp_ctrl_intr		(int IRQ, void *data, struct pt_regs *regs);
+extern irqreturn_t cpqhp_ctrl_intr		(int IRQ, void *data);
 extern int	cpqhp_find_available_resources	(struct controller *ctrl, void __iomem *rom_start);
 extern int	cpqhp_event_start_thread	(void);
 extern void	cpqhp_event_stop_thread		(void);
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 1fc2599..5617cfd 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index ae2dd36..79ff6b4 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -36,6 +36,7 @@
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include "cpqphp.h"
 
 static u32 configure_new_device(struct controller* ctrl, struct pci_func *func,
@@ -889,7 +890,7 @@
 }
 
 
-irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs)
+irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
 {
 	struct controller *ctrl = data;
 	u8 schedule_flag = 0;
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
index cf08789..298a6cf 100644
--- a/drivers/pci/hotplug/cpqphp_nvram.c
+++ b/drivers/pci/hotplug/cpqphp_nvram.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include "cpqphp.h"
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 0d96889..fc7c74d 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -33,6 +33,7 @@
 #include <linux/workqueue.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include "../pci.h"
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 5bab666..634f74d 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -32,6 +32,7 @@
 #include <linux/proc_fs.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/debugfs.h>
 #include "cpqphp.h"
 
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 05a4f0f..e27907c 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -35,10 +35,10 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include "pci_hotplug.h"
 #include "../pci.h"
 
 #if !defined(MODULE)
@@ -181,7 +181,9 @@
 
 	if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
 		temp->hdr_type = hdr_type & 0x7f;
-		if (!pci_find_slot(bus->number, temp->devfn)) {
+		if ((dev = pci_get_slot(bus, temp->devfn)) != NULL)
+			pci_dev_put(dev);
+		else {
 			dev = pci_scan_single_device(bus, temp->devfn);
 			if (dev) {
 				dbg("New device on %s function %x:%x\n",
@@ -205,7 +207,9 @@
 				continue;
 			temp->hdr_type = hdr_type & 0x7f;
 
-			if (!pci_find_slot(bus->number, temp->devfn)) {
+			if ((dev = pci_get_slot(bus, temp->devfn)) != NULL)
+				pci_dev_put(dev);
+			else {
 				dev = pci_scan_single_device(bus, temp->devfn);
 				if (dev) {
 					dbg("New device on %s function %x:%x\n",
@@ -305,7 +309,7 @@
 	/* search for subfunctions and disable them first */
 	if (!(dslot->dev->devfn & 7)) {
 		for (func = 1; func < 8; func++) {
-			dev = pci_find_slot(dslot->dev->bus->number,
+			dev = pci_get_slot(dslot->dev->bus,
 					dslot->dev->devfn + func);
 			if (dev) {
 				hslot = get_slot_from_dev(dev);
@@ -315,6 +319,7 @@
 					err("Hotplug slot not found for subfunction of PCI device\n");
 					return -ENODEV;
 				}
+				pci_dev_put(dev);
 			} else
 				dbg("No device in slot found\n");
 		}
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
index dba6d8c..612d963 100644
--- a/drivers/pci/hotplug/ibmphp.h
+++ b/drivers/pci/hotplug/ibmphp.h
@@ -30,7 +30,7 @@
  *
  */
 
-#include "pci_hotplug.h"
+#include <linux/pci_hotplug.h>
 
 extern int ibmphp_debug;
 
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index e2823ea..f5d632e 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -21,9 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>
- *
- * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs
+ * Send feedback to <kristen.c.accardi@intel.com>
  *
  */
 
@@ -32,6 +30,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
@@ -39,11 +39,8 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <asm/uaccess.h>
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include "pci_hotplug.h"
-
 
 #define MY_NAME	"pci_hotplug"
 
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index eaea9d3..4fb12fc 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -31,11 +31,11 @@
 
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/delay.h>
 #include <linux/sched.h>		/* signal_pending() */
 #include <linux/pcieport_if.h>
 #include <linux/mutex.h>
-#include "pci_hotplug.h"
 
 #define MY_NAME	"pciehp"
 
@@ -92,6 +92,7 @@
 struct controller {
 	struct controller *next;
 	struct mutex crit_sect;		/* critical section mutex */
+	struct mutex ctrl_lock;		/* controller lock */
 	struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
 	int num_slots;			/* Number of slots on ctlr */
 	int slot_num_inc;		/* 1 or -1 */
@@ -166,10 +167,10 @@
  * error Messages
  */
 #define msg_initialization_err	"Initialization failure, error=%d\n"
-#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
-#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
-#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
-#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"
+#define msg_button_on		"PCI slot #%s - powering on due to button press.\n"
+#define msg_button_off		"PCI slot #%s - powering off due to button press.\n"
+#define msg_button_cancel	"PCI slot #%s - action canceled due to button press.\n"
+#define msg_button_ignore	"PCI slot #%s - button press ignored.  (action in progress...)\n"
 
 /* controller functions */
 extern int	pciehp_event_start_thread	(void);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index c67b7c3..f93e81e 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -448,7 +448,7 @@
 	}
 
 	/* Wait for exclusive access to hardware */
-	mutex_lock(&ctrl->crit_sect);
+	mutex_lock(&ctrl->ctrl_lock);
 
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
 	
@@ -456,7 +456,7 @@
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
 		if (rc) {
 			/* Done with exclusive hardware access */
-			mutex_unlock(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->ctrl_lock);
 			goto err_out_free_ctrl_slot;
 		} else
 			/* Wait for the command to complete */
@@ -464,7 +464,7 @@
 	}
 
 	/* Done with exclusive hardware access */
-	mutex_unlock(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->ctrl_lock);
 
 	return 0;
 
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 41290a1..372c63e 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -43,6 +43,11 @@
 static unsigned long pushbutton_pending;	/* = 0 */
 static unsigned long surprise_rm_pending;	/* = 0 */
 
+static inline char *slot_name(struct slot *p_slot)
+{
+	return p_slot->hotplug_slot->name;
+}
+
 u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
 {
 	struct controller *ctrl = (struct controller *) inst_id;
@@ -68,7 +73,7 @@
 	/*
 	 *  Button pressed - See if need to TAKE ACTION!!!
 	 */
-	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	info("Button pressed on Slot(%s)\n", slot_name(p_slot));
 	taskInfo->event_type = INT_BUTTON_PRESS;
 
 	if ((p_slot->state == BLINKINGON_STATE)
@@ -78,7 +83,7 @@
 		 * or hot-remove
 		 */
 		taskInfo->event_type = INT_BUTTON_CANCEL;
-		info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Button cancel on Slot(%s)\n", slot_name(p_slot));
 	} else if ((p_slot->state == POWERON_STATE)
 		   || (p_slot->state == POWEROFF_STATE)) {
 		/* Ignore if the slot is on power-on or power-off state; this 
@@ -86,7 +91,7 @@
 		 * hot-remove is undergoing
 		 */
 		taskInfo->event_type = INT_BUTTON_IGNORE;
-		info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Button ignore on Slot(%s)\n", slot_name(p_slot));
 	}
 
 	if (rc)
@@ -122,13 +127,13 @@
 		/*
 		 * Switch opened
 		 */
-		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Latch open on Slot(%s)\n", slot_name(p_slot));
 		taskInfo->event_type = INT_SWITCH_OPEN;
 	} else {
 		/*
 		 *  Switch closed
 		 */
-		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Latch close on Slot(%s)\n", slot_name(p_slot));
 		taskInfo->event_type = INT_SWITCH_CLOSE;
 	}
 
@@ -166,13 +171,13 @@
 		/*
 		 * Card Present
 		 */
-		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Card present on Slot(%s)\n", slot_name(p_slot));
 		taskInfo->event_type = INT_PRESENCE_ON;
 	} else {
 		/*
 		 * Not Present
 		 */
-		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Card not present on Slot(%s)\n", slot_name(p_slot));
 		taskInfo->event_type = INT_PRESENCE_OFF;
 	}
 
@@ -206,13 +211,13 @@
 		/*
 		 * power fault Cleared
 		 */
-		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Power fault cleared on Slot(%s)\n", slot_name(p_slot));
 		taskInfo->event_type = INT_POWER_FAULT_CLEAR;
 	} else {
 		/*
 		 *   power fault
 		 */
-		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Power fault on Slot(%s)\n", slot_name(p_slot));
 		taskInfo->event_type = INT_POWER_FAULT;
 		info("power fault bit %x set\n", hp_slot);
 	}
@@ -229,13 +234,13 @@
 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 {
 	/* Wait for exclusive access to hardware */
-	mutex_lock(&ctrl->crit_sect);
+	mutex_lock(&ctrl->ctrl_lock);
 
 	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		if (pslot->hpc_ops->power_off_slot(pslot)) {   
 			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-			mutex_unlock(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->ctrl_lock);
 			return;
 		}
 		wait_for_ctrl_irq (ctrl);
@@ -249,14 +254,14 @@
 	if (ATTN_LED(ctrl->ctrlcap)) { 
 		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
 			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-			mutex_unlock(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->ctrl_lock);
 			return;
 		}
 		wait_for_ctrl_irq (ctrl);
 	}
 
 	/* Done with exclusive hardware access */
-	mutex_unlock(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->ctrl_lock);
 }
 
 /**
@@ -279,13 +284,13 @@
 			ctrl->slot_device_offset, hp_slot);
 
 	/* Wait for exclusive access to hardware */
-	mutex_lock(&ctrl->crit_sect);
+	mutex_lock(&ctrl->ctrl_lock);
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* Power on slot */
 		rc = p_slot->hpc_ops->power_on_slot(p_slot);
 		if (rc) {
-			mutex_unlock(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->ctrl_lock);
 			return -1;
 		}
 
@@ -301,7 +306,7 @@
 	}
 
 	/* Done with exclusive hardware access */
-	mutex_unlock(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->ctrl_lock);
 
 	/* Wait for ~1 second */
 	wait_for_ctrl_irq (ctrl);
@@ -335,7 +340,7 @@
 		pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
 	if (PWR_LED(ctrl->ctrlcap)) {
 		/* Wait for exclusive access to hardware */
-  		mutex_lock(&ctrl->crit_sect);
+  		mutex_lock(&ctrl->ctrl_lock);
 
   		p_slot->hpc_ops->green_led_on(p_slot);
   
@@ -343,7 +348,7 @@
   		wait_for_ctrl_irq (ctrl);
   	
   		/* Done with exclusive hardware access */
-  		mutex_unlock(&ctrl->crit_sect);
+  		mutex_unlock(&ctrl->ctrl_lock);
   	}
 	return 0;
 
@@ -375,14 +380,14 @@
 	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
 
 	/* Wait for exclusive access to hardware */
-	mutex_lock(&ctrl->crit_sect);
+	mutex_lock(&ctrl->ctrl_lock);
 
 	if (POWER_CTRL(ctrl->ctrlcap)) {
 		/* power off slot */
 		rc = p_slot->hpc_ops->power_off_slot(p_slot);
 		if (rc) {
 			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-			mutex_unlock(&ctrl->crit_sect);
+			mutex_unlock(&ctrl->ctrl_lock);
 			return rc;
 		}
 		/* Wait for the command to complete */
@@ -398,7 +403,7 @@
 	}
 
 	/* Done with exclusive hardware access */
-	mutex_unlock(&ctrl->crit_sect);
+	mutex_unlock(&ctrl->ctrl_lock);
 
 	return 0;
 }
@@ -445,7 +450,7 @@
 
 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 			/* Wait for exclusive access to hardware */
-			mutex_lock(&p_slot->ctrl->crit_sect);
+			mutex_lock(&p_slot->ctrl->ctrl_lock);
 
 			p_slot->hpc_ops->green_led_off(p_slot);
 
@@ -453,7 +458,7 @@
 			wait_for_ctrl_irq (p_slot->ctrl);
 
 			/* Done with exclusive hardware access */
-			mutex_unlock(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->ctrl_lock);
 		}
 		p_slot->state = STATIC_STATE;
 	}
@@ -495,7 +500,7 @@
 
 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
 			/* Wait for exclusive access to hardware */
-			mutex_lock(&p_slot->ctrl->crit_sect);
+			mutex_lock(&p_slot->ctrl->ctrl_lock);
 
 			p_slot->hpc_ops->green_led_off(p_slot);
 
@@ -503,7 +508,7 @@
 			wait_for_ctrl_irq (p_slot->ctrl);
 
 			/* Done with exclusive hardware access */
-			mutex_unlock(&p_slot->ctrl->crit_sect);
+			mutex_unlock(&p_slot->ctrl->ctrl_lock);
 		}
 		p_slot->state = STATIC_STATE;
 	}
@@ -616,7 +621,7 @@
 					switch (p_slot->state) {
 					case BLINKINGOFF_STATE:
 						/* Wait for exclusive access to hardware */
-						mutex_lock(&ctrl->crit_sect);
+						mutex_lock(&ctrl->ctrl_lock);
 						
 						if (PWR_LED(ctrl->ctrlcap)) {
 							p_slot->hpc_ops->green_led_on(p_slot);
@@ -630,11 +635,11 @@
 							wait_for_ctrl_irq (ctrl);
 						}
 						/* Done with exclusive hardware access */
-						mutex_unlock(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->ctrl_lock);
 						break;
 					case BLINKINGON_STATE:
 						/* Wait for exclusive access to hardware */
-						mutex_lock(&ctrl->crit_sect);
+						mutex_lock(&ctrl->ctrl_lock);
 
 						if (PWR_LED(ctrl->ctrlcap)) {
 							p_slot->hpc_ops->green_led_off(p_slot);
@@ -647,14 +652,14 @@
 							wait_for_ctrl_irq (ctrl);
 						}
 						/* Done with exclusive hardware access */
-						mutex_unlock(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->ctrl_lock);
 
 						break;
 					default:
 						warn("Not a valid state\n");
 						return;
 					}
-					info(msg_button_cancel, p_slot->number);
+					info(msg_button_cancel, slot_name(p_slot));
 					p_slot->state = STATIC_STATE;
 				}
 				/* ***********Button Pressed (No action on 1st press...) */
@@ -667,16 +672,16 @@
 							/* slot is on */
 							dbg("slot is on\n");
 							p_slot->state = BLINKINGOFF_STATE;
-							info(msg_button_off, p_slot->number);
+							info(msg_button_off, slot_name(p_slot));
 						} else {
 							/* slot is off */
 							dbg("slot is off\n");
 							p_slot->state = BLINKINGON_STATE;
-							info(msg_button_on, p_slot->number);
+							info(msg_button_on, slot_name(p_slot));
 						}
 
 						/* Wait for exclusive access to hardware */
-						mutex_lock(&ctrl->crit_sect);
+						mutex_lock(&ctrl->ctrl_lock);
 
 						/* blink green LED and turn off amber */
 						if (PWR_LED(ctrl->ctrlcap)) {
@@ -693,7 +698,7 @@
 						}
 
 						/* Done with exclusive hardware access */
-						mutex_unlock(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->ctrl_lock);
 
 						init_timer(&p_slot->task_event);
 						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
@@ -708,7 +713,7 @@
 					if (POWER_CTRL(ctrl->ctrlcap)) {
 						dbg("power fault\n");
 						/* Wait for exclusive access to hardware */
-						mutex_lock(&ctrl->crit_sect);
+						mutex_lock(&ctrl->ctrl_lock);
 
 						if (ATTN_LED(ctrl->ctrlcap)) {
 							p_slot->hpc_ops->set_attention_status(p_slot, 1);
@@ -721,7 +726,7 @@
 						}
 
 						/* Done with exclusive hardware access */
-						mutex_unlock(&ctrl->crit_sect);
+						mutex_unlock(&ctrl->ctrl_lock);
 					}
 				}
 				/***********SURPRISE REMOVAL********************/
@@ -760,14 +765,16 @@
 
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("%s: no adapter on slot(%s)\n", __FUNCTION__,
+		     slot_name(p_slot));
 		mutex_unlock(&p_slot->ctrl->crit_sect);
 		return -ENODEV;
 	}
 	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {	
 		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (rc || getstatus) {
-			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+			info("%s: latch open on slot(%s)\n", __FUNCTION__,
+			     slot_name(p_slot));
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -ENODEV;
 		}
@@ -776,12 +783,12 @@
 	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {	
 		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (rc || getstatus) {
-			info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+			info("%s: already enabled on slot(%s)\n", __FUNCTION__,
+			     slot_name(p_slot));
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -EINVAL;
 		}
 	}
-	mutex_unlock(&p_slot->ctrl->crit_sect);
 
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 
@@ -790,9 +797,9 @@
 		p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	}
 
-	if (p_slot)
-		update_slot_info(p_slot);
+	update_slot_info(p_slot);
 
+	mutex_unlock(&p_slot->ctrl->crit_sect);
 	return rc;
 }
 
@@ -811,7 +818,8 @@
 	if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {	
 		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
-			info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+			info("%s: no adapter on slot(%s)\n", __FUNCTION__,
+			     slot_name(p_slot));
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -ENODEV;
 		}
@@ -820,7 +828,8 @@
 	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {	
 		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (ret || getstatus) {
-			info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+			info("%s: latch open on slot(%s)\n", __FUNCTION__,
+			     slot_name(p_slot));
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -ENODEV;
 		}
@@ -829,16 +838,17 @@
 	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {	
 		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
-			info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+			info("%s: already disabled slot(%s)\n", __FUNCTION__,
+			     slot_name(p_slot));
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -EINVAL;
 		}
 	}
 
-	mutex_unlock(&p_slot->ctrl->crit_sect);
-
 	ret = remove_board(p_slot);
 	update_slot_info(p_slot);
+
+	mutex_unlock(&p_slot->ctrl->crit_sect);
 	return ret;
 }
 
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6ab3b6c..1c551c6 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -222,7 +222,7 @@
 static int ctlr_seq_num = 0;	/* Controller sequence # */
 static spinlock_t list_lock;
 
-static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+static irqreturn_t pcie_isr(int IRQ, void *dev_id);
 
 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
 
@@ -239,7 +239,7 @@
 	}
 
 	/* Poll for interrupt events.  regs == NULL => polling */
-	pcie_isr( 0, (void *)php_ctlr, NULL );
+	pcie_isr( 0, (void *)php_ctlr );
 
 	init_timer(&php_ctlr->int_poll_timer);
 
@@ -863,7 +863,7 @@
 	return retval;
 }
 
-static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pcie_isr(int IRQ, void *dev_id)
 {
 	struct controller *ctrl = NULL;
 	struct php_ctlr_state_s *php_ctlr;
@@ -1402,6 +1402,8 @@
 		pdev->subsystem_vendor, pdev->subsystem_device);
 
 	mutex_init(&ctrl->crit_sect);
+	mutex_init(&ctrl->ctrl_lock);
+
 	/* setup wait queue */
 	init_waitqueue_head(&ctrl->queue);
 
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
index 2b9e10e..50bcd3f 100644
--- a/drivers/pci/hotplug/pcihp_skeleton.c
+++ b/drivers/pci/hotplug/pcihp_skeleton.c
@@ -33,8 +33,8 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/init.h>
-#include "pci_hotplug.h"
 
 #define SLOT_NAME_SIZE	10
 struct slot {
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index db69be8..6c5be3f 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -14,7 +14,7 @@
  */
 #include <linux/kobject.h>
 #include <linux/string.h>
-#include "pci_hotplug.h"
+#include <linux/pci_hotplug.h>
 #include "rpadlpar.h"
 
 #define DLPAR_KOBJ_NAME       "control"
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 310b618..2e7accf 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -28,7 +28,7 @@
 #define _PPC64PHP_H
 
 #include <linux/pci.h>
-#include "pci_hotplug.h"
+#include <linux/pci_hotplug.h>
 
 #define DR_INDICATOR 9002
 #define DR_ENTITY_SENSE 9003
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 7288a3e..141486d 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -36,7 +37,6 @@
 #include "../pci.h"		/* for pci_add_new_bus */
 				/* and pci_do_scan_bus */
 #include "rpaphp.h"
-#include "pci_hotplug.h"
 
 int debug;
 static struct semaphore rpaphp_sem;
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index f31d83c..b62ad31 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/proc_fs.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
@@ -29,7 +30,6 @@
 #include <asm/sn/types.h>
 
 #include "../pci.h"
-#include "pci_hotplug.h"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index c7103ac..ea2087c 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -31,12 +31,11 @@
 
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 #include <linux/delay.h>
 #include <linux/sched.h>	/* signal_pending(), struct timer_list */
 #include <linux/mutex.h>
 
-#include "pci_hotplug.h"
-
 #if !defined(MODULE)
 	#define MY_NAME	"shpchp"
 #else
@@ -103,7 +102,6 @@
 	u32 cap_offset;
 	unsigned long mmio_base;
 	unsigned long mmio_size;
-	volatile int cmd_busy;
 };
 
 
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 0f9798d..83a5226 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -218,7 +218,7 @@
 
 static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
 
-static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t shpc_isr(int irq, void *dev_id);
 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec);
 static int hpc_check_cmd_status(struct controller *ctrl);
 
@@ -276,7 +276,7 @@
 	DBG_ENTER_ROUTINE
 
 	/* Poll for interrupt events.  regs == NULL => polling */
-	shpc_isr(0, php_ctlr->callback_instance_id, NULL);
+	shpc_isr(0, php_ctlr->callback_instance_id);
 
 	init_timer(&php_ctlr->int_poll_timer);
 	if (!shpchp_poll_time)
@@ -302,21 +302,51 @@
 	add_timer(&php_ctlr->int_poll_timer);
 }
 
+static inline int is_ctrl_busy(struct controller *ctrl)
+{
+	u16 cmd_status = shpc_readw(ctrl, CMD_STATUS);
+	return cmd_status & 0x1;
+}
+
+/*
+ * Returns 1 if SHPC finishes executing a command within 1 sec,
+ * otherwise returns 0.
+ */
+static inline int shpc_poll_ctrl_busy(struct controller *ctrl)
+{
+	int i;
+
+	if (!is_ctrl_busy(ctrl))
+		return 1;
+
+	/* Check every 0.1 sec for a total of 1 sec */
+	for (i = 0; i < 10; i++) {
+		msleep(100);
+		if (!is_ctrl_busy(ctrl))
+			return 1;
+	}
+
+	return 0;
+}
+
 static inline int shpc_wait_cmd(struct controller *ctrl)
 {
 	int retval = 0;
-	unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000;
-	unsigned long timeout = msecs_to_jiffies(timeout_msec);
-	int rc = wait_event_interruptible_timeout(ctrl->queue,
-						  !ctrl->cmd_busy, timeout);
-	if (!rc) {
+	unsigned long timeout = msecs_to_jiffies(1000);
+	int rc;
+
+	if (shpchp_poll_mode)
+		rc = shpc_poll_ctrl_busy(ctrl);
+	else
+		rc = wait_event_interruptible_timeout(ctrl->queue,
+						!is_ctrl_busy(ctrl), timeout);
+	if (!rc && is_ctrl_busy(ctrl)) {
 		retval = -EIO;
-		err("Command not completed in %d msec\n", timeout_msec);
+		err("Command not completed in 1000 msec\n");
 	} else if (rc < 0) {
 		retval = -EINTR;
 		info("Command was interrupted by a signal\n");
 	}
-	ctrl->cmd_busy = 0;
 
 	return retval;
 }
@@ -327,26 +357,15 @@
 	u16 cmd_status;
 	int retval = 0;
 	u16 temp_word;
-	int i;
 
 	DBG_ENTER_ROUTINE 
 
 	mutex_lock(&slot->ctrl->cmd_lock);
 
-	for (i = 0; i < 10; i++) {
-		cmd_status = shpc_readw(ctrl, CMD_STATUS);
-		
-		if (!(cmd_status & 0x1))
-			break;
-		/*  Check every 0.1 sec for a total of 1 sec*/
-		msleep(100);
-	}
-
-	cmd_status = shpc_readw(ctrl, CMD_STATUS);
-	
-	if (cmd_status & 0x1) { 
+	if (!shpc_poll_ctrl_busy(ctrl)) {
 		/* After 1 sec and and the controller is still busy */
-		err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__);
+		err("%s : Controller is still busy after 1 sec.\n",
+		    __FUNCTION__);
 		retval = -EBUSY;
 		goto out;
 	}
@@ -358,7 +377,6 @@
 	/* To make sure the Controller Busy bit is 0 before we send out the
 	 * command. 
 	 */
-	slot->ctrl->cmd_busy = 1;
 	shpc_writew(ctrl, CMD, temp_word);
 
 	/*
@@ -870,7 +888,7 @@
 	return retval;
 }
 
-static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t shpc_isr(int irq, void *dev_id)
 {
 	struct controller *ctrl = (struct controller *)dev_id;
 	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
@@ -908,7 +926,6 @@
 		serr_int &= ~SERR_INTR_RSVDZ_MASK;
 		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
 
-		ctrl->cmd_busy = 0;
 		wake_up_interruptible(&ctrl->queue);
 	}
 
@@ -1101,7 +1118,7 @@
 {
 	struct php_ctlr_state_s *php_ctlr, *p;
 	void *instance_id = ctrl;
-	int rc, num_slots = 0;
+	int rc = -1, num_slots = 0;
 	u8 hp_slot;
 	u32 shpc_base_offset;
 	u32 tempdword, slot_reg, slot_config;
@@ -1167,11 +1184,15 @@
 	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
 		pdev->subsystem_device);
 	
-	if (pci_enable_device(pdev))
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		err("%s: pci_enable_device failed\n", __FUNCTION__);
 		goto abort_free_ctlr;
+	}
 
 	if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
 		err("%s: cannot reserve MMIO region\n", __FUNCTION__);
+		rc = -1;
 		goto abort_free_ctlr;
 	}
 
@@ -1180,6 +1201,7 @@
 		err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
 		    ctrl->mmio_size, ctrl->mmio_base);
 		release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
+		rc = -1;
 		goto abort_free_ctlr;
 	}
 	dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
@@ -1282,8 +1304,10 @@
 	 */
 	if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
 		shpchp_wq = create_singlethread_workqueue("shpchpd");
-		if (!shpchp_wq)
-			return -ENOMEM;
+		if (!shpchp_wq) {
+			rc = -ENOMEM;
+			goto abort_free_ctlr;
+		}
 	}
 
 	/*
@@ -1313,8 +1337,10 @@
 
 	/* We end up here for the many possible ways to fail this API.  */
 abort_free_ctlr:
+	if (php_ctlr->creg)
+		iounmap(php_ctlr->creg);
 	kfree(php_ctlr);
 abort:
 	DBG_LEAVE_ROUTINE
-	return -1;
+	return rc;
 }
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index f9fdc54..9fc9a34 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -627,22 +627,24 @@
  * pci_msi_supported - check whether MSI may be enabled on device
  * @dev: pointer to the pci_dev data structure of MSI device function
  *
- * MSI must be globally enabled and supported by the device and its root
- * bus. But, the root bus is not easy to find since some architectures
- * have virtual busses on top of the PCI hierarchy (for instance the
- * hypertransport bus), while the actual bus where MSI must be supported
- * is below. So we test the MSI flag on all parent busses and assume
- * that no quirk will ever set the NO_MSI flag on a non-root bus.
+ * Look at global flags, the device itself, and its parent busses
+ * to return 0 if MSI are supported for the device.
  **/
 static
 int pci_msi_supported(struct pci_dev * dev)
 {
 	struct pci_bus *bus;
 
+	/* MSI must be globally enabled and supported by the device */
 	if (!pci_msi_enable || !dev || dev->no_msi)
 		return -EINVAL;
 
-	/* check MSI flags of all parent busses */
+	/* Any bridge which does NOT route MSI transactions from it's
+	 * secondary bus to it's primary bus must set NO_MSI flag on
+	 * the secondary pci_bus.
+	 * We expect only arch-specific PCI host bus controller driver
+	 * or quirks for specific PCI bridges to be setting NO_MSI.
+	 */
 	for (bus = dev->bus; bus; bus = bus->parent)
 		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
 			return -EINVAL;
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 0d4ac02..04c43ef 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -85,11 +85,10 @@
  * aer_irq - Root Port's ISR
  * @irq: IRQ assigned to Root Port
  * @context: pointer to Root Port data structure
- * @r: pointer struct pt_regs
  *
  * Invoked when Root Port detects AER messages.
  **/
-static irqreturn_t aer_irq(int irq, void *context, struct pt_regs * r)
+static irqreturn_t aer_irq(int irq, void *context)
 {
 	unsigned int status, id;
 	struct pcie_device *pdev = (struct pcie_device *)context;
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 67fcd17..3656e03 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -9,6 +9,8 @@
 #ifndef _PORTDRV_H_
 #define _PORTDRV_H_
 
+#include <linux/compiler.h>
+
 #if !defined(PCI_CAP_ID_PME)
 #define PCI_CAP_ID_PME			1
 #endif
@@ -39,7 +41,7 @@
 extern int pcie_port_device_resume(struct pci_dev *dev);
 #endif
 extern void pcie_port_device_remove(struct pci_dev *dev);
-extern int pcie_port_bus_register(void);
+extern int __must_check pcie_port_bus_register(void);
 extern void pcie_port_bus_unregister(void);
 
 #endif /* _PORTDRV_H_ */
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index bd6615b..b20a9b8 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -6,7 +6,6 @@
  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
  */
 
-#include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -401,7 +400,7 @@
 		pci_disable_msi(dev);
 }
 
-int __must_check pcie_port_bus_register(void)
+int pcie_port_bus_register(void)
 {
 	return bus_register(&pcie_port_bus_type);
 }
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 037690e..b4da795 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -37,7 +37,6 @@
 	return pci_save_state(dev);
 }
 
-#ifdef CONFIG_PM
 static int pcie_portdrv_restore_config(struct pci_dev *dev)
 {
 	int retval;
@@ -50,6 +49,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
 {
 	int ret = pcie_port_device_suspend(dev, state);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a3b0a5e..e159d66 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1067,3 +1067,95 @@
 EXPORT_SYMBOL(pci_scan_single_device);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
+
+static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
+{
+	if      (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
+	else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return  1;
+
+	if      (a->bus->number < b->bus->number) return -1;
+	else if (a->bus->number > b->bus->number) return  1;
+
+	if      (a->devfn < b->devfn) return -1;
+	else if (a->devfn > b->devfn) return  1;
+
+	return 0;
+}
+
+/*
+ * Yes, this forcably breaks the klist abstraction temporarily.  It
+ * just wants to sort the klist, not change reference counts and
+ * take/drop locks rapidly in the process.  It does all this while
+ * holding the lock for the list, so objects can't otherwise be
+ * added/removed while we're swizzling.
+ */
+static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
+{
+	struct list_head *pos;
+	struct klist_node *n;
+	struct device *dev;
+	struct pci_dev *b;
+
+	list_for_each(pos, list) {
+		n = container_of(pos, struct klist_node, n_node);
+		dev = container_of(n, struct device, knode_bus);
+		b = to_pci_dev(dev);
+		if (pci_sort_bf_cmp(a, b) <= 0) {
+			list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
+			return;
+		}
+	}
+	list_move_tail(&a->dev.knode_bus.n_node, list);
+}
+
+static void __init pci_sort_breadthfirst_klist(void)
+{
+	LIST_HEAD(sorted_devices);
+	struct list_head *pos, *tmp;
+	struct klist_node *n;
+	struct device *dev;
+	struct pci_dev *pdev;
+
+	spin_lock(&pci_bus_type.klist_devices.k_lock);
+	list_for_each_safe(pos, tmp, &pci_bus_type.klist_devices.k_list) {
+		n = container_of(pos, struct klist_node, n_node);
+		dev = container_of(n, struct device, knode_bus);
+		pdev = to_pci_dev(dev);
+		pci_insertion_sort_klist(pdev, &sorted_devices);
+	}
+	list_splice(&sorted_devices, &pci_bus_type.klist_devices.k_list);
+	spin_unlock(&pci_bus_type.klist_devices.k_lock);
+}
+
+static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list)
+{
+	struct pci_dev *b;
+
+	list_for_each_entry(b, list, global_list) {
+		if (pci_sort_bf_cmp(a, b) <= 0) {
+			list_move_tail(&a->global_list, &b->global_list);
+			return;
+		}
+	}
+	list_move_tail(&a->global_list, list);
+}
+
+static void __init pci_sort_breadthfirst_devices(void)
+{
+	LIST_HEAD(sorted_devices);
+	struct pci_dev *dev, *tmp;
+
+	down_write(&pci_bus_sem);
+	list_for_each_entry_safe(dev, tmp, &pci_devices, global_list) {
+		pci_insertion_sort_devices(dev, &sorted_devices);
+	}
+	list_splice(&sorted_devices, &pci_devices);
+	up_write(&pci_bus_sem);
+}
+
+void __init pci_sort_breadthfirst(void)
+{
+	pci_sort_breadthfirst_devices();
+	pci_sort_breadthfirst_klist();
+}
+
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 23b599d..e8a7f1b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -453,6 +453,12 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi );
 
 /*
  * VIA ACPI: One IO region pointed to by longword at
@@ -648,11 +654,43 @@
  * Some of the on-chip devices are actually '586 devices' so they are
  * listed here.
  */
+
+static int via_irq_fixup_needed = -1;
+
+/*
+ * As some VIA hardware is available in PCI-card form, we need to restrict
+ * this quirk to VIA PCI hardware built onto VIA-based motherboards only.
+ * We try to locate a VIA southbridge before deciding whether the quirk
+ * should be applied.
+ */
+static const struct pci_device_id via_irq_fixup_tbl[] = {
+	{
+		.vendor 	= PCI_VENDOR_ID_VIA,
+		.device		= PCI_ANY_ID,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= PCI_CLASS_BRIDGE_ISA << 8,
+		.class_mask	= 0xffff00,
+	},
+	{ 0, },
+};
+
 static void quirk_via_irq(struct pci_dev *dev)
 {
 	u8 irq, new_irq;
 
-	new_irq = dev->irq & 0xf;
+	if (via_irq_fixup_needed == -1)
+		via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl);
+
+	if (!via_irq_fixup_needed)
+		return;
+
+	new_irq = dev->irq;
+
+	/* Don't quirk interrupts outside the legacy IRQ range */
+	if (!new_irq || new_irq > 15)
+		return;
+
 	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
 	if (new_irq != irq) {
 		printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
@@ -661,14 +699,7 @@
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
 }
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
 
 /*
  * VIA VT82C598 has its device ID settable and many BIOSes
@@ -1588,6 +1619,51 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
 
+/*
+ * Fixup to mark boot BIOS video selected by BIOS before it changes
+ *
+ * From information provided by "Jon Smirl" <jonsmirl@gmail.com>
+ *
+ * The standard boot ROM sequence for an x86 machine uses the BIOS
+ * to select an initial video card for boot display. This boot video
+ * card will have it's BIOS copied to C0000 in system RAM.
+ * IORESOURCE_ROM_SHADOW is used to associate the boot video
+ * card with this copy. On laptops this copy has to be used since
+ * the main ROM may be compressed or combined with another image.
+ * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
+ * is marked here since the boot video device will be the only enabled
+ * video device at this point.
+ */
+
+static void __devinit fixup_video(struct pci_dev *pdev)
+{
+	struct pci_dev *bridge;
+	struct pci_bus *bus;
+	u16 config;
+
+	if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+		return;
+
+	/* Is VGA routed to us? */
+	bus = pdev->bus;
+	while (bus) {
+		bridge = bus->self;
+		if (bridge) {
+			pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
+						&config);
+			if (!(config & PCI_BRIDGE_CTL_VGA))
+				return;
+		}
+		bus = bus->parent;
+	}
+	pci_read_config_word(pdev, PCI_COMMAND, &config);
+	if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+		pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+		printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video);
+
 
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
 {
@@ -1764,7 +1840,7 @@
 	/* check HT MSI cap on this chipset and the root one.
 	 * a single one having MSI is enough to be sure that MSI are supported.
 	 */
-	pdev = pci_find_slot(dev->bus->number, 0);
+	pdev = pci_get_slot(dev->bus, 0);
 	if (dev->subordinate && !msi_ht_cap_enabled(dev)
 	    && !msi_ht_cap_enabled(pdev)) {
 		printk(KERN_WARNING "PCI: MSI quirk detected. "
@@ -1772,6 +1848,7 @@
 		       pci_name(dev));
 		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
 	}
+	pci_dev_put(pdev);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
 			quirk_nvidia_ck804_msi_ht_cap);
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index f5ee7ce..43e4a49 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -71,7 +71,10 @@
 	void __iomem *image;
 	int last_image;
 
-	/* IORESOURCE_ROM_SHADOW only set on x86 */
+	/*
+	 * IORESOURCE_ROM_SHADOW set if the VGA enable bit of the Bridge Control
+	 * register is set for embedded VGA.
+	 */
 	if (res->flags & IORESOURCE_ROM_SHADOW) {
 		/* primary video rom always starts here */
 		start = (loff_t)0xC0000;
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index d529462..2f13eba 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -140,6 +140,31 @@
 }
 
 /**
+ * pci_get_bus_and_slot - locate PCI device from a given PCI slot
+ * @bus: number of PCI bus on which desired PCI device resides
+ * @devfn: encodes number of PCI slot in which the desired PCI
+ * device resides and the logical device number within that slot
+ * in case of multi-function devices.
+ *
+ * Given a PCI bus and slot/function number, the desired PCI device
+ * is located in system global list of PCI devices.  If the device
+ * is found, a pointer to its data structure is returned.  If no
+ * device is found, %NULL is returned. The returned device has its
+ * reference count bumped by one.
+ */
+
+struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
+{
+	struct pci_dev *dev = NULL;
+
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		if (dev->bus->number == bus && dev->devfn == devfn)
+			return dev;
+	}
+	return NULL;
+}
+
+/**
  * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
@@ -274,6 +299,45 @@
 	return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 }
 
+/**
+ * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id
+ * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+ * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
+ * @from: Previous PCI device found in search, or %NULL for new search.
+ *
+ * Iterates through the list of known PCI devices in the reverse order of
+ * pci_get_device.
+ * If a PCI device is found with a matching @vendor and @device, the reference
+ * count to the  device is incremented and a pointer to its device structure
+ * is returned Otherwise, %NULL is returned.  A new search is initiated by
+ * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
+ * searches continue from next device on the global list.  The reference
+ * count for @from is always decremented if it is not %NULL.
+ */
+struct pci_dev *
+pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from)
+{
+	struct list_head *n;
+	struct pci_dev *dev;
+
+	WARN_ON(in_interrupt());
+	down_read(&pci_bus_sem);
+	n = from ? from->global_list.prev : pci_devices.prev;
+
+	while (n && (n != &pci_devices)) {
+		dev = pci_dev_g(n);
+		if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+		    (device == PCI_ANY_ID || dev->device == device))
+			goto exit;
+		n = n->prev;
+	}
+	dev = NULL;
+exit:
+	dev = pci_dev_get(dev);
+	up_read(&pci_bus_sem);
+	pci_dev_put(from);
+	return dev;
+}
 
 /**
  * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
@@ -382,12 +446,16 @@
 }
 EXPORT_SYMBOL(pci_dev_present);
 
-EXPORT_SYMBOL(pci_find_bus);
-EXPORT_SYMBOL(pci_find_next_bus);
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_device_reverse);
 EXPORT_SYMBOL(pci_find_slot);
+/* For boot time work */
+EXPORT_SYMBOL(pci_find_bus);
+EXPORT_SYMBOL(pci_find_next_bus);
+/* For everyone */
 EXPORT_SYMBOL(pci_get_device);
+EXPORT_SYMBOL(pci_get_device_reverse);
 EXPORT_SYMBOL(pci_get_subsys);
 EXPORT_SYMBOL(pci_get_slot);
+EXPORT_SYMBOL(pci_get_bus_and_slot);
 EXPORT_SYMBOL(pci_get_class);
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 40569f4..7f5df9a 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -64,9 +64,9 @@
 	return 0;
 }
 
-static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
+static irqreturn_t at91_cf_irq(int irq, void *_cf)
 {
-	struct at91_cf_socket	*cf = (struct at91_cf_socket *) _cf;
+	struct at91_cf_socket *cf = _cf;
 
 	if (irq == cf->board->det_pin) {
 		unsigned present = at91_cf_present(cf);
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index ad02629..caca0dc 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -650,7 +650,7 @@
  */
 static int hs_irq_demux(int irq, void *dev)
 {
-    	hs_socket_t *sp = (hs_socket_t *)dev;
+    	hs_socket_t *sp = dev;
 	u_int cscr;
     	
     	DPRINTK("hs_irq_demux(irq=%d)\n", irq);
@@ -671,13 +671,12 @@
  * Interrupt handling routine.
  */
  
-static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hs_interrupt(int irq, void *dev)
 {
-    	hs_socket_t *sp = (hs_socket_t *)dev;
+    	hs_socket_t *sp = dev;
 	u_int events = 0;
 	u_int cscr;
-	
-	
+
 	cscr = hs_in(sp, CSCR);
 	
 	DPRINTK("hs_interrupt, cscr=%04x\n", cscr);
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 2163aa7..82715f4 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -315,7 +315,7 @@
 
 /* Interrupt handler functionality */
 
-static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t i82092aa_interrupt(int irq, void *dev)
 {
 	int i;
 	int loopcount = 0;
diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h
index 9c14599..b0d4533 100644
--- a/drivers/pcmcia/i82092aa.h
+++ b/drivers/pcmcia/i82092aa.h
@@ -23,7 +23,7 @@
 static int  i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id);
 static void i82092aa_pci_remove(struct pci_dev *dev);
 static int card_present(int socketno);
-static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t i82092aa_interrupt(int irq, void *dev);
 
 
 
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 1cc2682..ea74f98 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -80,7 +80,7 @@
 #define debug(lvl, fmt, arg...) do { } while (0)
 #endif
 
-static irqreturn_t i365_count_irq(int, void *, struct pt_regs *);
+static irqreturn_t i365_count_irq(int, void *);
 static inline int _check_irq(int irq, int flags)
 {
     if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
@@ -498,7 +498,7 @@
 static volatile u_int irq_hits;
 static u_short irq_sock;
 
-static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t i365_count_irq(int irq, void *dev)
 {
     i365_get(irq_sock, I365_CSC);
     irq_hits++;
@@ -848,8 +848,7 @@
 
 /*====================================================================*/
 
-static irqreturn_t pcic_interrupt(int irq, void *dev,
-				    struct pt_regs *regs)
+static irqreturn_t pcic_interrupt(int irq, void *dev)
 {
     int i, j, csc;
     u_int events, active;
@@ -898,7 +897,7 @@
 
 static void pcic_interrupt_wrapper(u_long data)
 {
-    pcic_interrupt(0, NULL, NULL);
+    pcic_interrupt(0, NULL);
     poll_timer.expires = jiffies + poll_interval;
     add_timer(&poll_timer);
 }
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 9e768ea..36fdaa5 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -254,7 +254,7 @@
 #endif	/* CONFIG_PLAT_USRV */
 };
 
-static irqreturn_t pcc_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t pcc_interrupt(int, void *);
 
 /*====================================================================*/
 
@@ -372,14 +372,13 @@
 
 /*====================================================================*/
 
-static irqreturn_t pcc_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pcc_interrupt(int irq, void *dev)
 {
 	int i;
 	u_int events = 0;
 	int handled = 0;
 
-	debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p, regs=%p\n",
-		irq, dev, regs);
+	debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p\n", irq, dev);
 	for (i = 0; i < pcc_sockets; i++) {
 		if (socket[i].cs_irq1 != irq && socket[i].cs_irq2 != irq)
 			continue;
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 61d50b5..bbf0258 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -267,7 +267,7 @@
 	{ "xnux2", 0 }, { "xnux2", 0 },
 };
 
-static irqreturn_t pcc_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t pcc_interrupt(int, void *);
 
 /*====================================================================*/
 
@@ -352,7 +352,7 @@
 
 /*====================================================================*/
 
-static irqreturn_t pcc_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pcc_interrupt(int irq, void *dev)
 {
 	int i, j, irc;
 	u_int events, active;
@@ -395,7 +395,7 @@
 
 static void pcc_interrupt_wrapper(u_long data)
 {
-	pcc_interrupt(0, NULL, NULL);
+	pcc_interrupt(0, NULL);
 	init_timer(&poll_timer);
 	poll_timer.expires = jiffies + poll_interval;
 	add_timer(&poll_timer);
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index d0f68ab..e070a28 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -266,7 +266,7 @@
 
 /* ------------------------------------------------------------------------- */
 
-static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t m8xx_interrupt(int irq, void *dev);
 
 #define PCMCIA_BMT_LIMIT (15*4)  /* Bus Monitor Timeout value */
 
@@ -646,7 +646,7 @@
 static u32 pending_events[PCMCIA_SOCKETS_NO];
 static DEFINE_SPINLOCK(pending_event_lock);
 
-static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t m8xx_interrupt(int irq, void *dev)
 {
 	struct socket_info *s;
 	struct event_table *e;
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 01be47e..c8e838c 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -102,7 +102,7 @@
  * claim the card's IRQ.  It may also detect some card insertions, but
  * not removals; it can't always eliminate timer irqs.
  */
-static irqreturn_t omap_cf_irq(int irq, void *_cf, struct pt_regs *r)
+static irqreturn_t omap_cf_irq(int irq, void *_cf)
 {
 	omap_cf_timer((unsigned long)_cf);
 	return IRQ_HANDLED;
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index c832339..74cebd4 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -784,7 +784,7 @@
  */
 
 #ifdef CONFIG_PCMCIA_PROBE
-static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t test_action(int cpl, void *dev_id)
 {
 	return IRQ_NONE;
 }
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 22c5e74..c83a0a6 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -182,7 +182,7 @@
 
 /* Interrupt handler functionality */
 
-static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pd6729_interrupt(int irq, void *dev)
 {
 	struct pd6729_socket *socket = (struct pd6729_socket *)dev;
 	int i;
@@ -249,7 +249,7 @@
 {
 	struct pd6729_socket *socket = (struct pd6729_socket *) data;
 
-	pd6729_interrupt(0, (void *)socket, NULL);
+	pd6729_interrupt(0, (void *)socket);
 	mod_timer(&socket->poll_timer, jiffies + HZ);
 }
 
@@ -575,7 +575,7 @@
 	.set_mem_map		= pd6729_set_mem_map,
 };
 
-static irqreturn_t pd6729_test(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t pd6729_test(int irq, void *dev)
 {
 	dprintk("-> hit on irq %d\n", irq);
 	return IRQ_HANDLED;
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index ecaa132..3627e52 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -256,7 +256,7 @@
  * handling code performs scheduling operations which cannot be
  * executed from within an interrupt context.
  */
-static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev)
 {
 	struct soc_pcmcia_socket *skt = dev;
 
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 65a6067..2d2f415 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -116,7 +116,7 @@
 
 /*====================================================================*/
 
-static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
+static irqreturn_t tcic_interrupt(int irq, void *dev);
 static void tcic_timer(u_long data);
 static struct pccard_operations tcic_operations;
 
@@ -218,7 +218,7 @@
 
 static volatile u_int irq_hits;
 
-static irqreturn_t __init tcic_irq_count(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t __init tcic_irq_count(int irq, void *dev)
 {
     irq_hits++;
     return IRQ_HANDLED;
@@ -505,7 +505,7 @@
     }
     
     /* jump start interrupt handler, if needed */
-    tcic_interrupt(0, NULL, NULL);
+    tcic_interrupt(0, NULL);
 
     platform_device_register(&tcic_device);
 
@@ -547,7 +547,7 @@
 
 /*====================================================================*/
 
-static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t tcic_interrupt(int irq, void *dev)
 {
     int i, quick = 0;
     u_char latch, sstat;
@@ -606,7 +606,7 @@
 {
     debug(2, "tcic_timer()\n");
     tcic_timer_pending = 0;
-    tcic_interrupt(0, NULL, NULL);
+    tcic_interrupt(0, NULL);
 } /* tcic_timer */
 
 /*====================================================================*/
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index e076a13..e90d8e8 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -514,7 +514,7 @@
 	return events;
 }
 
-static irqreturn_t pccard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pccard_interrupt(int irq, void *dev_id)
 {
 	vrc4171_socket_t *socket;
 	unsigned int events;
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index d19a913..812f038 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -440,7 +440,7 @@
 	return events;
 }
 
-static void cardu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void cardu_interrupt(int irq, void *dev_id)
 {
 	vrc4173_socket_t *socket = (vrc4173_socket_t *)dev_id;
 	uint16_t events;
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 1344746..26229d9 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -442,7 +442,7 @@
 
 
 
-static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t yenta_interrupt(int irq, void *dev_id)
 {
 	unsigned int events;
 	struct yenta_socket *socket = (struct yenta_socket *) dev_id;
@@ -478,7 +478,7 @@
 {
 	struct yenta_socket *socket = (struct yenta_socket *) data;
 
-	yenta_interrupt(0, (void *)socket, NULL);
+	yenta_interrupt(0, (void *)socket);
 	socket->poll_timer.expires = jiffies + HZ;
 	add_timer(&socket->poll_timer);
 }
@@ -896,7 +896,7 @@
 #ifdef CONFIG_YENTA_TI
 
 /* interrupt handler, only used during probing */
-static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t yenta_probe_handler(int irq, void *dev_id)
 {
 	struct yenta_socket *socket = (struct yenta_socket *) dev_id;
 	u8 csc;
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index dc79b0a..379048f 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -776,21 +776,32 @@
 	struct resource *p)
 {
 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
-	if (p->flags & IORESOURCE_DMA_COMPATIBLE)
-		resource->data.dma.type = ACPI_COMPATIBILITY;
-	else if (p->flags & IORESOURCE_DMA_TYPEA)
-		resource->data.dma.type = ACPI_TYPE_A;
-	else if (p->flags & IORESOURCE_DMA_TYPEB)
-		resource->data.dma.type = ACPI_TYPE_B;
-	else if (p->flags & IORESOURCE_DMA_TYPEF)
-		resource->data.dma.type = ACPI_TYPE_F;
-	if (p->flags & IORESOURCE_DMA_8BIT)
-		resource->data.dma.transfer = ACPI_TRANSFER_8;
-	else if (p->flags & IORESOURCE_DMA_8AND16BIT)
-		resource->data.dma.transfer = ACPI_TRANSFER_8_16;
-	else if (p->flags & IORESOURCE_DMA_16BIT)
-		resource->data.dma.transfer = ACPI_TRANSFER_16;
-	resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER;
+	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
+		case IORESOURCE_DMA_TYPEA:
+			resource->data.dma.type = ACPI_TYPE_A;
+			break;
+		case IORESOURCE_DMA_TYPEB:
+			resource->data.dma.type = ACPI_TYPE_B;
+			break;
+		case IORESOURCE_DMA_TYPEF:
+			resource->data.dma.type = ACPI_TYPE_F;
+			break;
+		default:
+			resource->data.dma.type = ACPI_COMPATIBILITY;
+	}
+
+	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
+		case IORESOURCE_DMA_8BIT:
+			resource->data.dma.transfer = ACPI_TRANSFER_8;
+			break;
+		case IORESOURCE_DMA_8AND16BIT:
+			resource->data.dma.transfer = ACPI_TRANSFER_8_16;
+			break;
+		default:
+			resource->data.dma.transfer = ACPI_TRANSFER_16;
+	}
+
+	resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
 	resource->data.dma.channel_count = 1;
 	resource->data.dma.channels[0] = p->start;
 }
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 5c8ec21..a685fbe 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -348,7 +348,7 @@
 	return 1;
 }
 
-static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pnp_test_handler(int irq, void *dev_id)
 {
 	return IRQ_HANDLED;
 }
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c
index c0714da..bd61e99 100644
--- a/drivers/rtc/rtc-at91.c
+++ b/drivers/rtc/rtc-at91.c
@@ -238,8 +238,7 @@
 /*
  * IRQ handler for the RTC
  */
-static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = dev_id;
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 9647188..78552e6 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -189,8 +189,7 @@
 	return 0;
 }
 
-static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = dev_id;
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index 0b20dfa..d941707 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -136,7 +136,7 @@
 	dt->tm_min	= BCD2BIN(chip->buf[2]);
 	dt->tm_hour	= BCD2BIN(chip->buf[3]);
 	dt->tm_mday	= BCD2BIN(chip->buf[4]);
-	dt->tm_mon	= BCD2BIN(chip->buf[5] - 1);
+	dt->tm_mon	= BCD2BIN(chip->buf[5]) - 1;
 	dt->tm_wday	= BCD2BIN(chip->buf[6]);
 	dt->tm_year = BCD2BIN(chip->buf[7]);
 
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 739d1a6..f13daa9 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -47,7 +47,7 @@
 	void __iomem *base;
 };
 
-static irqreturn_t pl031_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pl031_interrupt(int irq, void *dev_id)
 {
 	struct rtc_device *rtc = dev_id;
 
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 625dad2..e301dea 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -46,7 +46,7 @@
 
 /* IRQ Handlers */
 
-static irqreturn_t s3c_rtc_alarmirq(int irq, void *id, struct pt_regs *r)
+static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
 {
 	struct rtc_device *rdev = id;
 
@@ -54,7 +54,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t s3c_rtc_tickirq(int irq, void *id, struct pt_regs *r)
+static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
 {
 	struct rtc_device *rdev = id;
 
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 439c41a..bd4d7d1 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -68,8 +68,7 @@
 	return ret;
 }
 
-static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id,
-		struct pt_regs *regs)
+static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = to_platform_device(dev_id);
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
@@ -106,8 +105,7 @@
 
 static int rtc_timer1_count;
 
-static irqreturn_t timer1_interrupt(int irq, void *dev_id,
-		struct pt_regs *regs)
+static irqreturn_t timer1_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = to_platform_device(dev_id);
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index d2ce0c8..143302a 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -73,7 +73,7 @@
 	spinlock_t lock;
 };
 
-static irqreturn_t sh_rtc_interrupt(int irq, void *id, struct pt_regs *regs)
+static irqreturn_t sh_rtc_interrupt(int irq, void *id)
 {
 	struct platform_device *pdev = id;
 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
@@ -97,7 +97,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sh_rtc_periodic(int irq, void *id, struct pt_regs *regs)
+static irqreturn_t sh_rtc_periodic(int irq, void *id)
 {
 	struct sh_rtc *rtc = dev_get_drvdata(id);
 
@@ -160,7 +160,7 @@
 	tmp |= RCR1_CIE;
 	writeb(tmp, rtc->regbase + RCR1);
 
-	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, SA_INTERRUPT,
+	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
 			  "sh-rtc period", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
@@ -168,7 +168,7 @@
 		return ret;
 	}
 
-	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, SA_INTERRUPT,
+	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
 			  "sh-rtc carry", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
@@ -177,7 +177,7 @@
 		goto err_bad_carry;
 	}
 
-	ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, SA_INTERRUPT,
+	ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED,
 			  "sh-rtc alarm", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index 09b714f..3b58d3d 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -195,9 +195,9 @@
 	 * are all disabled */
 	v3020_set_reg(chip, V3020_STATUS_0, 0x0);
 
-	dev_info(&pdev->dev, "Chip available at physical address 0x%p,"
+	dev_info(&pdev->dev, "Chip available at physical address 0x%llx,"
 		"data connected to D%d\n",
-		(void*)pdev->resource[0].start,
+		(unsigned long long)pdev->resource[0].start,
 		chip->leftshift);
 
 	platform_set_drvdata(pdev, chip);
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 58e5ed0..e40322b 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -268,7 +268,7 @@
 	return 0;
 }
 
-static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = (struct platform_device *)dev_id;
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
@@ -280,7 +280,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = (struct platform_device *)dev_id;
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d0647d1..79ffef6 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -203,6 +203,7 @@
 	rc = dasd_flush_ccw_queue(device, 1);
 	if (rc)
 		return rc;
+	dasd_clear_timer(device);
 
 	DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
 	if (device->debug_area != NULL) {
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 222a8a7..53db58a 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -218,7 +218,7 @@
 
 /* Handle external interruption. */
 static void
-dasd_ext_handler(struct pt_regs *regs, __u16 code)
+dasd_ext_handler(__u16 code)
 {
 	struct dasd_ccw_req *cqr, *next;
 	struct dasd_device *device;
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index d83eb63..49e9628 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -20,7 +20,7 @@
 static void
 ctrlchar_handle_sysrq(void *tty)
 {
-	handle_sysrq(ctrlchar_sysrq_key, NULL, (struct tty_struct *) tty);
+	handle_sysrq(ctrlchar_sysrq_key, (struct tty_struct *) tty);
 }
 
 static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq, NULL);
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 3be0656..e3491a5 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -304,7 +304,7 @@
 		if (kbd->sysrq) {
 			if (kbd->sysrq == K(KT_LATIN, '-')) {
 				kbd->sysrq = 0;
-				handle_sysrq(value, NULL, kbd->tty);
+				handle_sysrq(value, kbd->tty);
 				return;
 			}
 			if (value == '-') {
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 1e3939a..b9b0fc3 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -26,6 +26,7 @@
 #define MONWRITE_MAX_DATALEN	4024
 
 static int mon_max_bufs = 255;
+static int mon_buf_count;
 
 struct mon_buf {
 	struct list_head list;
@@ -40,7 +41,6 @@
 	size_t hdr_to_read;
 	size_t data_to_read;
 	struct mon_buf *current_buf;
-	int mon_buf_count;
 };
 
 /*
@@ -73,12 +73,15 @@
 	struct mon_buf *entry, *next;
 
 	list_for_each_entry_safe(entry, next, &monpriv->list, list)
-		if (entry->hdr.applid == monhdr->applid &&
+		if ((entry->hdr.mon_function == monhdr->mon_function ||
+		     monhdr->mon_function == MONWRITE_STOP_INTERVAL) &&
+		    entry->hdr.applid == monhdr->applid &&
 		    entry->hdr.record_num == monhdr->record_num &&
 		    entry->hdr.version == monhdr->version &&
 		    entry->hdr.release == monhdr->release &&
 		    entry->hdr.mod_level == monhdr->mod_level)
 			return entry;
+
 	return NULL;
 }
 
@@ -92,25 +95,27 @@
 	    monhdr->mon_function > MONWRITE_START_CONFIG ||
 	    monhdr->hdrlen != sizeof(struct monwrite_hdr))
 		return -EINVAL;
-	monbuf = monwrite_find_hdr(monpriv, monhdr);
+	monbuf = NULL;
+	if (monhdr->mon_function != MONWRITE_GEN_EVENT)
+		monbuf = monwrite_find_hdr(monpriv, monhdr);
 	if (monbuf) {
 		if (monhdr->mon_function == MONWRITE_STOP_INTERVAL) {
 			monhdr->datalen = monbuf->hdr.datalen;
 			rc = monwrite_diag(monhdr, monbuf->data,
 					   APPLDATA_STOP_REC);
 			list_del(&monbuf->list);
-			monpriv->mon_buf_count--;
+			mon_buf_count--;
 			kfree(monbuf->data);
 			kfree(monbuf);
 			monbuf = NULL;
 		}
-	} else {
-		if (monpriv->mon_buf_count >= mon_max_bufs)
+	} else if (monhdr->mon_function != MONWRITE_STOP_INTERVAL) {
+		if (mon_buf_count >= mon_max_bufs)
 			return -ENOSPC;
 		monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL);
 		if (!monbuf)
 			return -ENOMEM;
-		monbuf->data = kzalloc(monbuf->hdr.datalen,
+		monbuf->data = kzalloc(monhdr->datalen,
 				       GFP_KERNEL | GFP_DMA);
 		if (!monbuf->data) {
 			kfree(monbuf);
@@ -118,7 +123,8 @@
 		}
 		monbuf->hdr = *monhdr;
 		list_add_tail(&monbuf->list, &monpriv->list);
-		monpriv->mon_buf_count++;
+		if (monhdr->mon_function != MONWRITE_GEN_EVENT)
+			mon_buf_count++;
 	}
 	monpriv->current_buf = monbuf;
 	return 0;
@@ -186,7 +192,7 @@
 		if (entry->hdr.mon_function != MONWRITE_GEN_EVENT)
 			monwrite_diag(&entry->hdr, entry->data,
 				      APPLDATA_STOP_REC);
-		monpriv->mon_buf_count--;
+		mon_buf_count--;
 		list_del(&entry->list);
 		kfree(entry->data);
 		kfree(entry);
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 31e3357..8a056df 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -324,7 +324,7 @@
  * Prepare read event data request if necessary. Start processing of next
  * request on queue. */
 static void
-sclp_interrupt_handler(struct pt_regs *regs, __u16 code)
+sclp_interrupt_handler(__u16 code)
 {
 	struct sclp_req *req;
 	u32 finished_sccb;
@@ -743,7 +743,7 @@
 /* Handler for external interruption used during initialization. Modify
  * request state to done. */
 static void
-sclp_check_handler(struct pt_regs *regs, __u16 code)
+sclp_check_handler(__u16 code)
 {
 	u32 finished_sccb;
 
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 3bb4e47..2d78f0f 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -200,11 +200,13 @@
 	spin_unlock_irq(&sch->lock);
 	free_page((unsigned long)page);
 	if (!ret) {
-		int j, chpid;
+		int j, chpid, mask;
 		/* Allocate channel path structures, if needed. */
 		for (j = 0; j < 8; j++) {
+			mask = 0x80 >> j;
 			chpid = sch->ssd_info.chpid[j];
-			if (chpid && (get_chp_status(chpid) < 0))
+			if ((sch->schib.pmcw.pim & mask) &&
+			    (get_chp_status(chpid) < 0))
 			    new_channel_path(chpid);
 		}
 	}
@@ -222,13 +224,15 @@
 
 	sch = to_subchannel(dev);
 	chpid = data;
-	for (j = 0; j < 8; j++)
-		if (sch->schib.pmcw.chpid[j] == chpid->id)
+	for (j = 0; j < 8; j++) {
+		mask = 0x80 >> j;
+		if ((sch->schib.pmcw.pim & mask) &&
+		    (sch->schib.pmcw.chpid[j] == chpid->id))
 			break;
+	}
 	if (j >= 8)
 		return 0;
 
-	mask = 0x80 >> j;
 	spin_lock_irq(&sch->lock);
 
 	stsch(sch->schid, &schib);
@@ -366,7 +370,7 @@
 	struct res_acc_data *res_data;
 	struct subchannel *sch;
 
-	res_data = (struct res_acc_data *)data;
+	res_data = data;
 	sch = get_subchannel_by_schid(schid);
 	if (!sch)
 		/* Check if a subchannel is newly available. */
@@ -440,7 +444,7 @@
 		u32 isinfo[28];
 	} *lir;
 
-	lir = (struct lir*) data;
+	lir = data;
 	if (!(lir->iq&0x80))
 		/* NULL link incident record */
 		return -EINVAL;
@@ -620,18 +624,20 @@
 static int
 __chp_add(struct subchannel_id schid, void *data)
 {
-	int i;
+	int i, mask;
 	struct channel_path *chp;
 	struct subchannel *sch;
 
-	chp = (struct channel_path *)data;
+	chp = data;
 	sch = get_subchannel_by_schid(schid);
 	if (!sch)
 		/* Check if the subchannel is now available. */
 		return __chp_add_new_sch(schid);
 	spin_lock_irq(&sch->lock);
-	for (i=0; i<8; i++)
-		if (sch->schib.pmcw.chpid[i] == chp->id) {
+	for (i=0; i<8; i++) {
+		mask = 0x80 >> i;
+		if ((sch->schib.pmcw.pim & mask) &&
+		    (sch->schib.pmcw.chpid[i] == chp->id)) {
 			if (stsch(sch->schid, &sch->schib) != 0) {
 				/* Endgame. */
 				spin_unlock_irq(&sch->lock);
@@ -639,6 +645,7 @@
 			}
 			break;
 		}
+	}
 	if (i==8) {
 		spin_unlock_irq(&sch->lock);
 		return 0;
@@ -646,7 +653,7 @@
 	sch->lpm = ((sch->schib.pmcw.pim &
 		     sch->schib.pmcw.pam &
 		     sch->schib.pmcw.pom)
-		    | 0x80 >> i) & sch->opm;
+		    | mask) & sch->opm;
 
 	if (sch->driver && sch->driver->verify)
 		sch->driver->verify(&sch->dev);
@@ -700,8 +707,7 @@
 	return chp_add(chpid);
 }
 
-static inline int
-__check_for_io_and_kill(struct subchannel *sch, int index)
+static inline int check_for_io_on_path(struct subchannel *sch, int index)
 {
 	int cc;
 
@@ -711,10 +717,8 @@
 	cc = stsch(sch->schid, &sch->schib);
 	if (cc)
 		return 0;
-	if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
-		device_set_waiting(sch);
+	if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
 		return 1;
-	}
 	return 0;
 }
 
@@ -743,12 +747,10 @@
 		} else {
 			sch->opm &= ~(0x80 >> chp);
 			sch->lpm &= ~(0x80 >> chp);
-			/*
-			 * Give running I/O a grace period in which it
-			 * can successfully terminate, even using the
-			 * just varied off path. Then kill it.
-			 */
-			if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
+			if (check_for_io_on_path(sch, chp))
+				/* Path verification is done after killing. */
+				device_kill_io(sch);
+			else if (!sch->lpm) {
 				if (css_enqueue_subchannel_slow(sch->schid)) {
 					css_clear_subchannel_slow_list();
 					need_rescan = 1;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 2e2882d..8936e46 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -19,6 +19,7 @@
 #include <asm/cio.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
+#include <asm/irq_regs.h>
 #include <asm/setup.h>
 #include "airq.h"
 #include "cio.h"
@@ -606,15 +607,17 @@
 	struct tpi_info *tpi_info;
 	struct subchannel *sch;
 	struct irb *irb;
+	struct pt_regs *old_regs;
 
-	irq_enter ();
+	old_regs = set_irq_regs(regs);
+	irq_enter();
 	asm volatile ("mc 0,0");
 	if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
 		/**
 		 * Make sure that the i/o interrupt did not "overtake"
 		 * the last HZ timer interrupt.
 		 */
-		account_ticks(regs);
+		account_ticks();
 	/*
 	 * Get interrupt information from lowcore
 	 */
@@ -652,7 +655,8 @@
 		 * out of the sie which costs more cycles than it saves.
 		 */
 	} while (!MACHINE_IS_VM && tpi (NULL) != 0);
-	irq_exit ();
+	irq_exit();
+	set_irq_regs(old_regs);
 }
 
 #ifdef CONFIG_CCW_CONSOLE
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 7086a74..a2dee5b 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -177,7 +177,7 @@
 	struct device *dev;
 
 	dev = bus_find_device(&css_bus_type, NULL,
-			      (void *)&schid, check_subchannel);
+			      &schid, check_subchannel);
 
 	return dev ? to_subchannel(dev) : NULL;
 }
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 8aabb4a..4c2ff83 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -76,9 +76,8 @@
 	int state;		/* device state */
 	atomic_t onoff;
 	unsigned long registered;
-	__u16 devno;		/* device number */
-	__u16 sch_no;		/* subchannel number */
-	__u8 ssid;              /* subchannel set id */
+	struct ccw_dev_id dev_id;	/* device id */
+	struct subchannel_id schid;	/* subchannel number */
 	__u8 imask;		/* lpm mask for SNID/SID/SPGID */
 	int iretry;		/* retry counter SNID/SID/SPGID */
 	struct {
@@ -171,7 +170,7 @@
 
 /* Helper functions for vary on/off. */
 int device_is_online(struct subchannel *);
-void device_set_waiting(struct subchannel *);
+void device_kill_io(struct subchannel *);
 
 /* Machine check helper function. */
 void device_kill_pending_timer(struct subchannel *);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 6889456..94bdd4d 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -552,21 +552,19 @@
 }
 
 struct match_data {
-	unsigned int devno;
-	unsigned int ssid;
+	struct ccw_dev_id dev_id;
 	struct ccw_device * sibling;
 };
 
 static int
 match_devno(struct device * dev, void * data)
 {
-	struct match_data * d = (struct match_data *)data;
+	struct match_data * d = data;
 	struct ccw_device * cdev;
 
 	cdev = to_ccwdev(dev);
 	if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
-	    (cdev->private->devno == d->devno) &&
-	    (cdev->private->ssid == d->ssid) &&
+	    ccw_dev_id_is_equal(&cdev->private->dev_id, &d->dev_id) &&
 	    (cdev != d->sibling)) {
 		cdev->private->state = DEV_STATE_NOT_OPER;
 		return 1;
@@ -574,15 +572,13 @@
 	return 0;
 }
 
-static struct ccw_device *
-get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
-			 struct ccw_device *sibling)
+static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
+						     struct ccw_device *sibling)
 {
 	struct device *dev;
 	struct match_data data;
 
-	data.devno = devno;
-	data.ssid = ssid;
+	data.dev_id = *dev_id;
 	data.sibling = sibling;
 	dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
 
@@ -595,7 +591,7 @@
 
 	struct ccw_device *cdev;
 
-	cdev = (struct ccw_device *)data;
+	cdev = data;
 	if (device_add(&cdev->dev)) {
 		put_device(&cdev->dev);
 		return;
@@ -616,9 +612,9 @@
 	struct subchannel *sch;
 	int need_rename;
 
-	cdev = (struct ccw_device *)data;
+	cdev = data;
 	sch = to_subchannel(cdev->dev.parent);
-	if (cdev->private->devno != sch->schib.pmcw.dev) {
+	if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
 		/*
 		 * The device number has changed. This is usually only when
 		 * a device has been detached under VM and then re-appeared
@@ -633,10 +629,12 @@
 		 *        get possibly sick...
 		 */
 		struct ccw_device *other_cdev;
+		struct ccw_dev_id dev_id;
 
 		need_rename = 1;
-		other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev,
-						      sch->schid.ssid, cdev);
+		dev_id.devno = sch->schib.pmcw.dev;
+		dev_id.ssid = sch->schid.ssid;
+		other_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
 		if (other_cdev) {
 			struct subchannel *other_sch;
 
@@ -652,7 +650,7 @@
 		}
 		/* Update ssd info here. */
 		css_get_ssd_info(sch);
-		cdev->private->devno = sch->schib.pmcw.dev;
+		cdev->private->dev_id.devno = sch->schib.pmcw.dev;
 	} else
 		need_rename = 0;
 	device_remove_files(&cdev->dev);
@@ -662,7 +660,7 @@
 		snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
 			  sch->schid.ssid, sch->schib.pmcw.dev);
 	PREPARE_WORK(&cdev->private->kick_work,
-		     ccw_device_add_changed, (void *)cdev);
+		     ccw_device_add_changed, cdev);
 	queue_work(ccw_device_work, &cdev->private->kick_work);
 }
 
@@ -687,7 +685,7 @@
 	int ret;
 	unsigned long flags;
 
-	cdev = (struct ccw_device *) data;
+	cdev = data;
 	sch = to_subchannel(cdev->dev.parent);
 
 	if (klist_node_attached(&cdev->dev.knode_parent)) {
@@ -759,7 +757,7 @@
 			break;
 		sch = to_subchannel(cdev->dev.parent);
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_call_sch_unregister, (void *) cdev);
+			     ccw_device_call_sch_unregister, cdev);
 		queue_work(slow_path_wq, &cdev->private->kick_work);
 		if (atomic_dec_and_test(&ccw_device_init_count))
 			wake_up(&ccw_device_init_wq);
@@ -774,7 +772,7 @@
 		if (!get_device(&cdev->dev))
 			break;
 		PREPARE_WORK(&cdev->private->kick_work,
-			     io_subchannel_register, (void *) cdev);
+			     io_subchannel_register, cdev);
 		queue_work(slow_path_wq, &cdev->private->kick_work);
 		break;
 	}
@@ -792,9 +790,9 @@
 
 	/* Init private data. */
 	priv = cdev->private;
-	priv->devno = sch->schib.pmcw.dev;
-	priv->ssid = sch->schid.ssid;
-	priv->sch_no = sch->schid.sch_no;
+	priv->dev_id.devno = sch->schib.pmcw.dev;
+	priv->dev_id.ssid = sch->schid.ssid;
+	priv->schid = sch->schid;
 	priv->state = DEV_STATE_NOT_OPER;
 	INIT_LIST_HEAD(&priv->cmb_list);
 	init_waitqueue_head(&priv->wait_q);
@@ -912,7 +910,7 @@
 	 */
 	if (get_device(&cdev->dev)) {
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_unregister, (void *) cdev);
+			     ccw_device_unregister, cdev);
 		queue_work(ccw_device_work, &cdev->private->kick_work);
 	}
 	return 0;
@@ -1055,7 +1053,7 @@
 {
 	char *bus_id;
 
-	bus_id = (char *)id;
+	bus_id = id;
 
 	return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
 }
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 00be9a5..c6140cc 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -21,7 +21,6 @@
 	/* states to wait for i/o completion before doing something */
 	DEV_STATE_CLEAR_VERIFY,
 	DEV_STATE_TIMEOUT_KILL,
-	DEV_STATE_WAIT4IO,
 	DEV_STATE_QUIESCE,
 	/* special states for devices gone not operational */
 	DEV_STATE_DISCONNECTED,
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index b676202..de3d085 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -59,18 +59,6 @@
 	cdev->private->state = DEV_STATE_DISCONNECTED;
 }
 
-void
-device_set_waiting(struct subchannel *sch)
-{
-	struct ccw_device *cdev;
-
-	if (!sch->dev.driver_data)
-		return;
-	cdev = sch->dev.driver_data;
-	ccw_device_set_timeout(cdev, 10*HZ);
-	cdev->private->state = DEV_STATE_WAIT4IO;
-}
-
 /*
  * Timeout function. It just triggers a DEV_EVENT_TIMEOUT.
  */
@@ -183,9 +171,9 @@
 	    cdev->id.cu_model != cdev->private->senseid.cu_model ||
 	    cdev->id.dev_type != cdev->private->senseid.dev_type ||
 	    cdev->id.dev_model != cdev->private->senseid.dev_model ||
-	    cdev->private->devno != sch->schib.pmcw.dev) {
+	    cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_do_unreg_rereg, (void *)cdev);
+			     ccw_device_do_unreg_rereg, cdev);
 		queue_work(ccw_device_work, &cdev->private->kick_work);
 		return 0;
 	}
@@ -255,7 +243,7 @@
 	case DEV_STATE_NOT_OPER:
 		CIO_DEBUG(KERN_WARNING, 2,
 			  "SenseID : unknown device %04x on subchannel "
-			  "0.%x.%04x\n", cdev->private->devno,
+			  "0.%x.%04x\n", cdev->private->dev_id.devno,
 			  sch->schid.ssid, sch->schid.sch_no);
 		break;
 	case DEV_STATE_OFFLINE:
@@ -282,14 +270,15 @@
 		CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
 			  "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
 			  "%04X/%02X\n",
-			  cdev->private->ssid, cdev->private->devno,
+			  cdev->private->dev_id.ssid,
+			  cdev->private->dev_id.devno,
 			  cdev->id.cu_type, cdev->id.cu_model,
 			  cdev->id.dev_type, cdev->id.dev_model);
 		break;
 	case DEV_STATE_BOXED:
 		CIO_DEBUG(KERN_WARNING, 2,
 			  "SenseID : boxed device %04x on subchannel "
-			  "0.%x.%04x\n", cdev->private->devno,
+			  "0.%x.%04x\n", cdev->private->dev_id.devno,
 			  sch->schid.ssid, sch->schid.sch_no);
 		break;
 	}
@@ -325,13 +314,13 @@
 	struct subchannel *sch;
 	int ret;
 
-	cdev = (struct ccw_device *)data;
+	cdev = data;
 	sch = to_subchannel(cdev->dev.parent);
 	ret = (sch->driver && sch->driver->notify) ?
 		sch->driver->notify(&sch->dev, CIO_OPER) : 0;
 	if (!ret)
 		/* Driver doesn't want device back. */
-		ccw_device_do_unreg_rereg((void *)cdev);
+		ccw_device_do_unreg_rereg(cdev);
 	else {
 		/* Reenable channel measurements, if needed. */
 		cmf_reenable(cdev);
@@ -363,12 +352,12 @@
 	if (state == DEV_STATE_BOXED)
 		CIO_DEBUG(KERN_WARNING, 2,
 			  "Boxed device %04x on subchannel %04x\n",
-			  cdev->private->devno, sch->schid.sch_no);
+			  cdev->private->dev_id.devno, sch->schid.sch_no);
 
 	if (cdev->private->flags.donotify) {
 		cdev->private->flags.donotify = 0;
 		PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify,
-			     (void *)cdev);
+			     cdev);
 		queue_work(ccw_device_notify_work, &cdev->private->kick_work);
 	}
 	wake_up(&cdev->private->wait_q);
@@ -412,7 +401,8 @@
 		/* PGID mismatch, can't pathgroup. */
 		CIO_MSG_EVENT(0, "SNID - pgid mismatch for device "
 			      "0.%x.%04x, can't pathgroup\n",
-			      cdev->private->ssid, cdev->private->devno);
+			      cdev->private->dev_id.ssid,
+			      cdev->private->dev_id.devno);
 		cdev->private->options.pgroup = 0;
 		return;
 	}
@@ -523,7 +513,7 @@
 	struct subchannel *sch;
 	int ret;
 
-	cdev = (struct ccw_device *)data;
+	cdev = data;
 	sch = to_subchannel(cdev->dev.parent);
 	/* Extra sanity. */
 	if (sch->lpm)
@@ -537,7 +527,7 @@
 			if (get_device(&cdev->dev)) {
 				PREPARE_WORK(&cdev->private->kick_work,
 					     ccw_device_call_sch_unregister,
-					     (void *)cdev);
+					     cdev);
 				queue_work(ccw_device_work,
 					   &cdev->private->kick_work);
 			} else
@@ -588,11 +578,15 @@
 		}
 		break;
 	case -ETIME:
+		/* Reset oper notify indication after verify error. */
+		cdev->private->flags.donotify = 0;
 		ccw_device_done(cdev, DEV_STATE_BOXED);
 		break;
 	default:
+		/* Reset oper notify indication after verify error. */
+		cdev->private->flags.donotify = 0;
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_nopath_notify, (void *)cdev);
+			     ccw_device_nopath_notify, cdev);
 		queue_work(ccw_device_notify_work, &cdev->private->kick_work);
 		ccw_device_done(cdev, DEV_STATE_NOT_OPER);
 		break;
@@ -723,7 +717,7 @@
 	sch = to_subchannel(cdev->dev.parent);
 	if (get_device(&cdev->dev)) {
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_call_sch_unregister, (void *)cdev);
+			     ccw_device_call_sch_unregister, cdev);
 		queue_work(ccw_device_work, &cdev->private->kick_work);
 	}
 	wake_up(&cdev->private->wait_q);
@@ -754,7 +748,7 @@
 	}
 	if (get_device(&cdev->dev)) {
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_call_sch_unregister, (void *)cdev);
+			     ccw_device_call_sch_unregister, cdev);
 		queue_work(ccw_device_work, &cdev->private->kick_work);
 	}
 	wake_up(&cdev->private->wait_q);
@@ -859,7 +853,7 @@
 		sch = to_subchannel(cdev->dev.parent);
 		if (!sch->lpm) {
 			PREPARE_WORK(&cdev->private->kick_work,
-				     ccw_device_nopath_notify, (void *)cdev);
+				     ccw_device_nopath_notify, cdev);
 			queue_work(ccw_device_notify_work,
 				   &cdev->private->kick_work);
 		} else
@@ -885,7 +879,8 @@
 			/* Basic sense hasn't started. Try again. */
 			ccw_device_do_sense(cdev, irb);
 		else {
-			printk("Huh? %s(%s): unsolicited interrupt...\n",
+			printk(KERN_INFO "Huh? %s(%s): unsolicited "
+			       "interrupt...\n",
 			       __FUNCTION__, cdev->dev.bus_id);
 			if (cdev->handler)
 				cdev->handler (cdev, 0, irb);
@@ -944,10 +939,10 @@
 	cdev->private->state = DEV_STATE_ONLINE;
 	if (cdev->handler)
 		cdev->handler(cdev, cdev->private->intparm,
-			      ERR_PTR(-ETIMEDOUT));
+			      ERR_PTR(-EIO));
 	if (!sch->lpm) {
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_nopath_notify, (void *)cdev);
+			     ccw_device_nopath_notify, cdev);
 		queue_work(ccw_device_notify_work, &cdev->private->kick_work);
 	} else if (cdev->private->flags.doverify)
 		/* Start delayed path verification. */
@@ -970,7 +965,7 @@
 		sch = to_subchannel(cdev->dev.parent);
 		if (!sch->lpm) {
 			PREPARE_WORK(&cdev->private->kick_work,
-				     ccw_device_nopath_notify, (void *)cdev);
+				     ccw_device_nopath_notify, cdev);
 			queue_work(ccw_device_notify_work,
 				   &cdev->private->kick_work);
 		} else
@@ -981,51 +976,15 @@
 	cdev->private->state = DEV_STATE_ONLINE;
 	if (cdev->handler)
 		cdev->handler(cdev, cdev->private->intparm,
-			      ERR_PTR(-ETIMEDOUT));
+			      ERR_PTR(-EIO));
 }
 
-static void
-ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event)
-{
-	struct irb *irb;
-	struct subchannel *sch;
-
-	irb = (struct irb *) __LC_IRB;
-	/*
-	 * Accumulate status and find out if a basic sense is needed.
-	 * This is fine since we have already adapted the lpm.
-	 */
-	ccw_device_accumulate_irb(cdev, irb);
-	if (cdev->private->flags.dosense) {
-		if (ccw_device_do_sense(cdev, irb) == 0) {
-			cdev->private->state = DEV_STATE_W4SENSE;
-		}
-		return;
-	}
-
-	/* Iff device is idle, reset timeout. */
-	sch = to_subchannel(cdev->dev.parent);
-	if (!stsch(sch->schid, &sch->schib))
-		if (sch->schib.scsw.actl == 0)
-			ccw_device_set_timeout(cdev, 0);
-	/* Call the handler. */
-	ccw_device_call_handler(cdev);
-	if (!sch->lpm) {
-		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_nopath_notify, (void *)cdev);
-		queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-	} else if (cdev->private->flags.doverify)
-		ccw_device_online_verify(cdev, 0);
-}
-
-static void
-ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
+void device_kill_io(struct subchannel *sch)
 {
 	int ret;
-	struct subchannel *sch;
+	struct ccw_device *cdev;
 
-	sch = to_subchannel(cdev->dev.parent);
-	ccw_device_set_timeout(cdev, 0);
+	cdev = sch->dev.driver_data;
 	ret = ccw_device_cancel_halt_clear(cdev);
 	if (ret == -EBUSY) {
 		ccw_device_set_timeout(cdev, 3*HZ);
@@ -1035,7 +994,7 @@
 	if (ret == -ENODEV) {
 		if (!sch->lpm) {
 			PREPARE_WORK(&cdev->private->kick_work,
-				     ccw_device_nopath_notify, (void *)cdev);
+				     ccw_device_nopath_notify, cdev);
 			queue_work(ccw_device_notify_work,
 				   &cdev->private->kick_work);
 		} else
@@ -1044,12 +1003,12 @@
 	}
 	if (cdev->handler)
 		cdev->handler(cdev, cdev->private->intparm,
-			      ERR_PTR(-ETIMEDOUT));
+			      ERR_PTR(-EIO));
 	if (!sch->lpm) {
 		PREPARE_WORK(&cdev->private->kick_work,
-			     ccw_device_nopath_notify, (void *)cdev);
+			     ccw_device_nopath_notify, cdev);
 		queue_work(ccw_device_notify_work, &cdev->private->kick_work);
-	} else if (cdev->private->flags.doverify)
+	} else
 		/* Start delayed path verification. */
 		ccw_device_online_verify(cdev, 0);
 }
@@ -1286,12 +1245,6 @@
 		[DEV_EVENT_TIMEOUT]	= ccw_device_killing_timeout,
 		[DEV_EVENT_VERIFY]	= ccw_device_nop, //FIXME
 	},
-	[DEV_STATE_WAIT4IO] = {
-		[DEV_EVENT_NOTOPER]	= ccw_device_online_notoper,
-		[DEV_EVENT_INTERRUPT]	= ccw_device_wait4io_irq,
-		[DEV_EVENT_TIMEOUT]	= ccw_device_wait4io_timeout,
-		[DEV_EVENT_VERIFY]	= ccw_device_delay_verify,
-	},
 	[DEV_STATE_QUIESCE] = {
 		[DEV_EVENT_NOTOPER]	= ccw_device_quiesce_done,
 		[DEV_EVENT_INTERRUPT]	= ccw_device_quiesce_done,
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 1398367..a74785b 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -251,7 +251,7 @@
 		 */
 		CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
 			      "0.%x.%04x reports cmd reject\n",
-			      cdev->private->devno, sch->schid.ssid,
+			      cdev->private->dev_id.devno, sch->schid.ssid,
 			      sch->schid.sch_no);
 		return -EOPNOTSUPP;
 	}
@@ -259,7 +259,8 @@
 		CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, "
 			      "lpum %02X, cnt %02d, sns :"
 			      " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->private->ssid, cdev->private->devno,
+			      cdev->private->dev_id.ssid,
+			      cdev->private->dev_id.devno,
 			      irb->esw.esw0.sublog.lpum,
 			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
@@ -274,14 +275,15 @@
 			CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
 				      "on subchannel 0.%x.%04x is "
 				      "'not operational'\n", sch->orb.lpm,
-				      cdev->private->devno, sch->schid.ssid,
-				      sch->schid.sch_no);
+				      cdev->private->dev_id.devno,
+				      sch->schid.ssid, sch->schid.sch_no);
 		return -EACCES;
 	}
 	/* Hmm, whatever happened, try again. */
 	CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
 		      "subchannel 0.%x.%04x returns status %02X%02X\n",
-		      cdev->private->devno, sch->schid.ssid, sch->schid.sch_no,
+		      cdev->private->dev_id.devno, sch->schid.ssid,
+		      sch->schid.sch_no,
 		      irb->scsw.dstat, irb->scsw.cstat);
 	return -EAGAIN;
 }
@@ -330,7 +332,7 @@
 		/* fall through. */
 	default:		/* Sense ID failed. Try asking VM. */
 		if (MACHINE_IS_VM) {
-			VM_virtual_device_info (cdev->private->devno,
+			VM_virtual_device_info (cdev->private->dev_id.devno,
 						&cdev->private->senseid);
 			if (cdev->private->senseid.cu_type != 0xFFFF) {
 				/* Got the device information from VM. */
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 84b9b18..b39c1fa 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -50,7 +50,6 @@
 	if (cdev->private->state == DEV_STATE_NOT_OPER)
 		return -ENODEV;
 	if (cdev->private->state != DEV_STATE_ONLINE &&
-	    cdev->private->state != DEV_STATE_WAIT4IO &&
 	    cdev->private->state != DEV_STATE_W4SENSE)
 		return -EINVAL;
 	sch = to_subchannel(cdev->dev.parent);
@@ -155,7 +154,6 @@
 	if (cdev->private->state == DEV_STATE_NOT_OPER)
 		return -ENODEV;
 	if (cdev->private->state != DEV_STATE_ONLINE &&
-	    cdev->private->state != DEV_STATE_WAIT4IO &&
 	    cdev->private->state != DEV_STATE_W4SENSE)
 		return -EINVAL;
 	sch = to_subchannel(cdev->dev.parent);
@@ -592,13 +590,13 @@
 int
 _ccw_device_get_subchannel_number(struct ccw_device *cdev)
 {
-	return cdev->private->sch_no;
+	return cdev->private->schid.sch_no;
 }
 
 int
 _ccw_device_get_device_number(struct ccw_device *cdev)
 {
-	return cdev->private->devno;
+	return cdev->private->dev_id.devno;
 }
 
 
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 84917b3..2975ce8 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -79,7 +79,8 @@
 			CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
 				      "0.%x.%04x, lpm %02X, became 'not "
 				      "operational'\n",
-				      cdev->private->devno, sch->schid.ssid,
+				      cdev->private->dev_id.devno,
+				      sch->schid.ssid,
 				      sch->schid.sch_no, cdev->private->imask);
 
 		}
@@ -135,7 +136,8 @@
 		CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
 			      "lpum %02X, cnt %02d, sns : "
 			      "%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->private->ssid, cdev->private->devno,
+			      cdev->private->dev_id.ssid,
+			      cdev->private->dev_id.devno,
 			      irb->esw.esw0.sublog.lpum,
 			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
@@ -147,7 +149,7 @@
 	if (irb->scsw.cc == 3) {
 		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
 			      " lpm %02X, became 'not operational'\n",
-			      cdev->private->devno, sch->schid.ssid,
+			      cdev->private->dev_id.devno, sch->schid.ssid,
 			      sch->schid.sch_no, sch->orb.lpm);
 		return -EACCES;
 	}
@@ -155,7 +157,7 @@
 	if (cdev->private->pgid[i].inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
 		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
 			      "is reserved by someone else\n",
-			      cdev->private->devno, sch->schid.ssid,
+			      cdev->private->dev_id.devno, sch->schid.ssid,
 			      sch->schid.sch_no);
 		return -EUSERS;
 	}
@@ -261,7 +263,7 @@
 	/* PGID command failed on this path. */
 	CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
 		      "0.%x.%04x, lpm %02X, became 'not operational'\n",
-		      cdev->private->devno, sch->schid.ssid,
+		      cdev->private->dev_id.devno, sch->schid.ssid,
 		      sch->schid.sch_no, cdev->private->imask);
 	return ret;
 }
@@ -301,7 +303,7 @@
 	/* nop command failed on this path. */
 	CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel "
 		      "0.%x.%04x, lpm %02X, became 'not operational'\n",
-		      cdev->private->devno, sch->schid.ssid,
+		      cdev->private->dev_id.devno, sch->schid.ssid,
 		      sch->schid.sch_no, cdev->private->imask);
 	return ret;
 }
@@ -328,8 +330,9 @@
 		CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
 			      "cnt %02d, "
 			      "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->private->ssid,
-			      cdev->private->devno, irb->esw.esw0.erw.scnt,
+			      cdev->private->dev_id.ssid,
+			      cdev->private->dev_id.devno,
+			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
 			      irb->ecw[2], irb->ecw[3],
 			      irb->ecw[4], irb->ecw[5],
@@ -339,7 +342,7 @@
 	if (irb->scsw.cc == 3) {
 		CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
 			      " lpm %02X, became 'not operational'\n",
-			      cdev->private->devno, sch->schid.ssid,
+			      cdev->private->dev_id.devno, sch->schid.ssid,
 			      sch->schid.sch_no, cdev->private->imask);
 		return -EACCES;
 	}
@@ -362,7 +365,7 @@
 	if (irb->scsw.cc == 3) {
 		CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
 			      " lpm %02X, became 'not operational'\n",
-			      cdev->private->devno, sch->schid.ssid,
+			      cdev->private->dev_id.devno, sch->schid.ssid,
 			      sch->schid.sch_no, cdev->private->imask);
 		return -EACCES;
 	}
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index caf148d..3f7cbce 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -32,19 +32,18 @@
 				 SCHN_STAT_CHN_CTRL_CHK |
 				 SCHN_STAT_INTF_CTRL_CHK)))
 		return;
-		
 	CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
 		      "received"
 		      " ... device %04x on subchannel 0.%x.%04x, dev_stat "
 		      ": %02X sch_stat : %02X\n",
-		      cdev->private->devno, cdev->private->ssid,
-		      cdev->private->sch_no,
+		      cdev->private->dev_id.devno, cdev->private->schid.ssid,
+		      cdev->private->schid.sch_no,
 		      irb->scsw.dstat, irb->scsw.cstat);
 
 	if (irb->scsw.cc != 3) {
 		char dbf_text[15];
 
-		sprintf(dbf_text, "chk%x", cdev->private->sch_no);
+		sprintf(dbf_text, "chk%x", cdev->private->schid.sch_no);
 		CIO_TRACE_EVENT(0, dbf_text);
 		CIO_HEX_EVENT(0, irb, sizeof (struct irb));
 	}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index cde822d..476aa1d 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -1741,7 +1741,7 @@
 	void *ptr;
 	int available;
 
-	sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no);
+	sprintf(dbf_text,"qfqs%4x",cdev->private->schid.sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	for (i=0;i<no_input_qs;i++) {
 		q=irq_ptr->input_qs[i];
@@ -2924,7 +2924,7 @@
 
 	irq_ptr = cdev->private->qdio_data;
 
-	sprintf(dbf_text,"qehi%4x",cdev->private->sch_no);
+	sprintf(dbf_text,"qehi%4x",cdev->private->schid.sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
@@ -2943,7 +2943,7 @@
 	int rc;
 	char dbf_text[15];
 
-	sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no);
+	sprintf(dbf_text,"qini%4x",init_data->cdev->private->schid.sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
@@ -2964,7 +2964,7 @@
 	struct qdio_irq *irq_ptr;
 	char dbf_text[15];
 
-	sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no);
+	sprintf(dbf_text,"qalc%4x",init_data->cdev->private->schid.sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 	if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -3187,7 +3187,7 @@
 		tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
 	}
 
-	sprintf(dbf_text,"qest%4x",cdev->private->sch_no);
+	sprintf(dbf_text,"qest%4x",cdev->private->schid.sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
@@ -3529,7 +3529,7 @@
 #ifdef CONFIG_QDIO_DEBUG
 	char dbf_text[20];
 
-	sprintf(dbf_text,"doQD%04x",cdev->private->sch_no);
+	sprintf(dbf_text,"doQD%04x",cdev->private->schid.sch_no);
  	QDIO_DBF_TEXT3(0,trace,dbf_text);
 #endif /* CONFIG_QDIO_DEBUG */
 
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index cd30f37..c5ccd20 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1062,7 +1062,7 @@
 	unsigned long flags;
 	int requests;
 
-	set_user_nice(current, -20);
+	set_user_nice(current, 19);
 	while (1) {
 		if (need_resched()) {
 			schedule();
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 809dd8d..1476ce2 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -116,7 +116,7 @@
  *Internal function prototypes
  */
 static void iucv_tasklet_handler(unsigned long);
-static void iucv_irq_handler(struct pt_regs *, __u16);
+static void iucv_irq_handler(__u16);
 
 static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
 
@@ -2251,7 +2251,7 @@
  * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
  */
 static void
-iucv_irq_handler(struct pt_regs *regs, __u16 code)
+iucv_irq_handler(__u16 code)
 {
 	iucv_irqdata *irqdata;
 
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 862a411..c88babc 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1987,7 +1987,7 @@
 		sbale = &(adapter->response_queue.buffer[i]->element[0]);
 		sbale->length = 0;
 		sbale->flags = SBAL_FLAGS_LAST_ENTRY;
-		sbale->addr = 0;
+		sbale->addr = NULL;
 	}
 
 	ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, "
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index a305d40..a54b4ac 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -254,7 +254,7 @@
 return 0;
 }
 
-static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static irqreturn_t aurora_interrupt(int irq, void * dev_id);
 
 /* Main probing routine, also sets irq. */
 static int aurora_probe(void)
@@ -689,7 +689,7 @@
 }
 
 /* The main interrupt processing routine */
-static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t aurora_interrupt(int irq, void * dev_id)
 {
 	unsigned char status;
 	unsigned char ack,chip/*,chip_id*/;
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index d27e4f6..a54e414 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -4,11 +4,9 @@
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
  */
 
-#include <linux/kernel.h>
 #include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/kmod.h>
 #include <asm/oplib.h>
 #include <asm/ebus.h>
 
@@ -197,7 +195,7 @@
 	printk(KERN_CRIT "kenvctrld: Shutting down the system now.\n");
 
 	shutting_down = 1;
-	if (kernel_execve("/sbin/shutdown", argv, envp) < 0)
+	if (call_usermodehelper("/sbin/shutdown", argv, envp, 0) < 0)
 		printk(KERN_CRIT "envctrl: shutdown execution failed\n");
 }
 
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 7186235..22631f8 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -331,7 +331,7 @@
 EXPORT_SYMBOL(bbc_i2c_write_buf);
 EXPORT_SYMBOL(bbc_i2c_read_buf);
 
-static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id)
 {
 	struct bbc_i2c_bus *bp = dev_id;
 
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 40b6fc8..f5803ec 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -185,7 +185,7 @@
 #ifdef WD_DEBUG
 static void wd_dumpregs(void);
 #endif
-static irqreturn_t wd_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t wd_interrupt(int irq, void *dev_id);
 static void wd_toggleintr(struct wd_timer* pTimer, int enable);
 static void wd_pingtimer(struct wd_timer* pTimer);
 static void wd_starttimer(struct wd_timer* pTimer);
@@ -444,7 +444,7 @@
 #endif /* ifdef WD_DEBUG */
 }
 
-static irqreturn_t wd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wd_interrupt(int irq, void *dev_id)
 {
 	/* Only WD0 will interrupt-- others are NMI and we won't
 	 * see them here....
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 728a133..fff4660 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -20,16 +20,12 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/init.h>
 #include <linux/kthread.h>
-#include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
+#include <linux/kmod.h>
 
 #include <asm/ebus.h>
 #include <asm/uaccess.h>
@@ -980,7 +976,7 @@
 
 	inprog = 1;
 	printk(KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n");
-	ret = kernel_execve("/sbin/shutdown", argv, envp);
+	ret = call_usermodehelper("/sbin/shutdown", argv, envp, 0);
 	if (ret < 0) {
 		printk(KERN_CRIT "kenvctrld: WARNING: system shutdown failed!\n"); 
 		inprog = 0;  /* unlikely to succeed, but we could try again */
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 2f69876..81ba2d7 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -630,7 +630,7 @@
 	case OPROMPATH2NODE:
 		if ((file->f_mode & FMODE_READ) == 0)
 			return -EPERM;
-		return openprom_sunos_ioctl(inode, file, cmd, arg, 0);
+		return openprom_sunos_ioctl(inode, file, cmd, arg, NULL);
 
 	case OPIOCGET:
 	case OPIOCNEXTPROP:
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 575b1f7..b30372f 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -217,7 +217,7 @@
 	return 0;
 }
 
-static irqreturn_t uctrl_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t uctrl_interrupt(int irq, void *dev_id)
 {
 	struct uctrl_driver *driver = (struct uctrl_driver *)dev_id;
 	printk("in uctrl_interrupt\n");
@@ -400,7 +400,7 @@
 	}
 
 	driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK;
-	printk("uctrl: 0x%x (irq %d)\n", driver->regs, driver->irq);
+	printk("uctrl: 0x%p (irq %d)\n", driver->regs, driver->irq);
 	uctrl_get_event_status();
 	uctrl_get_external_status();
         return 0;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 5a9475e..5f8c26c 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1192,7 +1192,7 @@
 } /* End twa_initialize_device_extension() */
 
 /* This function is the interrupt service routine */
-static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t twa_interrupt(int irq, void *dev_instance)
 {
 	int request_id, error = 0;
 	u32 status_reg_value;
@@ -2211,7 +2211,7 @@
 {
 	printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
 
-	return pci_module_init(&twa_driver);
+	return pci_register_driver(&twa_driver);
 } /* End twa_init() */
 
 /* This function is called on driver exit */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index f3a5f42..99a259c 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -2078,8 +2078,7 @@
 } /* End tw_scsi_queue() */
 
 /* This function is the interrupt service routine */
-static irqreturn_t tw_interrupt(int irq, void *dev_instance,
-		     struct pt_regs *regs) 
+static irqreturn_t tw_interrupt(int irq, void *dev_instance) 
 {
 	int request_id;
 	u32 status_reg_value;
@@ -2486,7 +2485,7 @@
 {
 	printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
 
-	return pci_module_init(&tw_driver);
+	return pci_register_driver(&tw_driver);
 } /* End tw_init() */
 
 /* This function is called on driver exit */
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 31fe5ea..bbd654a 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -74,7 +74,7 @@
 	[0x00D] = "ERROR: Logical unit deleted: Unit #",
 	[0x00F] = "WARNING: SMART threshold exceeded: Port #",
 	[0x021] = "WARNING: ATA UDMA downgrade: Port #",
-	[0x021] = "WARNING: ATA UDMA upgrade: Port #",
+	[0x022] = "WARNING: ATA UDMA upgrade: Port #",
 	[0x023] = "WARNING: Sector repair occurred: Port #",
 	[0x024] = "ERROR: SBUF integrity check failure",
 	[0x025] = "ERROR: Lost cached write: Port #",
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 15ce40a..562432d 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1462,7 +1462,7 @@
 }
 
 irqreturn_t
-NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs)
+NCR_700_intr(int irq, void *dev_id)
 {
 	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
 	struct NCR_700_Host_Parameters *hostdata =
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index 97ebe71..f5c3caf 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -57,7 +57,7 @@
 struct Scsi_Host *NCR_700_detect(struct scsi_host_template *,
 		struct NCR_700_Host_Parameters *, struct device *);
 int NCR_700_release(struct Scsi_Host *host);
-irqreturn_t NCR_700_intr(int, void *, struct pt_regs *);
+irqreturn_t NCR_700_intr(int, void *);
 
 
 enum NCR_700_Host_State {
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index acf2927..640536e 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -323,7 +323,7 @@
 static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
 static int disable (struct Scsi_Host *host);
 static int NCR53c7xx_run_tests (struct Scsi_Host *host);
-static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id);
 static void NCR53c7x0_intfly (struct Scsi_Host *host);
 static int ncr_halt (struct Scsi_Host *host);
 static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
@@ -4227,7 +4227,7 @@
 }
 
 /*
- * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+ * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id)
  *
  * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
  *	the same IRQ line.  
@@ -4241,7 +4241,7 @@
  */
 
 static irqreturn_t
-NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+NCR53c7x0_intr (int irq, void *dev_id)
 {
     NCR53c7x0_local_declare();
     struct Scsi_Host *host;			/* Host we are looking at */
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 4ea49fd..cdd0337 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2653,7 +2653,7 @@
   Adapters.
 */
 
-static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, struct pt_regs *InterruptRegisters)
+static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier)
 {
 	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier;
 	unsigned long ProcessorFlags;
@@ -3600,5 +3600,16 @@
 
 __setup("BusLogic=", BusLogic_Setup);
 
+static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl);
+
 module_init(BusLogic_init);
 module_exit(BusLogic_exit);
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index d6d1d56..cca6d45e 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -1347,7 +1347,7 @@
 static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
-static irqreturn_t BusLogic_InterruptHandler(int, void *, struct pt_regs *);
+static irqreturn_t BusLogic_InterruptHandler(int, void *);
 static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset);
 static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
 static int __init BusLogic_Setup(char *);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index c6dfb6fa..9540eb8 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1016,7 +1016,7 @@
 
 config SCSI_IPR
 	tristate "IBM Power Linux RAID adapter support"
-	depends on PCI && SCSI
+	depends on PCI && SCSI && ATA
 	select FW_LOADER
 	---help---
 	  This driver supports the IBM Power Linux family RAID adapters.
@@ -1246,6 +1246,7 @@
 	  module will be called qlogicpti.
 
 source "drivers/scsi/qla2xxx/Kconfig"
+source "drivers/scsi/qla4xxx/Kconfig"
 
 config SCSI_LPFC
 	tristate "Emulex LightPulse Fibre Channel Support"
@@ -1262,8 +1263,8 @@
 	  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,
 	  available from <http://www.tldp.org/docs.html#howto>.  If it
-	  doesn't work out of the box, you may have to change some settings in
-	  <file:drivers/scsi/seagate.h>.
+	  doesn't work out of the box, you may have to change some macros at
+	  compiletime, which are described in <file:drivers/scsi/seagate.c>.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called seagate.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1ef951b..bcca39c 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -84,6 +84,7 @@
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogicfas408.o
 obj-$(CONFIG_SCSI_QLOGIC_1280)	+= qla1280.o 
 obj-$(CONFIG_SCSI_QLA_FC)	+= qla2xxx/
+obj-$(CONFIG_SCSI_QLA_ISCSI)	+= qla4xxx/
 obj-$(CONFIG_SCSI_LPFC)		+= lpfc/
 obj-$(CONFIG_SCSI_PAS16)	+= pas16.o
 obj-$(CONFIG_SCSI_SEAGATE)	+= seagate.o
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 616810a..a6aa910 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -558,8 +558,7 @@
  *	used by the IRQ probe code.
  */
  
-static irqreturn_t __init probe_intr(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t __init probe_intr(int irq, void *dev_id)
 {
 	probe_irq = irq;
 	return IRQ_HANDLED;
@@ -1148,7 +1147,6 @@
  * 	NCR5380_intr	-	generic NCR5380 irq handler
  *	@irq: interrupt number
  *	@dev_id: device info
- *	@regs: registers (unused)
  *
  *	Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
  *      from the disconnected queue, and restarting NCR5380_main() 
@@ -1157,7 +1155,7 @@
  *	Locks: takes the needed instance locks
  */
 
-static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) 
+static irqreturn_t NCR5380_intr(int irq, void *dev_id) 
 {
 	NCR5380_local_declare();
 	struct Scsi_Host *instance = (struct Scsi_Host *)dev_id;
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index c3462e3..1bc73de 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -296,7 +296,7 @@
 static void NCR5380_exit(struct Scsi_Host *instance);
 static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
-static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t NCR5380_intr(int irq, void *dev_id);
 #endif
 static void NCR5380_main(void *ptr);
 static void NCR5380_print_options(struct Scsi_Host *instance);
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index bdc6bb2..3c912ee 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -96,7 +96,7 @@
 static struct NCR_ESP *espchain;
 int nesps = 0, esps_in_use = 0, esps_running = 0;
 
-irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+irqreturn_t esp_intr(int irq, void *dev_id);
 
 /* Debugging routines */
 static struct esp_cmdstrings {
@@ -3533,7 +3533,7 @@
 }
 
 #ifndef CONFIG_SMP
-irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+irqreturn_t esp_intr(int irq, void *dev_id)
 {
 	struct NCR_ESP *esp;
 	unsigned long flags;
@@ -3570,7 +3570,7 @@
 }
 #else
 /* For SMP we only service one ESP on the list list at our IRQ level! */
-irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+irqreturn_t esp_intr(int irq, void *dev_id)
 {
 	struct NCR_ESP *esp;
 	unsigned long flags;
diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h
index 481653c..521e3f8 100644
--- a/drivers/scsi/NCR53C9x.h
+++ b/drivers/scsi/NCR53C9x.h
@@ -656,7 +656,7 @@
 extern void esp_deallocate(struct NCR_ESP *);
 extern void esp_release(void);
 extern void esp_initialize(struct NCR_ESP *);
-extern irqreturn_t esp_intr(int, void *, struct pt_regs *);
+extern irqreturn_t esp_intr(int, void *);
 extern const char *esp_info(struct Scsi_Host *);
 extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int esp_abort(Scsi_Cmnd *);
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 8472c53..d461381 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -168,8 +168,8 @@
 };
 
 /* Static function prototypes */
-static void NCR53c406a_intr(int, void *, struct pt_regs *);
-static irqreturn_t do_NCR53c406a_intr(int, void *, struct pt_regs *);
+static void NCR53c406a_intr(void *);
+static irqreturn_t do_NCR53c406a_intr(int, void *);
 static void chip_init(void);
 static void calc_port_addr(void);
 #ifndef IRQ_LEV
@@ -685,7 +685,7 @@
 		return;
 	}
 
-	NCR53c406a_intr(0, NULL, NULL);
+	NCR53c406a_intr(NULL);
 }
 #endif
 
@@ -761,19 +761,18 @@
 	return 0;
 }
 
-static irqreturn_t do_NCR53c406a_intr(int unused, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t do_NCR53c406a_intr(int unused, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = dev_id;
 
 	spin_lock_irqsave(dev->host_lock, flags);
-	NCR53c406a_intr(0, dev_id, regs);
+	NCR53c406a_intr(dev_id);
 	spin_unlock_irqrestore(dev->host_lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void NCR53c406a_intr(int unused, void *dev_id, struct pt_regs *regs)
+static void NCR53c406a_intr(void *dev_id)
 {
 	DEB(unsigned char fifo_size;
 	    )
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index d05681f..9859cd1 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -226,14 +226,14 @@
 }
 
 static int
-NCR_D700_intr(int irq, void *data, struct pt_regs *regs)
+NCR_D700_intr(int irq, void *data)
 {
 	struct NCR_D700_private *p = (struct NCR_D700_private *)data;
 	int i, found = 0;
 
 	for (i = 0; i < 2; i++)
 		if (p->hosts[i] &&
-		    NCR_700_intr(irq, p->hosts[i], regs) == IRQ_HANDLED)
+		    NCR_700_intr(irq, p->hosts[i]) == IRQ_HANDLED)
 			found++;
 
 	return found ? IRQ_HANDLED : IRQ_NONE;
diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
index c39ffbb..778844c 100644
--- a/drivers/scsi/NCR_Q720.c
+++ b/drivers/scsi/NCR_Q720.c
@@ -54,7 +54,7 @@
 };
 
 static irqreturn_t
-NCR_Q720_intr(int irq, void *data, struct pt_regs * regs)
+NCR_Q720_intr(int irq, void *data)
 {
 	struct NCR_Q720_private *p = (struct NCR_Q720_private *)data;
 	__u8 sir = (readb(p->mem_base + 0x0d) & 0xf0) >> 4;
@@ -68,7 +68,7 @@
 
 	while((siop = ffz(sir)) < p->siops) {
 		sir |= 1<<siop;
-		ncr53c8xx_intr(irq, p->hosts[siop], regs);
+		ncr53c8xx_intr(irq, p->hosts[siop]);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index d7e9fab..2650a5d 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1013,7 +1013,7 @@
 /*
  * Interrupt handler (main routine of the driver)
  */
-static irqreturn_t inia100_intr(int irqno, void *devid, struct pt_regs *regs)
+static irqreturn_t inia100_intr(int irqno, void *devid)
 {
 	struct Scsi_Host *host = (struct Scsi_Host *)devid;
 	ORC_HCS *pHcb = (ORC_HCS *)host->hostdata;
@@ -1187,7 +1187,7 @@
 
 static int __init inia100_init(void)
 {
-	return pci_module_init(&inia100_pci_driver);
+	return pci_register_driver(&inia100_pci_driver);
 }
 
 static void __exit inia100_exit(void)
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 0854069..f77016d 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -24,7 +24,7 @@
 #define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
-static irqreturn_t a2091_intr (int irq, void *_instance, struct pt_regs *fp)
+static irqreturn_t a2091_intr (int irq, void *_instance)
 {
     unsigned long flags;
     unsigned int status;
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index 7bf46d4..1299bc8 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -26,7 +26,7 @@
 
 static struct Scsi_Host *a3000_host = NULL;
 
-static irqreturn_t a3000_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t a3000_intr (int irq, void *dummy)
 {
 	unsigned long flags;
 	unsigned int status = DMA(a3000_host)->ISTR;
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index a1d214d..dcc8b0e 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -46,11 +46,11 @@
 
 #include "aacraid.h"
 
-static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t aac_rx_intr(int irq, void *dev_id)
 {
 	struct aac_dev *dev = dev_id;
 
-	dprintk((KERN_DEBUG "aac_rx_intr(%d,%p,%p)\n", irq, dev_id, regs));
+	dprintk((KERN_DEBUG "aac_rx_intr(%d,%p)\n", irq, dev_id));
 	if (dev->new_comm_interface) {
 		u32 Index = rx_readl(dev, MUnit.OutboundQueue);
 		if (Index == 0xFFFFFFFFL)
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index f906ead..511b0a9 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -46,7 +46,7 @@
 
 #include "aacraid.h"
 
-static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t aac_sa_intr(int irq, void *dev_id)
 {
 	struct aac_dev *dev = dev_id;
 	unsigned short intstat, mask;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 773f02e..2b34435 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -3881,7 +3881,7 @@
     /*
      * The following fields are used only for Wide Boards.
      */
-    void                 *ioremap_addr;         /* I/O Memory remap address. */
+    void                 __iomem *ioremap_addr; /* I/O Memory remap address. */
     ushort               ioport;                /* I/O Port address. */
     ADV_CARR_T           *orig_carrp;           /* ADV_CARR_T memory block. */
     adv_req_t            *orig_reqp;            /* adv_req_t memory block. */
@@ -3951,7 +3951,7 @@
 
 /* Number of boards detected in system. */
 STATIC int asc_board_count = 0;
-STATIC struct Scsi_Host    *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
+STATIC struct Scsi_Host    *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL };
 
 /* Overrun buffer used by all narrow boards. */
 STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
@@ -3999,7 +3999,7 @@
  * advansys.h contains function prototypes for functions global to Linux.
  */
 
-STATIC irqreturn_t advansys_interrupt(int, void *, struct pt_regs *);
+STATIC irqreturn_t advansys_interrupt(int, void *);
 STATIC int	  advansys_slave_configure(struct scsi_device *);
 STATIC void       asc_scsi_done_list(struct scsi_cmnd *);
 STATIC int        asc_execute_scsi_cmnd(struct scsi_cmnd *);
@@ -5997,7 +5997,7 @@
  * an AdvanSys adapter.
  */
 STATIC irqreturn_t
-advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+advansys_interrupt(int irq, void *dev_id)
 {
     ulong           flags;
     int             i;
@@ -6621,7 +6621,7 @@
 	        dma_map_single(dev, scp->request_buffer,
 			       scp->request_bufflen, scp->sc_data_direction);
 	} else {
-	    scsiqp->vdata_addr = 0;
+	    scsiqp->vdata_addr = NULL;
 	    scp->SCp.dma_handle = 0;
 	}
 	scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index fb6a476..306f46b 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -238,7 +238,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/blkdev.h>
 #include <asm/system.h>
 #include <linux/errno.h>
@@ -673,7 +673,7 @@
 };
 
 /* setup & interrupt */
-static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *);
+static irqreturn_t intr(int irq, void *dev_id);
 static void reset_ports(struct Scsi_Host *shpnt);
 static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
 static void done(struct Scsi_Host *shpnt, int error);
@@ -757,14 +757,9 @@
 	return ptr;
 }
 
-static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs)
+static irqreturn_t swintr(int irqno, void *dev_id)
 {
-	struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
-
-	if (!shpnt) {
-        	printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno);
-		return IRQ_NONE;
-	}
+	struct Scsi_Host *shpnt = dev_id;
 
 	HOSTDATA(shpnt)->swint++;
 
@@ -1463,7 +1458,7 @@
  * Interrupt handler
  *
  */
-static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
+static irqreturn_t intr(int irqno, void *dev_id)
 {
 	struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
 	unsigned long flags;
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 24f0f54..d7a61a6 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -174,9 +174,8 @@
 
 static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt);
 static int aha1542_restart(struct Scsi_Host *shost);
-static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id, struct pt_regs *regs);
-static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id,
-					struct pt_regs *regs);
+static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id);
+static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id);
 
 #define aha1542_intr_reset(base)  outb(IRST, CONTROL(base))
 
@@ -416,8 +415,7 @@
 }
 
 /* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
-static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *shost;
@@ -427,13 +425,13 @@
 		panic("Splunge!");
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	aha1542_intr_handle(shost, dev_id, regs);
+	aha1542_intr_handle(shost, dev_id);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	return IRQ_HANDLED;
 }
 
 /* A "high" level interrupt handler */
-static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id, struct pt_regs *regs)
+static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id)
 {
 	void (*my_done) (Scsi_Cmnd *) = NULL;
 	int errstatus, mbi, mbo, mbistatus;
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index 6b35ed8..c3c38a7 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -223,8 +223,7 @@
 }
 
 /* A "high" level interrupt handler */
-static irqreturn_t aha1740_intr_handle(int irq, void *dev_id,
-				       struct pt_regs *regs)
+static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
 {
 	struct Scsi_Host *host = (struct Scsi_Host *) dev_id;
         void (*my_done)(Scsi_Cmnd *);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index 8ad3ce9..a3266e0 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
@@ -527,7 +527,8 @@
 	 * or have other side effects when the low byte is
 	 * read.
 	 */
-	return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
+	uint16_t r = ahd_inb(ahd, port+1) << 8;
+	return r | ahd_inb(ahd, port);
 }
 
 static __inline void
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 1faa008..f8e6048 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1557,7 +1557,7 @@
  * SCSI controller interrupt handler.
  */
 irqreturn_t
-ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
+ahd_linux_isr(int irq, void *dev_id)
 {
 	struct	ahd_softc *ahd;
 	u_long	flags;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 601340d..fb3d4dd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -862,7 +862,7 @@
 				char channel, int lun, u_int tag,
 				role_t role, uint32_t status);
 irqreturn_t
-	ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
+	ahd_linux_isr(int irq, void *dev_id);
 void	ahd_done(struct ahd_softc*, struct scb*);
 void	ahd_send_async(struct ahd_softc *, char channel,
 		       u_int target, u_int lun, ac_code);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 50a41ed..4b53542 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -198,7 +198,7 @@
 int
 ahd_linux_pci_init(void)
 {
-	return (pci_module_init(&aic79xx_pci_driver));
+	return pci_register_driver(&aic79xx_pci_driver);
 }
 
 void
diff --git a/drivers/scsi/aic7xxx/aic7xxx_inline.h b/drivers/scsi/aic7xxx/aic7xxx_inline.h
index 2cc8a17..8e1954c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_inline.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_inline.h
@@ -300,7 +300,8 @@
 static __inline uint16_t
 ahc_inw(struct ahc_softc *ahc, u_int port)
 {
-	return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port));
+	uint16_t r = ahc_inb(ahc, port+1) << 8;
+	return r | ahc_inb(ahc, port);
 }
 
 static __inline void
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 339b85c..43ab753 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1608,7 +1608,7 @@
  * SCSI controller interrupt handler.
  */
 irqreturn_t
-ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
+ahc_linux_isr(int irq, void *dev_id)
 {
 	struct	ahc_softc *ahc;
 	u_long	flags;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index d42a71e..a87a4ce 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -830,7 +830,7 @@
 				char channel, int lun, u_int tag,
 				role_t role, uint32_t status);
 irqreturn_t
-	ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
+	ahc_linux_isr(int irq, void *dev_id);
 void	ahc_platform_flushwork(struct ahc_softc *ahc);
 void	ahc_done(struct ahc_softc*, struct scb*);
 void	ahc_send_async(struct ahc_softc *, char channel,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 7e42f07..d20ca51 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -246,8 +246,7 @@
 int
 ahc_linux_pci_init(void)
 {
-	/* Translate error or zero return into zero or one */
-	return pci_module_init(&aic7xxx_pci_driver) ? 0 : 1;
+	return pci_register_driver(&aic7xxx_pci_driver);
 }
 
 void
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 1035337..bcd7fff 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -780,24 +780,26 @@
 } ahc_bugs;
 
 struct aic7xxx_scb {
-        struct aic7xxx_hwscb  *hscb;          /* corresponding hardware scb */
-        Scsi_Cmnd             *cmd;              /* Scsi_Cmnd for this scb */
-        struct aic7xxx_scb    *q_next;        /* next scb in queue */
-        volatile scb_flag_type flags;         /* current state of scb */
-        struct hw_scatterlist *sg_list;       /* SG list in adapter format */
-        unsigned char          tag_action;
-        unsigned char          sg_count;
-        unsigned char          *sense_cmd;    /*
-                                               * Allocate 6 characters for
-                                               * sense command.
-                                               */
-	unsigned char	       *cmnd;
-        unsigned int           sg_length; /* We init this during buildscb so we
-                                           * don't have to calculate anything
-                                           * during underflow/overflow/stat code
-                                           */
-        void                  *kmalloc_ptr;
-	struct aic7xxx_scb_dma *scb_dma;
+	struct aic7xxx_hwscb	*hscb;		/* corresponding hardware scb */
+	struct scsi_cmnd	*cmd;		/* scsi_cmnd for this scb */
+	struct aic7xxx_scb	*q_next;        /* next scb in queue */
+	volatile scb_flag_type	flags;		/* current state of scb */
+	struct hw_scatterlist	*sg_list;	/* SG list in adapter format */
+	unsigned char		tag_action;
+	unsigned char		sg_count;
+	unsigned char		*sense_cmd;	/*
+						 * Allocate 6 characters for
+						 * sense command.
+						 */
+	unsigned char		*cmnd;
+	unsigned int		sg_length;	/*
+						 * We init this during
+						 * buildscb so we don't have
+						 * to calculate anything during
+						 * underflow/overflow/stat code
+						 */
+	void			*kmalloc_ptr;
+	struct aic7xxx_scb_dma	*scb_dma;
 };
 
 /*
@@ -918,79 +920,77 @@
    * We are grouping things here....first, items that get either read or
    * written with nearly every interrupt
    */
-  volatile long            flags;
-  ahc_feature              features;         /* chip features */
-  unsigned long            base;             /* card base address */
-  volatile unsigned char  __iomem *maddr;            /* memory mapped address */
-  unsigned long            isr_count;        /* Interrupt count */
-  unsigned long            spurious_int;
-  scb_data_type           *scb_data;
-  struct aic7xxx_cmd_queue {
-    Scsi_Cmnd *head;
-    Scsi_Cmnd *tail;
-  } completeq;
+	volatile long	flags;
+	ahc_feature	features;	/* chip features */
+	unsigned long	base;		/* card base address */
+	volatile unsigned char  __iomem *maddr;	/* memory mapped address */
+	unsigned long	isr_count;	/* Interrupt count */
+	unsigned long	spurious_int;
+	scb_data_type	*scb_data;
+	struct aic7xxx_cmd_queue {
+		struct scsi_cmnd *head;
+		struct scsi_cmnd *tail;
+	} completeq;
 
-  /*
-   * Things read/written on nearly every entry into aic7xxx_queue()
-   */
-  volatile scb_queue_type  waiting_scbs;
-  unsigned char            unpause;          /* unpause value for HCNTRL */
-  unsigned char            pause;            /* pause value for HCNTRL */
-  volatile unsigned char   qoutfifonext;
-  volatile unsigned char   activescbs;       /* active scbs */
-  volatile unsigned char   max_activescbs;
-  volatile unsigned char   qinfifonext;
-  volatile unsigned char  *untagged_scbs;
-  volatile unsigned char  *qoutfifo;
-  volatile unsigned char  *qinfifo;
+	/*
+	* Things read/written on nearly every entry into aic7xxx_queue()
+	*/
+	volatile scb_queue_type	waiting_scbs;
+	unsigned char	unpause;	/* unpause value for HCNTRL */
+	unsigned char	pause;		/* pause value for HCNTRL */
+	volatile unsigned char	qoutfifonext;
+	volatile unsigned char	activescbs;	/* active scbs */
+	volatile unsigned char	max_activescbs;
+	volatile unsigned char	qinfifonext;
+	volatile unsigned char	*untagged_scbs;
+	volatile unsigned char	*qoutfifo;
+	volatile unsigned char	*qinfifo;
 
-  unsigned char            dev_last_queue_full[MAX_TARGETS];
-  unsigned char            dev_last_queue_full_count[MAX_TARGETS];
-  unsigned short	   ultraenb;         /* Gets downloaded to card as a
-						bitmap */
-  unsigned short	   discenable;       /* Gets downloaded to card as a
-						bitmap */
-  transinfo_type           user[MAX_TARGETS];
+	unsigned char	dev_last_queue_full[MAX_TARGETS];
+	unsigned char	dev_last_queue_full_count[MAX_TARGETS];
+	unsigned short	ultraenb; /* Gets downloaded to card as a bitmap */
+	unsigned short	discenable; /* Gets downloaded to card as a bitmap */
+	transinfo_type	user[MAX_TARGETS];
 
-  unsigned char            msg_buf[13];      /* The message for the target */
-  unsigned char            msg_type;
+	unsigned char	msg_buf[13];	/* The message for the target */
+	unsigned char	msg_type;
 #define MSG_TYPE_NONE              0x00
 #define MSG_TYPE_INITIATOR_MSGOUT  0x01
 #define MSG_TYPE_INITIATOR_MSGIN   0x02
-  unsigned char            msg_len;          /* Length of message */
-  unsigned char            msg_index;        /* Index into msg_buf array */
+	unsigned char	msg_len;	/* Length of message */
+	unsigned char	msg_index;	/* Index into msg_buf array */
 
 
-  /*
-   * We put the less frequently used host structure items after the more
-   * frequently used items to try and ease the burden on the cache subsystem.
-   * These entries are not *commonly* accessed, whereas the preceding entries
-   * are accessed very often.
-   */
+	/*
+	 * We put the less frequently used host structure items
+	 * after the more frequently used items to try and ease
+	 * the burden on the cache subsystem.
+	 * These entries are not *commonly* accessed, whereas
+	 * the preceding entries are accessed very often.
+	 */
 
-  unsigned int             irq;              /* IRQ for this adapter */
-  int                      instance;         /* aic7xxx instance number */
-  int                      scsi_id;          /* host adapter SCSI ID */
-  int                      scsi_id_b;        /* channel B for twin adapters */
-  unsigned int             bios_address;
-  int                      board_name_index;
-  unsigned short           bios_control;     /* bios control - SEEPROM */
-  unsigned short           adapter_control;  /* adapter control - SEEPROM */
-  struct pci_dev	  *pdev;
-  unsigned char            pci_bus;
-  unsigned char            pci_device_fn;
-  struct seeprom_config    sc;
-  unsigned short           sc_type;
-  unsigned short           sc_size;
-  struct aic7xxx_host     *next;             /* allow for multiple IRQs */
-  struct Scsi_Host        *host;             /* pointer to scsi host */
-  struct list_head	   aic_devs;	     /* all aic_dev structs on host */
-  int                      host_no;          /* SCSI host number */
-  unsigned long            mbase;            /* I/O memory address */
-  ahc_chip                 chip;             /* chip type */
-  ahc_bugs                 bugs;
-  dma_addr_t		   fifo_dma;	     /* DMA handle for fifo arrays */
-
+	unsigned int	irq;		/* IRQ for this adapter */
+	int		instance;	/* aic7xxx instance number */
+	int		scsi_id;	/* host adapter SCSI ID */
+	int		scsi_id_b;	/* channel B for twin adapters */
+	unsigned int	bios_address;
+	int		board_name_index;
+	unsigned short	bios_control;		/* bios control - SEEPROM */
+	unsigned short	adapter_control;	/* adapter control - SEEPROM */
+	struct pci_dev	*pdev;
+	unsigned char	pci_bus;
+	unsigned char	pci_device_fn;
+	struct seeprom_config	sc;
+	unsigned short	sc_type;
+	unsigned short	sc_size;
+	struct aic7xxx_host	*next;	/* allow for multiple IRQs */
+	struct Scsi_Host	*host;	/* pointer to scsi host */
+	struct list_head	 aic_devs; /* all aic_dev structs on host */
+	int		host_no;	/* SCSI host number */
+	unsigned long	mbase;		/* I/O memory address */
+	ahc_chip	chip;		/* chip type */
+	ahc_bugs	bugs;
+	dma_addr_t	fifo_dma;	/* DMA handle for fifo arrays */
 };
 
 /*
@@ -1271,7 +1271,7 @@
 static void aic7xxx_set_width(struct aic7xxx_host *p, int target, int channel,
 		int lun, unsigned int width, unsigned int type,
 		struct aic_dev_data *aic_dev);
-static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd);
+static void aic7xxx_panic_abort(struct aic7xxx_host *p, struct scsi_cmnd *cmd);
 static void aic7xxx_print_card(struct aic7xxx_host *p);
 static void aic7xxx_print_scratch_ram(struct aic7xxx_host *p);
 static void aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded);
@@ -2626,7 +2626,7 @@
  *   we're finished.  This function queues the completed commands.
  *-F*************************************************************************/
 static void
-aic7xxx_queue_cmd_complete(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
+aic7xxx_queue_cmd_complete(struct aic7xxx_host *p, struct scsi_cmnd *cmd)
 {
   aic7xxx_position(cmd) = SCB_LIST_NULL;
   cmd->host_scribble = (char *)p->completeq.head;
@@ -2640,18 +2640,16 @@
  * Description:
  *   Process the completed command queue.
  *-F*************************************************************************/
-static void
-aic7xxx_done_cmds_complete(struct aic7xxx_host *p)
+static void aic7xxx_done_cmds_complete(struct aic7xxx_host *p)
 {
-  Scsi_Cmnd *cmd;
-  
-  while (p->completeq.head != NULL)
-  {
-    cmd = p->completeq.head;
-    p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble;
-    cmd->host_scribble = NULL;
-    cmd->scsi_done(cmd);
-  }
+	struct scsi_cmnd *cmd;
+
+	while (p->completeq.head != NULL) {
+		cmd = p->completeq.head;
+		p->completeq.head = (struct scsi_Cmnd *) cmd->host_scribble;
+		cmd->host_scribble = NULL;
+		cmd->scsi_done(cmd);
+	}
 }
 
 /*+F*************************************************************************
@@ -2687,11 +2685,11 @@
 static void
 aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
 {
-  Scsi_Cmnd *cmd = scb->cmd;
-  struct aic_dev_data *aic_dev = cmd->device->hostdata;
-  int tindex = TARGET_INDEX(cmd);
-  struct aic7xxx_scb *scbp;
-  unsigned char queue_depth;
+	struct scsi_cmnd *cmd = scb->cmd;
+	struct aic_dev_data *aic_dev = cmd->device->hostdata;
+	int tindex = TARGET_INDEX(cmd);
+	struct aic7xxx_scb *scbp;
+	unsigned char queue_depth;
 
   if (cmd->use_sg > 1)
   {
@@ -2891,7 +2889,7 @@
  *   aic7xxx_run_done_queue
  *
  * Description:
- *   Calls the aic7xxx_done() for the Scsi_Cmnd of each scb in the
+ *   Calls the aic7xxx_done() for the scsi_cmnd of each scb in the
  *   aborted list, and adds each scb to the free list.  If complete
  *   is TRUE, we also process the commands complete list.
  *-F*************************************************************************/
@@ -3826,9 +3824,9 @@
 static void
 aic7xxx_calculate_residual (struct aic7xxx_host *p, struct aic7xxx_scb *scb)
 {
-  struct aic7xxx_hwscb *hscb;
-  Scsi_Cmnd *cmd;
-  int actual, i;
+	struct aic7xxx_hwscb *hscb;
+	struct scsi_cmnd *cmd;
+	int actual, i;
 
   cmd = scb->cmd;
   hscb = scb->hscb;
@@ -4219,20 +4217,20 @@
 
     case BAD_STATUS:
       {
-        unsigned char scb_index;
-        struct aic7xxx_hwscb *hscb;
-        Scsi_Cmnd *cmd;
+	unsigned char scb_index;
+	struct aic7xxx_hwscb *hscb;
+	struct scsi_cmnd *cmd;
 
-        /* The sequencer will notify us when a command has an error that
-         * would be of interest to the kernel.  This allows us to leave
-         * the sequencer running in the common case of command completes
-         * without error.  The sequencer will have DMA'd the SCB back
-         * up to us, so we can reference the drivers SCB array.
-         *
-         * Set the default return value to 0 indicating not to send
-         * sense.  The sense code will change this if needed and this
-         * reduces code duplication.
-         */
+	/* The sequencer will notify us when a command has an error that
+	 * would be of interest to the kernel.  This allows us to leave
+	 * the sequencer running in the common case of command completes
+	 * without error.  The sequencer will have DMA'd the SCB back
+	 * up to us, so we can reference the drivers SCB array.
+	 *
+	 * Set the default return value to 0 indicating not to send
+	 * sense.  The sense code will change this if needed and this
+	 * reduces code duplication.
+	 */
         aic_outb(p, 0, RETURN_1);
         scb_index = aic_inb(p, SCB_TAG);
         if (scb_index > p->scb_data->numscbs)
@@ -5800,9 +5798,9 @@
   }
   else if ((status & SELTO) != 0)
   {
-    unsigned char scbptr;
-    unsigned char nextscb;
-    Scsi_Cmnd *cmd;
+	unsigned char scbptr;
+	unsigned char nextscb;
+	struct scsi_cmnd *cmd;
 
     scbptr = aic_inb(p, WAITING_SCBH);
     if (scbptr > p->scb_data->maxhscbs)
@@ -5941,11 +5939,11 @@
     /*
      * Determine the bus phase and queue an appropriate message.
      */
-    char  *phase;
-    Scsi_Cmnd *cmd;
-    unsigned char mesg_out = MSG_NOOP;
-    unsigned char lastphase = aic_inb(p, LASTPHASE);
-    unsigned char sstat2 = aic_inb(p, SSTAT2);
+	char  *phase;
+	struct scsi_cmnd *cmd;
+	unsigned char mesg_out = MSG_NOOP;
+	unsigned char lastphase = aic_inb(p, LASTPHASE);
+	unsigned char sstat2 = aic_inb(p, SSTAT2);
 
     cmd = scb->cmd;
     switch (lastphase)
@@ -6248,10 +6246,10 @@
 static void
 aic7xxx_handle_command_completion_intr(struct aic7xxx_host *p)
 {
-  struct aic7xxx_scb *scb = NULL;
-  struct aic_dev_data *aic_dev;
-  Scsi_Cmnd *cmd;
-  unsigned char scb_index, tindex;
+	struct aic7xxx_scb *scb = NULL;
+	struct aic_dev_data *aic_dev;
+	struct scsi_cmnd *cmd;
+	unsigned char scb_index, tindex;
 
 #ifdef AIC7XXX_VERBOSE_DEBUGGING
   if( (p->isr_count < 16) && (aic7xxx_verbose > 0xffff) )
@@ -6347,12 +6345,12 @@
  *   SCSI controller interrupt handler.
  *-F*************************************************************************/
 static void
-aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
+aic7xxx_isr(void *dev_id)
 {
   struct aic7xxx_host *p;
   unsigned char intstat;
 
-  p = (struct aic7xxx_host *)dev_id;
+  p = dev_id;
 
   /*
    * Just a few sanity checks.  Make sure that we have an int pending.
@@ -6479,7 +6477,7 @@
  *   anything like it, please inform the Gross Hack Police immediately
  *-F*************************************************************************/
 static irqreturn_t
-do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
+do_aic7xxx_isr(int irq, void *dev_id)
 {
   unsigned long cpu_flags;
   struct aic7xxx_host *p;
@@ -6491,7 +6489,7 @@
   p->flags |= AHC_IN_ISR;
   do
   {
-    aic7xxx_isr(irq, dev_id, regs);
+    aic7xxx_isr(dev_id);
   } while ( (aic_inb(p, INTSTAT) & INT_PEND) );
   aic7xxx_done_cmds_complete(p);
   aic7xxx_run_waiting_queues(p);
@@ -10131,9 +10129,8 @@
  * Description:
  *   Build a SCB.
  *-F*************************************************************************/
-static void
-aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
-    struct aic7xxx_scb *scb)
+static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd,
+			     struct aic7xxx_scb *scb)
 {
   unsigned short mask;
   struct aic7xxx_hwscb *hscb;
@@ -10285,8 +10282,7 @@
  * Description:
  *   Queue a SCB to the controller.
  *-F*************************************************************************/
-static int
-aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
+static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
 {
   struct aic7xxx_host *p;
   struct aic7xxx_scb *scb;
@@ -10319,11 +10315,11 @@
   }
   scb->cmd = cmd;
 
-  /*
-   * Make sure the Scsi_Cmnd pointer is saved, the struct it points to
-   * is set up properly, and the parity error flag is reset, then send
-   * the SCB to the sequencer and watch the fun begin.
-   */
+	/*
+	* Make sure the scsi_cmnd pointer is saved, the struct it points to
+	* is set up properly, and the parity error flag is reset, then send
+	* the SCB to the sequencer and watch the fun begin.
+	*/
   aic7xxx_position(cmd) = scb->hscb->tag;
   cmd->scsi_done = fn;
   cmd->result = DID_OK;
@@ -10356,8 +10352,7 @@
  *   aborted, then we will reset the channel and have all devices renegotiate.
  *   Returns an enumerated type that indicates the status of the operation.
  *-F*************************************************************************/
-static int
-__aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
+static int __aic7xxx_bus_device_reset(struct scsi_cmnd *cmd)
 {
   struct aic7xxx_host  *p;
   struct aic7xxx_scb   *scb;
@@ -10382,7 +10377,7 @@
 
   hscb = scb->hscb;
 
-  aic7xxx_isr(p->irq, (void *)p, NULL);
+  aic7xxx_isr(p);
   aic7xxx_done_cmds_complete(p);
   /* If the command was already complete or just completed, then we didn't
    * do a reset, return FAILED */
@@ -10550,8 +10545,7 @@
     return SUCCESS;
 }
 
-static int
-aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
+static int aic7xxx_bus_device_reset(struct scsi_cmnd *cmd)
 {
       int rc;
 
@@ -10570,8 +10564,7 @@
  * Description:
  *   Abort the current SCSI command(s).
  *-F*************************************************************************/
-static void
-aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
+static void aic7xxx_panic_abort(struct aic7xxx_host *p, struct scsi_cmnd *cmd)
 {
 
   printk("aic7xxx driver version %s\n", AIC7XXX_C_VERSION);
@@ -10595,8 +10588,7 @@
  * Description:
  *   Abort the current SCSI command(s).
  *-F*************************************************************************/
-static int
-__aic7xxx_abort(Scsi_Cmnd *cmd)
+static int __aic7xxx_abort(struct scsi_cmnd *cmd)
 {
   struct aic7xxx_scb  *scb = NULL;
   struct aic7xxx_host *p;
@@ -10616,7 +10608,7 @@
   else
     return FAILED;
 
-  aic7xxx_isr(p->irq, (void *)p, NULL);
+  aic7xxx_isr(p);
   aic7xxx_done_cmds_complete(p);
   /* If the command was already complete or just completed, then we didn't
    * do a reset, return FAILED */
@@ -10813,8 +10805,7 @@
   return SUCCESS;
 }
 
-static int
-aic7xxx_abort(Scsi_Cmnd *cmd)
+static int aic7xxx_abort(struct scsi_cmnd *cmd)
 {
 	int rc;
 
@@ -10836,8 +10827,7 @@
  *   DEVICE RESET message - on the offending target before pulling
  *   the SCSI bus reset line.
  *-F*************************************************************************/
-static int
-aic7xxx_reset(Scsi_Cmnd *cmd)
+static int aic7xxx_reset(struct scsi_cmnd *cmd)
 {
   struct aic7xxx_scb *scb;
   struct aic7xxx_host *p;
@@ -10873,7 +10863,7 @@
 
   while((aic_inb(p, INTSTAT) & INT_PEND) && !(p->flags & AHC_IN_ISR))
   {
-    aic7xxx_isr(p->irq, p, (void *)NULL );
+    aic7xxx_isr(p);
     pause_sequencer(p);
   }
   aic7xxx_done_cmds_complete(p);
diff --git a/drivers/scsi/aic94xx/Kconfig b/drivers/scsi/aic94xx/Kconfig
index 0ed391d..c83fe75 100644
--- a/drivers/scsi/aic94xx/Kconfig
+++ b/drivers/scsi/aic94xx/Kconfig
@@ -28,6 +28,7 @@
 	tristate "Adaptec AIC94xx SAS/SATA support"
 	depends on PCI
 	select SCSI_SAS_LIBSAS
+	select FW_LOADER
 	help
 		This driver supports Adaptec's SAS/SATA 3Gb/s 64 bit PCI-X
 		AIC94xx chip based host adapters.
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index 1d8c5e5..3c2d7a3 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -996,11 +996,10 @@
  * asd_hw_isr -- host adapter interrupt service routine
  * @irq: ignored
  * @dev_id: pointer to host adapter structure
- * @regs: ignored
  *
  * The ISR processes done list entries and level 3 error handling.
  */
-irqreturn_t asd_hw_isr(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t asd_hw_isr(int irq, void *dev_id)
 {
 	struct asd_ha_struct *asd_ha = dev_id;
 	u32 chimint = asd_read_reg_dword(asd_ha, CHIMINT);
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h
index 8498144..14319d1 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.h
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.h
@@ -371,7 +371,7 @@
 /* ---------- Function declarations ---------- */
 
 int  asd_init_hw(struct asd_ha_struct *asd_ha);
-irqreturn_t asd_hw_isr(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t asd_hw_isr(int irq, void *dev_id);
 
 
 struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 734adc9..99743ca 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -309,11 +309,29 @@
 }
 static DEVICE_ATTR(pcba_sn, S_IRUGO, asd_show_dev_pcba_sn, NULL);
 
-static void asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
+static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 {
-	device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
-	device_create_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
-	device_create_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
+	int err;
+
+	err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+	if (err)
+		return err;
+
+	err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
+	if (err)
+		goto err_rev;
+
+	err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
+	if (err)
+		goto err_biosb;
+
+	return 0;
+
+err_biosb:
+	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
+err_rev:
+	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+	return err;
 }
 
 static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
@@ -645,7 +663,9 @@
 	}
 	ASD_DPRINTK("escbs posted\n");
 
-	asd_create_dev_attrs(asd_ha);
+	err = asd_create_dev_attrs(asd_ha);
+	if (err)
+		goto Err_dev_attrs;
 
 	err = asd_register_sas_ha(asd_ha);
 	if (err)
@@ -668,6 +688,7 @@
 	asd_unregister_sas_ha(asd_ha);
 Err_reg_sas:
 	asd_remove_dev_attrs(asd_ha);
+Err_dev_attrs:
 Err_escbs:
 	asd_disable_ints(asd_ha);
 	free_irq(dev->irq, asd_ha);
@@ -754,9 +775,9 @@
 }
 static DRIVER_ATTR(version, S_IRUGO, asd_version_show, NULL);
 
-static void asd_create_driver_attrs(struct device_driver *driver)
+static int asd_create_driver_attrs(struct device_driver *driver)
 {
-	driver_create_file(driver, &driver_attr_version);
+	return driver_create_file(driver, &driver_attr_version);
 }
 
 static void asd_remove_driver_attrs(struct device_driver *driver)
@@ -834,10 +855,14 @@
 	if (err)
 		goto out_release_transport;
 
-	asd_create_driver_attrs(&aic94xx_pci_driver.driver);
+	err = asd_create_driver_attrs(&aic94xx_pci_driver.driver);
+	if (err)
+		goto out_unregister_pcidrv;
 
 	return err;
 
+ out_unregister_pcidrv:
+	pci_unregister_driver(&aic94xx_pci_driver);
  out_release_transport:
 	sas_release_transport(aic94xx_transport_template);
  out_destroy_caches:
diff --git a/drivers/scsi/amiga7xx.h b/drivers/scsi/amiga7xx.h
index 1b63759..7cd63a9 100644
--- a/drivers/scsi/amiga7xx.h
+++ b/drivers/scsi/amiga7xx.h
@@ -8,7 +8,7 @@
 int NCR53c7xx_abort(Scsi_Cmnd *);
 int NCR53c7x0_release (struct Scsi_Host *);
 int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+void NCR53c7x0_intr(int irq, void *dev_id);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 3
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 475f978..086cc97 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -147,8 +147,7 @@
 	.shutdown		= arcmsr_shutdown
 };
 
-static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id,
-	struct pt_regs *regs)
+static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
 {
 	irqreturn_t handle_state;
 	struct AdapterControlBlock *acb;
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 7621e3f..9cf902b 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -194,7 +194,8 @@
 unsigned int sdtr_period = SDTR_PERIOD;
 unsigned int sdtr_size   = SDTR_SIZE;
 
-static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
+static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
+			   unsigned int result);
 static int acornscsi_reconnect_finish(AS_Host *host);
 static void acornscsi_dma_cleanup(AS_Host *host);
 static void acornscsi_abortcmd(AS_Host *host, unsigned char tag);
@@ -712,7 +713,7 @@
 intr_ret_t acornscsi_kick(AS_Host *host)
 {
     int from_queue = 0;
-    Scsi_Cmnd *SCpnt;
+    struct scsi_cmnd *SCpnt;
 
     /* first check to see if a command is waiting to be executed */
     SCpnt = host->origSCpnt;
@@ -796,15 +797,15 @@
 }    
 
 /*
- * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
+ * Function: void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, unsigned int result)
  * Purpose : complete processing for command
  * Params  : host   - interface that completed
  *	     result - driver byte of result
  */
-static
-void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
+static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
+			   unsigned int result)
 {
-    Scsi_Cmnd *SCpnt = *SCpntp;
+	struct scsi_cmnd *SCpnt = *SCpntp;
 
     /* clean up */
     sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
@@ -1318,7 +1319,7 @@
 static void
 acornscsi_sendcommand(AS_Host *host)
 {
-    Scsi_Cmnd *SCpnt = host->SCpnt;
+	struct scsi_cmnd *SCpnt = host->SCpnt;
 
     sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0);
     sbic_arm_writenext(host->scsi.io_port, 0);
@@ -1693,7 +1694,7 @@
 		acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
 		msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
 	    } else {
-		Scsi_Cmnd *SCpnt = host->SCpnt;
+		struct scsi_cmnd *SCpnt = host->SCpnt;
 
 		acornscsi_dma_cleanup(host);
 
@@ -2460,14 +2461,13 @@
 }
 
 /*
- * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
+ * Prototype: void acornscsi_intr(int irq, void *dev_id)
  * Purpose  : handle interrupts from Acorn SCSI card
  * Params   : irq    - interrupt number
  *	      dev_id - device specific data (AS_Host structure)
- *	      regs   - processor registers when interrupt occurred
  */
 static irqreturn_t
-acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
+acornscsi_intr(int irq, void *dev_id)
 {
     AS_Host *host = (AS_Host *)dev_id;
     intr_ret_t ret;
@@ -2509,13 +2509,14 @@
  */
 
 /*
- * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+ * Function : acornscsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
  * Purpose  : queues a SCSI command
  * Params   : cmd  - SCSI command
  *	      done - function called on completion, with pointer to command descriptor
  * Returns  : 0, or < 0 on error.
  */
-int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+int acornscsi_queuecmd(struct scsi_cmnd *SCpnt,
+		       void (*done)(struct scsi_cmnd *))
 {
     AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
 
@@ -2565,17 +2566,18 @@
 }
 
 /*
- * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
+ * Prototype: void acornscsi_reportstatus(struct scsi_cmnd **SCpntp1, struct scsi_cmnd **SCpntp2, int result)
  * Purpose  : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
  * Params   : SCpntp1 - pointer to command to return
  *	      SCpntp2 - pointer to command to check
  *	      result  - result to pass back to mid-level done function
  * Returns  : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2.
  */
-static inline
-void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
+static inline void acornscsi_reportstatus(struct scsi_cmnd **SCpntp1,
+					  struct scsi_cmnd **SCpntp2,
+					  int result)
 {
-    Scsi_Cmnd *SCpnt = *SCpntp1;
+	struct scsi_cmnd *SCpnt = *SCpntp1;
 
     if (SCpnt) {
 	*SCpntp1 = NULL;
@@ -2591,13 +2593,12 @@
 enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
 
 /*
- * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt)
+ * Prototype: enum res acornscsi_do_abort(struct scsi_cmnd *SCpnt)
  * Purpose  : abort a command on this host
  * Params   : SCpnt - command to abort
  * Returns  : our abort status
  */
-static enum res_abort
-acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
+static enum res_abort acornscsi_do_abort(AS_Host *host, struct scsi_cmnd *SCpnt)
 {
 	enum res_abort res = res_not_running;
 
@@ -2684,12 +2685,12 @@
 }
 
 /*
- * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt)
+ * Prototype: int acornscsi_abort(struct scsi_cmnd *SCpnt)
  * Purpose  : abort a command on this host
  * Params   : SCpnt - command to abort
  * Returns  : one of SCSI_ABORT_ macros
  */
-int acornscsi_abort(Scsi_Cmnd *SCpnt)
+int acornscsi_abort(struct scsi_cmnd *SCpnt)
 {
 	AS_Host *host = (AS_Host *) SCpnt->device->host->hostdata;
 	int result;
@@ -2770,16 +2771,16 @@
 }
 
 /*
- * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+ * Prototype: int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags)
  * Purpose  : reset a command on this host/reset this host
  * Params   : SCpnt  - command causing reset
  *	      result - what type of reset to perform
  * Returns  : one of SCSI_RESET_ macros
  */
-int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags)
 {
-    AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
-    Scsi_Cmnd *SCptr;
+	AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
+	struct scsi_cmnd *SCptr;
     
     host->stats.resets += 1;
 
diff --git a/drivers/scsi/arm/acornscsi.h b/drivers/scsi/arm/acornscsi.h
index 2142290..d11424b 100644
--- a/drivers/scsi/arm/acornscsi.h
+++ b/drivers/scsi/arm/acornscsi.h
@@ -277,8 +277,8 @@
 typedef struct acornscsi_hostdata {
     /* miscellaneous */
     struct Scsi_Host	*host;			/* host					*/
-    Scsi_Cmnd		*SCpnt;			/* currently processing command		*/
-    Scsi_Cmnd		*origSCpnt;		/* original connecting command		*/
+    struct scsi_cmnd	*SCpnt;			/* currently processing command		*/
+    struct scsi_cmnd	*origSCpnt;		/* original connecting command		*/
 
     /* driver information */
     struct {
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 719af0d..19edd9c 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -137,10 +137,9 @@
  * Purpose  : handle interrupts from Cumana SCSI 2 card
  * Params   : irq    - interrupt number
  *	      dev_id - user-defined (Scsi_Host structure)
- *	      regs   - processor registers at interrupt
  */
 static irqreturn_t
-cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs)
+cumanascsi_2_intr(int irq, void *dev_id)
 {
 	struct cumanascsi2_info *info = dev_id;
 
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index dcbb4b2..3f876fb 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -138,10 +138,9 @@
  * Purpose  : handle interrupts from EESOX SCSI card
  * Params   : irq    - interrupt number
  *	      dev_id - user-defined (Scsi_Host structure)
- *	      regs   - processor registers at interrupt
  */
 static irqreturn_t
-eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
+eesoxscsi_intr(int irq, void *dev_id)
 {
 	struct eesoxscsi_info *info = dev_id;
 
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 4cf7afc..e05f0c2 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -297,8 +297,8 @@
 	printk("scsi%d.%c: %s", info->host->host_no, target, buf);
 }
 
-static void
-fas216_log_command(FAS216_Info *info, int level, Scsi_Cmnd *SCpnt, char *fmt, ...)
+static void fas216_log_command(FAS216_Info *info, int level,
+			       struct scsi_cmnd *SCpnt, char *fmt, ...)
 {
 	va_list args;
 
@@ -1662,7 +1662,7 @@
 	return handled;
 }
 
-static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+static void __fas216_start_command(FAS216_Info *info, struct scsi_cmnd *SCpnt)
 {
 	int tot_msglen;
 
@@ -1754,7 +1754,7 @@
 	return info->device[target].parity_check;
 }
 
-static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+static void fas216_start_command(FAS216_Info *info, struct scsi_cmnd *SCpnt)
 {
 	int disconnect_ok;
 
@@ -1808,7 +1808,7 @@
 	__fas216_start_command(info, SCpnt);
 }
 
-static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+static void fas216_allocate_tag(FAS216_Info *info, struct scsi_cmnd *SCpnt)
 {
 #ifdef SCSI2_TAG
 	/*
@@ -1842,7 +1842,8 @@
 	}
 }
 
-static void fas216_do_bus_device_reset(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+static void fas216_do_bus_device_reset(FAS216_Info *info,
+				       struct scsi_cmnd *SCpnt)
 {
 	struct message *msg;
 
@@ -1890,7 +1891,7 @@
  */
 static void fas216_kick(FAS216_Info *info)
 {
-	Scsi_Cmnd *SCpnt = NULL;
+	struct scsi_cmnd *SCpnt = NULL;
 #define TYPE_OTHER	0
 #define TYPE_RESET	1
 #define TYPE_QUEUE	2
@@ -1978,8 +1979,8 @@
 /*
  * Clean up from issuing a BUS DEVICE RESET message to a device.
  */
-static void
-fas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
+static void fas216_devicereset_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,
+				    unsigned int result)
 {
 	fas216_log(info, LOG_ERROR, "fas216 device reset complete");
 
@@ -1996,8 +1997,8 @@
  *
  * Finish processing automatic request sense command
  */
-static void
-fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
+static void fas216_rq_sns_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,
+			       unsigned int result)
 {
 	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
 		   "request sense complete, result=0x%04x%02x%02x",
@@ -2030,7 +2031,7 @@
  * Finish processing of standard command
  */
 static void
-fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
+fas216_std_done(FAS216_Info *info, struct scsi_cmnd *SCpnt, unsigned int result)
 {
 	info->stats.fins += 1;
 
@@ -2142,8 +2143,8 @@
  */
 static void fas216_done(FAS216_Info *info, unsigned int result)
 {
-	void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int);
-	Scsi_Cmnd *SCpnt;
+	void (*fn)(FAS216_Info *, struct scsi_cmnd *, unsigned int);
+	struct scsi_cmnd *SCpnt;
 	unsigned long flags;
 
 	fas216_checkmagic(info);
@@ -2182,7 +2183,7 @@
 	info->device[SCpnt->device->id].parity_check = 0;
 	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
 
-	fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble;
+	fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble;
 	fn(info, SCpnt, result);
 
 	if (info->scsi.irq != NO_IRQ) {
@@ -2207,7 +2208,8 @@
  * Returns: 0 on success, else error.
  * Notes: io_request_lock is held, interrupts are disabled.
  */
-int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+int fas216_queue_command(struct scsi_cmnd *SCpnt,
+			 void (*done)(struct scsi_cmnd *))
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result;
@@ -2254,7 +2256,7 @@
  *
  * Trigger restart of a waiting thread in fas216_command
  */
-static void fas216_internal_done(Scsi_Cmnd *SCpnt)
+static void fas216_internal_done(struct scsi_cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
@@ -2271,7 +2273,8 @@
  * Returns: scsi result code.
  * Notes: io_request_lock is held, interrupts are disabled.
  */
-int fas216_noqueue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+int fas216_noqueue_command(struct scsi_cmnd *SCpnt,
+			   void (*done)(struct scsi_cmnd *))
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
@@ -2350,7 +2353,8 @@
  * Decide how to abort a command.
  * Returns: abort status
  */
-static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
+static enum res_find fas216_find_command(FAS216_Info *info,
+					 struct scsi_cmnd *SCpnt)
 {
 	enum res_find res = res_failed;
 
@@ -2417,7 +2421,7 @@
  * Returns: FAILED if unable to abort
  * Notes: io_request_lock is taken, and irqs are disabled
  */
-int fas216_eh_abort(Scsi_Cmnd *SCpnt)
+int fas216_eh_abort(struct scsi_cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result = FAILED;
@@ -2474,7 +2478,7 @@
  * Notes: We won't be re-entered, so we'll only have one device
  * reset on the go at one time.
  */
-int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
+int fas216_eh_device_reset(struct scsi_cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	unsigned long flags;
@@ -2555,7 +2559,7 @@
  * Returns: FAILED if unable to reset.
  * Notes: Further commands are blocked.
  */
-int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
+int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	unsigned long flags;
@@ -2655,7 +2659,7 @@
  * Returns: FAILED if unable to reset.
  * Notes: io_request_lock is taken, and irqs are disabled
  */
-int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
+int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
index 540914d..00e5f05 100644
--- a/drivers/scsi/arm/fas216.h
+++ b/drivers/scsi/arm/fas216.h
@@ -218,11 +218,11 @@
 	unsigned long		magic_start;
 	spinlock_t		host_lock;
 	struct Scsi_Host	*host;			/* host					*/
-	Scsi_Cmnd		*SCpnt;			/* currently processing command		*/
-	Scsi_Cmnd		*origSCpnt;		/* original connecting command		*/
-	Scsi_Cmnd		*reqSCpnt;		/* request sense command		*/
-	Scsi_Cmnd		*rstSCpnt;		/* reset command			*/
-	Scsi_Cmnd		*pending_SCpnt[8];	/* per-device pending commands		*/
+	struct scsi_cmnd	*SCpnt;			/* currently processing command		*/
+	struct scsi_cmnd	*origSCpnt;		/* original connecting command		*/
+	struct scsi_cmnd	*reqSCpnt;		/* request sense command		*/
+	struct scsi_cmnd	*rstSCpnt;		/* reset command			*/
+	struct scsi_cmnd	*pending_SCpnt[8];	/* per-device pending commands		*/
 	int			next_pending;		/* next pending device			*/
 
 	/*
@@ -328,21 +328,23 @@
  */
 extern int fas216_add (struct Scsi_Host *instance, struct device *dev);
 
-/* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+/* Function: int fas216_queue_command(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
  * Purpose : queue a command for adapter to process.
  * Params  : SCpnt - Command to queue
  *	     done  - done function to call once command is complete
  * Returns : 0 - success, else error
  */
-extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int fas216_queue_command(struct scsi_cmnd *,
+				void (*done)(struct scsi_cmnd *));
 
-/* Function: int fas216_noqueue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+/* Function: int fas216_noqueue_command(istruct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
  * Purpose : queue a command for adapter to process, and process it to completion.
  * Params  : SCpnt - Command to queue
  *	     done  - done function to call once command is complete
  * Returns : 0 - success, else error
  */
-extern int fas216_noqueue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int fas216_noqueue_command(struct scsi_cmnd *,
+				  void (*done)(struct scsi_cmnd *));
 
 /* Function: irqreturn_t fas216_intr (FAS216_Info *info)
  * Purpose : handle interrupts from the interface to progress a command
@@ -363,32 +365,32 @@
 extern int fas216_print_stats(FAS216_Info *info, char *buffer);
 extern int fas216_print_devices(FAS216_Info *info, char *buffer);
 
-/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
+/* Function: int fas216_eh_abort(struct scsi_cmnd *SCpnt)
  * Purpose : abort this command
  * Params  : SCpnt - command to abort
  * Returns : FAILED if unable to abort
  */
-extern int fas216_eh_abort(Scsi_Cmnd *SCpnt);
+extern int fas216_eh_abort(struct scsi_cmnd *SCpnt);
 
-/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
+/* Function: int fas216_eh_device_reset(struct scsi_cmnd *SCpnt)
  * Purpose : Reset the device associated with this command
  * Params  : SCpnt - command specifing device to reset
  * Returns : FAILED if unable to reset
  */
-extern int fas216_eh_device_reset(Scsi_Cmnd *SCpnt);
+extern int fas216_eh_device_reset(struct scsi_cmnd *SCpnt);
 
-/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
+/* Function: int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt)
  * Purpose : Reset the complete bus associated with this command
  * Params  : SCpnt - command specifing bus to reset
  * Returns : FAILED if unable to reset
  */
-extern int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt);
+extern int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt);
 
-/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
+/* Function: int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
  * Purpose : Reset the host associated with this command
  * Params  : SCpnt - command specifing host to reset
  * Returns : FAILED if unable to reset
  */
-extern int fas216_eh_host_reset(Scsi_Cmnd *SCpnt);
+extern int fas216_eh_host_reset(struct scsi_cmnd *SCpnt);
 
 #endif /* FAS216_H */
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index b2c346a..ce159c1 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -112,10 +112,8 @@
  * Purpose  : handle interrupts from Powertec SCSI card
  * Params   : irq    - interrupt number
  *	      dev_id - user-defined (Scsi_Host structure)
- *	      regs   - processor registers at interrupt
  */
-static irqreturn_t
-powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t powertecscsi_intr(int irq, void *dev_id)
 {
 	struct powertec_info *info = dev_id;
 
diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
index 8caa590..cb11cce 100644
--- a/drivers/scsi/arm/queue.c
+++ b/drivers/scsi/arm/queue.c
@@ -29,7 +29,7 @@
 
 typedef struct queue_entry {
 	struct list_head   list;
-	Scsi_Cmnd	   *SCpnt;
+	struct scsi_cmnd   *SCpnt;
 #ifdef DEBUG
 	unsigned long	   magic;
 #endif
@@ -96,14 +96,14 @@
      
 
 /*
- * Function: int queue_add_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt, int head)
+ * Function: int __queue_add(Queue_t *queue, struct scsi_cmnd *SCpnt, int head)
  * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head.
  * Params  : queue - destination queue
  *	     SCpnt - command to add
  *	     head  - add command to head of queue
  * Returns : 0 on error, !0 on success
  */
-int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head)
+int __queue_add(Queue_t *queue, struct scsi_cmnd *SCpnt, int head)
 {
 	unsigned long flags;
 	struct list_head *l;
@@ -134,7 +134,7 @@
 	return ret;
 }
 
-static Scsi_Cmnd *__queue_remove(Queue_t *queue, struct list_head *ent)
+static struct scsi_cmnd *__queue_remove(Queue_t *queue, struct list_head *ent)
 {
 	QE_t *q;
 
@@ -152,17 +152,17 @@
 }
 
 /*
- * Function: Scsi_Cmnd *queue_remove_exclude (queue, exclude)
+ * Function: struct scsi_cmnd *queue_remove_exclude (queue, exclude)
  * Purpose : remove a SCSI command from a queue
  * Params  : queue   - queue to remove command from
  *	     exclude - bit array of target&lun which is busy
- * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
+ * Returns : struct scsi_cmnd if successful (and a reference), or NULL if no command available
  */
-Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude)
+struct scsi_cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude)
 {
 	unsigned long flags;
 	struct list_head *l;
-	Scsi_Cmnd *SCpnt = NULL;
+	struct scsi_cmnd *SCpnt = NULL;
 
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
@@ -178,15 +178,15 @@
 }
 
 /*
- * Function: Scsi_Cmnd *queue_remove (queue)
+ * Function: struct scsi_cmnd *queue_remove (queue)
  * Purpose : removes first SCSI command from a queue
  * Params  : queue   - queue to remove command from
- * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
+ * Returns : struct scsi_cmnd if successful (and a reference), or NULL if no command available
  */
-Scsi_Cmnd *queue_remove(Queue_t *queue)
+struct scsi_cmnd *queue_remove(Queue_t *queue)
 {
 	unsigned long flags;
-	Scsi_Cmnd *SCpnt = NULL;
+	struct scsi_cmnd *SCpnt = NULL;
 
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	if (!list_empty(&queue->head))
@@ -197,19 +197,20 @@
 }
 
 /*
- * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
+ * Function: struct scsi_cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
  * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
  * Params  : queue  - queue to remove command from
  *	     target - target that we want
  *	     lun    - lun on device
  *	     tag    - tag on device
- * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
+ * Returns : struct scsi_cmnd if successful, or NULL if no command satisfies requirements
  */
-Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag)
+struct scsi_cmnd *queue_remove_tgtluntag(Queue_t *queue, int target, int lun,
+					 int tag)
 {
 	unsigned long flags;
 	struct list_head *l;
-	Scsi_Cmnd *SCpnt = NULL;
+	struct scsi_cmnd *SCpnt = NULL;
 
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
@@ -275,13 +276,13 @@
 }
 
 /*
- * Function: int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt)
+ * Function: int queue_remove_cmd(Queue_t *queue, struct scsi_cmnd *SCpnt)
  * Purpose : remove a specific command from the queues
  * Params  : queue - queue to look in
  *	     SCpnt - command to find
  * Returns : 0 if not found
  */
-int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt)
+int queue_remove_cmd(Queue_t *queue, struct scsi_cmnd *SCpnt)
 {
 	unsigned long flags;
 	struct list_head *l;
diff --git a/drivers/scsi/arm/queue.h b/drivers/scsi/arm/queue.h
index 0c9dec4..3c519c9 100644
--- a/drivers/scsi/arm/queue.h
+++ b/drivers/scsi/arm/queue.h
@@ -32,46 +32,48 @@
 extern void queue_free (Queue_t *queue);
 
 /*
- * Function: Scsi_Cmnd *queue_remove (queue)
+ * Function: struct scsi_cmnd *queue_remove (queue)
  * Purpose : removes first SCSI command from a queue
  * Params  : queue   - queue to remove command from
- * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
+ * Returns : struct scsi_cmnd if successful (and a reference), or NULL if no command available
  */
-extern Scsi_Cmnd *queue_remove (Queue_t *queue);
+extern struct scsi_cmnd *queue_remove (Queue_t *queue);
 
 /*
- * Function: Scsi_Cmnd *queue_remove_exclude_ref (queue, exclude)
+ * Function: struct scsi_cmnd *queue_remove_exclude_ref (queue, exclude)
  * Purpose : remove a SCSI command from a queue
  * Params  : queue   - queue to remove command from
  *	     exclude - array of busy LUNs
- * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
+ * Returns : struct scsi_cmnd if successful (and a reference), or NULL if no command available
  */
-extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned long *exclude);
+extern struct scsi_cmnd *queue_remove_exclude(Queue_t *queue,
+					      unsigned long *exclude);
 
 #define queue_add_cmd_ordered(queue,SCpnt) \
 	__queue_add(queue,SCpnt,(SCpnt)->cmnd[0] == REQUEST_SENSE)
 #define queue_add_cmd_tail(queue,SCpnt) \
 	__queue_add(queue,SCpnt,0)
 /*
- * Function: int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head)
+ * Function: int __queue_add(Queue_t *queue, struct scsi_cmnd *SCpnt, int head)
  * Purpose : Add a new command onto a queue
  * Params  : queue - destination queue
  *	     SCpnt - command to add
  *	     head  - add command to head of queue
  * Returns : 0 on error, !0 on success
  */
-extern int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head);
+extern int __queue_add(Queue_t *queue, struct scsi_cmnd *SCpnt, int head);
 
 /*
- * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
+ * Function: struct scsi_cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
  * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
  * Params  : queue  - queue to remove command from
  *	     target - target that we want
  *	     lun    - lun on device
  *	     tag    - tag on device
- * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
+ * Returns : struct scsi_cmnd if successful, or NULL if no command satisfies requirements
  */
-extern Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag);
+extern struct scsi_cmnd *queue_remove_tgtluntag(Queue_t *queue, int target,
+						int lun, int tag);
 
 /*
  * Function: queue_remove_all_target(queue, target)
@@ -94,12 +96,12 @@
 extern int queue_probetgtlun (Queue_t *queue, int target, int lun);
 
 /*
- * Function: int queue_remove_cmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
+ * Function: int queue_remove_cmd (Queue_t *queue, struct scsi_cmnd *SCpnt)
  * Purpose : remove a specific command from the queues
  * Params  : queue - queue to look in
  *	     SCpnt - command to find
  * Returns : 0 if not found
  */
-int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt);
+int queue_remove_cmd(Queue_t *queue, struct scsi_cmnd *SCpnt);
 
 #endif /* QUEUE_H */
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index 8c2600f..3a39579 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -66,7 +66,7 @@
 	SCp->this_residual -= 1;
 }
 
-static inline void init_SCp(Scsi_Cmnd *SCpnt)
+static inline void init_SCp(struct scsi_cmnd *SCpnt)
 {
 	memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer));
 
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index e397129..0f920c8 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -1262,7 +1262,7 @@
  *
  */
 
-static irqreturn_t NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t NCR5380_intr (int irq, void *dev_id)
 {
     struct Scsi_Host *instance = first_instance;
     int done = 1, handled = 0;
diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c
index 8d5d2a5..cdc710e 100644
--- a/drivers/scsi/atari_dma_emul.c
+++ b/drivers/scsi/atari_dma_emul.c
@@ -110,7 +110,7 @@
 }
 
 /*
- * void hades_dma_emulator(int irq, void *dummy, struct pt_regs *fp)
+ * void hades_dma_emulator(int irq, void *dummy)
  * 
  * This code emulates TT SCSI DMA on the Hades.
  * 
@@ -140,7 +140,7 @@
  *    increased with one.
  */
 
-static irqreturn_t hades_dma_emulator(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t hades_dma_emulator(int irq, void *dummy)
 {
 	unsigned long dma_base;
 	register unsigned long dma_cnt asm ("d3");
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index e1be4a4..dfb1bcf 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -194,8 +194,8 @@
 static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
                                          Scsi_Cmnd *cmd, int write_flag );
 #endif
-static irqreturn_t scsi_tt_intr( int irq, void *dummy, struct pt_regs *fp);
-static irqreturn_t scsi_falcon_intr( int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_tt_intr( int irq, void *dummy);
+static irqreturn_t scsi_falcon_intr( int irq, void *dummy);
 static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
                                              hostdata );
 static void falcon_get_lock( void );
@@ -285,7 +285,7 @@
  * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
  * to clear the DMA int pending bit before it allows other level 6 interrupts.
  */
-static void scsi_dma_buserr (int irq, void *dummy, struct pt_regs *fp)
+static void scsi_dma_buserr (int irq, void *dummy)
 {
 	unsigned char	dma_stat = tt_scsi_dma.dma_ctrl;
 
@@ -314,7 +314,7 @@
 #endif
 
 
-static irqreturn_t scsi_tt_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_tt_intr (int irq, void *dummy)
 {
 #ifdef REAL_DMA
 	int dma_stat;
@@ -406,7 +406,7 @@
 }
 
 
-static irqreturn_t scsi_falcon_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
 {
 #ifdef REAL_DMA
 	int dma_stat;
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 0ec41f3..fec58cc 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -44,7 +44,7 @@
 static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
 static void tscam_885(void);
 
-static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
 {
 	unsigned long flags;
 	unsigned short int tmpcip, id;
diff --git a/drivers/scsi/bvme6000.h b/drivers/scsi/bvme6000.h
index 7c9c036..ea3e4b2 100644
--- a/drivers/scsi/bvme6000.h
+++ b/drivers/scsi/bvme6000.h
@@ -9,7 +9,7 @@
 int NCR53c7xx_abort(Scsi_Cmnd *);
 int NCR53c7x0_release (struct Scsi_Host *);
 int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+void NCR53c7x0_intr(int irq, void *dev_id);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 3
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index ff2b179..e95b367 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1219,7 +1219,7 @@
 			    	srb, srb->cmd, srb->cmd->pid,
 				srb->cmd->cmnd[0], srb->cmd->device->id,
 			       	srb->cmd->device->lun);
-		printk("  sglist=%p cnt=%i idx=%i len=%i\n",
+		printk("  sglist=%p cnt=%i idx=%i len=%zu\n",
 		       srb->segment_x, srb->sg_count, srb->sg_index,
 		       srb->total_xfer_length);
 		printk("  state=0x%04x status=0x%02x phase=0x%02x (%sconn.)\n",
@@ -1813,10 +1813,9 @@
 }
 
 
-static irqreturn_t dc395x_interrupt(int irq, void *dev_id,
-		struct pt_regs *regs)
+static irqreturn_t dc395x_interrupt(int irq, void *dev_id)
 {
-	struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)dev_id;
+	struct AdapterCtlBlk *acb = dev_id;
 	u16 scsi_status;
 	u8 dma_status;
 	irqreturn_t handled = IRQ_NONE;
@@ -4949,7 +4948,7 @@
  **/
 static int __init dc395x_module_init(void)
 {
-	return pci_module_init(&dc395x_driver);
+	return pci_register_driver(&dc395x_driver);
 }
 
 
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index eb32062..c29ccbc 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -94,9 +94,9 @@
 				 * via PIO.
 				 */
 
-static irqreturn_t scsi_dma_merr_int(int, void *, struct pt_regs *);
-static irqreturn_t scsi_dma_err_int(int, void *, struct pt_regs *);
-static irqreturn_t scsi_dma_int(int, void *, struct pt_regs *);
+static irqreturn_t scsi_dma_merr_int(int, void *);
+static irqreturn_t scsi_dma_err_int(int, void *);
+static irqreturn_t scsi_dma_int(int, void *);
 
 static int dec_esp_detect(struct scsi_host_template * tpnt);
 
@@ -307,7 +307,7 @@
 }
 
 /************************************************************* DMA Functions */
-static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id)
 {
 	printk("Got unexpected SCSI DMA Interrupt! < ");
 	printk("SCSI_DMA_MEMRDERR ");
@@ -316,14 +316,14 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t scsi_dma_err_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t scsi_dma_err_int(int irq, void *dev_id)
 {
 	/* empty */
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t scsi_dma_int(int irq, void *dev_id)
 {
 	u32 scsi_next_ptr;
 
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 879a266..fa738ec 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -155,7 +155,7 @@
 
 static int __init dmx3191d_init(void)
 {
-	return pci_module_init(&dmx3191d_pci_driver);
+	return pci_register_driver(&dmx3191d_pci_driver);
 }
 
 static void __exit dmx3191d_exit(void)
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index d84a281..b3fa7ed 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -47,21 +47,11 @@
  *	I2O Interface Objects
  */
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-
-#define DECLARE_MUTEX(name) struct semaphore name=MUTEX
-
-typedef struct wait_queue *adpt_wait_queue_head_t;
-#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) adpt_wait_queue_head_t wait = NULL
-typedef struct wait_queue adpt_wait_queue_t;
-#else
-
 #include <linux/wait.h>
 typedef wait_queue_head_t adpt_wait_queue_head_t;
 #define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD(wait)
 typedef wait_queue_t adpt_wait_queue_t;
 
-#endif
 /*
  * message structures
  */
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 7b3bd34..60b1b43 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -1989,7 +1989,7 @@
 }
 
 
-static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t adpt_isr(int irq, void *dev_id)
 {
 	struct scsi_cmnd* cmd;
 	adpt_hba* pHba = dev_id;
@@ -2212,7 +2212,7 @@
 	 */
 	host->io_port = 0;
 	host->n_io_port = 0;
-				/* see comments in hosts.h */
+				/* see comments in scsi_host.h */
 	host->max_id = 16;
 	host->max_lun = 256;
 	host->max_channel = pHba->top_scsi_channel + 1;
diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
index 2ad2a89..fd79068 100644
--- a/drivers/scsi/dpti.h
+++ b/drivers/scsi/dpti.h
@@ -44,7 +44,7 @@
 
 
 /*
- * struct scsi_host_template (see hosts.h)
+ * struct scsi_host_template (see scsi/scsi_host.h)
  */
 
 #define DPT_DRIVER_NAME	"Adaptec I2O RAID"
@@ -263,7 +263,7 @@
 static void adpt_i2o_sys_shutdown(void);
 static int adpt_init(void);
 static int adpt_i2o_build_sys_table(void);
-static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t adpt_isr(int irq, void *dev_id);
 #ifdef REBOOT_NOTIFIER
 static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p);
 #endif
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 0d5713d..5475672 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -82,7 +82,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include "dtc.h"
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index a5ff43b..2d38025 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -875,7 +875,7 @@
 /* But transfer orientation from the 16 bit data register is Little Endian */
 #define REG2H(x)   le16_to_cpu(x)
 
-static irqreturn_t do_interrupt_handler(int, void *, struct pt_regs *);
+static irqreturn_t do_interrupt_handler(int, void *);
 static void flush_dev(struct scsi_device *, unsigned long, struct hostdata *,
 		      unsigned int);
 static int do_trace = 0;
@@ -2555,8 +2555,7 @@
 	return IRQ_NONE;
 }
 
-static irqreturn_t do_interrupt_handler(int irq, void *shap,
-					struct pt_regs *regs)
+static irqreturn_t do_interrupt_handler(int irq, void *shap)
 {
 	struct Scsi_Host *shost;
 	unsigned int j;
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index d312633..2dbb66d 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -194,22 +194,21 @@
 	}
 }
 
-static irqreturn_t eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t eata_pio_int_handler(int irq, void *dev_id);
 
-static irqreturn_t do_eata_pio_int_handler(int irq, void *dev_id,
-						struct pt_regs *regs)
+static irqreturn_t do_eata_pio_int_handler(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = dev_id;
 	irqreturn_t ret;
 
 	spin_lock_irqsave(dev->host_lock, flags);
-	ret = eata_pio_int_handler(irq, dev_id, regs);
+	ret = eata_pio_int_handler(irq, dev_id);
 	spin_unlock_irqrestore(dev->host_lock, flags);
 	return ret;
 }
 
-static irqreturn_t eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t eata_pio_int_handler(int irq, void *dev_id)
 {
 	unsigned int eata_stat = 0xfffff;
 	struct scsi_cmnd *cmd;
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 5630868..2c2fe80 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -184,7 +184,7 @@
 };
 
 /* Forward declarations. */
-static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+static irqreturn_t esp_intr(int irq, void *dev_id);
 
 /* Debugging routines */
 struct esp_cmdstrings {
@@ -4282,7 +4282,7 @@
 }
 
 /* Service only the ESP described by dev_id. */
-static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+static irqreturn_t esp_intr(int irq, void *dev_id)
 {
 	struct esp *esp = dev_id;
 	unsigned long flags;
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index dde3edf..ef8285c 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -281,7 +281,7 @@
 
 #define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
 
-static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
 
 static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
@@ -617,7 +617,7 @@
 }
 
 /* only my_done needs to be protected  */
-static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
 {
 	unsigned long flags;
 	int status;
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index b0694dc..65e6e7b 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -278,9 +278,9 @@
 #include <linux/pci.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <scsi/scsicam.h>
 
-#include <asm/io.h>
 #include <asm/system.h>
 
 #include <scsi/scsi.h>
@@ -403,8 +403,7 @@
 static int               FIFO_Size = 0x2000; /* 8k FIFO for
 						pre-tmc18c30 chips */
 
-static irqreturn_t       do_fdomain_16x0_intr( int irq, void *dev_id,
-					    struct pt_regs * regs );
+static irqreturn_t       do_fdomain_16x0_intr( int irq, void *dev_id );
 /* Allow insmod parameters to be like LILO parameters.  For example:
    insmod fdomain fdomain=0x140,11 */
 static char * fdomain = NULL;
@@ -1094,8 +1093,7 @@
 #endif
 }
 
-static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id,
-					struct pt_regs * regs )
+static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 {
    unsigned long flags;
    int      status;
@@ -1738,6 +1736,15 @@
 };
 
 #ifndef PCMCIA
+
+static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl);
+
 #define driver_template fdomain_driver_template
 #include "scsi_module.c"
+
 #endif
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 0f3eb22..4bc14ad 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -424,7 +424,7 @@
 
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
-static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t gdth_interrupt(int irq, void *dev_id);
 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
 static int gdth_async_event(int hanum);
 static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
@@ -1804,7 +1804,7 @@
 
     gdth_from_wait = TRUE;
     do {
-        gdth_interrupt((int)ha->irq,ha,NULL);
+        gdth_interrupt((int)ha->irq,ha);
         if (wait_hanum==hanum && wait_index==index) {
             answer_found = TRUE;
             break;
@@ -3406,7 +3406,7 @@
 
 /* SCSI interface functions */
 
-static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
+static irqreturn_t gdth_interrupt(int irq,void *dev_id)
 {
     gdth_ha_str *ha2 = (gdth_ha_str *)dev_id;
     register gdth_ha_str *ha;
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index 47eae02..8c29eaf 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -936,18 +936,12 @@
     gdth_binfo_str      binfo;                  /* controller info */
     gdth_evt_data       dvr;                    /* event structure */
     spinlock_t          smp_lock;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     struct pci_dev      *pdev;
-#endif
     char                oem_name[8];
 #ifdef GDTH_DMA_STATISTICS
     ulong               dma32_cnt, dma64_cnt;   /* statistics: DMA buffer */
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     struct scsi_device         *sdev;
-#else
-    struct scsi_device         sdev;
-#endif
 } gdth_ha_str;
 
 /* structure for scsi_register(), SCSI bus != 0 */
@@ -1029,10 +1023,6 @@
 
 /* function prototyping */
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,int,int);
-#else
-int gdth_proc_info(char *,char **,off_t,int,int,int);
-#endif
 
 #endif
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 18dbe5c..2f6c113 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -24,7 +24,7 @@
 #define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base))
 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
-static irqreturn_t gvp11_intr (int irq, void *_instance, struct pt_regs *fp)
+static irqreturn_t gvp11_intr (int irq, void *_instance)
 {
     unsigned long flags;
     unsigned int status;
diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
deleted file mode 100644
index c27264b..0000000
--- a/drivers/scsi/hosts.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#warning "This file is obsolete, please use <scsi/scsi_host.h> instead"
-#include <scsi/scsi_host.h>
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 28bfb8f..bec83cb 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -431,7 +431,7 @@
 	writel(tag, &hba->iop->outbound_queue);
 }
 
-static irqreturn_t hptiop_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hptiop_intr(int irq, void *dev_id)
 {
 	struct hptiop_hba  *hba = dev_id;
 	int  handled;
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 2be1dc5..0e57fb6 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -497,8 +497,7 @@
 static int ldn_access_load(int, int);
 static int ldn_access_total_read_write(int);
 
-static irqreturn_t interrupt_handler(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t interrupt_handler(int irq, void *dev_id)
 {
 	int host_index, ihost_index;
 	unsigned int intr_reg;
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 01b8ac6..227c0f2 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -45,14 +45,11 @@
  * ibmvscsi_handle_event: - Interrupt handler for crq events
  * @irq:	number of irq to handle, not used
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
- * @regs:	pt_regs with registers
  *
  * Disables interrupts and schedules srp_task
  * Always returns IRQ_HANDLED
  */
-static irqreturn_t ibmvscsi_handle_event(int irq,
-					 void *dev_instance,
-					 struct pt_regs *regs)
+static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
 {
 	struct ibmvscsi_host_data *hostdata =
 	    (struct ibmvscsi_host_data *)dev_instance;
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 59a4097..312190a 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -829,7 +829,7 @@
  * but it _does_ need to be able to compile and run in an SMP kernel.)
  */
 
-static irqreturn_t in2000_intr(int irqnum, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t in2000_intr(int irqnum, void *dev_id)
 {
 	struct Scsi_Host *instance = dev_id;
 	struct IN2000_hostdata *hostdata;
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 9e10dac..afed293 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -142,8 +142,6 @@
 #define i91u_MAXQUEUE		2
 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"
 
-#define INI_VENDOR_ID   0x1101	/* Initio's PCI vendor ID       */
-#define DMX_VENDOR_ID	0x134a	/* Domex's PCI vendor ID	*/
 #define I950_DEVICE_ID	0x9500	/* Initio's inic-950 product ID   */
 #define I940_DEVICE_ID	0x9400	/* Initio's inic-940 product ID   */
 #define I935_DEVICE_ID	0x9401	/* Initio's inic-935 product ID   */
@@ -171,13 +169,16 @@
 
 static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
 
-static const PCI_ID i91u_pci_devices[] = {
-	{ INI_VENDOR_ID, I950_DEVICE_ID },
-	{ INI_VENDOR_ID, I940_DEVICE_ID },
-	{ INI_VENDOR_ID, I935_DEVICE_ID },
-	{ INI_VENDOR_ID, I920_DEVICE_ID },
-	{ DMX_VENDOR_ID, I920_DEVICE_ID },
+/* PCI Devices supported by this driver */
+static struct pci_device_id i91u_pci_devices[] __devinitdata = {
+	{ PCI_VENDOR_ID_INIT,  I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_INIT,  I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_INIT,  I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_INIT,  I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_DOMEX, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
 };
+MODULE_DEVICE_TABLE(pci, i91u_pci_devices);
 
 #define DEBUG_INTERRUPT 0
 #define DEBUG_QUEUE     0
@@ -2748,7 +2749,7 @@
 	return (tul_bad_seq(pCurHcb));
 }
 
-static irqreturn_t i91u_intr(int irqno, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i91u_intr(int irqno, void *dev_id)
 {
 	struct Scsi_Host *dev = dev_id;
 	unsigned long flags;
@@ -2771,7 +2772,7 @@
 
 	for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++)
 	{
-		while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) {
+		while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) {
 			if (pci_enable_device(pDev))
 				continue;
 			pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 7ed4eef..2dde821 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -70,6 +70,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/libata.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
@@ -78,6 +79,7 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_transport.h>
 #include "ipr.h"
 
 /*
@@ -199,6 +201,8 @@
 	"FFFA: Undefined device response recovered by the IOA"},
 	{0x014A0000, 1, 1,
 	"FFF6: Device bus error, message or command phase"},
+	{0x014A8000, 0, 1,
+	"FFFE: Task Management Function failed"},
 	{0x015D0000, 0, 1,
 	"FFF6: Failure prediction threshold exceeded"},
 	{0x015D9200, 0, 1,
@@ -261,6 +265,8 @@
 	"Device bus status error"},
 	{0x04448600, 0, 1,
 	"8157: IOA error requiring IOA reset to recover"},
+	{0x04448700, 0, 0,
+	"ATA device status error"},
 	{0x04490000, 0, 0,
 	"Message reject received from the device"},
 	{0x04449200, 0, 1,
@@ -273,6 +279,8 @@
 	"9082: IOA detected device error"},
 	{0x044A0000, 1, 1,
 	"3110: Device bus error, message or command phase"},
+	{0x044A8000, 1, 1,
+	"3110: SAS Command / Task Management Function failed"},
 	{0x04670400, 0, 1,
 	"9091: Incorrect hardware configuration change has been detected"},
 	{0x04678000, 0, 1,
@@ -453,7 +461,8 @@
 	trace_entry->time = jiffies;
 	trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];
 	trace_entry->type = type;
-	trace_entry->cmd_index = ipr_cmd->cmd_index;
+	trace_entry->ata_op_code = ipr_cmd->ioarcb.add_data.u.regs.command;
+	trace_entry->cmd_index = ipr_cmd->cmd_index & 0xff;
 	trace_entry->res_handle = ipr_cmd->ioarcb.res_handle;
 	trace_entry->u.add_data = add_data;
 }
@@ -480,8 +489,10 @@
 	ioarcb->read_ioadl_len = 0;
 	ioasa->ioasc = 0;
 	ioasa->residual_data_len = 0;
+	ioasa->u.gata.status = 0;
 
 	ipr_cmd->scsi_cmd = NULL;
+	ipr_cmd->qc = NULL;
 	ipr_cmd->sense_buffer[0] = 0;
 	ipr_cmd->dma_use_sg = 0;
 }
@@ -626,6 +637,28 @@
 }
 
 /**
+ * ipr_sata_eh_done - done function for aborted SATA commands
+ * @ipr_cmd:	ipr command struct
+ *
+ * This function is invoked for ops generated to SATA
+ * devices which are being aborted.
+ *
+ * Return value:
+ * 	none
+ **/
+static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
+{
+	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+	struct ata_queued_cmd *qc = ipr_cmd->qc;
+	struct ipr_sata_port *sata_port = qc->ap->private_data;
+
+	qc->err_mask |= AC_ERR_OTHER;
+	sata_port->ioasa.status |= ATA_BUSY;
+	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+	ata_qc_complete(qc);
+}
+
+/**
  * ipr_scsi_eh_done - mid-layer done function for aborted ops
  * @ipr_cmd:	ipr command struct
  *
@@ -669,6 +702,8 @@
 
 		if (ipr_cmd->scsi_cmd)
 			ipr_cmd->done = ipr_scsi_eh_done;
+		else if (ipr_cmd->qc)
+			ipr_cmd->done = ipr_sata_eh_done;
 
 		ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, IPR_IOASC_IOA_WAS_RESET);
 		del_timer(&ipr_cmd->timer);
@@ -825,6 +860,7 @@
 	res->del_from_ml = 0;
 	res->resetting_device = 0;
 	res->sdev = NULL;
+	res->sata_port = NULL;
 }
 
 /**
@@ -1316,7 +1352,7 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(ipr_error_table); i++)
-		if (ipr_error_table[i].ioasc == ioasc)
+		if (ipr_error_table[i].ioasc == (ioasc & IPR_IOASC_IOASC_MASK))
 			return i;
 
 	return 0;
@@ -3051,6 +3087,17 @@
  **/
 static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
+	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+	struct ipr_resource_entry *res;
+	unsigned long lock_flags = 0;
+
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	res = (struct ipr_resource_entry *)sdev->hostdata;
+
+	if (res && ipr_is_gata(res) && qdepth > IPR_MAX_CMD_PER_ATA_LUN)
+		qdepth = IPR_MAX_CMD_PER_ATA_LUN;
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
 	return sdev->queue_depth;
 }
@@ -3166,6 +3213,122 @@
 }
 
 /**
+ * ipr_find_starget - Find target based on bus/target.
+ * @starget:	scsi target struct
+ *
+ * Return value:
+ * 	resource entry pointer if found / NULL if not found
+ **/
+static struct ipr_resource_entry *ipr_find_starget(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) shost->hostdata;
+	struct ipr_resource_entry *res;
+
+	list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
+		if ((res->cfgte.res_addr.bus == starget->channel) &&
+		    (res->cfgte.res_addr.target == starget->id) &&
+		    (res->cfgte.res_addr.lun == 0)) {
+			return res;
+		}
+	}
+
+	return NULL;
+}
+
+static struct ata_port_info sata_port_info;
+
+/**
+ * ipr_target_alloc - Prepare for commands to a SCSI target
+ * @starget:	scsi target struct
+ *
+ * If the device is a SATA device, this function allocates an
+ * ATA port with libata, else it does nothing.
+ *
+ * Return value:
+ * 	0 on success / non-0 on failure
+ **/
+static int ipr_target_alloc(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) shost->hostdata;
+	struct ipr_sata_port *sata_port;
+	struct ata_port *ap;
+	struct ipr_resource_entry *res;
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	res = ipr_find_starget(starget);
+	starget->hostdata = NULL;
+
+	if (res && ipr_is_gata(res)) {
+		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+		sata_port = kzalloc(sizeof(*sata_port), GFP_KERNEL);
+		if (!sata_port)
+			return -ENOMEM;
+
+		ap = ata_sas_port_alloc(&ioa_cfg->ata_host, &sata_port_info, shost);
+		if (ap) {
+			spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+			sata_port->ioa_cfg = ioa_cfg;
+			sata_port->ap = ap;
+			sata_port->res = res;
+
+			res->sata_port = sata_port;
+			ap->private_data = sata_port;
+			starget->hostdata = sata_port;
+		} else {
+			kfree(sata_port);
+			return -ENOMEM;
+		}
+	}
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
+	return 0;
+}
+
+/**
+ * ipr_target_destroy - Destroy a SCSI target
+ * @starget:	scsi target struct
+ *
+ * If the device was a SATA device, this function frees the libata
+ * ATA port, else it does nothing.
+ *
+ **/
+static void ipr_target_destroy(struct scsi_target *starget)
+{
+	struct ipr_sata_port *sata_port = starget->hostdata;
+
+	if (sata_port) {
+		starget->hostdata = NULL;
+		ata_sas_port_destroy(sata_port->ap);
+		kfree(sata_port);
+	}
+}
+
+/**
+ * ipr_find_sdev - Find device based on bus/target/lun.
+ * @sdev:	scsi device struct
+ *
+ * Return value:
+ * 	resource entry pointer if found / NULL if not found
+ **/
+static struct ipr_resource_entry *ipr_find_sdev(struct scsi_device *sdev)
+{
+	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata;
+	struct ipr_resource_entry *res;
+
+	list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
+		if ((res->cfgte.res_addr.bus == sdev->channel) &&
+		    (res->cfgte.res_addr.target == sdev->id) &&
+		    (res->cfgte.res_addr.lun == sdev->lun))
+			return res;
+	}
+
+	return NULL;
+}
+
+/**
  * ipr_slave_destroy - Unconfigure a SCSI device
  * @sdev:	scsi device struct
  *
@@ -3183,8 +3346,11 @@
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 	res = (struct ipr_resource_entry *) sdev->hostdata;
 	if (res) {
+		if (res->sata_port)
+			ata_port_disable(res->sata_port->ap);
 		sdev->hostdata = NULL;
 		res->sdev = NULL;
+		res->sata_port = NULL;
 	}
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 }
@@ -3219,13 +3385,45 @@
 		}
 		if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
 			sdev->allow_restart = 1;
-		scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+		if (ipr_is_gata(res) && res->sata_port) {
+			scsi_adjust_queue_depth(sdev, 0, IPR_MAX_CMD_PER_ATA_LUN);
+			ata_sas_slave_configure(sdev, res->sata_port->ap);
+		} else {
+			scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+		}
 	}
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 	return 0;
 }
 
 /**
+ * ipr_ata_slave_alloc - Prepare for commands to a SATA device
+ * @sdev:	scsi device struct
+ *
+ * This function initializes an ATA port so that future commands
+ * sent through queuecommand will work.
+ *
+ * Return value:
+ * 	0 on success
+ **/
+static int ipr_ata_slave_alloc(struct scsi_device *sdev)
+{
+	struct ipr_sata_port *sata_port = NULL;
+	int rc = -ENXIO;
+
+	ENTER;
+	if (sdev->sdev_target)
+		sata_port = sdev->sdev_target->hostdata;
+	if (sata_port)
+		rc = ata_sas_port_init(sata_port->ap);
+	if (rc)
+		ipr_slave_destroy(sdev);
+
+	LEAVE;
+	return rc;
+}
+
+/**
  * ipr_slave_alloc - Prepare for commands to a device.
  * @sdev:	scsi device struct
  *
@@ -3248,18 +3446,18 @@
 
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 
-	list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
-		if ((res->cfgte.res_addr.bus == sdev->channel) &&
-		    (res->cfgte.res_addr.target == sdev->id) &&
-		    (res->cfgte.res_addr.lun == sdev->lun)) {
-			res->sdev = sdev;
-			res->add_to_ml = 0;
-			res->in_erp = 0;
-			sdev->hostdata = res;
-			if (!ipr_is_naca_model(res))
-				res->needs_sync_complete = 1;
-			rc = 0;
-			break;
+	res = ipr_find_sdev(sdev);
+	if (res) {
+		res->sdev = sdev;
+		res->add_to_ml = 0;
+		res->in_erp = 0;
+		sdev->hostdata = res;
+		if (!ipr_is_naca_model(res))
+			res->needs_sync_complete = 1;
+		rc = 0;
+		if (ipr_is_gata(res)) {
+			spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+			return ipr_ata_slave_alloc(sdev);
 		}
 	}
 
@@ -3314,7 +3512,8 @@
  * This function issues a device reset to the affected device.
  * If the device is a SCSI device, a LUN reset will be sent
  * to the device first. If that does not work, a target reset
- * will be sent.
+ * will be sent. If the device is a SATA device, a PHY reset will
+ * be sent.
  *
  * Return value:
  *	0 on success / non-zero on failure
@@ -3325,26 +3524,79 @@
 	struct ipr_cmnd *ipr_cmd;
 	struct ipr_ioarcb *ioarcb;
 	struct ipr_cmd_pkt *cmd_pkt;
+	struct ipr_ioarcb_ata_regs *regs;
 	u32 ioasc;
 
 	ENTER;
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ioarcb = &ipr_cmd->ioarcb;
 	cmd_pkt = &ioarcb->cmd_pkt;
+	regs = &ioarcb->add_data.u.regs;
 
 	ioarcb->res_handle = res->cfgte.res_handle;
 	cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
 	cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
+	if (ipr_is_gata(res)) {
+		cmd_pkt->cdb[2] = IPR_ATA_PHY_RESET;
+		ioarcb->add_cmd_parms_len = cpu_to_be32(sizeof(regs->flags));
+		regs->flags |= IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION;
+	}
 
 	ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
 	ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+	if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET)
+		memcpy(&res->sata_port->ioasa, &ipr_cmd->ioasa.u.gata,
+		       sizeof(struct ipr_ioasa_gata));
 
 	LEAVE;
 	return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
 }
 
 /**
+ * ipr_sata_reset - Reset the SATA port
+ * @ap:		SATA port to reset
+ * @classes:	class of the attached device
+ *
+ * This function issues a SATA phy reset to the affected ATA port.
+ *
+ * Return value:
+ *	0 on success / non-zero on failure
+ **/
+static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes)
+{
+	struct ipr_sata_port *sata_port = ap->private_data;
+	struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
+	struct ipr_resource_entry *res;
+	unsigned long lock_flags = 0;
+	int rc = -ENXIO;
+
+	ENTER;
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	res = sata_port->res;
+	if (res) {
+		rc = ipr_device_reset(ioa_cfg, res);
+		switch(res->cfgte.proto) {
+		case IPR_PROTO_SATA:
+		case IPR_PROTO_SAS_STP:
+			*classes = ATA_DEV_ATA;
+			break;
+		case IPR_PROTO_SATA_ATAPI:
+		case IPR_PROTO_SAS_STP_ATAPI:
+			*classes = ATA_DEV_ATAPI;
+			break;
+		default:
+			*classes = ATA_DEV_UNKNOWN;
+			break;
+		};
+	}
+
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+	LEAVE;
+	return rc;
+}
+
+/**
  * ipr_eh_dev_reset - Reset the device
  * @scsi_cmd:	scsi command struct
  *
@@ -3360,7 +3612,8 @@
 	struct ipr_cmnd *ipr_cmd;
 	struct ipr_ioa_cfg *ioa_cfg;
 	struct ipr_resource_entry *res;
-	int rc;
+	struct ata_port *ap;
+	int rc = 0;
 
 	ENTER;
 	ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
@@ -3388,7 +3641,14 @@
 
 	res->resetting_device = 1;
 	scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n");
-	rc = ipr_device_reset(ioa_cfg, res);
+
+	if (ipr_is_gata(res) && res->sata_port) {
+		ap = res->sata_port->ap;
+		spin_unlock_irq(scsi_cmd->device->host->host_lock);
+		ata_do_eh(ap, NULL, NULL, ipr_sata_reset, NULL);
+		spin_lock_irq(scsi_cmd->device->host->host_lock);
+	} else
+		rc = ipr_device_reset(ioa_cfg, res);
 	res->resetting_device = 0;
 
 	LEAVE;
@@ -3620,12 +3880,11 @@
  * ipr_isr - Interrupt service routine
  * @irq:	irq number
  * @devp:	pointer to ioa config struct
- * @regs:	pt_regs struct
  *
  * Return value:
  * 	IRQ_NONE / IRQ_HANDLED
  **/
-static irqreturn_t ipr_isr(int irq, void *devp, struct pt_regs *regs)
+static irqreturn_t ipr_isr(int irq, void *devp)
 {
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
 	unsigned long lock_flags = 0;
@@ -4300,6 +4559,9 @@
 		return 0;
 	}
 
+	if (ipr_is_gata(res) && res->sata_port)
+		return ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ioarcb = &ipr_cmd->ioarcb;
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
@@ -4345,6 +4607,26 @@
 }
 
 /**
+ * ipr_ioctl - IOCTL handler
+ * @sdev:	scsi device struct
+ * @cmd:	IOCTL cmd
+ * @arg:	IOCTL arg
+ *
+ * Return value:
+ * 	0 on success / other on failure
+ **/
+int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+	struct ipr_resource_entry *res;
+
+	res = (struct ipr_resource_entry *)sdev->hostdata;
+	if (res && ipr_is_gata(res))
+		return ata_scsi_ioctl(sdev, cmd, arg);
+
+	return -EINVAL;
+}
+
+/**
  * ipr_info - Get information about the card/driver
  * @scsi_host:	scsi host struct
  *
@@ -4366,10 +4648,45 @@
 	return buffer;
 }
 
+/**
+ * ipr_scsi_timed_out - Handle scsi command timeout
+ * @scsi_cmd:	scsi command struct
+ *
+ * Return value:
+ * 	EH_NOT_HANDLED
+ **/
+enum scsi_eh_timer_return ipr_scsi_timed_out(struct scsi_cmnd *scsi_cmd)
+{
+	struct ipr_ioa_cfg *ioa_cfg;
+	struct ipr_cmnd *ipr_cmd;
+	unsigned long flags;
+
+	ENTER;
+	spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
+	ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
+
+	list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+		if (ipr_cmd->qc && ipr_cmd->qc->scsicmd == scsi_cmd) {
+			ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
+			ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
+	LEAVE;
+	return EH_NOT_HANDLED;
+}
+
+static struct scsi_transport_template ipr_transport_template = {
+	.eh_timed_out = ipr_scsi_timed_out
+};
+
 static struct scsi_host_template driver_template = {
 	.module = THIS_MODULE,
 	.name = "IPR",
 	.info = ipr_ioa_info,
+	.ioctl = ipr_ioctl,
 	.queuecommand = ipr_queuecommand,
 	.eh_abort_handler = ipr_eh_abort,
 	.eh_device_reset_handler = ipr_eh_dev_reset,
@@ -4377,6 +4694,8 @@
 	.slave_alloc = ipr_slave_alloc,
 	.slave_configure = ipr_slave_configure,
 	.slave_destroy = ipr_slave_destroy,
+	.target_alloc = ipr_target_alloc,
+	.target_destroy = ipr_target_destroy,
 	.change_queue_depth = ipr_change_queue_depth,
 	.change_queue_type = ipr_change_queue_type,
 	.bios_param = ipr_biosparam,
@@ -4391,6 +4710,330 @@
 	.proc_name = IPR_NAME
 };
 
+/**
+ * ipr_ata_phy_reset - libata phy_reset handler
+ * @ap:		ata port to reset
+ *
+ **/
+static void ipr_ata_phy_reset(struct ata_port *ap)
+{
+	unsigned long flags;
+	struct ipr_sata_port *sata_port = ap->private_data;
+	struct ipr_resource_entry *res = sata_port->res;
+	struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
+	int rc;
+
+	ENTER;
+	spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
+	while(ioa_cfg->in_reset_reload) {
+		spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
+		wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+		spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
+	}
+
+	if (!ioa_cfg->allow_cmds)
+		goto out_unlock;
+
+	rc = ipr_device_reset(ioa_cfg, res);
+
+	if (rc) {
+		ap->ops->port_disable(ap);
+		goto out_unlock;
+	}
+
+	switch(res->cfgte.proto) {
+	case IPR_PROTO_SATA:
+	case IPR_PROTO_SAS_STP:
+		ap->device[0].class = ATA_DEV_ATA;
+		break;
+	case IPR_PROTO_SATA_ATAPI:
+	case IPR_PROTO_SAS_STP_ATAPI:
+		ap->device[0].class = ATA_DEV_ATAPI;
+		break;
+	default:
+		ap->device[0].class = ATA_DEV_UNKNOWN;
+		ap->ops->port_disable(ap);
+		break;
+	};
+
+out_unlock:
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
+	LEAVE;
+}
+
+/**
+ * ipr_ata_post_internal - Cleanup after an internal command
+ * @qc:	ATA queued command
+ *
+ * Return value:
+ * 	none
+ **/
+static void ipr_ata_post_internal(struct ata_queued_cmd *qc)
+{
+	struct ipr_sata_port *sata_port = qc->ap->private_data;
+	struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
+	struct ipr_cmnd *ipr_cmd;
+	unsigned long flags;
+
+	spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
+	list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+		if (ipr_cmd->qc == qc) {
+			ipr_device_reset(ioa_cfg, sata_port->res);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
+}
+
+/**
+ * ipr_tf_read - Read the current ATA taskfile for the ATA port
+ * @ap:	ATA port
+ * @tf:	destination ATA taskfile
+ *
+ * Return value:
+ * 	none
+ **/
+static void ipr_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ipr_sata_port *sata_port = ap->private_data;
+	struct ipr_ioasa_gata *g = &sata_port->ioasa;
+
+	tf->feature = g->error;
+	tf->nsect = g->nsect;
+	tf->lbal = g->lbal;
+	tf->lbam = g->lbam;
+	tf->lbah = g->lbah;
+	tf->device = g->device;
+	tf->command = g->status;
+	tf->hob_nsect = g->hob_nsect;
+	tf->hob_lbal = g->hob_lbal;
+	tf->hob_lbam = g->hob_lbam;
+	tf->hob_lbah = g->hob_lbah;
+	tf->ctl = g->alt_status;
+}
+
+/**
+ * ipr_copy_sata_tf - Copy a SATA taskfile to an IOA data structure
+ * @regs:	destination
+ * @tf:	source ATA taskfile
+ *
+ * Return value:
+ * 	none
+ **/
+static void ipr_copy_sata_tf(struct ipr_ioarcb_ata_regs *regs,
+			     struct ata_taskfile *tf)
+{
+	regs->feature = tf->feature;
+	regs->nsect = tf->nsect;
+	regs->lbal = tf->lbal;
+	regs->lbam = tf->lbam;
+	regs->lbah = tf->lbah;
+	regs->device = tf->device;
+	regs->command = tf->command;
+	regs->hob_feature = tf->hob_feature;
+	regs->hob_nsect = tf->hob_nsect;
+	regs->hob_lbal = tf->hob_lbal;
+	regs->hob_lbam = tf->hob_lbam;
+	regs->hob_lbah = tf->hob_lbah;
+	regs->ctl = tf->ctl;
+}
+
+/**
+ * ipr_sata_done - done function for SATA commands
+ * @ipr_cmd:	ipr command struct
+ *
+ * This function is invoked by the interrupt handler for
+ * ops generated by the SCSI mid-layer to SATA devices
+ *
+ * Return value:
+ * 	none
+ **/
+static void ipr_sata_done(struct ipr_cmnd *ipr_cmd)
+{
+	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+	struct ata_queued_cmd *qc = ipr_cmd->qc;
+	struct ipr_sata_port *sata_port = qc->ap->private_data;
+	struct ipr_resource_entry *res = sata_port->res;
+	u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+
+	memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata,
+	       sizeof(struct ipr_ioasa_gata));
+	ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
+
+	if (be32_to_cpu(ipr_cmd->ioasa.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET)
+		scsi_report_device_reset(ioa_cfg->host, res->cfgte.res_addr.bus,
+					 res->cfgte.res_addr.target);
+
+	if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR)
+		qc->err_mask |= __ac_err_mask(ipr_cmd->ioasa.u.gata.status);
+	else
+		qc->err_mask |= ac_err_mask(ipr_cmd->ioasa.u.gata.status);
+	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+	ata_qc_complete(qc);
+}
+
+/**
+ * ipr_build_ata_ioadl - Build an ATA scatter/gather list
+ * @ipr_cmd:	ipr command struct
+ * @qc:		ATA queued command
+ *
+ **/
+static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,
+				struct ata_queued_cmd *qc)
+{
+	u32 ioadl_flags = 0;
+	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+	struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
+	int len = qc->nbytes + qc->pad_len;
+	struct scatterlist *sg;
+
+	if (len == 0)
+		return;
+
+	if (qc->dma_dir == DMA_TO_DEVICE) {
+		ioadl_flags = IPR_IOADL_FLAGS_WRITE;
+		ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
+		ioarcb->write_data_transfer_length = cpu_to_be32(len);
+		ioarcb->write_ioadl_len =
+			cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+	} else if (qc->dma_dir == DMA_FROM_DEVICE) {
+		ioadl_flags = IPR_IOADL_FLAGS_READ;
+		ioarcb->read_data_transfer_length = cpu_to_be32(len);
+		ioarcb->read_ioadl_len =
+			cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+	}
+
+	ata_for_each_sg(sg, qc) {
+		ioadl->flags_and_data_len = cpu_to_be32(ioadl_flags | sg_dma_len(sg));
+		ioadl->address = cpu_to_be32(sg_dma_address(sg));
+		if (ata_sg_is_last(sg, qc))
+			ioadl->flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
+		else
+			ioadl++;
+	}
+}
+
+/**
+ * ipr_qc_issue - Issue a SATA qc to a device
+ * @qc:	queued command
+ *
+ * Return value:
+ * 	0 if success
+ **/
+static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ipr_sata_port *sata_port = ap->private_data;
+	struct ipr_resource_entry *res = sata_port->res;
+	struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
+	struct ipr_cmnd *ipr_cmd;
+	struct ipr_ioarcb *ioarcb;
+	struct ipr_ioarcb_ata_regs *regs;
+
+	if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead))
+		return -EIO;
+
+	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
+	ioarcb = &ipr_cmd->ioarcb;
+	regs = &ioarcb->add_data.u.regs;
+
+	memset(&ioarcb->add_data, 0, sizeof(ioarcb->add_data));
+	ioarcb->add_cmd_parms_len = cpu_to_be32(sizeof(ioarcb->add_data.u.regs));
+
+	list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+	ipr_cmd->qc = qc;
+	ipr_cmd->done = ipr_sata_done;
+	ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
+	ioarcb->cmd_pkt.request_type = IPR_RQTYPE_ATA_PASSTHRU;
+	ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
+	ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK;
+	ipr_cmd->dma_use_sg = qc->pad_len ? qc->n_elem + 1 : qc->n_elem;
+
+	ipr_build_ata_ioadl(ipr_cmd, qc);
+	regs->flags |= IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION;
+	ipr_copy_sata_tf(regs, &qc->tf);
+	memcpy(ioarcb->cmd_pkt.cdb, qc->cdb, IPR_MAX_CDB_LEN);
+	ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_GET_PHYS_LOC(res->cfgte.res_addr));
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_NODATA:
+	case ATA_PROT_PIO:
+		break;
+
+	case ATA_PROT_DMA:
+		regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
+		break;
+
+	case ATA_PROT_ATAPI:
+	case ATA_PROT_ATAPI_NODATA:
+		regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
+		break;
+
+	case ATA_PROT_ATAPI_DMA:
+		regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
+		regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
+		break;
+
+	default:
+		WARN_ON(1);
+		return -1;
+	}
+
+	mb();
+	writel(be32_to_cpu(ioarcb->ioarcb_host_pci_addr),
+	       ioa_cfg->regs.ioarrin_reg);
+	return 0;
+}
+
+/**
+ * ipr_ata_check_status - Return last ATA status
+ * @ap:	ATA port
+ *
+ * Return value:
+ * 	ATA status
+ **/
+static u8 ipr_ata_check_status(struct ata_port *ap)
+{
+	struct ipr_sata_port *sata_port = ap->private_data;
+	return sata_port->ioasa.status;
+}
+
+/**
+ * ipr_ata_check_altstatus - Return last ATA altstatus
+ * @ap:	ATA port
+ *
+ * Return value:
+ * 	Alt ATA status
+ **/
+static u8 ipr_ata_check_altstatus(struct ata_port *ap)
+{
+	struct ipr_sata_port *sata_port = ap->private_data;
+	return sata_port->ioasa.alt_status;
+}
+
+static struct ata_port_operations ipr_sata_ops = {
+	.port_disable = ata_port_disable,
+	.check_status = ipr_ata_check_status,
+	.check_altstatus = ipr_ata_check_altstatus,
+	.dev_select = ata_noop_dev_select,
+	.phy_reset = ipr_ata_phy_reset,
+	.post_internal_cmd = ipr_ata_post_internal,
+	.tf_read = ipr_tf_read,
+	.qc_prep = ata_noop_qc_prep,
+	.qc_issue = ipr_qc_issue,
+	.port_start = ata_sas_port_start,
+	.port_stop = ata_sas_port_stop
+};
+
+static struct ata_port_info sata_port_info = {
+	.flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
+	ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+	.pio_mask	= 0x10, /* pio4 */
+	.mwdma_mask = 0x07,
+	.udma_mask	= 0x7f, /* udma0-6 */
+	.port_ops	= &ipr_sata_ops
+};
+
 #ifdef CONFIG_PPC_PSERIES
 static const u16 ipr_blocked_processors[] = {
 	PV_NORTHSTAR,
@@ -6352,7 +6995,7 @@
 	struct Scsi_Host *host;
 	unsigned long ipr_regs_pci;
 	void __iomem *ipr_regs;
-	u32 rc = PCIBIOS_SUCCESSFUL;
+	int rc = PCIBIOS_SUCCESSFUL;
 	volatile u32 mask, uproc;
 
 	ENTER;
@@ -6374,6 +7017,9 @@
 
 	ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata;
 	memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg));
+	host->transportt = &ipr_transport_template;
+	ata_host_init(&ioa_cfg->ata_host, &pdev->dev,
+		      sata_port_info.flags, &ipr_sata_ops);
 
 	ioa_cfg->chip_cfg = ipr_get_chip_cfg(dev_id);
 
@@ -6749,7 +7395,7 @@
 	ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n",
 		 IPR_DRIVER_VERSION, IPR_DRIVER_DATE);
 
-	return pci_module_init(&ipr_driver);
+	return pci_register_driver(&ipr_driver);
 }
 
 /**
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 11eaff5..6d03528 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -28,6 +28,7 @@
 
 #include <linux/types.h>
 #include <linux/completion.h>
+#include <linux/libata.h>
 #include <linux/list.h>
 #include <linux/kref.h>
 #include <scsi/scsi.h>
@@ -36,8 +37,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.1.4"
-#define IPR_DRIVER_DATE "(August 2, 2006)"
+#define IPR_DRIVER_VERSION "2.2.0"
+#define IPR_DRIVER_DATE "(September 25, 2006)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -849,6 +850,13 @@
 	u32 max_xfer_rate;
 };
 
+struct ipr_sata_port {
+	struct ipr_ioa_cfg *ioa_cfg;
+	struct ata_port *ap;
+	struct ipr_resource_entry *res;
+	struct ipr_ioasa_gata ioasa;
+};
+
 struct ipr_resource_entry {
 	struct ipr_config_table_entry cfgte;
 	u8 needs_sync_complete:1;
@@ -858,6 +866,7 @@
 	u8 resetting_device:1;
 
 	struct scsi_device *sdev;
+	struct ipr_sata_port *sata_port;
 	struct list_head queue;
 };
 
@@ -928,10 +937,11 @@
 	u32 time;
 
 	u8 op_code;
+	u8 ata_op_code;
 	u8 type;
 #define IPR_TRACE_START			0x00
 #define IPR_TRACE_FINISH		0xff
-	u16 cmd_index;
+	u8 cmd_index;
 
 	__be32 res_handle;
 	union {
@@ -1073,6 +1083,7 @@
 
 	struct ipr_cmnd *reset_cmd;
 
+	struct ata_host ata_host;
 	char ipr_cmd_label[8];
 #define IPR_CMD_LABEL		"ipr_cmnd"
 	struct ipr_cmnd *ipr_cmnd_list[IPR_NUM_CMD_BLKS];
@@ -1085,6 +1096,7 @@
 	struct ipr_ioadl_desc ioadl[IPR_NUM_IOADL_ENTRIES];
 	struct list_head queue;
 	struct scsi_cmnd *scsi_cmd;
+	struct ata_queued_cmd *qc;
 	struct completion completion;
 	struct timer_list timer;
 	void (*done) (struct ipr_cmnd *);
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 3c63928..f06a06a 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -182,14 +182,8 @@
 #include <linux/dma-mapping.h>
 
 #include <scsi/sg.h>
-
 #include "scsi.h"
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include "hosts.h"
-#else
 #include <scsi/scsi_host.h>
-#endif
 
 #include "ips.h"
 
@@ -250,11 +244,11 @@
  */
 static int ips_detect(struct scsi_host_template *);
 static int ips_release(struct Scsi_Host *);
-static int ips_eh_abort(Scsi_Cmnd *);
-static int ips_eh_reset(Scsi_Cmnd *);
-static int ips_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
+static int ips_eh_abort(struct scsi_cmnd *);
+static int ips_eh_reset(struct scsi_cmnd *);
+static int ips_queue(struct scsi_cmnd *, void (*)(struct scsi_cmnd *));
 static const char *ips_info(struct Scsi_Host *);
-static irqreturn_t do_ipsintr(int, void *, struct pt_regs *);
+static irqreturn_t do_ipsintr(int, void *);
 static int ips_hainit(ips_ha_t *);
 static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
 static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
@@ -325,24 +319,26 @@
 static uint32_t ips_statupd_morpheus(ips_ha_t *);
 static ips_scb_t *ips_getscb(ips_ha_t *);
 static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, struct scsi_cmnd *);
 static void ips_putq_copp_tail(ips_copp_queue_t *,
 				      ips_copp_wait_item_t *);
 static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
 static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *,
+					  struct scsi_cmnd *);
 static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
 						     ips_copp_wait_item_t *);
 static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
 
-static int ips_is_passthru(Scsi_Cmnd *);
-static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
+static int ips_is_passthru(struct scsi_cmnd *);
+static int ips_make_passthru(ips_ha_t *, struct scsi_cmnd *, ips_scb_t *, int);
 static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
 static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
-static void ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data,
+static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data,
 			       unsigned int count);
-static void ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned int count);
+static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
+			      unsigned int count);
 
 static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int ips_host_info(ips_ha_t *, char *, off_t, int);
@@ -812,8 +808,7 @@
 /*   Abort a command (using the new error code stuff)                       */
 /* Note: this routine is called under the io_request_lock                   */
 /****************************************************************************/
-int
-ips_eh_abort(Scsi_Cmnd * SC)
+int ips_eh_abort(struct scsi_cmnd *SC)
 {
 	ips_ha_t *ha;
 	ips_copp_wait_item_t *item;
@@ -871,8 +866,7 @@
 /* NOTE: this routine is called under the io_request_lock spinlock          */
 /*                                                                          */
 /****************************************************************************/
-static int
-__ips_eh_reset(Scsi_Cmnd * SC)
+static int __ips_eh_reset(struct scsi_cmnd *SC)
 {
 	int ret;
 	int i;
@@ -968,7 +962,7 @@
 	ret = (*ha->func.reset) (ha);
 
 	if (!ret) {
-		Scsi_Cmnd *scsi_cmd;
+		struct scsi_cmnd *scsi_cmd;
 
 		IPS_PRINTK(KERN_NOTICE, ha->pcidev,
 			   "Controller reset failed - controller now offline.\n");
@@ -997,7 +991,7 @@
 	}
 
 	if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
-		Scsi_Cmnd *scsi_cmd;
+		struct scsi_cmnd *scsi_cmd;
 
 		IPS_PRINTK(KERN_NOTICE, ha->pcidev,
 			   "Controller reset failed - controller now offline.\n");
@@ -1059,8 +1053,7 @@
 
 }
 
-static int
-ips_eh_reset(Scsi_Cmnd * SC)
+static int ips_eh_reset(struct scsi_cmnd *SC)
 {
 	int rc;
 
@@ -1083,8 +1076,7 @@
 /*    Linux obtains io_request_lock before calling this function            */
 /*                                                                          */
 /****************************************************************************/
-static int
-ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
+static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 {
 	ips_ha_t *ha;
 	ips_passthru_t *pt;
@@ -1336,7 +1328,7 @@
 /*                                                                          */
 /****************************************************************************/
 static irqreturn_t
-do_ipsintr(int irq, void *dev_id, struct pt_regs * regs)
+do_ipsintr(int irq, void *dev_id)
 {
 	ips_ha_t *ha;
 	unsigned long cpu_flags;
@@ -1602,8 +1594,7 @@
 /*   Determine if the specified SCSI command is really a passthru command   */
 /*                                                                          */
 /****************************************************************************/
-static int
-ips_is_passthru(Scsi_Cmnd * SC)
+static int ips_is_passthru(struct scsi_cmnd *SC)
 {
 	unsigned long flags;
 
@@ -1685,7 +1676,7 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_make_passthru(ips_ha_t * ha, Scsi_Cmnd * SC, ips_scb_t * scb, int intr)
+ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr)
 {
 	ips_passthru_t *pt;
 	int length = 0;
@@ -2734,9 +2725,9 @@
 ips_next(ips_ha_t * ha, int intr)
 {
 	ips_scb_t *scb;
-	Scsi_Cmnd *SC;
-	Scsi_Cmnd *p;
-	Scsi_Cmnd *q;
+	struct scsi_cmnd *SC;
+	struct scsi_cmnd *p;
+	struct scsi_cmnd *q;
 	ips_copp_wait_item_t *item;
 	int ret;
 	unsigned long cpu_flags = 0;
@@ -2847,7 +2838,7 @@
 			dcdb_active[scmd_channel(p) -
 				    1] & (1 << scmd_id(p)))) {
 			ips_freescb(ha, scb);
-			p = (Scsi_Cmnd *) p->host_scribble;
+			p = (struct scsi_cmnd *) p->host_scribble;
 			continue;
 		}
 
@@ -2962,7 +2953,7 @@
 			break;
 		}		/* end case */
 
-		p = (Scsi_Cmnd *) p->host_scribble;
+		p = (struct scsi_cmnd *) p->host_scribble;
 
 	}			/* end while */
 
@@ -3090,8 +3081,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static void
-ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
 {
 	METHOD_TRACE("ips_putq_wait_tail", 1);
 
@@ -3122,10 +3112,9 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static Scsi_Cmnd *
-ips_removeq_wait_head(ips_wait_queue_t * queue)
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
 {
-	Scsi_Cmnd *item;
+	struct scsi_cmnd *item;
 
 	METHOD_TRACE("ips_removeq_wait_head", 1);
 
@@ -3135,7 +3124,7 @@
 		return (NULL);
 	}
 
-	queue->head = (Scsi_Cmnd *) item->host_scribble;
+	queue->head = (struct scsi_cmnd *) item->host_scribble;
 	item->host_scribble = NULL;
 
 	if (queue->tail == item)
@@ -3157,10 +3146,10 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static Scsi_Cmnd *
-ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *queue,
+					  struct scsi_cmnd *item)
 {
-	Scsi_Cmnd *p;
+	struct scsi_cmnd *p;
 
 	METHOD_TRACE("ips_removeq_wait", 1);
 
@@ -3173,8 +3162,8 @@
 
 	p = queue->head;
 
-	while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
-		p = (Scsi_Cmnd *) p->host_scribble;
+	while ((p) && (item != (struct scsi_cmnd *) p->host_scribble))
+		p = (struct scsi_cmnd *) p->host_scribble;
 
 	if (p) {
 		/* found a match */
@@ -3659,11 +3648,10 @@
 /* Routine Name: ips_scmd_buf_write                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
-/*  Write data to Scsi_Cmnd request_buffer at proper offsets                */
+/*  Write data to struct scsi_cmnd request_buffer at proper offsets	    */
 /****************************************************************************/
 static void
-ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data, unsigned
-		   int count)
+ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
 	if (scmd->use_sg) {
 		int i;
@@ -3698,11 +3686,10 @@
 /* Routine Name: ips_scmd_buf_read                                          */
 /*                                                                          */
 /* Routine Description:                                                     */
-/*  Copy data from a Scsi_Cmnd to a new, linear buffer                      */
+/*  Copy data from a struct scsi_cmnd to a new, linear buffer		    */
 /****************************************************************************/
 static void
-ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned
-		  int count)
+ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
 	if (scmd->use_sg) {
 		int i;
@@ -7078,7 +7065,7 @@
 static int __init
 ips_module_init(void)
 {
-	if (pci_module_init(&ips_pci_driver) < 0)
+	if (pci_register_driver(&ips_pci_driver) < 0)
 		return -ENODEV;
 	ips_driver_template.module = THIS_MODULE;
 	ips_order_controllers();
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index f46c382..34680f3 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -6,7 +6,7 @@
 /*             David Jeffery, Adaptec, Inc.                                  */
 /*                                                                           */
 /* Copyright (C) 1999 IBM Corporation                                        */
-/* Copyright (C) 2003 Adaptec, Inc.                                          */ 
+/* Copyright (C) 2003 Adaptec, 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      */
@@ -1033,14 +1033,14 @@
  * Wait queue_format
  */
 typedef struct ips_wait_queue {
-   Scsi_Cmnd      *head;
-   Scsi_Cmnd      *tail;
-   int             count;
+	struct scsi_cmnd *head;
+	struct scsi_cmnd *tail;
+	int count;
 } ips_wait_queue_t;
 
 typedef struct ips_copp_wait_item {
-   Scsi_Cmnd                 *scsi_cmd;
-   struct ips_copp_wait_item *next;
+	struct scsi_cmnd *scsi_cmd;
+	struct ips_copp_wait_item *next;
 } ips_copp_wait_item_t;
 
 typedef struct ips_copp_queue {
@@ -1149,7 +1149,7 @@
    uint32_t          flags;
    uint32_t          op_code;
    IPS_SG_LIST       sg_list;
-   Scsi_Cmnd        *scsi_cmd;
+   struct scsi_cmnd *scsi_cmd;
    struct ips_scb   *q_next;
    ips_scb_callback  callback;
    uint32_t          sg_busaddr;
@@ -1175,7 +1175,7 @@
    uint32_t          flags;
    uint32_t          op_code;
    IPS_SG_LIST      *sg_list;
-   Scsi_Cmnd        *scsi_cmd;
+   struct scsi_cmnd *scsi_cmd;
    struct ips_scb   *q_next;
    ips_scb_callback  callback;
 } ips_scb_pt_t;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 3d68449..1251788 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -120,7 +120,7 @@
 
 void lpfc_handle_eratt(struct lpfc_hba *);
 void lpfc_handle_latt(struct lpfc_hba *);
-irqreturn_t lpfc_intr_handler(int, void *, struct pt_regs *);
+irqreturn_t lpfc_intr_handler(int, void *);
 
 void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4cdf346..a5723ad 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -389,7 +389,8 @@
 
 	lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
 	pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-	if (lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT) != MBX_SUCCESS) {
+	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+	if (rc != MBX_SUCCESS) {
 		lpfc_printf_log(phba,
 				KERN_ERR,
 				LOG_INIT,
@@ -406,7 +407,8 @@
 		readl(phba->HAregaddr); /* flush */
 
 		phba->hba_state = LPFC_HBA_ERROR;
-		mempool_free(pmb, phba->mbox_mem_pool);
+		if (rc != MBX_BUSY)
+			mempool_free(pmb, phba->mbox_mem_pool);
 		return -EIO;
 	}
 	/* MBOX buffer will be freed in mbox compl */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 70f4d5a..24a1779 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -3119,7 +3119,7 @@
 }
 
 irqreturn_t
-lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
+lpfc_intr_handler(int irq, void *dev_id)
 {
 	struct lpfc_hba *phba;
 	uint32_t ha_copy;
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 6422de7..753d883 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -60,8 +60,8 @@
 
 static void mac53c94_init(struct fsc_state *);
 static void mac53c94_start(struct fsc_state *);
-static void mac53c94_interrupt(int, void *, struct pt_regs *);
-static irqreturn_t do_mac53c94_interrupt(int, void *, struct pt_regs *);
+static void mac53c94_interrupt(int, void *);
+static irqreturn_t do_mac53c94_interrupt(int, void *);
 static void cmd_done(struct fsc_state *, int result);
 static void set_dma_cmds(struct fsc_state *, struct scsi_cmnd *);
 
@@ -177,18 +177,18 @@
 		set_dma_cmds(state, cmd);
 }
 
-static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = ((struct fsc_state *) dev_id)->current_req->device->host;
 	
 	spin_lock_irqsave(dev->host_lock, flags);
-	mac53c94_interrupt(irq, dev_id, ptregs);
+	mac53c94_interrupt(irq, dev_id);
 	spin_unlock_irqrestore(dev->host_lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static void mac53c94_interrupt(int irq, void *dev_id)
 {
 	struct fsc_state *state = (struct fsc_state *) dev_id;
 	struct mac53c94_regs __iomem *regs = state->regs;
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 118206d..3586fac 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -44,7 +44,7 @@
 /* #define DEBUG_MAC_ESP */
 
 extern void esp_handle(struct NCR_ESP *esp);
-extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+extern void mac_esp_intr(int irq, void *dev_id);
 
 static int  dma_bytes_sent(struct NCR_ESP * esp, int fifo_count);
 static int  dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp);
@@ -88,7 +88,7 @@
  * set up properly!
  */
 
-void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+void mac_esp_intr(int irq, void *dev_id)
 {
 	struct NCR_ESP *esp = (struct NCR_ESP *) dev_id;
 	int irq_p = 0;
@@ -122,24 +122,24 @@
  * acknowledge on the various machines
  */
 
-void scsi_esp_polled(int irq, void *dev_id, struct pt_regs *pregs)
+void scsi_esp_polled(int irq, void *dev_id)
 {
 	if (esp_initialized == 0)
 		return;
 
-	mac_esp_intr(irq, dev_id, pregs);
+	mac_esp_intr(irq, dev_id);
 }
 
-void fake_intr(int irq, void *dev_id, struct pt_regs *pregs)
+void fake_intr(int irq, void *dev_id)
 {
 #ifdef DEBUG_MAC_ESP
 	printk("mac_esp: got irq\n");
 #endif
 
-	mac_esp_intr(irq, dev_id, pregs);
+	mac_esp_intr(irq, dev_id);
 }
 
-irqreturn_t fake_drq(int irq, void *dev_id, struct pt_regs *pregs)
+irqreturn_t fake_drq(int irq, void *dev_id)
 {
 	printk("mac_esp: got drq\n");
 	return IRQ_HANDLED;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index b87bef6..86099fd 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -1256,14 +1256,13 @@
  * megaraid_isr_iomapped()
  * @irq - irq
  * @devp - pointer to our soft state
- * @regs - unused
  *
  * Interrupt service routine for io-mapped controllers.
  * Find out if our device is interrupting. If yes, acknowledge the interrupt
  * and service the completed commands.
  */
 static irqreturn_t
-megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
+megaraid_isr_iomapped(int irq, void *devp)
 {
 	adapter_t	*adapter = devp;
 	unsigned long	flags;
@@ -1333,14 +1332,13 @@
  * megaraid_isr_memmapped()
  * @irq - irq
  * @devp - pointer to our soft state
- * @regs - unused
  *
  * Interrupt service routine for memory-mapped controllers.
  * Find out if our device is interrupting. If yes, acknowledge the interrupt
  * and service the completed commands.
  */
 static irqreturn_t
-megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs)
+megaraid_isr_memmapped(int irq, void *devp)
 {
 	adapter_t	*adapter = devp;
 	unsigned long	flags;
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 4b75fe6..66529f1 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -991,8 +991,8 @@
 static void __mega_runpendq(adapter_t *);
 static int issue_scb_block(adapter_t *, u_char *);
 
-static irqreturn_t megaraid_isr_memmapped(int, void *, struct pt_regs *);
-static irqreturn_t megaraid_isr_iomapped(int, void *, struct pt_regs *);
+static irqreturn_t megaraid_isr_memmapped(int, void *);
+static irqreturn_t megaraid_isr_iomapped(int, void *);
 
 static void mega_free_scb(adapter_t *, scb_t *);
 
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index 8cd0bd1..b50e27e 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -175,7 +175,7 @@
 	uint8_t			max_lun;
 
 	uint32_t		unique_id;
-	uint8_t			irq;
+	int			irq;
 	uint8_t			ito;
 	caddr_t			ibuf;
 	dma_addr_t		ibuf_dma_h;
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 266b391..7bac86d 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -120,7 +120,7 @@
 static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *,
 		struct scsi_cmnd *);
 
-static irqreturn_t megaraid_isr(int, void *, struct pt_regs *);
+static irqreturn_t megaraid_isr(int, void *);
 
 static void megaraid_mbox_dpc(unsigned long);
 
@@ -884,7 +884,7 @@
 
 	if (((magic64 == HBA_SIGNATURE_64_BIT) &&
 		((adapter->pdev->subsystem_device !=
-		PCI_SUBSYS_ID_MEGARAID_SATA_150_6) ||
+		PCI_SUBSYS_ID_MEGARAID_SATA_150_6) &&
 		(adapter->pdev->subsystem_device !=
 		PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) ||
 		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
@@ -2231,7 +2231,7 @@
  * Interrupt service routine for memory-mapped mailbox controllers.
  */
 static irqreturn_t
-megaraid_isr(int irq, void *devp, struct pt_regs *regs)
+megaraid_isr(int irq, void *devp)
 {
 	adapter_t	*adapter = devp;
 	int		handled;
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 4cab5b5..7e4262f 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_sas.c
- * Version	: v00.00.03.01
+ * Version	: v00.00.03.05
  *
  * Authors:
  * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
@@ -71,6 +71,8 @@
 static struct fasync_struct *megasas_async_queue;
 static DEFINE_MUTEX(megasas_async_queue_mutex);
 
+static u32 megasas_dbg_lvl;
+
 /**
  * megasas_get_cmd -	Get a command from the free pool
  * @instance:		Adapter soft state
@@ -135,6 +137,19 @@
 }
 
 /**
+ * megasas_disable_intr_xscale -Disables interrupt
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
+{
+	u32 mask = 0x1f;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
  * megasas_read_fw_status_reg_xscale - returns the current FW status value
  * @regs:			MFI register set
  */
@@ -185,6 +200,7 @@
 
 	.fire_cmd = megasas_fire_cmd_xscale,
 	.enable_intr = megasas_enable_intr_xscale,
+	.disable_intr = megasas_disable_intr_xscale,
 	.clear_intr = megasas_clear_intr_xscale,
 	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
 };
@@ -215,6 +231,19 @@
 }
 
 /**
+ * megasas_disable_intr_ppc -	Disable interrupt
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+	u32 mask = 0xFFFFFFFF;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
  * megasas_read_fw_status_reg_ppc - returns the current FW status value
  * @regs:			MFI register set
  */
@@ -265,6 +294,7 @@
 	
 	.fire_cmd = megasas_fire_cmd_ppc,
 	.enable_intr = megasas_enable_intr_ppc,
+	.disable_intr = megasas_disable_intr_ppc,
 	.clear_intr = megasas_clear_intr_ppc,
 	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
 };
@@ -275,25 +305,6 @@
 */
 
 /**
- * megasas_disable_intr -	Disables interrupts
- * @regs:			MFI register set
- */
-static inline void
-megasas_disable_intr(struct megasas_instance *instance)
-{
-	u32 mask = 0x1f; 
-	struct megasas_register_set __iomem *regs = instance->reg_set;
-
-	if(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078R)
-		mask = 0xffffffff;
-
-	writel(mask, &regs->outbound_intr_mask);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
  * megasas_issue_polled -	Issues a polling command
  * @instance:			Adapter soft state
  * @cmd:			Command packet to be issued 
@@ -336,6 +347,7 @@
  * @cmd:			Command to be issued
  *
  * This function waits on an event for the command to be returned from ISR.
+ * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
  * Used to issue ioctl commands.
  */
 static int
@@ -346,7 +358,8 @@
 
 	instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
 
-	wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA));
+	wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA),
+		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
 
 	return 0;
 }
@@ -358,7 +371,8 @@
  *
  * MFI firmware can abort previously issued AEN comamnd (automatic event
  * notification). The megasas_issue_blocked_abort_cmd() issues such abort
- * cmd and blocks till it is completed.
+ * cmd and waits for return status.
+ * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
  */
 static int
 megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
@@ -392,7 +406,8 @@
 	/*
 	 * Wait for this cmd to complete
 	 */
-	wait_event(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF));
+	wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF),
+		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
 
 	megasas_return_cmd(instance, cmd);
 	return 0;
@@ -495,6 +510,46 @@
 	return sge_count;
 }
 
+ /**
+ * megasas_get_frame_count - Computes the number of frames
+ * @sge_count		: number of sg elements
+ *
+ * Returns the number of frames required for numnber of sge's (sge_count)
+ */
+
+u32 megasas_get_frame_count(u8 sge_count)
+{
+	int num_cnt;
+	int sge_bytes;
+	u32 sge_sz;
+	u32 frame_count=0;
+
+	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+	    sizeof(struct megasas_sge32);
+
+	/*
+	* Main frame can contain 2 SGEs for 64-bit SGLs and
+	* 3 SGEs for 32-bit SGLs
+	*/
+	if (IS_DMA64)
+		num_cnt = sge_count - 2;
+	else
+		num_cnt = sge_count - 3;
+
+	if(num_cnt>0){
+		sge_bytes = sge_sz * num_cnt;
+
+		frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
+		    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ;
+	}
+	/* Main frame */
+	frame_count +=1;
+
+	if (frame_count > 7)
+		frame_count = 8;
+	return frame_count;
+}
+
 /**
  * megasas_build_dcdb -	Prepares a direct cdb (DCDB) command
  * @instance:		Adapter soft state
@@ -508,8 +563,6 @@
 megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
 		   struct megasas_cmd *cmd)
 {
-	u32 sge_sz;
-	int sge_bytes;
 	u32 is_logical;
 	u32 device_id;
 	u16 flags = 0;
@@ -544,9 +597,6 @@
 	/*
 	 * Construct SGL
 	 */
-	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
-	    sizeof(struct megasas_sge32);
-
 	if (IS_DMA64) {
 		pthru->flags |= MFI_FRAME_SGL64;
 		pthru->sge_count = megasas_make_sgl64(instance, scp,
@@ -562,17 +612,11 @@
 	pthru->sense_buf_phys_addr_hi = 0;
 	pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
 
-	sge_bytes = sge_sz * pthru->sge_count;
-
 	/*
 	 * Compute the total number of frames this command consumes. FW uses
 	 * this number to pull sufficient number of frames from host memory.
 	 */
-	cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
-	    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1;
-
-	if (cmd->frame_count > 7)
-		cmd->frame_count = 8;
+	cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
 
 	return cmd->frame_count;
 }
@@ -589,8 +633,6 @@
 megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
 		   struct megasas_cmd *cmd)
 {
-	u32 sge_sz;
-	int sge_bytes;
 	u32 device_id;
 	u8 sc = scp->cmnd[0];
 	u16 flags = 0;
@@ -605,7 +647,7 @@
 		flags = MFI_FRAME_DIR_READ;
 
 	/*
-	 * Preare the Logical IO frame: 2nd bit is zero for all read cmds
+	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
 	 */
 	ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ;
 	ldio->cmd_status = 0x0;
@@ -674,9 +716,6 @@
 	/*
 	 * Construct SGL
 	 */
-	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
-	    sizeof(struct megasas_sge32);
-
 	if (IS_DMA64) {
 		ldio->flags |= MFI_FRAME_SGL64;
 		ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
@@ -690,13 +729,11 @@
 	ldio->sense_buf_phys_addr_hi = 0;
 	ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
 
-	sge_bytes = sge_sz * ldio->sge_count;
-
-	cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
-	    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1;
-
-	if (cmd->frame_count > 7)
-		cmd->frame_count = 8;
+	/*
+	 * Compute the total number of frames this command consumes. FW uses
+	 * this number to pull sufficient number of frames from host memory.
+	 */
+	cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
 
 	return cmd->frame_count;
 }
@@ -727,6 +764,69 @@
 	}
 }
 
+ /**
+ * megasas_dump_pending_frames -	Dumps the frame address of all pending cmds
+ *                              	in FW
+ * @instance:				Adapter soft state
+ */
+static inline void
+megasas_dump_pending_frames(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	int i,n;
+	union megasas_sgl *mfi_sgl;
+	struct megasas_io_frame *ldio;
+	struct megasas_pthru_frame *pthru;
+	u32 sgcount;
+	u32 max_cmd = instance->max_fw_cmds;
+
+	printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no);
+	printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding));
+	if (IS_DMA64)
+		printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no);
+	else
+		printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no);
+
+	printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no);
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		if(!cmd->scmd)
+			continue;
+		printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
+		if (megasas_is_ldio(cmd->scmd)){
+			ldio = (struct megasas_io_frame *)cmd->frame;
+			mfi_sgl = &ldio->sgl;
+			sgcount = ldio->sge_count;
+			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount);
+		}
+		else {
+			pthru = (struct megasas_pthru_frame *) cmd->frame;
+			mfi_sgl = &pthru->sgl;
+			sgcount = pthru->sge_count;
+			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount);
+		}
+	if(megasas_dbg_lvl & MEGASAS_DBG_LVL){
+		for (n = 0; n < sgcount; n++){
+			if (IS_DMA64)
+				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ;
+			else
+				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ;
+			}
+		}
+		printk(KERN_ERR "\n");
+	} /*for max_cmd*/
+	printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no);
+	for (i = 0; i < max_cmd; i++) {
+
+		cmd = instance->cmd_list[i];
+
+		if(cmd->sync_cmd == 1){
+			printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
+		}
+	}
+	printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
+}
+
 /**
  * megasas_queue_command -	Queue entry point
  * @scmd:			SCSI command to be queued
@@ -832,6 +932,13 @@
 	}
 
 	if (atomic_read(&instance->fw_outstanding)) {
+		/*
+		* Send signal to FW to stop processing any pending cmds.
+		* The controller will be taken offline by the OS now.
+		*/
+		writel(MFI_STOP_ADP,
+				&instance->reg_set->inbound_doorbell);
+		megasas_dump_pending_frames(instance);
 		instance->hw_crit_error = 1;
 		return FAILED;
 	}
@@ -1168,11 +1275,6 @@
 static int
 megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
 {
-	u32 producer;
-	u32 consumer;
-	u32 context;
-	struct megasas_cmd *cmd;
-
 	/*
 	 * Check if it is our interrupt
 	 * Clear the interrupt 
@@ -1180,23 +1282,10 @@
 	if(instance->instancet->clear_intr(instance->reg_set))
 		return IRQ_NONE;
 
-	producer = *instance->producer;
-	consumer = *instance->consumer;
-
-	while (consumer != producer) {
-		context = instance->reply_queue[consumer];
-
-		cmd = instance->cmd_list[context];
-
-		megasas_complete_cmd(instance, cmd, alt_status);
-
-		consumer++;
-		if (consumer == (instance->max_fw_cmds + 1)) {
-			consumer = 0;
-		}
-	}
-
-	*instance->consumer = producer;
+        /*
+	 * Schedule the tasklet for cmd completion
+	 */
+	tasklet_schedule(&instance->isr_tasklet);
 
 	return IRQ_HANDLED;
 }
@@ -1204,7 +1293,7 @@
 /**
  * megasas_isr - isr entry point
  */
-static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs)
+static irqreturn_t megasas_isr(int irq, void *devp)
 {
 	return megasas_deplete_reply_queue((struct megasas_instance *)devp,
 					   DID_OK);
@@ -1229,10 +1318,12 @@
 
 	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
 
+	if (fw_state != MFI_STATE_READY)
+ 		printk(KERN_INFO "megasas: Waiting for FW to come to ready"
+ 		       " state\n");
+
 	while (fw_state != MFI_STATE_READY) {
 
-		printk(KERN_INFO "megasas: Waiting for FW to come to ready"
-		       " state\n");
 		switch (fw_state) {
 
 		case MFI_STATE_FAULT:
@@ -1244,19 +1335,27 @@
 			/*
 			 * Set the CLR bit in inbound doorbell
 			 */
-			writel(MFI_INIT_CLEAR_HANDSHAKE,
+			writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
 				&instance->reg_set->inbound_doorbell);
 
 			max_wait = 2;
 			cur_state = MFI_STATE_WAIT_HANDSHAKE;
 			break;
 
+		case MFI_STATE_BOOT_MESSAGE_PENDING:
+			writel(MFI_INIT_HOTPLUG,
+				&instance->reg_set->inbound_doorbell);
+
+			max_wait = 10;
+			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
+			break;
+
 		case MFI_STATE_OPERATIONAL:
 			/*
-			 * Bring it to READY state; assuming max wait 2 secs
+			 * Bring it to READY state; assuming max wait 10 secs
 			 */
-			megasas_disable_intr(instance);
-			writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
+			instance->instancet->disable_intr(instance->reg_set);
+			writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
 
 			max_wait = 10;
 			cur_state = MFI_STATE_OPERATIONAL;
@@ -1323,6 +1422,7 @@
 			return -ENODEV;
 		}
 	};
+ 	printk(KERN_INFO "megasas: FW now in Ready state\n");
 
 	return 0;
 }
@@ -1352,7 +1452,7 @@
 				      cmd->frame_phys_addr);
 
 		if (cmd->sense)
-			pci_pool_free(instance->sense_dma_pool, cmd->frame,
+			pci_pool_free(instance->sense_dma_pool, cmd->sense,
 				      cmd->sense_phys_addr);
 	}
 
@@ -1628,6 +1728,39 @@
 }
 
 /**
+ * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
+ * @instance_addr:			Address of adapter soft state
+ *
+ * Tasklet to complete cmds
+ */
+void megasas_complete_cmd_dpc(unsigned long instance_addr)
+{
+	u32 producer;
+	u32 consumer;
+	u32 context;
+	struct megasas_cmd *cmd;
+	struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
+
+	producer = *instance->producer;
+	consumer = *instance->consumer;
+
+	while (consumer != producer) {
+		context = instance->reply_queue[consumer];
+
+		cmd = instance->cmd_list[context];
+
+		megasas_complete_cmd(instance, cmd, DID_OK);
+
+		consumer++;
+		if (consumer == (instance->max_fw_cmds + 1)) {
+			consumer = 0;
+		}
+	}
+
+	*instance->consumer = producer;
+}
+
+/**
  * megasas_init_mfi -	Initializes the FW
  * @instance:		Adapter soft state
  *
@@ -1690,6 +1823,12 @@
 	 * Get various operational parameters from status register
 	 */
 	instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
+	/*
+	 * Reduce the max supported cmds by 1. This is to ensure that the
+	 * reply_q_sz (1 more than the max cmd that driver may send)
+	 * does not exceed max cmds that the FW can support
+	 */
+	instance->max_fw_cmds = instance->max_fw_cmds-1;
 	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> 
 					0x10;
 	/*
@@ -1754,7 +1893,7 @@
 	/*
 	 * disable the intr before firing the init frame to FW
 	 */
-	megasas_disable_intr(instance);
+	instance->instancet->disable_intr(instance->reg_set);
 
 	/*
 	 * Issue the init frame in polled mode
@@ -1791,6 +1930,12 @@
 
 	kfree(ctrl_info);
 
+        /*
+	* Setup tasklet for cmd completion
+	*/
+
+        tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+                        (unsigned long)instance);
 	return 0;
 
       fail_fw_init:
@@ -2182,6 +2327,8 @@
 	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
 	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
 
+	megasas_dbg_lvl = 0;
+
 	/*
 	 * Initialize MFI Firmware
 	 */
@@ -2234,7 +2381,7 @@
 	megasas_mgmt_info.max_index--;
 
 	pci_set_drvdata(pdev, NULL);
-	megasas_disable_intr(instance);
+	instance->instancet->disable_intr(instance->reg_set);
 	free_irq(instance->pdev->irq, instance);
 
 	megasas_release_mfi(instance);
@@ -2348,6 +2495,7 @@
 	scsi_remove_host(instance->host);
 	megasas_flush_cache(instance);
 	megasas_shutdown_controller(instance);
+	tasklet_kill(&instance->isr_tasklet);
 
 	/*
 	 * Take the instance off the instance array. Note that we will not
@@ -2364,7 +2512,7 @@
 
 	pci_set_drvdata(instance->pdev, NULL);
 
-	megasas_disable_intr(instance);
+	instance->instancet->disable_intr(instance->reg_set);
 
 	free_irq(instance->pdev->irq, instance);
 
@@ -2716,7 +2864,8 @@
 	int i;
 	int error = 0;
 
-	clear_user(ioc, sizeof(*ioc));
+	if (clear_user(ioc, sizeof(*ioc)))
+		return -EFAULT;
 
 	if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
 	    copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
@@ -2808,6 +2957,26 @@
 static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
 		   NULL);
 
+static ssize_t
+megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
+{
+	return sprintf(buf,"%u",megasas_dbg_lvl);
+}
+
+static ssize_t
+megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count)
+{
+	int retval = count;
+	if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){
+		printk(KERN_ERR "megasas: could not set dbg_lvl\n");
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
+		   megasas_sysfs_set_dbg_lvl);
+
 /**
  * megasas_init - Driver load entry point
  */
@@ -2842,14 +3011,33 @@
 
 	if (rval) {
 		printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n");
-		unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+		goto err_pcidrv;
 	}
 
-	driver_create_file(&megasas_pci_driver.driver, &driver_attr_version);
-	driver_create_file(&megasas_pci_driver.driver,
-			   &driver_attr_release_date);
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_version);
+	if (rval)
+		goto err_dcf_attr_ver;
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_release_date);
+	if (rval)
+		goto err_dcf_rel_date;
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_dbg_lvl);
+	if (rval)
+		goto err_dcf_dbg_lvl;
 
 	return rval;
+err_dcf_dbg_lvl:
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_release_date);
+err_dcf_rel_date:
+	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+err_dcf_attr_ver:
+	pci_unregister_driver(&megasas_pci_driver);
+err_pcidrv:
+	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+  	return rval;
 }
 
 /**
@@ -2857,9 +3045,11 @@
  */
 static void __exit megasas_exit(void)
 {
-	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_dbg_lvl);
 	driver_remove_file(&megasas_pci_driver.driver,
 			   &driver_attr_release_date);
+	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
 	pci_unregister_driver(&megasas_pci_driver);
 	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 3531a14..55eddcf 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,9 +18,9 @@
 /**
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.03.01"
-#define MEGASAS_RELDATE				"May 14, 2006"
-#define MEGASAS_EXT_VERSION			"Sun May 14 22:49:52 PDT 2006"
+#define MEGASAS_VERSION				"00.00.03.05"
+#define MEGASAS_RELDATE				"Oct 02, 2006"
+#define MEGASAS_EXT_VERSION			"Mon Oct 02 11:21:32 PDT 2006"
 
 /*
  * Device IDs
@@ -50,6 +50,7 @@
 #define MFI_STATE_WAIT_HANDSHAKE		0x60000000
 #define MFI_STATE_FW_INIT_2			0x70000000
 #define MFI_STATE_DEVICE_SCAN			0x80000000
+#define MFI_STATE_BOOT_MESSAGE_PENDING		0x90000000
 #define MFI_STATE_FLUSH_CACHE			0xA0000000
 #define MFI_STATE_READY				0xB0000000
 #define MFI_STATE_OPERATIONAL			0xC0000000
@@ -64,12 +65,18 @@
  * READY	: Move from OPERATIONAL to READY state; discard queue info
  * MFIMODE	: Discard (possible) low MFA posted in 64-bit mode (??)
  * CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver
+ * HOTPLUG	: Resume from Hotplug
+ * MFI_STOP_ADP	: Send signal to FW to stop processing
  */
-#define MFI_INIT_ABORT				0x00000000
+#define MFI_INIT_ABORT				0x00000001
 #define MFI_INIT_READY				0x00000002
 #define MFI_INIT_MFIMODE			0x00000004
 #define MFI_INIT_CLEAR_HANDSHAKE		0x00000008
-#define MFI_RESET_FLAGS				MFI_INIT_READY|MFI_INIT_MFIMODE
+#define MFI_INIT_HOTPLUG			0x00000010
+#define MFI_STOP_ADP				0x00000020
+#define MFI_RESET_FLAGS				MFI_INIT_READY| \
+						MFI_INIT_MFIMODE| \
+						MFI_INIT_ABORT
 
 /**
  * MFI frame flags
@@ -530,6 +537,8 @@
 #define MEGASAS_MAX_LUN				8
 #define MEGASAS_MAX_LD				64
 
+#define MEGASAS_DBG_LVL				1
+
 /*
  * When SCSI mid-layer calls driver's reset routine, driver waits for
  * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
@@ -538,6 +547,7 @@
  * every MEGASAS_RESET_NOTICE_INTERVAL seconds
  */
 #define MEGASAS_RESET_WAIT_TIME			180
+#define MEGASAS_INTERNAL_CMD_WAIT_TIME		180
 #define	MEGASAS_RESET_NOTICE_INTERVAL		5
 
 #define MEGASAS_IOCTL_CMD			0
@@ -1042,6 +1052,7 @@
 	void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
 
 	void (*enable_intr)(struct megasas_register_set __iomem *) ;
+	void (*disable_intr)(struct megasas_register_set __iomem *);
 
 	int (*clear_intr)(struct megasas_register_set __iomem *);
 
@@ -1092,6 +1103,7 @@
 	u32 hw_crit_error;
 
 	struct megasas_instance_template *instancet;
+	struct tasklet_struct isr_tasklet;
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 683fc7a..1fd3c75 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -185,7 +185,7 @@
  * Driver is too messy, we need a few prototypes...
  */
 static void mesh_done(struct mesh_state *ms, int start_next);
-static void mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs);
+static void mesh_interrupt(int irq, void *dev_id);
 static void cmd_complete(struct mesh_state *ms);
 static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd);
 static void halt_dma(struct mesh_state *ms);
@@ -466,7 +466,7 @@
 				dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x",
 				     MKWORD(mr->interrupt, mr->exception,
 					    mr->error, mr->fifo_count));
-				mesh_interrupt(0, (void *)ms, NULL);
+				mesh_interrupt(0, (void *)ms);
 				if (ms->phase != arbitrating)
 					return;
 			}
@@ -504,7 +504,7 @@
 		dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x",
 		     MKWORD(mr->interrupt, mr->exception,
 			    mr->error, mr->fifo_count));
-		mesh_interrupt(0, (void *)ms, NULL);
+		mesh_interrupt(0, (void *)ms);
 		if (ms->phase != arbitrating)
 			return;
 		dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x",
@@ -1015,13 +1015,13 @@
 	out_8(&mr->sequence, SEQ_ENBRESEL);
 }
 
-static irqreturn_t do_mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t do_mesh_interrupt(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = ((struct mesh_state *)dev_id)->host;
 	
 	spin_lock_irqsave(dev->host_lock, flags);
-	mesh_interrupt(irq, dev_id, ptregs);
+	mesh_interrupt(irq, dev_id);
 	spin_unlock_irqrestore(dev->host_lock, flags);
 	return IRQ_HANDLED;
 }
@@ -1661,7 +1661,7 @@
  * handler (do_mesh_interrupt) or by other functions in
  * exceptional circumstances
  */
-static void mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static void mesh_interrupt(int irq, void *dev_id)
 {
 	struct mesh_state *ms = (struct mesh_state *) dev_id;
 	volatile struct mesh_regs __iomem *mr = ms->mesh;
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index 9b991b7..1ddd7a1 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -20,7 +20,7 @@
 
 static struct Scsi_Host *mvme147_host = NULL;
 
-static irqreturn_t mvme147_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t mvme147_intr (int irq, void *dummy)
 {
     if (irq == MVME147_IRQ_SCSI_PORT)
 	wd33c93_intr (mvme147_host);
diff --git a/drivers/scsi/mvme16x.h b/drivers/scsi/mvme16x.h
index c7a1253..73e33b3 100644
--- a/drivers/scsi/mvme16x.h
+++ b/drivers/scsi/mvme16x.h
@@ -9,7 +9,7 @@
 int NCR53c7xx_abort(Scsi_Cmnd *);
 int NCR53c7x0_release (struct Scsi_Host *);
 int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+void NCR53c7x0_intr(int irq, void *dev_id);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 3
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index b28712d..6cc2bc2 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -8111,7 +8111,7 @@
      return sts;
 }
 
-irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t ncr53c8xx_intr(int irq, void *dev_id)
 {
      unsigned long flags;
      struct Scsi_Host *shost = (struct Scsi_Host *)dev_id;
diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
index 78818b6..cb8b770 100644
--- a/drivers/scsi/ncr53c8xx.h
+++ b/drivers/scsi/ncr53c8xx.h
@@ -1322,7 +1322,7 @@
 
 extern struct Scsi_Host *ncr_attach(struct scsi_host_template *tpnt, int unit, struct ncr_device *device);
 extern int ncr53c8xx_release(struct Scsi_Host *host);
-irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
+irqreturn_t ncr53c8xx_intr(int irq, void *dev_id);
 extern int ncr53c8xx_init(void);
 extern void ncr53c8xx_exit(void);
 
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index bfb4f49..7c13f6f 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -256,7 +256,7 @@
 static void nsp32_do_bus_reset(nsp32_hw_data *);
 
 /* hardware interrupt handler */
-static irqreturn_t do_nsp32_isr(int, void *, struct pt_regs *);
+static irqreturn_t do_nsp32_isr(int, void *);
 
 /* initialize hardware */
 static int  nsp32hw_init(nsp32_hw_data *);
@@ -1201,7 +1201,7 @@
 
 
 /* interrupt routine */
-static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_nsp32_isr(int irq, void *dev_id)
 {
 	nsp32_hw_data *data = dev_id;
 	unsigned int base = data->BaseAddress;
@@ -3581,7 +3581,7 @@
  */
 static int __init init_nsp32(void) {
 	nsp32_msg(KERN_INFO, "loading...");
-	return pci_module_init(&nsp32_driver);
+	return pci_register_driver(&nsp32_driver);
 }
 
 static void __exit exit_nsp32(void) {
diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h
index 5addf9f..a976e81 100644
--- a/drivers/scsi/nsp32.h
+++ b/drivers/scsi/nsp32.h
@@ -619,47 +619,5 @@
 #define REQSACK_TIMEOUT_TIME	10000	/* max wait time for REQ/SACK assertion
 					   or negation, 10000us == 10ms */
 
-/**************************************************************************
- * Compatibility functions
- */
-
-/* for Kernel 2.4 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-# define scsi_register_host(template) 	scsi_register_module(MODULE_SCSI_HA, template)
-# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template)
-# define scsi_host_put(host)            scsi_unregister(host)
-# define pci_name(pci_dev)              ((pci_dev)->slot_name)
-
-typedef void irqreturn_t;
-# define IRQ_NONE      /* */
-# define IRQ_HANDLED   /* */
-# define IRQ_RETVAL(x) /* */
-
-/* This is ad-hoc version of scsi_host_get_next() */
-static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host)
-{
-	if (host == NULL) {
-		return scsi_hostlist;
-	} else {
-		return host->next;
-	}
-}
-
-/* This is ad-hoc version of scsi_host_hn_get() */
-static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
-{
-	struct Scsi_Host *host;
-
-	for (host = scsi_host_get_next(NULL); host != NULL;
-	     host = scsi_host_get_next(host)) {
-		if (host->host_no == hostno) {
-			break;
-		}
-	}
-
-	return host;
-}
-#endif
-
 #endif /* _NSP32_H */
 /* end */
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 4a2fed3..824fe08 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -4843,8 +4843,7 @@
 static int osst_ioctl(struct inode * inode,struct file * file,
 	 unsigned int cmd_in, unsigned long arg)
 {
-	int		      i, cmd_nr, cmd_type, retval = 0;
-	unsigned int	      blk;
+	int		      i, cmd_nr, cmd_type, blk, retval = 0;
 	struct st_modedef   * STm;
 	struct st_partstat  * STps;
 	struct osst_request * SRpnt = NULL;
@@ -5207,12 +5206,12 @@
 		priority = GFP_KERNEL;
 
 	i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
-	tb = (struct osst_buffer *)kmalloc(i, priority);
+	tb = kzalloc(i, priority);
 	if (!tb) {
 		printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
 		return NULL;
 	}
-	memset(tb, 0, i);
+
 	tb->sg_segs = tb->orig_sg_segs = 0;
 	tb->use_sg = max_sg;
 	tb->in_use = 1;
@@ -5575,9 +5574,9 @@
 
 static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
 
-static void osst_create_driverfs_files(struct device_driver *driverfs)
+static int osst_create_driverfs_files(struct device_driver *driverfs)
 {
-	driver_create_file(driverfs, &driver_attr_version);
+	return driver_create_file(driverfs, &driver_attr_version);
 }
 
 static void osst_remove_driverfs_files(struct device_driver *driverfs)
@@ -5663,50 +5662,70 @@
 
 static struct class *osst_sysfs_class;
 
-static int osst_sysfs_valid = 0;
-
-static void osst_sysfs_init(void)
+static int osst_sysfs_init(void)
 {
 	osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
-	if ( IS_ERR(osst_sysfs_class) )
-		printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
-	else
-		osst_sysfs_valid = 1;
-}
-
-static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
-{
-	struct class_device *osst_class_member;
-
-	if (!osst_sysfs_valid) return;
-
-	osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name);
-	if (IS_ERR(osst_class_member)) {
-		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
-		return;
+	if (IS_ERR(osst_sysfs_class)) {
+		printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
+		return PTR_ERR(osst_sysfs_class);
 	}
-	class_set_devdata(osst_class_member, STp);
-	class_device_create_file(osst_class_member, &class_device_attr_ADR_rev);
-	class_device_create_file(osst_class_member, &class_device_attr_media_version);
-	class_device_create_file(osst_class_member, &class_device_attr_capacity);
-	class_device_create_file(osst_class_member, &class_device_attr_BOT_frame);
-	class_device_create_file(osst_class_member, &class_device_attr_EOD_frame);
-	class_device_create_file(osst_class_member, &class_device_attr_file_count);
+
+	return 0;
 }
 
 static void osst_sysfs_destroy(dev_t dev)
 {
-	if (!osst_sysfs_valid) return; 
-
 	class_device_destroy(osst_sysfs_class, dev);
 }
 
+static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+{
+	struct class_device *osst_class_member;
+	int err;
+
+	osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
+						device, "%s", name);
+	if (IS_ERR(osst_class_member)) {
+		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+		return PTR_ERR(osst_class_member);
+	}
+
+	class_set_devdata(osst_class_member, STp);
+	err = class_device_create_file(osst_class_member,
+				       &class_device_attr_ADR_rev);
+	if (err)
+		goto err_out;
+	err = class_device_create_file(osst_class_member,
+				       &class_device_attr_media_version);
+	if (err)
+		goto err_out;
+	err = class_device_create_file(osst_class_member,
+				       &class_device_attr_capacity);
+	if (err)
+		goto err_out;
+	err = class_device_create_file(osst_class_member,
+				       &class_device_attr_BOT_frame);
+	if (err)
+		goto err_out;
+	err = class_device_create_file(osst_class_member,
+				       &class_device_attr_EOD_frame);
+	if (err)
+		goto err_out;
+	err = class_device_create_file(osst_class_member,
+				       &class_device_attr_file_count);
+	if (err)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	osst_sysfs_destroy(dev);
+	return err;
+}
+
 static void osst_sysfs_cleanup(void)
 {
-	if (osst_sysfs_valid) {
-		class_destroy(osst_sysfs_class);
-		osst_sysfs_valid = 0;
-	}
+	class_destroy(osst_sysfs_class);
 }
 
 /*
@@ -5721,7 +5740,7 @@
 	struct st_partstat * STps;
 	struct osst_buffer * buffer;
 	struct gendisk	   * drive;
-	int		     i, dev_num;
+	int		     i, dev_num, err = -ENODEV;
 
 	if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
 		return -ENODEV;
@@ -5849,13 +5868,20 @@
 	init_MUTEX(&tpnt->lock);
 	osst_nr_dev++;
 	write_unlock(&os_scsi_tapes_lock);
+
 	{
 		char name[8];
+
 		/*  Rewind entry  */
-		osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
+		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
+		if (err)
+			goto out_free_buffer;
+
 		/*  No-rewind entry  */
 		snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
-		osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+		err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+		if (err)
+			goto out_free_sysfs1;
 	}
 
 	sdev_printk(KERN_INFO, SDp,
@@ -5864,9 +5890,13 @@
 
 	return 0;
 
+out_free_sysfs1:
+	osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
+out_free_buffer:
+	kfree(buffer);
 out_put_disk:
         put_disk(drive);
-        return -ENODEV;
+        return err;
 };
 
 static int osst_remove(struct device *dev)
@@ -5903,19 +5933,39 @@
 
 static int __init init_osst(void) 
 {
+	int err;
+
 	printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
 
 	validate_options();
-	osst_sysfs_init();
 
-	if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
+	err = osst_sysfs_init();
+	if (err)
+		return err;
+
+	err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
+	if (err < 0) {
 		printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
-		osst_sysfs_cleanup();
-		return 1;
+		goto err_out;
 	}
-	osst_create_driverfs_files(&osst_template.gendrv);
+
+	err = scsi_register_driver(&osst_template.gendrv);
+	if (err)
+		goto err_out_chrdev;
+
+	err = osst_create_driverfs_files(&osst_template.gendrv);
+	if (err)
+		goto err_out_scsidrv;
 
 	return 0;
+
+err_out_scsidrv:
+	scsi_unregister_driver(&osst_template.gendrv);
+err_out_chrdev:
+	unregister_chrdev(OSST_MAJOR, "osst");
+err_out:
+	osst_sysfs_cleanup();
+	return err;
 }
 
 static void __exit exit_osst (void)
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 0d4c04e..b1d3460 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -80,7 +80,6 @@
 module_param(free_ports, bool, 0);
 MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))");
 
-/* /usr/src/linux/drivers/scsi/hosts.h */
 static struct scsi_host_template nsp_driver_template = {
 	.proc_name	         = "nsp_cs",
 	.proc_info		 = nsp_proc_info,
@@ -949,7 +948,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t nspintr(int irq, void *dev_id)
 {
 	unsigned int   base;
 	unsigned char  irq_status, irq_phase, phase;
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 8908b8e..a88714f 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -346,7 +346,7 @@
 static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht);
 
 /* Interrupt handler */
-//static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs);
+//static irqreturn_t nspintr(int irq, void *dev_id);
 
 /* Module entry point*/
 static int  __init nsp_cs_init(void);
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 0b65099..72fe5d0 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -363,7 +363,7 @@
 }
 
 static irqreturn_t
-SYM53C500_intr(int irq, void *dev_id, struct pt_regs *regs)
+SYM53C500_intr(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = dev_id;
diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c
index 5c2cdf5..a720c92 100644
--- a/drivers/scsi/psi240i.c
+++ b/drivers/scsi/psi240i.c
@@ -247,12 +247,11 @@
  *
  *	Parameters:		irq		- Hardware IRQ number.
  *					dev_id	-
- *					regs	-
  *
  *	Returns:		TRUE if drive is not ready in time.
  *
  ****************************************************************/
-static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
+static void Irq_Handler (int irq, void *dev_id)
 	{
 	struct Scsi_Host   *shost;			// Pointer to host data block
 	PADAPTER240I		padapter;		// Pointer to adapter control structure
@@ -368,13 +367,13 @@
 	SCpnt->scsi_done (SCpnt);
 	}
 
-static irqreturn_t do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_Irq_Handler (int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = dev_id;
 	
 	spin_lock_irqsave(dev->host_lock, flags);
-	Irq_Handler(irq, dev_id, regs);
+	Irq_Handler(irq, dev_id);
 	spin_unlock_irqrestore(dev->host_lock, flags);
 	return IRQ_HANDLED;
 }
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 332151e..2521d54 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1113,7 +1113,7 @@
  *   Handles the H/W interrupt
  **************************************************************************/
 static irqreturn_t
-qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+qla1280_intr_handler(int irq, void *dev_id)
 {
 	struct scsi_qla_host *ha;
 	struct device_reg __iomem *reg;
@@ -2862,7 +2862,7 @@
 	memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
 
 	/* Set ISP command timeout. */
-	pkt->timeout = cpu_to_le16(30);
+	pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ);
 
 	/* Set device target ID and LUN */
 	pkt->lun = SCSI_LUN_32(cmd);
@@ -3161,7 +3161,7 @@
 	memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
 
 	/* Set ISP command timeout. */
-	pkt->timeout = cpu_to_le16(30);
+	pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ);
 
 	/* Set device target ID and LUN */
 	pkt->lun = SCSI_LUN_32(cmd);
@@ -4484,7 +4484,7 @@
 		qla1280_setup(qla1280);
 #endif
 
-	return pci_module_init(&qla1280_pci_driver);
+	return pci_register_driver(&qla1280_pci_driver);
 }
 
 static void __exit
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 87f90c4..ee75a71 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -691,13 +691,13 @@
 	uint32_t speed = 0;
 
 	switch (ha->link_data_rate) {
-	case LDR_1GB:
+	case PORT_SPEED_1GB:
 		speed = 1;
 		break;
-	case LDR_2GB:
+	case PORT_SPEED_2GB:
 		speed = 2;
 		break;
-	case LDR_4GB:
+	case PORT_SPEED_4GB:
 		speed = 4;
 		break;
 	}
@@ -849,6 +849,49 @@
 	return pfc_host_stat;
 }
 
+static void
+qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
+{
+	scsi_qla_host_t *ha = to_qla_host(shost);
+
+	qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost));
+}
+
+static void
+qla2x00_set_host_system_hostname(struct Scsi_Host *shost)
+{
+	scsi_qla_host_t *ha = to_qla_host(shost);
+
+	set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
+}
+
+static void
+qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
+{
+	scsi_qla_host_t *ha = to_qla_host(shost);
+	u64 node_name;
+
+	if (ha->device_flags & SWITCH_FOUND)
+		node_name = wwn_to_u64(ha->fabric_node_name);
+	else
+		node_name = wwn_to_u64(ha->node_name);
+
+	fc_host_fabric_name(shost) = node_name;
+}
+
+static void
+qla2x00_get_host_port_state(struct Scsi_Host *shost)
+{
+	scsi_qla_host_t *ha = to_qla_host(shost);
+
+	if (!ha->flags.online)
+		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+	else if (atomic_read(&ha->loop_state) == LOOP_TIMEOUT)
+		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+	else
+		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+}
+
 struct fc_function_template qla2xxx_transport_functions = {
 
 	.show_host_node_name = 1,
@@ -861,6 +904,14 @@
 	.show_host_speed = 1,
 	.get_host_port_type = qla2x00_get_host_port_type,
 	.show_host_port_type = 1,
+	.get_host_symbolic_name = qla2x00_get_host_symbolic_name,
+	.show_host_symbolic_name = 1,
+	.set_host_system_hostname = qla2x00_set_host_system_hostname,
+	.show_host_system_hostname = 1,
+	.get_host_fabric_name = qla2x00_get_host_fabric_name,
+	.show_host_fabric_name = 1,
+	.get_host_port_state = qla2x00_get_host_port_state,
+	.show_host_port_state = 1,
 
 	.dd_fcrport_size = sizeof(struct fc_port *),
 	.show_rport_supported_classes = 1,
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 5334253..90dad7e 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -38,7 +38,7 @@
 * Macros use for debugging the driver.
 */
 
-#define DEBUG(x)	do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
 
 #if defined(QL_DEBUG_LEVEL_1)
 #define DEBUG1(x)	do {x;} while (0)
@@ -46,12 +46,12 @@
 #define DEBUG1(x)	do {} while (0)
 #endif
 
-#define DEBUG2(x)	do { if (extended_error_logging) { x; } } while (0)
-#define DEBUG2_3(x)	do { if (extended_error_logging) { x; } } while (0)
-#define DEBUG2_3_11(x)	do { if (extended_error_logging) { x; } } while (0)
-#define DEBUG2_9_10(x)	do { if (extended_error_logging) { x; } } while (0)
-#define DEBUG2_11(x)	do { if (extended_error_logging) { x; } } while (0)
-#define DEBUG2_13(x)	do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG2(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
+#define DEBUG2_3(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
+#define DEBUG2_3_11(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
+#define DEBUG2_9_10(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
+#define DEBUG2_11(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
+#define DEBUG2_13(x)	do { if (qla2_extended_error_logging) { x; } } while (0)
 
 #if defined(QL_DEBUG_LEVEL_3)
 #define DEBUG3(x)	do {x;} while (0)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 0930260..bab33f6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -608,6 +608,7 @@
  */
 #define MBC_SERDES_PARAMS		0x10	/* Serdes Tx Parameters. */
 #define MBC_GET_IOCB_STATUS		0x12	/* Get IOCB status command. */
+#define MBC_PORT_PARAMS			0x1A	/* Port iDMA Parameters. */
 #define MBC_GET_TIMEOUT_PARAMS		0x22	/* Get FW timeouts. */
 #define MBC_TRACE_CONTROL		0x27	/* Trace control command. */
 #define MBC_GEN_SYSTEM_ERROR		0x2a	/* Generate System Error. */
@@ -1497,6 +1498,9 @@
 	port_id_t d_id;
 	uint8_t node_name[WWN_SIZE];
 	uint8_t port_name[WWN_SIZE];
+	uint8_t fabric_port_name[WWN_SIZE];
+	uint16_t fp_speeds;
+	uint16_t fp_speed;
 } sw_info_t;
 
 /*
@@ -1524,6 +1528,9 @@
 	uint16_t loop_id;
 	uint16_t old_loop_id;
 
+	uint8_t fabric_port_name[WWN_SIZE];
+	uint16_t fp_speed;
+
 	fc_port_type_t port_type;
 
 	atomic_t state;
@@ -1635,6 +1642,15 @@
 #define	RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255)
 #define	RSNN_NN_RSP_SIZE 16
 
+#define	GFPN_ID_CMD	0x11C
+#define	GFPN_ID_REQ_SIZE (16 + 4)
+#define	GFPN_ID_RSP_SIZE (16 + 8)
+
+#define	GPSC_CMD	0x127
+#define	GPSC_REQ_SIZE	(16 + 8)
+#define	GPSC_RSP_SIZE	(16 + 2 + 2)
+
+
 /*
  * HBA attribute types.
  */
@@ -1748,7 +1764,7 @@
 	uint8_t reserved[3];
 
 	union {
-		/* GA_NXT, GPN_ID, GNN_ID, GFT_ID */
+		/* GA_NXT, GPN_ID, GNN_ID, GFT_ID, GFPN_ID */
 		struct {
 			uint8_t reserved;
 			uint8_t port_id[3];
@@ -1823,6 +1839,10 @@
 		struct {
 			uint8_t port_name[8];
 		} dpa;
+
+		struct {
+			uint8_t port_name[8];
+		} gpsc;
 	} req;
 };
 
@@ -1886,6 +1906,15 @@
 			uint8_t port_name[8];
 			struct ct_fdmi_hba_attributes attrs;
 		} ghat;
+
+		struct {
+			uint8_t port_name[8];
+		} gfpn_id;
+
+		struct {
+			uint16_t speeds;
+			uint16_t speed;
+		} gpsc;
 	} rsp;
 };
 
@@ -1980,7 +2009,7 @@
 	char * (*pci_info_str) (struct scsi_qla_host *, char *);
 	char * (*fw_version_str) (struct scsi_qla_host *, char *);
 
-	irqreturn_t (*intr_handler) (int, void *, struct pt_regs *);
+	irq_handler_t intr_handler;
 	void (*enable_intrs) (struct scsi_qla_host *);
 	void (*disable_intrs) (struct scsi_qla_host *);
 
@@ -2182,11 +2211,11 @@
 	uint16_t	max_public_loop_ids;
 	uint16_t	min_external_loopid;	/* First external loop Id */
 
+#define PORT_SPEED_UNKNOWN 0xFFFF
+#define PORT_SPEED_1GB	0x00
+#define PORT_SPEED_2GB	0x01
+#define PORT_SPEED_4GB	0x03
 	uint16_t	link_data_rate;		/* F/W operating speed */
-#define LDR_1GB		0
-#define LDR_2GB		1
-#define LDR_4GB		3
-#define LDR_UNKNOWN	0xFFFF
 
 	uint8_t		current_topology;
 	uint8_t		prev_topology;
@@ -2333,6 +2362,7 @@
 
 	uint8_t		*node_name;
 	uint8_t		*port_name;
+	uint8_t		fabric_node_name[WWN_SIZE];
 	uint32_t    isp_abort_cnt;
 
 	/* Option ROM information. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 8311ac2b..7da6983 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -60,7 +60,7 @@
 extern int ql2xloginretrycount;
 extern int ql2xfdmienable;
 extern int ql2xallocfwdump;
-extern int extended_error_logging;
+extern int qla2_extended_error_logging;
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
@@ -208,12 +208,18 @@
 extern int
 qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
 
+extern int
+qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t *, uint16_t *);
+
+extern int
+qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
-extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *);
-extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *);
-extern irqreturn_t qla24xx_intr_handler(int, void *, struct pt_regs *);
+extern irqreturn_t qla2100_intr_handler(int, void *);
+extern irqreturn_t qla2300_intr_handler(int, void *);
+extern irqreturn_t qla24xx_intr_handler(int, void *);
 extern void qla2x00_process_response_queue(struct scsi_qla_host *);
 extern void qla24xx_process_response_queue(struct scsi_qla_host *);
 
@@ -279,6 +285,9 @@
 extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 extern int qla2x00_fdmi_register(scsi_qla_host_t *);
+extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
+extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
+extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 2ebf259..97fbc62 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -612,6 +612,14 @@
 	return (rval);
 }
 
+void
+qla2x00_get_sym_node_name(scsi_qla_host_t *ha, uint8_t *snn)
+{
+	sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s",ha->model_number,
+	    ha->fw_major_version, ha->fw_minor_version,
+	    ha->fw_subminor_version, qla2x00_version_str);
+}
+
 /**
  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
  * @ha: HA context
@@ -622,9 +630,6 @@
 qla2x00_rsnn_nn(scsi_qla_host_t *ha)
 {
 	int		rval;
-	uint8_t		*snn;
-	uint8_t		version[20];
-
 	ms_iocb_entry_t	*ms_pkt;
 	struct ct_sns_req	*ct_req;
 	struct ct_sns_rsp	*ct_rsp;
@@ -649,20 +654,11 @@
 	memcpy(ct_req->req.rsnn_nn.node_name, ha->node_name, WWN_SIZE);
 
 	/* Prepare the Symbolic Node Name */
-	/* Board type */
-	snn = ct_req->req.rsnn_nn.sym_node_name;
-	strcpy(snn, ha->model_number);
-	/* Firmware version */
-	strcat(snn, " FW:v");
-	sprintf(version, "%d.%02d.%02d", ha->fw_major_version,
-	    ha->fw_minor_version, ha->fw_subminor_version);
-	strcat(snn, version);
-	/* Driver version */
-	strcat(snn, " DVR:v");
-	strcat(snn, qla2x00_version_str);
+	qla2x00_get_sym_node_name(ha, ct_req->req.rsnn_nn.sym_node_name);
 
 	/* Calculate SNN length */
-	ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn);
+	ct_req->req.rsnn_nn.name_len =
+	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
 
 	/* Update MS IOCB request */
 	ms_pkt->req_bytecount =
@@ -687,7 +683,6 @@
 	return (rval);
 }
 
-
 /**
  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
  * @ha: HA context
@@ -1585,6 +1580,21 @@
 	DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no,
 	    eiter->a.os_dev_name));
 
+	/* Hostname. */
+	if (strlen(fc_host_system_hostname(ha->host))) {
+		eiter = (struct ct_fdmi_port_attr *) (entries + size);
+		eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
+		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
+		    "%s", fc_host_system_hostname(ha->host));
+		alen = strlen(eiter->a.host_name);
+		alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+		eiter->len = cpu_to_be16(4 + alen);
+		size += 4 + alen;
+
+		DEBUG13(printk("%s(%ld): HOSTNAME=%s.\n", __func__,
+		    ha->host_no, eiter->a.host_name));
+	}
+
 	/* Update MS request size. */
 	qla2x00_update_ms_fdmi_iocb(ha, size + 16);
 
@@ -1647,3 +1657,189 @@
 
 	return rval;
 }
+
+/**
+ * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
+ * @ha: HA context
+ * @list: switch info entries to populate
+ *
+ * Returns 0 on success.
+ */
+int
+qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list)
+{
+	int		rval;
+	uint16_t	i;
+
+	ms_iocb_entry_t	*ms_pkt;
+	struct ct_sns_req	*ct_req;
+	struct ct_sns_rsp	*ct_rsp;
+
+	if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
+		return QLA_FUNCTION_FAILED;
+
+	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
+		/* Issue GFPN_ID */
+		memset(list[i].fabric_port_name, 0, WWN_SIZE);
+
+		/* Prepare common MS IOCB */
+		ms_pkt = qla2x00_prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
+		    GFPN_ID_RSP_SIZE);
+
+		/* Prepare CT request */
+		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD,
+		    GFPN_ID_RSP_SIZE);
+		ct_rsp = &ha->ct_sns->p.rsp;
+
+		/* Prepare CT arguments -- port_id */
+		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
+		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
+		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
+
+		/* Execute MS IOCB */
+		rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+		    sizeof(ms_iocb_entry_t));
+		if (rval != QLA_SUCCESS) {
+			/*EMPTY*/
+			DEBUG2_3(printk("scsi(%ld): GFPN_ID issue IOCB "
+			    "failed (%d).\n", ha->host_no, rval));
+		} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
+		    "GFPN_ID") != QLA_SUCCESS) {
+			rval = QLA_FUNCTION_FAILED;
+		} else {
+			/* Save fabric portname */
+			memcpy(list[i].fabric_port_name,
+			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
+		}
+
+		/* Last device exit. */
+		if (list[i].d_id.b.rsvd_1 != 0)
+			break;
+	}
+
+	return (rval);
+}
+
+static inline void *
+qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+    uint32_t rsp_size)
+{
+	struct ct_entry_24xx *ct_pkt;
+
+	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
+
+	ct_pkt->entry_type = CT_IOCB_TYPE;
+	ct_pkt->entry_count = 1;
+	ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
+	ct_pkt->timeout = __constant_cpu_to_le16(59);
+	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
+	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
+	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+
+	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+
+	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+
+	return ct_pkt;
+}
+
+
+static inline struct ct_sns_req *
+qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd,
+    uint16_t rsp_size)
+{
+	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+
+	ct_req->header.revision = 0x01;
+	ct_req->header.gs_type = 0xFA;
+	ct_req->header.gs_subtype = 0x01;
+	ct_req->command = cpu_to_be16(cmd);
+	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+
+	return ct_req;
+}
+
+/**
+ * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
+ * @ha: HA context
+ * @list: switch info entries to populate
+ *
+ * Returns 0 on success.
+ */
+int
+qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
+{
+	int		rval;
+	uint16_t	i;
+
+	ms_iocb_entry_t	*ms_pkt;
+	struct ct_sns_req	*ct_req;
+	struct ct_sns_rsp	*ct_rsp;
+
+	if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
+		return QLA_FUNCTION_FAILED;
+
+	rval = qla2x00_mgmt_svr_login(ha);
+	if (rval)
+		return rval;
+
+	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
+		/* Issue GFPN_ID */
+		list[i].fp_speeds = list[i].fp_speed = 0;
+
+		/* Prepare common MS IOCB */
+		ms_pkt = qla24xx_prep_ms_fm_iocb(ha, GPSC_REQ_SIZE,
+		    GPSC_RSP_SIZE);
+
+		/* Prepare CT request */
+		ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req,
+		    GPSC_CMD, GPSC_RSP_SIZE);
+		ct_rsp = &ha->ct_sns->p.rsp;
+
+		/* Prepare CT arguments -- port_name */
+		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
+		    WWN_SIZE);
+
+		/* Execute MS IOCB */
+		rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+		    sizeof(ms_iocb_entry_t));
+		if (rval != QLA_SUCCESS) {
+			/*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) {
+			rval = QLA_FUNCTION_FAILED;
+		} else {
+			/* Save portname */
+			list[i].fp_speeds = ct_rsp->rsp.gpsc.speeds;
+			list[i].fp_speed = ct_rsp->rsp.gpsc.speed;
+
+			DEBUG2_3(printk("scsi(%ld): GPSC ext entry - "
+			    "fpn %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
+			    "speed=%04x.\n", ha->host_no,
+			    list[i].fabric_port_name[0],
+			    list[i].fabric_port_name[1],
+			    list[i].fabric_port_name[2],
+			    list[i].fabric_port_name[3],
+			    list[i].fabric_port_name[4],
+			    list[i].fabric_port_name[5],
+			    list[i].fabric_port_name[6],
+			    list[i].fabric_port_name[7],
+			    be16_to_cpu(list[i].fp_speeds),
+			    be16_to_cpu(list[i].fp_speed)));
+		}
+
+		/* Last device exit. */
+		if (list[i].d_id.b.rsvd_1 != 0)
+			break;
+	}
+
+	return (rval);
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 8596491..833b930 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1644,7 +1644,7 @@
 	 * Set host adapter parameters.
 	 */
 	if (nv->host_p[0] & BIT_7)
-		extended_error_logging = 1;
+		qla2_extended_error_logging = 1;
 	ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
 	/* Always load RISC code on non ISP2[12]00 chips. */
 	if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
@@ -2074,6 +2074,19 @@
 			new_fcport->flags &= ~FCF_FABRIC_DEVICE;
 		}
 
+		/* Base iIDMA settings on HBA port speed. */
+		switch (ha->link_data_rate) {
+		case PORT_SPEED_1GB:
+			fcport->fp_speed = cpu_to_be16(BIT_15);
+			break;
+		case PORT_SPEED_2GB:
+			fcport->fp_speed = cpu_to_be16(BIT_14);
+			break;
+		case PORT_SPEED_4GB:
+			fcport->fp_speed = cpu_to_be16(BIT_13);
+			break;
+		}
+
 		qla2x00_update_fcport(ha, fcport);
 
 		found_devs++;
@@ -2109,6 +2122,62 @@
 	}
 }
 
+static void
+qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+{
+#define LS_UNKNOWN      2
+	static char *link_speeds[5] = { "1", "2", "?", "4" };
+	int rval;
+	uint16_t port_speed, mb[6];
+
+	if (!IS_QLA24XX(ha))
+		return;
+
+	switch (be16_to_cpu(fcport->fp_speed)) {
+	case BIT_15:
+		port_speed = PORT_SPEED_1GB;
+		break;
+	case BIT_14:
+		port_speed = PORT_SPEED_2GB;
+		break;
+	case BIT_13:
+		port_speed = PORT_SPEED_4GB;
+		break;
+	default:
+		DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- "
+		    "unsupported FM port operating speed (%04x).\n",
+		    ha->host_no, fcport->port_name[0], fcport->port_name[1],
+		    fcport->port_name[2], fcport->port_name[3],
+		    fcport->port_name[4], fcport->port_name[5],
+		    fcport->port_name[6], fcport->port_name[7],
+		    be16_to_cpu(fcport->fp_speed)));
+		port_speed = PORT_SPEED_UNKNOWN;
+		break;
+	}
+	if (port_speed == PORT_SPEED_UNKNOWN)
+		return;
+
+	rval = qla2x00_set_idma_speed(ha, fcport->loop_id, port_speed, mb);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA "
+		    "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n",
+		    ha->host_no, fcport->port_name[0], fcport->port_name[1],
+		    fcport->port_name[2], fcport->port_name[3],
+		    fcport->port_name[4], fcport->port_name[5],
+		    fcport->port_name[6], fcport->port_name[7], rval,
+		    port_speed, mb[0], mb[1]));
+	} else {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "iIDMA adjusted to %s GB/s on "
+		    "%02x%02x%02x%02x%02x%02x%02x%02x.\n",
+		    link_speeds[port_speed], fcport->port_name[0],
+		    fcport->port_name[1], fcport->port_name[2],
+		    fcport->port_name[3], fcport->port_name[4],
+		    fcport->port_name[5], fcport->port_name[6],
+		    fcport->port_name[7]));
+	}
+}
+
 /*
  * qla2x00_update_fcport
  *	Updates device on list.
@@ -2135,6 +2204,8 @@
 	    PORT_RETRY_TIME);
 	fcport->flags &= ~FCF_LOGIN_NEEDED;
 
+	qla2x00_iidma_fcport(ha, fcport);
+
 	atomic_set(&fcport->state, FCS_ONLINE);
 
 	if (ha->flags.init_done)
@@ -2209,7 +2280,7 @@
 		loop_id = NPH_F_PORT;
 	else
 		loop_id = SNS_FL_PORT;
-	rval = qla2x00_get_port_name(ha, loop_id, NULL, 0);
+	rval = qla2x00_get_port_name(ha, loop_id, ha->fabric_node_name, 1);
 	if (rval != QLA_SUCCESS) {
 		DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL "
 		    "Port\n", ha->host_no));
@@ -2217,6 +2288,7 @@
 		ha->device_flags &= ~SWITCH_FOUND;
 		return (QLA_SUCCESS);
 	}
+	ha->device_flags |= SWITCH_FOUND;
 
 	/* Mark devices that need re-synchronization. */
 	rval2 = qla2x00_device_resync(ha);
@@ -2416,6 +2488,8 @@
 		} else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) {
 			kfree(swl);
 			swl = NULL;
+		} else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
+			qla2x00_gpsc(ha, swl);
 		}
 	}
 	swl_idx = 0;
@@ -2450,6 +2524,9 @@
 				    swl[swl_idx].node_name, WWN_SIZE);
 				memcpy(new_fcport->port_name,
 				    swl[swl_idx].port_name, WWN_SIZE);
+				memcpy(new_fcport->fabric_port_name,
+				    swl[swl_idx].fabric_port_name, WWN_SIZE);
+				new_fcport->fp_speed = swl[swl_idx].fp_speed;
 
 				if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
 					last_dev = 1;
@@ -2507,6 +2584,11 @@
 
 			found++;
 
+			/* Update port state. */
+			memcpy(fcport->fabric_port_name,
+			    new_fcport->fabric_port_name, WWN_SIZE);
+			fcport->fp_speed = new_fcport->fp_speed;
+
 			/*
 			 * If address the same and state FCS_ONLINE, nothing
 			 * changed.
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 45007ee..d3023338 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -104,7 +104,7 @@
 static inline void
 qla2x00_poll(scsi_qla_host_t *ha)
 {
-	ha->isp_ops.intr_handler(0, ha, NULL);
+	ha->isp_ops.intr_handler(0, ha);
 }
 
 static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index de06131..626c717 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -20,14 +20,13 @@
  * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
  * @irq:
  * @dev_id: SCSI driver HA context
- * @regs:
  *
  * Called by system whenever the host adapter generates an interrupt.
  *
  * Returns handled flag.
  */
 irqreturn_t
-qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+qla2100_intr_handler(int irq, void *dev_id)
 {
 	scsi_qla_host_t	*ha;
 	struct device_reg_2xxx __iomem *reg;
@@ -100,14 +99,13 @@
  * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
  * @irq:
  * @dev_id: SCSI driver HA context
- * @regs:
  *
  * Called by system whenever the host adapter generates an interrupt.
  *
  * Returns handled flag.
  */
 irqreturn_t
-qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+qla2300_intr_handler(int irq, void *dev_id)
 {
 	scsi_qla_host_t	*ha;
 	struct device_reg_2xxx __iomem *reg;
@@ -400,7 +398,7 @@
 	case MBA_LOOP_UP:		/* Loop Up Event */
 		if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 			link_speed = link_speeds[0];
-			ha->link_data_rate = LDR_1GB;
+			ha->link_data_rate = PORT_SPEED_1GB;
 		} else {
 			link_speed = link_speeds[LS_UNKNOWN];
 			if (mb[1] < 5)
@@ -429,7 +427,7 @@
 		}
 
 		ha->flags.management_server_logged_in = 0;
-		ha->link_data_rate = LDR_UNKNOWN;
+		ha->link_data_rate = PORT_SPEED_UNKNOWN;
 		if (ql2xfdmienable)
 			set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 		break;
@@ -1338,14 +1336,13 @@
  * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
  * @irq:
  * @dev_id: SCSI driver HA context
- * @regs:
  *
  * Called by system whenever the host adapter generates an interrupt.
  *
  * Returns handled flag.
  */
 irqreturn_t
-qla24xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+qla24xx_intr_handler(int irq, void *dev_id)
 {
 	scsi_qla_host_t	*ha;
 	struct device_reg_24xx __iomem *reg;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 879f281..4cde76c 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2540,3 +2540,89 @@
 
 	return rval;
 }
+
+int
+qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
+    uint16_t *port_speed, uint16_t *mb)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	if (!IS_QLA24XX(ha))
+		return QLA_FUNCTION_FAILED;
+
+	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+	mcp->mb[0] = MBC_PORT_PARAMS;
+	mcp->mb[1] = loop_id;
+	mcp->mb[2] = mcp->mb[3] = mcp->mb[4] = mcp->mb[5] = 0;
+	mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
+	mcp->tov = 30;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(ha, mcp);
+
+	/* Return mailbox statuses. */
+	if (mb != NULL) {
+		mb[0] = mcp->mb[0];
+		mb[1] = mcp->mb[1];
+		mb[3] = mcp->mb[3];
+		mb[4] = mcp->mb[4];
+		mb[5] = mcp->mb[5];
+	}
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+		    ha->host_no, rval));
+	} else {
+		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+		if (port_speed)
+			*port_speed = mcp->mb[3];
+	}
+
+	return rval;
+}
+
+int
+qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
+    uint16_t port_speed, uint16_t *mb)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+
+	if (!IS_QLA24XX(ha))
+		return QLA_FUNCTION_FAILED;
+
+	DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+	mcp->mb[0] = MBC_PORT_PARAMS;
+	mcp->mb[1] = loop_id;
+	mcp->mb[2] = BIT_0;
+	mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0);
+	mcp->mb[4] = mcp->mb[5] = 0;
+	mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
+	mcp->tov = 30;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(ha, mcp);
+
+	/* Return mailbox statuses. */
+	if (mb != NULL) {
+		mb[0] = mcp->mb[0];
+		mb[1] = mcp->mb[1];
+		mb[3] = mcp->mb[3];
+		mb[4] = mcp->mb[4];
+		mb[5] = mcp->mb[5];
+	}
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+		    ha->host_no, rval));
+	} else {
+		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+	}
+
+	return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 65cbe2f..3f20d76 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -61,9 +61,9 @@
 		"during HBA initialization.  Memory allocation requirements "
 		"vary by ISP type.  Default is 1 - allocate memory.");
 
-int extended_error_logging;
-module_param(extended_error_logging, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(extended_error_logging,
+int qla2_extended_error_logging;
+module_param(qla2_extended_error_logging, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(qla2_extended_error_logging,
 		"Option to enable extended error logging, "
 		"Default is 0 - no logging. 1 - log errors.");
 
@@ -589,6 +589,23 @@
 	return (return_status);
 }
 
+static void
+qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
+{
+	struct Scsi_Host *shost = cmnd->device->host;
+	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	while (rport->port_state == FC_PORTSTATE_BLOCKED) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		msleep(1000);
+		spin_lock_irqsave(shost->host_lock, flags);
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	return;
+}
+
 /**************************************************************************
 * qla2xxx_eh_abort
 *
@@ -615,6 +632,8 @@
 	unsigned long flags;
 	int wait = 0;
 
+	qla2x00_block_error_handler(cmd);
+
 	if (!CMD_SP(cmd))
 		return SUCCESS;
 
@@ -748,6 +767,8 @@
 	unsigned int id, lun;
 	unsigned long serial;
 
+	qla2x00_block_error_handler(cmd);
+
 	ret = FAILED;
 
 	id = cmd->device->id;
@@ -877,6 +898,8 @@
 	unsigned int id, lun;
 	unsigned long serial;
 
+	qla2x00_block_error_handler(cmd);
+
 	ret = FAILED;
 
 	id = cmd->device->id;
@@ -936,6 +959,8 @@
 	unsigned int id, lun;
 	unsigned long serial;
 
+	qla2x00_block_error_handler(cmd);
+
 	ret = FAILED;
 
 	id = cmd->device->id;
@@ -1385,7 +1410,7 @@
 	ha->prev_topology = 0;
 	ha->init_cb_size = sizeof(init_cb_t);
 	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
-	ha->link_data_rate = LDR_UNKNOWN;
+	ha->link_data_rate = PORT_SPEED_UNKNOWN;
 	ha->optrom_size = OPTROM_SIZE_2300;
 
 	/* Assign ISP specific operations. */
@@ -2564,14 +2589,20 @@
 #define FW_ISP2322	3
 #define FW_ISP24XX	4
 
+#define FW_FILE_ISP21XX	"ql2100_fw.bin"
+#define FW_FILE_ISP22XX	"ql2200_fw.bin"
+#define FW_FILE_ISP2300	"ql2300_fw.bin"
+#define FW_FILE_ISP2322	"ql2322_fw.bin"
+#define FW_FILE_ISP24XX	"ql2400_fw.bin"
+
 static DECLARE_MUTEX(qla_fw_lock);
 
 static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
-	{ .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, },
-	{ .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, },
-	{ .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
-	{ .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
-	{ .name = "ql2400_fw.bin", },
+	{ .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, },
+	{ .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, },
+	{ .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, },
+	{ .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
+	{ .name = FW_FILE_ISP24XX, },
 };
 
 struct fw_blob *
@@ -2666,7 +2697,7 @@
 
 	/* Derive version string. */
 	strcpy(qla2x00_version_str, QLA2XXX_VERSION);
-	if (extended_error_logging)
+	if (qla2_extended_error_logging)
 		strcat(qla2x00_version_str, "-debug");
 
 	qla2xxx_transport_template =
@@ -2702,3 +2733,8 @@
 MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(QLA2XXX_VERSION);
+MODULE_FIRMWARE(FW_FILE_ISP21XX);
+MODULE_FIRMWARE(FW_FILE_ISP22XX);
+MODULE_FIRMWARE(FW_FILE_ISP2300);
+MODULE_FIRMWARE(FW_FILE_ISP2322);
+MODULE_FIRMWARE(FW_FILE_ISP24XX);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 9712590..e57bf45 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-k1"
+#define QLA2XXX_VERSION      "8.01.07-k2"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig
new file mode 100644
index 0000000..08a07f0
--- /dev/null
+++ b/drivers/scsi/qla4xxx/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_QLA_ISCSI
+	tristate "QLogic ISP4XXX host adapter family support"
+	depends on PCI && SCSI
+	select SCSI_ISCSI_ATTRS
+	---help---
+	This driver supports the QLogic 40xx (ISP4XXX) iSCSI host
+	adapter family.
diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile
new file mode 100644
index 0000000..86ea37b
--- /dev/null
+++ b/drivers/scsi/qla4xxx/Makefile
@@ -0,0 +1,5 @@
+qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \
+		ql4_nvram.o ql4_dbg.o
+
+obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o
+
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c
new file mode 100644
index 0000000..752031f
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_dbg.c
@@ -0,0 +1,197 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+#include <scsi/scsi_dbg.h>
+
+static void qla4xxx_print_srb_info(struct srb * srb)
+{
+	printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
+	printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n",
+	       __func__, srb->cmd, (unsigned long) srb->dma_handle);
+	printk("%s: fw_ddb_index = %d, lun = %d\n",
+	       __func__, srb->fw_ddb_index, srb->cmd->device->lun);
+	printk("%s: iocb_tov = %d\n",
+	       __func__, srb->iocb_tov);
+	printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n",
+	       __func__, srb->cc_stat, srb->r_start, srb->u_start);
+}
+
+void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd)
+{
+	printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
+	printk("  b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n",
+	       cmd->device->channel, cmd->device->id, cmd->device->lun,
+	       cmd->cmd_len);
+	scsi_print_command(cmd);
+	printk("  seg_cnt = %d\n", cmd->use_sg);
+	printk("  request buffer = 0x%p, request buffer len = 0x%x\n",
+	       cmd->request_buffer, cmd->request_bufflen);
+	if (cmd->use_sg) {
+		struct scatterlist *sg;
+		sg = (struct scatterlist *)cmd->request_buffer;
+		printk("  SG buffer: \n");
+		qla4xxx_dump_buffer((caddr_t) sg,
+				    (cmd->use_sg * sizeof(*sg)));
+	}
+	printk("  tag = %d, transfersize = 0x%x \n", cmd->tag,
+	       cmd->transfersize);
+	printk("  Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr);
+	printk("  underflow size = 0x%x, direction=0x%x\n", cmd->underflow,
+	       cmd->sc_data_direction);
+	printk("  Current time (jiffies) = 0x%lx, "
+	       "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires);
+	qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr);
+}
+
+void __dump_registers(struct scsi_qla_host *ha)
+{
+	uint8_t i;
+	for (i = 0; i < MBOX_REG_COUNT; i++) {
+		printk(KERN_INFO "0x%02X mailbox[%d]	  = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg, mailbox[i]), i,
+		       readw(&ha->reg->mailbox[i]));
+	}
+	printk(KERN_INFO "0x%02X flash_address	 = 0x%08X\n",
+	       (uint8_t) offsetof(struct isp_reg, flash_address),
+	       readw(&ha->reg->flash_address));
+	printk(KERN_INFO "0x%02X flash_data	 = 0x%08X\n",
+	       (uint8_t) offsetof(struct isp_reg, flash_data),
+	       readw(&ha->reg->flash_data));
+	printk(KERN_INFO "0x%02X ctrl_status	 = 0x%08X\n",
+	       (uint8_t) offsetof(struct isp_reg, ctrl_status),
+	       readw(&ha->reg->ctrl_status));
+	if (is_qla4010(ha)) {
+		printk(KERN_INFO "0x%02X nvram		 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram),
+		       readw(&ha->reg->u1.isp4010.nvram));
+	}
+
+	else if (is_qla4022(ha)) {
+		printk(KERN_INFO "0x%02X intr_mask	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u1.isp4022.intr_mask),
+		       readw(&ha->reg->u1.isp4022.intr_mask));
+		printk(KERN_INFO "0x%02X nvram		 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram),
+		       readw(&ha->reg->u1.isp4022.nvram));
+		printk(KERN_INFO "0x%02X semaphore	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u1.isp4022.semaphore),
+		       readw(&ha->reg->u1.isp4022.semaphore));
+	}
+	printk(KERN_INFO "0x%02X req_q_in	 = 0x%08X\n",
+	       (uint8_t) offsetof(struct isp_reg, req_q_in),
+	       readw(&ha->reg->req_q_in));
+	printk(KERN_INFO "0x%02X rsp_q_out	 = 0x%08X\n",
+	       (uint8_t) offsetof(struct isp_reg, rsp_q_out),
+	       readw(&ha->reg->rsp_q_out));
+	if (is_qla4010(ha)) {
+		printk(KERN_INFO "0x%02X ext_hw_conf	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4010.ext_hw_conf),
+		       readw(&ha->reg->u2.isp4010.ext_hw_conf));
+		printk(KERN_INFO "0x%02X port_ctrl	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4010.port_ctrl),
+		       readw(&ha->reg->u2.isp4010.port_ctrl));
+		printk(KERN_INFO "0x%02X port_status	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4010.port_status),
+		       readw(&ha->reg->u2.isp4010.port_status));
+		printk(KERN_INFO "0x%02X req_q_out	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4010.req_q_out),
+		       readw(&ha->reg->u2.isp4010.req_q_out));
+		printk(KERN_INFO "0x%02X gp_out		 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out),
+		       readw(&ha->reg->u2.isp4010.gp_out));
+		printk(KERN_INFO "0x%02X gp_in		 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in),
+		       readw(&ha->reg->u2.isp4010.gp_in));
+		printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4010.port_err_status),
+		       readw(&ha->reg->u2.isp4010.port_err_status));
+	}
+
+	else if (is_qla4022(ha)) {
+		printk(KERN_INFO "Page 0 Registers:\n");
+		printk(KERN_INFO "0x%02X ext_hw_conf	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4022.p0.ext_hw_conf),
+		       readw(&ha->reg->u2.isp4022.p0.ext_hw_conf));
+		printk(KERN_INFO "0x%02X port_ctrl	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4022.p0.port_ctrl),
+		       readw(&ha->reg->u2.isp4022.p0.port_ctrl));
+		printk(KERN_INFO "0x%02X port_status	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4022.p0.port_status),
+		       readw(&ha->reg->u2.isp4022.p0.port_status));
+		printk(KERN_INFO "0x%02X gp_out		 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4022.p0.gp_out),
+		       readw(&ha->reg->u2.isp4022.p0.gp_out));
+		printk(KERN_INFO "0x%02X gp_in		 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in),
+		       readw(&ha->reg->u2.isp4022.p0.gp_in));
+		printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4022.p0.port_err_status),
+		       readw(&ha->reg->u2.isp4022.p0.port_err_status));
+		printk(KERN_INFO "Page 1 Registers:\n");
+		writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
+		       &ha->reg->ctrl_status);
+		printk(KERN_INFO "0x%02X req_q_out	 = 0x%08X\n",
+		       (uint8_t) offsetof(struct isp_reg,
+					  u2.isp4022.p1.req_q_out),
+		       readw(&ha->reg->u2.isp4022.p1.req_q_out));
+		writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
+		       &ha->reg->ctrl_status);
+	}
+}
+
+void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha)
+{
+	unsigned long flags = 0;
+	int i = 0;
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (i = 1; i < MBOX_REG_COUNT; i++)
+		printk(KERN_INFO "  Mailbox[%d] = %08x\n", i,
+		       readw(&ha->reg->mailbox[i]));
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+void qla4xxx_dump_registers(struct scsi_qla_host *ha)
+{
+	unsigned long flags = 0;
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	__dump_registers(ha);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+void qla4xxx_dump_buffer(void *b, uint32_t size)
+{
+	uint32_t cnt;
+	uint8_t *c = b;
+
+	printk(" 0   1	 2   3	 4   5	 6   7	 8   9	Ah  Bh	Ch  Dh	Eh  "
+	       "Fh\n");
+	printk("------------------------------------------------------------"
+	       "--\n");
+	for (cnt = 0; cnt < size; cnt++, c++) {
+		printk(KERN_DEBUG "%02x", *c);
+		if (!(cnt % 16))
+			printk(KERN_DEBUG "\n");
+
+		else
+			printk(KERN_DEBUG "  ");
+	}
+	if (cnt % 16)
+		printk(KERN_DEBUG "\n");
+}
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h
new file mode 100644
index 0000000..3e99dcf
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_dbg.h
@@ -0,0 +1,55 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+/*
+ * Driver debug definitions.
+ */
+/* #define QL_DEBUG  */			/* DEBUG messages */
+/* #define QL_DEBUG_LEVEL_3  */		/* Output function tracing */
+/* #define QL_DEBUG_LEVEL_4  */
+/* #define QL_DEBUG_LEVEL_5  */
+/* #define QL_DEBUG_LEVEL_9  */
+
+#define QL_DEBUG_LEVEL_2	/* ALways enable error messagess */
+#if defined(QL_DEBUG)
+#define DEBUG(x)   do {x;} while (0);
+#else
+#define DEBUG(x)	do {} while (0);
+#endif
+
+#if defined(QL_DEBUG_LEVEL_2)
+#define DEBUG2(x)      do {if(qla4_extended_error_logging == 2) x;} while (0);
+#define DEBUG2_3(x)   do {x;} while (0);
+#else				/*  */
+#define DEBUG2(x)	do {} while (0);
+#endif				/*  */
+
+#if defined(QL_DEBUG_LEVEL_3)
+#define DEBUG3(x)      do {if(qla4_extended_error_logging == 3) x;} while (0);
+#else				/*  */
+#define DEBUG3(x)	do {} while (0);
+#if !defined(QL_DEBUG_LEVEL_2)
+#define DEBUG2_3(x)	do {} while (0);
+#endif				/*  */
+#endif				/*  */
+#if defined(QL_DEBUG_LEVEL_4)
+#define DEBUG4(x)	do {x;} while (0);
+#else				/*  */
+#define DEBUG4(x)	do {} while (0);
+#endif				/*  */
+
+#if defined(QL_DEBUG_LEVEL_5)
+#define DEBUG5(x)	do {x;} while (0);
+#else				/*  */
+#define DEBUG5(x)	do {} while (0);
+#endif				/*  */
+
+#if defined(QL_DEBUG_LEVEL_9)
+#define DEBUG9(x)	do {x;} while (0);
+#else				/*  */
+#define DEBUG9(x)	do {} while (0);
+#endif				/*  */
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
new file mode 100644
index 0000000..a7f6c7b
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -0,0 +1,586 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#ifndef __QL4_DEF_H
+#define __QL4_DEF_H
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/dmapool.h>
+#include <linux/mempool.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+
+#include <net/tcp.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP4010
+#define PCI_DEVICE_ID_QLOGIC_ISP4010	0x4010
+#endif
+
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP4022
+#define PCI_DEVICE_ID_QLOGIC_ISP4022	0x4022
+#endif				/*  */
+
+#define QLA_SUCCESS			0
+#define QLA_ERROR			1
+
+/*
+ * Data bit definitions
+ */
+#define BIT_0	0x1
+#define BIT_1	0x2
+#define BIT_2	0x4
+#define BIT_3	0x8
+#define BIT_4	0x10
+#define BIT_5	0x20
+#define BIT_6	0x40
+#define BIT_7	0x80
+#define BIT_8	0x100
+#define BIT_9	0x200
+#define BIT_10	0x400
+#define BIT_11	0x800
+#define BIT_12	0x1000
+#define BIT_13	0x2000
+#define BIT_14	0x4000
+#define BIT_15	0x8000
+#define BIT_16	0x10000
+#define BIT_17	0x20000
+#define BIT_18	0x40000
+#define BIT_19	0x80000
+#define BIT_20	0x100000
+#define BIT_21	0x200000
+#define BIT_22	0x400000
+#define BIT_23	0x800000
+#define BIT_24	0x1000000
+#define BIT_25	0x2000000
+#define BIT_26	0x4000000
+#define BIT_27	0x8000000
+#define BIT_28	0x10000000
+#define BIT_29	0x20000000
+#define BIT_30	0x40000000
+#define BIT_31	0x80000000
+
+/*
+ * Host adapter default definitions
+ ***********************************/
+#define MAX_HBAS		16
+#define MAX_BUSES		1
+#define MAX_TARGETS		(MAX_PRST_DEV_DB_ENTRIES +  MAX_DEV_DB_ENTRIES)
+#define MAX_LUNS		0xffff
+#define MAX_AEN_ENTRIES		256 /* should be > EXT_DEF_MAX_AEN_QUEUE */
+#define MAX_DDB_ENTRIES		(MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES)
+#define MAX_PDU_ENTRIES		32
+#define INVALID_ENTRY		0xFFFF
+#define MAX_CMDS_TO_RISC	1024
+#define MAX_SRBS		MAX_CMDS_TO_RISC
+#define MBOX_AEN_REG_COUNT	5
+#define MAX_INIT_RETRIES	5
+#define IOCB_HIWAT_CUSHION	16
+
+/*
+ * Buffer sizes
+ */
+#define REQUEST_QUEUE_DEPTH		MAX_CMDS_TO_RISC
+#define RESPONSE_QUEUE_DEPTH		64
+#define QUEUE_SIZE			64
+#define DMA_BUFFER_SIZE			512
+
+/*
+ * Misc
+ */
+#define MAC_ADDR_LEN			6	/* in bytes */
+#define IP_ADDR_LEN			4	/* in bytes */
+#define DRIVER_NAME			"qla4xxx"
+
+#define MAX_LINKED_CMDS_PER_LUN		3
+#define MAX_REQS_SERVICED_PER_INTR	16
+
+#define ISCSI_IPADDR_SIZE		4	/* IP address size */
+#define ISCSI_ALIAS_SIZE		32	/* ISCSI Alais name size */
+#define ISCSI_NAME_SIZE			255	/* ISCSI Name size -
+						 * usually a string */
+
+#define LSDW(x) ((u32)((u64)(x)))
+#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
+
+/*
+ * Retry & Timeout Values
+ */
+#define MBOX_TOV			60
+#define SOFT_RESET_TOV			30
+#define RESET_INTR_TOV			3
+#define SEMAPHORE_TOV			10
+#define ADAPTER_INIT_TOV		120
+#define ADAPTER_RESET_TOV		180
+#define EXTEND_CMD_TOV			60
+#define WAIT_CMD_TOV			30
+#define EH_WAIT_CMD_TOV			120
+#define FIRMWARE_UP_TOV			60
+#define RESET_FIRMWARE_TOV		30
+#define LOGOUT_TOV			10
+#define IOCB_TOV_MARGIN			10
+#define RELOGIN_TOV			18
+#define ISNS_DEREG_TOV			5
+
+#define MAX_RESET_HA_RETRIES		2
+
+/*
+ * SCSI Request Block structure	 (srb)	that is placed
+ * on cmd->SCp location of every I/O	 [We have 22 bytes available]
+ */
+struct srb {
+	struct list_head list;	/* (8)	 */
+	struct scsi_qla_host *ha;	/* HA the SP is queued on */
+	struct ddb_entry	*ddb;
+	uint16_t flags;		/* (1) Status flags. */
+
+#define SRB_DMA_VALID		BIT_3	/* DMA Buffer mapped. */
+#define SRB_GOT_SENSE		BIT_4	/* sense data recieved. */
+	uint8_t state;		/* (1) Status flags. */
+
+#define SRB_NO_QUEUE_STATE	 0	/* Request is in between states */
+#define SRB_FREE_STATE		 1
+#define SRB_ACTIVE_STATE	 3
+#define SRB_ACTIVE_TIMEOUT_STATE 4
+#define SRB_SUSPENDED_STATE	 7	/* Request in suspended state */
+
+	struct scsi_cmnd *cmd;	/* (4) SCSI command block */
+	dma_addr_t dma_handle;	/* (4) for unmap of single transfers */
+	atomic_t ref_count;	/* reference count for this srb */
+	uint32_t fw_ddb_index;
+	uint8_t err_id;		/* error id */
+#define SRB_ERR_PORT	   1	/* Request failed because "port down" */
+#define SRB_ERR_LOOP	   2	/* Request failed because "loop down" */
+#define SRB_ERR_DEVICE	   3	/* Request failed because "device error" */
+#define SRB_ERR_OTHER	   4
+
+	uint16_t reserved;
+	uint16_t iocb_tov;
+	uint16_t iocb_cnt;	/* Number of used iocbs */
+	uint16_t cc_stat;
+	u_long r_start;		/* Time we recieve a cmd from OS */
+	u_long u_start;		/* Time when we handed the cmd to F/W */
+};
+
+	/*
+	 * Device Database (DDB) structure
+	 */
+struct ddb_entry {
+	struct list_head list;	/* ddb list */
+	struct scsi_qla_host *ha;
+	struct iscsi_cls_session *sess;
+	struct iscsi_cls_conn *conn;
+
+	atomic_t state;		/* DDB State */
+
+	unsigned long flags;	/* DDB Flags */
+
+	unsigned long dev_scan_wait_to_start_relogin;
+	unsigned long dev_scan_wait_to_complete_relogin;
+
+	uint16_t os_target_id;	/* Target ID */
+	uint16_t fw_ddb_index;	/* DDB firmware index */
+	uint8_t reserved[2];
+	uint32_t fw_ddb_device_state; /* F/W Device State  -- see ql4_fw.h */
+
+	uint32_t CmdSn;
+	uint16_t target_session_id;
+	uint16_t connection_id;
+	uint16_t exe_throttle;	/* Max mumber of cmds outstanding
+				 * simultaneously */
+	uint16_t task_mgmt_timeout; /* Min time for task mgmt cmds to
+				     * complete */
+	uint16_t default_relogin_timeout; /*  Max time to wait for
+					   *  relogin to complete */
+	uint16_t tcp_source_port_num;
+	uint32_t default_time2wait; /* Default Min time between
+				     * relogins (+aens) */
+
+	atomic_t port_down_timer; /* Device connection timer */
+	atomic_t retry_relogin_timer; /* Min Time between relogins
+				       * (4000 only) */
+	atomic_t relogin_timer;	/* Max Time to wait for relogin to complete */
+	atomic_t relogin_retry_count; /* Num of times relogin has been
+				       * retried */
+
+	uint16_t port;
+	uint32_t tpgt;
+	uint8_t ip_addr[ISCSI_IPADDR_SIZE];
+	uint8_t iscsi_name[ISCSI_NAME_SIZE];	/* 72 x48 */
+	uint8_t iscsi_alias[0x20];
+};
+
+/*
+ * DDB states.
+ */
+#define DDB_STATE_DEAD		0	/* We can no longer talk to
+					 * this device */
+#define DDB_STATE_ONLINE	1	/* Device ready to accept
+					 * commands */
+#define DDB_STATE_MISSING	2	/* Device logged off, trying
+					 * to re-login */
+
+/*
+ * DDB flags.
+ */
+#define DF_RELOGIN		0	/* Relogin to device */
+#define DF_NO_RELOGIN		1	/* Do not relogin if IOCTL
+					 * logged it out */
+#define DF_ISNS_DISCOVERED	2	/* Device was discovered via iSNS */
+#define DF_FO_MASKED		3
+
+/*
+ * Asynchronous Event Queue structure
+ */
+struct aen {
+	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
+};
+
+
+#include "ql4_fw.h"
+#include "ql4_nvram.h"
+
+/*
+ * Linux Host Adapter structure
+ */
+struct scsi_qla_host {
+	/* Linux adapter configuration data */
+	struct Scsi_Host *host; /* pointer to host data */
+	uint32_t tot_ddbs;
+	unsigned long flags;
+
+#define AF_ONLINE		      0 /* 0x00000001 */
+#define AF_INIT_DONE		      1 /* 0x00000002 */
+#define AF_MBOX_COMMAND		      2 /* 0x00000004 */
+#define AF_MBOX_COMMAND_DONE	      3 /* 0x00000008 */
+#define AF_INTERRUPTS_ON	      6 /* 0x00000040 Not Used */
+#define AF_GET_CRASH_RECORD	      7 /* 0x00000080 */
+#define AF_LINK_UP		      8 /* 0x00000100 */
+#define AF_TOPCAT_CHIP_PRESENT	      9 /* 0x00000200 */
+#define AF_IRQ_ATTACHED		     10 /* 0x00000400 */
+#define AF_ISNS_CMD_IN_PROCESS	     12 /* 0x00001000 */
+#define AF_ISNS_CMD_DONE	     13 /* 0x00002000 */
+
+	unsigned long dpc_flags;
+
+#define DPC_RESET_HA		      1 /* 0x00000002 */
+#define DPC_RETRY_RESET_HA	      2 /* 0x00000004 */
+#define DPC_RELOGIN_DEVICE	      3 /* 0x00000008 */
+#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */
+#define DPC_RESET_HA_INTR	      5 /* 0x00000020 */
+#define DPC_ISNS_RESTART	      7 /* 0x00000080 */
+#define DPC_AEN			      9 /* 0x00000200 */
+#define DPC_GET_DHCP_IP_ADDR	     15 /* 0x00008000 */
+
+	uint16_t	iocb_cnt;
+	uint16_t	iocb_hiwat;
+
+	/* SRB cache. */
+#define SRB_MIN_REQ	128
+	mempool_t *srb_mempool;
+
+	/* pci information */
+	struct pci_dev *pdev;
+
+	struct isp_reg __iomem *reg; /* Base I/O address */
+	unsigned long pio_address;
+	unsigned long pio_length;
+#define MIN_IOBASE_LEN		0x100
+
+	uint16_t req_q_count;
+	uint8_t marker_needed;
+	uint8_t rsvd1;
+
+	unsigned long host_no;
+
+	/* NVRAM registers */
+	struct eeprom_data *nvram;
+	spinlock_t hardware_lock ____cacheline_aligned;
+	spinlock_t list_lock;
+	uint32_t   eeprom_cmd_data;
+
+	/* Counters for general statistics */
+	uint64_t adapter_error_count;
+	uint64_t device_error_count;
+	uint64_t total_io_count;
+	uint64_t total_mbytes_xferred;
+	uint64_t link_failure_count;
+	uint64_t invalid_crc_count;
+	uint32_t spurious_int_count;
+	uint32_t aborted_io_count;
+	uint32_t io_timeout_count;
+	uint32_t mailbox_timeout_count;
+	uint32_t seconds_since_last_intr;
+	uint32_t seconds_since_last_heartbeat;
+	uint32_t mac_index;
+
+	/* Info Needed for Management App */
+	/* --- From GetFwVersion --- */
+	uint32_t firmware_version[2];
+	uint32_t patch_number;
+	uint32_t build_number;
+
+	/* --- From Init_FW --- */
+	/* init_cb_t *init_cb; */
+	uint16_t firmware_options;
+	uint16_t tcp_options;
+	uint8_t ip_address[IP_ADDR_LEN];
+	uint8_t subnet_mask[IP_ADDR_LEN];
+	uint8_t gateway[IP_ADDR_LEN];
+	uint8_t alias[32];
+	uint8_t name_string[256];
+	uint8_t heartbeat_interval;
+	uint8_t rsvd;
+
+	/* --- From FlashSysInfo --- */
+	uint8_t my_mac[MAC_ADDR_LEN];
+	uint8_t serial_number[16];
+
+	/* --- From GetFwState --- */
+	uint32_t firmware_state;
+	uint32_t board_id;
+	uint32_t addl_fw_state;
+
+	/* Linux kernel thread */
+	struct workqueue_struct *dpc_thread;
+	struct work_struct dpc_work;
+
+	/* Linux timer thread */
+	struct timer_list timer;
+	uint32_t timer_active;
+
+	/* Recovery Timers */
+	uint32_t port_down_retry_count;
+	uint32_t discovery_wait;
+	atomic_t check_relogin_timeouts;
+	uint32_t retry_reset_ha_cnt;
+	uint32_t isp_reset_timer;	/* reset test timer */
+	uint32_t nic_reset_timer;	/* simulated nic reset test timer */
+	int eh_start;
+	struct list_head free_srb_q;
+	uint16_t free_srb_q_count;
+	uint16_t num_srbs_allocated;
+
+	/* DMA Memory Block */
+	void *queues;
+	dma_addr_t queues_dma;
+	unsigned long queues_len;
+
+#define MEM_ALIGN_VALUE \
+	    ((max(REQUEST_QUEUE_DEPTH, RESPONSE_QUEUE_DEPTH)) * \
+	     sizeof(struct queue_entry))
+	/* request and response queue variables */
+	dma_addr_t request_dma;
+	struct queue_entry *request_ring;
+	struct queue_entry *request_ptr;
+	dma_addr_t response_dma;
+	struct queue_entry *response_ring;
+	struct queue_entry *response_ptr;
+	dma_addr_t shadow_regs_dma;
+	struct shadow_regs *shadow_regs;
+	uint16_t request_in;	/* Current indexes. */
+	uint16_t request_out;
+	uint16_t response_in;
+	uint16_t response_out;
+
+	/* aen queue variables */
+	uint16_t aen_q_count;	/* Number of available aen_q entries */
+	uint16_t aen_in;	/* Current indexes */
+	uint16_t aen_out;
+	struct aen aen_q[MAX_AEN_ENTRIES];
+
+	/* This mutex protects several threads to do mailbox commands
+	 * concurrently.
+	 */
+	struct mutex  mbox_sem;
+	wait_queue_head_t mailbox_wait_queue;
+
+	/* temporary mailbox status registers */
+	volatile uint8_t mbox_status_count;
+	volatile uint32_t mbox_status[MBOX_REG_COUNT];
+
+	/* local device database list (contains internal ddb entries) */
+	struct list_head ddb_list;
+
+	/* Map ddb_list entry by FW ddb index */
+	struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES];
+
+};
+
+static inline int is_qla4010(struct scsi_qla_host *ha)
+{
+	return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4010;
+}
+
+static inline int is_qla4022(struct scsi_qla_host *ha)
+{
+	return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022;
+}
+
+static inline int adapter_up(struct scsi_qla_host *ha)
+{
+	return (test_bit(AF_ONLINE, &ha->flags) != 0) &&
+		(test_bit(AF_LINK_UP, &ha->flags) != 0);
+}
+
+static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost)
+{
+	return (struct scsi_qla_host *)shost->hostdata;
+}
+
+static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u1.isp4022.semaphore :
+		&ha->reg->u1.isp4010.nvram);
+}
+
+static inline void __iomem* isp_nvram(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u1.isp4022.nvram :
+		&ha->reg->u1.isp4010.nvram);
+}
+
+static inline void __iomem* isp_ext_hw_conf(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u2.isp4022.p0.ext_hw_conf :
+		&ha->reg->u2.isp4010.ext_hw_conf);
+}
+
+static inline void __iomem* isp_port_status(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u2.isp4022.p0.port_status :
+		&ha->reg->u2.isp4010.port_status);
+}
+
+static inline void __iomem* isp_port_ctrl(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u2.isp4022.p0.port_ctrl :
+		&ha->reg->u2.isp4010.port_ctrl);
+}
+
+static inline void __iomem* isp_port_error_status(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u2.isp4022.p0.port_err_status :
+		&ha->reg->u2.isp4010.port_err_status);
+}
+
+static inline void __iomem * isp_gp_out(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		&ha->reg->u2.isp4022.p0.gp_out :
+		&ha->reg->u2.isp4010.gp_out);
+}
+
+static inline int eeprom_ext_hw_conf_offset(struct scsi_qla_host *ha)
+{
+	return (is_qla4022(ha) ?
+		offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2 :
+		offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2);
+}
+
+int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits);
+void ql4xxx_sem_unlock(struct scsi_qla_host * ha, u32 sem_mask);
+int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits);
+
+static inline int ql4xxx_lock_flash(struct scsi_qla_host *a)
+{
+	if (is_qla4022(a))
+		return ql4xxx_sem_spinlock(a, QL4022_FLASH_SEM_MASK,
+					   (QL4022_RESOURCE_BITS_BASE_CODE |
+					    (a->mac_index)) << 13);
+	else
+		return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK,
+					   QL4010_FLASH_SEM_BITS);
+}
+
+static inline void ql4xxx_unlock_flash(struct scsi_qla_host *a)
+{
+	if (is_qla4022(a))
+		ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK);
+	else
+		ql4xxx_sem_unlock(a, QL4010_FLASH_SEM_MASK);
+}
+
+static inline int ql4xxx_lock_nvram(struct scsi_qla_host *a)
+{
+	if (is_qla4022(a))
+		return ql4xxx_sem_spinlock(a, QL4022_NVRAM_SEM_MASK,
+					   (QL4022_RESOURCE_BITS_BASE_CODE |
+					    (a->mac_index)) << 10);
+	else
+		return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK,
+					   QL4010_NVRAM_SEM_BITS);
+}
+
+static inline void ql4xxx_unlock_nvram(struct scsi_qla_host *a)
+{
+	if (is_qla4022(a))
+		ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK);
+	else
+		ql4xxx_sem_unlock(a, QL4010_NVRAM_SEM_MASK);
+}
+
+static inline int ql4xxx_lock_drvr(struct scsi_qla_host *a)
+{
+	if (is_qla4022(a))
+		return ql4xxx_sem_lock(a, QL4022_DRVR_SEM_MASK,
+				       (QL4022_RESOURCE_BITS_BASE_CODE |
+					(a->mac_index)) << 1);
+	else
+		return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK,
+				       QL4010_DRVR_SEM_BITS);
+}
+
+static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a)
+{
+	if (is_qla4022(a))
+		ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK);
+	else
+		ql4xxx_sem_unlock(a, QL4010_DRVR_SEM_MASK);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */
+#define PRESERVE_DDB_LIST	0
+#define REBUILD_DDB_LIST	1
+
+/* Defines for process_aen() */
+#define PROCESS_ALL_AENS	 0
+#define FLUSH_DDB_CHANGED_AENS	 1
+#define RELOGIN_DDB_CHANGED_AENS 2
+
+#include "ql4_version.h"
+#include "ql4_glbl.h"
+#include "ql4_dbg.h"
+#include "ql4_inline.h"
+
+
+#endif	/*_QLA4XXX_H */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
new file mode 100644
index 0000000..427489d
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -0,0 +1,843 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#ifndef _QLA4X_FW_H
+#define _QLA4X_FW_H
+
+
+#define MAX_PRST_DEV_DB_ENTRIES		64
+#define MIN_DISC_DEV_DB_ENTRY		MAX_PRST_DEV_DB_ENTRIES
+#define MAX_DEV_DB_ENTRIES 512
+
+/*************************************************************************
+ *
+ *		ISP 4010 I/O Register Set Structure and Definitions
+ *
+ *************************************************************************/
+
+struct port_ctrl_stat_regs {
+	__le32 ext_hw_conf;	/*  80 x50  R/W */
+	__le32 intChipConfiguration; /*	 84 x54 */
+	__le32 port_ctrl;	/*  88 x58 */
+	__le32 port_status;	/*  92 x5c */
+	__le32 HostPrimMACHi;	/*  96 x60 */
+	__le32 HostPrimMACLow;	/* 100 x64 */
+	__le32 HostSecMACHi;	/* 104 x68 */
+	__le32 HostSecMACLow;	/* 108 x6c */
+	__le32 EPPrimMACHi;	/* 112 x70 */
+	__le32 EPPrimMACLow;	/* 116 x74 */
+	__le32 EPSecMACHi;	/* 120 x78 */
+	__le32 EPSecMACLow;	/* 124 x7c */
+	__le32 HostPrimIPHi;	/* 128 x80 */
+	__le32 HostPrimIPMidHi; /* 132 x84 */
+	__le32 HostPrimIPMidLow;	/* 136 x88 */
+	__le32 HostPrimIPLow;	/* 140 x8c */
+	__le32 HostSecIPHi;	/* 144 x90 */
+	__le32 HostSecIPMidHi;	/* 148 x94 */
+	__le32 HostSecIPMidLow; /* 152 x98 */
+	__le32 HostSecIPLow;	/* 156 x9c */
+	__le32 EPPrimIPHi;	/* 160 xa0 */
+	__le32 EPPrimIPMidHi;	/* 164 xa4 */
+	__le32 EPPrimIPMidLow;	/* 168 xa8 */
+	__le32 EPPrimIPLow;	/* 172 xac */
+	__le32 EPSecIPHi;	/* 176 xb0 */
+	__le32 EPSecIPMidHi;	/* 180 xb4 */
+	__le32 EPSecIPMidLow;	/* 184 xb8 */
+	__le32 EPSecIPLow;	/* 188 xbc */
+	__le32 IPReassemblyTimeout; /* 192 xc0 */
+	__le32 EthMaxFramePayload; /* 196 xc4 */
+	__le32 TCPMaxWindowSize; /* 200 xc8 */
+	__le32 TCPCurrentTimestampHi; /* 204 xcc */
+	__le32 TCPCurrentTimestampLow; /* 208 xd0 */
+	__le32 LocalRAMAddress; /* 212 xd4 */
+	__le32 LocalRAMData;	/* 216 xd8 */
+	__le32 PCSReserved1;	/* 220 xdc */
+	__le32 gp_out;		/* 224 xe0 */
+	__le32 gp_in;		/* 228 xe4 */
+	__le32 ProbeMuxAddr;	/* 232 xe8 */
+	__le32 ProbeMuxData;	/* 236 xec */
+	__le32 ERMQueueBaseAddr0; /* 240 xf0 */
+	__le32 ERMQueueBaseAddr1; /* 244 xf4 */
+	__le32 MACConfiguration; /* 248 xf8 */
+	__le32 port_err_status; /* 252 xfc  COR */
+};
+
+struct host_mem_cfg_regs {
+	__le32 NetRequestQueueOut; /*  80 x50 */
+	__le32 NetRequestQueueOutAddrHi; /*  84 x54 */
+	__le32 NetRequestQueueOutAddrLow; /*  88 x58 */
+	__le32 NetRequestQueueBaseAddrHi; /*  92 x5c */
+	__le32 NetRequestQueueBaseAddrLow; /*  96 x60 */
+	__le32 NetRequestQueueLength; /* 100 x64 */
+	__le32 NetResponseQueueIn; /* 104 x68 */
+	__le32 NetResponseQueueInAddrHi; /* 108 x6c */
+	__le32 NetResponseQueueInAddrLow; /* 112 x70 */
+	__le32 NetResponseQueueBaseAddrHi; /* 116 x74 */
+	__le32 NetResponseQueueBaseAddrLow; /* 120 x78 */
+	__le32 NetResponseQueueLength; /* 124 x7c */
+	__le32 req_q_out;	/* 128 x80 */
+	__le32 RequestQueueOutAddrHi; /* 132 x84 */
+	__le32 RequestQueueOutAddrLow; /* 136 x88 */
+	__le32 RequestQueueBaseAddrHi; /* 140 x8c */
+	__le32 RequestQueueBaseAddrLow; /* 144 x90 */
+	__le32 RequestQueueLength; /* 148 x94 */
+	__le32 ResponseQueueIn; /* 152 x98 */
+	__le32 ResponseQueueInAddrHi; /* 156 x9c */
+	__le32 ResponseQueueInAddrLow; /* 160 xa0 */
+	__le32 ResponseQueueBaseAddrHi; /* 164 xa4 */
+	__le32 ResponseQueueBaseAddrLow; /* 168 xa8 */
+	__le32 ResponseQueueLength; /* 172 xac */
+	__le32 NetRxLargeBufferQueueOut; /* 176 xb0 */
+	__le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */
+	__le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */
+	__le32 NetRxLargeBufferQueueLength; /* 188 xbc */
+	__le32 NetRxLargeBufferLength; /* 192 xc0 */
+	__le32 NetRxSmallBufferQueueOut; /* 196 xc4 */
+	__le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */
+	__le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */
+	__le32 NetRxSmallBufferQueueLength; /* 208 xd0 */
+	__le32 NetRxSmallBufferLength; /* 212 xd4 */
+	__le32 HMCReserved0[10]; /* 216 xd8 */
+};
+
+struct local_ram_cfg_regs {
+	__le32 BufletSize;	/*  80 x50 */
+	__le32 BufletMaxCount;	/*  84 x54 */
+	__le32 BufletCurrCount; /*  88 x58 */
+	__le32 BufletPauseThresholdCount; /*  92 x5c */
+	__le32 BufletTCPWinThresholdHi; /*  96 x60 */
+	__le32 BufletTCPWinThresholdLow; /* 100 x64 */
+	__le32 IPHashTableBaseAddr; /* 104 x68 */
+	__le32 IPHashTableSize; /* 108 x6c */
+	__le32 TCPHashTableBaseAddr; /* 112 x70 */
+	__le32 TCPHashTableSize; /* 116 x74 */
+	__le32 NCBAreaBaseAddr; /* 120 x78 */
+	__le32 NCBMaxCount;	/* 124 x7c */
+	__le32 NCBCurrCount;	/* 128 x80 */
+	__le32 DRBAreaBaseAddr; /* 132 x84 */
+	__le32 DRBMaxCount;	/* 136 x88 */
+	__le32 DRBCurrCount;	/* 140 x8c */
+	__le32 LRCReserved[28]; /* 144 x90 */
+};
+
+struct prot_stat_regs {
+	__le32 MACTxFrameCount; /*  80 x50   R */
+	__le32 MACTxByteCount;	/*  84 x54   R */
+	__le32 MACRxFrameCount; /*  88 x58   R */
+	__le32 MACRxByteCount;	/*  92 x5c   R */
+	__le32 MACCRCErrCount;	/*  96 x60   R */
+	__le32 MACEncErrCount;	/* 100 x64   R */
+	__le32 MACRxLengthErrCount; /* 104 x68	 R */
+	__le32 IPTxPacketCount; /* 108 x6c   R */
+	__le32 IPTxByteCount;	/* 112 x70   R */
+	__le32 IPTxFragmentCount; /* 116 x74   R */
+	__le32 IPRxPacketCount; /* 120 x78   R */
+	__le32 IPRxByteCount;	/* 124 x7c   R */
+	__le32 IPRxFragmentCount; /* 128 x80   R */
+	__le32 IPDatagramReassemblyCount; /* 132 x84   R */
+	__le32 IPV6RxPacketCount; /* 136 x88   R */
+	__le32 IPErrPacketCount; /* 140 x8c   R */
+	__le32 IPReassemblyErrCount; /* 144 x90	  R */
+	__le32 TCPTxSegmentCount; /* 148 x94   R */
+	__le32 TCPTxByteCount;	/* 152 x98   R */
+	__le32 TCPRxSegmentCount; /* 156 x9c   R */
+	__le32 TCPRxByteCount;	/* 160 xa0   R */
+	__le32 TCPTimerExpCount; /* 164 xa4   R */
+	__le32 TCPRxAckCount;	/* 168 xa8   R */
+	__le32 TCPTxAckCount;	/* 172 xac   R */
+	__le32 TCPRxErrOOOCount; /* 176 xb0   R */
+	__le32 PSReserved0;	/* 180 xb4 */
+	__le32 TCPRxWindowProbeUpdateCount; /* 184 xb8	 R */
+	__le32 ECCErrCorrectionCount; /* 188 xbc   R */
+	__le32 PSReserved1[16]; /* 192 xc0 */
+};
+
+
+/*  remote register set (access via PCI memory read/write) */
+struct isp_reg {
+#define MBOX_REG_COUNT 8
+	__le32 mailbox[MBOX_REG_COUNT];
+
+	__le32 flash_address;	/* 0x20 */
+	__le32 flash_data;
+	__le32 ctrl_status;
+
+	union {
+		struct {
+			__le32 nvram;
+			__le32 reserved1[2]; /* 0x30 */
+		} __attribute__ ((packed)) isp4010;
+		struct {
+			__le32 intr_mask;
+			__le32 nvram; /* 0x30 */
+			__le32 semaphore;
+		} __attribute__ ((packed)) isp4022;
+	} u1;
+
+	__le32 req_q_in;    /* SCSI Request Queue Producer Index */
+	__le32 rsp_q_out;   /* SCSI Completion Queue Consumer Index */
+
+	__le32 reserved2[4];	/* 0x40 */
+
+	union {
+		struct {
+			__le32 ext_hw_conf; /* 0x50 */
+			__le32 flow_ctrl;
+			__le32 port_ctrl;
+			__le32 port_status;
+
+			__le32 reserved3[8]; /* 0x60 */
+
+			__le32 req_q_out; /* 0x80 */
+
+			__le32 reserved4[23]; /* 0x84 */
+
+			__le32 gp_out; /* 0xe0 */
+			__le32 gp_in;
+
+			__le32 reserved5[5];
+
+			__le32 port_err_status; /* 0xfc */
+		} __attribute__ ((packed)) isp4010;
+		struct {
+			union {
+				struct port_ctrl_stat_regs p0;
+				struct host_mem_cfg_regs p1;
+				struct local_ram_cfg_regs p2;
+				struct prot_stat_regs p3;
+				__le32 r_union[44];
+			};
+
+		} __attribute__ ((packed)) isp4022;
+	} u2;
+};				/* 256 x100 */
+
+
+/* Semaphore Defines for 4010 */
+#define QL4010_DRVR_SEM_BITS	0x00000030
+#define QL4010_GPIO_SEM_BITS	0x000000c0
+#define QL4010_SDRAM_SEM_BITS	0x00000300
+#define QL4010_PHY_SEM_BITS	0x00000c00
+#define QL4010_NVRAM_SEM_BITS	0x00003000
+#define QL4010_FLASH_SEM_BITS	0x0000c000
+
+#define QL4010_DRVR_SEM_MASK	0x00300000
+#define QL4010_GPIO_SEM_MASK	0x00c00000
+#define QL4010_SDRAM_SEM_MASK	0x03000000
+#define QL4010_PHY_SEM_MASK	0x0c000000
+#define QL4010_NVRAM_SEM_MASK	0x30000000
+#define QL4010_FLASH_SEM_MASK	0xc0000000
+
+/* Semaphore Defines for 4022 */
+#define QL4022_RESOURCE_MASK_BASE_CODE 0x7
+#define QL4022_RESOURCE_BITS_BASE_CODE 0x4
+
+
+#define QL4022_DRVR_SEM_MASK	(QL4022_RESOURCE_MASK_BASE_CODE << (1+16))
+#define QL4022_DDR_RAM_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (4+16))
+#define QL4022_PHY_GIO_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (7+16))
+#define QL4022_NVRAM_SEM_MASK	(QL4022_RESOURCE_MASK_BASE_CODE << (10+16))
+#define QL4022_FLASH_SEM_MASK	(QL4022_RESOURCE_MASK_BASE_CODE << (13+16))
+
+
+
+/* Page # defines for 4022 */
+#define PORT_CTRL_STAT_PAGE			0	/* 4022 */
+#define HOST_MEM_CFG_PAGE			1	/* 4022 */
+#define LOCAL_RAM_CFG_PAGE			2	/* 4022 */
+#define PROT_STAT_PAGE				3	/* 4022 */
+
+/* Register Mask - sets corresponding mask bits in the upper word */
+static inline uint32_t set_rmask(uint32_t val)
+{
+	return (val & 0xffff) | (val << 16);
+}
+
+
+static inline uint32_t clr_rmask(uint32_t val)
+{
+	return 0 | (val << 16);
+}
+
+/*  ctrl_status definitions */
+#define CSR_SCSI_PAGE_SELECT			0x00000003
+#define CSR_SCSI_INTR_ENABLE			0x00000004	/* 4010 */
+#define CSR_SCSI_RESET_INTR			0x00000008
+#define CSR_SCSI_COMPLETION_INTR		0x00000010
+#define CSR_SCSI_PROCESSOR_INTR			0x00000020
+#define CSR_INTR_RISC				0x00000040
+#define CSR_BOOT_ENABLE				0x00000080
+#define CSR_NET_PAGE_SELECT			0x00000300	/* 4010 */
+#define CSR_FUNC_NUM				0x00000700	/* 4022 */
+#define CSR_NET_RESET_INTR			0x00000800	/* 4010 */
+#define CSR_FORCE_SOFT_RESET			0x00002000	/* 4022 */
+#define CSR_FATAL_ERROR				0x00004000
+#define CSR_SOFT_RESET				0x00008000
+#define ISP_CONTROL_FN_MASK			CSR_FUNC_NUM
+#define ISP_CONTROL_FN0_SCSI			0x0500
+#define ISP_CONTROL_FN1_SCSI			0x0700
+
+#define INTR_PENDING				(CSR_SCSI_COMPLETION_INTR |\
+						 CSR_SCSI_PROCESSOR_INTR |\
+						 CSR_SCSI_RESET_INTR)
+
+/* ISP InterruptMask definitions */
+#define IMR_SCSI_INTR_ENABLE			0x00000004	/* 4022 */
+
+/* ISP 4022 nvram definitions */
+#define NVR_WRITE_ENABLE			0x00000010	/* 4022 */
+
+/*  ISP port_status definitions */
+
+/*  ISP Semaphore definitions */
+
+/*  ISP General Purpose Output definitions */
+#define GPOR_TOPCAT_RESET			0x00000004
+
+/*  shadow registers (DMA'd from HA to system memory.  read only) */
+struct shadow_regs {
+	/* SCSI Request Queue Consumer Index */
+	__le32 req_q_out;	/*  0 x0   R */
+
+	/* SCSI Completion Queue Producer Index */
+	__le32 rsp_q_in;	/*  4 x4   R */
+};		  /*  8 x8 */
+
+
+/*  External hardware configuration register */
+union external_hw_config_reg {
+	struct {
+		/* FIXME: Do we even need this?	 All values are
+		 * referred to by 16 bit quantities.  Platform and
+		 * endianess issues. */
+		__le32 bReserved0:1;
+		__le32 bSDRAMProtectionMethod:2;
+		__le32 bSDRAMBanks:1;
+		__le32 bSDRAMChipWidth:1;
+		__le32 bSDRAMChipSize:2;
+		__le32 bParityDisable:1;
+		__le32 bExternalMemoryType:1;
+		__le32 bFlashBIOSWriteEnable:1;
+		__le32 bFlashUpperBankSelect:1;
+		__le32 bWriteBurst:2;
+		__le32 bReserved1:3;
+		__le32 bMask:16;
+	};
+	uint32_t Asuint32_t;
+};
+
+/*************************************************************************
+ *
+ *		Mailbox Commands Structures and Definitions
+ *
+ *************************************************************************/
+
+/*  Mailbox command definitions */
+#define MBOX_CMD_ABOUT_FW			0x0009
+#define MBOX_CMD_LUN_RESET			0x0016
+#define MBOX_CMD_GET_FW_STATUS			0x001F
+#define MBOX_CMD_SET_ISNS_SERVICE		0x0021
+#define ISNS_DISABLE				0
+#define ISNS_ENABLE				1
+#define MBOX_CMD_READ_FLASH			0x0026
+#define MBOX_CMD_CLEAR_DATABASE_ENTRY		0x0031
+#define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT		0x0056
+#define LOGOUT_OPTION_CLOSE_SESSION		0x01
+#define LOGOUT_OPTION_RELOGIN			0x02
+#define MBOX_CMD_EXECUTE_IOCB_A64		0x005A
+#define MBOX_CMD_INITIALIZE_FIRMWARE		0x0060
+#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK		0x0061
+#define MBOX_CMD_REQUEST_DATABASE_ENTRY		0x0062
+#define MBOX_CMD_SET_DATABASE_ENTRY		0x0063
+#define MBOX_CMD_GET_DATABASE_ENTRY		0x0064
+#define DDB_DS_UNASSIGNED			0x00
+#define DDB_DS_NO_CONNECTION_ACTIVE		0x01
+#define DDB_DS_SESSION_ACTIVE			0x04
+#define DDB_DS_SESSION_FAILED			0x06
+#define DDB_DS_LOGIN_IN_PROCESS			0x07
+#define MBOX_CMD_GET_FW_STATE			0x0069
+
+/* Mailbox 1 */
+#define FW_STATE_READY				0x0000
+#define FW_STATE_CONFIG_WAIT			0x0001
+#define FW_STATE_ERROR				0x0004
+#define FW_STATE_DHCP_IN_PROGRESS		0x0008
+
+/* Mailbox 3 */
+#define FW_ADDSTATE_OPTICAL_MEDIA		0x0001
+#define FW_ADDSTATE_DHCP_ENABLED		0x0002
+#define FW_ADDSTATE_LINK_UP			0x0010
+#define FW_ADDSTATE_ISNS_SVC_ENABLED		0x0020
+#define MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS	0x006B
+#define MBOX_CMD_CONN_OPEN_SESS_LOGIN		0x0074
+#define MBOX_CMD_GET_CRASH_RECORD		0x0076	/* 4010 only */
+#define MBOX_CMD_GET_CONN_EVENT_LOG		0x0077
+
+/*  Mailbox status definitions */
+#define MBOX_COMPLETION_STATUS			4
+#define MBOX_STS_BUSY				0x0007
+#define MBOX_STS_INTERMEDIATE_COMPLETION	0x1000
+#define MBOX_STS_COMMAND_COMPLETE		0x4000
+#define MBOX_STS_COMMAND_ERROR			0x4005
+
+#define MBOX_ASYNC_EVENT_STATUS			8
+#define MBOX_ASTS_SYSTEM_ERROR			0x8002
+#define MBOX_ASTS_REQUEST_TRANSFER_ERROR	0x8003
+#define MBOX_ASTS_RESPONSE_TRANSFER_ERROR	0x8004
+#define MBOX_ASTS_PROTOCOL_STATISTIC_ALARM	0x8005
+#define MBOX_ASTS_SCSI_COMMAND_PDU_REJECTED	0x8006
+#define MBOX_ASTS_LINK_UP			0x8010
+#define MBOX_ASTS_LINK_DOWN			0x8011
+#define MBOX_ASTS_DATABASE_CHANGED		0x8014
+#define MBOX_ASTS_UNSOLICITED_PDU_RECEIVED	0x8015
+#define MBOX_ASTS_SELF_TEST_FAILED		0x8016
+#define MBOX_ASTS_LOGIN_FAILED			0x8017
+#define MBOX_ASTS_DNS				0x8018
+#define MBOX_ASTS_HEARTBEAT			0x8019
+#define MBOX_ASTS_NVRAM_INVALID			0x801A
+#define MBOX_ASTS_MAC_ADDRESS_CHANGED		0x801B
+#define MBOX_ASTS_IP_ADDRESS_CHANGED		0x801C
+#define MBOX_ASTS_DHCP_LEASE_EXPIRED		0x801D
+#define MBOX_ASTS_DHCP_LEASE_ACQUIRED		0x801F
+#define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021
+#define ISNS_EVENT_DATA_RECEIVED		0x0000
+#define ISNS_EVENT_CONNECTION_OPENED		0x0001
+#define ISNS_EVENT_CONNECTION_FAILED		0x0002
+#define MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR	0x8022
+#define MBOX_ASTS_SUBNET_STATE_CHANGE		0x8027
+
+/*************************************************************************/
+
+/* Host Adapter Initialization Control Block (from host) */
+struct init_fw_ctrl_blk {
+	uint8_t Version;	/* 00 */
+	uint8_t Control;	/* 01 */
+
+	uint16_t FwOptions;	/* 02-03 */
+#define	 FWOPT_HEARTBEAT_ENABLE		  0x1000
+#define	 FWOPT_SESSION_MODE		  0x0040
+#define	 FWOPT_INITIATOR_MODE		  0x0020
+#define	 FWOPT_TARGET_MODE		  0x0010
+
+	uint16_t ExecThrottle;	/* 04-05 */
+	uint8_t RetryCount;	/* 06 */
+	uint8_t RetryDelay;	/* 07 */
+	uint16_t MaxEthFrPayloadSize;	/* 08-09 */
+	uint16_t AddFwOptions;	/* 0A-0B */
+
+	uint8_t HeartbeatInterval;	/* 0C */
+	uint8_t InstanceNumber; /* 0D */
+	uint16_t RES2;		/* 0E-0F */
+	uint16_t ReqQConsumerIndex;	/* 10-11 */
+	uint16_t ComplQProducerIndex;	/* 12-13 */
+	uint16_t ReqQLen;	/* 14-15 */
+	uint16_t ComplQLen;	/* 16-17 */
+	uint32_t ReqQAddrLo;	/* 18-1B */
+	uint32_t ReqQAddrHi;	/* 1C-1F */
+	uint32_t ComplQAddrLo;	/* 20-23 */
+	uint32_t ComplQAddrHi;	/* 24-27 */
+	uint32_t ShadowRegBufAddrLo;	/* 28-2B */
+	uint32_t ShadowRegBufAddrHi;	/* 2C-2F */
+
+	uint16_t iSCSIOptions;	/* 30-31 */
+
+	uint16_t TCPOptions;	/* 32-33 */
+
+	uint16_t IPOptions;	/* 34-35 */
+
+	uint16_t MaxPDUSize;	/* 36-37 */
+	uint16_t RcvMarkerInt;	/* 38-39 */
+	uint16_t SndMarkerInt;	/* 3A-3B */
+	uint16_t InitMarkerlessInt;	/* 3C-3D */
+	uint16_t FirstBurstSize;	/* 3E-3F */
+	uint16_t DefaultTime2Wait;	/* 40-41 */
+	uint16_t DefaultTime2Retain;	/* 42-43 */
+	uint16_t MaxOutStndngR2T;	/* 44-45 */
+	uint16_t KeepAliveTimeout;	/* 46-47 */
+	uint16_t PortNumber;	/* 48-49 */
+	uint16_t MaxBurstSize;	/* 4A-4B */
+	uint32_t RES4;		/* 4C-4F */
+	uint8_t IPAddr[4];	/* 50-53 */
+	uint8_t RES5[12];	/* 54-5F */
+	uint8_t SubnetMask[4];	/* 60-63 */
+	uint8_t RES6[12];	/* 64-6F */
+	uint8_t GatewayIPAddr[4];	/* 70-73 */
+	uint8_t RES7[12];	/* 74-7F */
+	uint8_t PriDNSIPAddr[4];	/* 80-83 */
+	uint8_t SecDNSIPAddr[4];	/* 84-87 */
+	uint8_t RES8[8];	/* 88-8F */
+	uint8_t Alias[32];	/* 90-AF */
+	uint8_t TargAddr[8];	/* B0-B7 *//* /FIXME: Remove?? */
+	uint8_t CHAPNameSecretsTable[8];	/* B8-BF */
+	uint8_t EthernetMACAddr[6];	/* C0-C5 */
+	uint16_t TargetPortalGroup;	/* C6-C7 */
+	uint8_t SendScale;	/* C8	 */
+	uint8_t RecvScale;	/* C9	 */
+	uint8_t TypeOfService;	/* CA	 */
+	uint8_t Time2Live;	/* CB	 */
+	uint16_t VLANPriority;	/* CC-CD */
+	uint16_t Reserved8;	/* CE-CF */
+	uint8_t SecIPAddr[4];	/* D0-D3 */
+	uint8_t Reserved9[12];	/* D4-DF */
+	uint8_t iSNSIPAddr[4];	/* E0-E3 */
+	uint16_t iSNSServerPortNumber;	/* E4-E5 */
+	uint8_t Reserved10[10]; /* E6-EF */
+	uint8_t SLPDAIPAddr[4]; /* F0-F3 */
+	uint8_t Reserved11[12]; /* F4-FF */
+	uint8_t iSCSINameString[256];	/* 100-1FF */
+};
+
+/*************************************************************************/
+
+struct dev_db_entry {
+	uint8_t options;	/* 00 */
+#define DDB_OPT_DISC_SESSION  0x10
+#define DDB_OPT_TARGET	      0x02 /* device is a target */
+
+	uint8_t control;	/* 01 */
+
+	uint16_t exeThrottle;	/* 02-03 */
+	uint16_t exeCount;	/* 04-05 */
+	uint8_t retryCount;	/* 06	 */
+	uint8_t retryDelay;	/* 07	 */
+	uint16_t iSCSIOptions;	/* 08-09 */
+
+	uint16_t TCPOptions;	/* 0A-0B */
+
+	uint16_t IPOptions;	/* 0C-0D */
+
+	uint16_t maxPDUSize;	/* 0E-0F */
+	uint16_t rcvMarkerInt;	/* 10-11 */
+	uint16_t sndMarkerInt;	/* 12-13 */
+	uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */
+	uint16_t firstBurstSize;	/* 16-17 */
+	uint16_t minTime2Wait;	/* 18-19 : RA :default_time2wait */
+	uint16_t maxTime2Retain;	/* 1A-1B */
+	uint16_t maxOutstndngR2T;	/* 1C-1D */
+	uint16_t keepAliveTimeout;	/* 1E-1F */
+	uint8_t ISID[6];	/* 20-25 big-endian, must be converted
+				 * to little-endian */
+	uint16_t TSID;		/* 26-27 */
+	uint16_t portNumber;	/* 28-29 */
+	uint16_t maxBurstSize;	/* 2A-2B */
+	uint16_t taskMngmntTimeout;	/* 2C-2D */
+	uint16_t reserved1;	/* 2E-2F */
+	uint8_t ipAddr[0x10];	/* 30-3F */
+	uint8_t iSCSIAlias[0x20];	/* 40-5F */
+	uint8_t targetAddr[0x20];	/* 60-7F */
+	uint8_t userID[0x20];	/* 80-9F */
+	uint8_t password[0x20]; /* A0-BF */
+	uint8_t iscsiName[0x100];	/* C0-1BF : xxzzy Make this a
+					 * pointer to a string so we
+					 * don't have to reserve soooo
+					 * much RAM */
+	uint16_t ddbLink;	/* 1C0-1C1 */
+	uint16_t CHAPTableIndex; /* 1C2-1C3 */
+	uint16_t TargetPortalGroup; /* 1C4-1C5 */
+	uint16_t reserved2[2];	/* 1C6-1C7 */
+	uint32_t statSN;	/* 1C8-1CB */
+	uint32_t expStatSN;	/* 1CC-1CF */
+	uint16_t reserved3[0x2C]; /* 1D0-1FB */
+	uint16_t ddbValidCookie; /* 1FC-1FD */
+	uint16_t ddbValidSize;	/* 1FE-1FF */
+};
+
+/*************************************************************************/
+
+/* Flash definitions */
+
+#define FLASH_OFFSET_SYS_INFO	0x02000000
+#define FLASH_DEFAULTBLOCKSIZE	0x20000
+#define FLASH_EOF_OFFSET	(FLASH_DEFAULTBLOCKSIZE-8) /* 4 bytes
+							    * for EOF
+							    * signature */
+
+struct sys_info_phys_addr {
+	uint8_t address[6];	/* 00-05 */
+	uint8_t filler[2];	/* 06-07 */
+};
+
+struct flash_sys_info {
+	uint32_t cookie;	/* 00-03 */
+	uint32_t physAddrCount; /* 04-07 */
+	struct sys_info_phys_addr physAddr[4]; /* 08-27 */
+	uint8_t vendorId[128];	/* 28-A7 */
+	uint8_t productId[128]; /* A8-127 */
+	uint32_t serialNumber;	/* 128-12B */
+
+	/*  PCI Configuration values */
+	uint32_t pciDeviceVendor;	/* 12C-12F */
+	uint32_t pciDeviceId;	/* 130-133 */
+	uint32_t pciSubsysVendor;	/* 134-137 */
+	uint32_t pciSubsysId;	/* 138-13B */
+
+	/*  This validates version 1. */
+	uint32_t crumbs;	/* 13C-13F */
+
+	uint32_t enterpriseNumber;	/* 140-143 */
+
+	uint32_t mtu;		/* 144-147 */
+	uint32_t reserved0;	/* 148-14b */
+	uint32_t crumbs2;	/* 14c-14f */
+	uint8_t acSerialNumber[16];	/* 150-15f */
+	uint32_t crumbs3;	/* 160-16f */
+
+	/* Leave this last in the struct so it is declared invalid if
+	 * any new items are added.
+	 */
+	uint32_t reserved1[39]; /* 170-1ff */
+};	/* 200 */
+
+struct crash_record {
+	uint16_t fw_major_version;	/* 00 - 01 */
+	uint16_t fw_minor_version;	/* 02 - 03 */
+	uint16_t fw_patch_version;	/* 04 - 05 */
+	uint16_t fw_build_version;	/* 06 - 07 */
+
+	uint8_t build_date[16]; /* 08 - 17 */
+	uint8_t build_time[16]; /* 18 - 27 */
+	uint8_t build_user[16]; /* 28 - 37 */
+	uint8_t card_serial_num[16];	/* 38 - 47 */
+
+	uint32_t time_of_crash_in_secs; /* 48 - 4B */
+	uint32_t time_of_crash_in_ms;	/* 4C - 4F */
+
+	uint16_t out_RISC_sd_num_frames;	/* 50 - 51 */
+	uint16_t OAP_sd_num_words;	/* 52 - 53 */
+	uint16_t IAP_sd_num_frames;	/* 54 - 55 */
+	uint16_t in_RISC_sd_num_words;	/* 56 - 57 */
+
+	uint8_t reserved1[28];	/* 58 - 7F */
+
+	uint8_t out_RISC_reg_dump[256]; /* 80 -17F */
+	uint8_t in_RISC_reg_dump[256];	/*180 -27F */
+	uint8_t in_out_RISC_stack_dump[0];	/*280 - ??? */
+};
+
+struct conn_event_log_entry {
+#define MAX_CONN_EVENT_LOG_ENTRIES	100
+	uint32_t timestamp_sec; /* 00 - 03 seconds since boot */
+	uint32_t timestamp_ms;	/* 04 - 07 milliseconds since boot */
+	uint16_t device_index;	/* 08 - 09  */
+	uint16_t fw_conn_state; /* 0A - 0B  */
+	uint8_t event_type;	/* 0C - 0C  */
+	uint8_t error_code;	/* 0D - 0D  */
+	uint16_t error_code_detail;	/* 0E - 0F  */
+	uint8_t num_consecutive_events; /* 10 - 10  */
+	uint8_t rsvd[3];	/* 11 - 13  */
+};
+
+/*************************************************************************
+ *
+ *				IOCB Commands Structures and Definitions
+ *
+ *************************************************************************/
+#define IOCB_MAX_CDB_LEN	    16	/* Bytes in a CBD */
+#define IOCB_MAX_SENSEDATA_LEN	    32	/* Bytes of sense data */
+
+/* IOCB header structure */
+struct qla4_header {
+	uint8_t entryType;
+#define ET_STATUS		 0x03
+#define ET_MARKER		 0x04
+#define ET_CONT_T1		 0x0A
+#define ET_STATUS_CONTINUATION	 0x10
+#define ET_CMND_T3		 0x19
+#define ET_PASSTHRU0		 0x3A
+#define ET_PASSTHRU_STATUS	 0x3C
+
+	uint8_t entryStatus;
+	uint8_t systemDefined;
+	uint8_t entryCount;
+
+	/* SyetemDefined definition */
+};
+
+/* Generic queue entry structure*/
+struct queue_entry {
+	uint8_t data[60];
+	uint32_t signature;
+
+};
+
+/* 64 bit addressing segment counts*/
+
+#define COMMAND_SEG_A64	  1
+#define CONTINUE_SEG_A64  5
+
+/* 64 bit addressing segment definition*/
+
+struct data_seg_a64 {
+	struct {
+		uint32_t addrLow;
+		uint32_t addrHigh;
+
+	} base;
+
+	uint32_t count;
+
+};
+
+/* Command Type 3 entry structure*/
+
+struct command_t3_entry {
+	struct qla4_header hdr;	/* 00-03 */
+
+	uint32_t handle;	/* 04-07 */
+	uint16_t target;	/* 08-09 */
+	uint16_t connection_id; /* 0A-0B */
+
+	uint8_t control_flags;	/* 0C */
+
+	/* data direction  (bits 5-6) */
+#define CF_WRITE		0x20
+#define CF_READ			0x40
+#define CF_NO_DATA		0x00
+
+	/* task attributes (bits 2-0) */
+#define CF_HEAD_TAG		0x03
+#define CF_ORDERED_TAG		0x02
+#define CF_SIMPLE_TAG		0x01
+
+	/* STATE FLAGS FIELD IS A PLACE HOLDER. THE FW WILL SET BITS
+	 * IN THIS FIELD AS THE COMMAND IS PROCESSED. WHEN THE IOCB IS
+	 * CHANGED TO AN IOSB THIS FIELD WILL HAVE THE STATE FLAGS SET
+	 * PROPERLY.
+	 */
+	uint8_t state_flags;	/* 0D */
+	uint8_t cmdRefNum;	/* 0E */
+	uint8_t reserved1;	/* 0F */
+	uint8_t cdb[IOCB_MAX_CDB_LEN];	/* 10-1F */
+	struct scsi_lun lun;	/* FCP LUN (BE). */
+	uint32_t cmdSeqNum;	/* 28-2B */
+	uint16_t timeout;	/* 2C-2D */
+	uint16_t dataSegCnt;	/* 2E-2F */
+	uint32_t ttlByteCnt;	/* 30-33 */
+	struct data_seg_a64 dataseg[COMMAND_SEG_A64];	/* 34-3F */
+
+};
+
+
+/* Continuation Type 1 entry structure*/
+struct continuation_t1_entry {
+	struct qla4_header hdr;
+
+	struct data_seg_a64 dataseg[CONTINUE_SEG_A64];
+
+};
+
+/* Parameterize for 64 or 32 bits */
+#define COMMAND_SEG	COMMAND_SEG_A64
+#define CONTINUE_SEG	CONTINUE_SEG_A64
+
+#define ET_COMMAND	ET_CMND_T3
+#define ET_CONTINUE	ET_CONT_T1
+
+/* Marker entry structure*/
+struct marker_entry {
+	struct qla4_header hdr;	/* 00-03 */
+
+	uint32_t system_defined; /* 04-07 */
+	uint16_t target;	/* 08-09 */
+	uint16_t modifier;	/* 0A-0B */
+#define MM_LUN_RESET	     0
+
+	uint16_t flags;		/* 0C-0D */
+	uint16_t reserved1;	/* 0E-0F */
+	struct scsi_lun lun;	/* FCP LUN (BE). */
+	uint64_t reserved2;	/* 18-1F */
+	uint64_t reserved3;	/* 20-27 */
+	uint64_t reserved4;	/* 28-2F */
+	uint64_t reserved5;	/* 30-37 */
+	uint64_t reserved6;	/* 38-3F */
+};
+
+/* Status entry structure*/
+struct status_entry {
+	struct qla4_header hdr;	/* 00-03 */
+
+	uint32_t handle;	/* 04-07 */
+
+	uint8_t scsiStatus;	/* 08 */
+#define SCSI_CHECK_CONDITION		  0x02
+
+	uint8_t iscsiFlags;	/* 09 */
+#define ISCSI_FLAG_RESIDUAL_UNDER	  0x02
+#define ISCSI_FLAG_RESIDUAL_OVER	  0x04
+
+	uint8_t iscsiResponse;	/* 0A */
+
+	uint8_t completionStatus;	/* 0B */
+#define SCS_COMPLETE			  0x00
+#define SCS_INCOMPLETE			  0x01
+#define SCS_RESET_OCCURRED		  0x04
+#define SCS_ABORTED			  0x05
+#define SCS_TIMEOUT			  0x06
+#define SCS_DATA_OVERRUN		  0x07
+#define SCS_DATA_UNDERRUN		  0x15
+#define SCS_QUEUE_FULL			  0x1C
+#define SCS_DEVICE_UNAVAILABLE		  0x28
+#define SCS_DEVICE_LOGGED_OUT		  0x29
+
+	uint8_t reserved1;	/* 0C */
+
+	/* state_flags MUST be at the same location as state_flags in
+	 * the Command_T3/4_Entry */
+	uint8_t state_flags;	/* 0D */
+
+	uint16_t senseDataByteCnt;	/* 0E-0F */
+	uint32_t residualByteCnt;	/* 10-13 */
+	uint32_t bidiResidualByteCnt;	/* 14-17 */
+	uint32_t expSeqNum;	/* 18-1B */
+	uint32_t maxCmdSeqNum;	/* 1C-1F */
+	uint8_t senseData[IOCB_MAX_SENSEDATA_LEN];	/* 20-3F */
+
+};
+
+struct passthru0 {
+	struct qla4_header hdr;		       /* 00-03 */
+	uint32_t handle;	/* 04-07 */
+	uint16_t target;	/* 08-09 */
+	uint16_t connectionID;	/* 0A-0B */
+#define ISNS_DEFAULT_SERVER_CONN_ID	((uint16_t)0x8000)
+
+	uint16_t controlFlags;	/* 0C-0D */
+#define PT_FLAG_ETHERNET_FRAME		0x8000
+#define PT_FLAG_ISNS_PDU		0x8000
+#define PT_FLAG_SEND_BUFFER		0x0200
+#define PT_FLAG_WAIT_4_RESPONSE		0x0100
+
+	uint16_t timeout;	/* 0E-0F */
+#define PT_DEFAULT_TIMEOUT		30 /* seconds */
+
+	struct data_seg_a64 outDataSeg64;	/* 10-1B */
+	uint32_t res1;		/* 1C-1F */
+	struct data_seg_a64 inDataSeg64;	/* 20-2B */
+	uint8_t res2[20];	/* 2C-3F */
+};
+
+struct passthru_status {
+	struct qla4_header hdr;		       /* 00-03 */
+	uint32_t handle;	/* 04-07 */
+	uint16_t target;	/* 08-09 */
+	uint16_t connectionID;	/* 0A-0B */
+
+	uint8_t completionStatus;	/* 0C */
+#define PASSTHRU_STATUS_COMPLETE		0x01
+
+	uint8_t residualFlags;	/* 0D */
+
+	uint16_t timeout;	/* 0E-0F */
+	uint16_t portNumber;	/* 10-11 */
+	uint8_t res1[10];	/* 12-1B */
+	uint32_t outResidual;	/* 1C-1F */
+	uint8_t res2[12];	/* 20-2B */
+	uint32_t inResidual;	/* 2C-2F */
+	uint8_t res4[16];	/* 30-3F */
+};
+
+#endif /*  _QLA4X_FW_H */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
new file mode 100644
index 0000000..2c803ed
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -0,0 +1,78 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#ifndef __QLA4x_GBL_H
+#define	__QLA4x_GBL_H
+
+int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
+int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
+int qla4xxx_initialize_adapter(struct scsi_qla_host * ha,
+			       uint8_t renew_ddb_list);
+int qla4xxx_soft_reset(struct scsi_qla_host *ha);
+irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id);
+
+void qla4xxx_free_ddb_list(struct scsi_qla_host * ha);
+void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen);
+
+int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha);
+int qla4xxx_relogin_device(struct scsi_qla_host * ha,
+			   struct ddb_entry * ddb_entry);
+int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+		      int lun);
+int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+		      uint32_t offset, uint32_t len);
+int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
+int qla4xxx_get_firmware_state(struct scsi_qla_host * ha);
+int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha);
+
+/* FIXME: Goodness!  this really wants a small struct to hold the
+ * parameters. On x86 the args will get passed on the stack! */
+int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
+			    uint16_t fw_ddb_index,
+			    struct dev_db_entry *fw_ddb_entry,
+			    dma_addr_t fw_ddb_entry_dma,
+			    uint32_t *num_valid_ddb_entries,
+			    uint32_t *next_ddb_index,
+			    uint32_t *fw_ddb_device_state,
+			    uint32_t *conn_err_detail,
+			    uint16_t *tcp_source_port_num,
+			    uint16_t *connection_id);
+
+struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host * ha,
+				     uint32_t fw_ddb_index);
+int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
+			  dma_addr_t fw_ddb_entry_dma);
+
+void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
+				 struct ddb_entry *ddb_entry);
+u16 rd_nvram_word(struct scsi_qla_host * ha, int offset);
+void qla4xxx_get_crash_record(struct scsi_qla_host * ha);
+struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha);
+int qla4xxx_add_sess(struct ddb_entry *);
+void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry);
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
+				   uint16_t fw_ddb_index,
+				   uint16_t connection_id,
+				   uint16_t option);
+int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
+				 uint16_t fw_ddb_index);
+int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha);
+int qla4xxx_get_fw_version(struct scsi_qla_host * ha);
+void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
+				       uint32_t intr_status);
+int qla4xxx_init_rings(struct scsi_qla_host * ha);
+void qla4xxx_dump_buffer(void *b, uint32_t size);
+struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
+void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
+int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
+int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
+				uint32_t fw_ddb_index, uint32_t state);
+
+extern int qla4_extended_error_logging;
+extern int ql4xdiscoverywait;
+extern int ql4xdontresethba;
+#endif				/* _QLA4x_GBL_H */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
new file mode 100644
index 0000000..bb3a1c1
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -0,0 +1,1340 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+
+/*
+ * QLogic ISP4xxx Hardware Support Function Prototypes.
+ */
+
+static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
+{
+	uint32_t value;
+	uint8_t func_number;
+	unsigned long flags;
+
+	/* Get the function number */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	value = readw(&ha->reg->ctrl_status);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	func_number = (uint8_t) ((value >> 4) & 0x30);
+	switch (value & ISP_CONTROL_FN_MASK) {
+	case ISP_CONTROL_FN0_SCSI:
+		ha->mac_index = 1;
+		break;
+	case ISP_CONTROL_FN1_SCSI:
+		ha->mac_index = 3;
+		break;
+	default:
+		DEBUG2(printk("scsi%ld: %s: Invalid function number, "
+			      "ispControlStatus = 0x%x\n", ha->host_no,
+			      __func__, value));
+		break;
+	}
+	DEBUG2(printk("scsi%ld: %s: mac_index %d.\n", ha->host_no, __func__,
+		      ha->mac_index));
+}
+
+/**
+ * qla4xxx_free_ddb - deallocate ddb
+ * @ha: pointer to host adapter structure.
+ * @ddb_entry: pointer to device database entry
+ *
+ * This routine deallocates and unlinks the specified ddb_entry from the
+ * adapter's
+ **/
+void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry)
+{
+	/* Remove device entry from list */
+	list_del_init(&ddb_entry->list);
+
+	/* Remove device pointer from index mapping arrays */
+	ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] =
+		(struct ddb_entry *) INVALID_ENTRY;
+	ha->tot_ddbs--;
+
+	/* Free memory and scsi-ml struct for device entry */
+	qla4xxx_destroy_sess(ddb_entry);
+}
+
+/**
+ * qla4xxx_free_ddb_list - deallocate all ddbs
+ * @ha: pointer to host adapter structure.
+ *
+ * This routine deallocates and removes all devices on the sppecified adapter.
+ **/
+void qla4xxx_free_ddb_list(struct scsi_qla_host *ha)
+{
+	struct list_head *ptr;
+	struct ddb_entry *ddb_entry;
+
+	while (!list_empty(&ha->ddb_list)) {
+		ptr = ha->ddb_list.next;
+		/* Free memory for device entry and remove */
+		ddb_entry = list_entry(ptr, struct ddb_entry, list);
+		qla4xxx_free_ddb(ha, ddb_entry);
+	}
+}
+
+/**
+ * qla4xxx_init_rings - initialize hw queues
+ * @ha: pointer to host adapter structure.
+ *
+ * This routine initializes the internal queues for the specified adapter.
+ * The QLA4010 requires us to restart the queues at index 0.
+ * The QLA4000 doesn't care, so just default to QLA4010's requirement.
+ **/
+int qla4xxx_init_rings(struct scsi_qla_host *ha)
+{
+	unsigned long flags = 0;
+
+	/* Initialize request queue. */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	ha->request_out = 0;
+	ha->request_in = 0;
+	ha->request_ptr = &ha->request_ring[ha->request_in];
+	ha->req_q_count = REQUEST_QUEUE_DEPTH;
+
+	/* Initialize response queue. */
+	ha->response_in = 0;
+	ha->response_out = 0;
+	ha->response_ptr = &ha->response_ring[ha->response_out];
+
+	/*
+	 * Initialize DMA Shadow registers.  The firmware is really supposed to
+	 * take care of this, but on some uniprocessor systems, the shadow
+	 * registers aren't cleared-- causing the interrupt_handler to think
+	 * there are responses to be processed when there aren't.
+	 */
+	ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0);
+	ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0);
+	wmb();
+
+	writel(0, &ha->reg->req_q_in);
+	writel(0, &ha->reg->rsp_q_out);
+	readl(&ha->reg->rsp_q_out);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_validate_mac_address - validate adapter MAC address(es)
+ * @ha: pointer to host adapter structure.
+ *
+ **/
+static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha)
+{
+	struct flash_sys_info *sys_info;
+	dma_addr_t sys_info_dma;
+	int status = QLA_ERROR;
+
+	sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+				      &sys_info_dma, GFP_KERNEL);
+	if (sys_info == NULL) {
+		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
+			      ha->host_no, __func__));
+
+		goto exit_validate_mac_no_free;
+	}
+	memset(sys_info, 0, sizeof(*sys_info));
+
+	/* Get flash sys info */
+	if (qla4xxx_get_flash(ha, sys_info_dma, FLASH_OFFSET_SYS_INFO,
+			      sizeof(*sys_info)) != QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: get_flash FLASH_OFFSET_SYS_INFO "
+			      "failed\n", ha->host_no, __func__));
+
+		goto exit_validate_mac;
+	}
+
+	/* Save M.A.C. address & serial_number */
+	memcpy(ha->my_mac, &sys_info->physAddr[0].address[0],
+	       min(sizeof(ha->my_mac),
+		   sizeof(sys_info->physAddr[0].address)));
+	memcpy(ha->serial_number, &sys_info->acSerialNumber,
+	       min(sizeof(ha->serial_number),
+		   sizeof(sys_info->acSerialNumber)));
+
+	status = QLA_SUCCESS;
+
+ exit_validate_mac:
+	dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info,
+			  sys_info_dma);
+
+ exit_validate_mac_no_free:
+	return status;
+}
+
+/**
+ * qla4xxx_init_local_data - initialize adapter specific local data
+ * @ha: pointer to host adapter structure.
+ *
+ **/
+static int qla4xxx_init_local_data(struct scsi_qla_host *ha)
+{
+	/* Initilize aen queue */
+	ha->aen_q_count = MAX_AEN_ENTRIES;
+
+	return qla4xxx_get_firmware_status(ha);
+}
+
+static int qla4xxx_fw_ready(struct scsi_qla_host *ha)
+{
+	uint32_t timeout_count;
+	int ready = 0;
+
+	DEBUG2(dev_info(&ha->pdev->dev, "Waiting for Firmware Ready..\n"));
+	for (timeout_count = ADAPTER_INIT_TOV; timeout_count > 0;
+	     timeout_count--) {
+		if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
+			qla4xxx_get_dhcp_ip_address(ha);
+
+		/* Get firmware state. */
+		if (qla4xxx_get_firmware_state(ha) != QLA_SUCCESS) {
+			DEBUG2(printk("scsi%ld: %s: unable to get firmware "
+				      "state\n", ha->host_no, __func__));
+			break;
+
+		}
+
+		if (ha->firmware_state & FW_STATE_ERROR) {
+			DEBUG2(printk("scsi%ld: %s: an unrecoverable error has"
+				      " occurred\n", ha->host_no, __func__));
+			break;
+
+		}
+		if (ha->firmware_state & FW_STATE_CONFIG_WAIT) {
+			/*
+			 * The firmware has not yet been issued an Initialize
+			 * Firmware command, so issue it now.
+			 */
+			if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR)
+				break;
+
+			/* Go back and test for ready state - no wait. */
+			continue;
+		}
+
+		if (ha->firmware_state == FW_STATE_READY) {
+			DEBUG2(dev_info(&ha->pdev->dev, "Firmware Ready..\n"));
+			/* The firmware is ready to process SCSI commands. */
+			DEBUG2(dev_info(&ha->pdev->dev,
+					  "scsi%ld: %s: MEDIA TYPE - %s\n",
+					  ha->host_no,
+					  __func__, (ha->addl_fw_state &
+						     FW_ADDSTATE_OPTICAL_MEDIA)
+					  != 0 ? "OPTICAL" : "COPPER"));
+			DEBUG2(dev_info(&ha->pdev->dev,
+					  "scsi%ld: %s: DHCP STATE Enabled "
+					  "%s\n",
+					  ha->host_no, __func__,
+					  (ha->addl_fw_state &
+					   FW_ADDSTATE_DHCP_ENABLED) != 0 ?
+					  "YES" : "NO"));
+			DEBUG2(dev_info(&ha->pdev->dev,
+					  "scsi%ld: %s: LINK %s\n",
+					  ha->host_no, __func__,
+					  (ha->addl_fw_state &
+					   FW_ADDSTATE_LINK_UP) != 0 ?
+					  "UP" : "DOWN"));
+			DEBUG2(dev_info(&ha->pdev->dev,
+					  "scsi%ld: %s: iSNS Service "
+					  "Started %s\n",
+					  ha->host_no, __func__,
+					  (ha->addl_fw_state &
+					   FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ?
+					  "YES" : "NO"));
+
+			ready = 1;
+			break;
+		}
+		DEBUG2(printk("scsi%ld: %s: waiting on fw, state=%x:%x - "
+			      "seconds expired= %d\n", ha->host_no, __func__,
+			      ha->firmware_state, ha->addl_fw_state,
+			      timeout_count));
+		msleep(1000);
+	}			/* end of for */
+
+	if (timeout_count <= 0)
+		DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n",
+			      ha->host_no, __func__));
+
+	if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS)  {
+		DEBUG2(printk("scsi%ld: %s: FW is reporting its waiting to"
+			      " grab an IP address from DHCP server\n",
+			      ha->host_no, __func__));
+		ready = 1;
+	}
+
+	return ready;
+}
+
+/**
+ * qla4xxx_init_firmware - initializes the firmware.
+ * @ha: pointer to host adapter structure.
+ *
+ **/
+static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
+{
+	int status = QLA_ERROR;
+
+	dev_info(&ha->pdev->dev, "Initializing firmware..\n");
+	if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) {
+		DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware "
+			      "control block\n", ha->host_no, __func__));
+		return status;
+	}
+	if (!qla4xxx_fw_ready(ha))
+		return status;
+
+	set_bit(AF_ONLINE, &ha->flags);
+	return qla4xxx_get_firmware_status(ha);
+}
+
+static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
+					       uint32_t fw_ddb_index)
+{
+	struct dev_db_entry *fw_ddb_entry = NULL;
+	dma_addr_t fw_ddb_entry_dma;
+	struct ddb_entry *ddb_entry = NULL;
+	int found = 0;
+	uint32_t device_state;
+
+	/* Make sure the dma buffer is valid */
+	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
+					  sizeof(*fw_ddb_entry),
+					  &fw_ddb_entry_dma, GFP_KERNEL);
+	if (fw_ddb_entry == NULL) {
+		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
+			      ha->host_no, __func__));
+		return NULL;
+	}
+
+	if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
+				    fw_ddb_entry_dma, NULL, NULL,
+				    &device_state, NULL, NULL, NULL) ==
+	    QLA_ERROR) {
+		DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
+			      "fw_ddb_index %d\n", ha->host_no, __func__,
+			      fw_ddb_index));
+		return NULL;
+	}
+
+	/* Allocate DDB if not already allocated. */
+	DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
+		      __func__, fw_ddb_index));
+	list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
+		if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName,
+			   ISCSI_NAME_SIZE) == 0) {
+			found++;
+			break;
+		}
+	}
+
+	if (!found) {
+		DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
+			      "new ddb\n", ha->host_no, __func__,
+			      fw_ddb_index));
+		ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
+	}
+
+	/* if not found allocate new ddb */
+	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
+			  fw_ddb_entry_dma);
+
+	return ddb_entry;
+}
+
+/**
+ * qla4xxx_update_ddb_entry - update driver's internal ddb
+ * @ha: pointer to host adapter structure.
+ * @ddb_entry: pointer to device database structure to be filled
+ * @fw_ddb_index: index of the ddb entry in fw ddb table
+ *
+ * This routine updates the driver's internal device database entry
+ * with information retrieved from the firmware's device database
+ * entry for the specified device. The ddb_entry->fw_ddb_index field
+ * must be initialized prior to	calling this routine
+ *
+ **/
+int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
+			     struct ddb_entry *ddb_entry,
+			     uint32_t fw_ddb_index)
+{
+	struct dev_db_entry *fw_ddb_entry = NULL;
+	dma_addr_t fw_ddb_entry_dma;
+	int status = QLA_ERROR;
+
+	if (ddb_entry == NULL) {
+		DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no,
+			      __func__));
+		goto exit_update_ddb;
+	}
+
+	/* Make sure the dma buffer is valid */
+	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
+					  sizeof(*fw_ddb_entry),
+					  &fw_ddb_entry_dma, GFP_KERNEL);
+	if (fw_ddb_entry == NULL) {
+		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
+			      ha->host_no, __func__));
+
+		goto exit_update_ddb;
+	}
+
+	if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
+				    fw_ddb_entry_dma, NULL, NULL,
+				    &ddb_entry->fw_ddb_device_state, NULL,
+				    &ddb_entry->tcp_source_port_num,
+				    &ddb_entry->connection_id) ==
+	    QLA_ERROR) {
+		DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
+			      "fw_ddb_index %d\n", ha->host_no, __func__,
+			      fw_ddb_index));
+
+		goto exit_update_ddb;
+	}
+
+	status = QLA_SUCCESS;
+	ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID);
+	ddb_entry->task_mgmt_timeout =
+		le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
+	ddb_entry->CmdSn = 0;
+	ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle);
+	ddb_entry->default_relogin_timeout =
+		le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
+	ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait);
+
+	/* Update index in case it changed */
+	ddb_entry->fw_ddb_index = fw_ddb_index;
+	ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
+
+	ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber);
+	ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup);
+	memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0],
+	       min(sizeof(ddb_entry->iscsi_name),
+		   sizeof(fw_ddb_entry->iscsiName)));
+	memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0],
+	       min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr)));
+
+	DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
+		      ha->host_no, __func__, fw_ddb_index,
+		      ddb_entry->fw_ddb_device_state, status));
+
+ exit_update_ddb:
+	if (fw_ddb_entry)
+		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+				  fw_ddb_entry, fw_ddb_entry_dma);
+
+	return status;
+}
+
+/**
+ * qla4xxx_alloc_ddb - allocate device database entry
+ * @ha: Pointer to host adapter structure.
+ * @fw_ddb_index: Firmware's device database index
+ *
+ * This routine allocates a ddb_entry, ititializes some values, and
+ * inserts it into the ddb list.
+ **/
+struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
+				     uint32_t fw_ddb_index)
+{
+	struct ddb_entry *ddb_entry;
+
+	DEBUG2(printk("scsi%ld: %s: fw_ddb_index [%d]\n", ha->host_no,
+		      __func__, fw_ddb_index));
+
+	ddb_entry = qla4xxx_alloc_sess(ha);
+	if (ddb_entry == NULL) {
+		DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
+			      "to add fw_ddb_index [%d]\n",
+			      ha->host_no, __func__, fw_ddb_index));
+		return ddb_entry;
+	}
+
+	ddb_entry->fw_ddb_index = fw_ddb_index;
+	atomic_set(&ddb_entry->port_down_timer, ha->port_down_retry_count);
+	atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
+	atomic_set(&ddb_entry->relogin_timer, 0);
+	atomic_set(&ddb_entry->relogin_retry_count, 0);
+	atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+	list_add_tail(&ddb_entry->list, &ha->ddb_list);
+	ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
+	ha->tot_ddbs++;
+
+	return ddb_entry;
+}
+
+/**
+ * qla4xxx_configure_ddbs - builds driver ddb list
+ * @ha: Pointer to host adapter structure.
+ *
+ * This routine searches for all valid firmware ddb entries and builds
+ * an internal ddb list. Ddbs that are considered valid are those with
+ * a device state of SESSION_ACTIVE.
+ **/
+static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
+{
+	int status = QLA_SUCCESS;
+	uint32_t fw_ddb_index = 0;
+	uint32_t next_fw_ddb_index = 0;
+	uint32_t ddb_state;
+	uint32_t conn_err, err_code;
+	struct ddb_entry *ddb_entry;
+
+	dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
+	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
+	     fw_ddb_index = next_fw_ddb_index) {
+		/* First, let's see if a device exists here */
+		if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, NULL, 0, NULL,
+					    &next_fw_ddb_index, &ddb_state,
+					    &conn_err, NULL, NULL) ==
+		    QLA_ERROR) {
+			DEBUG2(printk("scsi%ld: %s: get_ddb_entry, "
+				      "fw_ddb_index %d failed", ha->host_no,
+				      __func__, fw_ddb_index));
+			return QLA_ERROR;
+		}
+
+		DEBUG2(printk("scsi%ld: %s: Getting DDB[%d] ddbstate=0x%x, "
+			      "next_fw_ddb_index=%d.\n", ha->host_no, __func__,
+			      fw_ddb_index, ddb_state, next_fw_ddb_index));
+
+		/* Issue relogin, if necessary. */
+		if (ddb_state == DDB_DS_SESSION_FAILED ||
+		    ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) {
+			/* Try and login to device */
+			DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n",
+				      ha->host_no, __func__, fw_ddb_index));
+			err_code = ((conn_err & 0x00ff0000) >> 16);
+			if (err_code == 0x1c || err_code == 0x06) {
+				DEBUG2(printk("scsi%ld: %s send target "
+					      "completed "
+					      "or access denied failure\n",
+					      ha->host_no, __func__));
+			} else
+				qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
+		}
+
+		if (ddb_state != DDB_DS_SESSION_ACTIVE)
+			goto next_one;
+		/*
+		 * if fw_ddb with session active state found,
+		 * add to ddb_list
+		 */
+		DEBUG2(printk("scsi%ld: %s: DDB[%d] added to list\n",
+			      ha->host_no, __func__, fw_ddb_index));
+
+		/* Add DDB to internal our ddb list. */
+		ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+		if (ddb_entry == NULL) {
+			DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
+				      "for device at fw_ddb_index %d\n",
+				      ha->host_no, __func__, fw_ddb_index));
+			return QLA_ERROR;
+		}
+		/* Fill in the device structure */
+		if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
+		    QLA_ERROR) {
+			ha->fw_ddb_index_map[fw_ddb_index] =
+				(struct ddb_entry *)INVALID_ENTRY;
+
+
+			DEBUG2(printk("scsi%ld: %s: update_ddb_entry failed "
+				      "for fw_ddb_index %d.\n",
+				      ha->host_no, __func__, fw_ddb_index));
+			return QLA_ERROR;
+		}
+
+next_one:
+		/* We know we've reached the last device when
+		 * next_fw_ddb_index is 0 */
+		if (next_fw_ddb_index == 0)
+			break;
+	}
+
+	dev_info(&ha->pdev->dev, "DDB list done..\n");
+
+	return status;
+}
+
+struct qla4_relog_scan {
+	int halt_wait;
+	uint32_t conn_err;
+	uint32_t err_code;
+	uint32_t fw_ddb_index;
+	uint32_t next_fw_ddb_index;
+	uint32_t fw_ddb_device_state;
+};
+
+static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs)
+{
+	struct ddb_entry *ddb_entry;
+
+	/*
+	 * Don't want to do a relogin if connection
+	 * error is 0x1c.
+	 */
+	rs->err_code = ((rs->conn_err & 0x00ff0000) >> 16);
+	if (rs->err_code == 0x1c || rs->err_code == 0x06) {
+		DEBUG2(printk(
+			       "scsi%ld: %s send target"
+			       " completed or "
+			       "access denied failure\n",
+			       ha->host_no, __func__));
+	} else {
+		/* We either have a device that is in
+		 * the process of relogging in or a
+		 * device that is waiting to be
+		 * relogged in */
+		rs->halt_wait = 0;
+
+		ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha,
+							   rs->fw_ddb_index);
+		if (ddb_entry == NULL)
+			return QLA_ERROR;
+
+		if (ddb_entry->dev_scan_wait_to_start_relogin != 0
+		    && time_after_eq(jiffies,
+				     ddb_entry->
+				     dev_scan_wait_to_start_relogin))
+		{
+			ddb_entry->dev_scan_wait_to_start_relogin = 0;
+			qla4xxx_set_ddb_entry(ha, rs->fw_ddb_index, 0);
+		}
+	}
+	return QLA_SUCCESS;
+}
+
+static int qla4_scan_for_relogin(struct scsi_qla_host *ha,
+				 struct qla4_relog_scan *rs)
+{
+	int error;
+
+	/* scan for relogins
+	 * ----------------- */
+	for (rs->fw_ddb_index = 0; rs->fw_ddb_index < MAX_DDB_ENTRIES;
+	     rs->fw_ddb_index = rs->next_fw_ddb_index) {
+		if (qla4xxx_get_fwddb_entry(ha, rs->fw_ddb_index, NULL, 0,
+					    NULL, &rs->next_fw_ddb_index,
+					    &rs->fw_ddb_device_state,
+					    &rs->conn_err, NULL, NULL)
+		    == QLA_ERROR)
+			return QLA_ERROR;
+
+		if (rs->fw_ddb_device_state == DDB_DS_LOGIN_IN_PROCESS)
+			rs->halt_wait = 0;
+
+		if (rs->fw_ddb_device_state == DDB_DS_SESSION_FAILED ||
+		    rs->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE) {
+			error = qla4_test_rdy(ha, rs);
+			if (error)
+				return error;
+		}
+
+		/* We know we've reached the last device when
+		 * next_fw_ddb_index is 0 */
+		if (rs->next_fw_ddb_index == 0)
+			break;
+	}
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_devices_ready - wait for target devices to be logged in
+ * @ha: pointer to adapter structure
+ *
+ * This routine waits up to ql4xdiscoverywait seconds
+ * F/W database during driver load time.
+ **/
+static int qla4xxx_devices_ready(struct scsi_qla_host *ha)
+{
+	int error;
+	unsigned long discovery_wtime;
+	struct qla4_relog_scan rs;
+
+	discovery_wtime = jiffies + (ql4xdiscoverywait * HZ);
+
+	DEBUG(printk("Waiting (%d) for devices ...\n", ql4xdiscoverywait));
+	do {
+		/* poll for AEN. */
+		qla4xxx_get_firmware_state(ha);
+		if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) {
+			/* Set time-between-relogin timer */
+			qla4xxx_process_aen(ha, RELOGIN_DDB_CHANGED_AENS);
+		}
+
+		/* if no relogins active or needed, halt discvery wait */
+		rs.halt_wait = 1;
+
+		error = qla4_scan_for_relogin(ha, &rs);
+
+		if (rs.halt_wait) {
+			DEBUG2(printk("scsi%ld: %s: Delay halted.  Devices "
+				      "Ready.\n", ha->host_no, __func__));
+			return QLA_SUCCESS;
+		}
+
+		msleep(2000);
+	} while (!time_after_eq(jiffies, discovery_wtime));
+
+	DEBUG3(qla4xxx_get_conn_event_log(ha));
+
+	return QLA_SUCCESS;
+}
+
+static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
+{
+	unsigned long wtime;
+
+	/* Flush the 0x8014 AEN from the firmware as a result of
+	 * Auto connect. We are basically doing get_firmware_ddb()
+	 * to determine whether we need to log back in or not.
+	 *  Trying to do a set ddb before we have processed 0x8014
+	 *  will result in another set_ddb() for the same ddb. In other
+	 *  words there will be stale entries in the aen_q.
+	 */
+	wtime = jiffies + (2 * HZ);
+	do {
+		if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
+			if (ha->firmware_state & (BIT_2 | BIT_0))
+				return;
+
+		if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
+			qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+
+		msleep(1000);
+	} while (!time_after_eq(jiffies, wtime));
+
+}
+
+static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
+{
+	uint16_t fw_ddb_index;
+	int status = QLA_SUCCESS;
+
+	/* free the ddb list if is not empty */
+	if (!list_empty(&ha->ddb_list))
+		qla4xxx_free_ddb_list(ha);
+
+	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
+		ha->fw_ddb_index_map[fw_ddb_index] =
+			(struct ddb_entry *)INVALID_ENTRY;
+
+	ha->tot_ddbs = 0;
+
+	qla4xxx_flush_AENS(ha);
+
+	/*
+	 * First perform device discovery for active
+	 * fw ddb indexes and build
+	 * ddb list.
+	 */
+	if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR)
+		return status;
+
+	/* Wait for an AEN */
+	qla4xxx_devices_ready(ha);
+
+	/*
+	 * Targets can come online after the inital discovery, so processing
+	 * the aens here will catch them.
+	 */
+	if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
+		qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
+
+	return status;
+}
+
+/**
+ * qla4xxx_update_ddb_list - update the driver ddb list
+ * @ha: pointer to host adapter structure.
+ *
+ * This routine obtains device information from the F/W database after
+ * firmware or adapter resets.  The device table is preserved.
+ **/
+int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha)
+{
+	int status = QLA_SUCCESS;
+	struct ddb_entry *ddb_entry, *detemp;
+
+	/* Update the device information for all devices. */
+	list_for_each_entry_safe(ddb_entry, detemp, &ha->ddb_list, list) {
+		qla4xxx_update_ddb_entry(ha, ddb_entry,
+					 ddb_entry->fw_ddb_index);
+		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+			atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+			DEBUG2(printk ("scsi%ld: %s: ddb index [%d] marked "
+				       "ONLINE\n", ha->host_no, __func__,
+				       ddb_entry->fw_ddb_index));
+		} else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
+			qla4xxx_mark_device_missing(ha, ddb_entry);
+	}
+	return status;
+}
+
+/**
+ * qla4xxx_relogin_device - re-establish session
+ * @ha: Pointer to host adapter structure.
+ * @ddb_entry: Pointer to device database entry
+ *
+ * This routine does a session relogin with the specified device.
+ * The ddb entry must be assigned prior to making this call.
+ **/
+int qla4xxx_relogin_device(struct scsi_qla_host *ha,
+			   struct ddb_entry * ddb_entry)
+{
+	uint16_t relogin_timer;
+
+	relogin_timer = max(ddb_entry->default_relogin_timeout,
+			    (uint16_t)RELOGIN_TOV);
+	atomic_set(&ddb_entry->relogin_timer, relogin_timer);
+
+	DEBUG2(printk("scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no,
+		      ddb_entry->fw_ddb_index, relogin_timer));
+
+	qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0);
+
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4010_get_topcat_presence - check if it is QLA4040 TopCat Chip
+ * @ha: Pointer to host adapter structure.
+ *
+ **/
+static int qla4010_get_topcat_presence(struct scsi_qla_host *ha)
+{
+	unsigned long flags;
+	uint16_t topcat;
+
+	if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS)
+		return QLA_ERROR;
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	topcat = rd_nvram_word(ha, offsetof(struct eeprom_data,
+					    isp4010.topcat));
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	if ((topcat & TOPCAT_MASK) == TOPCAT_PRESENT)
+		set_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags);
+	else
+		clear_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags);
+	ql4xxx_unlock_nvram(ha);
+	return QLA_SUCCESS;
+}
+
+
+static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
+{
+	unsigned long flags;
+	union external_hw_config_reg extHwConfig;
+
+	DEBUG2(printk("scsi%ld: %s: Get EEProm parameters \n", ha->host_no,
+		      __func__));
+	if (ql4xxx_lock_flash(ha) != QLA_SUCCESS)
+		return (QLA_ERROR);
+	if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS) {
+		ql4xxx_unlock_flash(ha);
+		return (QLA_ERROR);
+	}
+
+	/* Get EEPRom Parameters from NVRAM and validate */
+	dev_info(&ha->pdev->dev, "Configuring NVRAM ...\n");
+	if (qla4xxx_is_nvram_configuration_valid(ha) == QLA_SUCCESS) {
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		extHwConfig.Asuint32_t =
+			rd_nvram_word(ha, eeprom_ext_hw_conf_offset(ha));
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	} else {
+		/*
+		 * QLogic adapters should always have a valid NVRAM.
+		 * If not valid, do not load.
+		 */
+		dev_warn(&ha->pdev->dev,
+			   "scsi%ld: %s: EEProm checksum invalid.  "
+			   "Please update your EEPROM\n", ha->host_no,
+			   __func__);
+
+		/* set defaults */
+		if (is_qla4010(ha))
+			extHwConfig.Asuint32_t = 0x1912;
+		else if (is_qla4022(ha))
+			extHwConfig.Asuint32_t = 0x0023;
+	}
+	DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n",
+		     ha->host_no, __func__, extHwConfig.Asuint32_t));
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	writel((0xFFFF << 16) | extHwConfig.Asuint32_t, isp_ext_hw_conf(ha));
+	readl(isp_ext_hw_conf(ha));
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	ql4xxx_unlock_nvram(ha);
+	ql4xxx_unlock_flash(ha);
+
+	return (QLA_SUCCESS);
+}
+
+static void qla4x00_pci_config(struct scsi_qla_host *ha)
+{
+	uint16_t w, mwi;
+
+	dev_info(&ha->pdev->dev, "Configuring PCI space...\n");
+
+	pci_set_master(ha->pdev);
+	mwi = 0;
+	if (pci_set_mwi(ha->pdev))
+		mwi = PCI_COMMAND_INVALIDATE;
+	/*
+	 * We want to respect framework's setting of PCI configuration space
+	 * command register and also want to make sure that all bits of
+	 * interest to us are properly set in command register.
+	 */
+	pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
+	w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+	w &= ~PCI_COMMAND_INTX_DISABLE;
+	pci_write_config_word(ha->pdev, PCI_COMMAND, w);
+}
+
+static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha)
+{
+	int status = QLA_ERROR;
+	uint32_t max_wait_time;
+	unsigned long flags;
+	uint32_t mbox_status;
+
+	dev_info(&ha->pdev->dev, "Starting firmware ...\n");
+
+	/*
+	 * Start firmware from flash ROM
+	 *
+	 * WORKAROUND: Stuff a non-constant value that the firmware can
+	 * use as a seed for a random number generator in MB7 prior to
+	 * setting BOOT_ENABLE.	 Fixes problem where the TCP
+	 * connections use the same TCP ports after each reboot,
+	 * causing some connections to not get re-established.
+	 */
+	DEBUG(printk("scsi%d: %s: Start firmware from flash ROM\n",
+		     ha->host_no, __func__));
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	writel(jiffies, &ha->reg->mailbox[7]);
+	if (is_qla4022(ha))
+		writel(set_rmask(NVR_WRITE_ENABLE),
+		       &ha->reg->u1.isp4022.nvram);
+
+	writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status);
+	readl(&ha->reg->ctrl_status);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	/* Wait for firmware to come UP. */
+	max_wait_time = FIRMWARE_UP_TOV * 4;
+	do {
+		uint32_t ctrl_status;
+
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		ctrl_status = readw(&ha->reg->ctrl_status);
+		mbox_status = readw(&ha->reg->mailbox[0]);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		if (ctrl_status & set_rmask(CSR_SCSI_PROCESSOR_INTR))
+			break;
+		if (mbox_status == MBOX_STS_COMMAND_COMPLETE)
+			break;
+
+		DEBUG2(printk("scsi%ld: %s: Waiting for boot firmware to "
+			      "complete... ctrl_sts=0x%x, remaining=%d\n",
+			      ha->host_no, __func__, ctrl_status,
+			      max_wait_time));
+
+		msleep(250);
+	} while ((max_wait_time--));
+
+	if (mbox_status == MBOX_STS_COMMAND_COMPLETE) {
+		DEBUG(printk("scsi%ld: %s: Firmware has started\n",
+			     ha->host_no, __func__));
+
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
+		       &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		status = QLA_SUCCESS;
+	} else {
+		printk(KERN_INFO "scsi%ld: %s: Boot firmware failed "
+		       "-  mbox status 0x%x\n", ha->host_no, __func__,
+		       mbox_status);
+		status = QLA_ERROR;
+	}
+	return status;
+}
+
+static int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
+{
+#define QL4_LOCK_DRVR_WAIT	300
+#define QL4_LOCK_DRVR_SLEEP	100
+
+	int drvr_wait = QL4_LOCK_DRVR_WAIT;
+	while (drvr_wait) {
+		if (ql4xxx_lock_drvr(a) == 0) {
+			msleep(QL4_LOCK_DRVR_SLEEP);
+			if (drvr_wait) {
+				DEBUG2(printk("scsi%ld: %s: Waiting for "
+					      "Global Init Semaphore...n",
+					      a->host_no,
+					      __func__));
+			}
+			drvr_wait -= QL4_LOCK_DRVR_SLEEP;
+		} else {
+			DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
+				      "acquired.n", a->host_no, __func__));
+			return QLA_SUCCESS;
+		}
+	}
+	return QLA_ERROR;
+}
+
+/**
+ * qla4xxx_start_firmware - starts qla4xxx firmware
+ * @ha: Pointer to host adapter structure.
+ *
+ * This routine performs the neccessary steps to start the firmware for
+ * the QLA4010 adapter.
+ **/
+static int qla4xxx_start_firmware(struct scsi_qla_host *ha)
+{
+	unsigned long flags = 0;
+	uint32_t mbox_status;
+	int status = QLA_ERROR;
+	int soft_reset = 1;
+	int config_chip = 0;
+
+	if (is_qla4010(ha)){
+		if (qla4010_get_topcat_presence(ha) != QLA_SUCCESS)
+			return QLA_ERROR;
+	}
+
+	if (is_qla4022(ha))
+		ql4xxx_set_mac_number(ha);
+
+	if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)
+		return QLA_ERROR;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	DEBUG2(printk("scsi%ld: %s: port_ctrl	= 0x%08X\n", ha->host_no,
+		      __func__, readw(isp_port_ctrl(ha))));
+	DEBUG(printk("scsi%ld: %s: port_status = 0x%08X\n", ha->host_no,
+		     __func__, readw(isp_port_status(ha))));
+
+	/* Is Hardware already initialized? */
+	if ((readw(isp_port_ctrl(ha)) & 0x8000) != 0) {
+		DEBUG(printk("scsi%ld: %s: Hardware has already been "
+			     "initialized\n", ha->host_no, __func__));
+
+		/* Receive firmware boot acknowledgement */
+		mbox_status = readw(&ha->reg->mailbox[0]);
+
+		DEBUG2(printk("scsi%ld: %s: H/W Config complete - mbox[0]= "
+			      "0x%x\n", ha->host_no, __func__, mbox_status));
+
+		/* Is firmware already booted? */
+		if (mbox_status == 0) {
+			/* F/W not running, must be config by net driver */
+			config_chip = 1;
+			soft_reset = 0;
+		} else {
+			writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
+			       &ha->reg->ctrl_status);
+			readl(&ha->reg->ctrl_status);
+			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+			if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) {
+				DEBUG2(printk("scsi%ld: %s: Get firmware "
+					      "state -- state = 0x%x\n",
+					      ha->host_no,
+					      __func__, ha->firmware_state));
+				/* F/W is running */
+				if (ha->firmware_state &
+				    FW_STATE_CONFIG_WAIT) {
+					DEBUG2(printk("scsi%ld: %s: Firmware "
+						      "in known state -- "
+						      "config and "
+						      "boot, state = 0x%x\n",
+						      ha->host_no, __func__,
+						      ha->firmware_state));
+					config_chip = 1;
+					soft_reset = 0;
+				}
+			} else {
+				DEBUG2(printk("scsi%ld: %s: Firmware in "
+					      "unknown state -- resetting,"
+					      " state = "
+					      "0x%x\n", ha->host_no, __func__,
+					      ha->firmware_state));
+			}
+			spin_lock_irqsave(&ha->hardware_lock, flags);
+		}
+	} else {
+		DEBUG(printk("scsi%ld: %s: H/W initialization hasn't been "
+			     "started - resetting\n", ha->host_no, __func__));
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	DEBUG(printk("scsi%ld: %s: Flags soft_rest=%d, config= %d\n ",
+		     ha->host_no, __func__, soft_reset, config_chip));
+	if (soft_reset) {
+		DEBUG(printk("scsi%ld: %s: Issue Soft Reset\n", ha->host_no,
+			     __func__));
+		status = qla4xxx_soft_reset(ha);
+		if (status == QLA_ERROR) {
+			DEBUG(printk("scsi%d: %s: Soft Reset failed!\n",
+				     ha->host_no, __func__));
+			ql4xxx_unlock_drvr(ha);
+			return QLA_ERROR;
+		}
+		config_chip = 1;
+
+		/* Reset clears the semaphore, so aquire again */
+		if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)
+			return QLA_ERROR;
+	}
+
+	if (config_chip) {
+		if ((status = qla4xxx_config_nvram(ha)) == QLA_SUCCESS)
+			status = qla4xxx_start_firmware_from_flash(ha);
+	}
+
+	ql4xxx_unlock_drvr(ha);
+	if (status == QLA_SUCCESS) {
+		qla4xxx_get_fw_version(ha);
+		if (test_and_clear_bit(AF_GET_CRASH_RECORD, &ha->flags))
+			qla4xxx_get_crash_record(ha);
+	} else {
+		DEBUG(printk("scsi%ld: %s: Firmware has NOT started\n",
+			     ha->host_no, __func__));
+	}
+	return status;
+}
+
+
+/**
+ * qla4xxx_initialize_adapter - initiailizes hba
+ * @ha: Pointer to host adapter structure.
+ * @renew_ddb_list: Indicates what to do with the adapter's ddb list
+ *	after adapter recovery has completed.
+ *	0=preserve ddb list, 1=destroy and rebuild ddb list
+ *
+ * This routine parforms all of the steps necessary to initialize the adapter.
+ *
+ **/
+int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
+			       uint8_t renew_ddb_list)
+{
+	int status = QLA_ERROR;
+	int8_t ip_address[IP_ADDR_LEN] = {0} ;
+
+	ha->eeprom_cmd_data = 0;
+
+	qla4x00_pci_config(ha);
+
+	qla4xxx_disable_intrs(ha);
+
+	/* Initialize the Host adapter request/response queues and firmware */
+	if (qla4xxx_start_firmware(ha) == QLA_ERROR)
+		return status;
+
+	if (qla4xxx_validate_mac_address(ha) == QLA_ERROR)
+		return status;
+
+	if (qla4xxx_init_local_data(ha) == QLA_ERROR)
+		return status;
+
+	status = qla4xxx_init_firmware(ha);
+	if (status == QLA_ERROR)
+		return status;
+
+	/*
+	 * FW is waiting to get an IP address from DHCP server: Skip building
+	 * the ddb_list and wait for DHCP lease acquired aen to come in
+	 * followed by 0x8014 aen" to trigger the tgt discovery process.
+	 */
+	if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS)
+		return status;
+
+	/* Skip device discovery if ip and subnet is zero */
+	if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
+	    memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
+		return status;
+
+	if (renew_ddb_list == PRESERVE_DDB_LIST) {
+		/*
+		 * We want to preserve lun states (i.e. suspended, etc.)
+		 * for recovery initiated by the driver.  So just update
+		 * the device states for the existing ddb_list.
+		 */
+		qla4xxx_reinitialize_ddb_list(ha);
+	} else if (renew_ddb_list == REBUILD_DDB_LIST) {
+		/*
+		 * We want to build the ddb_list from scratch during
+		 * driver initialization and recovery initiated by the
+		 * INT_HBA_RESET IOCTL.
+		 */
+		status = qla4xxx_initialize_ddb_list(ha);
+		if (status == QLA_ERROR) {
+			DEBUG2(printk("%s(%ld) Error occurred during build"
+				      "ddb list\n", __func__, ha->host_no));
+			goto exit_init_hba;
+		}
+
+	}
+	if (!ha->tot_ddbs) {
+		DEBUG2(printk("scsi%ld: Failed to initialize devices or none "
+			      "present in Firmware device database\n",
+			      ha->host_no));
+	}
+
+ exit_init_hba:
+	return status;
+
+}
+
+/**
+ * qla4xxx_add_device_dynamically - ddb addition due to an AEN
+ * @ha:  Pointer to host adapter structure.
+ * @fw_ddb_index:  Firmware's device database index
+ *
+ * This routine processes adds a device as a result of an 8014h AEN.
+ **/
+static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha,
+					   uint32_t fw_ddb_index)
+{
+	struct ddb_entry * ddb_entry;
+
+	/* First allocate a device structure */
+	ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+	if (ddb_entry == NULL) {
+		DEBUG2(printk(KERN_WARNING
+			      "scsi%ld: Unable to allocate memory to add "
+			      "fw_ddb_index %d\n", ha->host_no, fw_ddb_index));
+		return;
+	}
+
+	if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
+				    QLA_ERROR) {
+		ha->fw_ddb_index_map[fw_ddb_index] =
+					(struct ddb_entry *)INVALID_ENTRY;
+		DEBUG2(printk(KERN_WARNING
+			      "scsi%ld: failed to add new device at index "
+			      "[%d]\n Unable to retrieve fw ddb entry\n",
+			      ha->host_no, fw_ddb_index));
+		qla4xxx_free_ddb(ha, ddb_entry);
+		return;
+	}
+
+	if (qla4xxx_add_sess(ddb_entry)) {
+		DEBUG2(printk(KERN_WARNING
+			      "scsi%ld: failed to add new device at index "
+			      "[%d]\n Unable to add connection and session\n",
+			      ha->host_no, fw_ddb_index));
+		qla4xxx_free_ddb(ha, ddb_entry);
+	}
+}
+
+/**
+ * qla4xxx_process_ddb_changed - process ddb state change
+ * @ha - Pointer to host adapter structure.
+ * @fw_ddb_index - Firmware's device database index
+ * @state - Device state
+ *
+ * This routine processes a Decive Database Changed AEN Event.
+ **/
+int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
+				uint32_t fw_ddb_index, uint32_t state)
+{
+	struct ddb_entry * ddb_entry;
+	uint32_t old_fw_ddb_device_state;
+
+	/* check for out of range index */
+	if (fw_ddb_index >= MAX_DDB_ENTRIES)
+		return QLA_ERROR;
+
+	/* Get the corresponging ddb entry */
+	ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
+	/* Device does not currently exist in our database. */
+	if (ddb_entry == NULL) {
+		if (state == DDB_DS_SESSION_ACTIVE)
+			qla4xxx_add_device_dynamically(ha, fw_ddb_index);
+		return QLA_SUCCESS;
+	}
+
+	/* Device already exists in our database. */
+	old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
+	DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
+		      "index [%d]\n", ha->host_no, __func__,
+		      ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
+	if (old_fw_ddb_device_state == state &&
+	    state == DDB_DS_SESSION_ACTIVE) {
+		/* Do nothing, state not changed. */
+		return QLA_SUCCESS;
+	}
+
+	ddb_entry->fw_ddb_device_state = state;
+	/* Device is back online. */
+	if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+		atomic_set(&ddb_entry->port_down_timer,
+			   ha->port_down_retry_count);
+		atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+		atomic_set(&ddb_entry->relogin_retry_count, 0);
+		atomic_set(&ddb_entry->relogin_timer, 0);
+		clear_bit(DF_RELOGIN, &ddb_entry->flags);
+		clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
+		iscsi_if_create_session_done(ddb_entry->conn);
+		/*
+		 * Change the lun state to READY in case the lun TIMEOUT before
+		 * the device came back.
+		 */
+	} else {
+		/* Device went away, try to relogin. */
+		/* Mark device missing */
+		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
+			qla4xxx_mark_device_missing(ha, ddb_entry);
+		/*
+		 * Relogin if device state changed to a not active state.
+		 * However, do not relogin if this aen is a result of an IOCTL
+		 * logout (DF_NO_RELOGIN) or if this is a discovered device.
+		 */
+		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
+		    !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
+		    !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) &&
+		    !test_bit(DF_ISNS_DISCOVERED, &ddb_entry->flags)) {
+			/*
+			 * This triggers a relogin.  After the relogin_timer
+			 * expires, the relogin gets scheduled.	 We must wait a
+			 * minimum amount of time since receiving an 0x8014 AEN
+			 * with failed device_state or a logout response before
+			 * we can issue another relogin.
+			 */
+			/* Firmware padds this timeout: (time2wait +1).
+			 * Driver retry to login should be longer than F/W.
+			 * Otherwise F/W will fail
+			 * set_ddb() mbx cmd with 0x4005 since it still
+			 * counting down its time2wait.
+			 */
+			atomic_set(&ddb_entry->relogin_timer, 0);
+			atomic_set(&ddb_entry->retry_relogin_timer,
+				   ddb_entry->default_time2wait + 4);
+		}
+	}
+
+	return QLA_SUCCESS;
+}
+
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h
new file mode 100644
index 0000000..0d61797
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_inline.h
@@ -0,0 +1,84 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+/*
+ *
+ * qla4xxx_lookup_ddb_by_fw_index
+ *	This routine locates a device handle given the firmware device
+ *	database index.	 If device doesn't exist, returns NULL.
+ *
+ * Input:
+ *	ha - Pointer to host adapter structure.
+ *	fw_ddb_index - Firmware's device database index
+ *
+ * Returns:
+ *	Pointer to the corresponding internal device database structure
+ */
+static inline struct ddb_entry *
+qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index)
+{
+	struct ddb_entry *ddb_entry = NULL;
+
+	if ((fw_ddb_index < MAX_DDB_ENTRIES) &&
+	    (ha->fw_ddb_index_map[fw_ddb_index] !=
+		(struct ddb_entry *) INVALID_ENTRY)) {
+		ddb_entry = ha->fw_ddb_index_map[fw_ddb_index];
+	}
+
+	DEBUG3(printk("scsi%d: %s: index [%d], ddb_entry = %p\n",
+	    ha->host_no, __func__, fw_ddb_index, ddb_entry));
+
+	return ddb_entry;
+}
+
+static inline void
+__qla4xxx_enable_intrs(struct scsi_qla_host *ha)
+{
+	if (is_qla4022(ha)) {
+		writel(set_rmask(IMR_SCSI_INTR_ENABLE),
+		       &ha->reg->u1.isp4022.intr_mask);
+		readl(&ha->reg->u1.isp4022.intr_mask);
+	} else {
+		writel(set_rmask(CSR_SCSI_INTR_ENABLE), &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+	}
+	set_bit(AF_INTERRUPTS_ON, &ha->flags);
+}
+
+static inline void
+__qla4xxx_disable_intrs(struct scsi_qla_host *ha)
+{
+	if (is_qla4022(ha)) {
+		writel(clr_rmask(IMR_SCSI_INTR_ENABLE),
+		       &ha->reg->u1.isp4022.intr_mask);
+		readl(&ha->reg->u1.isp4022.intr_mask);
+	} else {
+		writel(clr_rmask(CSR_SCSI_INTR_ENABLE), &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+	}
+	clear_bit(AF_INTERRUPTS_ON, &ha->flags);
+}
+
+static inline void
+qla4xxx_enable_intrs(struct scsi_qla_host *ha)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	__qla4xxx_enable_intrs(ha);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+static inline void
+qla4xxx_disable_intrs(struct scsi_qla_host *ha)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	__qla4xxx_disable_intrs(ha);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
new file mode 100644
index 0000000..c0a254b
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -0,0 +1,368 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+
+#include <scsi/scsi_tcq.h>
+
+/**
+ * qla4xxx_get_req_pkt - returns a valid entry in request queue.
+ * @ha: Pointer to host adapter structure.
+ * @queue_entry: Pointer to pointer to queue entry structure
+ *
+ * This routine performs the following tasks:
+ *	- returns the current request_in pointer (if queue not full)
+ *	- advances the request_in pointer
+ *	- checks for queue full
+ **/
+int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
+			struct queue_entry **queue_entry)
+{
+	uint16_t request_in;
+	uint8_t status = QLA_SUCCESS;
+
+	*queue_entry = ha->request_ptr;
+
+	/* get the latest request_in and request_out index */
+	request_in = ha->request_in;
+	ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
+
+	/* Advance request queue pointer and check for queue full */
+	if (request_in == (REQUEST_QUEUE_DEPTH - 1)) {
+		request_in = 0;
+		ha->request_ptr = ha->request_ring;
+	} else {
+		request_in++;
+		ha->request_ptr++;
+	}
+
+	/* request queue is full, try again later */
+	if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) {
+		/* restore request pointer */
+		ha->request_ptr = *queue_entry;
+		status = QLA_ERROR;
+	} else {
+		ha->request_in = request_in;
+		memset(*queue_entry, 0, sizeof(**queue_entry));
+	}
+
+	return status;
+}
+
+/**
+ * qla4xxx_send_marker_iocb - issues marker iocb to HBA
+ * @ha: Pointer to host adapter structure.
+ * @ddb_entry: Pointer to device database entry
+ * @lun: SCSI LUN
+ * @marker_type: marker identifier
+ *
+ * This routine issues a marker IOCB.
+ **/
+int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+			     struct ddb_entry *ddb_entry, int lun)
+{
+	struct marker_entry *marker_entry;
+	unsigned long flags = 0;
+	uint8_t status = QLA_SUCCESS;
+
+	/* Acquire hardware specific lock */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	/* Get pointer to the queue entry for the marker */
+	if (qla4xxx_get_req_pkt(ha, (struct queue_entry **) &marker_entry) !=
+	    QLA_SUCCESS) {
+		status = QLA_ERROR;
+		goto exit_send_marker;
+	}
+
+	/* Put the marker in the request queue */
+	marker_entry->hdr.entryType = ET_MARKER;
+	marker_entry->hdr.entryCount = 1;
+	marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
+	marker_entry->modifier = cpu_to_le16(MM_LUN_RESET);
+	int_to_scsilun(lun, &marker_entry->lun);
+	wmb();
+
+	/* Tell ISP it's got a new I/O request */
+	writel(ha->request_in, &ha->reg->req_q_in);
+	readl(&ha->reg->req_q_in);
+
+exit_send_marker:
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	return status;
+}
+
+struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
+	struct scsi_qla_host *ha)
+{
+	struct continuation_t1_entry *cont_entry;
+
+	cont_entry = (struct continuation_t1_entry *)ha->request_ptr;
+
+	/* Advance request queue pointer */
+	if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) {
+		ha->request_in = 0;
+		ha->request_ptr = ha->request_ring;
+	} else {
+		ha->request_in++;
+		ha->request_ptr++;
+	}
+
+	/* Load packet defaults */
+	cont_entry->hdr.entryType = ET_CONTINUE;
+	cont_entry->hdr.entryCount = 1;
+	cont_entry->hdr.systemDefined = (uint8_t) cpu_to_le16(ha->request_in);
+
+	return cont_entry;
+}
+
+uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
+{
+	uint16_t iocbs;
+
+	iocbs = 1;
+	if (dsds > COMMAND_SEG) {
+		iocbs += (dsds - COMMAND_SEG) / CONTINUE_SEG;
+		if ((dsds - COMMAND_SEG) % CONTINUE_SEG)
+			iocbs++;
+	}
+	return iocbs;
+}
+
+void qla4xxx_build_scsi_iocbs(struct srb *srb,
+			      struct command_t3_entry *cmd_entry,
+			      uint16_t tot_dsds)
+{
+	struct scsi_qla_host *ha;
+	uint16_t avail_dsds;
+	struct data_seg_a64 *cur_dsd;
+	struct scsi_cmnd *cmd;
+
+	cmd = srb->cmd;
+	ha = srb->ha;
+
+	if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+		/* No data being transferred */
+		cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0);
+		return;
+	}
+
+	avail_dsds = COMMAND_SEG;
+	cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]);
+
+	/* Load data segments */
+	if (cmd->use_sg) {
+		struct scatterlist *cur_seg;
+		struct scatterlist *end_seg;
+
+		cur_seg = (struct scatterlist *)cmd->request_buffer;
+		end_seg = cur_seg + tot_dsds;
+		while (cur_seg < end_seg) {
+			dma_addr_t sle_dma;
+
+			/* Allocate additional continuation packets? */
+			if (avail_dsds == 0) {
+				struct continuation_t1_entry *cont_entry;
+
+				cont_entry = qla4xxx_alloc_cont_entry(ha);
+				cur_dsd =
+					(struct data_seg_a64 *)
+					&cont_entry->dataseg[0];
+				avail_dsds = CONTINUE_SEG;
+			}
+
+			sle_dma = sg_dma_address(cur_seg);
+			cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
+			cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
+			cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg));
+			avail_dsds--;
+
+			cur_dsd++;
+			cur_seg++;
+		}
+	} else {
+		cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle));
+		cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle));
+		cur_dsd->count = cpu_to_le32(cmd->request_bufflen);
+	}
+}
+
+/**
+ * qla4xxx_send_command_to_isp - issues command to HBA
+ * @ha: pointer to host adapter structure.
+ * @srb: pointer to SCSI Request Block to be sent to ISP
+ *
+ * This routine is called by qla4xxx_queuecommand to build an ISP
+ * command and pass it to the ISP for execution.
+ **/
+int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
+{
+	struct scsi_cmnd *cmd = srb->cmd;
+	struct ddb_entry *ddb_entry;
+	struct command_t3_entry *cmd_entry;
+	struct scatterlist *sg = NULL;
+
+	uint16_t tot_dsds;
+	uint16_t req_cnt;
+
+	unsigned long flags;
+	uint16_t cnt;
+	uint32_t index;
+	char tag[2];
+
+	/* Get real lun and adapter */
+	ddb_entry = srb->ddb;
+
+	/* Send marker(s) if needed. */
+	if (ha->marker_needed == 1) {
+		if (qla4xxx_send_marker_iocb(ha, ddb_entry,
+					     cmd->device->lun) != QLA_SUCCESS)
+			return QLA_ERROR;
+
+		ha->marker_needed = 0;
+	}
+	tot_dsds = 0;
+
+	/* Acquire hardware specific lock */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	index = (uint32_t)cmd->request->tag;
+
+	/* Calculate the number of request entries needed. */
+	if (cmd->use_sg) {
+		sg = (struct scatterlist *)cmd->request_buffer;
+		tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
+				      cmd->sc_data_direction);
+		if (tot_dsds == 0)
+			goto queuing_error;
+	} else if (cmd->request_bufflen) {
+		dma_addr_t	req_dma;
+
+		req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
+					 cmd->request_bufflen,
+					 cmd->sc_data_direction);
+		if (dma_mapping_error(req_dma))
+			goto queuing_error;
+
+		srb->dma_handle = req_dma;
+		tot_dsds = 1;
+	}
+	req_cnt = qla4xxx_calc_request_entries(tot_dsds);
+
+	if (ha->req_q_count < (req_cnt + 2)) {
+		cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
+		if (ha->request_in < cnt)
+			ha->req_q_count = cnt - ha->request_in;
+		else
+			ha->req_q_count = REQUEST_QUEUE_DEPTH -
+				(ha->request_in - cnt);
+	}
+
+	if (ha->req_q_count < (req_cnt + 2))
+		goto queuing_error;
+
+	/* total iocbs active */
+	if ((ha->iocb_cnt + req_cnt) >= REQUEST_QUEUE_DEPTH)
+		goto queuing_error;
+
+	/* Build command packet */
+	cmd_entry = (struct command_t3_entry *) ha->request_ptr;
+	memset(cmd_entry, 0, sizeof(struct command_t3_entry));
+	cmd_entry->hdr.entryType = ET_COMMAND;
+	cmd_entry->handle = cpu_to_le32(index);
+	cmd_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
+	cmd_entry->connection_id = cpu_to_le16(ddb_entry->connection_id);
+
+	int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
+	cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
+	cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen);
+	memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
+	cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
+	cmd_entry->hdr.entryCount = req_cnt;
+
+	/* Set data transfer direction control flags
+	 * NOTE: Look at data_direction bits iff there is data to be
+	 *	 transferred, as the data direction bit is sometimed filled
+	 *	 in when there is no data to be transferred */
+	cmd_entry->control_flags = CF_NO_DATA;
+	if (cmd->request_bufflen) {
+		if (cmd->sc_data_direction == DMA_TO_DEVICE)
+			cmd_entry->control_flags = CF_WRITE;
+		else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+			cmd_entry->control_flags = CF_READ;
+	}
+
+	/* Set tagged queueing control flags */
+	cmd_entry->control_flags |= CF_SIMPLE_TAG;
+	if (scsi_populate_tag_msg(cmd, tag))
+		switch (tag[0]) {
+		case MSG_HEAD_TAG:
+			cmd_entry->control_flags |= CF_HEAD_TAG;
+			break;
+		case MSG_ORDERED_TAG:
+			cmd_entry->control_flags |= CF_ORDERED_TAG;
+			break;
+		}
+
+
+	/* Advance request queue pointer */
+	ha->request_in++;
+	if (ha->request_in == REQUEST_QUEUE_DEPTH) {
+		ha->request_in = 0;
+		ha->request_ptr = ha->request_ring;
+	} else
+		ha->request_ptr++;
+
+
+	qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds);
+	wmb();
+
+	/*
+	 * Check to see if adapter is online before placing request on
+	 * request queue.  If a reset occurs and a request is in the queue,
+	 * the firmware will still attempt to process the request, retrieving
+	 * garbage for pointers.
+	 */
+	if (!test_bit(AF_ONLINE, &ha->flags)) {
+		DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! "
+			      "Do not issue command.\n",
+			      ha->host_no, __func__));
+		goto queuing_error;
+	}
+
+	srb->cmd->host_scribble = (unsigned char *)srb;
+
+	/* update counters */
+	srb->state = SRB_ACTIVE_STATE;
+	srb->flags |= SRB_DMA_VALID;
+
+	/* Track IOCB used */
+	ha->iocb_cnt += req_cnt;
+	srb->iocb_cnt = req_cnt;
+	ha->req_q_count -= req_cnt;
+
+	/* Debug print statements */
+	writel(ha->request_in, &ha->reg->req_q_in);
+	readl(&ha->reg->req_q_in);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return QLA_SUCCESS;
+
+queuing_error:
+
+	if (cmd->use_sg && tot_dsds) {
+		sg = (struct scatterlist *) cmd->request_buffer;
+		pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
+			     cmd->sc_data_direction);
+	} else if (tot_dsds)
+		pci_unmap_single(ha->pdev, srb->dma_handle,
+				 cmd->request_bufflen, cmd->sc_data_direction);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return QLA_ERROR;
+}
+
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
new file mode 100644
index 0000000..1e28332
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -0,0 +1,796 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+
+/**
+ * qla2x00_process_completed_request() - Process a Fast Post response.
+ * @ha: SCSI driver HA context
+ * @index: SRB index
+ **/
+static void qla4xxx_process_completed_request(struct scsi_qla_host *ha,
+					      uint32_t index)
+{
+	struct srb *srb;
+
+	srb = qla4xxx_del_from_active_array(ha, index);
+	if (srb) {
+		/* Save ISP completion status */
+		srb->cmd->result = DID_OK << 16;
+		qla4xxx_srb_compl(ha, srb);
+	} else {
+		DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
+			      "%d\n", ha->host_no, index));
+		set_bit(DPC_RESET_HA, &ha->dpc_flags);
+	}
+}
+
+/**
+ * qla4xxx_status_entry - processes status IOCBs
+ * @ha: Pointer to host adapter structure.
+ * @sts_entry: Pointer to status entry structure.
+ **/
+static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+				 struct status_entry *sts_entry)
+{
+	uint8_t scsi_status;
+	struct scsi_cmnd *cmd;
+	struct srb *srb;
+	struct ddb_entry *ddb_entry;
+	uint32_t residual;
+	uint16_t sensebytecnt;
+
+	if (sts_entry->completionStatus == SCS_COMPLETE &&
+	    sts_entry->scsiStatus == 0) {
+		qla4xxx_process_completed_request(ha,
+						  le32_to_cpu(sts_entry->
+							      handle));
+		return;
+	}
+
+	srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
+	if (!srb) {
+		/* FIXMEdg: Don't we need to reset ISP in this case??? */
+		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid "
+			      "handle 0x%x, sp=%p. This cmd may have already "
+			      "been completed.\n", ha->host_no, __func__,
+			      le32_to_cpu(sts_entry->handle), srb));
+		return;
+	}
+
+	cmd = srb->cmd;
+	if (cmd == NULL) {
+		DEBUG2(printk("scsi%ld: %s: Command already returned back to "
+			      "OS pkt->handle=%d srb=%p srb->state:%d\n",
+			      ha->host_no, __func__, sts_entry->handle,
+			      srb, srb->state));
+		dev_warn(&ha->pdev->dev, "Command is NULL:"
+			" already returned to OS (srb=%p)\n", srb);
+		return;
+	}
+
+	ddb_entry = srb->ddb;
+	if (ddb_entry == NULL) {
+		cmd->result = DID_NO_CONNECT << 16;
+		goto status_entry_exit;
+	}
+
+	residual = le32_to_cpu(sts_entry->residualByteCnt);
+
+	/* Translate ISP error to a Linux SCSI error. */
+	scsi_status = sts_entry->scsiStatus;
+	switch (sts_entry->completionStatus) {
+	case SCS_COMPLETE:
+		if (scsi_status == 0) {
+			cmd->result = DID_OK << 16;
+			break;
+		}
+
+		if (sts_entry->iscsiFlags &
+		    (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER))
+			cmd->resid = residual;
+
+		cmd->result = DID_OK << 16 | scsi_status;
+
+		if (scsi_status != SCSI_CHECK_CONDITION)
+			break;
+
+		/* Copy Sense Data into sense buffer. */
+		memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+
+		sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt);
+		if (sensebytecnt == 0)
+			break;
+
+		memcpy(cmd->sense_buffer, sts_entry->senseData,
+		       min(sensebytecnt,
+			   (uint16_t) sizeof(cmd->sense_buffer)));
+
+		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, "
+			      "ASC/ASCQ = %02x/%02x\n", ha->host_no,
+			      cmd->device->channel, cmd->device->id,
+			      cmd->device->lun, __func__,
+			      sts_entry->senseData[2] & 0x0f,
+			      sts_entry->senseData[12],
+			      sts_entry->senseData[13]));
+
+		srb->flags |= SRB_GOT_SENSE;
+		break;
+
+	case SCS_INCOMPLETE:
+		/* Always set the status to DID_ERROR, since
+		 * all conditions result in that status anyway */
+		cmd->result = DID_ERROR << 16;
+		break;
+
+	case SCS_RESET_OCCURRED:
+		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Device RESET occurred\n",
+			      ha->host_no, cmd->device->channel,
+			      cmd->device->id, cmd->device->lun, __func__));
+
+		cmd->result = DID_RESET << 16;
+		break;
+
+	case SCS_ABORTED:
+		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Abort occurred\n",
+			      ha->host_no, cmd->device->channel,
+			      cmd->device->id, cmd->device->lun, __func__));
+
+		cmd->result = DID_RESET << 16;
+		break;
+
+	case SCS_TIMEOUT:
+		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: Timeout\n",
+			      ha->host_no, cmd->device->channel,
+			      cmd->device->id, cmd->device->lun));
+
+		cmd->result = DID_BUS_BUSY << 16;
+
+		/*
+		 * Mark device missing so that we won't continue to send
+		 * I/O to this device.	We should get a ddb state change
+		 * AEN soon.
+		 */
+		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
+			qla4xxx_mark_device_missing(ha, ddb_entry);
+		break;
+
+	case SCS_DATA_UNDERRUN:
+	case SCS_DATA_OVERRUN:
+		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
+			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, "
+				      "residual = 0x%x\n", ha->host_no,
+				      cmd->device->channel, cmd->device->id,
+				      cmd->device->lun, __func__, residual));
+
+			cmd->result = DID_ERROR << 16;
+			break;
+		}
+
+		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
+			/*
+			 * Firmware detected a SCSI transport underrun
+			 * condition
+			 */
+			cmd->resid = residual;
+			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status "
+				      "detected, xferlen = 0x%x, residual = "
+				      "0x%x\n",
+				      ha->host_no, cmd->device->channel,
+				      cmd->device->id,
+				      cmd->device->lun, __func__,
+				      cmd->request_bufflen,
+				      residual));
+		}
+
+		/*
+		 * If there is scsi_status, it takes precedense over
+		 * underflow condition.
+		 */
+		if (scsi_status != 0) {
+			cmd->result = DID_OK << 16 | scsi_status;
+
+			if (scsi_status != SCSI_CHECK_CONDITION)
+				break;
+
+			/* Copy Sense Data into sense buffer. */
+			memset(cmd->sense_buffer, 0,
+			       sizeof(cmd->sense_buffer));
+
+			sensebytecnt =
+				le16_to_cpu(sts_entry->senseDataByteCnt);
+			if (sensebytecnt == 0)
+				break;
+
+			memcpy(cmd->sense_buffer, sts_entry->senseData,
+			       min(sensebytecnt,
+				   (uint16_t) sizeof(cmd->sense_buffer)));
+
+			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, "
+				      "ASC/ASCQ = %02x/%02x\n", ha->host_no,
+				      cmd->device->channel, cmd->device->id,
+				      cmd->device->lun, __func__,
+				      sts_entry->senseData[2] & 0x0f,
+				      sts_entry->senseData[12],
+				      sts_entry->senseData[13]));
+		} else {
+			/*
+			 * If RISC reports underrun and target does not
+			 * report it then we must have a lost frame, so
+			 * tell upper layer to retry it by reporting a
+			 * bus busy.
+			 */
+			if ((sts_entry->iscsiFlags &
+			     ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
+				cmd->result = DID_BUS_BUSY << 16;
+			} else if ((cmd->request_bufflen - residual) <
+				   cmd->underflow) {
+				/*
+				 * Handle mid-layer underflow???
+				 *
+				 * For kernels less than 2.4, the driver must
+				 * return an error if an underflow is detected.
+				 * For kernels equal-to and above 2.4, the
+				 * mid-layer will appearantly handle the
+				 * underflow by detecting the residual count --
+				 * unfortunately, we do not see where this is
+				 * actually being done.	 In the interim, we
+				 * will return DID_ERROR.
+				 */
+				DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
+					      "Mid-layer Data underrun, "
+					      "xferlen = 0x%x, "
+					      "residual = 0x%x\n", ha->host_no,
+					      cmd->device->channel,
+					      cmd->device->id,
+					      cmd->device->lun, __func__,
+					      cmd->request_bufflen, residual));
+
+				cmd->result = DID_ERROR << 16;
+			} else {
+				cmd->result = DID_OK << 16;
+			}
+		}
+		break;
+
+	case SCS_DEVICE_LOGGED_OUT:
+	case SCS_DEVICE_UNAVAILABLE:
+		/*
+		 * Mark device missing so that we won't continue to
+		 * send I/O to this device.  We should get a ddb
+		 * state change AEN soon.
+		 */
+		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
+			qla4xxx_mark_device_missing(ha, ddb_entry);
+
+		cmd->result = DID_BUS_BUSY << 16;
+		break;
+
+	case SCS_QUEUE_FULL:
+		/*
+		 * SCSI Mid-Layer handles device queue full
+		 */
+		cmd->result = DID_OK << 16 | sts_entry->scsiStatus;
+		DEBUG2(printk("scsi%ld:%d:%d: %s: QUEUE FULL detected "
+			      "compl=%02x, scsi=%02x, state=%02x, iFlags=%02x,"
+			      " iResp=%02x\n", ha->host_no, cmd->device->id,
+			      cmd->device->lun, __func__,
+			      sts_entry->completionStatus,
+			      sts_entry->scsiStatus, sts_entry->state_flags,
+			      sts_entry->iscsiFlags,
+			      sts_entry->iscsiResponse));
+		break;
+
+	default:
+		cmd->result = DID_ERROR << 16;
+		break;
+	}
+
+status_entry_exit:
+
+	/* complete the request */
+	srb->cc_stat = sts_entry->completionStatus;
+	qla4xxx_srb_compl(ha, srb);
+}
+
+/**
+ * qla4xxx_process_response_queue - process response queue completions
+ * @ha: Pointer to host adapter structure.
+ *
+ * This routine process response queue completions in interrupt context.
+ * Hardware_lock locked upon entry
+ **/
+static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
+{
+	uint32_t count = 0;
+	struct srb *srb = NULL;
+	struct status_entry *sts_entry;
+
+	/* Process all responses from response queue */
+	while ((ha->response_in =
+		(uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in)) !=
+	       ha->response_out) {
+		sts_entry = (struct status_entry *) ha->response_ptr;
+		count++;
+
+		/* Advance pointers for next entry */
+		if (ha->response_out == (RESPONSE_QUEUE_DEPTH - 1)) {
+			ha->response_out = 0;
+			ha->response_ptr = ha->response_ring;
+		} else {
+			ha->response_out++;
+			ha->response_ptr++;
+		}
+
+		/* process entry */
+		switch (sts_entry->hdr.entryType) {
+		case ET_STATUS:
+			/*
+			 * Common status - Single completion posted in single
+			 * IOSB.
+			 */
+			qla4xxx_status_entry(ha, sts_entry);
+			break;
+
+		case ET_PASSTHRU_STATUS:
+			break;
+
+		case ET_STATUS_CONTINUATION:
+			/* Just throw away the status continuation entries */
+			DEBUG2(printk("scsi%ld: %s: Status Continuation entry "
+				      "- ignoring\n", ha->host_no, __func__));
+			break;
+
+		case ET_COMMAND:
+			/* ISP device queue is full. Command not
+			 * accepted by ISP.  Queue command for
+			 * later */
+
+			srb = qla4xxx_del_from_active_array(ha,
+						    le32_to_cpu(sts_entry->
+								handle));
+			if (srb == NULL)
+				goto exit_prq_invalid_handle;
+
+			DEBUG2(printk("scsi%ld: %s: FW device queue full, "
+				      "srb %p\n", ha->host_no, __func__, srb));
+
+			/* ETRY normally by sending it back with
+			 * DID_BUS_BUSY */
+			srb->cmd->result = DID_BUS_BUSY << 16;
+			qla4xxx_srb_compl(ha, srb);
+			break;
+
+		case ET_CONTINUE:
+			/* Just throw away the continuation entries */
+			DEBUG2(printk("scsi%ld: %s: Continuation entry - "
+				      "ignoring\n", ha->host_no, __func__));
+			break;
+
+		default:
+			/*
+			 * Invalid entry in response queue, reset RISC
+			 * firmware.
+			 */
+			DEBUG2(printk("scsi%ld: %s: Invalid entry %x in "
+				      "response queue \n", ha->host_no,
+				      __func__,
+				      sts_entry->hdr.entryType));
+			goto exit_prq_error;
+		}
+	}
+
+	/*
+	 * Done with responses, update the ISP For QLA4010, this also clears
+	 * the interrupt.
+	 */
+	writel(ha->response_out, &ha->reg->rsp_q_out);
+	readl(&ha->reg->rsp_q_out);
+
+	return;
+
+exit_prq_invalid_handle:
+	DEBUG2(printk("scsi%ld: %s: Invalid handle(srb)=%p type=%x IOCS=%x\n",
+		      ha->host_no, __func__, srb, sts_entry->hdr.entryType,
+		      sts_entry->completionStatus));
+
+exit_prq_error:
+	writel(ha->response_out, &ha->reg->rsp_q_out);
+	readl(&ha->reg->rsp_q_out);
+
+	set_bit(DPC_RESET_HA, &ha->dpc_flags);
+}
+
+/**
+ * qla4xxx_isr_decode_mailbox - decodes mailbox status
+ * @ha: Pointer to host adapter structure.
+ * @mailbox_status: Mailbox status.
+ *
+ * This routine decodes the mailbox status during the ISR.
+ * Hardware_lock locked upon entry. runs in interrupt context.
+ **/
+static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
+				       uint32_t mbox_status)
+{
+	int i;
+
+	if ((mbox_status == MBOX_STS_BUSY) ||
+	    (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
+	    (mbox_status >> 12 == MBOX_COMPLETION_STATUS)) {
+		ha->mbox_status[0] = mbox_status;
+
+		if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
+			/*
+			 * Copy all mailbox registers to a temporary
+			 * location and set mailbox command done flag
+			 */
+			for (i = 1; i < ha->mbox_status_count; i++)
+				ha->mbox_status[i] =
+					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.
+		 * Only queue the database_changed AENs */
+		switch (mbox_status) {
+		case MBOX_ASTS_SYSTEM_ERROR:
+			/* Log Mailbox registers */
+			if (ql4xdontresethba) {
+				DEBUG2(printk("%s:Dont Reset HBA\n",
+					      __func__));
+			} else {
+				set_bit(AF_GET_CRASH_RECORD, &ha->flags);
+				set_bit(DPC_RESET_HA, &ha->dpc_flags);
+			}
+			break;
+
+		case MBOX_ASTS_REQUEST_TRANSFER_ERROR:
+		case MBOX_ASTS_RESPONSE_TRANSFER_ERROR:
+		case MBOX_ASTS_NVRAM_INVALID:
+		case MBOX_ASTS_IP_ADDRESS_CHANGED:
+		case MBOX_ASTS_DHCP_LEASE_EXPIRED:
+			DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, "
+				      "Reset HA\n", ha->host_no, mbox_status));
+			set_bit(DPC_RESET_HA, &ha->dpc_flags);
+			break;
+
+		case MBOX_ASTS_LINK_UP:
+			DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK UP\n",
+				      ha->host_no, mbox_status));
+			set_bit(AF_LINK_UP, &ha->flags);
+			break;
+
+		case MBOX_ASTS_LINK_DOWN:
+			DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK DOWN\n",
+				      ha->host_no, mbox_status));
+			clear_bit(AF_LINK_UP, &ha->flags);
+			break;
+
+		case MBOX_ASTS_HEARTBEAT:
+			ha->seconds_since_last_heartbeat = 0;
+			break;
+
+		case MBOX_ASTS_DHCP_LEASE_ACQUIRED:
+			DEBUG2(printk("scsi%ld: AEN %04x DHCP LEASE "
+				      "ACQUIRED\n", ha->host_no, mbox_status));
+			set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
+			break;
+
+		case MBOX_ASTS_PROTOCOL_STATISTIC_ALARM:
+		case MBOX_ASTS_SCSI_COMMAND_PDU_REJECTED: /* Target
+							   * mode
+							   * only */
+		case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED:  /* Connection mode */
+		case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR:
+		case MBOX_ASTS_SUBNET_STATE_CHANGE:
+			/* No action */
+			DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no,
+				      mbox_status));
+			break;
+
+		case MBOX_ASTS_MAC_ADDRESS_CHANGED:
+		case MBOX_ASTS_DNS:
+			/* No action */
+			DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, "
+				      "mbox_sts[1]=%04x, mbox_sts[2]=%04x\n",
+				      ha->host_no, mbox_status,
+				      readl(&ha->reg->mailbox[1]),
+				      readl(&ha->reg->mailbox[2])));
+			break;
+
+		case MBOX_ASTS_SELF_TEST_FAILED:
+		case MBOX_ASTS_LOGIN_FAILED:
+			/* No action */
+			DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, "
+				      "mbox_sts[2]=%04x, mbox_sts[3]=%04x\n",
+				      ha->host_no, mbox_status,
+				      readl(&ha->reg->mailbox[1]),
+				      readl(&ha->reg->mailbox[2]),
+				      readl(&ha->reg->mailbox[3])));
+			break;
+
+		case MBOX_ASTS_DATABASE_CHANGED:
+			/* Queue AEN information and process it in the DPC
+			 * routine */
+			if (ha->aen_q_count > 0) {
+				/* advance pointer */
+				if (ha->aen_in == (MAX_AEN_ENTRIES - 1))
+					ha->aen_in = 0;
+				else
+					ha->aen_in++;
+
+				/* decrement available counter */
+				ha->aen_q_count--;
+
+				for (i = 1; i < MBOX_AEN_REG_COUNT; i++)
+					ha->aen_q[ha->aen_in].mbox_sts[i] =
+						readl(&ha->reg->mailbox[i]);
+
+				ha->aen_q[ha->aen_in].mbox_sts[0] = mbox_status;
+
+				/* print debug message */
+				DEBUG2(printk("scsi%ld: AEN[%d] %04x queued"
+					      " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n",
+					      ha->host_no, ha->aen_in,
+					      mbox_status,
+					      ha->aen_q[ha->aen_in].mbox_sts[1],
+					      ha->aen_q[ha->aen_in].mbox_sts[2],
+					      ha->aen_q[ha->aen_in].mbox_sts[3],
+					      ha->aen_q[ha->aen_in].  mbox_sts[4]));
+
+				/* The DPC routine will process the aen */
+				set_bit(DPC_AEN, &ha->dpc_flags);
+			} else {
+				DEBUG2(printk("scsi%ld: %s: aen %04x, queue "
+					      "overflowed!  AEN LOST!!\n",
+					      ha->host_no, __func__,
+					      mbox_status));
+
+				DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n",
+					      ha->host_no));
+
+				for (i = 0; i < MAX_AEN_ENTRIES; i++) {
+					DEBUG2(printk("AEN[%d] %04x %04x %04x "
+						      "%04x\n", i,
+						      ha->aen_q[i].mbox_sts[0],
+						      ha->aen_q[i].mbox_sts[1],
+						      ha->aen_q[i].mbox_sts[2],
+						      ha->aen_q[i].mbox_sts[3]));
+				}
+			}
+			break;
+
+		default:
+			DEBUG2(printk(KERN_WARNING
+				      "scsi%ld: AEN %04x UNKNOWN\n",
+				      ha->host_no, mbox_status));
+			break;
+		}
+	} else {
+		DEBUG2(printk("scsi%ld: Unknown mailbox status %08X\n",
+			      ha->host_no, mbox_status));
+
+		ha->mbox_status[0] = mbox_status;
+	}
+}
+
+/**
+ * qla4xxx_interrupt_service_routine - isr
+ * @ha: pointer to host adapter structure.
+ *
+ * This is the main interrupt service routine.
+ * hardware_lock locked upon entry. runs in interrupt context.
+ **/
+void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
+				       uint32_t intr_status)
+{
+	/* Process response queue interrupt. */
+	if (intr_status & CSR_SCSI_COMPLETION_INTR)
+		qla4xxx_process_response_queue(ha);
+
+	/* Process mailbox/asynch event	 interrupt.*/
+	if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
+		qla4xxx_isr_decode_mailbox(ha,
+					   readl(&ha->reg->mailbox[0]));
+
+		/* Clear Mailbox Interrupt */
+		writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
+		       &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+	}
+}
+
+/**
+ * qla4xxx_intr_handler - hardware interrupt handler.
+ * @irq: Unused
+ * @dev_id: Pointer to host adapter structure
+ **/
+irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
+{
+	struct scsi_qla_host *ha;
+	uint32_t intr_status;
+	unsigned long flags = 0;
+	uint8_t reqs_count = 0;
+
+	ha = (struct scsi_qla_host *) dev_id;
+	if (!ha) {
+		DEBUG2(printk(KERN_INFO
+			      "qla4xxx: Interrupt with NULL host ptr\n"));
+		return IRQ_NONE;
+	}
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	/*
+	 * Repeatedly service interrupts up to a maximum of
+	 * MAX_REQS_SERVICED_PER_INTR
+	 */
+	while (1) {
+		/*
+		 * Read interrupt status
+		 */
+		if (le32_to_cpu(ha->shadow_regs->rsp_q_in) !=
+		    ha->response_out)
+			intr_status = CSR_SCSI_COMPLETION_INTR;
+		else
+			intr_status = readl(&ha->reg->ctrl_status);
+
+		if ((intr_status &
+		     (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) ==
+		    0) {
+			if (reqs_count == 0)
+				ha->spurious_int_count++;
+			break;
+		}
+
+		if (intr_status & CSR_FATAL_ERROR) {
+			DEBUG2(printk(KERN_INFO "scsi%ld: Fatal Error, "
+				      "Status 0x%04x\n", ha->host_no,
+				      readl(isp_port_error_status (ha))));
+
+			/* Issue Soft Reset to clear this error condition.
+			 * This will prevent the RISC from repeatedly
+			 * interrupting the driver; thus, allowing the DPC to
+			 * get scheduled to continue error recovery.
+			 * NOTE: Disabling RISC interrupts does not work in
+			 * this case, as CSR_FATAL_ERROR overrides
+			 * CSR_SCSI_INTR_ENABLE */
+			if ((readl(&ha->reg->ctrl_status) &
+			     CSR_SCSI_RESET_INTR) == 0) {
+				writel(set_rmask(CSR_SOFT_RESET),
+				       &ha->reg->ctrl_status);
+				readl(&ha->reg->ctrl_status);
+			}
+
+			writel(set_rmask(CSR_FATAL_ERROR),
+			       &ha->reg->ctrl_status);
+			readl(&ha->reg->ctrl_status);
+
+			__qla4xxx_disable_intrs(ha);
+
+			set_bit(DPC_RESET_HA, &ha->dpc_flags);
+
+			break;
+		} else if (intr_status & CSR_SCSI_RESET_INTR) {
+			clear_bit(AF_ONLINE, &ha->flags);
+			__qla4xxx_disable_intrs(ha);
+
+			writel(set_rmask(CSR_SCSI_RESET_INTR),
+			       &ha->reg->ctrl_status);
+			readl(&ha->reg->ctrl_status);
+
+			set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+
+			break;
+		} else if (intr_status & INTR_PENDING) {
+			qla4xxx_interrupt_service_routine(ha, intr_status);
+			ha->total_io_count++;
+			if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
+				break;
+
+			intr_status = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * qla4xxx_process_aen - processes AENs generated by firmware
+ * @ha: pointer to host adapter structure.
+ * @process_aen: type of AENs to process
+ *
+ * Processes specific types of Asynchronous Events generated by firmware.
+ * The type of AENs to process is specified by process_aen and can be
+ *	PROCESS_ALL_AENS	 0
+ *	FLUSH_DDB_CHANGED_AENS	 1
+ *	RELOGIN_DDB_CHANGED_AENS 2
+ **/
+void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
+{
+	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
+	struct aen *aen;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	while (ha->aen_out != ha->aen_in) {
+		/* Advance pointers for next entry */
+		if (ha->aen_out == (MAX_AEN_ENTRIES - 1))
+			ha->aen_out = 0;
+		else
+			ha->aen_out++;
+
+		ha->aen_q_count++;
+		aen = &ha->aen_q[ha->aen_out];
+
+		/* copy aen information to local structure */
+		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
+			mbox_sts[i] = aen->mbox_sts[i];
+
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x "
+			     "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out,
+			     mbox_sts[0], mbox_sts[2], mbox_sts[3],
+			     mbox_sts[1], mbox_sts[4]));
+
+		switch (mbox_sts[0]) {
+		case MBOX_ASTS_DATABASE_CHANGED:
+			if (process_aen == FLUSH_DDB_CHANGED_AENS) {
+				DEBUG2(printk("scsi%ld: AEN[%d] %04x, index "
+					      "[%d] state=%04x FLUSHED!\n",
+					      ha->host_no, ha->aen_out,
+					      mbox_sts[0], mbox_sts[2],
+					      mbox_sts[3]));
+				break;
+			} else if (process_aen == RELOGIN_DDB_CHANGED_AENS) {
+				/* for use during init time, we only want to
+				 * relogin non-active ddbs */
+				struct ddb_entry *ddb_entry;
+
+				ddb_entry =
+					/* FIXME: name length? */
+					qla4xxx_lookup_ddb_by_fw_index(ha,
+								       mbox_sts[2]);
+				if (!ddb_entry)
+					break;
+
+				ddb_entry->dev_scan_wait_to_complete_relogin =
+					0;
+				ddb_entry->dev_scan_wait_to_start_relogin =
+					jiffies +
+					((ddb_entry->default_time2wait +
+					  4) * HZ);
+
+				DEBUG2(printk("scsi%ld: ddb index [%d] initate"
+					      " RELOGIN after %d seconds\n",
+					      ha->host_no,
+					      ddb_entry->fw_ddb_index,
+					      ddb_entry->default_time2wait +
+					      4));
+				break;
+			}
+
+			if (mbox_sts[1] == 0) {	/* Global DB change. */
+				qla4xxx_reinitialize_ddb_list(ha);
+			} else if (mbox_sts[1] == 1) {	/* Specific device. */
+				qla4xxx_process_ddb_changed(ha, mbox_sts[2],
+							    mbox_sts[3]);
+			}
+			break;
+		}
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+}
+
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
new file mode 100644
index 0000000..ef82399
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -0,0 +1,930 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+
+
+/**
+ * qla4xxx_mailbox_command - issues mailbox commands
+ * @ha: Pointer to host adapter structure.
+ * @inCount: number of mailbox registers to load.
+ * @outCount: number of mailbox registers to return.
+ * @mbx_cmd: data pointer for mailbox in registers.
+ * @mbx_sts: data pointer for mailbox out registers.
+ *
+ * This routine sssue mailbox commands and waits for completion.
+ * If outCount is 0, this routine completes successfully WITHOUT waiting
+ * for the mailbox command to complete.
+ **/
+int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
+			    uint8_t outCount, uint32_t *mbx_cmd,
+			    uint32_t *mbx_sts)
+{
+	int status = QLA_ERROR;
+	uint8_t i;
+	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;
+	}
+
+	/* To prevent overwriting mailbox registers for a command that has
+	 * not yet been serviced, check to see if a previously issued
+	 * mailbox command is interrupting.
+	 * -----------------------------------------------------------------
+	 */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	intr_status = readl(&ha->reg->ctrl_status);
+	if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
+		/* Service existing interrupt */
+		qla4xxx_interrupt_service_routine(ha, intr_status);
+		clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
+	}
+
+	/* Send the mailbox command to the firmware */
+	ha->mbox_status_count = outCount;
+	for (i = 0; i < outCount; i++)
+		ha->mbox_status[i] = 0;
+
+	/* Load all mailbox registers, except mailbox 0. */
+	for (i = 1; i < inCount; i++)
+		writel(mbx_cmd[i], &ha->reg->mailbox[i]);
+
+	/* Wakeup firmware  */
+	writel(mbx_cmd[0], &ha->reg->mailbox[0]);
+	readl(&ha->reg->mailbox[0]);
+	writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
+	readl(&ha->reg->ctrl_status);
+	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
+	 * complete.  For example, MBOX_CMD_RESET_FW doesn't return status,
+	 * you must poll the inbound Interrupt Mask for completion.
+	 */
+	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 */
+	wait_count = jiffies + MBOX_TOV * HZ;
+	while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
+		if (time_after_eq(jiffies, wait_count))
+			break;
+
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		intr_status = readl(&ha->reg->ctrl_status);
+		if (intr_status & INTR_PENDING) {
+			/*
+			 * Service the interrupt.
+			 * The ISR will save the mailbox status registers
+			 * to a temporary storage location in the adapter
+			 * structure.
+			 */
+			ha->mbox_status_count = outCount;
+			qla4xxx_interrupt_service_routine(ha, intr_status);
+		}
+		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)) {
+		DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
+			      " Scheduling Adapter Reset\n", ha->host_no,
+			      mbx_cmd[0]));
+		ha->mailbox_timeout_count++;
+		mbx_sts[0] = (-1);
+		set_bit(DPC_RESET_HA, &ha->dpc_flags);
+		goto mbox_exit;
+	}
+
+	/*
+	 * Copy the mailbox out registers to the caller's mailbox in/out
+	 * structure.
+	 */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (i = 0; i < outCount; i++)
+		mbx_sts[i] = ha->mbox_status[i];
+
+	/* Set return status and error flags (if applicable). */
+	switch (ha->mbox_status[0]) {
+	case MBOX_STS_COMMAND_COMPLETE:
+		status = QLA_SUCCESS;
+		break;
+
+	case MBOX_STS_INTERMEDIATE_COMPLETION:
+		status = QLA_SUCCESS;
+		break;
+
+	case MBOX_STS_BUSY:
+		DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
+			       ha->host_no, __func__, mbx_cmd[0]));
+		ha->mailbox_timeout_count++;
+		break;
+
+	default:
+		DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
+			      "sts = %08X ****\n", ha->host_no, __func__,
+			      mbx_cmd[0], mbx_sts[0]));
+		break;
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+mbox_exit:
+	clear_bit(AF_MBOX_COMMAND, &ha->flags);
+	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
+	mutex_unlock(&ha->mbox_sem);
+
+	return status;
+}
+
+
+/**
+ * qla4xxx_issue_iocb - issue mailbox iocb command
+ * @ha: adapter state pointer.
+ * @buffer: buffer pointer.
+ * @phys_addr: physical address of buffer.
+ * @size: size of buffer.
+ *
+ * Issues iocbs via mailbox commands.
+ * TARGET_QUEUE_LOCK must be released.
+ * ADAPTER_STATE_LOCK must be released.
+ **/
+int
+qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer,
+		   dma_addr_t phys_addr, size_t size)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
+	mbox_cmd[1] = 0;
+	mbox_cmd[2] = LSDW(phys_addr);
+	mbox_cmd[3] = MSDW(phys_addr);
+	status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
+	return status;
+}
+
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
+				   uint16_t fw_ddb_index,
+				   uint16_t connection_id,
+				   uint16_t option)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+	mbox_cmd[1] = fw_ddb_index;
+	mbox_cmd[2] = connection_id;
+	mbox_cmd[3] = LOGOUT_OPTION_RELOGIN;
+	if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
+			      "option %04x failed sts %04X %04X",
+			      ha->host_no, __func__,
+			      option, mbox_sts[0], mbox_sts[1]));
+		if (mbox_sts[0] == 0x4005)
+			DEBUG2(printk("%s reason %04X\n", __func__,
+				      mbox_sts[1]));
+	}
+	return QLA_SUCCESS;
+}
+
+int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
+				 uint16_t fw_ddb_index)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
+	mbox_cmd[1] = fw_ddb_index;
+	if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS)
+		return QLA_ERROR;
+
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_initialize_fw_cb - initializes firmware control block.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
+{
+	struct init_fw_ctrl_blk *init_fw_cb;
+	dma_addr_t init_fw_cb_dma;
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status = QLA_ERROR;
+
+	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+					sizeof(struct init_fw_ctrl_blk),
+					&init_fw_cb_dma, GFP_KERNEL);
+	if (init_fw_cb == NULL) {
+		DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
+			      ha->host_no, __func__));
+		return 10;
+	}
+	memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
+
+	/* Get Initialize Firmware Control Block. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
+	mbox_cmd[2] = LSDW(init_fw_cb_dma);
+	mbox_cmd[3] = MSDW(init_fw_cb_dma);
+	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		dma_free_coherent(&ha->pdev->dev,
+				  sizeof(struct init_fw_ctrl_blk),
+				  init_fw_cb, init_fw_cb_dma);
+		return status;
+	}
+
+	/* Initialize request and response queues. */
+	qla4xxx_init_rings(ha);
+
+	/* Fill in the request and response queue information. */
+	init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
+	init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
+	init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
+	init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
+	init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
+	init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
+	init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
+	init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
+	init_fw_cb->ShadowRegBufAddrLo =
+		cpu_to_le32(LSDW(ha->shadow_regs_dma));
+	init_fw_cb->ShadowRegBufAddrHi =
+		cpu_to_le32(MSDW(ha->shadow_regs_dma));
+
+	/* Set up required options. */
+	init_fw_cb->FwOptions |=
+		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
+				       FWOPT_INITIATOR_MODE);
+	init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
+
+	/* Save some info in adapter structure. */
+	ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
+	ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
+	ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
+	memcpy(ha->ip_address, init_fw_cb->IPAddr,
+	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
+	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
+	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
+	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
+	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
+	memcpy(ha->name_string, init_fw_cb->iSCSINameString,
+	       min(sizeof(ha->name_string),
+		   sizeof(init_fw_cb->iSCSINameString)));
+	memcpy(ha->alias, init_fw_cb->Alias,
+	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
+
+	/* Save Command Line Paramater info */
+	ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
+	ha->discovery_wait = ql4xdiscoverywait;
+
+	/* Send Initialize Firmware Control Block. */
+	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
+	mbox_cmd[1] = 0;
+	mbox_cmd[2] = LSDW(init_fw_cb_dma);
+	mbox_cmd[3] = MSDW(init_fw_cb_dma);
+	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
+	    QLA_SUCCESS)
+		status = QLA_SUCCESS;
+	 else {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_INITIALIZE_FIRMWARE "
+			      "failed w/ status %04X\n", ha->host_no, __func__,
+			      mbox_sts[0]));
+	}
+	dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
+			  init_fw_cb, init_fw_cb_dma);
+
+	return status;
+}
+
+/**
+ * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
+{
+	struct init_fw_ctrl_blk *init_fw_cb;
+	dma_addr_t init_fw_cb_dma;
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+					sizeof(struct init_fw_ctrl_blk),
+					&init_fw_cb_dma, GFP_KERNEL);
+	if (init_fw_cb == NULL) {
+		printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
+		       __func__);
+		return 10;
+	}
+
+	/* Get Initialize Firmware Control Block. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
+	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
+	mbox_cmd[2] = LSDW(init_fw_cb_dma);
+	mbox_cmd[3] = MSDW(init_fw_cb_dma);
+
+	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
+			      ha->host_no, __func__));
+		dma_free_coherent(&ha->pdev->dev,
+				  sizeof(struct init_fw_ctrl_blk),
+				  init_fw_cb, init_fw_cb_dma);
+		return QLA_ERROR;
+	}
+
+	/* Save IP Address. */
+	memcpy(ha->ip_address, init_fw_cb->IPAddr,
+	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
+	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
+	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
+	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
+	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
+
+	dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
+			  init_fw_cb, init_fw_cb_dma);
+
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_get_firmware_state - gets firmware state of HBA
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	/* Get firmware version */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
+	if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
+			      "status %04X\n", ha->host_no, __func__,
+			      mbox_sts[0]));
+		return QLA_ERROR;
+	}
+	ha->firmware_state = mbox_sts[1];
+	ha->board_id = mbox_sts[2];
+	ha->addl_fw_state = mbox_sts[3];
+	DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
+		      ha->host_no, __func__, ha->firmware_state);)
+
+		return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_get_firmware_status - retrieves firmware status
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	/* Get firmware version */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
+	if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
+			      "status %04X\n", ha->host_no, __func__,
+			      mbox_sts[0]));
+		return QLA_ERROR;
+	}
+
+	/* High-water mark of IOCBs */
+	ha->iocb_hiwat = mbox_sts[2];
+	if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
+		ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
+	else
+		dev_info(&ha->pdev->dev, "WARNING!!!  You have less than %d "
+			   "firmare IOCBs available (%d).\n",
+			   IOCB_HIWAT_CUSHION, ha->iocb_hiwat);
+
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
+ * @ha: Pointer to host adapter structure.
+ * @fw_ddb_index: Firmware's device database index
+ * @fw_ddb_entry: Pointer to firmware's device database entry structure
+ * @num_valid_ddb_entries: Pointer to number of valid ddb entries
+ * @next_ddb_index: Pointer to next valid device database index
+ * @fw_ddb_device_state: Pointer to device state
+ **/
+int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
+			    uint16_t fw_ddb_index,
+			    struct dev_db_entry *fw_ddb_entry,
+			    dma_addr_t fw_ddb_entry_dma,
+			    uint32_t *num_valid_ddb_entries,
+			    uint32_t *next_ddb_index,
+			    uint32_t *fw_ddb_device_state,
+			    uint32_t *conn_err_detail,
+			    uint16_t *tcp_source_port_num,
+			    uint16_t *connection_id)
+{
+	int status = QLA_ERROR;
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	/* Make sure the device index is valid */
+	if (fw_ddb_index >= MAX_DDB_ENTRIES) {
+		DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n",
+			      ha->host_no, __func__, fw_ddb_index));
+		goto exit_get_fwddb;
+	}
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
+	mbox_cmd[1] = (uint32_t) fw_ddb_index;
+	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
+	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
+	if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
+	    QLA_ERROR) {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
+			      " with status 0x%04X\n", ha->host_no, __func__,
+			      mbox_sts[0]));
+		goto exit_get_fwddb;
+	}
+	if (fw_ddb_index != mbox_sts[1]) {
+		DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n",
+			      ha->host_no, __func__, fw_ddb_index,
+			      mbox_sts[1]));
+		goto exit_get_fwddb;
+	}
+	if (fw_ddb_entry) {
+		dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
+			   "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
+			   fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
+			   mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
+			   fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
+			   fw_ddb_entry->ipAddr[3],
+			   le16_to_cpu(fw_ddb_entry->portNumber),
+			   fw_ddb_entry->iscsiName);
+	}
+	if (num_valid_ddb_entries)
+		*num_valid_ddb_entries = mbox_sts[2];
+	if (next_ddb_index)
+		*next_ddb_index = mbox_sts[3];
+	if (fw_ddb_device_state)
+		*fw_ddb_device_state = mbox_sts[4];
+
+	/*
+	 * RA: This mailbox has been changed to pass connection error and
+	 * details.  Its true for ISP4010 as per Version E - Not sure when it
+	 * was changed.	 Get the time2wait from the fw_dd_entry field :
+	 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
+	 * struct.
+	 */
+	if (conn_err_detail)
+		*conn_err_detail = mbox_sts[5];
+	if (tcp_source_port_num)
+		*tcp_source_port_num = (uint16_t) mbox_sts[6] >> 16;
+	if (connection_id)
+		*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
+	status = QLA_SUCCESS;
+
+exit_get_fwddb:
+	return status;
+}
+
+/**
+ * qla4xxx_set_fwddb_entry - sets a ddb entry.
+ * @ha: Pointer to host adapter structure.
+ * @fw_ddb_index: Firmware's device database index
+ * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL.
+ *
+ * This routine initializes or updates the adapter's device database
+ * entry for the specified device. It also triggers a login for the
+ * specified device. Therefore, it may also be used as a secondary
+ * login routine when a NULL pointer is specified for the fw_ddb_entry.
+ **/
+int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
+			  dma_addr_t fw_ddb_entry_dma)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	/* Do not wait for completion. The firmware will send us an
+	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
+	 */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
+	mbox_cmd[1] = (uint32_t) fw_ddb_index;
+	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
+	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
+	return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
+}
+
+int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
+				    uint16_t fw_ddb_index)
+{
+	int status = QLA_ERROR;
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	/* Do not wait for completion. The firmware will send us an
+	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
+	 */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN;
+	mbox_cmd[1] = (uint32_t) fw_ddb_index;
+	mbox_cmd[2] = 0;
+	mbox_cmd[3] = 0;
+	mbox_cmd[4] = 0;
+	status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]);
+	DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n",
+		      __func__, fw_ddb_index, status, mbox_sts[0],
+		      mbox_sts[1]);)
+
+		return status;
+}
+
+/**
+ * qla4xxx_get_crash_record - retrieves crash record.
+ * @ha: Pointer to host adapter structure.
+ *
+ * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
+ **/
+void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	struct crash_record *crash_record = NULL;
+	dma_addr_t crash_record_dma = 0;
+	uint32_t crash_record_size = 0;
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_cmd));
+
+	/* Get size of crash record. */
+	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
+	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
+			      ha->host_no, __func__));
+		goto exit_get_crash_record;
+	}
+	crash_record_size = mbox_sts[4];
+	if (crash_record_size == 0) {
+		DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
+			      ha->host_no, __func__));
+		goto exit_get_crash_record;
+	}
+
+	/* Alloc Memory for Crash Record. */
+	crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
+					  &crash_record_dma, GFP_KERNEL);
+	if (crash_record == NULL)
+		goto exit_get_crash_record;
+
+	/* Get Crash Record. */
+	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
+	mbox_cmd[2] = LSDW(crash_record_dma);
+	mbox_cmd[3] = MSDW(crash_record_dma);
+	mbox_cmd[4] = crash_record_size;
+	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS)
+		goto exit_get_crash_record;
+
+	/* Dump Crash Record. */
+
+exit_get_crash_record:
+	if (crash_record)
+		dma_free_coherent(&ha->pdev->dev, crash_record_size,
+				  crash_record, crash_record_dma);
+}
+
+/**
+ * qla4xxx_get_conn_event_log - retrieves connection event log
+ * @ha: Pointer to host adapter structure.
+ **/
+void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	struct conn_event_log_entry *event_log = NULL;
+	dma_addr_t event_log_dma = 0;
+	uint32_t event_log_size = 0;
+	uint32_t num_valid_entries;
+	uint32_t      oldest_entry = 0;
+	uint32_t	max_event_log_entries;
+	uint8_t		i;
+
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_cmd));
+
+	/* Get size of crash record. */
+	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
+	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS)
+		goto exit_get_event_log;
+
+	event_log_size = mbox_sts[4];
+	if (event_log_size == 0)
+		goto exit_get_event_log;
+
+	/* Alloc Memory for Crash Record. */
+	event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size,
+				       &event_log_dma, GFP_KERNEL);
+	if (event_log == NULL)
+		goto exit_get_event_log;
+
+	/* Get Crash Record. */
+	mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
+	mbox_cmd[2] = LSDW(event_log_dma);
+	mbox_cmd[3] = MSDW(event_log_dma);
+	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
+			      "log!\n", ha->host_no, __func__));
+		goto exit_get_event_log;
+	}
+
+	/* Dump Event Log. */
+	num_valid_entries = mbox_sts[1];
+
+	max_event_log_entries = event_log_size /
+		sizeof(struct conn_event_log_entry);
+
+	if (num_valid_entries > max_event_log_entries)
+		oldest_entry = num_valid_entries % max_event_log_entries;
+
+	DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n",
+		      ha->host_no, num_valid_entries));
+
+	if (qla4_extended_error_logging == 3) {
+		if (oldest_entry == 0) {
+			/* Circular Buffer has not wrapped around */
+			for (i=0; i < num_valid_entries; i++) {
+				qla4xxx_dump_buffer((uint8_t *)event_log+
+						    (i*sizeof(*event_log)),
+						    sizeof(*event_log));
+			}
+		}
+		else {
+			/* Circular Buffer has wrapped around -
+			 * display accordingly*/
+			for (i=oldest_entry; i < max_event_log_entries; i++) {
+				qla4xxx_dump_buffer((uint8_t *)event_log+
+						    (i*sizeof(*event_log)),
+						    sizeof(*event_log));
+			}
+			for (i=0; i < oldest_entry; i++) {
+				qla4xxx_dump_buffer((uint8_t *)event_log+
+						    (i*sizeof(*event_log)),
+						    sizeof(*event_log));
+			}
+		}
+	}
+
+exit_get_event_log:
+	if (event_log)
+		dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
+				  event_log_dma);
+}
+
+/**
+ * qla4xxx_reset_lun - issues LUN Reset
+ * @ha: Pointer to host adapter structure.
+ * @db_entry: Pointer to device database entry
+ * @un_entry: Pointer to lun entry structure
+ *
+ * This routine performs a LUN RESET on the specified target/lun.
+ * The caller must ensure that the ddb_entry and lun_entry pointers
+ * are valid before calling this routine.
+ **/
+int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+		      int lun)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status = QLA_SUCCESS;
+
+	DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
+		      ddb_entry->os_target_id, lun));
+
+	/*
+	 * Send lun reset command to ISP, so that the ISP will return all
+	 * outstanding requests with RESET status
+	 */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
+	mbox_cmd[1] = ddb_entry->fw_ddb_index;
+	mbox_cmd[2] = lun << 8;
+	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
+	qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
+	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
+	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
+		status = QLA_ERROR;
+
+	return status;
+}
+
+
+int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+		      uint32_t offset, uint32_t len)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
+	mbox_cmd[1] = LSDW(dma_addr);
+	mbox_cmd[2] = MSDW(dma_addr);
+	mbox_cmd[3] = offset;
+	mbox_cmd[4] = len;
+	if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
+		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
+		    __func__, mbox_sts[0], mbox_sts[1], offset, len));
+		return QLA_ERROR;
+	}
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_get_fw_version - gets firmware version
+ * @ha: Pointer to host adapter structure.
+ *
+ * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may
+ * hold an address for data.  Make sure that we write 0 to those mailboxes,
+ * if unused.
+ **/
+int qla4xxx_get_fw_version(struct scsi_qla_host * ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	/* Get firmware version. */
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
+	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
+		    "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
+		return QLA_ERROR;
+	}
+
+	/* Save firmware version information. */
+	ha->firmware_version[0] = mbox_sts[1];
+	ha->firmware_version[1] = mbox_sts[2];
+	ha->patch_number = mbox_sts[3];
+	ha->build_number = mbox_sts[4];
+
+	return QLA_SUCCESS;
+}
+
+int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
+	mbox_cmd[2] = LSDW(dma_addr);
+	mbox_cmd[3] = MSDW(dma_addr);
+
+	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
+		     ha->host_no, __func__, mbox_sts[0]));
+		return QLA_ERROR;
+	}
+	return QLA_SUCCESS;
+}
+
+int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
+	mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
+
+	if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+	    QLA_SUCCESS) {
+		if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
+			*ddb_index = mbox_sts[2];
+		} else {
+			DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
+			     ha->host_no, __func__, mbox_sts[0]));
+			return QLA_ERROR;
+		}
+	} else {
+		*ddb_index = MAX_PRST_DEV_DB_ENTRIES;
+	}
+
+	return QLA_SUCCESS;
+}
+
+
+int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
+{
+	struct dev_db_entry *fw_ddb_entry;
+	dma_addr_t fw_ddb_entry_dma;
+	uint32_t ddb_index;
+	int ret_val = QLA_SUCCESS;
+
+
+	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
+					  sizeof(*fw_ddb_entry),
+					  &fw_ddb_entry_dma, GFP_KERNEL);
+	if (!fw_ddb_entry) {
+		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
+			      ha->host_no, __func__));
+		ret_val = QLA_ERROR;
+		goto qla4xxx_send_tgts_exit;
+	}
+
+	ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma);
+	if (ret_val != QLA_SUCCESS)
+		goto qla4xxx_send_tgts_exit;
+
+	ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index);
+	if (ret_val != QLA_SUCCESS)
+		goto qla4xxx_send_tgts_exit;
+
+	memset((void *)fw_ddb_entry->iSCSIAlias, 0,
+	       sizeof(fw_ddb_entry->iSCSIAlias));
+
+	memset((void *)fw_ddb_entry->iscsiName, 0,
+	       sizeof(fw_ddb_entry->iscsiName));
+
+	memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
+	memset((void *)fw_ddb_entry->targetAddr, 0,
+	       sizeof(fw_ddb_entry->targetAddr));
+
+	fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
+	fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
+
+	fw_ddb_entry->ipAddr[0] = *ip;
+	fw_ddb_entry->ipAddr[1] = *(ip + 1);
+	fw_ddb_entry->ipAddr[2] = *(ip + 2);
+	fw_ddb_entry->ipAddr[3] = *(ip + 3);
+
+	ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
+
+qla4xxx_send_tgts_exit:
+	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+			  fw_ddb_entry, fw_ddb_entry_dma);
+	return ret_val;
+}
+
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
new file mode 100644
index 0000000..e3957ca
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -0,0 +1,224 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+
+static inline int eeprom_size(struct scsi_qla_host *ha)
+{
+	return is_qla4022(ha) ? FM93C86A_SIZE_16 : FM93C66A_SIZE_16;
+}
+
+static inline int eeprom_no_addr_bits(struct scsi_qla_host *ha)
+{
+	return is_qla4022(ha) ? FM93C86A_NO_ADDR_BITS_16 :
+		FM93C56A_NO_ADDR_BITS_16;
+}
+
+static inline int eeprom_no_data_bits(struct scsi_qla_host *ha)
+{
+	return FM93C56A_DATA_BITS_16;
+}
+
+static int fm93c56a_select(struct scsi_qla_host * ha)
+{
+	DEBUG5(printk(KERN_ERR "fm93c56a_select:\n"));
+
+	ha->eeprom_cmd_data = AUBURN_EEPROM_CS_1 | 0x000f0000;
+	writel(ha->eeprom_cmd_data, isp_nvram(ha));
+	readl(isp_nvram(ha));
+	return 1;
+}
+
+static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr)
+{
+	int i;
+	int mask;
+	int dataBit;
+	int previousBit;
+
+	/* Clock in a zero, then do the start bit. */
+	writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, isp_nvram(ha));
+	writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
+	       AUBURN_EEPROM_CLK_RISE, isp_nvram(ha));
+	writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
+	       AUBURN_EEPROM_CLK_FALL, isp_nvram(ha));
+	readl(isp_nvram(ha));
+	mask = 1 << (FM93C56A_CMD_BITS - 1);
+
+	/* Force the previous data bit to be different. */
+	previousBit = 0xffff;
+	for (i = 0; i < FM93C56A_CMD_BITS; i++) {
+		dataBit =
+			(cmd & mask) ? AUBURN_EEPROM_DO_1 : AUBURN_EEPROM_DO_0;
+		if (previousBit != dataBit) {
+
+			/*
+			 * If the bit changed, then change the DO state to
+			 * match.
+			 */
+			writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha));
+			previousBit = dataBit;
+		}
+		writel(ha->eeprom_cmd_data | dataBit |
+		       AUBURN_EEPROM_CLK_RISE, isp_nvram(ha));
+		writel(ha->eeprom_cmd_data | dataBit |
+		       AUBURN_EEPROM_CLK_FALL, isp_nvram(ha));
+		readl(isp_nvram(ha));
+		cmd = cmd << 1;
+	}
+	mask = 1 << (eeprom_no_addr_bits(ha) - 1);
+
+	/* Force the previous data bit to be different. */
+	previousBit = 0xffff;
+	for (i = 0; i < eeprom_no_addr_bits(ha); i++) {
+		dataBit = addr & mask ? AUBURN_EEPROM_DO_1 :
+			AUBURN_EEPROM_DO_0;
+		if (previousBit != dataBit) {
+			/*
+			 * If the bit changed, then change the DO state to
+			 * match.
+			 */
+			writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha));
+			previousBit = dataBit;
+		}
+		writel(ha->eeprom_cmd_data | dataBit |
+		       AUBURN_EEPROM_CLK_RISE, isp_nvram(ha));
+		writel(ha->eeprom_cmd_data | dataBit |
+		       AUBURN_EEPROM_CLK_FALL, isp_nvram(ha));
+		readl(isp_nvram(ha));
+		addr = addr << 1;
+	}
+	return 1;
+}
+
+static int fm93c56a_deselect(struct scsi_qla_host * ha)
+{
+	ha->eeprom_cmd_data = AUBURN_EEPROM_CS_0 | 0x000f0000;
+	writel(ha->eeprom_cmd_data, isp_nvram(ha));
+	readl(isp_nvram(ha));
+	return 1;
+}
+
+static int fm93c56a_datain(struct scsi_qla_host * ha, unsigned short *value)
+{
+	int i;
+	int data = 0;
+	int dataBit;
+
+	/* Read the data bits
+	 * The first bit is a dummy.  Clock right over it. */
+	for (i = 0; i < eeprom_no_data_bits(ha); i++) {
+		writel(ha->eeprom_cmd_data |
+		       AUBURN_EEPROM_CLK_RISE, isp_nvram(ha));
+		writel(ha->eeprom_cmd_data |
+		       AUBURN_EEPROM_CLK_FALL, isp_nvram(ha));
+		dataBit =
+			(readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0;
+		data = (data << 1) | dataBit;
+	}
+
+	*value = data;
+	return 1;
+}
+
+static int eeprom_readword(int eepromAddr, u16 * value,
+			   struct scsi_qla_host * ha)
+{
+	fm93c56a_select(ha);
+	fm93c56a_cmd(ha, FM93C56A_READ, eepromAddr);
+	fm93c56a_datain(ha, value);
+	fm93c56a_deselect(ha);
+	return 1;
+}
+
+/* Hardware_lock must be set before calling */
+u16 rd_nvram_word(struct scsi_qla_host * ha, int offset)
+{
+	u16 val;
+
+	/* NOTE: NVRAM uses half-word addresses */
+	eeprom_readword(offset, &val, ha);
+	return val;
+}
+
+int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha)
+{
+	int status = QLA_ERROR;
+	uint16_t checksum = 0;
+	uint32_t index;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (index = 0; index < eeprom_size(ha); index++)
+		checksum += rd_nvram_word(ha, index);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	if (checksum == 0)
+		status = QLA_SUCCESS;
+
+	return status;
+}
+
+/*************************************************************************
+ *
+ *			Hardware Semaphore routines
+ *
+ *************************************************************************/
+int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits)
+{
+	uint32_t value;
+	unsigned long flags;
+	unsigned int seconds = 30;
+
+	DEBUG2(printk("scsi%ld : Trying to get SEM lock - mask= 0x%x, code = "
+		      "0x%x\n", ha->host_no, sem_mask, sem_bits));
+	do {
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		writel((sem_mask | sem_bits), isp_semaphore(ha));
+		value = readw(isp_semaphore(ha));
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+		if ((value & (sem_mask >> 16)) == sem_bits) {
+			DEBUG2(printk("scsi%ld : Got SEM LOCK - mask= 0x%x, "
+				      "code = 0x%x\n", ha->host_no,
+				      sem_mask, sem_bits));
+			return QLA_SUCCESS;
+		}
+		ssleep(1);
+	} while (--seconds);
+	return QLA_ERROR;
+}
+
+void ql4xxx_sem_unlock(struct scsi_qla_host * ha, u32 sem_mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	writel(sem_mask, isp_semaphore(ha));
+	readl(isp_semaphore(ha));
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	DEBUG2(printk("scsi%ld : UNLOCK SEM - mask= 0x%x\n", ha->host_no,
+		      sem_mask));
+}
+
+int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits)
+{
+	uint32_t value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	writel((sem_mask | sem_bits), isp_semaphore(ha));
+	value = readw(isp_semaphore(ha));
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	if ((value & (sem_mask >> 16)) == sem_bits) {
+		DEBUG2(printk("scsi%ld : Got SEM LOCK - mask= 0x%x, code = "
+			      "0x%x, sema code=0x%x\n", ha->host_no,
+			      sem_mask, sem_bits, value));
+		return 1;
+	}
+	return 0;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h
new file mode 100644
index 0000000..08e2aed
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_nvram.h
@@ -0,0 +1,256 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#ifndef _QL4XNVRM_H_
+#define _QL4XNVRM_H_
+
+/*
+ * AM29LV Flash definitions
+ */
+#define FM93C56A_SIZE_8	 0x100
+#define FM93C56A_SIZE_16 0x80
+#define FM93C66A_SIZE_8	 0x200
+#define FM93C66A_SIZE_16 0x100/* 4010 */
+#define FM93C86A_SIZE_16 0x400/* 4022 */
+
+#define	 FM93C56A_START	      0x1
+
+// Commands
+#define	 FM93C56A_READ	      0x2
+#define	 FM93C56A_WEN	      0x0
+#define	 FM93C56A_WRITE	      0x1
+#define	 FM93C56A_WRITE_ALL   0x0
+#define	 FM93C56A_WDS	      0x0
+#define	 FM93C56A_ERASE	      0x3
+#define	 FM93C56A_ERASE_ALL   0x0
+
+/* Command Extentions */
+#define	 FM93C56A_WEN_EXT	 0x3
+#define	 FM93C56A_WRITE_ALL_EXT	 0x1
+#define	 FM93C56A_WDS_EXT	 0x0
+#define	 FM93C56A_ERASE_ALL_EXT	 0x2
+
+/* Address Bits */
+#define	 FM93C56A_NO_ADDR_BITS_16   8	/* 4010 */
+#define	 FM93C56A_NO_ADDR_BITS_8    9	/* 4010 */
+#define	 FM93C86A_NO_ADDR_BITS_16   10	/* 4022 */
+
+/* Data Bits */
+#define	 FM93C56A_DATA_BITS_16	 16
+#define	 FM93C56A_DATA_BITS_8	 8
+
+/* Special Bits */
+#define	 FM93C56A_READ_DUMMY_BITS   1
+#define	 FM93C56A_READY		    0
+#define	 FM93C56A_BUSY		    1
+#define	 FM93C56A_CMD_BITS	    2
+
+/* Auburn Bits */
+#define	 AUBURN_EEPROM_DI	    0x8
+#define	 AUBURN_EEPROM_DI_0	    0x0
+#define	 AUBURN_EEPROM_DI_1	    0x8
+#define	 AUBURN_EEPROM_DO	    0x4
+#define	 AUBURN_EEPROM_DO_0	    0x0
+#define	 AUBURN_EEPROM_DO_1	    0x4
+#define	 AUBURN_EEPROM_CS	    0x2
+#define	 AUBURN_EEPROM_CS_0	    0x0
+#define	 AUBURN_EEPROM_CS_1	    0x2
+#define	 AUBURN_EEPROM_CLK_RISE	    0x1
+#define	 AUBURN_EEPROM_CLK_FALL	    0x0
+
+/* */
+/* EEPROM format */
+/* */
+struct bios_params {
+	uint16_t SpinUpDelay:1;
+	uint16_t BIOSDisable:1;
+	uint16_t MMAPEnable:1;
+	uint16_t BootEnable:1;
+	uint16_t Reserved0:12;
+	uint8_t bootID0:7;
+	uint8_t bootID0Valid:1;
+	uint8_t bootLUN0[8];
+	uint8_t bootID1:7;
+	uint8_t bootID1Valid:1;
+	uint8_t bootLUN1[8];
+	uint16_t MaxLunsPerTarget;
+	uint8_t Reserved1[10];
+};
+
+struct eeprom_port_cfg {
+
+	/* MTU MAC 0 */
+	u16 etherMtu_mac;
+
+	/* Flow Control MAC 0 */
+	u16 pauseThreshold_mac;
+	u16 resumeThreshold_mac;
+	u16 reserved[13];
+};
+
+struct eeprom_function_cfg {
+	u8 reserved[30];
+
+	/* MAC ADDR */
+	u8 macAddress[6];
+	u8 macAddressSecondary[6];
+	u16 subsysVendorId;
+	u16 subsysDeviceId;
+};
+
+struct eeprom_data {
+	union {
+		struct {	/* isp4010 */
+			u8 asic_id[4]; /* x00 */
+			u8 version;	/* x04 */
+			u8 reserved;	/* x05 */
+			u16 board_id;	/* x06 */
+#define	  EEPROM_BOARDID_ELDORADO    1
+#define	  EEPROM_BOARDID_PLACER	     2
+
+#define EEPROM_SERIAL_NUM_SIZE	     16
+			u8 serial_number[EEPROM_SERIAL_NUM_SIZE]; /* x08 */
+
+			/* ExtHwConfig: */
+			/* Offset = 24bytes
+			 *
+			 * | SSRAM Size|     |ST|PD|SDRAM SZ| W| B| SP	|  |
+			 * |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+			 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+			 */
+			u16 ext_hw_conf; /* x18 */
+			u8 mac0[6];	/* x1A */
+			u8 mac1[6];	/* x20 */
+			u8 mac2[6];	/* x26 */
+			u8 mac3[6];	/* x2C */
+			u16 etherMtu;	/* x32 */
+			u16 macConfig;	/* x34 */
+#define	 MAC_CONFIG_ENABLE_ANEG	    0x0001
+#define	 MAC_CONFIG_ENABLE_PAUSE    0x0002
+			u16 phyConfig;	/* x36 */
+#define	 PHY_CONFIG_PHY_ADDR_MASK	      0x1f
+#define	 PHY_CONFIG_ENABLE_FW_MANAGEMENT_MASK 0x20
+			u16 topcat;	/* x38 */
+#define TOPCAT_PRESENT		0x0100
+#define TOPCAT_MASK		0xFF00
+
+#define EEPROM_UNUSED_1_SIZE   2
+			u8 unused_1[EEPROM_UNUSED_1_SIZE]; /* x3A */
+			u16 bufletSize;	/* x3C */
+			u16 bufletCount;	/* x3E */
+			u16 bufletPauseThreshold; /* x40 */
+			u16 tcpWindowThreshold50; /* x42 */
+			u16 tcpWindowThreshold25; /* x44 */
+			u16 tcpWindowThreshold0; /* x46 */
+			u16 ipHashTableBaseHi;	/* x48 */
+			u16 ipHashTableBaseLo;	/* x4A */
+			u16 ipHashTableSize;	/* x4C */
+			u16 tcpHashTableBaseHi;	/* x4E */
+			u16 tcpHashTableBaseLo;	/* x50 */
+			u16 tcpHashTableSize;	/* x52 */
+			u16 ncbTableBaseHi;	/* x54 */
+			u16 ncbTableBaseLo;	/* x56 */
+			u16 ncbTableSize;	/* x58 */
+			u16 drbTableBaseHi;	/* x5A */
+			u16 drbTableBaseLo;	/* x5C */
+			u16 drbTableSize;	/* x5E */
+
+#define EEPROM_UNUSED_2_SIZE   4
+			u8 unused_2[EEPROM_UNUSED_2_SIZE]; /* x60 */
+			u16 ipReassemblyTimeout; /* x64 */
+			u16 tcpMaxWindowSizeHi;	/* x66 */
+			u16 tcpMaxWindowSizeLo;	/* x68 */
+			u32 net_ip_addr0;	/* x6A Added for TOE
+						 * functionality. */
+			u32 net_ip_addr1;	/* x6E */
+			u32 scsi_ip_addr0;	/* x72 */
+			u32 scsi_ip_addr1;	/* x76 */
+#define EEPROM_UNUSED_3_SIZE   128	/* changed from 144 to account
+					 * for ip addresses */
+			u8 unused_3[EEPROM_UNUSED_3_SIZE]; /* x7A */
+			u16 subsysVendorId_f0;	/* xFA */
+			u16 subsysDeviceId_f0;	/* xFC */
+
+			/* Address = 0x7F */
+#define FM93C56A_SIGNATURE  0x9356
+#define FM93C66A_SIGNATURE  0x9366
+			u16 signature;	/* xFE */
+
+#define EEPROM_UNUSED_4_SIZE   250
+			u8 unused_4[EEPROM_UNUSED_4_SIZE]; /* x100 */
+			u16 subsysVendorId_f1;	/* x1FA */
+			u16 subsysDeviceId_f1;	/* x1FC */
+			u16 checksum;	/* x1FE */
+		} __attribute__ ((packed)) isp4010;
+		struct {	/* isp4022 */
+			u8 asicId[4];	/* x00 */
+			u8 version;	/* x04 */
+			u8 reserved_5;	/* x05 */
+			u16 boardId;	/* x06 */
+			u8 boardIdStr[16];	/* x08 */
+			u8 serialNumber[16];	/* x18 */
+
+			/* External Hardware Configuration */
+			u16 ext_hw_conf;	/* x28 */
+
+			/* MAC 0 CONFIGURATION */
+			struct eeprom_port_cfg macCfg_port0; /* x2A */
+
+			/* MAC 1 CONFIGURATION */
+			struct eeprom_port_cfg macCfg_port1; /* x4A */
+
+			/* DDR SDRAM Configuration */
+			u16 bufletSize;	/* x6A */
+			u16 bufletCount;	/* x6C */
+			u16 tcpWindowThreshold50; /* x6E */
+			u16 tcpWindowThreshold25; /* x70 */
+			u16 tcpWindowThreshold0; /* x72 */
+			u16 ipHashTableBaseHi;	/* x74 */
+			u16 ipHashTableBaseLo;	/* x76 */
+			u16 ipHashTableSize;	/* x78 */
+			u16 tcpHashTableBaseHi;	/* x7A */
+			u16 tcpHashTableBaseLo;	/* x7C */
+			u16 tcpHashTableSize;	/* x7E */
+			u16 ncbTableBaseHi;	/* x80 */
+			u16 ncbTableBaseLo;	/* x82 */
+			u16 ncbTableSize;	/* x84 */
+			u16 drbTableBaseHi;	/* x86 */
+			u16 drbTableBaseLo;	/* x88 */
+			u16 drbTableSize;	/* x8A */
+			u16 reserved_142[4];	/* x8C */
+
+			/* TCP/IP Parameters */
+			u16 ipReassemblyTimeout; /* x94 */
+			u16 tcpMaxWindowSize;	/* x96 */
+			u16 ipSecurity;	/* x98 */
+			u8 reserved_156[294]; /* x9A */
+			u16 qDebug[8];	/* QLOGIC USE ONLY   x1C0 */
+			struct eeprom_function_cfg funcCfg_fn0;	/* x1D0 */
+			u16 reserved_510; /* x1FE */
+
+			/* Address = 512 */
+			u8 oemSpace[432]; /* x200 */
+			struct bios_params sBIOSParams_fn1; /* x3B0 */
+			struct eeprom_function_cfg funcCfg_fn1;	/* x3D0 */
+			u16 reserved_1022; /* x3FE */
+
+			/* Address = 1024 */
+			u8 reserved_1024[464];	/* x400 */
+			struct eeprom_function_cfg funcCfg_fn2;	/* x5D0 */
+			u16 reserved_1534; /* x5FE */
+
+			/* Address = 1536 */
+			u8 reserved_1536[432];	/* x600 */
+			struct bios_params sBIOSParams_fn3; /* x7B0 */
+			struct eeprom_function_cfg funcCfg_fn3;	/* x7D0 */
+			u16 checksum;	/* x7FE */
+		} __attribute__ ((packed)) isp4022;
+	};
+};
+
+
+#endif	/* _QL4XNVRM_H_ */
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
new file mode 100644
index 0000000..178fcdd
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -0,0 +1,1755 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+#include <linux/moduleparam.h>
+
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsicam.h>
+
+#include "ql4_def.h"
+
+/*
+ * Driver version
+ */
+char qla4xxx_version_str[40];
+
+/*
+ * SRB allocation cache
+ */
+static kmem_cache_t *srb_cachep;
+
+/*
+ * Module parameter information and variables
+ */
+int ql4xdiscoverywait = 60;
+module_param(ql4xdiscoverywait, int, S_IRUGO | S_IRUSR);
+MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time");
+int ql4xdontresethba = 0;
+module_param(ql4xdontresethba, int, S_IRUGO | S_IRUSR);
+MODULE_PARM_DESC(ql4xdontresethba,
+		 "Dont reset the HBA when the driver gets 0x8002 AEN "
+		 " default it will reset hba :0"
+		 " set to 1 to avoid resetting HBA");
+
+int qla4_extended_error_logging = 0; /* 0 = off, 1 = log errors */
+module_param(qla4_extended_error_logging, int, S_IRUGO | S_IRUSR);
+MODULE_PARM_DESC(qla4_extended_error_logging,
+		 "Option to enable extended error logging, "
+		 "Default is 0 - no logging, 1 - debug logging");
+
+/*
+ * SCSI host template entry points
+ */
+
+void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
+
+/*
+ * iSCSI template entry points
+ */
+static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
+			     uint32_t enable, struct sockaddr *dst_addr);
+static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+				  enum iscsi_param param, char *buf);
+static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+				  enum iscsi_param param, char *buf);
+static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
+static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
+static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+
+/*
+ * SCSI host template entry points
+ */
+static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+				void (*done) (struct scsi_cmnd *));
+static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
+static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
+static int qla4xxx_slave_alloc(struct scsi_device *device);
+static int qla4xxx_slave_configure(struct scsi_device *device);
+static void qla4xxx_slave_destroy(struct scsi_device *sdev);
+
+static struct scsi_host_template qla4xxx_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= DRIVER_NAME,
+	.proc_name		= DRIVER_NAME,
+	.queuecommand		= qla4xxx_queuecommand,
+
+	.eh_device_reset_handler = qla4xxx_eh_device_reset,
+	.eh_host_reset_handler	= qla4xxx_eh_host_reset,
+
+	.slave_configure	= qla4xxx_slave_configure,
+	.slave_alloc		= qla4xxx_slave_alloc,
+	.slave_destroy		= qla4xxx_slave_destroy,
+
+	.this_id		= -1,
+	.cmd_per_lun		= 3,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.sg_tablesize		= SG_ALL,
+
+	.max_sectors		= 0xFFFF,
+};
+
+static struct iscsi_transport qla4xxx_iscsi_transport = {
+	.owner			= THIS_MODULE,
+	.name			= DRIVER_NAME,
+	.param_mask		= ISCSI_CONN_PORT |
+				  ISCSI_CONN_ADDRESS |
+				  ISCSI_TARGET_NAME |
+				  ISCSI_TPGT,
+	.sessiondata_size	= sizeof(struct ddb_entry),
+	.host_template		= &qla4xxx_driver_template,
+
+	.tgt_dscvr		= qla4xxx_tgt_dscvr,
+	.get_conn_param		= qla4xxx_conn_get_param,
+	.get_session_param	= qla4xxx_sess_get_param,
+	.start_conn		= qla4xxx_conn_start,
+	.stop_conn		= qla4xxx_conn_stop,
+	.session_recovery_timedout = qla4xxx_recovery_timedout,
+};
+
+static struct scsi_transport_template *qla4xxx_scsi_transport;
+
+static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
+{
+	struct ddb_entry *ddb_entry = session->dd_data;
+	struct scsi_qla_host *ha = ddb_entry->ha;
+
+	DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count of (%d) "
+		      "secs exhausted, marking device DEAD.\n", ha->host_no,
+		      __func__, ddb_entry->fw_ddb_index,
+		      ha->port_down_retry_count));
+
+	atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+
+	DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc flags = "
+		      "0x%lx\n", ha->host_no, __func__, ha->dpc_flags));
+	queue_work(ha->dpc_thread, &ha->dpc_work);
+}
+
+static int qla4xxx_conn_start(struct iscsi_cls_conn *conn)
+{
+	struct iscsi_cls_session *session;
+	struct ddb_entry *ddb_entry;
+
+	session = iscsi_dev_to_session(conn->dev.parent);
+	ddb_entry = session->dd_data;
+
+	DEBUG2(printk("scsi%ld: %s: index [%d] starting conn\n",
+		      ddb_entry->ha->host_no, __func__,
+		      ddb_entry->fw_ddb_index));
+	iscsi_unblock_session(session);
+	return 0;
+}
+
+static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag)
+{
+	struct iscsi_cls_session *session;
+	struct ddb_entry *ddb_entry;
+
+	session = iscsi_dev_to_session(conn->dev.parent);
+	ddb_entry = session->dd_data;
+
+	DEBUG2(printk("scsi%ld: %s: index [%d] stopping conn\n",
+		      ddb_entry->ha->host_no, __func__,
+		      ddb_entry->fw_ddb_index));
+	if (flag == STOP_CONN_RECOVER)
+		iscsi_block_session(session);
+	else
+		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+}
+
+static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+				  enum iscsi_param param, char *buf)
+{
+	struct ddb_entry *ddb_entry = sess->dd_data;
+	int len;
+
+	switch (param) {
+	case ISCSI_PARAM_TARGET_NAME:
+		len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
+			       ddb_entry->iscsi_name);
+		break;
+	case ISCSI_PARAM_TPGT:
+		len = sprintf(buf, "%u\n", ddb_entry->tpgt);
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return len;
+}
+
+static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+				  enum iscsi_param param, char *buf)
+{
+	struct iscsi_cls_session *session;
+	struct ddb_entry *ddb_entry;
+	int len;
+
+	session = iscsi_dev_to_session(conn->dev.parent);
+	ddb_entry = session->dd_data;
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_PORT:
+		len = sprintf(buf, "%hu\n", ddb_entry->port);
+		break;
+	case ISCSI_PARAM_CONN_ADDRESS:
+		/* TODO: what are the ipv6 bits */
+		len = sprintf(buf, "%u.%u.%u.%u\n",
+			      NIPQUAD(ddb_entry->ip_addr));
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return len;
+}
+
+static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
+			     uint32_t enable, struct sockaddr *dst_addr)
+{
+	struct scsi_qla_host *ha;
+	struct Scsi_Host *shost;
+	struct sockaddr_in *addr;
+	struct sockaddr_in6 *addr6;
+	int ret = 0;
+
+	shost = scsi_host_lookup(host_no);
+	if (IS_ERR(shost)) {
+		printk(KERN_ERR "Could not find host no %u\n", host_no);
+		return -ENODEV;
+	}
+
+	ha = (struct scsi_qla_host *) shost->hostdata;
+
+	switch (type) {
+	case ISCSI_TGT_DSCVR_SEND_TARGETS:
+		if (dst_addr->sa_family == AF_INET) {
+			addr = (struct sockaddr_in *)dst_addr;
+			if (qla4xxx_send_tgts(ha, (char *)&addr->sin_addr,
+					      addr->sin_port) != QLA_SUCCESS)
+				ret = -EIO;
+		} else if (dst_addr->sa_family == AF_INET6) {
+			/*
+			 * TODO: fix qla4xxx_send_tgts
+			 */
+			addr6 = (struct sockaddr_in6 *)dst_addr;
+			if (qla4xxx_send_tgts(ha, (char *)&addr6->sin6_addr,
+					      addr6->sin6_port) != QLA_SUCCESS)
+				ret = -EIO;
+		} else
+			ret = -ENOSYS;
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	scsi_host_put(shost);
+	return ret;
+}
+
+void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
+{
+	if (!ddb_entry->sess)
+		return;
+
+	if (ddb_entry->conn) {
+		iscsi_if_destroy_session_done(ddb_entry->conn);
+		iscsi_destroy_conn(ddb_entry->conn);
+		iscsi_remove_session(ddb_entry->sess);
+	}
+	iscsi_free_session(ddb_entry->sess);
+}
+
+int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+{
+	int err;
+
+	err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
+	if (err) {
+		DEBUG2(printk(KERN_ERR "Could not add session.\n"));
+		return err;
+	}
+
+	ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0);
+	if (!ddb_entry->conn) {
+		iscsi_remove_session(ddb_entry->sess);
+		DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
+		return -ENOMEM;
+	}
+
+	ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count;
+	iscsi_if_create_session_done(ddb_entry->conn);
+	return 0;
+}
+
+struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
+{
+	struct ddb_entry *ddb_entry;
+	struct iscsi_cls_session *sess;
+
+	sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport);
+	if (!sess)
+		return NULL;
+
+	ddb_entry = sess->dd_data;
+	memset(ddb_entry, 0, sizeof(*ddb_entry));
+	ddb_entry->ha = ha;
+	ddb_entry->sess = sess;
+	return ddb_entry;
+}
+
+/*
+ * Timer routines
+ */
+
+static void qla4xxx_start_timer(struct scsi_qla_host *ha, void *func,
+				unsigned long interval)
+{
+	DEBUG(printk("scsi: %s: Starting timer thread for adapter %d\n",
+		     __func__, ha->host->host_no));
+	init_timer(&ha->timer);
+	ha->timer.expires = jiffies + interval * HZ;
+	ha->timer.data = (unsigned long)ha;
+	ha->timer.function = (void (*)(unsigned long))func;
+	add_timer(&ha->timer);
+	ha->timer_active = 1;
+}
+
+static void qla4xxx_stop_timer(struct scsi_qla_host *ha)
+{
+	del_timer_sync(&ha->timer);
+	ha->timer_active = 0;
+}
+
+/***
+ * qla4xxx_mark_device_missing - mark a device as missing.
+ * @ha: Pointer to host adapter structure.
+ * @ddb_entry: Pointer to device database entry
+ *
+ * This routine marks a device missing and resets the relogin retry count.
+ **/
+void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
+				 struct ddb_entry *ddb_entry)
+{
+	atomic_set(&ddb_entry->state, DDB_STATE_MISSING);
+	DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n",
+		      ha->host_no, ddb_entry->bus, ddb_entry->target,
+		      ddb_entry->fw_ddb_index));
+	iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
+}
+
+static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
+				       struct ddb_entry *ddb_entry,
+				       struct scsi_cmnd *cmd,
+				       void (*done)(struct scsi_cmnd *))
+{
+	struct srb *srb;
+
+	srb = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
+	if (!srb)
+		return srb;
+
+	atomic_set(&srb->ref_count, 1);
+	srb->ha = ha;
+	srb->ddb = ddb_entry;
+	srb->cmd = cmd;
+	srb->flags = 0;
+	cmd->SCp.ptr = (void *)srb;
+	cmd->scsi_done = done;
+
+	return srb;
+}
+
+static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)
+{
+	struct scsi_cmnd *cmd = srb->cmd;
+
+	if (srb->flags & SRB_DMA_VALID) {
+		if (cmd->use_sg) {
+			pci_unmap_sg(ha->pdev, cmd->request_buffer,
+				     cmd->use_sg, cmd->sc_data_direction);
+		} else if (cmd->request_bufflen) {
+			pci_unmap_single(ha->pdev, srb->dma_handle,
+					 cmd->request_bufflen,
+					 cmd->sc_data_direction);
+		}
+		srb->flags &= ~SRB_DMA_VALID;
+	}
+	cmd->SCp.ptr = NULL;
+}
+
+void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb)
+{
+	struct scsi_cmnd *cmd = srb->cmd;
+
+	qla4xxx_srb_free_dma(ha, srb);
+
+	mempool_free(srb, ha->srb_mempool);
+
+	cmd->scsi_done(cmd);
+}
+
+/**
+ * qla4xxx_queuecommand - scsi layer issues scsi command to driver.
+ * @cmd: Pointer to Linux's SCSI command structure
+ * @done_fn: Function that the driver calls to notify the SCSI mid-layer
+ *	that the command has been processed.
+ *
+ * Remarks:
+ * This routine is invoked by Linux to send a SCSI command to the driver.
+ * The mid-level driver tries to ensure that queuecommand never gets
+ * invoked concurrently with itself or the interrupt handler (although
+ * the interrupt handler may call this routine as part of request-
+ * completion handling).   Unfortunely, it sometimes calls the scheduler
+ * in interrupt context which is a big NO! NO!.
+ **/
+static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+				void (*done)(struct scsi_cmnd *))
+{
+	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
+	struct ddb_entry *ddb_entry = cmd->device->hostdata;
+	struct srb *srb;
+	int rval;
+
+	if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
+		if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
+			cmd->result = DID_NO_CONNECT << 16;
+			goto qc_fail_command;
+		}
+		goto qc_host_busy;
+	}
+
+	spin_unlock_irq(ha->host->host_lock);
+
+	srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
+	if (!srb)
+		goto qc_host_busy_lock;
+
+	rval = qla4xxx_send_command_to_isp(ha, srb);
+	if (rval != QLA_SUCCESS)
+		goto qc_host_busy_free_sp;
+
+	spin_lock_irq(ha->host->host_lock);
+	return 0;
+
+qc_host_busy_free_sp:
+	qla4xxx_srb_free_dma(ha, srb);
+	mempool_free(srb, ha->srb_mempool);
+
+qc_host_busy_lock:
+	spin_lock_irq(ha->host->host_lock);
+
+qc_host_busy:
+	return SCSI_MLQUEUE_HOST_BUSY;
+
+qc_fail_command:
+	done(cmd);
+
+	return 0;
+}
+
+/**
+ * qla4xxx_mem_free - frees memory allocated to adapter
+ * @ha: Pointer to host adapter structure.
+ *
+ * Frees memory previously allocated by qla4xxx_mem_alloc
+ **/
+static void qla4xxx_mem_free(struct scsi_qla_host *ha)
+{
+	if (ha->queues)
+		dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
+				  ha->queues_dma);
+
+	ha->queues_len = 0;
+	ha->queues = NULL;
+	ha->queues_dma = 0;
+	ha->request_ring = NULL;
+	ha->request_dma = 0;
+	ha->response_ring = NULL;
+	ha->response_dma = 0;
+	ha->shadow_regs = NULL;
+	ha->shadow_regs_dma = 0;
+
+	/* Free srb pool. */
+	if (ha->srb_mempool)
+		mempool_destroy(ha->srb_mempool);
+
+	ha->srb_mempool = NULL;
+
+	/* release io space registers  */
+	if (ha->reg)
+		iounmap(ha->reg);
+	pci_release_regions(ha->pdev);
+}
+
+/**
+ * qla4xxx_mem_alloc - allocates memory for use by adapter.
+ * @ha: Pointer to host adapter structure
+ *
+ * Allocates DMA memory for request and response queues. Also allocates memory
+ * for srbs.
+ **/
+static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
+{
+	unsigned long align;
+
+	/* Allocate contiguous block of DMA memory for queues. */
+	ha->queues_len = ((REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
+			  (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE) +
+			  sizeof(struct shadow_regs) +
+			  MEM_ALIGN_VALUE +
+			  (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+	ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
+					&ha->queues_dma, GFP_KERNEL);
+	if (ha->queues == NULL) {
+		dev_warn(&ha->pdev->dev,
+			"Memory Allocation failed - queues.\n");
+
+		goto mem_alloc_error_exit;
+	}
+	memset(ha->queues, 0, ha->queues_len);
+
+	/*
+	 * As per RISC alignment requirements -- the bus-address must be a
+	 * multiple of the request-ring size (in bytes).
+	 */
+	align = 0;
+	if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1))
+		align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma &
+					   (MEM_ALIGN_VALUE - 1));
+
+	/* Update request and response queue pointers. */
+	ha->request_dma = ha->queues_dma + align;
+	ha->request_ring = (struct queue_entry *) (ha->queues + align);
+	ha->response_dma = ha->queues_dma + align +
+		(REQUEST_QUEUE_DEPTH * QUEUE_SIZE);
+	ha->response_ring = (struct queue_entry *) (ha->queues + align +
+						    (REQUEST_QUEUE_DEPTH *
+						     QUEUE_SIZE));
+	ha->shadow_regs_dma = ha->queues_dma + align +
+		(REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +
+		(RESPONSE_QUEUE_DEPTH * QUEUE_SIZE);
+	ha->shadow_regs = (struct shadow_regs *) (ha->queues + align +
+						  (REQUEST_QUEUE_DEPTH *
+						   QUEUE_SIZE) +
+						  (RESPONSE_QUEUE_DEPTH *
+						   QUEUE_SIZE));
+
+	/* Allocate memory for srb pool. */
+	ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,
+					 mempool_free_slab, srb_cachep);
+	if (ha->srb_mempool == NULL) {
+		dev_warn(&ha->pdev->dev,
+			"Memory Allocation failed - SRB Pool.\n");
+
+		goto mem_alloc_error_exit;
+	}
+
+	return QLA_SUCCESS;
+
+mem_alloc_error_exit:
+	qla4xxx_mem_free(ha);
+	return QLA_ERROR;
+}
+
+/**
+ * qla4xxx_timer - checks every second for work to do.
+ * @ha: Pointer to host adapter structure.
+ **/
+static void qla4xxx_timer(struct scsi_qla_host *ha)
+{
+	struct ddb_entry *ddb_entry, *dtemp;
+	int start_dpc = 0;
+
+	/* Search for relogin's to time-out and port down retry. */
+	list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
+		/* Count down time between sending relogins */
+		if (adapter_up(ha) &&
+		    !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
+		    atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
+			if (atomic_read(&ddb_entry->retry_relogin_timer) !=
+			    INVALID_ENTRY) {
+				if (atomic_read(&ddb_entry->retry_relogin_timer)
+				    		== 0) {
+					atomic_set(&ddb_entry->
+						retry_relogin_timer,
+						INVALID_ENTRY);
+					set_bit(DPC_RELOGIN_DEVICE,
+						&ha->dpc_flags);
+					set_bit(DF_RELOGIN, &ddb_entry->flags);
+					DEBUG2(printk("scsi%ld: %s: index [%d]"
+						      " login device\n",
+						      ha->host_no, __func__,
+						      ddb_entry->fw_ddb_index));
+				} else
+					atomic_dec(&ddb_entry->
+							retry_relogin_timer);
+			}
+		}
+
+		/* Wait for relogin to timeout */
+		if (atomic_read(&ddb_entry->relogin_timer) &&
+		    (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
+			/*
+			 * If the relogin times out and the device is
+			 * still NOT ONLINE then try and relogin again.
+			 */
+			if (atomic_read(&ddb_entry->state) !=
+			    DDB_STATE_ONLINE &&
+			    ddb_entry->fw_ddb_device_state ==
+			    DDB_DS_SESSION_FAILED) {
+				/* Reset retry relogin timer */
+				atomic_inc(&ddb_entry->relogin_retry_count);
+				DEBUG2(printk("scsi%ld: index[%d] relogin"
+					      " timed out-retrying"
+					      " relogin (%d)\n",
+					      ha->host_no,
+					      ddb_entry->fw_ddb_index,
+					      atomic_read(&ddb_entry->
+							  relogin_retry_count))
+					);
+				start_dpc++;
+				DEBUG(printk("scsi%ld:%d:%d: index [%d] "
+					     "initate relogin after"
+					     " %d seconds\n",
+					     ha->host_no, ddb_entry->bus,
+					     ddb_entry->target,
+					     ddb_entry->fw_ddb_index,
+					     ddb_entry->default_time2wait + 4)
+					);
+
+				atomic_set(&ddb_entry->retry_relogin_timer,
+					   ddb_entry->default_time2wait + 4);
+			}
+		}
+	}
+
+	/* Check for heartbeat interval. */
+	if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&
+	    ha->heartbeat_interval != 0) {
+		ha->seconds_since_last_heartbeat++;
+		if (ha->seconds_since_last_heartbeat >
+		    ha->heartbeat_interval + 2)
+			set_bit(DPC_RESET_HA, &ha->dpc_flags);
+	}
+
+
+	/* Wakeup the dpc routine for this adapter, if needed. */
+	if ((start_dpc ||
+	     test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
+	     test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||
+	     test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) ||
+	     test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
+	     test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
+	     test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
+	     test_bit(DPC_AEN, &ha->dpc_flags)) &&
+	     ha->dpc_thread) {
+		DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
+			      " - dpc flags = 0x%lx\n",
+			      ha->host_no, __func__, ha->dpc_flags));
+		queue_work(ha->dpc_thread, &ha->dpc_work);
+	}
+
+	/* Reschedule timer thread to call us back in one second */
+	mod_timer(&ha->timer, jiffies + HZ);
+
+	DEBUG2(ha->seconds_since_last_intr++);
+}
+
+/**
+ * qla4xxx_cmd_wait - waits for all outstanding commands to complete
+ * @ha: Pointer to host adapter structure.
+ *
+ * This routine stalls the driver until all outstanding commands are returned.
+ * Caller must release the Hardware Lock prior to calling this routine.
+ **/
+static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
+{
+	uint32_t index = 0;
+	int stat = QLA_SUCCESS;
+	unsigned long flags;
+	struct scsi_cmnd *cmd;
+	int wait_cnt = WAIT_CMD_TOV;	/*
+					 * Initialized for 30 seconds as we
+					 * expect all commands to retuned
+					 * ASAP.
+					 */
+
+	while (wait_cnt) {
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		/* Find a command that hasn't completed. */
+		for (index = 0; index < ha->host->can_queue; index++) {
+			cmd = scsi_host_find_tag(ha->host, index);
+			if (cmd != NULL)
+				break;
+		}
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		/* If No Commands are pending, wait is complete */
+		if (index == ha->host->can_queue) {
+			break;
+		}
+
+		/* If we timed out on waiting for commands to come back
+		 * return ERROR.
+		 */
+		wait_cnt--;
+		if (wait_cnt == 0)
+			stat = QLA_ERROR;
+		else {
+			msleep(1000);
+		}
+	}			/* End of While (wait_cnt) */
+
+	return stat;
+}
+
+/**
+ * qla4010_soft_reset - performs soft reset.
+ * @ha: Pointer to host adapter structure.
+ **/
+static int qla4010_soft_reset(struct scsi_qla_host *ha)
+{
+	uint32_t max_wait_time;
+	unsigned long flags = 0;
+	int status = QLA_ERROR;
+	uint32_t ctrl_status;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	/*
+	 * If the SCSI Reset Interrupt bit is set, clear it.
+	 * Otherwise, the Soft Reset won't work.
+	 */
+	ctrl_status = readw(&ha->reg->ctrl_status);
+	if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0)
+		writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
+
+	/* Issue Soft Reset */
+	writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status);
+	readl(&ha->reg->ctrl_status);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	/* Wait until the Network Reset Intr bit is cleared */
+	max_wait_time = RESET_INTR_TOV;
+	do {
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		ctrl_status = readw(&ha->reg->ctrl_status);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		if ((ctrl_status & CSR_NET_RESET_INTR) == 0)
+			break;
+
+		msleep(1000);
+	} while ((--max_wait_time));
+
+	if ((ctrl_status & CSR_NET_RESET_INTR) != 0) {
+		DEBUG2(printk(KERN_WARNING
+			      "scsi%ld: Network Reset Intr not cleared by "
+			      "Network function, clearing it now!\n",
+			      ha->host_no));
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	}
+
+	/* Wait until the firmware tells us the Soft Reset is done */
+	max_wait_time = SOFT_RESET_TOV;
+	do {
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		ctrl_status = readw(&ha->reg->ctrl_status);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		if ((ctrl_status & CSR_SOFT_RESET) == 0) {
+			status = QLA_SUCCESS;
+			break;
+		}
+
+		msleep(1000);
+	} while ((--max_wait_time));
+
+	/*
+	 * Also, make sure that the SCSI Reset Interrupt bit has been cleared
+	 * after the soft reset has taken place.
+	 */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	ctrl_status = readw(&ha->reg->ctrl_status);
+	if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) {
+		writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	/* If soft reset fails then most probably the bios on other
+	 * function is also enabled.
+	 * Since the initialization is sequential the other fn
+	 * wont be able to acknowledge the soft reset.
+	 * Issue a force soft reset to workaround this scenario.
+	 */
+	if (max_wait_time == 0) {
+		/* Issue Force Soft Reset */
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		writel(set_rmask(CSR_FORCE_SOFT_RESET), &ha->reg->ctrl_status);
+		readl(&ha->reg->ctrl_status);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+		/* Wait until the firmware tells us the Soft Reset is done */
+		max_wait_time = SOFT_RESET_TOV;
+		do {
+			spin_lock_irqsave(&ha->hardware_lock, flags);
+			ctrl_status = readw(&ha->reg->ctrl_status);
+			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+			if ((ctrl_status & CSR_FORCE_SOFT_RESET) == 0) {
+				status = QLA_SUCCESS;
+				break;
+			}
+
+			msleep(1000);
+		} while ((--max_wait_time));
+	}
+
+	return status;
+}
+
+/**
+ * qla4xxx_topcat_reset - performs hard reset of TopCat Chip.
+ * @ha: Pointer to host adapter structure.
+ **/
+static int qla4xxx_topcat_reset(struct scsi_qla_host *ha)
+{
+	unsigned long flags;
+
+	ql4xxx_lock_nvram(ha);
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	writel(set_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha));
+	readl(isp_gp_out(ha));
+	mdelay(1);
+
+	writel(clr_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha));
+	readl(isp_gp_out(ha));
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	mdelay(2523);
+
+	ql4xxx_unlock_nvram(ha);
+	return QLA_SUCCESS;
+}
+
+/**
+ * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S.
+ * @ha: Pointer to host adapter structure.
+ *
+ * This routine is called just prior to a HARD RESET to return all
+ * outstanding commands back to the Operating System.
+ * Caller should make sure that the following locks are released
+ * before this calling routine: Hardware lock, and io_request_lock.
+ **/
+static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha)
+{
+	struct srb *srb;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (i = 0; i < ha->host->can_queue; i++) {
+		srb = qla4xxx_del_from_active_array(ha, i);
+		if (srb != NULL) {
+			srb->cmd->result = DID_RESET << 16;
+			qla4xxx_srb_compl(ha, srb);
+		}
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+}
+
+/**
+ * qla4xxx_hard_reset - performs HBA Hard Reset
+ * @ha: Pointer to host adapter structure.
+ **/
+static int qla4xxx_hard_reset(struct scsi_qla_host *ha)
+{
+	/* The QLA4010 really doesn't have an equivalent to a hard reset */
+	qla4xxx_flush_active_srbs(ha);
+	if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) {
+		int status = QLA_ERROR;
+
+		if ((qla4010_soft_reset(ha) == QLA_SUCCESS) &&
+		    (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) &&
+		    (qla4010_soft_reset(ha) == QLA_SUCCESS))
+			status = QLA_SUCCESS;
+		return status;
+	} else
+		return qla4010_soft_reset(ha);
+}
+
+/**
+ * qla4xxx_recover_adapter - recovers adapter after a fatal error
+ * @ha: Pointer to host adapter structure.
+ * @renew_ddb_list: Indicates what to do with the adapter's ddb list
+ *	after adapter recovery has completed.
+ *	0=preserve ddb list, 1=destroy and rebuild ddb list
+ **/
+static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
+				uint8_t renew_ddb_list)
+{
+	int status;
+
+	/* Stall incoming I/O until we are done */
+	clear_bit(AF_ONLINE, &ha->flags);
+	DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no,
+		      __func__));
+
+	/* Wait for outstanding commands to complete.
+	 * Stalls the driver for max 30 secs
+	 */
+	status = qla4xxx_cmd_wait(ha);
+
+	qla4xxx_disable_intrs(ha);
+
+	/* Flush any pending ddb changed AENs */
+	qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+
+	/* Reset the firmware.	If successful, function
+	 * returns with ISP interrupts enabled.
+	 */
+	if (status == QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n",
+			      ha->host_no, __func__));
+		status = qla4xxx_soft_reset(ha);
+	}
+	/* FIXMEkaren: Do we want to keep interrupts enabled and process
+	   AENs after soft reset */
+
+	/* If firmware (SOFT) reset failed, or if all outstanding
+	 * commands have not returned, then do a HARD reset.
+	 */
+	if (status == QLA_ERROR) {
+		DEBUG2(printk("scsi%ld: %s - Performing hard reset..\n",
+			      ha->host_no, __func__));
+		status = qla4xxx_hard_reset(ha);
+	}
+
+	/* Flush any pending ddb changed AENs */
+	qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+
+	/* Re-initialize firmware. If successful, function returns
+	 * with ISP interrupts enabled */
+	if (status == QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld: %s - Initializing adapter..\n",
+			      ha->host_no, __func__));
+
+		/* If successful, AF_ONLINE flag set in
+		 * qla4xxx_initialize_adapter */
+		status = qla4xxx_initialize_adapter(ha, renew_ddb_list);
+	}
+
+	/* Failed adapter initialization?
+	 * Retry reset_ha only if invoked via DPC (DPC_RESET_HA) */
+	if ((test_bit(AF_ONLINE, &ha->flags) == 0) &&
+	    (test_bit(DPC_RESET_HA, &ha->dpc_flags))) {
+		/* Adapter initialization failed, see if we can retry
+		 * resetting the ha */
+		if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) {
+			ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES;
+			DEBUG2(printk("scsi%ld: recover adapter - retrying "
+				      "(%d) more times\n", ha->host_no,
+				      ha->retry_reset_ha_cnt));
+			set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
+			status = QLA_ERROR;
+		} else {
+			if (ha->retry_reset_ha_cnt > 0) {
+				/* Schedule another Reset HA--DPC will retry */
+				ha->retry_reset_ha_cnt--;
+				DEBUG2(printk("scsi%ld: recover adapter - "
+					      "retry remaining %d\n",
+					      ha->host_no,
+					      ha->retry_reset_ha_cnt));
+				status = QLA_ERROR;
+			}
+
+			if (ha->retry_reset_ha_cnt == 0) {
+				/* Recover adapter retries have been exhausted.
+				 * Adapter DEAD */
+				DEBUG2(printk("scsi%ld: recover adapter "
+					      "failed - board disabled\n",
+					      ha->host_no));
+				qla4xxx_flush_active_srbs(ha);
+				clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
+				clear_bit(DPC_RESET_HA, &ha->dpc_flags);
+				clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST,
+					  &ha->dpc_flags);
+				status = QLA_ERROR;
+			}
+		}
+	} else {
+		clear_bit(DPC_RESET_HA, &ha->dpc_flags);
+		clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags);
+		clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);
+	}
+
+	ha->adapter_error_count++;
+
+	if (status == QLA_SUCCESS)
+		qla4xxx_enable_intrs(ha);
+
+	DEBUG2(printk("scsi%ld: recover adapter .. DONE\n", ha->host_no));
+	return status;
+}
+
+/**
+ * qla4xxx_do_dpc - dpc routine
+ * @data: in our case pointer to adapter structure
+ *
+ * This routine is a task that is schedule by the interrupt handler
+ * to perform the background processing for interrupts.  We put it
+ * on a task queue that is consumed whenever the scheduler runs; that's
+ * so you can do anything (i.e. put the process to sleep etc).  In fact,
+ * the mid-level tries to sleep when it reaches the driver threshold
+ * "host->can_queue". This can cause a panic if we were in our interrupt code.
+ **/
+static void qla4xxx_do_dpc(void *data)
+{
+	struct scsi_qla_host *ha = (struct scsi_qla_host *) data;
+	struct ddb_entry *ddb_entry, *dtemp;
+
+	DEBUG2(printk("scsi%ld: %s: DPC handler waking up.\n",
+		      ha->host_no, __func__));
+
+	DEBUG2(printk("scsi%ld: %s: ha->flags = 0x%08lx\n",
+		      ha->host_no, __func__, ha->flags));
+	DEBUG2(printk("scsi%ld: %s: ha->dpc_flags = 0x%08lx\n",
+		      ha->host_no, __func__, ha->dpc_flags));
+
+	/* Initialization not yet finished. Don't do anything yet. */
+	if (!test_bit(AF_INIT_DONE, &ha->flags))
+		return;
+
+	if (adapter_up(ha) ||
+	    test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
+	    test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
+	    test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) {
+		if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags))
+			/*
+			 * dg 09/23 Never initialize ddb list
+			 * once we up and running
+			 * qla4xxx_recover_adapter(ha,
+			 *    REBUILD_DDB_LIST);
+			 */
+			qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
+
+		if (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)) {
+			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__));
+		}
+	}
+
+	/* ---- process AEN? --- */
+	if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
+		qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
+
+	/* ---- Get DHCP IP Address? --- */
+	if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
+		qla4xxx_get_dhcp_ip_address(ha);
+
+	/* ---- relogin device? --- */
+	if (adapter_up(ha) &&
+	    test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
+		list_for_each_entry_safe(ddb_entry, dtemp,
+					 &ha->ddb_list, list) {
+			if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
+			    atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
+				qla4xxx_relogin_device(ha, ddb_entry);
+
+			/*
+			 * If mbx cmd times out there is no point
+			 * in continuing further.
+			 * With large no of targets this can hang
+			 * the system.
+			 */
+			if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
+				printk(KERN_WARNING "scsi%ld: %s: "
+				       "need to reset hba\n",
+				       ha->host_no, __func__);
+				break;
+			}
+		}
+	}
+}
+
+/**
+ * qla4xxx_free_adapter - release the adapter
+ * @ha: pointer to adapter structure
+ **/
+static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
+{
+
+	if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) {
+		/* Turn-off interrupts on the card. */
+		qla4xxx_disable_intrs(ha);
+	}
+
+	/* Kill the kernel thread for this host */
+	if (ha->dpc_thread)
+		destroy_workqueue(ha->dpc_thread);
+
+	/* Issue Soft Reset to put firmware in unknown state */
+	qla4xxx_soft_reset(ha);
+
+	/* Remove timer thread, if present */
+	if (ha->timer_active)
+		qla4xxx_stop_timer(ha);
+
+	/* free extra memory */
+	qla4xxx_mem_free(ha);
+
+	/* Detach interrupts */
+	if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
+		free_irq(ha->pdev->irq, ha);
+
+	pci_disable_device(ha->pdev);
+
+}
+
+/***
+ * qla4xxx_iospace_config - maps registers
+ * @ha: pointer to adapter structure
+ *
+ * This routines maps HBA's registers from the pci address space
+ * into the kernel virtual address space for memory mapped i/o.
+ **/
+static int qla4xxx_iospace_config(struct scsi_qla_host *ha)
+{
+	unsigned long pio, pio_len, pio_flags;
+	unsigned long mmio, mmio_len, mmio_flags;
+
+	pio = pci_resource_start(ha->pdev, 0);
+	pio_len = pci_resource_len(ha->pdev, 0);
+	pio_flags = pci_resource_flags(ha->pdev, 0);
+	if (pio_flags & IORESOURCE_IO) {
+		if (pio_len < MIN_IOBASE_LEN) {
+			dev_warn(&ha->pdev->dev,
+				"Invalid PCI I/O region size\n");
+			pio = 0;
+		}
+	} else {
+		dev_warn(&ha->pdev->dev, "region #0 not a PIO resource\n");
+		pio = 0;
+	}
+
+	/* Use MMIO operations for all accesses. */
+	mmio = pci_resource_start(ha->pdev, 1);
+	mmio_len = pci_resource_len(ha->pdev, 1);
+	mmio_flags = pci_resource_flags(ha->pdev, 1);
+
+	if (!(mmio_flags & IORESOURCE_MEM)) {
+		dev_err(&ha->pdev->dev,
+			"region #0 not an MMIO resource, aborting\n");
+
+		goto iospace_error_exit;
+	}
+	if (mmio_len < MIN_IOBASE_LEN) {
+		dev_err(&ha->pdev->dev,
+			"Invalid PCI mem region size, aborting\n");
+		goto iospace_error_exit;
+	}
+
+	if (pci_request_regions(ha->pdev, DRIVER_NAME)) {
+		dev_warn(&ha->pdev->dev,
+			"Failed to reserve PIO/MMIO regions\n");
+
+		goto iospace_error_exit;
+	}
+
+	ha->pio_address = pio;
+	ha->pio_length = pio_len;
+	ha->reg = ioremap(mmio, MIN_IOBASE_LEN);
+	if (!ha->reg) {
+		dev_err(&ha->pdev->dev,
+			"cannot remap MMIO, aborting\n");
+
+		goto iospace_error_exit;
+	}
+
+	return 0;
+
+iospace_error_exit:
+	return -ENOMEM;
+}
+
+/**
+ * qla4xxx_probe_adapter - callback function to probe HBA
+ * @pdev: pointer to pci_dev structure
+ * @pci_device_id: pointer to pci_device entry
+ *
+ * This routine will probe for Qlogic 4xxx iSCSI host adapters.
+ * It returns zero if successful. It also initializes all data necessary for
+ * the driver.
+ **/
+static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+					   const struct pci_device_id *ent)
+{
+	int ret = -ENODEV, status;
+	struct Scsi_Host *host;
+	struct scsi_qla_host *ha;
+	struct ddb_entry *ddb_entry, *ddbtemp;
+	uint8_t init_retry_count = 0;
+	char buf[34];
+
+	if (pci_enable_device(pdev))
+		return -1;
+
+	host = scsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha));
+	if (host == NULL) {
+		printk(KERN_WARNING
+		       "qla4xxx: Couldn't allocate host from scsi layer!\n");
+		goto probe_disable_device;
+	}
+
+	/* Clear our data area */
+	ha = (struct scsi_qla_host *) host->hostdata;
+	memset(ha, 0, sizeof(*ha));
+
+	/* Save the information from PCI BIOS.	*/
+	ha->pdev = pdev;
+	ha->host = host;
+	ha->host_no = host->host_no;
+
+	/* Configure PCI I/O space. */
+	ret = qla4xxx_iospace_config(ha);
+	if (ret)
+		goto probe_failed;
+
+	dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n",
+		   pdev->device, pdev->irq, ha->reg);
+
+	qla4xxx_config_dma_addressing(ha);
+
+	/* Initialize lists and spinlocks. */
+	INIT_LIST_HEAD(&ha->ddb_list);
+	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);
+	spin_lock_init(&ha->list_lock);
+
+	/* Allocate dma buffers */
+	if (qla4xxx_mem_alloc(ha)) {
+		dev_warn(&ha->pdev->dev,
+			   "[ERROR] Failed to allocate memory for adapter\n");
+
+		ret = -ENOMEM;
+		goto probe_failed;
+	}
+
+	/*
+	 * Initialize the Host adapter request/response queues and
+	 * firmware
+	 * NOTE: interrupts enabled upon successful completion
+	 */
+	status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
+	while (status == QLA_ERROR && init_retry_count++ < MAX_INIT_RETRIES) {
+		DEBUG2(printk("scsi: %s: retrying adapter initialization "
+			      "(%d)\n", __func__, init_retry_count));
+		qla4xxx_soft_reset(ha);
+		status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
+	}
+	if (status == QLA_ERROR) {
+		dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n");
+
+		ret = -ENODEV;
+		goto probe_failed;
+	}
+
+	host->cmd_per_lun = 3;
+	host->max_channel = 0;
+	host->max_lun = MAX_LUNS - 1;
+	host->max_id = MAX_TARGETS;
+	host->max_cmd_len = IOCB_MAX_CDB_LEN;
+	host->can_queue = MAX_SRBS ;
+	host->transportt = qla4xxx_scsi_transport;
+
+        ret = scsi_init_shared_tag_map(host, MAX_SRBS);
+        if (ret) {
+                dev_warn(&ha->pdev->dev, "scsi_init_shared_tag_map failed");
+                goto probe_failed;
+        }
+
+	/* Startup the kernel thread for this host adapter. */
+	DEBUG2(printk("scsi: %s: Starting kernel thread for "
+		      "qla4xxx_dpc\n", __func__));
+	sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no);
+	ha->dpc_thread = create_singlethread_workqueue(buf);
+	if (!ha->dpc_thread) {
+		dev_warn(&ha->pdev->dev, "Unable to start DPC thread!\n");
+		ret = -ENODEV;
+		goto probe_failed;
+	}
+	INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc, ha);
+
+	ret = request_irq(pdev->irq, qla4xxx_intr_handler,
+			  SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha);
+	if (ret) {
+		dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d"
+			" already in use.\n", pdev->irq);
+		goto probe_failed;
+	}
+	set_bit(AF_IRQ_ATTACHED, &ha->flags);
+	host->irq = pdev->irq;
+	DEBUG(printk("scsi%d: irq %d attached\n", ha->host_no, ha->pdev->irq));
+
+	qla4xxx_enable_intrs(ha);
+
+	/* Start timer thread. */
+	qla4xxx_start_timer(ha, qla4xxx_timer, 1);
+
+	set_bit(AF_INIT_DONE, &ha->flags);
+
+	pci_set_drvdata(pdev, ha);
+
+	ret = scsi_add_host(host, &pdev->dev);
+	if (ret)
+		goto probe_failed;
+
+	/* Update transport device information for all devices. */
+	list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
+		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
+			if (qla4xxx_add_sess(ddb_entry))
+				goto remove_host;
+	}
+
+	printk(KERN_INFO
+	       " QLogic iSCSI HBA Driver version: %s\n"
+	       "  QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
+	       qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
+	       ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
+	       ha->patch_number, ha->build_number);
+
+	return 0;
+
+remove_host:
+	qla4xxx_free_ddb_list(ha);
+	scsi_remove_host(host);
+
+probe_failed:
+	qla4xxx_free_adapter(ha);
+	scsi_host_put(ha->host);
+
+probe_disable_device:
+	pci_disable_device(pdev);
+
+	return ret;
+}
+
+/**
+ * qla4xxx_remove_adapter - calback function to remove adapter.
+ * @pci_dev: PCI device pointer
+ **/
+static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
+{
+	struct scsi_qla_host *ha;
+
+	ha = pci_get_drvdata(pdev);
+
+	/* remove devs from iscsi_sessions to scsi_devices */
+	qla4xxx_free_ddb_list(ha);
+
+	scsi_remove_host(ha->host);
+
+	qla4xxx_free_adapter(ha);
+
+	scsi_host_put(ha->host);
+
+	pci_set_drvdata(pdev, NULL);
+}
+
+/**
+ * qla4xxx_config_dma_addressing() - Configure OS DMA addressing method.
+ * @ha: HA context
+ *
+ * At exit, the @ha's flags.enable_64bit_addressing set to indicated
+ * supported addressing method.
+ */
+void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
+{
+	int retval;
+
+	/* Update our PCI device dma_mask for full 64 bit mask */
+	if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) {
+		if (pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
+			dev_dbg(&ha->pdev->dev,
+				  "Failed to set 64 bit PCI consistent mask; "
+				   "using 32 bit.\n");
+			retval = pci_set_consistent_dma_mask(ha->pdev,
+							     DMA_32BIT_MASK);
+		}
+	} else
+		retval = pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
+}
+
+static int qla4xxx_slave_alloc(struct scsi_device *sdev)
+{
+	struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
+	struct ddb_entry *ddb = sess->dd_data;
+
+	sdev->hostdata = ddb;
+	sdev->tagged_supported = 1;
+	scsi_activate_tcq(sdev, sdev->host->can_queue);
+	return 0;
+}
+
+static int qla4xxx_slave_configure(struct scsi_device *sdev)
+{
+	sdev->tagged_supported = 1;
+	return 0;
+}
+
+static void qla4xxx_slave_destroy(struct scsi_device *sdev)
+{
+	scsi_deactivate_tcq(sdev, 1);
+}
+
+/**
+ * qla4xxx_del_from_active_array - returns an active srb
+ * @ha: Pointer to host adapter structure.
+ * @index: index into to the active_array
+ *
+ * This routine removes and returns the srb at the specified index
+ **/
+struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index)
+{
+	struct srb *srb = NULL;
+	struct scsi_cmnd *cmd;
+
+	if (!(cmd = scsi_host_find_tag(ha->host, index)))
+		return srb;
+
+	if (!(srb = (struct srb *)cmd->host_scribble))
+		return srb;
+
+	/* update counters */
+	if (srb->flags & SRB_DMA_VALID) {
+		ha->req_q_count += srb->iocb_cnt;
+		ha->iocb_cnt -= srb->iocb_cnt;
+		if (srb->cmd)
+			srb->cmd->host_scribble = NULL;
+	}
+	return srb;
+}
+
+/**
+ * qla4xxx_soft_reset - performs a SOFT RESET of hba.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+{
+
+	DEBUG2(printk(KERN_WARNING "scsi%ld: %s: chip reset!\n", ha->host_no,
+		      __func__));
+	if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) {
+		int status = QLA_ERROR;
+
+		if ((qla4010_soft_reset(ha) == QLA_SUCCESS) &&
+		    (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) &&
+		    (qla4010_soft_reset(ha) == QLA_SUCCESS) )
+			status = QLA_SUCCESS;
+		return status;
+	} else
+		return qla4010_soft_reset(ha);
+}
+
+/**
+ * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware
+ * @ha: actual ha whose done queue will contain the comd returned by firmware.
+ * @cmd: Scsi Command to wait on.
+ *
+ * This routine waits for the command to be returned by the Firmware
+ * for some max time.
+ **/
+static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha,
+				      struct scsi_cmnd *cmd)
+{
+	int done = 0;
+	struct srb *rp;
+	uint32_t max_wait_time = EH_WAIT_CMD_TOV;
+
+	do {
+		/* Checking to see if its returned to OS */
+		rp = (struct srb *) cmd->SCp.ptr;
+		if (rp == NULL) {
+			done++;
+			break;
+		}
+
+		msleep(2000);
+	} while (max_wait_time--);
+
+	return done;
+}
+
+/**
+ * qla4xxx_wait_for_hba_online - waits for HBA to come online
+ * @ha: Pointer to host adapter structure
+ **/
+static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+{
+	unsigned long wait_online;
+
+	wait_online = jiffies + (30 * HZ);
+	while (time_before(jiffies, wait_online)) {
+
+		if (adapter_up(ha))
+			return QLA_SUCCESS;
+		else if (ha->retry_reset_ha_cnt == 0)
+			return QLA_ERROR;
+
+		msleep(2000);
+	}
+
+	return QLA_ERROR;
+}
+
+/**
+ * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
+ * @ha: pointer to to HBA
+ * @t: target id
+ * @l: lun id
+ *
+ * This function waits for all outstanding commands to a lun to complete. It
+ * returns 0 if all pending commands are returned and 1 otherwise.
+ **/
+static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha,
+						 int t, int l)
+{
+	int cnt;
+	int status = 0;
+	struct scsi_cmnd *cmd;
+
+	/*
+	 * Waiting for all commands for the designated target in the active
+	 * array
+	 */
+	for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
+		cmd = scsi_host_find_tag(ha->host, cnt);
+		if (cmd && cmd->device->id == t && cmd->device->lun == l) {
+			if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
+				status++;
+				break;
+			}
+		}
+	}
+	return status;
+}
+
+/**
+ * qla4xxx_eh_device_reset - callback for target reset.
+ * @cmd: Pointer to Linux's SCSI command structure
+ *
+ * This routine is called by the Linux OS to reset all luns on the
+ * specified target.
+ **/
+static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
+{
+	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
+	struct ddb_entry *ddb_entry = cmd->device->hostdata;
+	struct srb *sp;
+	int ret = FAILED, stat;
+
+	sp = (struct srb *) cmd->SCp.ptr;
+	if (!sp || !ddb_entry)
+		return ret;
+
+	dev_info(&ha->pdev->dev,
+		   "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no,
+		   cmd->device->channel, cmd->device->id, cmd->device->lun);
+
+	DEBUG2(printk(KERN_INFO
+		      "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"
+		      "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,
+		      cmd, jiffies, cmd->timeout_per_command / HZ,
+		      ha->dpc_flags, cmd->result, cmd->allowed));
+
+	/* FIXME: wait for hba to go online */
+	stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
+	if (stat != QLA_SUCCESS) {
+		dev_info(&ha->pdev->dev, "DEVICE RESET FAILED. %d\n", stat);
+		goto eh_dev_reset_done;
+	}
+
+	/* Send marker. */
+	ha->marker_needed = 1;
+
+	/*
+	 * If we are coming down the EH path, wait for all commands to complete
+	 * for the device.
+	 */
+	if (cmd->device->host->shost_state == SHOST_RECOVERY) {
+		if (qla4xxx_eh_wait_for_active_target_commands(ha,
+							  cmd->device->id,
+							  cmd->device->lun)){
+			dev_info(&ha->pdev->dev,
+				   "DEVICE RESET FAILED - waiting for "
+				   "commands.\n");
+			goto eh_dev_reset_done;
+		}
+	}
+
+	dev_info(&ha->pdev->dev,
+		   "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
+		   ha->host_no, cmd->device->channel, cmd->device->id,
+		   cmd->device->lun);
+
+	ret = SUCCESS;
+
+eh_dev_reset_done:
+
+	return ret;
+}
+
+/**
+ * qla4xxx_eh_host_reset - kernel callback
+ * @cmd: Pointer to Linux's SCSI command structure
+ *
+ * This routine is invoked by the Linux kernel to perform fatal error
+ * recovery on the specified adapter.
+ **/
+static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
+{
+	int return_status = FAILED;
+	struct scsi_qla_host *ha;
+
+	ha = (struct scsi_qla_host *) cmd->device->host->hostdata;
+
+	dev_info(&ha->pdev->dev,
+		   "scsi(%ld:%d:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no,
+		   cmd->device->channel, cmd->device->id, cmd->device->lun);
+
+	if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
+		DEBUG2(printk("scsi%ld:%d: %s: Unable to reset host.  Adapter "
+			      "DEAD.\n", ha->host_no, cmd->device->channel,
+			      __func__));
+
+		return FAILED;
+	}
+
+	if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) {
+		return_status = SUCCESS;
+	}
+
+	dev_info(&ha->pdev->dev, "HOST RESET %s.\n",
+		   return_status == FAILED ? "FAILED" : "SUCCEDED");
+
+	return return_status;
+}
+
+
+static struct pci_device_id qla4xxx_pci_tbl[] = {
+	{
+		.vendor		= PCI_VENDOR_ID_QLOGIC,
+		.device		= PCI_DEVICE_ID_QLOGIC_ISP4010,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_QLOGIC,
+		.device		= PCI_DEVICE_ID_QLOGIC_ISP4022,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{0, 0},
+};
+MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
+
+struct pci_driver qla4xxx_pci_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= qla4xxx_pci_tbl,
+	.probe		= qla4xxx_probe_adapter,
+	.remove		= qla4xxx_remove_adapter,
+};
+
+static int __init qla4xxx_module_init(void)
+{
+	int ret;
+
+	/* Allocate cache for SRBs. */
+	srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
+				       SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (srb_cachep == NULL) {
+		printk(KERN_ERR
+		       "%s: Unable to allocate SRB cache..."
+		       "Failing load!\n", DRIVER_NAME);
+		ret = -ENOMEM;
+		goto no_srp_cache;
+	}
+
+	/* Derive version string. */
+	strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION);
+	if (qla4_extended_error_logging)
+		strcat(qla4xxx_version_str, "-debug");
+
+	qla4xxx_scsi_transport =
+		iscsi_register_transport(&qla4xxx_iscsi_transport);
+	if (!qla4xxx_scsi_transport){
+		ret = -ENODEV;
+		goto release_srb_cache;
+	}
+
+	printk(KERN_INFO "QLogic iSCSI HBA Driver\n");
+	ret = pci_register_driver(&qla4xxx_pci_driver);
+	if (ret)
+		goto unregister_transport;
+
+	printk(KERN_INFO "QLogic iSCSI HBA Driver\n");
+	return 0;
+unregister_transport:
+	iscsi_unregister_transport(&qla4xxx_iscsi_transport);
+release_srb_cache:
+	kmem_cache_destroy(srb_cachep);
+no_srp_cache:
+	return ret;
+}
+
+static void __exit qla4xxx_module_exit(void)
+{
+	pci_unregister_driver(&qla4xxx_pci_driver);
+	iscsi_unregister_transport(&qla4xxx_iscsi_transport);
+	kmem_cache_destroy(srb_cachep);
+}
+
+module_init(qla4xxx_module_init);
+module_exit(qla4xxx_module_exit);
+
+MODULE_AUTHOR("QLogic Corporation");
+MODULE_DESCRIPTION("QLogic iSCSI HBA Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA4XXX_DRIVER_VERSION);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
new file mode 100644
index 0000000..b3fe7e6
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -0,0 +1,13 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#define QLA4XXX_DRIVER_VERSION	"5.00.05b9-k"
+
+#define QL4_DRIVER_MAJOR_VER	5
+#define QL4_DRIVER_MINOR_VER	0
+#define QL4_DRIVER_PATCH_VER	5
+#define QL4_DRIVER_BETA_VER	9
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 52fb2ec..e072535 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -405,10 +405,10 @@
  *	Interrupt handler 
  */
 
-static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs)
+static void ql_ihandl(void *dev_id)
 {
 	Scsi_Cmnd *icmd;
-	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
+	struct Scsi_Host *host = dev_id;
 	struct qlogicfas408_priv *priv = get_priv_by_host(host);
 	int qbase = priv->qbase;
 	REG0;
@@ -432,13 +432,13 @@
 	(icmd->scsi_done) (icmd);
 }
 
-irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *host = dev_id;
 
 	spin_lock_irqsave(host->host_lock, flags);
-	ql_ihandl(irq, dev_id, regs);
+	ql_ihandl(dev_id);
 	spin_unlock_irqrestore(host->host_lock, flags);
 	return IRQ_HANDLED;
 }
diff --git a/drivers/scsi/qlogicfas408.h b/drivers/scsi/qlogicfas408.h
index 4b3df20..8fd5555 100644
--- a/drivers/scsi/qlogicfas408.h
+++ b/drivers/scsi/qlogicfas408.h
@@ -102,7 +102,7 @@
 #define get_priv_by_cmd(x) (struct qlogicfas408_priv *)&((x)->device->host->hostdata[0])
 #define get_priv_by_host(x) (struct qlogicfas408_priv *)&((x)->hostdata[0])
 
-irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id);
 int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
 int qlogicfas408_biosparam(struct scsi_device * disk,
 		        struct block_device *dev,
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 5b2f074..9b827ce 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -461,7 +461,7 @@
 
 #define PTI_RESET_LIMIT 400
 
-static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
+static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
 {
 	struct Scsi_Host *host = qpti->qhost;
 	unsigned short csum = 0;
@@ -649,7 +649,7 @@
 	return 0;
 }
 
-static irqreturn_t qpti_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t qpti_intr(int irq, void *dev_id);
 
 static void __init qpti_chain_add(struct qlogicpti *qpti)
 {
@@ -1297,7 +1297,7 @@
 	return done_queue;
 }
 
-static irqreturn_t qpti_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t qpti_intr(int irq, void *dev_id)
 {
 	struct qlogicpti *qpti = dev_id;
 	unsigned long flags;
diff --git a/drivers/scsi/qlogicpti_asm.c b/drivers/scsi/qlogicpti_asm.c
index 1545b30..19aa84f 100644
--- a/drivers/scsi/qlogicpti_asm.c
+++ b/drivers/scsi/qlogicpti_asm.c
@@ -1,5 +1,5 @@
 /* Version 1.31.00 ISP1000 Initiator RISC firmware */
-unsigned short sbus_risc_code01[] __initdata = {
+unsigned short sbus_risc_code01[] __devinitdata = {
 	0x0078, 0x1030, 0x0000, 0x2419, 0x0000, 0x12ff, 0x2043, 0x4f50,
 	0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
 	0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
@@ -1157,4 +1157,4 @@
 	0x003c, 0x0040, 0x3415, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c,
 	0x92a7
 };
-unsigned short sbus_risc_code_length01 = 0x2419;
+unsigned short __devinitdata sbus_risc_code_length01 = 0x2419;
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 327b33a..86e1318 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -215,18 +215,19 @@
 	kfree(rc);
 }
 
-void raid_component_add(struct raid_template *r,struct device *raid_dev,
-			struct device *component_dev)
+int raid_component_add(struct raid_template *r,struct device *raid_dev,
+		       struct device *component_dev)
 {
 	struct class_device *cdev =
 		attribute_container_find_class_device(&r->raid_attrs.ac,
 						      raid_dev);
 	struct raid_component *rc;
 	struct raid_data *rd = class_get_devdata(cdev);
+	int err;
 
 	rc = kzalloc(sizeof(*rc), GFP_KERNEL);
 	if (!rc)
-		return;
+		return -ENOMEM;
 
 	INIT_LIST_HEAD(&rc->node);
 	class_device_initialize(&rc->cdev);
@@ -239,7 +240,18 @@
 	list_add_tail(&rc->node, &rd->component_list);
 	rc->cdev.parent = cdev;
 	rc->cdev.class = &raid_class.class;
-	class_device_add(&rc->cdev);
+	err = class_device_add(&rc->cdev);
+	if (err)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	list_del(&rc->node);
+	rd->component_count--;
+	put_device(component_dev);
+	kfree(rc);
+	return err;
 }
 EXPORT_SYMBOL(raid_component_add);
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index da95bce..c59f315 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -128,7 +128,7 @@
 		return "Well-known LUN   ";
 	if (type == 0x1f)
 		return "No Device        ";
-	if (type > ARRAY_SIZE(scsi_device_types))
+	if (type >= ARRAY_SIZE(scsi_device_types))
 		return "Unknown          ";
 	return scsi_device_types[type];
 }
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 3d0429b..ce63044 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -150,6 +150,7 @@
 	{"DELL", "PERCRAID", NULL, BLIST_FORCELUN},
 	{"DGC", "RAID", NULL, BLIST_SPARSELUN},	/* Dell PV 650F, storage on LUN 0 */
 	{"DGC", "DISK", NULL, BLIST_SPARSELUN},	/* Dell PV 650F, no storage on LUN 0 */
+	{"EMC",  "Invista", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
 	{"EMULEX", "MD21/S2     ESDI", NULL, BLIST_SINGLELUN},
 	{"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
@@ -161,6 +162,11 @@
 	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
 	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},	/* HP VA7400 */
 	{"HP", "OPEN-", "*", BLIST_REPORTLUN2}, /* HP XP Arrays */
 	{"HP", "NetRAID-4M", NULL, BLIST_FORCELUN},
@@ -168,6 +174,14 @@
 	{"HP", "C1557A", NULL, BLIST_FORCELUN},
 	{"HP", "C3323-300", "4269", BLIST_NOTQ},
 	{"HP", "C5713A", NULL, BLIST_NOREPORTLUN},
+	{"HP", "DF400", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "DF500", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "DF600", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HP", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
 	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
@@ -188,6 +202,7 @@
 	{"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+	{"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
 	{"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
@@ -210,6 +225,7 @@
 	{"SUN", "T300", "*", BLIST_SPARSELUN},
 	{"SUN", "T4", "*", BLIST_SPARSELUN},
 	{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
+	{"Tornado-", "F4", "*", BLIST_NOREPORTLUN},
 	{"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
 	{"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
 	{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 3d355d0..aff1b0c 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -495,7 +495,7 @@
 	memcpy(scmd->cmnd, cmnd, cmnd_size);
 
 	if (copy_sense) {
-		int gfp_mask = GFP_ATOMIC;
+		gfp_t gfp_mask = GFP_ATOMIC;
 
 		if (shost->hostt->unchecked_isa_dma)
 			gfp_mask |= __GFP_DMA;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7108472..743f67e 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -426,7 +426,7 @@
 free_req:
 	blk_put_request(req);
 free_sense:
-	kfree(sioc);
+	kmem_cache_free(scsi_io_context_cache, sioc);
 	return DRIVER_ERROR << 24;
 }
 EXPORT_SYMBOL_GPL(scsi_execute_async);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 10bc99c..84ff203 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1794,7 +1794,7 @@
  **/
 static int __init init_sd(void)
 {
-	int majors = 0, i;
+	int majors = 0, i, err;
 
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 
@@ -1805,9 +1805,22 @@
 	if (!majors)
 		return -ENODEV;
 
-	class_register(&sd_disk_class);
+	err = class_register(&sd_disk_class);
+	if (err)
+		goto err_out;
 
-	return scsi_register_driver(&sd_template.gendrv);
+	err = scsi_register_driver(&sd_template.gendrv);
+	if (err)
+		goto err_out_class;
+
+	return 0;
+
+err_out_class:
+	class_unregister(&sd_disk_class);
+err_out:
+	for (i = 0; i < SD_MAJORS; i++)
+		unregister_blkdev(sd_major(i), "sd");
+	return err;
 }
 
 /**
@@ -1822,10 +1835,10 @@
 	SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
 	scsi_unregister_driver(&sd_template.gendrv);
+	class_unregister(&sd_disk_class);
+
 	for (i = 0; i < SD_MAJORS; i++)
 		unregister_blkdev(sd_major(i), "sd");
-
-	class_unregister(&sd_disk_class);
 }
 
 module_init(init_sd);
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 2679ea8b..5ffec27 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -94,21 +94,21 @@
 #include <linux/string.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/blkdev.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#include "scsi.h"
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi.h>
+
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_host.h>
-#include "seagate.h"
 
-#include <scsi/scsi_ioctl.h>
 
 #ifdef DEBUG
 #define DPRINTK( when, msg... ) do { if ( (DEBUG & (when)) == (when) ) printk( msg ); } while (0)
@@ -320,8 +320,9 @@
  */
 
 static int hostno = -1;
-static void seagate_reconnect_intr (int, void *, struct pt_regs *);
-static irqreturn_t do_seagate_reconnect_intr (int, void *, struct pt_regs *);
+static void seagate_reconnect_intr (int, void *);
+static irqreturn_t do_seagate_reconnect_intr (int, void *);
+static int seagate_st0x_bus_reset(struct scsi_cmnd *);
 
 #ifdef FAST
 static int fast = 1;
@@ -585,8 +586,8 @@
 static unsigned char linked_target, linked_lun;
 #endif
 
-static void (*done_fn) (Scsi_Cmnd *) = NULL;
-static Scsi_Cmnd *SCint = NULL;
+static void (*done_fn) (struct scsi_cmnd *) = NULL;
+static struct scsi_cmnd *SCint = NULL;
 
 /*
  * These control whether or not disconnect / reconnect will be attempted,
@@ -618,22 +619,21 @@
  * asserting SEL.
  */
 
-static irqreturn_t do_seagate_reconnect_intr(int irq, void *dev_id,
-						struct pt_regs *regs)
+static irqreturn_t do_seagate_reconnect_intr(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct Scsi_Host *dev = dev_id;
 	
 	spin_lock_irqsave (dev->host_lock, flags);
-	seagate_reconnect_intr (irq, dev_id, regs);
+	seagate_reconnect_intr (irq, dev_id);
 	spin_unlock_irqrestore (dev->host_lock, flags);
 	return IRQ_HANDLED;
 }
 
-static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs)
+static void seagate_reconnect_intr (int irq, void *dev_id)
 {
 	int temp;
-	Scsi_Cmnd *SCtmp;
+	struct scsi_cmnd *SCtmp;
 
 	DPRINTK (PHASE_RESELECT, "scsi%d : seagate_reconnect_intr() called\n", hostno);
 
@@ -675,10 +675,11 @@
 
 static int recursion_depth = 0;
 
-static int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+static int seagate_st0x_queue_command(struct scsi_cmnd * SCpnt,
+				      void (*done) (struct scsi_cmnd *))
 {
 	int result, reconnect;
-	Scsi_Cmnd *SCtmp;
+	struct scsi_cmnd *SCtmp;
 
 	DANY ("seagate: que_command");
 	done_fn = done;
@@ -1609,7 +1610,7 @@
 	return retcode (st0x_aborted);
 }				/* end of internal_command */
 
-static int seagate_st0x_abort (Scsi_Cmnd * SCpnt)
+static int seagate_st0x_abort(struct scsi_cmnd * SCpnt)
 {
 	st0x_aborted = DID_ABORT;
 	return SUCCESS;
@@ -1624,7 +1625,7 @@
  * May be called with SCpnt = NULL
  */
 
-static int seagate_st0x_bus_reset(Scsi_Cmnd * SCpnt)
+static int seagate_st0x_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	/* No timeouts - this command is going to fail because it was reset. */
 	DANY ("scsi%d: Reseting bus... ", hostno);
diff --git a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h
deleted file mode 100644
index fb5f380..0000000
--- a/drivers/scsi/seagate.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *	seagate.h Copyright (C) 1992 Drew Eckhardt 
- *	low level scsi driver header for ST01/ST02 by
- *		Drew Eckhardt 
- *
- *	<drew@colorado.edu>
- */
-
-#ifndef _SEAGATE_H
-#define SEAGATE_H
-
-static int seagate_st0x_detect(struct scsi_host_template *);
-static int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-
-static int seagate_st0x_abort(Scsi_Cmnd *);
-static const char *seagate_st0x_info(struct Scsi_Host *);
-static int seagate_st0x_bus_reset(Scsi_Cmnd *);
-
-#endif /* _SEAGATE_H */
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 34f9343e..3f8b931 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -60,7 +60,7 @@
 
 #ifdef CONFIG_SCSI_PROC_FS
 #include <linux/proc_fs.h>
-static char *sg_version_date = "20060818";
+static char *sg_version_date = "20060920";
 
 static int sg_proc_init(void);
 static void sg_proc_cleanup(void);
@@ -94,6 +94,9 @@
 static int def_reserved_size = -1;	/* picks up init parameter */
 static int sg_allow_dio = SG_ALLOW_DIO_DEF;
 
+static int scatter_elem_sz = SG_SCATTER_SZ;
+static int scatter_elem_sz_prev = SG_SCATTER_SZ;
+
 #define SG_SECTOR_SZ 512
 #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
 
@@ -1537,11 +1540,9 @@
 		msleep(10);	/* dirty detach so delay device destruction */
 }
 
-/* Set 'perm' (4th argument) to 0 to disable module_param's definition
- * of sysfs parameters (which module_param doesn't yet support).
- * Sysfs parameters defined explicitly below.
- */
-module_param_named(def_reserved_size, def_reserved_size, int, S_IRUGO);
+module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
+module_param_named(def_reserved_size, def_reserved_size, int,
+		   S_IRUGO | S_IWUSR);
 module_param_named(allow_dio, sg_allow_dio, int, S_IRUGO | S_IWUSR);
 
 MODULE_AUTHOR("Douglas Gilbert");
@@ -1550,6 +1551,8 @@
 MODULE_VERSION(SG_VERSION_STR);
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_GENERIC_MAJOR);
 
+MODULE_PARM_DESC(scatter_elem_sz, "scatter gather element "
+                "size (default: max(SG_SCATTER_SZ, PAGE_SIZE))");
 MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
 MODULE_PARM_DESC(allow_dio, "allow direct I/O (default: 0 (disallow))");
 
@@ -1558,8 +1561,14 @@
 {
 	int rc;
 
+	if (scatter_elem_sz < PAGE_SIZE) {
+		scatter_elem_sz = PAGE_SIZE;
+		scatter_elem_sz_prev = scatter_elem_sz;
+	}
 	if (def_reserved_size >= 0)
 		sg_big_buff = def_reserved_size;
+	else
+		def_reserved_size = sg_big_buff;
 
 	rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), 
 				    SG_MAX_DEVS, "sg");
@@ -1842,15 +1851,30 @@
 	if (mx_sc_elems < 0)
 		return mx_sc_elems;	/* most likely -ENOMEM */
 
+	num = scatter_elem_sz;
+	if (unlikely(num != scatter_elem_sz_prev)) {
+		if (num < PAGE_SIZE) {
+			scatter_elem_sz = PAGE_SIZE;
+			scatter_elem_sz_prev = PAGE_SIZE;
+		} else
+			scatter_elem_sz_prev = num;
+	}
 	for (k = 0, sg = schp->buffer, rem_sz = blk_size;
 	     (rem_sz > 0) && (k < mx_sc_elems);
 	     ++k, rem_sz -= ret_sz, ++sg) {
 		
-		num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
+		num = (rem_sz > scatter_elem_sz_prev) ?
+		      scatter_elem_sz_prev : rem_sz;
 		p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
 		if (!p)
 			return -ENOMEM;
 
+		if (num == scatter_elem_sz_prev) {
+			if (unlikely(ret_sz > scatter_elem_sz_prev)) {
+				scatter_elem_sz = ret_sz;
+				scatter_elem_sz_prev = ret_sz;
+			}
+		}
 		sg->page = p;
 		sg->length = ret_sz;
 
@@ -2341,6 +2365,9 @@
 	}
 	write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
+	if (unlikely(sg_big_buff != def_reserved_size))
+		sg_big_buff = def_reserved_size;
+
 	sg_build_reserve(sfp, sg_big_buff);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
 			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));
@@ -2437,16 +2464,16 @@
 	return srp ? 1 : 0;
 }
 
-/* If retSzp==NULL want exact size or fail */
+/* The size fetched (value output via retSzp) set when non-NULL return */
 static struct page *
 sg_page_malloc(int rqSz, int lowDma, int *retSzp)
 {
 	struct page *resp = NULL;
 	gfp_t page_mask;
 	int order, a_size;
-	int resSz = rqSz;
+	int resSz;
 
-	if (rqSz <= 0)
+	if ((rqSz <= 0) || (NULL == retSzp))
 		return resp;
 
 	if (lowDma)
@@ -2456,8 +2483,9 @@
 
 	for (order = 0, a_size = PAGE_SIZE; a_size < rqSz;
 	     order++, a_size <<= 1) ;
+	resSz = a_size;		/* rounded up if necessary */
 	resp = alloc_pages(page_mask, order);
-	while ((!resp) && order && retSzp) {
+	while ((!resp) && order) {
 		--order;
 		a_size >>= 1;	/* divide by 2, until PAGE_SIZE */
 		resp =  alloc_pages(page_mask, order);	/* try half */
@@ -2466,8 +2494,7 @@
 	if (resp) {
 		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 			memset(page_address(resp), 0, resSz);
-		if (retSzp)
-			*retSzp = resSz;
+		*retSzp = resSz;
 	}
 	return resp;
 }
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 4f1db6f..e81f97a 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -84,7 +84,7 @@
 	return value;
 }
 
-static irqreturn_t sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sgiwd93_intr(int irq, void *dev_id)
 {
 	struct Scsi_Host * host = (struct Scsi_Host *) dev_id;
 	unsigned long flags;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 7f669b6..3babdc7 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -195,9 +195,9 @@
 static int st_probe(struct device *);
 static int st_remove(struct device *);
 
-static void do_create_driverfs_files(void);
+static int do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
-static void do_create_class_files(struct scsi_tape *, int, int);
+static int do_create_class_files(struct scsi_tape *, int, int);
 
 static struct scsi_driver st_template = {
 	.owner			= THIS_MODULE,
@@ -4048,7 +4048,9 @@
 			STm->cdevs[j] = cdev;
 
 		}
-		do_create_class_files(tpnt, dev_num, mode);
+		error = do_create_class_files(tpnt, dev_num, mode);
+		if (error)
+			goto out_free_tape;
 	}
 
 	sdev_printk(KERN_WARNING, SDp,
@@ -4157,32 +4159,45 @@
 
 static int __init init_st(void)
 {
+	int err;
+
 	validate_options();
 
-	printk(KERN_INFO
-		"st: Version %s, fixed bufsize %d, s/g segs %d\n",
+	printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n",
 		verstr, st_fixed_buffer_size, st_max_sg_segs);
 
 	st_sysfs_class = class_create(THIS_MODULE, "scsi_tape");
 	if (IS_ERR(st_sysfs_class)) {
-		st_sysfs_class = NULL;
 		printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n");
-		return 1;
+		return PTR_ERR(st_sysfs_class);
 	}
 
-	if (!register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
-				    ST_MAX_TAPE_ENTRIES, "st")) {
-		if (scsi_register_driver(&st_template.gendrv) == 0) {
-			do_create_driverfs_files();
-			return 0;
-		}
-		unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
-					 ST_MAX_TAPE_ENTRIES);
+	err = register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
+				     ST_MAX_TAPE_ENTRIES, "st");
+	if (err) {
+		printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
+		       SCSI_TAPE_MAJOR);
+		goto err_class;
 	}
+
+	err = scsi_register_driver(&st_template.gendrv);
+	if (err)
+		goto err_chrdev;
+
+	err = do_create_driverfs_files();
+	if (err)
+		goto err_scsidrv;
+
+	return 0;
+
+err_scsidrv:
+	scsi_unregister_driver(&st_template.gendrv);
+err_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
+				 ST_MAX_TAPE_ENTRIES);
+err_class:
 	class_destroy(st_sysfs_class);
-
-	printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR);
-	return 1;
+	return err;
 }
 
 static void __exit exit_st(void)
@@ -4225,14 +4240,33 @@
 }
 static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
 
-static void do_create_driverfs_files(void)
+static int do_create_driverfs_files(void)
 {
 	struct device_driver *driverfs = &st_template.gendrv;
+	int err;
 
-	driver_create_file(driverfs, &driver_attr_try_direct_io);
-	driver_create_file(driverfs, &driver_attr_fixed_buffer_size);
-	driver_create_file(driverfs, &driver_attr_max_sg_segs);
-	driver_create_file(driverfs, &driver_attr_version);
+	err = driver_create_file(driverfs, &driver_attr_try_direct_io);
+	if (err)
+		return err;
+	err = driver_create_file(driverfs, &driver_attr_fixed_buffer_size);
+	if (err)
+		goto err_try_direct_io;
+	err = driver_create_file(driverfs, &driver_attr_max_sg_segs);
+	if (err)
+		goto err_attr_fixed_buf;
+	err = driver_create_file(driverfs, &driver_attr_version);
+	if (err)
+		goto err_attr_max_sg;
+
+	return 0;
+
+err_attr_max_sg:
+	driver_remove_file(driverfs, &driver_attr_max_sg_segs);
+err_attr_fixed_buf:
+	driver_remove_file(driverfs, &driver_attr_fixed_buffer_size);
+err_try_direct_io:
+	driver_remove_file(driverfs, &driver_attr_try_direct_io);
+	return err;
 }
 
 static void do_remove_driverfs_files(void)
@@ -4293,15 +4327,12 @@
 
 CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
 
-static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
 {
 	int i, rew, error;
 	char name[10];
 	struct class_device *st_class_member;
 
-	if (!st_sysfs_class)
-		return;
-
 	for (rew=0; rew < 2; rew++) {
 		/* Make sure that the minor numbers corresponding to the four
 		   first modes always get the same names */
@@ -4316,18 +4347,24 @@
 		if (IS_ERR(st_class_member)) {
 			printk(KERN_WARNING "st%d: class_device_create failed\n",
 			       dev_num);
+			error = PTR_ERR(st_class_member);
 			goto out;
 		}
 		class_set_devdata(st_class_member, &STp->modes[mode]);
 
-		class_device_create_file(st_class_member,
-					 &class_device_attr_defined);
-		class_device_create_file(st_class_member,
-					 &class_device_attr_default_blksize);
-		class_device_create_file(st_class_member,
-					 &class_device_attr_default_density);
-		class_device_create_file(st_class_member,
-					 &class_device_attr_default_compression);
+		error = class_device_create_file(st_class_member,
+					       &class_device_attr_defined);
+		if (error) goto out;
+		error = class_device_create_file(st_class_member,
+					    &class_device_attr_default_blksize);
+		if (error) goto out;
+		error = class_device_create_file(st_class_member,
+					    &class_device_attr_default_density);
+		if (error) goto out;
+		error = class_device_create_file(st_class_member,
+				        &class_device_attr_default_compression);
+		if (error) goto out;
+
 		if (mode == 0 && rew == 0) {
 			error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
 						  &st_class_member->kobj,
@@ -4336,11 +4373,15 @@
 				printk(KERN_ERR
 				       "st%d: Can't create sysfs link from SCSI device.\n",
 				       dev_num);
+				goto out;
 			}
 		}
 	}
- out:
-	return;
+
+	return 0;
+
+out:
+	return error;
 }
 
 /* The following functions may be useful for a larger audience. */
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 3cf3106..185c270 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -11,7 +11,7 @@
  *	Written By:
  *		Ed Lin <promise_linux@promise.com>
  *
- *	Version: 2.9.0.13
+ *	Version: 3.0.0.1
  *
  */
 
@@ -37,11 +37,11 @@
 #include <scsi/scsi_tcq.h>
 
 #define DRV_NAME "stex"
-#define ST_DRIVER_VERSION "2.9.0.13"
-#define ST_VER_MAJOR 		2
-#define ST_VER_MINOR 		9
+#define ST_DRIVER_VERSION "3.0.0.1"
+#define ST_VER_MAJOR 		3
+#define ST_VER_MINOR 		0
 #define ST_OEM 			0
-#define ST_BUILD_VER 		13
+#define ST_BUILD_VER 		1
 
 enum {
 	/* MU register offset */
@@ -120,12 +120,18 @@
 
 	st_shasta				= 0,
 	st_vsc					= 1,
+	st_yosemite				= 2,
 
 	PASSTHRU_REQ_TYPE			= 0x00000001,
 	PASSTHRU_REQ_NO_WAKEUP			= 0x00000100,
 	ST_INTERNAL_TIMEOUT			= 30,
 
+	ST_TO_CMD				= 0,
+	ST_FROM_CMD				= 1,
+
 	/* vendor specific commands of Promise */
+	MGT_CMD					= 0xd8,
+	SINBAND_MGT_CMD				= 0xd9,
 	ARRAY_CMD				= 0xe0,
 	CONTROLLER_CMD				= 0xe1,
 	DEBUGGING_CMD				= 0xe2,
@@ -133,14 +139,48 @@
 
 	PASSTHRU_GET_ADAPTER			= 0x05,
 	PASSTHRU_GET_DRVVER			= 0x10,
+
+	CTLR_CONFIG_CMD				= 0x03,
+	CTLR_SHUTDOWN				= 0x0d,
+
 	CTLR_POWER_STATE_CHANGE			= 0x0e,
 	CTLR_POWER_SAVING			= 0x01,
 
 	PASSTHRU_SIGNATURE			= 0x4e415041,
+	MGT_CMD_SIGNATURE			= 0xba,
 
 	INQUIRY_EVPD				= 0x01,
 };
 
+/* SCSI inquiry data */
+typedef struct st_inq {
+	u8 DeviceType			:5;
+	u8 DeviceTypeQualifier		:3;
+	u8 DeviceTypeModifier		:7;
+	u8 RemovableMedia		:1;
+	u8 Versions;
+	u8 ResponseDataFormat		:4;
+	u8 HiSupport			:1;
+	u8 NormACA			:1;
+	u8 ReservedBit			:1;
+	u8 AERC				:1;
+	u8 AdditionalLength;
+	u8 Reserved[2];
+	u8 SoftReset			:1;
+	u8 CommandQueue			:1;
+	u8 Reserved2			:1;
+	u8 LinkedCommands		:1;
+	u8 Synchronous			:1;
+	u8 Wide16Bit			:1;
+	u8 Wide32Bit			:1;
+	u8 RelativeAddressing		:1;
+	u8 VendorId[8];
+	u8 ProductId[16];
+	u8 ProductRevisionLevel[4];
+	u8 VendorSpecific[20];
+	u8 Reserved3[40];
+} ST_INQ;
+
 struct st_sgitem {
 	u8 ctrl;	/* SG_CF_xxx */
 	u8 reserved[3];
@@ -181,7 +221,7 @@
 	u8 task_attr;
 	u8 task_manage;
 	u8 prd_entry;
-	u8 payload_sz;		/* payload size in 4-byte */
+	u8 payload_sz;		/* payload size in 4-byte, not used */
 	u8 cdb[STEX_CDB_LENGTH];
 	u8 variable[REQ_VARIABLE_LEN];
 };
@@ -242,7 +282,8 @@
 #define MU_REQ_BUFFER_SIZE	(MU_REQ_COUNT * sizeof(struct req_msg))
 #define MU_STATUS_BUFFER_SIZE	(MU_STATUS_COUNT * sizeof(struct status_msg))
 #define MU_BUFFER_SIZE		(MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE)
-#define STEX_BUFFER_SIZE	(MU_BUFFER_SIZE + sizeof(struct st_frame))
+#define STEX_EXTRA_SIZE		max(sizeof(struct st_frame), sizeof(ST_INQ))
+#define STEX_BUFFER_SIZE	(MU_BUFFER_SIZE + STEX_EXTRA_SIZE)
 
 struct st_ccb {
 	struct req_msg *req;
@@ -403,7 +444,7 @@
 }
 
 static void stex_internal_copy(struct scsi_cmnd *cmd,
-	const void *src, size_t *count, int sg_count)
+	const void *src, size_t *count, int sg_count, int direction)
 {
 	size_t lcount;
 	size_t len;
@@ -427,7 +468,10 @@
 		} else
 			d = cmd->request_buffer;
 
-		memcpy(d, s, len);
+		if (direction == ST_TO_CMD)
+			memcpy(d, s, len);
+		else
+			memcpy(s, d, len);
 
 		lcount -= len;
 		if (cmd->use_sg)
@@ -449,7 +493,7 @@
 			return 0;
 	}
 
-	stex_internal_copy(cmd, src, &cp_len, n_elem);
+	stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
 
 	if (cmd->use_sg)
 		pci_unmap_sg(hba->pdev, cmd->request_buffer,
@@ -480,7 +524,7 @@
 	p->subid =
 		hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
 
-	stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count);
+	stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_TO_CMD);
 }
 
 static void
@@ -489,7 +533,6 @@
 	req->tag = cpu_to_le16(tag);
 	req->task_attr = TASK_ATTRIBUTE_SIMPLE;
 	req->task_manage = 0; /* not supported yet */
-	req->payload_sz = (u8)(sizeof(struct req_msg)/sizeof(u32));
 
 	hba->ccb[tag].req = req;
 	hba->out_req_cnt++;
@@ -595,8 +638,14 @@
 		return SCSI_MLQUEUE_HOST_BUSY;
 
 	req = stex_alloc_req(hba);
-	req->lun = lun;
-	req->target = id;
+
+	if (hba->cardtype == st_yosemite) {
+		req->lun = lun * (ST_MAX_TARGET_NUM - 1) + id;
+		req->target = 0;
+	} else {
+		req->lun = lun;
+		req->target = id;
+	}
 
 	/* cdb */
 	memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
@@ -680,7 +729,51 @@
 
 	if (ccb->cmd == NULL)
 		return;
-	stex_internal_copy(ccb->cmd, resp->variable, &count, ccb->sg_count);
+	stex_internal_copy(ccb->cmd,
+		resp->variable, &count, ccb->sg_count, ST_TO_CMD);
+}
+
+static void stex_ys_commands(struct st_hba *hba,
+	struct st_ccb *ccb, struct status_msg *resp)
+{
+	size_t count;
+
+	if (ccb->cmd->cmnd[0] == MGT_CMD &&
+		resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
+		ccb->cmd->request_bufflen =
+			le32_to_cpu(*(__le32 *)&resp->variable[0]);
+		return;
+	}
+
+	if (resp->srb_status != 0)
+		return;
+
+	/* determine inquiry command status by DeviceTypeQualifier */
+	if (ccb->cmd->cmnd[0] == INQUIRY &&
+		resp->scsi_status == SAM_STAT_GOOD) {
+		ST_INQ *inq_data;
+
+		count = STEX_EXTRA_SIZE;
+		stex_internal_copy(ccb->cmd, hba->copy_buffer,
+			&count, ccb->sg_count, ST_FROM_CMD);
+		inq_data = (ST_INQ *)hba->copy_buffer;
+		if (inq_data->DeviceTypeQualifier != 0)
+			ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
+		else
+			ccb->srb_status = SRB_STATUS_SUCCESS;
+	} else if (ccb->cmd->cmnd[0] == REPORT_LUNS) {
+		u8 *report_lun_data = (u8 *)hba->copy_buffer;
+
+		count = STEX_EXTRA_SIZE;
+		stex_internal_copy(ccb->cmd, report_lun_data,
+			&count, ccb->sg_count, ST_FROM_CMD);
+		if (report_lun_data[2] || report_lun_data[3]) {
+			report_lun_data[2] = 0x00;
+			report_lun_data[3] = 0x08;
+			stex_internal_copy(ccb->cmd, report_lun_data,
+				&count, ccb->sg_count, ST_TO_CMD);
+		}
+	}
 }
 
 static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
@@ -702,8 +795,17 @@
 		return;
 	}
 
-	if (unlikely(hba->mu_status != MU_STATE_STARTED ||
-		hba->out_req_cnt <= 0)) {
+	/*
+	 * it's not a valid status payload if:
+	 * 1. there are no pending requests(e.g. during init stage)
+	 * 2. there are some pending requests, but the controller is in
+	 *     reset status, and its type is not st_yosemite
+	 * firmware of st_yosemite in reset status will return pending requests
+	 * to driver, so we allow it to pass
+	 */
+	if (unlikely(hba->out_req_cnt <= 0 ||
+			(hba->mu_status == MU_STATE_RESETTING &&
+			 hba->cardtype != st_yosemite))) {
 		hba->status_tail = hba->status_head;
 		goto update_status;
 	}
@@ -723,6 +825,7 @@
 		if (unlikely(ccb->req == NULL)) {
 			printk(KERN_WARNING DRV_NAME
 				"(%s): lagging req\n", pci_name(hba->pdev));
+			hba->out_req_cnt--;
 			continue;
 		}
 
@@ -741,9 +844,13 @@
 		ccb->scsi_status = resp->scsi_status;
 
 		if (likely(ccb->cmd != NULL)) {
+			if (hba->cardtype == st_yosemite)
+				stex_ys_commands(hba, ccb, resp);
+
 			if (unlikely(ccb->cmd->cmnd[0] == PASSTHRU_CMD &&
 				ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
 				stex_controller_info(hba, ccb);
+
 			stex_unmap_sg(hba, ccb->cmd);
 			stex_scsi_done(ccb);
 			hba->out_req_cnt--;
@@ -764,7 +871,7 @@
 	readl(base + IMR1); /* flush */
 }
 
-static irqreturn_t stex_intr(int irq, void *__hba, struct pt_regs *regs)
+static irqreturn_t stex_intr(int irq, void *__hba)
 {
 	struct st_hba *hba = __hba;
 	void __iomem *base = hba->mmio_base;
@@ -948,6 +1055,7 @@
 {
 	struct st_hba *hba;
 	unsigned long flags;
+	unsigned long before;
 	hba = (struct st_hba *) &cmd->device->host->hostdata[0];
 
 	hba->mu_status = MU_STATE_RESETTING;
@@ -955,20 +1063,37 @@
 	if (hba->cardtype == st_shasta)
 		stex_hard_reset(hba);
 
-	if (stex_handshake(hba)) {
-		printk(KERN_WARNING DRV_NAME
-			"(%s): resetting: handshake failed\n",
-			pci_name(hba->pdev));
-		return FAILED;
+	if (hba->cardtype != st_yosemite) {
+		if (stex_handshake(hba)) {
+			printk(KERN_WARNING DRV_NAME
+				"(%s): resetting: handshake failed\n",
+				pci_name(hba->pdev));
+			return FAILED;
+		}
+		spin_lock_irqsave(hba->host->host_lock, flags);
+		hba->req_head = 0;
+		hba->req_tail = 0;
+		hba->status_head = 0;
+		hba->status_tail = 0;
+		hba->out_req_cnt = 0;
+		spin_unlock_irqrestore(hba->host->host_lock, flags);
+		return SUCCESS;
 	}
-	spin_lock_irqsave(hba->host->host_lock, flags);
-	hba->req_head = 0;
-	hba->req_tail = 0;
-	hba->status_head = 0;
-	hba->status_tail = 0;
-	hba->out_req_cnt = 0;
-	spin_unlock_irqrestore(hba->host->host_lock, flags);
 
+	/* st_yosemite */
+	writel(MU_INBOUND_DOORBELL_RESET, hba->mmio_base + IDBL);
+	readl(hba->mmio_base + IDBL); /* flush */
+	before = jiffies;
+	while (hba->out_req_cnt > 0) {
+		if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) {
+			printk(KERN_WARNING DRV_NAME
+				"(%s): reset timeout\n", pci_name(hba->pdev));
+			return FAILED;
+		}
+		msleep(1);
+	}
+
+	hba->mu_status = MU_STATE_STARTED;
 	return SUCCESS;
 }
 
@@ -1156,9 +1281,16 @@
 	req = stex_alloc_req(hba);
 	memset(req->cdb, 0, STEX_CDB_LENGTH);
 
-	req->cdb[0] = CONTROLLER_CMD;
-	req->cdb[1] = CTLR_POWER_STATE_CHANGE;
-	req->cdb[2] = CTLR_POWER_SAVING;
+	if (hba->cardtype == st_yosemite) {
+		req->cdb[0] = MGT_CMD;
+		req->cdb[1] = MGT_CMD_SIGNATURE;
+		req->cdb[2] = CTLR_CONFIG_CMD;
+		req->cdb[3] = CTLR_SHUTDOWN;
+	} else {
+		req->cdb[0] = CONTROLLER_CMD;
+		req->cdb[1] = CTLR_POWER_STATE_CHANGE;
+		req->cdb[2] = CTLR_POWER_SAVING;
+	}
 
 	hba->ccb[tag].cmd = NULL;
 	hba->ccb[tag].sg_count = 0;
@@ -1222,6 +1354,7 @@
 	{ 0x105a, 0x8301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
 	{ 0x105a, 0x8302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
 	{ 0x1725, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc },
+	{ 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite },
 	{ }	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, stex_pci_tbl);
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 7f9bcef..5ec5af8 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -1252,7 +1252,7 @@
  *
  */
 
-static irqreturn_t NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t NCR5380_intr (int irq, void *dev_id)
 {
     struct Scsi_Host *instance = first_instance;
     int done = 1, handled = 0;
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 44a99ae..e625b4c 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -102,7 +102,7 @@
 #define	ENABLE_IRQ()	enable_irq( IRQ_SUN3_SCSI ); 
 
 
-static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
 static inline unsigned char sun3scsi_read(int reg);
 static inline void sun3scsi_write(int reg, int value);
 
@@ -371,7 +371,7 @@
 // safe bits for the CSR
 #define CSR_GOOD 0x060f
 
-static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
 {
 	unsigned short csr = dregs->csr;
 	int handled = 0;
@@ -388,7 +388,7 @@
 	}
 
 	if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
-		NCR5380_intr(irq, dummy, fp);
+		NCR5380_intr(irq, dummy);
 		handled = 1;
 	}
 
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
index f5742b8..e8faab1 100644
--- a/drivers/scsi/sun3_scsi_vme.c
+++ b/drivers/scsi/sun3_scsi_vme.c
@@ -67,7 +67,7 @@
 #define ENABLE_IRQ()
 
 
-static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
 static inline unsigned char sun3scsi_read(int reg);
 static inline void sun3scsi_write(int reg, int value);
 
@@ -340,7 +340,7 @@
 // safe bits for the CSR
 #define CSR_GOOD 0x060f
 
-static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
 {
 	unsigned short csr = dregs->csr;
 	int handled = 0;
@@ -371,7 +371,7 @@
 	}
 
 	if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
-		NCR5380_intr(irq, dummy, fp);
+		NCR5380_intr(irq, dummy);
 		handled = 1;
 	}
 
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index 8640253..32c883f 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -326,8 +326,7 @@
 	return orig_len - len;
 }
 
-static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id)
 {
 	struct Scsi_Host *dev = dev_id;
 	int base = 0;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 739d3ef..4d78c7e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -652,7 +652,7 @@
 /*
  *  Linux entry point of the interrupt handler.
  */
-static irqreturn_t sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t sym53c8xx_intr(int irq, void *dev_id)
 {
 	unsigned long flags;
 	struct sym_hcb *np = (struct sym_hcb *)dev_id;
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index 2df6747..0b7a70f 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -109,7 +109,7 @@
 #include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/stat.h>
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 9404ff3..d03aa6c 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -279,6 +279,10 @@
 static u32	dc390_laststatus = 0;
 static u8	dc390_adapterCnt = 0;
 
+static int disable_clustering;
+module_param(disable_clustering, int, S_IRUGO);
+MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
+
 /* Startup values, to be overriden on the commandline */
 static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
 
@@ -696,9 +700,9 @@
 
 
 static irqreturn_t __inline__
-DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs)
+DC390_Interrupt(void *dev_id)
 {
-    struct dc390_acb *pACB = (struct dc390_acb*)dev_id;
+    struct dc390_acb *pACB = dev_id;
     struct dc390_dcb *pDCB;
     struct dc390_srb *pSRB;
     u8  sstatus=0;
@@ -807,12 +811,12 @@
     return IRQ_HANDLED;
 }
 
-static irqreturn_t do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
 {
     irqreturn_t ret;
     DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
     /* Locking is done in DC390_Interrupt */
-    ret = DC390_Interrupt(irq, dev_id, regs);
+    ret = DC390_Interrupt(dev_id);
     DEBUG1(printk (".. IRQ returned\n"));
     return ret;
 }
@@ -2299,7 +2303,7 @@
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
 	.cmd_per_lun		= 1,
-	.use_clustering		= DISABLE_CLUSTERING,
+	.use_clustering		= ENABLE_CLUSTERING,
 };
 
 /***********************************************************************
@@ -2525,6 +2529,8 @@
 	pci_set_master(pdev);
 
 	error = -ENOMEM;
+	if (disable_clustering)
+		driver_template.use_clustering = DISABLE_CLUSTERING;
 	shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
 	if (!shost)
 		goto out_disable_device;
@@ -2660,6 +2666,10 @@
 
 static int __init dc390_module_init(void)
 {
+	if (!disable_clustering)
+		printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n"
+		       "\twith \"disable_clustering=1\" and report to maintainers\n");
+
 	if (tmscsim[0] == -1 || tmscsim[0] > 15) {
 		tmscsim[0] = 7;
 		tmscsim[1] = 4;
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 5744961..3de08a1 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -634,7 +634,7 @@
 #define H2DEV(x) cpu_to_le32(x)
 #define DEV2H(x) le32_to_cpu(x)
 
-static irqreturn_t do_interrupt_handler(int, void *, struct pt_regs *);
+static irqreturn_t do_interrupt_handler(int, void *);
 static void flush_dev(struct scsi_device *, unsigned long, unsigned int, unsigned int);
 static int do_trace = FALSE;
 static int setup_done = FALSE;
@@ -1932,8 +1932,7 @@
    return IRQ_NONE;
 }
 
-static irqreturn_t do_interrupt_handler(int irq, void *shap,
-                                        struct pt_regs *regs) {
+static irqreturn_t do_interrupt_handler(int irq, void *shap) {
    unsigned int j;
    unsigned long spin_flags;
    irqreturn_t ret;
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 0372aa9..56906ab 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -287,8 +287,8 @@
 };
 #endif
 
-static void ultrastor_interrupt(int, void *, struct pt_regs *);
-static irqreturn_t do_ultrastor_interrupt(int, void *, struct pt_regs *);
+static void ultrastor_interrupt(void *);
+static irqreturn_t do_ultrastor_interrupt(int, void *);
 static inline void build_sg_list(struct mscp *, struct scsi_cmnd *SCpnt);
 
 
@@ -893,7 +893,7 @@
 	
 	spin_lock_irqsave(host->host_lock, flags);
 	/* FIXME: Ewww... need to think about passing host around properly */
-	ultrastor_interrupt(0, NULL, NULL);
+	ultrastor_interrupt(NULL);
 	spin_unlock_irqrestore(host->host_lock, flags);
 	return SUCCESS;
       }
@@ -1039,7 +1039,7 @@
     return 0;
 }
 
-static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void ultrastor_interrupt(void *dev_id)
 {
     unsigned int status;
 #if ULTRASTOR_MAX_CMDS > 1
@@ -1171,14 +1171,13 @@
 #endif
 }
 
-static irqreturn_t do_ultrastor_interrupt(int irq, void *dev_id,
-						struct pt_regs *regs)
+static irqreturn_t do_ultrastor_interrupt(int irq, void *dev_id)
 {
     unsigned long flags;
     struct Scsi_Host *dev = dev_id;
     
     spin_lock_irqsave(dev->host_lock, flags);
-    ultrastor_interrupt(irq, dev_id, regs);
+    ultrastor_interrupt(dev_id);
     spin_unlock_irqrestore(dev->host_lock, flags);
     return IRQ_HANDLED;
 }
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index a0b61af..30be765 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -178,10 +178,10 @@
 #include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/stat.h>
+#include <linux/io.h>
 
 #include <asm/system.h>
 #include <asm/dma.h>
-#include <asm/io.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -998,7 +998,7 @@
 #define wd7000_intr_ack(host)   outb (0, host->iobase + ASC_INTR_ACK)
 
 
-static irqreturn_t wd7000_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t wd7000_intr(int irq, void *dev_id)
 {
 	Adapter *host = (Adapter *) dev_id;
 	int flag, icmb, errstatus, icmb_status;
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 76d83ad..6a1a568 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -85,7 +85,7 @@
 {
 }
 
-static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct tty_struct *tty = port->info->tty;
@@ -123,7 +123,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct circ_buf *xmit = &port->info->xmit;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index bac853c..9b8b585 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -275,8 +275,7 @@
 	return;
 }
 
-static void receive_chars(struct m68k_serial *info, struct pt_regs *regs,
-			  unsigned short rx)
+static void receive_chars(struct m68k_serial *info, unsigned short rx)
 {
 	struct tty_struct *tty = info->tty;
 	m68328_uart *uart = &uart_addr[info->line];
@@ -377,7 +376,7 @@
 /*
  * This is the serial driver's generic interrupt routine
  */
-irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t rs_interrupt(int irq, void *dev_id)
 {
 	struct m68k_serial * info;
 	m68328_uart *uart;
@@ -394,10 +393,10 @@
 #ifdef USE_INTS
 	tx = uart->utx.w;
 
-	if (rx & URX_DATA_READY) receive_chars(info, regs, rx);
+	if (rx & URX_DATA_READY) receive_chars(info, rx);
 	if (tx & UTX_TX_AVAIL)   transmit_chars(info);
 #else
-	receive_chars(info, regs, rx);		
+	receive_chars(info, rx);		
 #endif
 	return IRQ_HANDLED;
 }
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 1b299e8..634ecca 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -612,7 +612,7 @@
  * This is the serial driver's interrupt routine for a single port
  */
 /* static void rs_360_interrupt(void *dev_id) */ /* until and if we start servicing irqs here */
-static void rs_360_interrupt(int vec, void *dev_id, struct pt_regs *fp)
+static void rs_360_interrupt(int vec, void *dev_id)
 {
 	u_char	events;
 	int	idx;
@@ -620,7 +620,7 @@
 	volatile struct smc_regs *smcp;
 	volatile struct scc_regs *sccp;
 	
-	info = (ser_info_t *)dev_id;
+	info = dev_id;
 
 	idx = PORT_NUM(info->state->smc_scc_num);
 	if (info->state->smc_scc_num & NUM_IS_SCC) {
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index cc2a205..e34bd03 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1175,7 +1175,7 @@
 }
 
 static void
-receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
+receive_chars(struct uart_8250_port *up, int *status)
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned char ch, lsr = *status;
@@ -1233,7 +1233,7 @@
 			else if (lsr & UART_LSR_FE)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			goto ignore_char;
 
 		uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
@@ -1309,7 +1309,7 @@
  * This handles the interrupt from one port.
  */
 static inline void
-serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
+serial8250_handle_port(struct uart_8250_port *up)
 {
 	unsigned int status;
 
@@ -1320,7 +1320,7 @@
 	DEBUG_INTR("status = %x...", status);
 
 	if (status & UART_LSR_DR)
-		receive_chars(up, &status, regs);
+		receive_chars(up, &status);
 	check_modem_status(up);
 	if (status & UART_LSR_THRE)
 		transmit_chars(up);
@@ -1342,7 +1342,7 @@
  * This means we need to loop through all ports. checking that they
  * don't have an interrupt pending.
  */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 {
 	struct irq_info *i = dev_id;
 	struct list_head *l, *end = NULL;
@@ -1361,7 +1361,7 @@
 
 		iir = serial_in(up, UART_IIR);
 		if (!(iir & UART_IIR_NO_INT)) {
-			serial8250_handle_port(up, regs);
+			serial8250_handle_port(up);
 
 			handled = 1;
 
@@ -1461,7 +1461,7 @@
 
 	iir = serial_in(up, UART_IIR);
 	if (!(iir & UART_IIR_NO_INT))
-		serial8250_handle_port(up, NULL);
+		serial8250_handle_port(up);
 
 	timeout = up->port.timeout;
 	timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b0d5026..0b71e7d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -767,37 +767,37 @@
 	bool "Support for SCC1 serial port"
 	depends on SERIAL_CPM=y
 	help
-	  Select the is option to use SCC1 as a serial port
+	  Select this option to use SCC1 as a serial port
 
 config SERIAL_CPM_SCC2
 	bool "Support for SCC2 serial port"
 	depends on SERIAL_CPM=y
 	help
-	  Select the is option to use SCC2 as a serial port
+	  Select this option to use SCC2 as a serial port
 
 config SERIAL_CPM_SCC3
 	bool "Support for SCC3 serial port"
 	depends on SERIAL_CPM=y
 	help
-	  Select the is option to use SCC3 as a serial port
+	  Select this option to use SCC3 as a serial port
 
 config SERIAL_CPM_SCC4
 	bool "Support for SCC4 serial port"
 	depends on SERIAL_CPM=y
 	help
-	  Select the is option to use SCC4 as a serial port
+	  Select this option to use SCC4 as a serial port
 
 config SERIAL_CPM_SMC1
 	bool "Support for SMC1 serial port"
 	depends on SERIAL_CPM=y
 	help
-	  Select the is option to use SMC1 as a serial port
+	  Select this option to use SMC1 as a serial port
 
 config SERIAL_CPM_SMC2
 	bool "Support for SMC2 serial port"
 	depends on SERIAL_CPM=y
 	help
-	  Select the is option to use SMC2 as a serial port
+	  Select this option to use SMC2 as a serial port
 
 config SERIAL_SGI_L1_CONSOLE
 	bool "SGI Altix L1 serial console support"
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 7311d84..4213fab 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -111,12 +111,7 @@
 	writel(cr, port->membase + UART010_CR);
 }
 
-static void
-#ifdef SUPPORT_SYSRQ
-pl010_rx_chars(struct uart_port *port, struct pt_regs *regs)
-#else
-pl010_rx_chars(struct uart_port *port)
-#endif
+static void pl010_rx_chars(struct uart_port *port)
 {
 	struct tty_struct *tty = port->info->tty;
 	unsigned int status, ch, flag, rsr, max_count = 256;
@@ -156,7 +151,7 @@
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(port, ch, regs))
+		if (uart_handle_sysrq_char(port, ch))
 			goto ignore_char;
 
 		uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
@@ -227,7 +222,7 @@
 	wake_up_interruptible(&uap->port.info->delta_msr_wait);
 }
 
-static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pl010_int(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
@@ -239,11 +234,7 @@
 	if (status) {
 		do {
 			if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
-#ifdef SUPPORT_SYSRQ
-				pl010_rx_chars(port, regs);
-#else
 				pl010_rx_chars(port);
-#endif
 			if (status & UART010_IIR_MIS)
 				pl010_modem_status(port);
 			if (status & UART010_IIR_TIS)
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index a8d7124..d503625 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -107,12 +107,7 @@
 	writew(uap->im, uap->port.membase + UART011_IMSC);
 }
 
-static void
-#ifdef SUPPORT_SYSRQ
-pl011_rx_chars(struct uart_amba_port *uap, struct pt_regs *regs)
-#else
-pl011_rx_chars(struct uart_amba_port *uap)
-#endif
+static void pl011_rx_chars(struct uart_amba_port *uap)
 {
 	struct tty_struct *tty = uap->port.info->tty;
 	unsigned int status, ch, flag, max_count = 256;
@@ -150,7 +145,7 @@
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(&uap->port, ch & 255, regs))
+		if (uart_handle_sysrq_char(&uap->port, ch & 255))
 			goto ignore_char;
 
 		uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
@@ -218,7 +213,7 @@
 	wake_up_interruptible(&uap->port.info->delta_msr_wait);
 }
 
-static irqreturn_t pl011_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pl011_int(int irq, void *dev_id)
 {
 	struct uart_amba_port *uap = dev_id;
 	unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
@@ -234,11 +229,7 @@
 			       uap->port.membase + UART011_ICR);
 
 			if (status & (UART011_RTIS|UART011_RXIS))
-#ifdef SUPPORT_SYSRQ
-				pl011_rx_chars(uap, regs);
-#else
 				pl011_rx_chars(uap);
-#endif
 			if (status & (UART011_DSRMIS|UART011_DCDMIS|
 				      UART011_CTSMIS|UART011_RIMIS))
 				pl011_modem_status(uap);
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 955c46d..391a1f4 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -249,7 +249,7 @@
 /*
  * Characters received (called from interrupt handler)
  */
-static void atmel_rx_chars(struct uart_port *port, struct pt_regs *regs)
+static void atmel_rx_chars(struct uart_port *port)
 {
 	struct tty_struct *tty = port->info->tty;
 	unsigned int status, ch, flg;
@@ -291,7 +291,7 @@
 				flg = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(port, ch, regs))
+		if (uart_handle_sysrq_char(port, ch))
 			goto ignore_char;
 
 		uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg);
@@ -339,7 +339,7 @@
 /*
  * Interrupt handler
  */
-static irqreturn_t atmel_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
@@ -350,7 +350,7 @@
 	while (pending) {
 		/* Interrupt receive */
 		if (pending & ATMEL_US_RXRDY)
-			atmel_rx_chars(port, regs);
+			atmel_rx_chars(port);
 
 		// TODO: All reads to CSR will clear these interrupts!
 		if (pending & ATMEL_US_RIIC) port->icount.rng++;
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index f27d852..5980127 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -93,7 +93,7 @@
 {
 }
 
-static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct tty_struct *tty = port->info->tty;
@@ -131,7 +131,7 @@
 #endif
 		}
 
-		if (uart_handle_sysrq_char(port, ch, regs))
+		if (uart_handle_sysrq_char(port, ch))
 			goto ignore_char;
 
 		/*
@@ -147,7 +147,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct circ_buf *xmit = &port->info->xmit;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index a0d6136..0abb544 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -248,7 +248,7 @@
 /*
  * Transmit characters, refill buffer descriptor, if possible
  */
-static void cpm_uart_int_tx(struct uart_port *port, struct pt_regs *regs)
+static void cpm_uart_int_tx(struct uart_port *port)
 {
 	pr_debug("CPM uart[%d]:TX INT\n", port->line);
 
@@ -258,7 +258,7 @@
 /*
  * Receive characters
  */
-static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
+static void cpm_uart_int_rx(struct uart_port *port)
 {
 	int i;
 	unsigned char ch, *cp;
@@ -304,7 +304,7 @@
 			if (status &
 			    (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
 				goto handle_error;
-			if (uart_handle_sysrq_char(port, ch, regs))
+			if (uart_handle_sysrq_char(port, ch))
 				continue;
 
 		      error_return:
@@ -373,7 +373,7 @@
 /*
  * Asynchron mode interrupt handler
  */
-static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t cpm_uart_int(int irq, void *data)
 {
 	u8 events;
 	struct uart_port *port = (struct uart_port *)data;
@@ -389,18 +389,18 @@
 		if (events & SMCM_BRKE)
 			uart_handle_break(port);
 		if (events & SMCM_RX)
-			cpm_uart_int_rx(port, regs);
+			cpm_uart_int_rx(port);
 		if (events & SMCM_TX)
-			cpm_uart_int_tx(port, regs);
+			cpm_uart_int_tx(port);
 	} else {
 		events = sccp->scc_scce;
 		sccp->scc_scce = events;
 		if (events & UART_SCCM_BRKE)
 			uart_handle_break(port);
 		if (events & UART_SCCM_RX)
-			cpm_uart_int_rx(port, regs);
+			cpm_uart_int_rx(port);
 		if (events & UART_SCCM_TX)
-			cpm_uart_int_tx(port, regs);
+			cpm_uart_int_tx(port);
 	}
 	return (events) ? IRQ_HANDLED : IRQ_NONE;
 }
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 9851d9e..7a24e53 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -2346,7 +2346,7 @@
 */
 
 static irqreturn_t
-tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+tr_interrupt(int irq, void *dev_id)
 {
 	struct e100_serial *info;
 	unsigned long ireg;
@@ -2395,7 +2395,7 @@
 /* dma input channel interrupt handler */
 
 static irqreturn_t
-rec_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+rec_interrupt(int irq, void *dev_id)
 {
 	struct e100_serial *info;
 	unsigned long ireg;
@@ -3054,7 +3054,7 @@
  * ser_int duration: just sending: 8-15 us normally, up to 73 us
  */
 static irqreturn_t
-ser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ser_interrupt(int irq, void *dev_id)
 {
 	static volatile int tx_started = 0;
 	struct e100_serial *info;
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 8a98aae..53662b3 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -339,7 +339,7 @@
  * It deals with the multiple ports.
  * ------------------------------------------------------------
  */
-static irqreturn_t dz_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t dz_interrupt(int irq, void *dev)
 {
 	struct dz_port *dport;
 	unsigned short status;
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index a3c00a2..8aa0f641 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -844,8 +844,7 @@
 	spin_unlock(&icom_port->uart_port.lock);
 }
 
-static irqreturn_t icom_interrupt(int irq, void *dev_id,
-				  struct pt_regs *regs)
+static irqreturn_t icom_interrupt(int irq, void *dev_id)
 {
 	void __iomem * int_reg;
 	u32 adapter_interrupts;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 4a142d6..ee5c782 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -182,7 +182,7 @@
 		imx_transmit_buffer(sport);
 }
 
-static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t imx_rtsint(int irq, void *dev_id)
 {
 	struct imx_port *sport = (struct imx_port *)dev_id;
 	unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS;
@@ -198,7 +198,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t imx_txint(int irq, void *dev_id)
 {
 	struct imx_port *sport = (struct imx_port *)dev_id;
 	struct circ_buf *xmit = &sport->port.info->xmit;
@@ -227,7 +227,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t imx_rxint(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
 	unsigned int rx,flg,ignored = 0;
@@ -248,7 +248,7 @@
 		}
 
 		if (uart_handle_sysrq_char
-		            (&sport->port, (unsigned char)rx, regs))
+		            (&sport->port, (unsigned char)rx))
 			goto ignore_char;
 
 		if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
index 8097cd9..2308d26 100644
--- a/drivers/serial/ioc3_serial.c
+++ b/drivers/serial/ioc3_serial.c
@@ -1428,13 +1428,12 @@
  * @is : submodule
  * @idd: driver data
  * @pending: interrupts to handle
- * @regs: pt_regs
  */
 
 static int inline
 ioc3uart_intr_one(struct ioc3_submodule *is,
 			struct ioc3_driver_data *idd,
-			unsigned int pending, struct pt_regs *regs)
+			unsigned int pending)
 {
 	int port_num = GET_PORT_FROM_SIO_IR(pending);
 	struct port_hooks *hooks;
@@ -1628,13 +1627,12 @@
  * @is : submodule
  * @idd: driver data
  * @pending: interrupts to handle
- * @regs: pt_regs
  *
  */
 
 static int ioc3uart_intr(struct ioc3_submodule *is,
 			struct ioc3_driver_data *idd,
-			unsigned int pending, struct pt_regs *regs)
+			unsigned int pending)
 {
 	int ret = 0;
 
@@ -1644,9 +1642,9 @@
 	 */
 
 	if (pending & SIO_IR_SA)
-		ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs);
+		ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA);
 	if (pending & SIO_IR_SB)
-		ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs);
+		ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB);
 
 	return ret;
 }
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 5ec4716..ff4fa25 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -987,10 +987,9 @@
  * ioc4_intr - Top level IOC4 interrupt handler.
  * @irq: irq value
  * @arg: handler arg
- * @regs: registers
  */
 
-static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t ioc4_intr(int irq, void *arg)
 {
 	struct ioc4_soft *soft;
 	uint32_t this_ir, this_mir;
@@ -2936,7 +2935,7 @@
 	uart_unregister_driver(&ioc4_uart_rs422);
 }
 
-module_init(ioc4_serial_init);
+late_initcall(ioc4_serial_init); /* Call only after tty init is done */
 module_exit(ioc4_serial_exit);
 
 MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index dbf13c0..dca6c1b 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -252,8 +252,7 @@
 }
 
 static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
-				   struct zilog_channel *channel,
-				   struct pt_regs *regs)
+				   struct zilog_channel *channel)
 {
 	struct tty_struct *tty = up->port.info->tty;	/* XXX info==NULL? */
 
@@ -319,7 +318,7 @@
 			else if (r1 & CRC_ERR)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			goto next_char;
 
 		if (up->port.ignore_status_mask == 0xff ||
@@ -339,8 +338,7 @@
 }
 
 static void ip22zilog_status_handle(struct uart_ip22zilog_port *up,
-				   struct zilog_channel *channel,
-				   struct pt_regs *regs)
+				   struct zilog_channel *channel)
 {
 	unsigned char status;
 
@@ -443,7 +441,7 @@
 	ZS_WSYNC(channel);
 }
 
-static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id)
 {
 	struct uart_ip22zilog_port *up = dev_id;
 
@@ -462,9 +460,9 @@
 			ZS_WSYNC(channel);
 
 			if (r3 & CHARxIP)
-				ip22zilog_receive_chars(up, channel, regs);
+				ip22zilog_receive_chars(up, channel);
 			if (r3 & CHAEXT)
-				ip22zilog_status_handle(up, channel, regs);
+				ip22zilog_status_handle(up, channel);
 			if (r3 & CHATxIP)
 				ip22zilog_transmit_chars(up, channel);
 		}
@@ -481,9 +479,9 @@
 			ZS_WSYNC(channel);
 
 			if (r3 & CHBRxIP)
-				ip22zilog_receive_chars(up, channel, regs);
+				ip22zilog_receive_chars(up, channel);
 			if (r3 & CHBEXT)
-				ip22zilog_status_handle(up, channel, regs);
+				ip22zilog_status_handle(up, channel);
 			if (r3 & CHBTxIP)
 				ip22zilog_transmit_chars(up, channel);
 		}
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index 043f50b..12c934a 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -99,7 +99,7 @@
  * Per board operations structure					*
  ************************************************************************/
 struct board_ops {
-	irqreturn_t (*intr) (int irq, void *voidbrd, struct pt_regs *regs);
+	irq_handler_t intr;
 	void (*uart_init) (struct jsm_channel *ch);
 	void (*uart_off) (struct jsm_channel *ch);
 	void (*param) (struct jsm_channel *ch);
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index a5fc589..8be8da3 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -1114,9 +1114,9 @@
  *
  * Neo specific interrupt handler.
  */
-static irqreturn_t neo_intr(int irq, void *voidbrd, struct pt_regs *regs)
+static irqreturn_t neo_intr(int irq, void *voidbrd)
 {
-	struct jsm_board *brd = (struct jsm_board *) voidbrd;
+	struct jsm_board *brd = voidbrd;
 	struct jsm_channel *ch;
 	int port = 0;
 	int type = 0;
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 28c9ce6..7656a35 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -323,8 +323,7 @@
 	serial_out(up, UART_IER, up->ier);
 }
 
-static void receive_chars(struct uart_sio_port *up, int *status,
-			  struct pt_regs *regs)
+static void receive_chars(struct uart_sio_port *up, int *status)
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned char ch;
@@ -378,7 +377,7 @@
 			else if (*status & UART_LSR_FE)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			goto ignore_char;
 		if ((*status & up->port.ignore_status_mask) == 0)
 			tty_insert_flip_char(tty, ch, flag);
@@ -439,12 +438,12 @@
  * This handles the interrupt from one port.
  */
 static inline void m32r_sio_handle_port(struct uart_sio_port *up,
-	unsigned int status, struct pt_regs *regs)
+	unsigned int status)
 {
 	DEBUG_INTR("status = %x...", status);
 
 	if (status & 0x04)
-		receive_chars(up, &status, regs);
+		receive_chars(up, &status);
 	if (status & 0x01)
 		transmit_chars(up);
 }
@@ -463,8 +462,7 @@
  * This means we need to loop through all ports. checking that they
  * don't have an interrupt pending.
  */
-static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id,
-	struct pt_regs *regs)
+static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id)
 {
 	struct irq_info *i = dev_id;
 	struct list_head *l, *end = NULL;
@@ -492,7 +490,7 @@
 		sts = sio_in(up, SIOSTS);
 		if (sts & 0x5) {
 			spin_lock(&up->port.lock);
-			m32r_sio_handle_port(up, sts, regs);
+			m32r_sio_handle_port(up, sts);
 			spin_unlock(&up->port.lock);
 
 			end = NULL;
@@ -592,7 +590,7 @@
 	sts = sio_in(up, SIOSTS);
 	if (sts & 0x5) {
 		spin_lock(&up->port.lock);
-		m32r_sio_handle_port(up, sts, NULL);
+		m32r_sio_handle_port(up, sts);
 		spin_unlock(&up->port.lock);
 	}
 
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 00d7859..aee1b31 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -385,7 +385,7 @@
 /*
  * This is the serial driver's generic interrupt routine
  */
-irqreturn_t mcfrs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mcfrs_interrupt(int irq, void *dev_id)
 {
 	struct mcf_serial	*info;
 	unsigned char		isr;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index dbad0e3..4f80c5b 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -85,7 +85,7 @@
 
 
 /* Forward declaration of the interruption handling routine */
-static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id,struct pt_regs *regs);
+static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id);
 
 
 /* Simple macro to test if a port is console or not. This one is taken
@@ -410,7 +410,7 @@
 /* ======================================================================== */
 	
 static inline int
-mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
+mpc52xx_uart_int_rx_chars(struct uart_port *port)
 {
 	struct tty_struct *tty = port->info->tty;
 	unsigned char ch, flag;
@@ -425,7 +425,7 @@
 
 		/* Handle sysreq char */
 #ifdef SUPPORT_SYSRQ
-		if (uart_handle_sysrq_char(port, ch, regs)) {
+		if (uart_handle_sysrq_char(port, ch)) {
 			port->sysrq = 0;
 			continue;
 		}
@@ -510,21 +510,13 @@
 }
 
 static irqreturn_t 
-mpc52xx_uart_int(int irq, void *dev_id, struct pt_regs *regs)
+mpc52xx_uart_int(int irq, void *dev_id)
 {
-	struct uart_port *port = (struct uart_port *) dev_id;
+	struct uart_port *port = dev_id;
 	unsigned long pass = ISR_PASS_LIMIT;
 	unsigned int keepgoing;
 	unsigned short status;
 	
-	if ( irq != port->irq ) {
-		printk( KERN_WARNING
-		        "mpc52xx_uart_int : " \
-		        "Received wrong int %d. Waiting for %d\n",
-		       irq, port->irq);
-		return IRQ_NONE;
-	}
-	
 	spin_lock(&port->lock);
 	
 	/* While we have stuff to do, we continue */
@@ -539,7 +531,7 @@
 		/* Do we need to receive chars ? */
 		/* For this RX interrupts must be on and some chars waiting */
 		if ( status & MPC52xx_PSC_IMR_RXRDY )
-			keepgoing |= mpc52xx_uart_int_rx_chars(port, regs);
+			keepgoing |= mpc52xx_uart_int_rx_chars(port);
 
 		/* Do we need to send chars ? */
 		/* For this, TX must be ready and TX interrupt enabled */
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 704243c..8eea69f 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -992,7 +992,7 @@
  */
 
 static inline int
-mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs)
+mpsc_rx_intr(struct mpsc_port_info *pi)
 {
 	struct mpsc_rx_desc *rxre;
 	struct tty_struct *tty = pi->port.info->tty;
@@ -1072,7 +1072,7 @@
 				flag = TTY_PARITY;
 		}
 
-		if (uart_handle_sysrq_char(&pi->port, *bp, regs)) {
+		if (uart_handle_sysrq_char(&pi->port, *bp)) {
 			bp++;
 			bytes_in--;
 			goto next_frame;
@@ -1257,7 +1257,7 @@
  * handling those descriptors, we restart the Rx/Tx engines if they're stopped.
  */
 static irqreturn_t
-mpsc_sdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+mpsc_sdma_intr(int irq, void *dev_id)
 {
 	struct mpsc_port_info *pi = dev_id;
 	ulong iflags;
@@ -1267,7 +1267,7 @@
 
 	spin_lock_irqsave(&pi->port.lock, iflags);
 	mpsc_sdma_intr_ack(pi);
-	if (mpsc_rx_intr(pi, regs))
+	if (mpsc_rx_intr(pi))
 		rc = IRQ_HANDLED;
 	if (mpsc_tx_intr(pi))
 		rc = IRQ_HANDLED;
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index aa819d3..8ad1b8c 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -230,7 +230,7 @@
 				continue;
 		}
 
-		if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
+		if (uart_handle_sysrq_char(port, data & 0xffu))
 			continue;
 
 		tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c
index 7502109..062bad4 100644
--- a/drivers/serial/netx-serial.c
+++ b/drivers/serial/netx-serial.c
@@ -200,7 +200,7 @@
 		uart_write_wakeup(port);
 }
 
-static void netx_rxint(struct uart_port *port, struct pt_regs *regs)
+static void netx_rxint(struct uart_port *port)
 {
 	unsigned char rx, flg, status;
 	struct tty_struct *tty = port->info->tty;
@@ -235,7 +235,7 @@
 				flg = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(port, rx, regs))
+		if (uart_handle_sysrq_char(port, rx))
 			continue;
 
 		uart_insert_char(port, status, SR_OE, rx, flg);
@@ -245,9 +245,9 @@
 	return;
 }
 
-static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t netx_int(int irq, void *dev_id)
 {
-	struct uart_port *port = (struct uart_port *)dev_id;
+	struct uart_port *port = dev_id;
 	unsigned long flags;
 	unsigned char status;
 
@@ -256,7 +256,7 @@
 	status = readl(port->membase + UART_IIR) & IIR_MASK;
 	while (status) {
 		if (status & IIR_RIS)
-			netx_rxint(port, regs);
+			netx_rxint(port);
 		if (status & IIR_TIS)
 			netx_txint(port);
 		if (status & IIR_MIS) {
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index a3b99ca..bf9809e 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -204,8 +204,7 @@
 	}
 }
 
-static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
-					    struct pt_regs *regs)
+static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
 {
 	struct tty_struct *tty = NULL;
 	unsigned char ch, r1, drop, error, flag;
@@ -267,7 +266,7 @@
 		if (uap->port.sysrq) {
 			int swallow;
 			spin_unlock(&uap->port.lock);
-			swallow = uart_handle_sysrq_char(&uap->port, ch, regs);
+			swallow = uart_handle_sysrq_char(&uap->port, ch);
 			spin_lock(&uap->port.lock);
 			if (swallow)
 				goto next_char;
@@ -335,7 +334,7 @@
 	return tty;
 }
 
-static void pmz_status_handle(struct uart_pmac_port *uap, struct pt_regs *regs)
+static void pmz_status_handle(struct uart_pmac_port *uap)
 {
 	unsigned char status;
 
@@ -438,7 +437,7 @@
 }
 
 /* Hrm... we register that twice, fixme later.... */
-static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pmz_interrupt(int irq, void *dev_id)
 {
 	struct uart_pmac_port *uap = dev_id;
 	struct uart_pmac_port *uap_a;
@@ -462,9 +461,9 @@
 		write_zsreg(uap_a, R0, RES_H_IUS);
 		zssync(uap_a);		
        		if (r3 & CHAEXT)
-       			pmz_status_handle(uap_a, regs);
+       			pmz_status_handle(uap_a);
 		if (r3 & CHARxIP)
-			tty = pmz_receive_chars(uap_a, regs);
+			tty = pmz_receive_chars(uap_a);
        		if (r3 & CHATxIP)
        			pmz_transmit_chars(uap_a);
 	        rc = IRQ_HANDLED;
@@ -482,9 +481,9 @@
 		write_zsreg(uap_b, R0, RES_H_IUS);
 		zssync(uap_b);
        		if (r3 & CHBEXT)
-       			pmz_status_handle(uap_b, regs);
+       			pmz_status_handle(uap_b);
        	       	if (r3 & CHBRxIP)
-       			tty = pmz_receive_chars(uap_b, regs);
+       			tty = pmz_receive_chars(uap_b);
        		if (r3 & CHBTxIP)
        			pmz_transmit_chars(uap_b);
 	       	rc = IRQ_HANDLED;
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index a720953..415fe96 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -98,8 +98,7 @@
 	serial_out(up, UART_IER, up->ier);
 }
 
-static inline void
-receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
+static inline void receive_chars(struct uart_pxa_port *up, int *status)
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned int ch, flag;
@@ -153,7 +152,7 @@
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			goto ignore_char;
 
 		uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
@@ -231,10 +230,9 @@
 /*
  * This handles the interrupt from one port.
  */
-static inline irqreturn_t
-serial_pxa_irq(int irq, void *dev_id, struct pt_regs *regs)
+static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id)
 {
-	struct uart_pxa_port *up = (struct uart_pxa_port *)dev_id;
+	struct uart_pxa_port *up = dev_id;
 	unsigned int iir, lsr;
 
 	iir = serial_in(up, UART_IIR);
@@ -242,7 +240,7 @@
 		return IRQ_NONE;
 	lsr = serial_in(up, UART_LSR);
 	if (lsr & UART_LSR_DR)
-		receive_chars(up, &lsr, regs);
+		receive_chars(up, &lsr);
 	check_modem_status(up);
 	if (lsr & UART_LSR_THRE)
 		transmit_chars(up);
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 95738a1..8dfc2dd 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -310,7 +310,7 @@
 #define S3C2410_UERSTAT_PARITY (0x1000)
 
 static irqreturn_t
-s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
+s3c24xx_serial_rx_chars(int irq, void *dev_id)
 {
 	struct s3c24xx_uart_port *ourport = dev_id;
 	struct uart_port *port = &ourport->port;
@@ -379,7 +379,7 @@
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(port, ch, regs))
+		if (uart_handle_sysrq_char(port, ch))
 			goto ignore_char;
 
 		uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag);
@@ -393,7 +393,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *regs)
+static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
 {
 	struct s3c24xx_uart_port *ourport = id;
 	struct uart_port *port = &ourport->port;
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index db3486d..d406526 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -190,7 +190,7 @@
 }
 
 static void
-sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
+sa1100_rx_chars(struct sa1100_port *sport)
 {
 	struct tty_struct *tty = sport->port.info->tty;
 	unsigned int status, ch, flg;
@@ -228,7 +228,7 @@
 #endif
 		}
 
-		if (uart_handle_sysrq_char(&sport->port, ch, regs))
+		if (uart_handle_sysrq_char(&sport->port, ch))
 			goto ignore_char;
 
 		uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg);
@@ -281,7 +281,7 @@
 		sa1100_stop_tx(&sport->port);
 }
 
-static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sa1100_int(int irq, void *dev_id)
 {
 	struct sa1100_port *sport = dev_id;
 	unsigned int status, pass_counter = 0;
@@ -294,7 +294,7 @@
 			/* Clear the receiver idle bit, if set */
 			if (status & UTSR0_RID)
 				UART_PUT_UTSR0(sport, UTSR0_RID);
-			sa1100_rx_chars(sport, regs);
+			sa1100_rx_chars(sport);
 		}
 
 		/* Clear the relevant break bits */
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 23ddedb..5e1ac35 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -135,12 +135,7 @@
 	BIT_SET (port, UART_R_INTEN, ModemInt);
 }
 
-static void
-#ifdef SUPPORT_SYSRQ
-lh7a40xuart_rx_chars (struct uart_port* port, struct pt_regs* regs)
-#else
-lh7a40xuart_rx_chars (struct uart_port* port)
-#endif
+static void lh7a40xuart_rx_chars (struct uart_port* port)
 {
 	struct tty_struct* tty = port->info->tty;
 	int cbRxMax = 256;	/* (Gross) limit on receive */
@@ -177,7 +172,7 @@
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
+		if (uart_handle_sysrq_char (port, (unsigned char) data))
 			continue;
 
 		uart_insert_char(port, data, RxOverrunError, data, flag);
@@ -248,8 +243,7 @@
 	wake_up_interruptible (&port->info->delta_msr_wait);
 }
 
-static irqreturn_t lh7a40xuart_int (int irq, void* dev_id,
-				    struct pt_regs* regs)
+static irqreturn_t lh7a40xuart_int (int irq, void* dev_id)
 {
 	struct uart_port* port = dev_id;
 	unsigned int cLoopLimit = ISR_LOOP_LIMIT;
@@ -258,11 +252,7 @@
 
 	do {
 		if (isr & (RxInt | RxTimeoutInt))
-#ifdef SUPPORT_SYSRQ
-			lh7a40xuart_rx_chars(port, regs);
-#else
 			lh7a40xuart_rx_chars(port);
-#endif
 		if (isr & ModemInt)
 			lh7a40xuart_modem_status (port);
 		if (isr & TxInt)
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index ebd8d2b..2a48289 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -283,7 +283,7 @@
 }
 
 static inline void
-receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *regs)
+receive_chars(struct uart_txx9_port *up, unsigned int *status)
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned char ch;
@@ -344,7 +344,7 @@
 			else if (disr & TXX9_SIDISR_UFER)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			goto ignore_char;
 
 		uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
@@ -391,7 +391,7 @@
 		serial_txx9_stop_tx(&up->port);
 }
 
-static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
 {
 	int pass_counter = 0;
 	struct uart_txx9_port *up = dev_id;
@@ -409,7 +409,7 @@
 		}
 
 		if (status & TXX9_SIDISR_RDIS)
-			receive_chars(up, &status, regs);
+			receive_chars(up, &status);
 		if (status & TXX9_SIDISR_TDIS)
 			transmit_chars(up);
 		/* Clear TX/RX Int. Status */
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 5c025d1..cfcc3ca 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -446,8 +446,7 @@
 /* On SH3, SCIF may read end-of-break as a space->mark char */
 #define STEPFN(c)  ({int __c=(c); (((__c-1)|(__c)) == -1); })
 
-static inline void sci_receive_chars(struct uart_port *port,
-				     struct pt_regs *regs)
+static inline void sci_receive_chars(struct uart_port *port)
 {
 	struct sci_port *sci_port = (struct sci_port *)port;
 	struct tty_struct *tty = port->info->tty;
@@ -476,7 +475,7 @@
 
 		if (port->type == PORT_SCI) {
 			char c = sci_in(port, SCxRDR);
-			if (uart_handle_sysrq_char(port, c, regs) || sci_port->break_flag)
+			if (uart_handle_sysrq_char(port, c) || sci_port->break_flag)
 				count = 0;
 			else {
 				tty_insert_flip_char(tty, c, TTY_NORMAL);
@@ -504,7 +503,7 @@
 					}
 				}
 #endif /* CONFIG_CPU_SH3 */
-				if (uart_handle_sysrq_char(port, c, regs)) {
+				if (uart_handle_sysrq_char(port, c)) {
 					count--; i--;
 					continue;
 				}
@@ -652,18 +651,18 @@
 	return copied;
 }
 
-static irqreturn_t sci_rx_interrupt(int irq, void *port, struct pt_regs *regs)
+static irqreturn_t sci_rx_interrupt(int irq, void *port)
 {
 	/* I think sci_receive_chars has to be called irrespective
 	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
 	 * to be disabled?
 	 */
-	sci_receive_chars(port, regs);
+	sci_receive_chars(port);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
 {
 	struct uart_port *port = ptr;
 
@@ -674,7 +673,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sci_er_interrupt(int irq, void *ptr)
 {
 	struct uart_port *port = ptr;
 
@@ -696,18 +695,18 @@
 			pr_debug("scif: overrun error\n");
 		}
 #endif
-		sci_rx_interrupt(irq, ptr, regs);
+		sci_rx_interrupt(irq, ptr);
 	}
 
 	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
 
 	/* Kick the transmission */
-	sci_tx_interrupt(irq, ptr, regs);
+	sci_tx_interrupt(irq, ptr);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sci_br_interrupt(int irq, void *ptr)
 {
 	struct uart_port *port = ptr;
 
@@ -724,7 +723,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 {
         unsigned short ssr_status, scr_status;
         struct uart_port *port = ptr;
@@ -734,16 +733,16 @@
 
 	/* Tx Interrupt */
         if ((ssr_status & 0x0020) && (scr_status & 0x0080))
-                sci_tx_interrupt(irq, ptr, regs);
+                sci_tx_interrupt(irq, ptr);
 	/* Rx Interrupt */
         if ((ssr_status & 0x0002) && (scr_status & 0x0040))
-                sci_rx_interrupt(irq, ptr, regs);
+                sci_rx_interrupt(irq, ptr);
 	/* Error Interrupt */
         if ((ssr_status & 0x0080) && (scr_status & 0x0400))
-                sci_er_interrupt(irq, ptr, regs);
+                sci_er_interrupt(irq, ptr);
 	/* Break Interrupt */
         if ((ssr_status & 0x0010) && (scr_status & 0x0200))
-                sci_br_interrupt(irq, ptr, regs);
+                sci_br_interrupt(irq, ptr);
 
 	return IRQ_HANDLED;
 }
@@ -795,7 +794,7 @@
 static int sci_request_irq(struct sci_port *port)
 {
 	int i;
-	irqreturn_t (*handlers[4])(int irq, void *ptr, struct pt_regs *regs) = {
+	irqreturn_t (*handlers[4])(int irq, void *ptr) = {
 		sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt,
 		sci_br_interrupt,
 	};
@@ -809,7 +808,7 @@
 		}
 
 		if (request_irq(port->irqs[0], sci_mpxed_interrupt,
-				SA_INTERRUPT, "sci", port)) {
+				IRQF_DISABLED, "sci", port)) {
 			printk(KERN_ERR "sci: Cannot allocate irq.\n");
 			return -ENODEV;
 		}
@@ -818,7 +817,7 @@
 			if (!port->irqs[i])
 				continue;
 			if (request_irq(port->irqs[i], handlers[i],
-					SA_INTERRUPT, desc[i], port)) {
+					IRQF_DISABLED, desc[i], port)) {
 				printk(KERN_ERR "sci: Cannot allocate irq.\n");
 				return -ENODEV;
 			}
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 2f148e5..956b2cf 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -447,7 +447,6 @@
 /**
  * sn_receive_chars - Grab characters, pass them to tty layer
  * @port: Port to operate on
- * @regs: Saved registers (needed by uart_handle_sysrq_char)
  * @flags: irq flags
  *
  * Note: If we're not registered with the serial core infrastructure yet,
@@ -455,8 +454,7 @@
  *
  */
 static void
-sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs,
-		 unsigned long flags)
+sn_receive_chars(struct sn_cons_port *port, unsigned long flags)
 {
 	int ch;
 	struct tty_struct *tty;
@@ -494,7 +492,7 @@
                         sysrq_requested = 0;
                         if (ch && time_before(jiffies, sysrq_timeout)) {
                                 spin_unlock_irqrestore(&port->sc_port.lock, flags);
-                                handle_sysrq(ch, regs, NULL);
+                                handle_sysrq(ch, NULL);
                                 spin_lock_irqsave(&port->sc_port.lock, flags);
                                 /* ignore actual sysrq command char */
                                 continue;
@@ -615,10 +613,9 @@
  * sn_sal_interrupt - Handle console interrupts
  * @irq: irq #, useful for debug statements
  * @dev_id: our pointer to our port (sn_cons_port which contains the uart port)
- * @regs: Saved registers, used by sn_receive_chars for uart_handle_sysrq_char
  *
  */
-static irqreturn_t sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sn_sal_interrupt(int irq, void *dev_id)
 {
 	struct sn_cons_port *port = (struct sn_cons_port *)dev_id;
 	unsigned long flags;
@@ -629,7 +626,7 @@
 
 	spin_lock_irqsave(&port->sc_port.lock, flags);
 	if (status & SAL_CONSOLE_INTR_RECV) {
-		sn_receive_chars(port, regs, flags);
+		sn_receive_chars(port, flags);
 	}
 	if (status & SAL_CONSOLE_INTR_XMIT) {
 		sn_transmit_chars(port, TRANSMIT_BUFFERED);
@@ -677,7 +674,7 @@
 	if (!port->sc_port.irq) {
 		spin_lock_irqsave(&port->sc_port.lock, flags);
 		if (sn_process_input)
-			sn_receive_chars(port, NULL, flags);
+			sn_receive_chars(port, flags);
 		sn_transmit_chars(port, TRANSMIT_RAW);
 		spin_unlock_irqrestore(&port->sc_port.lock, flags);
 		mod_timer(&port->sc_timer,
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index f851f0f..03941d2 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -73,7 +73,7 @@
 
 static int hung_up = 0;
 
-static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs *regs)
+static struct tty_struct *receive_chars(struct uart_port *port)
 {
 	struct tty_struct *tty = NULL;
 	int saw_console_brk = 0;
@@ -106,7 +106,7 @@
 		}
 
 		if (tty == NULL) {
-			uart_handle_sysrq_char(port, c, regs);
+			uart_handle_sysrq_char(port, c);
 			continue;
 		}
 
@@ -119,7 +119,7 @@
 			flag = TTY_BREAK;
 		}
 
-		if (uart_handle_sysrq_char(port, c, regs))
+		if (uart_handle_sysrq_char(port, c))
 			continue;
 
 		if ((port->ignore_status_mask & IGNORE_ALL) ||
@@ -161,14 +161,14 @@
 		uart_write_wakeup(port);
 }
 
-static irqreturn_t sunhv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sunhv_interrupt(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
 	struct tty_struct *tty;
 	unsigned long flags;
 
 	spin_lock_irqsave(&port->lock, flags);
-	tty = receive_chars(port, regs);
+	tty = receive_chars(port);
 	transmit_chars(port);
 	spin_unlock_irqrestore(&port->lock, flags);
 
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index cfe20f7..08a7cd6 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -108,8 +108,7 @@
 
 static struct tty_struct *
 receive_chars(struct uart_sunsab_port *up,
-	      union sab82532_irq_status *stat,
-	      struct pt_regs *regs)
+	      union sab82532_irq_status *stat)
 {
 	struct tty_struct *tty = NULL;
 	unsigned char buf[32];
@@ -161,7 +160,7 @@
 		unsigned char ch = buf[i], flag;
 
 		if (tty == NULL) {
-			uart_handle_sysrq_char(&up->port, ch, regs);
+			uart_handle_sysrq_char(&up->port, ch);
 			continue;
 		}
 
@@ -208,7 +207,7 @@
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			continue;
 
 		if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
@@ -301,7 +300,7 @@
 	wake_up_interruptible(&up->port.info->delta_msr_wait);
 }
 
-static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sunsab_interrupt(int irq, void *dev_id)
 {
 	struct uart_sunsab_port *up = dev_id;
 	struct tty_struct *tty;
@@ -321,7 +320,7 @@
 		if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
 					 SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
 		    (status.sreg.isr1 & SAB82532_ISR1_BRK))
-			tty = receive_chars(up, &status, regs);
+			tty = receive_chars(up, &status);
 		if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
 		    (status.sreg.isr1 & SAB82532_ISR1_CSC))
 			check_status(up, &status);
@@ -350,7 +349,7 @@
 					 SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
 		    (status.sreg.isr1 & SAB82532_ISR1_BRK))
 
-			tty = receive_chars(up, &status, regs);
+			tty = receive_chars(up, &status);
 		if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
 		    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
 			check_status(up, &status);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 9b3b9aa..c577fae 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -310,7 +310,7 @@
 }
 
 static struct tty_struct *
-receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
+receive_chars(struct uart_sunsu_port *up, unsigned char *status)
 {
 	struct tty_struct *tty = up->port.info->tty;
 	unsigned char ch, flag;
@@ -367,7 +367,7 @@
 			else if (*status & UART_LSR_FE)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			goto ignore_char;
 		if ((*status & up->port.ignore_status_mask) == 0)
 			tty_insert_flip_char(tty, ch, flag);
@@ -445,7 +445,7 @@
 	wake_up_interruptible(&up->port.info->delta_msr_wait);
 }
 
-static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id)
 {
 	struct uart_sunsu_port *up = dev_id;
 	unsigned long flags;
@@ -459,7 +459,7 @@
 		status = serial_inp(up, UART_LSR);
 		tty = NULL;
 		if (status & UART_LSR_DR)
-			tty = receive_chars(up, &status, regs);
+			tty = receive_chars(up, &status);
 		check_modem_status(up);
 		if (status & UART_LSR_THRE)
 			transmit_chars(up);
@@ -497,7 +497,7 @@
 	sunsu_change_speed(&up->port, up->cflag, 0, quot);
 }
 
-static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *regs, int is_break)
+static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break)
 {
 	do {
 		unsigned char ch = serial_inp(up, UART_RX);
@@ -505,7 +505,7 @@
 		/* Stop-A is handled by drivers/char/keyboard.c now. */
 		if (up->su_type == SU_PORT_KBD) {
 #ifdef CONFIG_SERIO
-			serio_interrupt(&up->serio, ch, 0, regs);
+			serio_interrupt(&up->serio, ch, 0);
 #endif
 		} else if (up->su_type == SU_PORT_MS) {
 			int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -519,7 +519,7 @@
 
 			case 0:
 #ifdef CONFIG_SERIO
-				serio_interrupt(&up->serio, ch, 0, regs);
+				serio_interrupt(&up->serio, ch, 0);
 #endif
 				break;
 			};
@@ -527,7 +527,7 @@
 	} while (serial_in(up, UART_LSR) & UART_LSR_DR);
 }
 
-static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id)
 {
 	struct uart_sunsu_port *up = dev_id;
 
@@ -535,8 +535,7 @@
 		unsigned char status = serial_inp(up, UART_LSR);
 
 		if ((status & UART_LSR_DR) || (status & UART_LSR_BI))
-			receive_kbd_ms_chars(up, regs,
-					     (status & UART_LSR_BI) != 0);
+			receive_kbd_ms_chars(up, (status & UART_LSR_BI) != 0);
 	}
 
 	return IRQ_HANDLED;
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 0da3ebf..b2cc703 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -277,14 +277,13 @@
 }
 
 static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
-					 unsigned char ch, int is_break,
-					 struct pt_regs *regs)
+					 unsigned char ch, int is_break)
 {
 	if (ZS_IS_KEYB(up)) {
 		/* Stop-A is handled by drivers/char/keyboard.c now. */
 #ifdef CONFIG_SERIO
 		if (up->serio_open)
-			serio_interrupt(&up->serio, ch, 0, regs);
+			serio_interrupt(&up->serio, ch, 0);
 #endif
 	} else if (ZS_IS_MOUSE(up)) {
 		int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -299,7 +298,7 @@
 		case 0:
 #ifdef CONFIG_SERIO
 			if (up->serio_open)
-				serio_interrupt(&up->serio, ch, 0, regs);
+				serio_interrupt(&up->serio, ch, 0);
 #endif
 			break;
 		};
@@ -308,8 +307,7 @@
 
 static struct tty_struct *
 sunzilog_receive_chars(struct uart_sunzilog_port *up,
-		       struct zilog_channel __iomem *channel,
-		       struct pt_regs *regs)
+		       struct zilog_channel __iomem *channel)
 {
 	struct tty_struct *tty;
 	unsigned char ch, r1, flag;
@@ -346,12 +344,12 @@
 		ch &= up->parity_mask;
 
 		if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) {
-			sunzilog_kbdms_receive_chars(up, ch, 0, regs);
+			sunzilog_kbdms_receive_chars(up, ch, 0);
 			continue;
 		}
 
 		if (tty == NULL) {
-			uart_handle_sysrq_char(&up->port, ch, regs);
+			uart_handle_sysrq_char(&up->port, ch);
 			continue;
 		}
 
@@ -379,7 +377,7 @@
 			else if (r1 & CRC_ERR)
 				flag = TTY_FRAME;
 		}
-		if (uart_handle_sysrq_char(&up->port, ch, regs))
+		if (uart_handle_sysrq_char(&up->port, ch))
 			continue;
 
 		if (up->port.ignore_status_mask == 0xff ||
@@ -394,8 +392,7 @@
 }
 
 static void sunzilog_status_handle(struct uart_sunzilog_port *up,
-				   struct zilog_channel __iomem *channel,
-				   struct pt_regs *regs)
+				   struct zilog_channel __iomem *channel)
 {
 	unsigned char status;
 
@@ -408,7 +405,7 @@
 
 	if (status & BRK_ABRT) {
 		if (ZS_IS_MOUSE(up))
-			sunzilog_kbdms_receive_chars(up, 0, 1, regs);
+			sunzilog_kbdms_receive_chars(up, 0, 1);
 		if (ZS_IS_CONS(up)) {
 			/* Wait for BREAK to deassert to avoid potentially
 			 * confusing the PROM.
@@ -517,7 +514,7 @@
 	ZS_WSYNC(channel);
 }
 
-static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sunzilog_interrupt(int irq, void *dev_id)
 {
 	struct uart_sunzilog_port *up = dev_id;
 
@@ -538,9 +535,9 @@
 			ZS_WSYNC(channel);
 
 			if (r3 & CHARxIP)
-				tty = sunzilog_receive_chars(up, channel, regs);
+				tty = sunzilog_receive_chars(up, channel);
 			if (r3 & CHAEXT)
-				sunzilog_status_handle(up, channel, regs);
+				sunzilog_status_handle(up, channel);
 			if (r3 & CHATxIP)
 				sunzilog_transmit_chars(up, channel);
 		}
@@ -561,9 +558,9 @@
 			ZS_WSYNC(channel);
 
 			if (r3 & CHBRxIP)
-				tty = sunzilog_receive_chars(up, channel, regs);
+				tty = sunzilog_receive_chars(up, channel);
 			if (r3 & CHBEXT)
-				sunzilog_status_handle(up, channel, regs);
+				sunzilog_status_handle(up, channel);
 			if (r3 & CHBTxIP)
 				sunzilog_transmit_chars(up, channel);
 		}
@@ -1060,7 +1057,7 @@
 
 static void sunzilog_putchar(struct uart_port *port, int ch)
 {
-	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
+	struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
 	int loops = ZS_PUT_CHAR_MAX_DELAY;
 
 	/* This is a timed polling loop so do not switch the explicit
@@ -1185,7 +1182,7 @@
 	return 0;
 }
 
-static struct console sunzilog_console = {
+static struct console sunzilog_console_ops = {
 	.name	=	"ttyS",
 	.write	=	sunzilog_console_write,
 	.device	=	uart_console_device,
@@ -1211,10 +1208,10 @@
 	if (i == NUM_CHANNELS)
 		return NULL;
 
-	sunzilog_console.index = i;
+	sunzilog_console_ops.index = i;
 	sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
 
-	return &sunzilog_console;
+	return &sunzilog_console_ops;
 }
 
 #else
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index f802867..28f3bbf 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -271,14 +271,14 @@
 		v850e_uart_stop_tx (port, stopped);
 }
 
-static irqreturn_t v850e_uart_tx_irq(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t v850e_uart_tx_irq(int irq, void *data)
 {
 	struct uart_port *port = data;
 	v850e_uart_tx (port);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t v850e_uart_rx_irq(int irq, void *data)
 {
 	struct uart_port *port = data;
 	unsigned ch_stat = TTY_NORMAL;
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 6c8b0ea..fd51f81 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -359,8 +359,7 @@
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static inline void receive_chars(struct uart_port *port, uint8_t *status,
-                                 struct pt_regs *regs)
+static inline void receive_chars(struct uart_port *port, uint8_t *status)
 {
 	struct tty_struct *tty;
 	uint8_t lsr, ch;
@@ -405,7 +404,7 @@
 				flag = TTY_PARITY;
 		}
 
-		if (uart_handle_sysrq_char(port, ch, regs))
+		if (uart_handle_sysrq_char(port, ch))
 			goto ignore_char;
 
 		uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
@@ -472,7 +471,7 @@
 		siu_stop_tx(port);
 }
 
-static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t siu_interrupt(int irq, void *dev_id)
 {
 	struct uart_port *port;
 	uint8_t iir, lsr;
@@ -485,7 +484,7 @@
 
 	lsr = siu_read(port, UART_LSR);
 	if (lsr & UART_LSR_DR)
-		receive_chars(port, &lsr, regs);
+		receive_chars(port, &lsr);
 
 	check_modem_status(port);
 
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
index a347316..c66ba9a 100644
--- a/drivers/sn/Kconfig
+++ b/drivers/sn/Kconfig
@@ -5,19 +5,6 @@
 menu "SN Devices"
 	depends on SGI_SN
 
-config SGI_IOC4
-	tristate "SGI IOC4 Base IO support"
-	depends on MMTIMER
-	default m
-	---help---
-	This option enables basic support for the SGI IOC4-based Base IO
-	controller card.  This option does not enable any specific
-	functions on such a card, but provides necessary infrastructure
-	for other drivers to utilize.
-
-	If you have an SGI Altix with an IOC4-based
-	I/O controller say Y.  Otherwise say N.
-
 config SGI_IOC3
 	tristate "SGI IOC3 Base IO support"
 	default m
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index 2cda011..693db8b 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -3,5 +3,4 @@
 #
 #
 
-obj-$(CONFIG_SGI_IOC4) += ioc4.o
 obj-$(CONFIG_SGI_IOC3) += ioc3.o
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index 6c7e035..cd6b653 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -398,10 +398,10 @@
 	return intrs;
 }
 
-static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t ioc3_intr_io(int irq, void *arg)
 {
 	unsigned long flags;
-	struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
+	struct ioc3_driver_data *idd = arg;
 	int handled = 1, id;
 	unsigned int pending;
 
@@ -412,7 +412,7 @@
 		if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
 						ioc3_ethernet->intr) {
 			handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
-							idd, 0, regs);
+							idd, 0);
 		}
 	}
 	pending = get_pending_intrs(idd);	/* look at the IO IRQs */
@@ -424,8 +424,7 @@
 			write_ireg(idd, ioc3_submodules[id]->irq_mask,
 							IOC3_W_IEC);
 			if(!ioc3_submodules[id]->intr(ioc3_submodules[id],
-				   idd, pending & ioc3_submodules[id]->irq_mask,
-					regs))
+				   idd, pending & ioc3_submodules[id]->irq_mask))
 				pending &= ~ioc3_submodules[id]->irq_mask;
 			if (ioc3_submodules[id]->reset_mask)
 				write_ireg(idd, ioc3_submodules[id]->irq_mask,
@@ -442,7 +441,7 @@
 	return handled?IRQ_HANDLED:IRQ_NONE;
 }
 
-static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t ioc3_intr_eth(int irq, void *arg)
 {
 	unsigned long flags;
 	struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
@@ -453,8 +452,7 @@
 	read_lock_irqsave(&ioc3_submodules_lock, flags);
 	if(ioc3_ethernet && idd->active[ioc3_ethernet->id]
 				&& ioc3_ethernet->intr)
-		handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0,
-								regs);
+		handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0);
 	read_unlock_irqrestore(&ioc3_submodules_lock, flags);
 	return handled?IRQ_HANDLED:IRQ_NONE;
 }
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 29aec77..72025df 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -409,7 +409,7 @@
 	return limit;
 }
 
-static void dma_handler(int channel, void *data, struct pt_regs *regs)
+static void dma_handler(int channel, void *data)
 {
 	struct driver_data *drv_data = data;
 	struct spi_message *msg = drv_data->cur_msg;
@@ -667,9 +667,9 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ssp_int(int irq, void *dev_id)
 {
-	struct driver_data *drv_data = (struct driver_data *)dev_id;
+	struct driver_data *drv_data = dev_id;
 	void *reg = drv_data->ioaddr;
 
 	if (!drv_data->cur_msg) {
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index 5d92a7e..ff0b048 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -296,8 +296,7 @@
 	return t->len - mpc83xx_spi->count;
 }
 
-irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data,
-			    struct pt_regs * ptregs)
+irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data)
 {
 	struct mpc83xx_spi *mpc83xx_spi = context_data;
 	u32 event;
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 20eb6e9..2ebe1fc 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -196,7 +196,7 @@
 	return hw->count;
 }
 
-static irqreturn_t s3c24xx_spi_irq(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
 {
 	struct s3c24xx_spi *hw = dev;
 	unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 622881f..792becd 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -347,7 +347,7 @@
 	tasklet_schedule(&info->tlet);
 }
 
-static void receive_chars(struct dec_serial *info, struct pt_regs *regs)
+static void receive_chars(struct dec_serial *info)
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, stat, flag;
@@ -389,7 +389,7 @@
 			if (ch == 0)
 				continue;
 			if (time_before(jiffies, break_pressed + HZ * 5)) {
-				handle_sysrq(ch, regs, NULL);
+				handle_sysrq(ch, NULL);
 				break_pressed = 0;
 				continue;
 			}
@@ -490,7 +490,7 @@
 /*
  * This is the serial driver's generic interrupt routine
  */
-static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rs_interrupt(int irq, void *dev_id)
 {
 	struct dec_serial *info = (struct dec_serial *) dev_id;
 	irqreturn_t status = IRQ_NONE;
@@ -518,7 +518,7 @@
 		status = IRQ_HANDLED;
 
 		if (zs_intreg & CHBRxIP) {
-			receive_chars(info, regs);
+			receive_chars(info);
 		}
 		if (zs_intreg & CHBTxIP) {
 			transmit_chars(info);
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index f6b2948..1b601b6 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -284,6 +284,14 @@
 
 module_param(ixjdebug, int, 0);
 
+static struct pci_device_id ixj_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, ixj_pci_tbl);
+
 /************************************************************************
 *
 * ixjdebug meanings are now bit mapped instead of level based
@@ -7683,7 +7691,8 @@
 	IXJ *j = NULL;
 
 	for (i = 0; i < IXJMAX - *cnt; i++) {
-		pci = pci_find_device(0x15E2, 0x0500, pci);
+		pci = pci_find_device(PCI_VENDOR_ID_QUICKNET,
+				      PCI_DEVICE_ID_QUICKNET_XJ, pci);
 		if (!pci)
 			break;
 
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 97d57cf..825bf88 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -33,7 +33,6 @@
 obj-$(CONFIG_USB_MOUSE)		+= input/
 obj-$(CONFIG_USB_MTOUCH)	+= input/
 obj-$(CONFIG_USB_POWERMATE)	+= input/
-obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/
 obj-$(CONFIG_USB_WACOM)		+= input/
 obj-$(CONFIG_USB_XPAD)		+= input/
 
@@ -66,6 +65,7 @@
 obj-$(CONFIG_USB_RIO500)	+= misc/
 obj-$(CONFIG_USB_SISUSBVGA)	+= misc/
 obj-$(CONFIG_USB_TEST)		+= misc/
+obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/
 obj-$(CONFIG_USB_USS720)	+= misc/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 04631dc..e656563 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -171,7 +171,7 @@
 };
 
 /* the following three functions are stolen from drivers/usb/core/message.c */
-static void cxacru_blocking_completion(struct urb *urb, struct pt_regs *regs)
+static void cxacru_blocking_completion(struct urb *urb)
 {
 	complete((struct completion *)urb->context);
 }
@@ -793,6 +793,9 @@
 	{ /* V = Conexant			P = ADSL modem				*/
 		USB_DEVICE(0x0572, 0xcb06),	.driver_info = (unsigned long) &cxacru_cb00
 	},
+	{ /* V = Conexant			P = ADSL modem (ZTE ZXDSL 852)		*/
+		USB_DEVICE(0x0572, 0xcb07),	.driver_info = (unsigned long) &cxacru_cb00
+	},
 	{ /* V = Olitec				P = ADSL modem version 2		*/
 		USB_DEVICE(0x08e3, 0x0100),	.driver_info = (unsigned long) &cxacru_cafe
 	},
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 956b7a1..c870c80 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -55,7 +55,6 @@
 #define OFFSET_d	9		/* size 4 */
 #define OFFSET_e	13		/* size 1 */
 #define OFFSET_f	14		/* size 1 */
-#define TOTAL		15
 
 #define SIZE_7		1
 #define SIZE_b		8
@@ -79,6 +78,18 @@
 static int enable_isoc = DEFAULT_ENABLE_ISOC;
 static int sw_buffering = DEFAULT_SW_BUFFERING;
 
+#define DEFAULT_B_MAX_DSL	8128
+#define DEFAULT_MODEM_MODE	11
+#define MODEM_OPTION_LENGTH	16
+static const unsigned char DEFAULT_MODEM_OPTION[MODEM_OPTION_LENGTH] = {
+	0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned int BMaxDSL = DEFAULT_B_MAX_DSL;
+static unsigned char ModemMode = DEFAULT_MODEM_MODE;
+static unsigned char ModemOption[MODEM_OPTION_LENGTH];
+static int num_ModemOption;
+
 module_param(altsetting, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(altsetting,
 		"Alternative setting for data interface (bulk_default: "
@@ -100,6 +111,17 @@
 		 "Enable software buffering (default: "
 		 __MODULE_STRING(DEFAULT_SW_BUFFERING) ")");
 
+module_param(BMaxDSL, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(BMaxDSL,
+		"default: " __MODULE_STRING(DEFAULT_B_MAX_DSL));
+
+module_param(ModemMode, byte, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ModemMode,
+		"default: " __MODULE_STRING(DEFAULT_MODEM_MODE));
+
+module_param_array(ModemOption, byte, &num_ModemOption, S_IRUGO);
+MODULE_PARM_DESC(ModemOption, "default: 0x10,0x00,0x00,0x00,0x20");
+
 #define INTERFACE_DATA		1
 #define ENDPOINT_INT		0x81
 #define ENDPOINT_BULK_DATA	0x07
@@ -108,10 +130,17 @@
 
 #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )
 
+struct speedtch_params {
+	unsigned int altsetting;
+	unsigned int BMaxDSL;
+	unsigned char ModemMode;
+	unsigned char ModemOption[MODEM_OPTION_LENGTH];
+};
+
 struct speedtch_instance_data {
 	struct usbatm_data *usbatm;
 
-	unsigned int altsetting;
+	struct speedtch_params params; /* set in probe, constant afterwards */
 
 	struct work_struct status_checker;
 
@@ -123,7 +152,7 @@
 	struct urb *int_urb;
 	unsigned char int_data[16];
 
-	unsigned char scratch_buffer[TOTAL];
+	unsigned char scratch_buffer[16];
 };
 
 /***************
@@ -186,6 +215,34 @@
 			      0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT);
 	if (ret < 0)
 		usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret);
+
+	/* Extra initialisation in recent drivers - gives higher speeds */
+
+	/* URBext1 */
+	buf[0] = instance->params.ModemMode;
+	ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			      0x01, 0x40, 0x11, 0x00, buf, 1, CTRL_TIMEOUT);
+	if (ret < 0)
+		usb_warn(usbatm, "%s failed on URBext1: %d\n", __func__, ret);
+
+	/* URBext2 */
+	/* This seems to be the one which actually triggers the higher sync
+	   rate -- it does require the new firmware too, although it works OK
+	   with older firmware */
+	ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			      0x01, 0x40, 0x14, 0x00,
+			      instance->params.ModemOption,
+			      MODEM_OPTION_LENGTH, CTRL_TIMEOUT);
+	if (ret < 0)
+		usb_warn(usbatm, "%s failed on URBext2: %d\n", __func__, ret);
+
+	/* URBext3 */
+	buf[0] = instance->params.BMaxDSL & 0xff;
+	buf[1] = instance->params.BMaxDSL >> 8;
+	ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			      0x01, 0x40, 0x12, 0x00, buf, 2, CTRL_TIMEOUT);
+	if (ret < 0)
+		usb_warn(usbatm, "%s failed on URBext3: %d\n", __func__, ret);
 }
 
 static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
@@ -285,8 +342,8 @@
 	   because we're in our own kernel thread anyway. */
 	msleep_interruptible(1000);
 
-	if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
-		usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret);
+	if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->params.altsetting)) < 0) {
+		usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->params.altsetting, ret);
 		goto out_free;
 	}
 
@@ -372,7 +429,7 @@
 	unsigned char *buf = instance->scratch_buffer;
 	int ret;
 
-	memset(buf, 0, TOTAL);
+	memset(buf, 0, 16);
 
 	ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
 			      0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7,
@@ -547,7 +604,7 @@
 	}
 }
 
-static void speedtch_handle_int(struct urb *int_urb, struct pt_regs *regs)
+static void speedtch_handle_int(struct urb *int_urb)
 {
 	struct speedtch_instance_data *instance = int_urb->context;
 	struct usbatm_data *usbatm = instance->usbatm;
@@ -746,17 +803,21 @@
 
 	instance->usbatm = usbatm;
 
-	/* altsetting and enable_isoc may change at any moment, so take a snapshot */
-	instance->altsetting = altsetting;
+	/* module parameters may change at any moment, so take a snapshot */
+	instance->params.altsetting = altsetting;
+	instance->params.BMaxDSL = BMaxDSL;
+	instance->params.ModemMode = ModemMode;
+	memcpy(instance->params.ModemOption, DEFAULT_MODEM_OPTION, MODEM_OPTION_LENGTH);
+	memcpy(instance->params.ModemOption, ModemOption, num_ModemOption);
 	use_isoc = enable_isoc;
 
-	if (instance->altsetting)
-		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
-			usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret);
-			instance->altsetting = 0; /* fall back to default */
+	if (instance->params.altsetting)
+		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->params.altsetting)) < 0) {
+			usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->params.altsetting, ret);
+			instance->params.altsetting = 0; /* fall back to default */
 		}
 
-	if (!instance->altsetting && use_isoc)
+	if (!instance->params.altsetting && use_isoc)
 		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) {
 			usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret);
 			use_isoc = 0; /* fall back to bulk */
@@ -783,14 +844,14 @@
 			usb_info(usbatm, "isochronous transfer not supported - using bulk\n");
 	}
 
-	if (!use_isoc && !instance->altsetting)
+	if (!use_isoc && !instance->params.altsetting)
 		if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) {
 			usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret);
 			goto fail_free;
 		}
 
-	if (!instance->altsetting)
-		instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING;
+	if (!instance->params.altsetting)
+		instance->params.altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING;
 
 	usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
 
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 465961a..f6b9f7e 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -68,7 +68,7 @@
 
 #include "usbatm.h"
 
-#define EAGLEUSBVERSION "ueagle 1.3"
+#define EAGLEUSBVERSION "ueagle 1.4"
 
 
 /*
@@ -80,14 +80,14 @@
 			dev_dbg(&(usb_dev)->dev, \
 				"[ueagle-atm dbg] %s: " format, \
 					__FUNCTION__, ##args); \
-       } while (0)
+	} while (0)
 
 #define uea_vdbg(usb_dev, format, args...)	\
 	do { \
 		if (debug >= 2) \
 			dev_dbg(&(usb_dev)->dev, \
 				"[ueagle-atm vdbg]  " format, ##args); \
-       } while (0)
+	} while (0)
 
 #define uea_enters(usb_dev) \
 	uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
@@ -218,8 +218,8 @@
 #define UEA_CHIP_VERSION(x) \
 	((x)->driver_info & 0xf)
 
-#define IS_ISDN(sc) \
-	(le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)
+#define IS_ISDN(usb_dev) \
+	(le16_to_cpu((usb_dev)->descriptor.bcdDevice) & 0x80)
 
 #define INS_TO_USBDEV(ins) ins->usb_dev
 
@@ -625,12 +625,12 @@
 	char *dsp_name;
 
 	if (UEA_CHIP_VERSION(sc) == ADI930) {
-		if (IS_ISDN(sc))
+		if (IS_ISDN(sc->usb_dev))
 			dsp_name = FW_DIR "DSP9i.bin";
 		else
 			dsp_name = FW_DIR "DSP9p.bin";
 	} else {
-		if (IS_ISDN(sc))
+		if (IS_ISDN(sc->usb_dev))
 			dsp_name = FW_DIR "DSPei.bin";
 		else
 			dsp_name = FW_DIR "DSPep.bin";
@@ -744,7 +744,7 @@
 
 static inline int wait_cmv_ack(struct uea_softc *sc)
 {
-	int ret = wait_event_timeout(sc->cmv_ack_wait,
+	int ret = wait_event_interruptible_timeout(sc->cmv_ack_wait,
 						   sc->cmv_ack, ACK_TIMEOUT);
 	sc->cmv_ack = 0;
 
@@ -885,7 +885,8 @@
 		break;
 
 	case 3:		/* fail ... */
-		uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n");
+		uea_info(INS_TO_USBDEV(sc), "modem synchronization failed"
+				" (may be try other cmv/dsp)\n");
 		return -EAGAIN;
 
 	case 4 ... 6:	/* test state */
@@ -913,12 +914,6 @@
 			release_firmware(sc->dsp_firm);
 			sc->dsp_firm = NULL;
 		}
-
-		ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
-		if (ret < 0)
-			return ret;
-		uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
-				sc->stats.phy.firmid);
 	}
 
 	/* always update it as atm layer could not be init when we switch to
@@ -1033,9 +1028,9 @@
 
 	if (cmv_file[sc->modem_index] == NULL) {
 		if (UEA_CHIP_VERSION(sc) == ADI930)
-			file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin";
+			file = (IS_ISDN(sc->usb_dev)) ? "CMV9i.bin" : "CMV9p.bin";
 		else
-			file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin";
+			file = (IS_ISDN(sc->usb_dev)) ? "CMVei.bin" : "CMVep.bin";
 	} else
 		file = cmv_file[sc->modem_index];
 
@@ -1131,6 +1126,13 @@
 	if (ret < 0)
 		return ret;
 
+	/* Dump firmware version */
+	ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
+	if (ret < 0)
+		return ret;
+	uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
+			sc->stats.phy.firmid);
+
 	/* get options */
  	ret = len = request_cmvs(sc, &cmvs, &cmvs_fw);
 	if (ret < 0)
@@ -1147,6 +1149,8 @@
 	/* Enter in R-ACT-REQ */
 	ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
 	uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
+	uea_info(INS_TO_USBDEV(sc), "Modem started, "
+		"waiting synchronization\n");
 out:
 	release_firmware(cmvs_fw);
 	sc->reset = 0;
@@ -1172,7 +1176,10 @@
 		if (!ret)
 			ret = uea_stat(sc);
 		if (ret != -EAGAIN)
-			msleep(1000);
+			msleep_interruptible(1000);
+ 		if (try_to_freeze())
+			uea_err(INS_TO_USBDEV(sc), "suspend/resume not supported, "
+				"please unplug/replug your modem\n");
 	}
 	uea_leaves(INS_TO_USBDEV(sc));
 	return ret;
@@ -1297,7 +1304,7 @@
 /*
  * interrupt handler
  */
-static void uea_intr(struct urb *urb, struct pt_regs *regs)
+static void uea_intr(struct urb *urb)
 {
 	struct uea_softc *sc = urb->context;
 	struct intr_pkt *intr = urb->transfer_buffer;
@@ -1566,6 +1573,7 @@
 UEA_ATTR(dscorr, 0);
 UEA_ATTR(usunc, 0);
 UEA_ATTR(dsunc, 0);
+UEA_ATTR(firmid, 0);
 
 /* Retrieve the device End System Identifier (MAC) */
 
@@ -1597,7 +1605,7 @@
 {
 	struct uea_softc *sc = usbatm->driver_data;
 
-	wait_event(sc->sync_q, IS_OPERATIONAL(sc));
+	wait_event_interruptible(sc->sync_q, IS_OPERATIONAL(sc));
 
 	return 0;
 
@@ -1639,16 +1647,13 @@
 	&dev_attr_stat_dscorr.attr,
 	&dev_attr_stat_usunc.attr,
 	&dev_attr_stat_dsunc.attr,
+	&dev_attr_stat_firmid.attr,
+	NULL,
 };
 static struct attribute_group attr_grp = {
 	.attrs = attrs,
 };
 
-static int create_fs_entries(struct usb_interface *intf)
-{
-	return sysfs_create_group(&intf->dev.kobj, &attr_grp);
-}
-
 static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
 		   const struct usb_device_id *id)
 {
@@ -1708,31 +1713,25 @@
 		}
 	}
 
+	ret = sysfs_create_group(&intf->dev.kobj, &attr_grp);
+	if (ret < 0)
+		goto error;
+
 	ret = uea_boot(sc);
-	if (ret < 0) {
-		kfree(sc);
-		return ret;
-	}
+	if (ret < 0)
+		goto error;
 
-	ret = create_fs_entries(intf);
-	if (ret) {
-		uea_stop(sc);
-		kfree(sc);
-		return ret;
-	}
 	return 0;
-}
-
-static void destroy_fs_entries(struct usb_interface *intf)
-{
-	sysfs_remove_group(&intf->dev.kobj, &attr_grp);
+error:
+	kfree(sc);
+	return ret;
 }
 
 static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
 {
 	struct uea_softc *sc = usbatm->driver_data;
 
-	destroy_fs_entries(intf);
+	sysfs_remove_group(&intf->dev.kobj, &attr_grp);
 	uea_stop(sc);
 	kfree(sc);
 }
@@ -1753,10 +1752,10 @@
 	struct usb_device *usb = interface_to_usbdev(intf);
 
 	uea_enters(usb);
-	uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n",
+	uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s %s\n",
 	       le16_to_cpu(usb->descriptor.idVendor),
 	       le16_to_cpu(usb->descriptor.idProduct),
-	       chip_name[UEA_CHIP_VERSION(id)]);
+	       chip_name[UEA_CHIP_VERSION(id)], IS_ISDN(usb)?"isdn":"pots");
 
 	usb_reset_device(usb);
 
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index a38701c..ec63b0e 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -254,7 +254,7 @@
 	return ret;
 }
 
-static void usbatm_complete(struct urb *urb, struct pt_regs *regs)
+static void usbatm_complete(struct urb *urb)
 {
 	struct usbatm_channel *channel = urb->context;
 	unsigned long flags;
@@ -1001,6 +1001,7 @@
 
 	daemonize(instance->driver->driver_name);
 	allow_signal(SIGTERM);
+	instance->thread_pid = current->pid;
 
 	complete(&instance->thread_started);
 
@@ -1025,10 +1026,6 @@
 		return ret;
 	}
 
-	mutex_lock(&instance->serialize);
-	instance->thread_pid = ret;
-	mutex_unlock(&instance->serialize);
-
 	wait_for_completion(&instance->thread_started);
 
 	return 0;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 7128829..9a9012f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -218,7 +218,7 @@
  */
 
 /* control interface reports status changes with "interrupt" transfers */
-static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
+static void acm_ctrl_irq(struct urb *urb)
 {
 	struct acm *acm = urb->context;
 	struct usb_cdc_notification *dr = urb->transfer_buffer;
@@ -285,7 +285,7 @@
 }
 
 /* data interface returns incoming bytes, or we got unthrottled */
-static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
+static void acm_read_bulk(struct urb *urb)
 {
 	struct acm_rb *buf;
 	struct acm_ru *rcv = urb->context;
@@ -325,7 +325,7 @@
 	struct acm_rb *buf;
 	struct tty_struct *tty = acm->tty;
 	struct acm_ru *rcv;
-	//unsigned long flags;
+	unsigned long flags;
 	int i = 0;
 	dbg("Entering acm_rx_tasklet");
 
@@ -333,15 +333,15 @@
 		return;
 
 next_buffer:
-	spin_lock(&acm->read_lock);
+	spin_lock_irqsave(&acm->read_lock, flags);
 	if (list_empty(&acm->filled_read_bufs)) {
-		spin_unlock(&acm->read_lock);
+		spin_unlock_irqrestore(&acm->read_lock, flags);
 		goto urbs;
 	}
 	buf = list_entry(acm->filled_read_bufs.next,
 			 struct acm_rb, list);
 	list_del(&buf->list);
-	spin_unlock(&acm->read_lock);
+	spin_unlock_irqrestore(&acm->read_lock, flags);
 
 	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
@@ -356,29 +356,29 @@
 		memmove(buf->base, buf->base + i, buf->size - i);
 		buf->size -= i;
 		spin_unlock(&acm->throttle_lock);
-		spin_lock(&acm->read_lock);
+		spin_lock_irqsave(&acm->read_lock, flags);
 		list_add(&buf->list, &acm->filled_read_bufs);
-		spin_unlock(&acm->read_lock);
+		spin_unlock_irqrestore(&acm->read_lock, flags);
 		return;
 	}
 	spin_unlock(&acm->throttle_lock);
 
-	spin_lock(&acm->read_lock);
+	spin_lock_irqsave(&acm->read_lock, flags);
 	list_add(&buf->list, &acm->spare_read_bufs);
-	spin_unlock(&acm->read_lock);
+	spin_unlock_irqrestore(&acm->read_lock, flags);
 	goto next_buffer;
 
 urbs:
 	while (!list_empty(&acm->spare_read_bufs)) {
-		spin_lock(&acm->read_lock);
+		spin_lock_irqsave(&acm->read_lock, flags);
 		if (list_empty(&acm->spare_read_urbs)) {
-			spin_unlock(&acm->read_lock);
+			spin_unlock_irqrestore(&acm->read_lock, flags);
 			return;
 		}
 		rcv = list_entry(acm->spare_read_urbs.next,
 				 struct acm_ru, list);
 		list_del(&rcv->list);
-		spin_unlock(&acm->read_lock);
+		spin_unlock_irqrestore(&acm->read_lock, flags);
 
 		buf = list_entry(acm->spare_read_bufs.next,
 				 struct acm_rb, list);
@@ -400,16 +400,16 @@
 		   free-urbs-pool and resubmited ASAP */
 		if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
 			list_add(&buf->list, &acm->spare_read_bufs);
-			spin_lock(&acm->read_lock);
+			spin_lock_irqsave(&acm->read_lock, flags);
 			list_add(&rcv->list, &acm->spare_read_urbs);
-			spin_unlock(&acm->read_lock);
+			spin_unlock_irqrestore(&acm->read_lock, flags);
 			return;
 		}
 	}
 }
 
 /* data interface wrote those outgoing bytes */
-static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
+static void acm_write_bulk(struct urb *urb)
 {
 	struct acm *acm = (struct acm *)urb->context;
 
@@ -1083,6 +1083,9 @@
 	{ USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
+	{ USB_DEVICE(0x079b, 0x000f), /* BT On-Air USB MODEM */
+	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+	},
 	{ USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */
 	.driver_info = SINGLE_RX_URB, /* firmware bug */
 	},
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 9cac11c..809d465 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -154,6 +154,7 @@
 	unsigned char		used;			/* True if open */
 	unsigned char		present;		/* True if not disconnected */
 	unsigned char		bidir;			/* interface is bidirectional */
+	unsigned char		sleeping;		/* interface is suspended */
 	unsigned char		*device_id_string;	/* IEEE 1284 DEVICE ID string (ptr) */
 							/* first 2 bytes are (big-endian) length */
 };
@@ -183,6 +184,7 @@
 	dbg("quirks=%d", usblp->quirks);
 	dbg("used=%d", usblp->used);
 	dbg("bidir=%d", usblp->bidir);
+	dbg("sleeping=%d", usblp->sleeping);
 	dbg("device_id_string=\"%s\"",
 		usblp->device_id_string ?
 			usblp->device_id_string + 2 :
@@ -271,7 +273,7 @@
  * URB callback.
  */
 
-static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs)
+static void usblp_bulk_read(struct urb *urb)
 {
 	struct usblp *usblp = urb->context;
 
@@ -288,7 +290,7 @@
 	wake_up_interruptible(&usblp->wait);
 }
 
-static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs)
+static void usblp_bulk_write(struct urb *urb)
 {
 	struct usblp *usblp = urb->context;
 
@@ -338,6 +340,20 @@
 	return newerr;
 }
 
+static int handle_bidir (struct usblp *usblp)
+{
+	if (usblp->bidir && usblp->used && !usblp->sleeping) {
+		usblp->readcount = 0;
+		usblp->readurb->dev = usblp->dev;
+		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
+			usblp->used = 0;
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * File op functions.
  */
@@ -390,14 +406,9 @@
 	usblp->writeurb->status = 0;
 	usblp->readurb->status = 0;
 
-	if (usblp->bidir) {
-		usblp->readcount = 0;
-		usblp->readurb->dev = usblp->dev;
-		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
-			retval = -EIO;
-			usblp->used = 0;
-			file->private_data = NULL;
-		}
+	if (handle_bidir(usblp) < 0) {
+		file->private_data = NULL;
+		retval = -EIO;
 	}
 out:
 	mutex_unlock (&usblp_mutex);
@@ -460,6 +471,11 @@
 		goto done;
 	}
 
+	if (usblp->sleeping) {
+		retval = -ENODEV;
+		goto done;
+	}
+
 	dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
 		_IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
 
@@ -658,6 +674,11 @@
 			return -ENODEV;
 		}
 
+		if (usblp->sleeping) {
+			up (&usblp->sem);
+			return writecount ? writecount : -ENODEV;
+		}
+
 		if (usblp->writeurb->status != 0) {
 			if (usblp->quirks & USBLP_QUIRK_BIDIR) {
 				if (!usblp->wcomplete)
@@ -749,6 +770,11 @@
 		goto done;
 	}
 
+	if (usblp->sleeping) {
+		count = -ENODEV;
+		goto done;
+	}
+
 	if (usblp->readurb->status) {
 		err("usblp%d: error %d reading from printer",
 			usblp->minor, usblp->readurb->status);
@@ -1167,6 +1193,41 @@
 	mutex_unlock (&usblp_mutex);
 }
 
+static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
+{
+	struct usblp *usblp = usb_get_intfdata (intf);
+
+	/* this races against normal access and open */
+	mutex_lock (&usblp_mutex);
+	down (&usblp->sem);
+	/* we take no more IO */
+	usblp->sleeping = 1;
+	/* we wait for anything printing */
+	wait_event (usblp->wait, usblp->wcomplete || !usblp->present);
+	usblp_unlink_urbs(usblp);
+	up (&usblp->sem);
+	mutex_unlock (&usblp_mutex);
+
+	return 0;
+}
+
+static int usblp_resume (struct usb_interface *intf)
+{
+	struct usblp *usblp = usb_get_intfdata (intf);
+	int r;
+
+	mutex_lock (&usblp_mutex);
+	down (&usblp->sem);
+
+	usblp->sleeping = 0;
+	r = handle_bidir (usblp);
+
+	up (&usblp->sem);
+	mutex_unlock (&usblp_mutex);
+
+	return r;
+}
+
 static struct usb_device_id usblp_ids [] = {
 	{ USB_DEVICE_INFO(7, 1, 1) },
 	{ USB_DEVICE_INFO(7, 1, 2) },
@@ -1183,6 +1244,8 @@
 	.name =		"usblp",
 	.probe =	usblp_probe,
 	.disconnect =	usblp_disconnect,
+	.suspend =	usblp_suspend,
+	.resume =	usblp_resume,
 	.id_table =	usblp_ids,
 };
 
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 3f509be..fed92be 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -304,7 +304,7 @@
 	printk("\n");
 }
 
-static void async_completed(struct urb *urb, struct pt_regs *regs)
+static void async_completed(struct urb *urb)
 {
         struct async *as = urb->context;
         struct dev_state *ps = as->ps;
@@ -1216,7 +1216,7 @@
 {
 	struct usbdevfs_urb uurb;
 
-	if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg))
+	if (get_urb32(&uurb,(struct usbdevfs_urb32 __user *)arg))
 		return -EFAULT;
 
 	return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg);
@@ -1251,7 +1251,7 @@
 	}
 
 	free_async(as);
-	if (put_user((u32)(u64)addr, (u32 __user *)arg))
+	if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
 		return -EFAULT;
 	return 0;
 }
@@ -1520,7 +1520,7 @@
 
 	case USBDEVFS_IOCTL32:
 		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
-		ret = proc_ioctl_compat(ps, (compat_uptr_t)(long)p);
+		ret = proc_ioctl_compat(ps, ptr_to_compat(p));
 		break;
 #endif
 
@@ -1588,15 +1588,18 @@
 	.release =	usbdev_release,
 };
 
-static void usbdev_add(struct usb_device *dev)
+static int usbdev_add(struct usb_device *dev)
 {
 	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
 	dev->class_dev = class_device_create(usb_device_class, NULL,
 				MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
 				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
+	if (IS_ERR(dev->class_dev))
+		return PTR_ERR(dev->class_dev);
 
 	dev->class_dev->class_data = dev;
+	return 0;
 }
 
 static void usbdev_remove(struct usb_device *dev)
@@ -1609,7 +1612,8 @@
 {
 	switch (action) {
 	case USB_DEVICE_ADD:
-		usbdev_add(dev);
+		if (usbdev_add(dev))
+			return NOTIFY_BAD;
 		break;
 	case USB_DEVICE_REMOVE:
 		usbdev_remove(dev);
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 3ebb901..3b2d137 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -223,7 +223,7 @@
 	ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
 	if (!ep_dev) {
 		retval = -ENOMEM;
-		goto exit;
+		goto error_alloc;
 	}
 
 	/* fun calculation to determine the minor of this endpoint */
@@ -241,33 +241,31 @@
 
 	retval = device_register(&ep_dev->dev);
 	if (retval)
-		goto error;
+		goto error_register;
 	retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
 	if (retval)
 		goto error_group;
 
-	endpoint->ep_dev = ep_dev;
-
 	/* create the symlink to the old-style "ep_XX" directory */
 	sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
-	retval = sysfs_create_link(&parent->kobj,
-				   &endpoint->ep_dev->dev.kobj, name);
+	retval = sysfs_create_link(&parent->kobj, &ep_dev->dev.kobj, name);
 	if (retval)
 		goto error_link;
-exit:
+	endpoint->ep_dev = ep_dev;
 	return retval;
 
 error_link:
 	sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
-
 error_group:
 	device_unregister(&ep_dev->dev);
-	endpoint->ep_dev = NULL;
 	destroy_endpoint_class();
 	return retval;
-error:
+
+error_register:
 	kfree(ep_dev);
+error_alloc:
 	destroy_endpoint_class();
+exit:
 	return retval;
 }
 
@@ -282,8 +280,6 @@
 		sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
 		device_unregister(&endpoint->ep_dev->dev);
 		endpoint->ep_dev = NULL;
+		destroy_endpoint_class();
 	}
-	destroy_endpoint_class();
 }
-
-
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e658089..afa2dd2 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -522,7 +522,7 @@
 	if (urb->status == -EINPROGRESS)
 		urb->status = status;
 	spin_unlock (&urb->lock);
-	usb_hcd_giveback_urb (hcd, urb, NULL);
+	usb_hcd_giveback_urb (hcd, urb);
 	local_irq_restore (flags);
 	return 0;
 }
@@ -572,7 +572,7 @@
 
 		/* local irqs are always blocked in completions */
 		if (length > 0)
-			usb_hcd_giveback_urb (hcd, urb, NULL);
+			usb_hcd_giveback_urb (hcd, urb);
 		else
 			hcd->poll_pending = 1;
 		local_irq_restore (flags);
@@ -656,7 +656,7 @@
 			urb = NULL;		/* wasn't fully queued */
 		spin_unlock (&hcd_root_hub_lock);
 		if (urb)
-			usb_hcd_giveback_urb (hcd, urb, NULL);
+			usb_hcd_giveback_urb (hcd, urb);
 		local_irq_restore (flags);
 	}
 
@@ -1498,7 +1498,6 @@
  * usb_hcd_giveback_urb - return URB from HCD to device driver
  * @hcd: host controller returning the URB
  * @urb: urb being returned to the USB device driver.
- * @regs: pt_regs, passed down to the URB completion handler
  * Context: in_interrupt()
  *
  * This hands the URB from HCD to its USB device driver, using its
@@ -1507,7 +1506,7 @@
  * the device driver won't cause problems if it frees, modifies,
  * or resubmits this URB.
  */
-void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
+void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
 {
 	int at_root_hub;
 
@@ -1534,7 +1533,7 @@
 
 	usbmon_urb_complete (&hcd->self, urb);
 	/* pass ownership to the completion handler */
-	urb->complete (urb, regs);
+	urb->complete (urb);
 	atomic_dec (&urb->use_count);
 	if (unlikely (urb->reject))
 		wake_up (&usb_kill_urb_queue);
@@ -1553,7 +1552,7 @@
  * If the controller isn't HALTed, calls the driver's irq handler.
  * Checks whether the controller is now dead.
  */
-irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
+irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
 	struct usb_hcd		*hcd = __hcd;
 	int			start = hcd->state;
@@ -1561,7 +1560,7 @@
 	if (unlikely(start == HC_STATE_HALT ||
 	    !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
 		return IRQ_NONE;
-	if (hcd->driver->irq (hcd, r) == IRQ_NONE)
+	if (hcd->driver->irq (hcd) == IRQ_NONE)
 		return IRQ_NONE;
 
 	set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 676877c..8f8df0d 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -143,15 +143,13 @@
 /*-------------------------------------------------------------------------*/
 
 
-struct pt_regs;
-
 struct hc_driver {
 	const char	*description;	/* "ehci-hcd" etc */
 	const char	*product_desc;	/* product/vendor string */
 	size_t		hcd_priv_size;	/* size of private data */
 
 	/* irq handler */
-	irqreturn_t	(*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
+	irqreturn_t	(*irq) (struct usb_hcd *hcd);
 
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
@@ -205,8 +203,7 @@
 
 extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
 extern int usb_hcd_unlink_urb (struct urb *urb, int status);
-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
-		struct pt_regs *regs);
+extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
 extern void usb_hcd_endpoint_disable (struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 extern int usb_hcd_get_frame_number (struct usb_device *udev);
@@ -248,7 +245,7 @@
 	void *addr, dma_addr_t dma);
 
 /* generic bus glue, needed for host controllers that don't use PCI */
-extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
+extern irqreturn_t usb_hcd_irq (int irq, void *__hcd);
 
 extern void usb_hc_died (struct usb_hcd *hcd);
 extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 7676690..66bff18 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -291,7 +291,7 @@
 
 
 /* completion function, fires on port status changes and various faults */
-static void hub_irq(struct urb *urb, struct pt_regs *regs)
+static void hub_irq(struct urb *urb)
 {
 	struct usb_hub *hub = urb->context;
 	int status;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 85b1cd1..fccd195 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -17,7 +17,7 @@
 #include "hcd.h"	/* for usbcore internals */
 #include "usb.h"
 
-static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
+static void usb_api_blocking_completion(struct urb *urb)
 {
 	complete((struct completion *)urb->context);
 }
@@ -246,7 +246,7 @@
 	io->dev = NULL;
 }
 
-static void sg_complete (struct urb *urb, struct pt_regs *regs)
+static void sg_complete (struct urb *urb)
 {
 	struct usb_sg_request	*io = urb->context;
 
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 77beba4..72f3db9 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1366,7 +1366,7 @@
 	}
 }
 
-static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r)
+static irqreturn_t at91_udc_irq (int irq, void *_udc)
 {
 	struct at91_udc		*udc = _udc;
 	u32			rescans = 5;
@@ -1552,7 +1552,7 @@
 	/* ep6 and ep7 are also reserved (custom silicon might use them) */
 };
 
-static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r)
+static irqreturn_t at91_vbus_irq(int irq, void *_udc)
 {
 	struct at91_udc	*udc = _udc;
 	unsigned	value;
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4d2946e..f1f32d7 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1551,7 +1551,7 @@
 			ep->already_seen = ep->setup_stage = 0;
 
 		spin_unlock (&dum->lock);
-		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb, NULL);
+		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb);
 		spin_lock (&dum->lock);
 
 		goto restart;
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 7cf2999..a3076da 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1628,7 +1628,7 @@
 		handled = 1; \
 		}
 
-static irqreturn_t goku_irq(int irq, void *_dev, struct pt_regs *r)
+static irqreturn_t goku_irq(int irq, void *_dev)
 {
 	struct goku_udc			*dev = _dev;
 	struct goku_udc_regs __iomem	*regs = dev->regs;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 36db725..1792596 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -922,7 +922,7 @@
 /*
  *	lh7a40x usb client interrupt handler.
  */
-static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev, struct pt_regs *r)
+static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev)
 {
 	struct lh7a40x_udc *dev = _dev;
 
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3bda37f..3acc896 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1774,8 +1774,8 @@
 
 #else
 
-#define device_create_file(a,b)	do {} while (0)
-#define device_remove_file	device_create_file
+#define device_create_file(a,b)	(0)
+#define device_remove_file(a,b)	do { } while (0)
 
 #endif
 
@@ -2044,8 +2044,10 @@
 		return retval;
 	}
 
-	device_create_file (&dev->pdev->dev, &dev_attr_function);
-	device_create_file (&dev->pdev->dev, &dev_attr_queues);
+	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
+	if (retval) goto err_unbind;
+	retval = device_create_file (&dev->pdev->dev, &dev_attr_queues);
+	if (retval) goto err_func;
 
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
@@ -2060,6 +2062,14 @@
 
 	/* pci writes may still be posted */
 	return 0;
+
+err_func:
+	device_remove_file (&dev->pdev->dev, &dev_attr_function);
+err_unbind:
+	driver->unbind (&dev->gadget);
+	dev->gadget.dev.driver = NULL;
+	dev->driver = NULL;
+	return retval;
 }
 EXPORT_SYMBOL (usb_gadget_register_driver);
 
@@ -2753,7 +2763,7 @@
 		DEBUG (dev, "unhandled irqstat1 %08x\n", stat);
 }
 
-static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r)
+static irqreturn_t net2280_irq (int irq, void *_dev)
 {
 	struct net2280		*dev = _dev;
 
@@ -2974,8 +2984,10 @@
 				: "disabled");
 	the_controller = dev;
 
-	device_register (&dev->gadget.dev);
-	device_create_file (&pdev->dev, &dev_attr_registers);
+	retval = device_register (&dev->gadget.dev);
+	if (retval) goto done;
+	retval = device_create_file (&pdev->dev, &dev_attr_registers);
+	if (retval) goto done;
 
 	return 0;
 
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 8c18df8..48a09fd 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1815,8 +1815,7 @@
 	UDC_IRQ_SRC_REG = UDC_DS_CHG;
 }
 
-static irqreturn_t
-omap_udc_irq(int irq, void *_udc, struct pt_regs *r)
+static irqreturn_t omap_udc_irq(int irq, void *_udc)
 {
 	struct omap_udc	*udc = _udc;
 	u16		irq_src;
@@ -1888,8 +1887,7 @@
 	spin_unlock_irqrestore(&ep->udc->lock, flags);
 }
 
-static irqreturn_t
-omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
+static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
 {
 	u16		epn_stat, irq_src;
 	irqreturn_t	status = IRQ_NONE;
@@ -1968,8 +1966,7 @@
 }
 
 #ifdef	USE_ISO
-static irqreturn_t
-omap_udc_iso_irq(int irq, void *_dev, struct pt_regs *r)
+static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
 {
 	struct omap_udc	*udc = _dev;
 	struct omap_ep	*ep;
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index f1adcf8..671c24b 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -43,11 +43,11 @@
 #include <linux/mm.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/irq.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
@@ -110,7 +110,7 @@
 module_param(use_dma, bool, 0);
 MODULE_PARM_DESC (use_dma, "true to use dma");
 
-static void dma_nodesc_handler (int dmach, void *_ep, struct pt_regs *r);
+static void dma_nodesc_handler (int dmach, void *_ep);
 static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
 
 #ifdef USE_OUT_DMA
@@ -828,7 +828,7 @@
 }
 
 /* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */
-static void dma_nodesc_handler(int dmach, void *_ep, struct pt_regs *r)
+static void dma_nodesc_handler(int dmach, void *_ep)
 {
 	struct pxa2xx_ep	*ep = _ep;
 	struct pxa2xx_request	*req;
@@ -1724,7 +1724,7 @@
  */
 
 static irqreturn_t
-lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
+lubbock_vbus_irq(int irq, void *_dev)
 {
 	struct pxa2xx_udc	*dev = _dev;
 	int			vbus;
@@ -1754,8 +1754,7 @@
 
 #endif
 
-static irqreturn_t
-udc_vbus_irq(int irq, void *_dev, struct pt_regs *r)
+static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 {
 	struct pxa2xx_udc	*dev = _dev;
 	int			vbus = pxa_gpio_get(dev->mach->gpio_vbus);
@@ -2084,7 +2083,7 @@
  * could cause usb protocol errors.
  */
 static irqreturn_t
-pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
+pxa2xx_udc_irq(int irq, void *_dev)
 {
 	struct pxa2xx_udc	*dev = _dev;
 	int			handled;
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 23b95b2..34b7a31 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -754,7 +754,9 @@
 	}
 
 	if (ehci->reclaim) {
-		temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim);
+		temp = scnprintf (next, size, "reclaim qh %p%s\n",
+				ehci->reclaim,
+				ehci->reclaim_ready ? " ready" : "");
 		size -= temp;
 		next += temp;
 	}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5ac9185..9030994 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -111,7 +111,7 @@
 #define	EHCI_TUNE_MULT_TT	1
 #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
 
-#define EHCI_IAA_MSECS		10		/* arbitrary */
+#define EHCI_IAA_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
 #define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
@@ -254,8 +254,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs);
-static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
+static void ehci_work(struct ehci_hcd *ehci);
 
 #include "ehci-hub.c"
 #include "ehci-mem.c"
@@ -264,29 +263,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_iaa_watchdog (unsigned long param)
-{
-	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
-	unsigned long		flags;
-	u32			status;
-
-	spin_lock_irqsave (&ehci->lock, flags);
-	WARN_ON(!ehci->reclaim);
-
-	/* lost IAA irqs wedge things badly; seen first with a vt8235 */
-	if (ehci->reclaim) {
-		status = readl (&ehci->regs->status);
-		if (status & STS_IAA) {
-			ehci_vdbg (ehci, "lost IAA\n");
-			COUNT (ehci->stats.lost_iaa);
-			writel (STS_IAA, &ehci->regs->status);
-			end_unlink_async (ehci, NULL);
-		}
-	}
-
-	spin_unlock_irqrestore (&ehci->lock, flags);
-}
-
 static void ehci_watchdog (unsigned long param)
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
@@ -294,12 +270,23 @@
 
 	spin_lock_irqsave (&ehci->lock, flags);
 
-	/* stop async processing after it's idled a bit */
+	/* lost IAA irqs wedge things badly; seen with a vt8235 */
+	if (ehci->reclaim) {
+		u32		status = readl (&ehci->regs->status);
+		if (status & STS_IAA) {
+			ehci_vdbg (ehci, "lost IAA\n");
+			COUNT (ehci->stats.lost_iaa);
+			writel (STS_IAA, &ehci->regs->status);
+			ehci->reclaim_ready = 1;
+		}
+	}
+
+ 	/* stop async processing after it's idled a bit */
 	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
 		start_unlink_async (ehci, ehci->async);
 
 	/* ehci could run by timer, without IRQs ... */
-	ehci_work (ehci, NULL);
+	ehci_work (ehci);
 
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
@@ -342,9 +329,11 @@
  * ehci_work is called from some interrupts, timers, and so on.
  * it calls driver completion functions, after dropping ehci->lock.
  */
-static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
+static void ehci_work (struct ehci_hcd *ehci)
 {
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
+	if (ehci->reclaim_ready)
+		end_unlink_async (ehci);
 
 	/* another CPU may drop ehci->lock during a schedule scan while
 	 * it reports urb completions.  this flag guards against bogus
@@ -353,9 +342,9 @@
 	if (ehci->scanning)
 		return;
 	ehci->scanning = 1;
-	scan_async (ehci, regs);
+	scan_async (ehci);
 	if (ehci->next_uframe != -1)
-		scan_periodic (ehci, regs);
+		scan_periodic (ehci);
 	ehci->scanning = 0;
 
 	/* the IO watchdog guards against hardware or driver bugs that
@@ -379,7 +368,6 @@
 
 	/* no more interrupts ... */
 	del_timer_sync (&ehci->watchdog);
-	del_timer_sync (&ehci->iaa_watchdog);
 
 	spin_lock_irq(&ehci->lock);
 	if (HC_IS_RUNNING (hcd->state))
@@ -397,7 +385,7 @@
 	/* root hub is shut down separately (first, when possible) */
 	spin_lock_irq (&ehci->lock);
 	if (ehci->async)
-		ehci_work (ehci, NULL);
+		ehci_work (ehci);
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
@@ -426,10 +414,6 @@
 	ehci->watchdog.function = ehci_watchdog;
 	ehci->watchdog.data = (unsigned long) ehci;
 
-	init_timer(&ehci->iaa_watchdog);
-	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
-	ehci->iaa_watchdog.data = (unsigned long) ehci;
-
 	/*
 	 * hw default: 1K periodic list heads, one per frame.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -446,6 +430,7 @@
 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
 	ehci->reclaim = NULL;
+	ehci->reclaim_ready = 0;
 	ehci->next_uframe = -1;
 
 	/*
@@ -573,7 +558,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			status;
@@ -619,7 +604,7 @@
 	/* complete the unlinking of some qh [4.15.2.3] */
 	if (status & STS_IAA) {
 		COUNT (ehci->stats.reclaim);
-		end_unlink_async (ehci, regs);
+		ehci->reclaim_ready = 1;
 		bh = 1;
 	}
 
@@ -670,7 +655,7 @@
 	}
 
 	if (bh)
-		ehci_work (ehci, regs);
+		ehci_work (ehci);
 	spin_unlock (&ehci->lock);
 	return IRQ_HANDLED;
 }
@@ -723,14 +708,10 @@
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	// BUG_ON(qh->qh_state != QH_STATE_LINKED);
-
-	/* failfast */
-	if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
-		end_unlink_async (ehci, NULL);
-
-	/* defer till later if busy */
-	else if (ehci->reclaim) {
+	/* if we need to use IAA and it's busy, defer */
+	if (qh->qh_state == QH_STATE_LINKED
+			&& ehci->reclaim
+			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
 		struct ehci_qh		*last;
 
 		for (last = ehci->reclaim;
@@ -740,8 +721,12 @@
 		qh->qh_state = QH_STATE_UNLINK_WAIT;
 		last->reclaim = qh;
 
-	/* start IAA cycle */
-	} else
+	/* bypass IAA if the hc can't care */
+	} else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
+		end_unlink_async (ehci);
+
+	/* something else might have unlinked the qh by now */
+	if (qh->qh_state == QH_STATE_LINKED)
 		start_unlink_async (ehci, qh);
 }
 
@@ -763,19 +748,7 @@
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 			break;
-		switch (qh->qh_state) {
-		case QH_STATE_LINKED:
-		case QH_STATE_COMPLETING:
-			unlink_async (ehci, qh);
-			break;
-		case QH_STATE_UNLINK:
-		case QH_STATE_UNLINK_WAIT:
-			/* already started */
-			break;
-		case QH_STATE_IDLE:
-			WARN_ON(1);
-			break;
-		}
+		unlink_async (ehci, qh);
 		break;
 
 	case PIPE_INTERRUPT:
@@ -787,7 +760,7 @@
 			intr_deschedule (ehci, qh);
 			/* FALL THROUGH */
 		case QH_STATE_IDLE:
-			qh_completions (ehci, qh, NULL);
+			qh_completions (ehci, qh);
 			break;
 		default:
 			ehci_dbg (ehci, "bogus qh %p state %d\n",
@@ -867,7 +840,6 @@
 		unlink_async (ehci, qh);
 		/* FALL THROUGH */
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
-	case QH_STATE_UNLINK_WAIT:
 idle_timeout:
 		spin_unlock_irqrestore (&ehci->lock, flags);
 		schedule_timeout_uninterruptible(1);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index b2ee13c..1b20722 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -48,8 +48,8 @@
 	}
 	ehci->command = readl (&ehci->regs->command);
 	if (ehci->reclaim)
-		end_unlink_async (ehci, NULL);
-	ehci_work(ehci, NULL);
+		ehci->reclaim_ready = 1;
+	ehci_work(ehci);
 
 	/* suspend any active/unsuspended ports, maybe allow wakeup */
 	while (port--) {
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 08d0472..e51c1ed8 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -303,8 +303,8 @@
 	/* emptying the schedule aborts any urbs */
 	spin_lock_irq(&ehci->lock);
 	if (ehci->reclaim)
-		end_unlink_async (ehci, NULL);
-	ehci_work(ehci, NULL);
+		ehci->reclaim_ready = 1;
+	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 
 	/* restart; khubd will disconnect devices */
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 7fc25b6..62e46dc 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -214,7 +214,7 @@
 }
 
 static void
-ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs)
+ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb)
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
@@ -262,7 +262,7 @@
 
 	/* complete() can reenter this HCD */
 	spin_unlock (&ehci->lock);
-	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb, regs);
+	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb);
 	spin_lock (&ehci->lock);
 }
 
@@ -279,7 +279,7 @@
  */
 #define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
 static unsigned
-qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
+qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	struct ehci_qtd		*last = NULL, *end = qh->dummy;
 	struct list_head	*entry, *tmp;
@@ -317,7 +317,7 @@
 		/* clean up any state from previous QTD ...*/
 		if (last) {
 			if (likely (last->urb != urb)) {
-				ehci_urb_done (ehci, last->urb, regs);
+				ehci_urb_done (ehci, last->urb);
 				count++;
 			}
 			ehci_qtd_free (ehci, last);
@@ -407,7 +407,7 @@
 
 	/* last urb's completion might still need calling */
 	if (likely (last != NULL)) {
-		ehci_urb_done (ehci, last->urb, regs);
+		ehci_urb_done (ehci, last->urb);
 		count++;
 		ehci_qtd_free (ehci, last);
 	}
@@ -962,12 +962,12 @@
 
 /* the async qh for the qtds being reclaimed are now unlinked from the HC */
 
-static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
+static void end_unlink_async (struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*next;
 
-	iaa_watchdog_done (ehci);
+	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
 
 	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
@@ -977,9 +977,10 @@
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
 	next = qh->reclaim;
 	ehci->reclaim = next;
+	ehci->reclaim_ready = 0;
 	qh->reclaim = NULL;
 
-	qh_completions (ehci, qh, regs);
+	qh_completions (ehci, qh);
 
 	if (!list_empty (&qh->qtd_list)
 			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
@@ -1047,20 +1048,20 @@
 		/* if (unlikely (qh->reclaim != 0))
 		 *	this will recurse, probably not much
 		 */
-		end_unlink_async (ehci, NULL);
+		end_unlink_async (ehci);
 		return;
 	}
 
+	ehci->reclaim_ready = 0;
 	cmd |= CMD_IAAD;
 	writel (cmd, &ehci->regs->command);
 	(void) readl (&ehci->regs->command);
-	iaa_watchdog_start (ehci);
+	timer_action (ehci, TIMER_IAA_WATCHDOG);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static void
-scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
+static void scan_async (struct ehci_hcd *ehci)
 {
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
@@ -1084,7 +1085,7 @@
 				 */
 				qh = qh_get (qh);
 				qh->stamp = ehci->stamp;
-				temp = qh_completions (ehci, qh, regs);
+				temp = qh_completions (ehci, qh);
 				qh_put (qh);
 				if (temp != 0) {
 					goto rescan;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index e5e9c65..65c402a 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1553,8 +1553,7 @@
 static unsigned
 itd_complete (
 	struct ehci_hcd	*ehci,
-	struct ehci_itd	*itd,
-	struct pt_regs	*regs
+	struct ehci_itd	*itd
 ) {
 	struct urb				*urb = itd->urb;
 	struct usb_iso_packet_descriptor	*desc;
@@ -1613,7 +1612,7 @@
 
 	/* give urb back to the driver ... can be out-of-order */
 	dev = urb->dev;
-	ehci_urb_done (ehci, urb, regs);
+	ehci_urb_done (ehci, urb);
 	urb = NULL;
 
 	/* defer stopping schedule; completion can submit */
@@ -1930,8 +1929,7 @@
 static unsigned
 sitd_complete (
 	struct ehci_hcd		*ehci,
-	struct ehci_sitd	*sitd,
-	struct pt_regs		*regs
+	struct ehci_sitd	*sitd
 ) {
 	struct urb				*urb = sitd->urb;
 	struct usb_iso_packet_descriptor	*desc;
@@ -1978,7 +1976,7 @@
 
 	/* give urb back to the driver */
 	dev = urb->dev;
-	ehci_urb_done (ehci, urb, regs);
+	ehci_urb_done (ehci, urb);
 	urb = NULL;
 
 	/* defer stopping schedule; completion can submit */
@@ -2065,8 +2063,7 @@
 static inline unsigned
 sitd_complete (
 	struct ehci_hcd		*ehci,
-	struct ehci_sitd	*sitd,
-	struct pt_regs		*regs
+	struct ehci_sitd	*sitd
 ) {
 	ehci_err (ehci, "sitd_complete %p?\n", sitd);
 	return 0;
@@ -2077,7 +2074,7 @@
 /*-------------------------------------------------------------------------*/
 
 static void
-scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
+scan_periodic (struct ehci_hcd *ehci)
 {
 	unsigned	frame, clock, now_uframe, mod;
 	unsigned	modified;
@@ -2131,7 +2128,7 @@
 				temp.qh = qh_get (q.qh);
 				type = Q_NEXT_TYPE (q.qh->hw_next);
 				q = q.qh->qh_next;
-				modified = qh_completions (ehci, temp.qh, regs);
+				modified = qh_completions (ehci, temp.qh);
 				if (unlikely (list_empty (&temp.qh->qtd_list)))
 					intr_deschedule (ehci, temp.qh);
 				qh_put (temp.qh);
@@ -2169,7 +2166,7 @@
 				*hw_p = q.itd->hw_next;
 				type = Q_NEXT_TYPE (q.itd->hw_next);
 				wmb();
-				modified = itd_complete (ehci, q.itd, regs);
+				modified = itd_complete (ehci, q.itd);
 				q = *q_p;
 				break;
 			case Q_TYPE_SITD:
@@ -2185,7 +2182,7 @@
 				*hw_p = q.sitd->hw_next;
 				type = Q_NEXT_TYPE (q.sitd->hw_next);
 				wmb();
-				modified = sitd_complete (ehci, q.sitd, regs);
+				modified = sitd_complete (ehci, q.sitd);
 				q = *q_p;
 				break;
 			default:
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 6aac39f..bbc3082 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -58,6 +58,7 @@
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
+	unsigned		reclaim_ready : 1;
 	unsigned		scanning : 1;
 
 	/* periodic schedule support */
@@ -80,7 +81,6 @@
 	struct dma_pool		*itd_pool;	/* itd per iso urb */
 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
 
-	struct timer_list	iaa_watchdog;
 	struct timer_list	watchdog;
 	unsigned long		actions;
 	unsigned		stamp;
@@ -114,21 +114,9 @@
 }
 
 
-static inline void
-iaa_watchdog_start (struct ehci_hcd *ehci)
-{
-	WARN_ON(timer_pending(&ehci->iaa_watchdog));
-	mod_timer (&ehci->iaa_watchdog,
-			jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
-}
-
-static inline void iaa_watchdog_done (struct ehci_hcd *ehci)
-{
-	del_timer (&ehci->iaa_watchdog);
-}
-
 enum ehci_timer_action {
 	TIMER_IO_WATCHDOG,
+	TIMER_IAA_WATCHDOG,
 	TIMER_ASYNC_SHRINK,
 	TIMER_ASYNC_OFF,
 };
@@ -146,6 +134,9 @@
 		unsigned long t;
 
 		switch (action) {
+		case TIMER_IAA_WATCHDOG:
+			t = EHCI_IAA_JIFFIES;
+			break;
 		case TIMER_IO_WATCHDOG:
 			t = EHCI_IO_JIFFIES;
 			break;
@@ -162,7 +153,8 @@
 		// async queue SHRINK often precedes IAA.  while it's ready
 		// to go OFF neither can matter, and afterwards the IO
 		// watchdog stops unless there's still periodic traffic.
-		if (time_before_eq(t, ehci->watchdog.expires)
+		if (action != TIMER_IAA_WATCHDOG
+				&& t > ehci->watchdog.expires
 				&& timer_pending (&ehci->watchdog))
 			return;
 		mod_timer (&ehci->watchdog, t);
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 61e5717..87eca6a 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -478,9 +478,9 @@
 static int etrax_usb_unlink_urb(struct urb *urb, int status);
 static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
 
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc, struct pt_regs *regs);
+static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc);
+static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc);
+static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc);
 static void etrax_usb_hc_interrupt_bottom_half(void *data);
 
 static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data);
@@ -1573,7 +1573,7 @@
 	return (*R_USB_FM_NUMBER & 0x7ff);
 }
 
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs)
+static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc)
 {
 	DBFENTER;
 
@@ -1839,7 +1839,7 @@
 
 
 
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs)
+static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc)
 {
 	struct urb *urb;
 	etrax_urb_priv_t *urb_priv;
@@ -3280,7 +3280,7 @@
 
 
 
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc, struct pt_regs *regs)
+static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc)
 {
 	usb_interrupt_registers_t *reg;
 	unsigned long flags;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index a72e041..2718b5d 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -418,7 +418,7 @@
   processed urbs.
 */
 static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
-			   struct urb *urb, struct pt_regs *regs)
+			   struct urb *urb)
 __releases(isp116x->lock) __acquires(isp116x->lock)
 {
 	unsigned i;
@@ -432,7 +432,7 @@
 	urb_dbg(urb, "Finish");
 
 	spin_unlock(&isp116x->lock);
-	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, regs);
+	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
 	spin_lock(&isp116x->lock);
 
 	/* take idle endpoints out of the schedule */
@@ -568,7 +568,7 @@
 /*
   Finish the processed transfers
 */
-static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs)
+static void finish_atl_transfers(struct isp116x *isp116x)
 {
 	struct isp116x_ep *ep;
 	struct urb *urb;
@@ -590,12 +590,12 @@
 		   occured, while URB_SHORT_NOT_OK was set */
 		if (urb && urb->status != -EINPROGRESS
 		    && ep->nextpid != USB_PID_ACK)
-			finish_request(isp116x, ep, urb, regs);
+			finish_request(isp116x, ep, urb);
 	}
 	atomic_dec(&isp116x->atl_finishing);
 }
 
-static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
 {
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	u16 irqstat;
@@ -608,7 +608,7 @@
 
 	if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) {
 		ret = IRQ_HANDLED;
-		finish_atl_transfers(isp116x, regs);
+		finish_atl_transfers(isp116x);
 	}
 
 	if (irqstat & HCuPINT_OPR) {
@@ -824,7 +824,7 @@
 	spin_lock(&urb->lock);
 	if (urb->status != -EINPROGRESS) {
 		spin_unlock(&urb->lock);
-		finish_request(isp116x, ep, urb, NULL);
+		finish_request(isp116x, ep, urb);
 		ret = 0;
 		goto fail;
 	}
@@ -870,7 +870,7 @@
 			}
 
 	if (urb)
-		finish_request(isp116x, ep, urb, NULL);
+		finish_request(isp116x, ep, urb);
 
 	spin_unlock_irqrestore(&isp116x->lock, flags);
 	return 0;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index d1d68c4..9be6b30 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -261,7 +261,7 @@
 	if (urb->status != -EINPROGRESS) {
 		spin_unlock (&urb->lock);
 		urb->hcpriv = urb_priv;
-		finish_urb (ohci, urb, NULL);
+		finish_urb (ohci, urb);
 		retval = 0;
 		goto fail;
 	}
@@ -337,7 +337,7 @@
 		 * any more ... just clean up every urb's memory.
 		 */
 		if (urb->hcpriv)
-			finish_urb (ohci, urb, NULL);
+			finish_urb (ohci, urb);
 	}
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return 0;
@@ -369,7 +369,7 @@
 	if (!HC_IS_RUNNING (hcd->state)) {
 sanitize:
 		ed->state = ED_IDLE;
-		finish_unlinks (ohci, 0, NULL);
+		finish_unlinks (ohci, 0);
 	}
 
 	switch (ed->state) {
@@ -691,7 +691,7 @@
 
 /* an interrupt happens */
 
-static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
+static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	struct ohci_regs __iomem *regs = ohci->regs;
@@ -747,7 +747,7 @@
 		if (HC_IS_RUNNING(hcd->state))
 			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
 		spin_lock (&ohci->lock);
-		dl_done_list (ohci, ptregs);
+		dl_done_list (ohci);
 		spin_unlock (&ohci->lock);
 		if (HC_IS_RUNNING(hcd->state))
 			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable); 
@@ -760,7 +760,7 @@
 	 */
 	spin_lock (&ohci->lock);
 	if (ohci->ed_rm_list)
-		finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
+		finish_unlinks (ohci, ohci_frame_no(ohci));
 	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
 			&& HC_IS_RUNNING(hcd->state))
 		ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);	
@@ -852,7 +852,7 @@
 		urb->status = -ESHUTDOWN;
 		spin_unlock (&urb->lock);
 	}
-	finish_unlinks (ohci, 0, NULL);
+	finish_unlinks (ohci, 0);
 	spin_unlock_irq(&ohci->lock);
 
 	/* paranoia, in case that didn't work: */
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index ec75774..6f11359 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -47,8 +47,8 @@
 #define OHCI_SCHED_ENABLES \
 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
-static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
-static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
+static void dl_done_list (struct ohci_hcd *);
+static void finish_unlinks (struct ohci_hcd *, u16);
 
 static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
 __releases(ohci->lock)
@@ -94,8 +94,8 @@
 		msleep (8);
 		spin_lock_irq (&ohci->lock);
 	}
-	dl_done_list (ohci, NULL);
-	finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
+	dl_done_list (ohci);
+	finish_unlinks (ohci, ohci_frame_no(ohci));
 
 	/* maybe resume can wake root hub */
 	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 82cb22f..2dbb774 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -262,6 +262,7 @@
 	 */
 	.start = ohci_pnx4008_start,
 	.stop = ohci_stop,
+	.shutdown = ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -280,7 +281,11 @@
 	 */
 	.hub_status_data = ohci_hub_status_data,
 	.hub_control = ohci_hub_control,
-
+	.hub_irq_enable = ohci_rhsc_enable,
+#ifdef	CONFIG_PM
+	.bus_suspend = ohci_bus_suspend,
+	.bus_resume = ohci_bus_resume,
+#endif
 	.start_port_reset = ohci_start_port_reset,
 };
 
@@ -410,8 +415,6 @@
 		goto out4;
 	}
 
-	hcd->self.hcpriv = (void *)hcd;
-
 	pnx4008_start_hc();
 	platform_set_drvdata(pdev, hcd);
 	ohci = hcd_to_ohci(hcd);
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index e372306..fe1fe2f 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -7,6 +7,8 @@
  * This file is licenced under the GPL.
  */
 
+#include <linux/irq.h>
+
 static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
 {
 	int		last = urb_priv->length - 1;
@@ -34,7 +36,7 @@
  * PRECONDITION:  ohci lock held, irqs blocked.
  */
 static void
-finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
+finish_urb (struct ohci_hcd *ohci, struct urb *urb)
 __releases(ohci->lock)
 __acquires(ohci->lock)
 {
@@ -73,7 +75,7 @@
 
 	/* urb->complete() can reenter this HCD */
 	spin_unlock (&ohci->lock);
-	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb, regs);
+	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb);
 	spin_lock (&ohci->lock);
 
 	/* stop periodic dma if it's not needed */
@@ -910,7 +912,7 @@
 
 /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
 static void
-finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
+finish_unlinks (struct ohci_hcd *ohci, u16 tick)
 {
 	struct ed	*ed, **last;
 
@@ -923,7 +925,7 @@
 		/* only take off EDs that the HC isn't using, accounting for
 		 * frame counter wraps and EDs with partially retired TDs
 		 */
-		if (likely (regs && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
+		if (likely (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
 			if (tick_before (tick, ed->tick)) {
 skip_ed:
 				last = &ed->ed_next;
@@ -990,7 +992,7 @@
 			/* if URB is done, clean up */
 			if (urb_priv->td_cnt == urb_priv->length) {
 				modified = completed = 1;
-				finish_urb (ohci, urb, regs);
+				finish_urb (ohci, urb);
 			}
 		}
 		if (completed && !list_empty (&ed->td_list))
@@ -1068,7 +1070,7 @@
  * scanning the (re-reversed) donelist as this does.
  */
 static void
-dl_done_list (struct ohci_hcd *ohci, struct pt_regs *regs)
+dl_done_list (struct ohci_hcd *ohci)
 {
 	struct td	*td = dl_reverse_done_list (ohci);
 
@@ -1084,7 +1086,7 @@
 
 		/* If all this urb's TDs are done, call complete() */
   		if (urb_priv->td_cnt == urb_priv->length)
-  			finish_urb (ohci, urb, regs);
+  			finish_urb (ohci, urb);
 
 		/* clean schedule:  unlink EDs that are no longer busy */
 		if (list_empty (&ed->td_list)) {
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 3a586aa..5fa5647 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -428,7 +428,6 @@
 	struct sl811		*sl811,
 	struct sl811h_ep	*ep,
 	struct urb		*urb,
-	struct pt_regs		*regs,
 	int			status
 ) __releases(sl811->lock) __acquires(sl811->lock)
 {
@@ -444,7 +443,7 @@
 	spin_unlock(&urb->lock);
 
 	spin_unlock(&sl811->lock);
-	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, regs);
+	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb);
 	spin_lock(&sl811->lock);
 
 	/* leave active endpoints in the schedule */
@@ -484,7 +483,7 @@
 }
 
 static void
-done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
+done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
 {
 	u8			status;
 	struct urb		*urb;
@@ -608,7 +607,7 @@
 	}
 
 	if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS))
-		finish_request(sl811, ep, urb, regs, urbstat);
+		finish_request(sl811, ep, urb, urbstat);
 }
 
 static inline u8 checkdone(struct sl811 *sl811)
@@ -641,7 +640,7 @@
 	return irqstat;
 }
 
-static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t sl811h_irq(struct usb_hcd *hcd)
 {
 	struct sl811	*sl811 = hcd_to_sl811(hcd);
 	u8		irqstat;
@@ -670,13 +669,13 @@
 	 * issued ... that's fine if they're different endpoints.
 	 */
 	if (irqstat & SL11H_INTMASK_DONE_A) {
-		done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF), regs);
+		done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF));
 		sl811->active_a = NULL;
 		sl811->stat_a++;
 	}
 #ifdef USE_B
 	if (irqstat & SL11H_INTMASK_DONE_B) {
-		done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF), regs);
+		done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF));
 		sl811->active_b = NULL;
 		sl811->stat_b++;
 	}
@@ -723,7 +722,7 @@
 				container_of(sl811->active_a
 						->hep->urb_list.next,
 					struct urb, urb_list),
-				NULL, -ESHUTDOWN);
+				-ESHUTDOWN);
 			sl811->active_a = NULL;
 		}
 #ifdef	USE_B
@@ -957,7 +956,7 @@
 	spin_lock(&urb->lock);
 	if (urb->status != -EINPROGRESS) {
 		spin_unlock(&urb->lock);
-		finish_request(sl811, ep, urb, NULL, 0);
+		finish_request(sl811, ep, urb, 0);
 		retval = 0;
 		goto fail;
 	}
@@ -1026,7 +1025,7 @@
 		}
 
 		if (urb)
-			finish_request(sl811, ep, urb, NULL, 0);
+			finish_request(sl811, ep, urb, 0);
 		else
 			VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
 				(sl811->active_a == ep) ? "A" : "B");
@@ -1083,7 +1082,7 @@
 	 */
 	local_irq_save(flags);
 	if (!timer_pending(&sl811->timer)) {
-		if (sl811h_irq( /* ~0, */ hcd, NULL) != IRQ_NONE)
+		if (sl811h_irq( /* ~0, */ hcd) != IRQ_NONE)
 			sl811->stat_lost++;
 	}
 	local_irq_restore(flags);
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 0a31520..32c635e 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -557,7 +557,7 @@
         u132_ring_queue_work(u132, ring, 0);
         up(&u132->scheduler_lock);
         u132_endp_put_kref(u132, endp);
-        usb_hcd_giveback_urb(hcd, urb, NULL);
+        usb_hcd_giveback_urb(hcd, urb);
         return;
 }
 
@@ -590,7 +590,7 @@
                 endp->active = 0;
                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
                 kfree(urbq);
-        } usb_hcd_giveback_urb(hcd, urb, NULL);
+        } usb_hcd_giveback_urb(hcd, urb);
         return;
 }
 
@@ -2434,7 +2434,7 @@
                         endp->queue_size -= 1;
                         urb->error_count = 0;
                         urb->hcpriv = NULL;
-                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        usb_hcd_giveback_urb(hcd, urb);
                         return 0;
                 } else
                         continue;
@@ -2512,7 +2512,7 @@
                                 kfree(urbq);
                         } urb->error_count = 0;
                         urb->hcpriv = NULL;
-                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        usb_hcd_giveback_urb(hcd, urb);
                         return 0;
                 } else if (list_empty(&endp->urb_more)) {
                         dev_err(&u132->platform_dev->dev, "urb=%p not found in "
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index eb4eab9..226bf3d 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -40,6 +40,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/usb.h>
 #include <linux/bitops.h>
+#include <linux/dmi.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -196,12 +197,42 @@
 	return 0;
 }
 
+static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
+{
+	static struct dmi_system_id broken_wakeup_table[] = {
+		{
+			.ident = "Asus A7V8X",
+			.matches = {
+				DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
+				DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
+				DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
+			}
+		},
+		{ }
+	};
+	int port;
+
+	/* One of Asus's motherboards has a bug which causes it to
+	 * wake up immediately from suspend-to-RAM if any of the ports
+	 * are connected.  In such cases we will not set EGSM.
+	 */
+	if (dmi_check_system(broken_wakeup_table)) {
+		for (port = 0; port < uhci->rh_numports; ++port) {
+			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
+					USBPORTSC_CCS)
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
 static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
 	int auto_stop;
-	int int_enable;
+	int int_enable, egsm_enable;
 
 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
 	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
@@ -217,15 +248,18 @@
 	}
 
 	/* Enable resume-detect interrupts if they work.
-	 * Then enter Global Suspend mode, still configured.
+	 * Then enter Global Suspend mode if _it_ works, still configured.
 	 */
+	egsm_enable = USBCMD_EGSM;
 	uhci->working_RD = 1;
 	int_enable = USBINTR_RESUME;
-	if (resume_detect_interrupts_are_broken(uhci)) {
+	if (remote_wakeup_is_broken(uhci))
+		egsm_enable = 0;
+	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable)
 		uhci->working_RD = int_enable = 0;
-	}
+
 	outw(int_enable, uhci->io_addr + USBINTR);
-	outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
+	outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
 	mb();
 	udelay(5);
 
@@ -252,7 +286,7 @@
 	uhci->is_stopped = UHCI_IS_STOPPED;
 	uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
-	uhci_scan_schedule(uhci, NULL);
+	uhci_scan_schedule(uhci);
 	uhci_fsbr_off(uhci);
 }
 
@@ -309,7 +343,7 @@
 	mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
-static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t uhci_irq(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned short status;
@@ -358,7 +392,7 @@
 		usb_hcd_poll_rh_status(hcd);
 	else {
 		spin_lock_irqsave(&uhci->lock, flags);
-		uhci_scan_schedule(uhci, regs);
+		uhci_scan_schedule(uhci);
 		spin_unlock_irqrestore(&uhci->lock, flags);
 	}
 
@@ -671,7 +705,7 @@
 	spin_lock_irq(&uhci->lock);
 	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
 		uhci_hc_died(uhci);
-	uhci_scan_schedule(uhci, NULL);
+	uhci_scan_schedule(uhci);
 	spin_unlock_irq(&uhci->lock);
 
 	del_timer_sync(&uhci->fsbr_timer);
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 16fb72e..f8347f1 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -176,7 +176,7 @@
 
 	spin_lock_irqsave(&uhci->lock, flags);
 
-	uhci_scan_schedule(uhci, NULL);
+	uhci_scan_schedule(uhci);
 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
 		goto done;
 	uhci_check_ports(uhci);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 431e8f3..06115f2 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1244,7 +1244,7 @@
  * Finish unlinking an URB and give it back
  */
 static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
-		struct urb *urb, struct pt_regs *regs)
+		struct urb *urb)
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
@@ -1293,7 +1293,7 @@
 	}
 
 	spin_unlock(&uhci->lock);
-	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, regs);
+	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);
 	spin_lock(&uhci->lock);
 
 	/* If the queue is now empty, we can unlink the QH and give up its
@@ -1313,8 +1313,7 @@
 		(qh->state == QH_STATE_UNLINKING &&	\
 		uhci->frame_number + uhci->is_stopped != qh->unlink_frame)
 
-static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
-		struct pt_regs *regs)
+static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct urb_priv *urbp;
 	struct urb *urb;
@@ -1347,7 +1346,7 @@
 				return;
 		}
 
-		uhci_giveback_urb(uhci, qh, urb, regs);
+		uhci_giveback_urb(uhci, qh, urb);
 		if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
 			break;
 	}
@@ -1372,7 +1371,7 @@
 				qh->is_stopped = 0;
 				return;
 			}
-			uhci_giveback_urb(uhci, qh, urb, regs);
+			uhci_giveback_urb(uhci, qh, urb);
 			goto restart;
 		}
 	}
@@ -1487,7 +1486,7 @@
 /*
  * Process events in the schedule, but only in one thread at a time
  */
-static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+static void uhci_scan_schedule(struct uhci_hcd *uhci)
 {
 	int i;
 	struct uhci_qh *qh;
@@ -1515,7 +1514,7 @@
 					struct uhci_qh, node);
 
 			if (uhci_advance_check(uhci, qh)) {
-				uhci_scan_qh(uhci, qh, regs);
+				uhci_scan_qh(uhci, qh);
 				if (qh->state == QH_STATE_ACTIVE) {
 					uhci_urbp_wants_fsbr(uhci,
 	list_entry(qh->queue.next, struct urb_priv, node));
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index ca6305c..63a84bb 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -280,7 +280,7 @@
 /*
  * USB IRQ Handler for InputLine
  */
-static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_irq (struct urb *urb)
 {
 	int data_received=0, wake_up;
 	unsigned char* b=urb->transfer_buffer;
@@ -374,7 +374,7 @@
 /*
  * The write_urb callback function
  */
-static void mdc800_usb_write_notify (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_write_notify (struct urb *urb)
 {
 	struct mdc800_data* mdc800=urb->context;
 
@@ -394,7 +394,7 @@
 /*
  * The download_urb callback function
  */
-static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_download_notify (struct urb *urb)
 {
 	struct mdc800_data* mdc800=urb->context;
 
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 5f86133..3038ed0 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -370,7 +370,7 @@
 mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback);
 
 static void mts_transfer_cleanup( struct urb *transfer );
-static void mts_do_sg(struct urb * transfer, struct pt_regs *regs);
+static void mts_do_sg(struct urb * transfer);
 
 static inline
 void mts_int_submit_urb (struct urb* transfer,
@@ -417,7 +417,7 @@
 
 }
 
-static void mts_transfer_done( struct urb *transfer, struct pt_regs *regs )
+static void mts_transfer_done( struct urb *transfer )
 {
 	MTS_INT_INIT();
 
@@ -443,7 +443,7 @@
 			   mts_transfer_done );
 }
 
-static void mts_data_done( struct urb* transfer, struct pt_regs *regs )
+static void mts_data_done( struct urb* transfer )
 /* Interrupt context! */
 {
 	MTS_INT_INIT();
@@ -460,7 +460,7 @@
 }
 
 
-static void mts_command_done( struct urb *transfer, struct pt_regs *regs )
+static void mts_command_done( struct urb *transfer )
 /* Interrupt context! */
 {
 	MTS_INT_INIT();
@@ -501,7 +501,7 @@
 	return;
 }
 
-static void mts_do_sg (struct urb* transfer, struct pt_regs *regs)
+static void mts_do_sg (struct urb* transfer)
 {
 	struct scatterlist * sg;
 	MTS_INT_INIT();
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 21cd226..20db364 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -348,13 +348,3 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called appletouch.
-
-config USB_TRANCEVIBRATOR
-	tristate "PlayStation 2 Trance Vibrator driver support"
-	depends on USB
-	help
-	  Say Y here if you want to connect a PlayStation 2 Trance Vibrator
-	  device to your computer's USB port.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called trancevibrator.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 295f459..d946d52 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Multipart objects.
-wacom-objs	:= wacom_sys.o wacom_wac.o
+wacom-objs	:= wacom_wac.o wacom_sys.o
 usbhid-objs	:= hid-core.o
 
 # Optional parts of multipart objects.
@@ -48,7 +48,6 @@
 obj-$(CONFIG_USB_YEALINK)	+= yealink.o
 obj-$(CONFIG_USB_XPAD)		+= xpad.o
 obj-$(CONFIG_USB_APPLETOUCH)	+= appletouch.o
-obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index d83603b..0096373 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -58,7 +58,7 @@
 	dma_addr_t data_dma;
 };
 
-static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs)
+static void usb_acecad_irq(struct urb *urb)
 {
 	struct usb_acecad *acecad = urb->context;
 	unsigned char *data = acecad->data;
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index b138dae..bf42818 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -396,7 +396,7 @@
  * replaced with the input_sync() method (which emits EV_SYN.)
  */
 
-static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
+static void aiptek_irq(struct urb *urb)
 {
 	struct aiptek *aiptek = urb->context;
 	unsigned char *data = aiptek->data;
@@ -442,8 +442,6 @@
 			aiptek->diagnostic =
 			    AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE;
 		} else {
-			input_regs(inputdev, regs);
-
 			x = aiptek_convert_from_2s_complement(data[2]);
 			y = aiptek_convert_from_2s_complement(data[3]);
 
@@ -488,8 +486,6 @@
 			    (aiptek->curSetting.pointerMode)) {
 				aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
 		} else {
-			input_regs(inputdev, regs);
-
 			x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
 			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
 			z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
@@ -568,7 +564,6 @@
 			(aiptek->curSetting.pointerMode)) {
 			aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
 		} else {
-			input_regs(inputdev, regs);
 			x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
 			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
 
@@ -631,8 +626,6 @@
 		z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
 
 		if (dv != 0) {
-			input_regs(inputdev, regs);
-
 			/* If we've not already sent a tool_button_?? code, do
 			 * so now. Then set FIRED_BIT so it won't be resent unless
 			 * the user forces FIRED_BIT off.
@@ -681,8 +674,6 @@
 		macro = data[3];
 
 		if (dv != 0) {
-			input_regs(inputdev, regs);
-
 			/* If we've not already sent a tool_button_?? code, do
 			 * so now. Then set FIRED_BIT so it won't be resent unless
 			 * the user forces FIRED_BIT off.
@@ -726,8 +717,6 @@
 	 */
 	else if (data[0] == 6) {
 		macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
-		input_regs(inputdev, regs);
-
 		if (macro > 0) {
 			input_report_key(inputdev, macroKeyEvents[macro - 1],
 					 0);
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 0aa9cc2..4c21351 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -210,7 +210,7 @@
 	input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
 }
 
-static void atp_complete(struct urb* urb, struct pt_regs* regs)
+static void atp_complete(struct urb* urb)
 {
 	int x, y, x_z, y_z, x_f, y_f;
 	int retval, i, j;
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 3558d7e..f659f30 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -283,9 +283,9 @@
 static int ati_remote_open		(struct input_dev *inputdev);
 static void ati_remote_close		(struct input_dev *inputdev);
 static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
-static void ati_remote_irq_out		(struct urb *urb, struct pt_regs *regs);
-static void ati_remote_irq_in		(struct urb *urb, struct pt_regs *regs);
-static void ati_remote_input_report	(struct urb *urb, struct pt_regs *regs);
+static void ati_remote_irq_out		(struct urb *urb);
+static void ati_remote_irq_in		(struct urb *urb);
+static void ati_remote_input_report	(struct urb *urb);
 static int ati_remote_initialize	(struct ati_remote *ati_remote);
 static int ati_remote_probe		(struct usb_interface *interface, const struct usb_device_id *id);
 static void ati_remote_disconnect	(struct usb_interface *interface);
@@ -344,7 +344,7 @@
 /*
  *		ati_remote_irq_out
  */
-static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs)
+static void ati_remote_irq_out(struct urb *urb)
 {
 	struct ati_remote *ati_remote = urb->context;
 
@@ -453,7 +453,7 @@
 /*
  *	ati_remote_report_input
  */
-static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
+static void ati_remote_input_report(struct urb *urb)
 {
 	struct ati_remote *ati_remote = urb->context;
 	unsigned char *data= ati_remote->inbuf;
@@ -491,7 +491,6 @@
 		remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
 
 	if (ati_remote_tbl[index].kind == KIND_LITERAL) {
-		input_regs(dev, regs);
 		input_event(dev, ati_remote_tbl[index].type,
 			ati_remote_tbl[index].code,
 			ati_remote_tbl[index].value);
@@ -520,7 +519,6 @@
 			return;
 
 
-		input_regs(dev, regs);
 		input_event(dev, ati_remote_tbl[index].type,
 			ati_remote_tbl[index].code, 1);
 		input_sync(dev);
@@ -537,7 +535,6 @@
 		 */
 		acc = ati_remote_compute_accel(ati_remote);
 
-		input_regs(dev, regs);
 		switch (ati_remote_tbl[index].kind) {
 		case KIND_ACCEL:
 			input_event(dev, ati_remote_tbl[index].type,
@@ -575,14 +572,14 @@
 /*
  *	ati_remote_irq_in
  */
-static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs)
+static void ati_remote_irq_in(struct urb *urb)
 {
 	struct ati_remote *ati_remote = urb->context;
 	int retval;
 
 	switch (urb->status) {
 	case 0:			/* success */
-		ati_remote_input_report(urb, regs);
+		ati_remote_input_report(urb);
 		break;
 	case -ECONNRESET:	/* unlink */
 	case -ENOENT:
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index ea71de8..f982a2b 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -142,7 +142,7 @@
 	usb_kill_urb(ar2->urb[1]);
 }
 
-static void ati_remote2_input_mouse(struct ati_remote2 *ar2, struct pt_regs *regs)
+static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
 {
 	struct input_dev *idev = ar2->idev;
 	u8 *data = ar2->buf[0];
@@ -157,7 +157,6 @@
 	if (!((1 << data[0]) & mode_mask))
 		return;
 
-	input_regs(idev, regs);
 	input_event(idev, EV_REL, REL_X, (s8) data[1]);
 	input_event(idev, EV_REL, REL_Y, (s8) data[2]);
 	input_sync(idev);
@@ -174,7 +173,7 @@
 	return -1;
 }
 
-static void ati_remote2_input_key(struct ati_remote2 *ar2, struct pt_regs *regs)
+static void ati_remote2_input_key(struct ati_remote2 *ar2)
 {
 	struct input_dev *idev = ar2->idev;
 	u8 *data = ar2->buf[1];
@@ -245,19 +244,18 @@
 		return;
 	}
 
-	input_regs(idev, regs);
 	input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
 	input_sync(idev);
 }
 
-static void ati_remote2_complete_mouse(struct urb *urb, struct pt_regs *regs)
+static void ati_remote2_complete_mouse(struct urb *urb)
 {
 	struct ati_remote2 *ar2 = urb->context;
 	int r;
 
 	switch (urb->status) {
 	case 0:
-		ati_remote2_input_mouse(ar2, regs);
+		ati_remote2_input_mouse(ar2);
 		break;
 	case -ENOENT:
 	case -EILSEQ:
@@ -277,14 +275,14 @@
 			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
 }
 
-static void ati_remote2_complete_key(struct urb *urb, struct pt_regs *regs)
+static void ati_remote2_complete_key(struct urb *urb)
 {
 	struct ati_remote2 *ar2 = urb->context;
 	int r;
 
 	switch (urb->status) {
 	case 0:
-		ati_remote2_input_key(ar2, regs);
+		ati_remote2_input_key(ar2);
 		break;
 	case -ENOENT:
 	case -EILSEQ:
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index e0fd116..45f44fe 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -750,21 +750,31 @@
 }
 
 /*
- * Extract/implement a data field from/to a report.
+ * Extract/implement a data field from/to a little endian report (bit array).
  */
 
 static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
 {
-	report += (offset >> 5) << 2; offset &= 31;
-	return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1);
+	u32 x;
+
+	report += offset >> 3;  /* adjust byte index */
+	offset &= 8 - 1;
+	x = get_unaligned((u32 *) report);
+	x = le32_to_cpu(x);
+	x = (x >> offset) & ((1 << n) - 1);
+	return x;
 }
 
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
 {
-	report += (offset >> 5) << 2; offset &= 31;
-	put_unaligned((get_unaligned((__le64*)report)
-		& cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
-		| cpu_to_le64((__u64)value << offset), (__le64*)report);
+	u32 x;
+
+	report += offset >> 3;
+	offset &= 8 - 1;
+	x = get_unaligned((u32 *)report);
+	x &= cpu_to_le32(~((((__u32) 1 << n) - 1) << offset));
+	x |= cpu_to_le32(value << offset);
+	put_unaligned(x,(u32 *)report);
 }
 
 /*
@@ -780,13 +790,13 @@
 	return -1;
 }
 
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt, struct pt_regs *regs)
+static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
 {
 	hid_dump_input(usage, value);
 	if (hid->claimed & HID_CLAIMED_INPUT)
-		hidinput_hid_event(hid, field, usage, value, regs);
+		hidinput_hid_event(hid, field, usage, value);
 	if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
-		hiddev_hid_event(hid, field, usage, value, regs);
+		hiddev_hid_event(hid, field, usage, value);
 }
 
 /*
@@ -795,7 +805,7 @@
  * reporting to the layer).
  */
 
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt, struct pt_regs *regs)
+static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
 {
 	unsigned n;
 	unsigned count = field->report_count;
@@ -822,19 +832,19 @@
 	for (n = 0; n < count; n++) {
 
 		if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-			hid_process_event(hid, field, &field->usage[n], value[n], interrupt, regs);
+			hid_process_event(hid, field, &field->usage[n], value[n], interrupt);
 			continue;
 		}
 
 		if (field->value[n] >= min && field->value[n] <= max
 			&& field->usage[field->value[n] - min].hid
 			&& search(value, field->value[n], count))
-				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt, regs);
+				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
 
 		if (value[n] >= min && value[n] <= max
 			&& field->usage[value[n] - min].hid
 			&& search(field->value, value[n], count))
-				hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt, regs);
+				hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
 	}
 
 	memcpy(field->value, value, count * sizeof(__s32));
@@ -842,7 +852,7 @@
 	kfree(value);
 }
 
-static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_regs *regs)
+static int hid_input_report(int type, struct urb *urb, int interrupt)
 {
 	struct hid_device *hid = urb->context;
 	struct hid_report_enum *report_enum = hid->report_enum + type;
@@ -892,7 +902,7 @@
 		hiddev_report_event(hid, report);
 
 	for (n = 0; n < report->maxfield; n++)
-		hid_input_field(hid, report->field[n], data, interrupt, regs);
+		hid_input_field(hid, report->field[n], data, interrupt);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_report_event(hid, report);
@@ -1004,7 +1014,7 @@
  * Input interrupt completion handler.
  */
 
-static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
+static void hid_irq_in(struct urb *urb)
 {
 	struct hid_device	*hid = urb->context;
 	int			status;
@@ -1012,7 +1022,7 @@
 	switch (urb->status) {
 		case 0:			/* success */
 			hid->retry_delay = 0;
-			hid_input_report(HID_INPUT_REPORT, urb, 1, regs);
+			hid_input_report(HID_INPUT_REPORT, urb, 1);
 			break;
 		case -ECONNRESET:	/* unlink */
 		case -ENOENT:
@@ -1193,7 +1203,7 @@
  * Output interrupt completion handler.
  */
 
-static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
+static void hid_irq_out(struct urb *urb)
 {
 	struct hid_device *hid = urb->context;
 	unsigned long flags;
@@ -1238,7 +1248,7 @@
  * Control pipe completion handler.
  */
 
-static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
+static void hid_ctrl(struct urb *urb)
 {
 	struct hid_device *hid = urb->context;
 	unsigned long flags;
@@ -1249,7 +1259,7 @@
 	switch (urb->status) {
 		case 0:			/* success */
 			if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
-				hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
+				hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0);
 			break;
 		case -ESHUTDOWN:	/* unplug */
 			unplug = 1;
@@ -1381,6 +1391,9 @@
 
 #define USB_VENDOR_ID_PANJIT		0x134c
 
+#define USB_VENDOR_ID_TURBOX		0x062a
+#define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
+
 /*
  * Initialize all reports
  */
@@ -1768,6 +1781,8 @@
 	{ USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
 
+	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+	
 	{ 0, 0 }
 };
 
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 4c62afb..9a808a3 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -613,7 +613,7 @@
 	return;
 }
 
-void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs)
+void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
 {
 	struct input_dev *input;
 	int *quirks = &hid->quirks;
@@ -623,8 +623,6 @@
 
 	input = field->hidinput->input;
 
-	input_regs(input, regs);
-
 	if (!usage->type)
 		return;
 
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index b03fd9b..9b50eff 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -499,13 +499,13 @@
 /* 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))
-extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32, struct pt_regs *regs);
+extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
 extern int hidinput_connect(struct hid_device *);
 extern void hidinput_disconnect(struct hid_device *);
 #else
 #define IS_INPUT_APPLICATION(a) (0)
-static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) { }
+static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
 static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { }
 static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
 static inline void hidinput_disconnect(struct hid_device *hid) { }
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index a2b419d..7dc14d0 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -179,7 +179,7 @@
  * the interrupt pipe
  */
 void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
-		      struct hid_usage *usage, __s32 value, struct pt_regs *regs)
+		      struct hid_usage *usage, __s32 value)
 {
 	unsigned type = field->report_type;
 	struct hiddev_usage_ref uref;
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 61966d7..aac968a 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -36,7 +36,11 @@
  *
  * 1.2.1  09/03/2005 (HCE) hc@mivu.no
  *   Code cleanup and adjusting syntax to start matching kernel standards
- *
+ * 
+ * 1.2.2  10/05/2006 (MJA) massad@gmail.com
+ *   Flag for detecting if the screen was being touch was incorrectly 
+ *   inverted, so no touch events were being detected. 	
+ *   
  *****************************************************************************/
 
 #include <linux/kernel.h>
@@ -53,7 +57,7 @@
 #define USB_PRODUCT_ID_TOUCHPANEL	0xf9e9
 
 #define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>"
-#define DRIVER_VERSION "v1.2.1"
+#define DRIVER_VERSION "v1.2.2"
 #define DRIVER_DESC "USB ITM Inc Touch Panel Driver"
 #define DRIVER_LICENSE "GPL"
 
@@ -76,7 +80,7 @@
 	{ }
 };
 
-static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
+static void itmtouch_irq(struct urb *urb)
 {
 	struct itmtouch_dev *itmtouch = urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -105,10 +109,8 @@
 		goto exit;
 	}
 
-	input_regs(dev, regs);
-
 	/* if pressure has been released, then don't report X/Y */
-	if (data[7] & 0x20) {
+	if (!(data[7] & 0x20)) {
 		input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F));
 		input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F));
 	}
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index 604ade3..fedbcb1 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -41,7 +41,7 @@
 	char phys[32];
 };
 
-static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
+static void kbtab_irq(struct urb *urb)
 {
 	struct kbtab *kbtab = urb->context;
 	unsigned char *data = kbtab->data;
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index a903595..50aa810 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -176,7 +176,7 @@
 /*
  * Routine that handles all the logic needed to parse out the message from the remote.
  */
-static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs)
+static void keyspan_check_data(struct usb_keyspan *remote)
 {
 	int i;
 	int found = 0;
@@ -311,7 +311,6 @@
 			__FUNCTION__, message.system, message.button, message.toggle);
 
 		if (message.toggle != remote->toggle) {
-			input_regs(remote->input, regs);
 			input_report_key(remote->input, keyspan_key_table[message.button], 1);
 			input_report_key(remote->input, keyspan_key_table[message.button], 0);
 			input_sync(remote->input);
@@ -361,7 +360,7 @@
 /*
  * Routine used to handle a new message that has come in.
  */
-static void keyspan_irq_recv(struct urb *urb, struct pt_regs *regs)
+static void keyspan_irq_recv(struct urb *urb)
 {
 	struct usb_keyspan *dev = urb->context;
 	int retval;
@@ -385,7 +384,7 @@
 	if (debug)
 		keyspan_print(dev);
 
-	keyspan_check_data(dev, regs);
+	keyspan_check_data(dev);
 
 resubmit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 5dce951..79a85d4 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -98,7 +98,7 @@
 	{ }
 };
 
-static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
+static void mtouchusb_irq(struct urb *urb)
 {
 	struct mtouch_usb *mtouch = urb->context;
 	int retval;
@@ -125,7 +125,6 @@
 		goto exit;
 	}
 
-	input_regs(mtouch->input, regs);
 	input_report_key(mtouch->input, BTN_TOUCH,
 			 MTOUCHUSB_GET_TOUCHED(mtouch->data));
 	input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index f0f8db6..0bf9177 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -80,10 +80,10 @@
 static char pm_name_powermate[] = "Griffin PowerMate";
 static char pm_name_soundknob[] = "Griffin SoundKnob";
 
-static void powermate_config_complete(struct urb *urb, struct pt_regs *regs);
+static void powermate_config_complete(struct urb *urb);
 
 /* Callback for data arriving from the PowerMate over the USB interrupt pipe */
-static void powermate_irq(struct urb *urb, struct pt_regs *regs)
+static void powermate_irq(struct urb *urb)
 {
 	struct powermate_device *pm = urb->context;
 	int retval;
@@ -104,7 +104,6 @@
 	}
 
 	/* handle updates to device state */
-	input_regs(pm->input, regs);
 	input_report_key(pm->input, BTN_0, pm->data[0] & 0x01);
 	input_report_rel(pm->input, REL_DIAL, pm->data[1]);
 	input_sync(pm->input);
@@ -191,7 +190,7 @@
 }
 
 /* Called when our asynchronous control message completes. We may need to issue another immediately */
-static void powermate_config_complete(struct urb *urb, struct pt_regs *regs)
+static void powermate_config_complete(struct urb *urb)
 {
 	struct powermate_device *pm = urb->context;
 	unsigned long flags;
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 30b9f82..05c0d1c 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -92,8 +92,7 @@
 
 
 /* processes one input packet. */
-static void touchkit_process_pkt(struct touchkit_usb *touchkit,
-                                 struct pt_regs *regs, char *pkt)
+static void touchkit_process_pkt(struct touchkit_usb *touchkit, char *pkt)
 {
 	int x, y;
 
@@ -109,7 +108,6 @@
 		y = touchkit_get_y(pkt);
 	}
 
-	input_regs(touchkit->input, regs);
 	input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
 	input_report_abs(touchkit->input, ABS_X, x);
 	input_report_abs(touchkit->input, ABS_Y, y);
@@ -130,8 +128,7 @@
 	return 0;
 }
 
-static void touchkit_process(struct touchkit_usb *touchkit, int len,
-                             struct pt_regs *regs)
+static void touchkit_process(struct touchkit_usb *touchkit, int len)
 {
 	char *buffer;
 	int pkt_len, buf_len, pos;
@@ -153,7 +150,7 @@
 		/* append, process */
 		tmp = pkt_len - touchkit->buf_len;
 		memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
-		touchkit_process_pkt(touchkit, regs, touchkit->buffer);
+		touchkit_process_pkt(touchkit, touchkit->buffer);
 
 		buffer = touchkit->data + tmp;
 		buf_len = len - tmp;
@@ -181,7 +178,7 @@
 
 		/* full packet: process */
 		if (likely(pkt_len <= buf_len)) {
-			touchkit_process_pkt(touchkit, regs, buffer + pos);
+			touchkit_process_pkt(touchkit, buffer + pos);
 		} else {
 			/* incomplete packet: save in buffer */
 			memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
@@ -192,7 +189,7 @@
 }
 
 
-static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
+static void touchkit_irq(struct urb *urb)
 {
 	struct touchkit_usb *touchkit = urb->context;
 	int retval;
@@ -219,7 +216,7 @@
 		goto exit;
 	}
 
-	touchkit_process(touchkit, urb->actual_length, regs);
+	touchkit_process(touchkit, urb->actual_length);
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 5067a6a..c73285c 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -80,7 +80,7 @@
 	dma_addr_t leds_dma;
 };
 
-static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
+static void usb_kbd_irq(struct urb *urb)
 {
 	struct usb_kbd *kbd = urb->context;
 	int i;
@@ -97,8 +97,6 @@
 		goto resubmit;
 	}
 
-	input_regs(kbd->dev, regs);
-
 	for (i = 0; i < 8; i++)
 		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
 
@@ -158,7 +156,7 @@
 	return 0;
 }
 
-static void usb_kbd_led(struct urb *urb, struct pt_regs *regs)
+static void usb_kbd_led(struct urb *urb)
 {
 	struct usb_kbd *kbd = urb->context;
 
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 0fb792b..cbbbea3 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -55,7 +55,7 @@
 	dma_addr_t data_dma;
 };
 
-static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
+static void usb_mouse_irq(struct urb *urb)
 {
 	struct usb_mouse *mouse = urb->context;
 	signed char *data = mouse->data;
@@ -74,8 +74,6 @@
 		goto resubmit;
 	}
 
-	input_regs(dev, regs);
-
 	input_report_key(dev, BTN_LEFT,   data[0] & 0x01);
 	input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);
 	input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 923e22d..2902742 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -61,7 +61,7 @@
 	int rept_size;
 	int flags;
 
-	void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
+	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  (*init)        (struct usbtouch_usb *usbtouch);
@@ -91,7 +91,6 @@
 
 #ifdef MULTI_PACKET
 static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
-                                   struct pt_regs *regs,
                                    unsigned char *pkt, int len);
 #endif
 
@@ -257,10 +256,10 @@
 {
 	*x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
 	*y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
-	*press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F);
+	*press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
 	*touch = ~pkt[7] & 0x20;
 
-	return 1;
+	return *touch;
 }
 #endif
 
@@ -397,7 +396,7 @@
  * Generic Part
  */
 static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
-                                 struct pt_regs *regs, unsigned char *pkt, int len)
+                                 unsigned char *pkt, int len)
 {
 	int x, y, touch, press;
 	struct usbtouch_device_info *type = usbtouch->type;
@@ -405,7 +404,6 @@
 	if (!type->read_data(pkt, &x, &y, &touch, &press))
 			return;
 
-	input_regs(usbtouch->input, regs);
 	input_report_key(usbtouch->input, BTN_TOUCH, touch);
 
 	if (swap_xy) {
@@ -423,7 +421,6 @@
 
 #ifdef MULTI_PACKET
 static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
-                                   struct pt_regs *regs,
                                    unsigned char *pkt, int len)
 {
 	unsigned char *buffer;
@@ -460,7 +457,7 @@
 		if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
 			goto out_flush_buf;
 		memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
-		usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
+		usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len);
 
 		buffer = pkt + tmp;
 		buf_len = len - tmp;
@@ -481,7 +478,7 @@
 
 		/* full packet: process */
 		if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
-			usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+			usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len);
 		} else {
 			/* incomplete packet: save in buffer */
 			memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
@@ -498,7 +495,7 @@
 #endif
 
 
-static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
+static void usbtouch_irq(struct urb *urb)
 {
 	struct usbtouch_usb *usbtouch = urb->context;
 	int retval;
@@ -525,7 +522,7 @@
 		goto exit;
 	}
 
-	usbtouch->type->process_pkt(usbtouch, regs, usbtouch->data, urb->actual_length);
+	usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
index 832737b..1cf08f0 100644
--- a/drivers/usb/input/wacom.h
+++ b/drivers/usb/input/wacom.h
@@ -63,6 +63,7 @@
  *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
  *		   - where wacom_sys.c deals with system specific code,
  * 		   - and wacom_wac.c deals with Wacom specific code
+ *		   - Support Intuos3 4x6
  */
 
 /*
@@ -106,20 +107,19 @@
 struct wacom_combo {
 	struct wacom * wacom;
 	struct urb * urb;
-	struct pt_regs *regs;
 };
 
 extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
-extern void wacom_sys_irq(struct urb *urb, struct pt_regs *regs);
+extern void wacom_sys_irq(struct urb *urb);
 extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
 extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
 extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
 extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value);
-extern void wacom_input_regs(void *wcombo);
 extern void wacom_input_sync(void *wcombo);
 extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index 7c3b52b..3498b89 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -42,7 +42,7 @@
 	return wcombo->wacom->dev;
 }
 
-void wacom_sys_irq(struct urb *urb, struct pt_regs *regs)
+void wacom_sys_irq(struct urb *urb)
 {
 	struct wacom *wacom = urb->context;
 	struct wacom_combo wcombo;
@@ -65,7 +65,6 @@
 
 	wcombo.wacom = wacom;
 	wcombo.urb = urb;
-	wcombo.regs = regs;
 
 	if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo))
 		input_sync(get_input_dev(&wcombo));
@@ -111,16 +110,10 @@
 __u16 wacom_le16_to_cpu(unsigned char *data)
 {
 	__u16 value;
-	value = be16_to_cpu(*(__be16 *) data);
+	value = le16_to_cpu(*(__le16 *) data);
 	return value;
 }
 
-void wacom_input_regs(void *wcombo)
-{
-	input_regs(get_input_dev((struct wacom_combo *)wcombo), ((struct wacom_combo *)wcombo)->regs);
-	return;
-}
-
 void wacom_input_sync(void *wcombo)
 {
 	input_sync(get_input_dev((struct wacom_combo *)wcombo));
@@ -150,7 +143,7 @@
 	input_dev->evbit[0] |= BIT(EV_MSC);
 	input_dev->mscbit[0] |= BIT(MSC_SERIAL);
 	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_4);
 }
 
 void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -162,11 +155,16 @@
 	input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
 }
 
-void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3);
 	input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+}
+
+void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
 	input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
 }
 
@@ -225,8 +223,7 @@
 	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
 	wacom_wac->features = get_wacom_feature(id);
-	if (wacom_wac->features->pktlen > 10)
-		BUG();
+	BUG_ON(wacom_wac->features->pktlen > 10);
 
 	input_dev->name = wacom_wac->features->name;
 	wacom->wacom_wac = wacom_wac;
@@ -251,7 +248,7 @@
 	usb_fill_int_urb(wacom->irq, dev,
 			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
 			 wacom_wac->data, wacom_wac->features->pktlen,
-			 wacom_wac->features->irq, wacom, endpoint->bInterval);
+			 wacom_sys_irq, wacom, endpoint->bInterval);
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -285,8 +282,8 @@
 		input_unregister_device(wacom->dev);
 		usb_free_urb(wacom->irq);
 		usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
-		kfree(wacom);
 		kfree(wacom->wacom_wac);
+		kfree(wacom);
 	}
 }
 
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
index 85d458c..92726fe 100644
--- a/drivers/usb/input/wacom_wac.c
+++ b/drivers/usb/input/wacom_wac.c
@@ -20,7 +20,6 @@
 
 	switch (data[0]) {
 		case 1:
-			wacom_input_regs(wcombo);
 			if (data[5] & 0x80) {
 				wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 				wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
@@ -39,7 +38,6 @@
 			}
 			break;
 		case 2:
-			wacom_input_regs(wcombo);
 			wacom_report_key(wcombo, BTN_TOOL_PEN, 1);
 			wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
 			wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
@@ -67,8 +65,6 @@
 
 	prox = data[1] & 0x40;
 
-	wacom_input_regs(wcombo);
-
 	id = ERASER_DEVICE_ID;
 	if (prox) {
 
@@ -138,7 +134,6 @@
 		return 0;
 	}
 
-	wacom_input_regs(wcombo);
 	if (data[1] & 0x04) {
 		wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);
 		wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);
@@ -167,8 +162,6 @@
 		return 0;
 	}
 
-	wacom_input_regs(wcombo);
-
 	id = STYLUS_DEVICE_ID;
 	if (data[1] & 0x10) { /* in prox */
 
@@ -198,9 +191,9 @@
 				wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
 				wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
 				if (wacom->features->type == WACOM_G4)
-					wacom_report_abs(wcombo, ABS_DISTANCE, data[6]);
+					wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
 				else
-					wacom_report_abs(wcombo, ABS_DISTANCE, data[7]);
+					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
 				break;
 		}
 	}
@@ -310,8 +303,9 @@
 				wacom->tool[idx] = BTN_TOOL_PEN;
 		}
 		/* only large I3 support Lens Cursor */
-		if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
-				(wacom->features->type == INTUOS3))) {
+		if(!((wacom->tool[idx] == BTN_TOOL_LENS)
+				 && ((wacom->features->type == INTUOS3)
+				 || (wacom->features->type == INTUOS3S)))) {
 			wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
 			wacom_report_key(wcombo, wacom->tool[idx], 1);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
@@ -322,10 +316,14 @@
 
 	/* Exit report */
 	if ((data[1] & 0xfe) == 0x80) {
-		wacom_report_key(wcombo, wacom->tool[idx], 0);
-		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
-		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-		return 2;
+ 		if(!((wacom->tool[idx] == BTN_TOOL_LENS)
+				 && ((wacom->features->type == INTUOS3)
+				 || (wacom->features->type == INTUOS3S)))) {
+			wacom_report_key(wcombo, wacom->tool[idx], 0);
+			wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+			return 2;
+		}
 	}
 	return 0;
 }
@@ -369,8 +367,6 @@
                 return 0;
 	}
 
-	wacom_input_regs(wcombo);
-
 	/* tool number */
 	idx = data[1] & 0x01;
 
@@ -391,7 +387,8 @@
 		wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
 		wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
 
-		if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
+		if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) |
+			data[2] | (data[3] & 0x1f) | data[4])
 			wacom_report_key(wcombo, wacom->tool[1], 1);
 		else
 			wacom_report_key(wcombo, wacom->tool[1], 0);
@@ -441,7 +438,7 @@
 					((t - 1) / 2) : -t / 2);
 			}
 
-		} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
+		} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) {
 			/* 4D mouse packet */
 			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
 			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
@@ -461,12 +458,12 @@
 						 - ((data[8] & 0x02) >> 1));
 
 			/* I3 2D mouse side buttons */
-			if (wacom->features->type == INTUOS3) {
+			if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
 				wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
 				wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
 			}
 
-		} else if (wacom->features->type < INTUOS3) {
+		} else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) {
 			/* Lens cursor packets */
 			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
 			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
@@ -499,6 +496,7 @@
 			return (wacom_ptu_irq(wacom_wac, wcombo));
 			break;
 		case INTUOS:
+		case INTUOS3S:
 		case INTUOS3:
 		case INTUOS3L:
 		case CINTIQ:
@@ -524,6 +522,8 @@
 		case CINTIQ:
 			input_dev_i3(input_dev, wacom_wac);
 			/* fall through */
+		case INTUOS3S:
+			input_dev_i3s(input_dev, wacom_wac);
 		case INTUOS:
 			input_dev_i(input_dev, wacom_wac);
 			break;
@@ -539,49 +539,50 @@
 }
 
 static struct wacom_features wacom_features[] = {
-	{ "Wacom Penpartner",    7,   5040,  3780,  255, 32, PENPARTNER,	wacom_sys_irq },
-        { "Wacom Graphire",      8,  10206,  7422,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Graphire3",     8,  10208,  7424,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 32, WACOM_G4,	wacom_sys_irq },
-	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 32, WACOM_G4,	wacom_sys_irq },
-	{ "Wacom Volito",        8,   5104,  3712,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom PenStation2",   8,   3250,  2320,  255, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 32, GRAPHIRE,	wacom_sys_irq },
-	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, INTUOS,	wacom_sys_irq},
-	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, INTUOS,	wacom_sys_irq},
-	{ "Wacom PL400",         8,   5408,  4056,  255, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL500",         8,   6144,  4608,  255, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL600",         8,   6126,  4604,  255, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL600SX",       8,   6260,  5016,  255, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL550",         8,   6144,  4608,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL800",         8,   7220,  5780,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL700",         8,   6758,  5406,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom PL510",         8,   6282,  4762,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,	wacom_sys_irq },
-	{ "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PTU,	wacom_sys_irq },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS,	wacom_sys_irq },
-	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,	wacom_sys_irq },
-	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,	wacom_sys_irq },
-	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,	wacom_sys_irq },
-	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS3L,	wacom_sys_irq },
-	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS3L,	wacom_sys_irq },
-	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,	wacom_sys_irq },
-	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,	wacom_sys_irq },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,	wacom_sys_irq },
+	{ "Wacom Penpartner",    7,   5040,  3780,  255,  0, PENPARTNER },
+        { "Wacom Graphire",      8,  10206,  7422,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire3",     8,  10208,  7424,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 63, WACOM_G4 },
+	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 63, WACOM_G4 },
+	{ "Wacom Volito",        8,   5104,  3712,  511,  0, GRAPHIRE },
+	{ "Wacom PenStation2",   8,   3250,  2320,  255,  0, GRAPHIRE },
+	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511,  0, GRAPHIRE },
+	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511,  0, GRAPHIRE },
+	{ "Wacom PenPartner2",   8,   3250,  2320,  255,  0, GRAPHIRE },
+	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 63, INTUOS },
+	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 63, INTUOS },
+	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 63, INTUOS },
+	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 63, INTUOS },
+	{ "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
+	{ "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
+	{ "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
+	{ "Wacom PL600SX",       8,   6260,  5016,  255,  0, PL },
+	{ "Wacom PL550",         8,   6144,  4608,  511,  0, PL },
+	{ "Wacom PL800",         8,   7220,  5780,  511,  0, PL },
+	{ "Wacom PL700",         8,   6758,  5406,  511,  0, PL },
+	{ "Wacom PL510",         8,   6282,  4762,  511,  0, PL },
+	{ "Wacom DTU710",        8,  34080, 27660,  511,  0, PL },
+	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
+	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
+	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
+	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS },
+	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
+	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
+	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
+	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 15, INTUOS3S },
+	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 63, INTUOS },
 	{ }
 };
 
@@ -627,6 +628,7 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
 	{ }
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h
index ceae7bf..a1d9ce0 100644
--- a/drivers/usb/input/wacom_wac.h
+++ b/drivers/usb/input/wacom_wac.h
@@ -20,6 +20,7 @@
 	PTU,
 	PL,
 	INTUOS,
+	INTUOS3S,
 	INTUOS3,
 	INTUOS3L,
 	CINTIQ,
@@ -34,7 +35,6 @@
 	int pressure_max;
 	int distance_max;
 	int type;
-	usb_complete_t irq;
 };
 
 struct wacom_wac {
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 9889b1c..6a12a94 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -1,8 +1,9 @@
 /*
- * X-Box gamepad - v0.0.5
+ * X-Box gamepad - v0.0.6
  *
  * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
- *
+ *               2005 Dominic Cerquetti <binary1230@yahoo.com>
+ *               2006 Adam Buchbinder <adam.buchbinder@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
@@ -30,9 +31,10 @@
  *  - Greg Kroah-Hartman - usb-skeleton driver
  *
  * TODO:
- *  - fine tune axes
+ *  - fine tune axes (especially trigger axes)
  *  - fix "analog" buttons (reported as digital now)
  *  - get rumble working
+ *  - need USB IDs for other dance pads
  *
  * History:
  *
@@ -57,25 +59,40 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/smp_lock.h>
 #include <linux/usb/input.h>
 
-#define DRIVER_VERSION "v0.0.5"
+#define DRIVER_VERSION "v0.0.6"
 #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
 #define DRIVER_DESC "X-Box pad driver"
 
 #define XPAD_PKT_LEN 32
 
+/* xbox d-pads should map to buttons, as is required for DDR pads
+   but we map them to axes when possible to simplify things */
+#define MAP_DPAD_TO_BUTTONS    0
+#define MAP_DPAD_TO_AXES       1
+#define MAP_DPAD_UNKNOWN       -1
+
+static int dpad_to_buttons;
+module_param(dpad_to_buttons, bool, S_IRUGO);
+MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
+
 static const struct xpad_device {
 	u16 idVendor;
 	u16 idProduct;
 	char *name;
+	u8 dpad_mapping;
 } xpad_device[] = {
-	{ 0x045e, 0x0202, "Microsoft X-Box pad (US)" },
-	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)" },
-	{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)" },
-	{ 0x0000, 0x0000, "X-Box pad" }
+	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES },
+	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES },
+	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES },
+	{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES },
+	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS },
+	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN }
 };
 
 static const signed short xpad_btn[] = {
@@ -84,11 +101,23 @@
 	-1						/* terminating entry */
 };
 
+/* only used if MAP_DPAD_TO_BUTTONS */
+static const signed short xpad_btn_pad[] = {
+	BTN_LEFT, BTN_RIGHT,		/* d-pad left, right */
+	BTN_0, BTN_1,			/* d-pad up, down (XXX names??) */
+	-1				/* terminating entry */
+};
+
 static const signed short xpad_abs[] = {
 	ABS_X, ABS_Y,		/* left stick */
 	ABS_RX, ABS_RY,		/* right stick */
 	ABS_Z, ABS_RZ,		/* triggers left/right */
-	ABS_HAT0X, ABS_HAT0Y,	/* digital pad */
+	-1			/* terminating entry */
+};
+
+/* only used if MAP_DPAD_TO_AXES */
+static const signed short xpad_abs_pad[] = {
+	ABS_HAT0X, ABS_HAT0Y,	/* d-pad axes */
 	-1			/* terminating entry */
 };
 
@@ -100,14 +129,16 @@
 MODULE_DEVICE_TABLE (usb, xpad_table);
 
 struct usb_xpad {
-	struct input_dev *dev;			/* input device interface */
-	struct usb_device *udev;		/* usb device */
+	struct input_dev *dev;		/* input device interface */
+	struct usb_device *udev;	/* usb device */
 
-	struct urb *irq_in;			/* urb for interrupt in report */
-	unsigned char *idata;			/* input data */
+	struct urb *irq_in;		/* urb for interrupt in report */
+	unsigned char *idata;		/* input data */
 	dma_addr_t idata_dma;
 
-	char phys[65];				/* physical device path */
+	char phys[65];			/* physical device path */
+
+	int dpad_mapping;		/* map d-pad to buttons or to axes */
 };
 
 /*
@@ -120,12 +151,10 @@
  *	 http://euc.jp/periphs/xbox-controller.ja.html
  */
 
-static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs)
+static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
 {
 	struct input_dev *dev = xpad->dev;
 
-	input_regs(dev, regs);
-
 	/* left stick */
 	input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12]));
 	input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14]));
@@ -139,14 +168,21 @@
 	input_report_abs(dev, ABS_RZ, data[11]);
 
 	/* digital pad */
-	input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
-	input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
+		input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
+		input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+	} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
+		input_report_key(dev, BTN_LEFT,  data[2] & 0x04);
+		input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
+		input_report_key(dev, BTN_0,     data[2] & 0x01); // up
+		input_report_key(dev, BTN_1,     data[2] & 0x02); // down
+	}
 
 	/* start/back buttons and stick press left/right */
-	input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4);
-	input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5);
-	input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6);
-	input_report_key(dev, BTN_THUMBR, data[2] >> 7);
+	input_report_key(dev, BTN_START,  data[2] & 0x10);
+	input_report_key(dev, BTN_BACK,   data[2] & 0x20);
+	input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
+	input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
 
 	/* "analog" buttons A, B, X, Y */
 	input_report_key(dev, BTN_A, data[4]);
@@ -161,7 +197,7 @@
 	input_sync(dev);
 }
 
-static void xpad_irq_in(struct urb *urb, struct pt_regs *regs)
+static void xpad_irq_in(struct urb *urb)
 {
 	struct usb_xpad *xpad = urb->context;
 	int retval;
@@ -181,7 +217,7 @@
 		goto exit;
 	}
 
-	xpad_process_packet(xpad, 0, xpad->idata, regs);
+	xpad_process_packet(xpad, 0, xpad->idata);
 
 exit:
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -208,6 +244,28 @@
 	usb_kill_urb(xpad->irq_in);
 }
 
+static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
+{
+	set_bit(abs, input_dev->absbit);
+
+	switch (abs) {
+	case ABS_X:
+	case ABS_Y:
+	case ABS_RX:
+	case ABS_RY:	/* the two sticks */
+		input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128);
+		break;
+	case ABS_Z:
+	case ABS_RZ:	/* the triggers */
+		input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
+		break;
+	case ABS_HAT0X:
+	case ABS_HAT0Y:	/* the d-pad (only if MAP_DPAD_TO_AXES) */
+		input_set_abs_params(input_dev, abs, -1, 1, 0, 0);
+		break;
+	}
+}
+
 static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev (intf);
@@ -237,6 +295,9 @@
 		goto fail2;
 
 	xpad->udev = udev;
+	xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+	if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
+		xpad->dpad_mapping = dpad_to_buttons;
 	xpad->dev = input_dev;
 	usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
 	strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
@@ -251,32 +312,19 @@
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
+	/* set up buttons */
 	for (i = 0; xpad_btn[i] >= 0; i++)
 		set_bit(xpad_btn[i], input_dev->keybit);
+	if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
+		for (i = 0; xpad_btn_pad[i] >= 0; i++)
+			set_bit(xpad_btn_pad[i], input_dev->keybit);
 
-	for (i = 0; xpad_abs[i] >= 0; i++) {
-
-		signed short t = xpad_abs[i];
-
-		set_bit(t, input_dev->absbit);
-
-		switch (t) {
-			case ABS_X:
-			case ABS_Y:
-			case ABS_RX:
-			case ABS_RY:	/* the two sticks */
-				input_set_abs_params(input_dev, t, -32768, 32767, 16, 128);
-				break;
-			case ABS_Z:
-			case ABS_RZ:	/* the triggers */
-				input_set_abs_params(input_dev, t, 0, 255, 0, 0);
-				break;
-			case ABS_HAT0X:
-			case ABS_HAT0Y:	/* the d-pad */
-				input_set_abs_params(input_dev, t, -1, 1, 0, 0);
-				break;
-		}
-	}
+	/* set up axes */
+	for (i = 0; xpad_abs[i] >= 0; i++)
+		xpad_set_up_abs(input_dev, xpad_abs[i]);
+	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES)
+		for (i = 0; xpad_abs_pad[i] >= 0; i++)
+		    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
 
 	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
 	usb_fill_int_urb(xpad->irq_in, udev,
@@ -307,7 +355,8 @@
 		usb_kill_urb(xpad->irq_in);
 		input_unregister_device(xpad->dev);
 		usb_free_urb(xpad->irq_in);
-		usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+		usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN,
+				xpad->idata, xpad->idata_dma);
 		kfree(xpad);
 	}
 }
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 7291e7a..905bf63 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -233,11 +233,10 @@
  *
  * The key parameter can be cascaded: key2 << 8 | key1
  */
-static void report_key(struct yealink_dev *yld, int key, struct pt_regs *regs)
+static void report_key(struct yealink_dev *yld, int key)
 {
 	struct input_dev *idev = yld->idev;
 
-	input_regs(idev, regs);
 	if (yld->key_code >= 0) {
 		/* old key up */
 		input_report_key(idev, yld->key_code & 0xff, 0);
@@ -422,7 +421,7 @@
  * error,start
  *
  */
-static void urb_irq_callback(struct urb *urb, struct pt_regs *regs)
+static void urb_irq_callback(struct urb *urb)
 {
 	struct yealink_dev *yld = urb->context;
 	int ret;
@@ -439,7 +438,7 @@
 	case CMD_SCANCODE:
 		dbg("get scancode %x", yld->irq_data->data[0]);
 
-		report_key(yld, map_p1k_to_key(yld->irq_data->data[0]), regs);
+		report_key(yld, map_p1k_to_key(yld->irq_data->data[0]));
 		break;
 
 	default:
@@ -453,7 +452,7 @@
 		err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
 }
 
-static void urb_ctl_callback(struct urb *urb, struct pt_regs *regs)
+static void urb_ctl_callback(struct urb *urb)
 {
 	struct yealink_dev *yld = urb->context;
 	int ret;
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index c29658f..a74bf86 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -223,6 +223,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ldusb.
 
+config USB_TRANCEVIBRATOR
+	tristate "PlayStation 2 Trance Vibrator driver support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a PlayStation 2 Trance Vibrator
+	  device to your computer's USB port.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called trancevibrator.
+
 config USB_TEST
 	tristate "USB testing driver (DEVELOPMENT)"
 	depends on USB && USB_DEVICEFS && EXPERIMENTAL
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 2be70fa..11dc595 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_USB_PHIDGETSERVO)	+= phidgetservo.o
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
+obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
 
 obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index d396319..af2934e 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -177,7 +177,7 @@
 	dbg(2, "%s : leave", __FUNCTION__);
 }
 
-static void adu_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+static void adu_interrupt_in_callback(struct urb *urb)
 {
 	struct adu_device *dev = urb->context;
 
@@ -221,7 +221,7 @@
 	dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
 }
 
-static void adu_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+static void adu_interrupt_out_callback(struct urb *urb)
 {
 	struct adu_device *dev = urb->context;
 
@@ -370,7 +370,8 @@
 	retval = adu_release_internal(dev);
 
 exit:
-	up(&dev->sem);
+	if (dev)
+		up(&dev->sem);
 	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
 	return retval;
 }
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index fc6cc14..6b23a1d 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -84,7 +84,7 @@
 static atomic_t count_displays = ATOMIC_INIT(0);
 static struct workqueue_struct *wq;
 
-static void appledisplay_complete(struct urb *urb, struct pt_regs *regs)
+static void appledisplay_complete(struct urb *urb)
 {
 	struct appledisplay *pdata = urb->context;
 	unsigned long flags;
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 4fd2110..0be9d62 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -267,7 +267,7 @@
 
 /*-------------------------------------------------------------------*/
 /* Forwards */
-static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs);
+static void auerswald_ctrlread_complete (struct urb * urb);
 static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
 static struct usb_driver auerswald_driver;
 
@@ -277,7 +277,7 @@
 /* --------------------------                                        */
 
 /* completion function for chained urbs */
-static void auerchain_complete (struct urb * urb, struct pt_regs *regs)
+static void auerchain_complete (struct urb * urb)
 {
 	unsigned long flags;
         int result;
@@ -296,7 +296,7 @@
            NOTE: this function may lead to more urbs submitted into the chain.
                  (no chain lock at calling complete()!)
                  acp->active != NULL is protecting us against recursion.*/
-        urb->complete (urb, regs);
+        urb->complete (urb);
 
         /* detach element from chain data structure */
 	spin_lock_irqsave (&acp->lock, flags);
@@ -331,7 +331,7 @@
                         urb->status = result;
                         dbg("auerchain_complete: usb_submit_urb with error code %d", result);
                         /* and do error handling via *this* completion function (recursive) */
-                        auerchain_complete( urb, NULL);
+                        auerchain_complete( urb);
                 }
         } else {
                 /* simple return without submitting a new urb.
@@ -408,7 +408,7 @@
                         urb->status = result;
                         dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
                         /* and do error handling via completion function */
-                        auerchain_complete( urb, NULL);
+                        auerchain_complete( urb);
                 }
         }
 
@@ -448,7 +448,7 @@
                         spin_unlock_irqrestore (&acp->lock, flags);
                         dbg ("unlink waiting urb");
                         urb->status = -ENOENT;
-                        urb->complete (urb, NULL);
+                        urb->complete (urb);
                         return 0;
                 }
         }
@@ -505,7 +505,7 @@
                 spin_unlock_irqrestore (&acp->lock, flags);
                 dbg ("unlink waiting urb");
                 urbp->status = -ENOENT;
-                urbp->complete (urbp, NULL);
+                urbp->complete (urbp);
                 spin_lock_irqsave (&acp->lock, flags);
         }
         spin_unlock_irqrestore (&acp->lock, flags);
@@ -591,7 +591,7 @@
 
 
 /* completion handler for synchronous chained URBs */
-static void auerchain_blocking_completion (struct urb *urb, struct pt_regs *regs)
+static void auerchain_blocking_completion (struct urb *urb)
 {
 	pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
 	pchs->done = 1;
@@ -846,7 +846,7 @@
 }
 
 /* Completion of asynchronous write block */
-static void auerchar_ctrlwrite_complete (struct urb * urb, struct pt_regs *regs)
+static void auerchar_ctrlwrite_complete (struct urb * urb)
 {
 	pauerbuf_t bp = (pauerbuf_t) urb->context;
 	pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
@@ -859,7 +859,7 @@
 }
 
 /* Completion handler for dummy retry packet */
-static void auerswald_ctrlread_wretcomplete (struct urb * urb, struct pt_regs *regs)
+static void auerswald_ctrlread_wretcomplete (struct urb * urb)
 {
         pauerbuf_t bp = (pauerbuf_t) urb->context;
         pauerswald_t cp;
@@ -893,12 +893,12 @@
         if (ret) {
         	dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
         	bp->urbp->status = ret;
-        	auerswald_ctrlread_complete (bp->urbp, NULL);
+        	auerswald_ctrlread_complete (bp->urbp);
     	}
 }
 
 /* completion handler for receiving of control messages */
-static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs)
+static void auerswald_ctrlread_complete (struct urb * urb)
 {
         unsigned int  serviceid;
         pauerswald_t  cp;
@@ -941,7 +941,7 @@
        		if (ret) {
                		dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
                		bp->urbp->status = ret;
-               		auerswald_ctrlread_wretcomplete (bp->urbp, regs);
+               		auerswald_ctrlread_wretcomplete (bp->urbp);
 		}
                 return;
         }
@@ -970,7 +970,7 @@
    messages from the USB device.
 */
 /* int completion handler. */
-static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs)
+static void auerswald_int_complete (struct urb * urb)
 {
         unsigned long flags;
         unsigned  int channelid;
@@ -1070,7 +1070,7 @@
         if (ret) {
                 dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
                 bp->urbp->status = ret;
-                auerswald_ctrlread_complete( bp->urbp, NULL);
+                auerswald_ctrlread_complete( bp->urbp);
 		/* here applies the same problem as above: device locking! */
         }
 exit:
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index c6f2f48..9b591b8 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -513,8 +513,6 @@
                         ftdi->disconnected += 1;
                 } else if (retval == -ENODEV) {
                         ftdi->disconnected += 1;
-                } else if (retval == -ENODEV) {
-                        ftdi->disconnected += 1;
                 } else if (retval == -EILSEQ) {
                         ftdi->disconnected += 1;
                 } else {
@@ -758,7 +756,7 @@
                 return bytes_read;
 }
 
-static void ftdi_elan_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void ftdi_elan_write_bulk_callback(struct urb *urb)
 {
         struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
         if (urb->status && !(urb->status == -ENOENT || urb->status ==
@@ -1186,11 +1184,8 @@
         int retval = 0;
         struct urb *urb;
         char *buf;
-        char data[30 *3 + 4];
-        char *d = data;
-        const char __user *s = user_buffer;
-        int m = (sizeof(data) - 1) / 3;
-        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        struct usb_ftdi *ftdi = file->private_data;
+
         if (ftdi->disconnected > 0) {
                 return -ENODEV;
         }
@@ -1220,27 +1215,18 @@
         if (retval) {
                 dev_err(&ftdi->udev->dev, "failed submitting write urb, error %"
                         "d\n", retval);
-                goto error_4;
+                goto error_3;
         }
         usb_free_urb(urb);
-      exit:;
-        if (count > m) {
-                int I = m - 1;
-                while (I-- > 0) {
-                        d += sprintf(d, " %02X", 0x000000FF & *s++);
-                }
-                d += sprintf(d, " ..");
-        } else {
-                int I = count;
-                while (I-- > 0) {
-                        d += sprintf(d, " %02X", 0x000000FF & *s++);
-                }
-        }
+
+exit:
         return count;
-      error_4: error_3:usb_buffer_free(ftdi->udev, count, buf,
-              urb->transfer_dma);
-      error_2:usb_free_urb(urb);
-      error_1:return retval;
+error_3:
+	usb_buffer_free(ftdi->udev, count, buf, urb->transfer_dma);
+error_2:
+	usb_free_urb(urb);
+error_1:
+	return retval;
 }
 
 static struct file_operations ftdi_elan_fops = {
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 10b6403..788a11e 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -212,7 +212,7 @@
 /**
  *	ld_usb_interrupt_in_callback
  */
-static void ld_usb_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+static void ld_usb_interrupt_in_callback(struct urb *urb)
 {
 	struct ld_usb *dev = urb->context;
 	size_t *actual_buffer;
@@ -264,7 +264,7 @@
 /**
  *	ld_usb_interrupt_out_callback
  */
-static void ld_usb_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+static void ld_usb_interrupt_out_callback(struct urb *urb)
 {
 	struct ld_usb *dev = urb->context;
 
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 77c36e6..2708949 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -248,8 +248,8 @@
 
 static void tower_abort_transfers (struct lego_usb_tower *dev);
 static void tower_check_for_read_packet (struct lego_usb_tower *dev);
-static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs);
-static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs);
+static void tower_interrupt_in_callback (struct urb *urb);
+static void tower_interrupt_out_callback (struct urb *urb);
 
 static int  tower_probe	(struct usb_interface *interface, const struct usb_device_id *id);
 static void tower_disconnect	(struct usb_interface *interface);
@@ -755,7 +755,7 @@
 /**
  *	tower_interrupt_in_callback
  */
-static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs)
+static void tower_interrupt_in_callback (struct urb *urb)
 {
 	struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
 	int retval;
@@ -811,7 +811,7 @@
 /**
  *	tower_interrupt_out_callback
  */
-static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs)
+static void tower_interrupt_out_callback (struct urb *urb)
 {
 	struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
 
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 78e4199..abb4dcd 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -300,7 +300,7 @@
 
 static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
 
-static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
+static void interfacekit_irq(struct urb *urb)
 {
 	struct interfacekit *kit = urb->context;
 	unsigned char *buffer = kit->data;
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 6b59b62..5c780ca 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -90,7 +90,7 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void motorcontrol_irq(struct urb *urb, struct pt_regs *regs)
+static void motorcontrol_irq(struct urb *urb)
 {
 	struct motorcontrol *mc = urb->context;
 	unsigned char *buffer = mc->data;
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index a287836..b99ca9c 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -209,7 +209,7 @@
 /* completion callback */
 
 static void
-sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
+sisusb_bulk_completeout(struct urb *urb)
 {
 	struct sisusb_urb_context *context = urb->context;
 	struct sisusb_usb_data *sisusb;
@@ -288,7 +288,7 @@
 /* completion callback */
 
 static void
-sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
+sisusb_bulk_completein(struct urb *urb)
 {
 	struct sisusb_usb_data *sisusb = urb->context;
 
diff --git a/drivers/usb/input/trancevibrator.c b/drivers/usb/misc/trancevibrator.c
similarity index 100%
rename from drivers/usb/input/trancevibrator.c
rename to drivers/usb/misc/trancevibrator.c
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index dbaca9f..ada2ebc 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -165,7 +165,7 @@
 	return 0;
 }
 
-static void lcd_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void lcd_write_bulk_callback(struct urb *urb)
 {
 	struct usb_lcd *dev;
 
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 983e104..7c2cbdf 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -198,7 +198,7 @@
  * them with non-zero test data (or test for it) when appropriate.
  */
 
-static void simple_callback (struct urb *urb, struct pt_regs *regs)
+static void simple_callback (struct urb *urb)
 {
 	complete ((struct completion *) urb->context);
 }
@@ -730,7 +730,7 @@
 	int			expected;
 };
 
-static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
+static void ctrl_complete (struct urb *urb)
 {
 	struct ctrl_ctx		*ctx = urb->context;
 	struct usb_ctrlrequest	*reqp;
@@ -1035,7 +1035,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void unlink1_callback (struct urb *urb, struct pt_regs *regs)
+static void unlink1_callback (struct urb *urb)
 {
 	int	status = urb->status;
 
@@ -1343,7 +1343,7 @@
 	struct usbtest_dev	*dev;
 };
 
-static void iso_callback (struct urb *urb, struct pt_regs *regs)
+static void iso_callback (struct urb *urb)
 {
 	struct iso_context	*ctx = urb->context;
 
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 4081990..7e8a0ac 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -106,7 +106,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void async_complete(struct urb *urb, struct pt_regs *ptregs)
+static void async_complete(struct urb *urb)
 {
 	struct uss720_async_request *rq;
 	struct parport *pp;
@@ -127,7 +127,7 @@
 #endif
 		/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
 		if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
-			parport_generic_irq(0, pp, NULL);
+			parport_generic_irq(0, pp);
 	}
 	complete(&rq->compl);
 	kref_put(&rq->ref_count, destroy_async);
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index 0540596..454a186 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -207,6 +207,14 @@
 	  Choose this option if you're using a host-to-host cable
 	  with one of these chips.
 
+config USB_NET_MCS7830
+	tristate "MosChip MCS7830 based Ethernet adapters"
+	depends on USB_USBNET
+	help
+	  Choose this option if you're using a 10/100 Ethernet USB2
+	  adapter based on the MosChip 7830 controller. This includes
+	  adapters marketed under the DeLOCK brand.
+
 config USB_NET_RNDIS_HOST
 	tristate "Host for RNDIS devices (EXPERIMENTAL)"
 	depends on USB_USBNET && EXPERIMENTAL
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 160f19d..7b51964 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -14,6 +14,7 @@
 obj-$(CONFIG_USB_NET_RNDIS_HOST)	+= rndis_host.o
 obj-$(CONFIG_USB_NET_CDC_SUBSET)	+= cdc_subset.o
 obj-$(CONFIG_USB_NET_ZAURUS)	+= zaurus.o
+obj-$(CONFIG_USB_NET_MCS7830)	+= mcs7830.o
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 9c0eacf..881841e 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -214,7 +214,7 @@
 		USB_CTRL_SET_TIMEOUT);
 }
 
-static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+static void asix_async_cmd_callback(struct urb *urb)
 {
 	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
 
@@ -569,10 +569,12 @@
 	struct usbnet *dev = netdev_priv(netdev);
 	u16 res;
 
+	mutex_lock(&dev->phy_mutex);
 	asix_set_sw_mii(dev);
 	asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
 				(__u16)loc, 2, (u16 *)&res);
 	asix_set_hw_mii(dev);
+	mutex_unlock(&dev->phy_mutex);
 
 	devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff));
 
@@ -586,10 +588,12 @@
 	u16 res = cpu_to_le16(val);
 
 	devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val);
+	mutex_lock(&dev->phy_mutex);
 	asix_set_sw_mii(dev);
 	asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
 				(__u16)loc, 2, (u16 *)&res);
 	asix_set_hw_mii(dev);
+	mutex_unlock(&dev->phy_mutex);
 }
 
 /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
@@ -700,32 +704,6 @@
 	info->eedump_len = data->eeprom_len;
 }
 
-static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
-{
-	struct usbnet *dev = netdev_priv(net);
-
-	return mii_ethtool_gset(&dev->mii,cmd);
-}
-
-static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
-{
-	struct usbnet *dev = netdev_priv(net);
-	int res = mii_ethtool_sset(&dev->mii,cmd);
-
-	/* link speed/duplex might have changed */
-	if (dev->driver_info->link_reset)
-		dev->driver_info->link_reset(dev);
-
-	return res;
-}
-
-static int asix_nway_reset(struct net_device *net)
-{
-	struct usbnet *dev = netdev_priv(net);
-
-	return mii_nway_restart(&dev->mii);
-}
-
 static u32 asix_get_link(struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -746,15 +724,15 @@
 static struct ethtool_ops ax88172_ethtool_ops = {
 	.get_drvinfo		= asix_get_drvinfo,
 	.get_link		= asix_get_link,
-	.nway_reset		= asix_nway_reset,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
 	.get_wol		= asix_get_wol,
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
-	.get_settings		= asix_get_settings,
-	.set_settings		= asix_set_settings,
+	.get_settings		= usbnet_get_settings,
+	.set_settings		= usbnet_set_settings,
+	.nway_reset		= usbnet_nway_reset,
 };
 
 static void ax88172_set_multicast(struct net_device *net)
@@ -885,15 +863,15 @@
 static struct ethtool_ops ax88772_ethtool_ops = {
 	.get_drvinfo		= asix_get_drvinfo,
 	.get_link		= asix_get_link,
-	.nway_reset		= asix_nway_reset,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
 	.get_wol		= asix_get_wol,
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
-	.get_settings		= asix_get_settings,
-	.set_settings		= asix_set_settings,
+	.get_settings		= usbnet_get_settings,
+	.set_settings		= usbnet_set_settings,
+	.nway_reset		= usbnet_nway_reset,
 };
 
 static int ax88772_link_reset(struct usbnet *dev)
@@ -1046,15 +1024,15 @@
 static struct ethtool_ops ax88178_ethtool_ops = {
 	.get_drvinfo		= asix_get_drvinfo,
 	.get_link		= asix_get_link,
-	.nway_reset		= asix_nway_reset,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
 	.get_wol		= asix_get_wol,
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
-	.get_settings		= asix_get_settings,
-	.set_settings		= asix_set_settings,
+	.get_settings		= usbnet_get_settings,
+	.set_settings		= usbnet_set_settings,
+	.nway_reset		= usbnet_nway_reset,
 };
 
 static int marvell_phy_init(struct usbnet *dev)
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index be5f5e1..f740325 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -223,7 +223,7 @@
  * Receive routines.
  */
 
-static void catc_rx_done(struct urb *urb, struct pt_regs *regs)
+static void catc_rx_done(struct urb *urb)
 {
 	struct catc *catc = urb->context;
 	u8 *pkt_start = urb->transfer_buffer;
@@ -289,7 +289,7 @@
 	}
 }
 
-static void catc_irq_done(struct urb *urb, struct pt_regs *regs)
+static void catc_irq_done(struct urb *urb)
 {
 	struct catc *catc = urb->context;
 	u8 *data = urb->transfer_buffer;
@@ -376,7 +376,7 @@
 	catc->netdev->trans_start = jiffies;
 }
 
-static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
+static void catc_tx_done(struct urb *urb)
 {
 	struct catc *catc = urb->context;
 	unsigned long flags;
@@ -486,7 +486,7 @@
 		err("submit(ctrl_urb) status %d", status);
 }
 
-static void catc_ctrl_done(struct urb *urb, struct pt_regs *regs)
+static void catc_ctrl_done(struct urb *urb)
 {
 	struct catc *catc = urb->context;
 	struct ctrl_queue *q;
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index 82ce035..f6971b8 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -498,7 +498,7 @@
 
 static int __init cdc_init(void)
 {
-	BUG_ON((sizeof(((struct usbnet *)0)->data)
+	BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
 			< sizeof(struct cdc_state)));
 
  	return usb_register(&cdc_driver);
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index 3155f25..a3242be 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -106,7 +106,7 @@
 	return retval;
 }
 
-static void gl_interrupt_complete(struct urb *urb, struct pt_regs *regs)
+static void gl_interrupt_complete(struct urb *urb)
 {
 	int status = urb->status;
 
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 544d41f..7c906a4 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -65,16 +65,6 @@
 
 #undef DEBUG
 
-#ifdef DEBUG
-#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
-#else
-#define kaweth_dbg(format, arg...) do {} while (0)
-#endif
-#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg)
-#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg)
-#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg)
-
-
 #include "kawethfw.h"
 
 #define KAWETH_MTU			1514
@@ -86,6 +76,9 @@
 
 #define KAWETH_STATUS_BROKEN		0x0000001
 #define KAWETH_STATUS_CLOSING		0x0000002
+#define KAWETH_STATUS_SUSPENDING	0x0000004
+
+#define KAWETH_STATUS_BLOCKED (KAWETH_STATUS_CLOSING | KAWETH_STATUS_SUSPENDING)
 
 #define KAWETH_PACKET_FILTER_PROMISCUOUS	0x01
 #define KAWETH_PACKET_FILTER_ALL_MULTICAST	0x02
@@ -112,6 +105,8 @@
 #define STATE_MASK				0x40
 #define	STATE_SHIFT				5
 
+#define IS_BLOCKED(s) (s & KAWETH_STATUS_BLOCKED)
+
 
 MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>");
 MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
@@ -128,6 +123,8 @@
 				       unsigned int pipe,
 				       struct usb_ctrlrequest *cmd, void *data,
 				       int len, int timeout);
+static int kaweth_suspend(struct usb_interface *intf, pm_message_t message);
+static int kaweth_resume(struct usb_interface *intf);
 
 /****************************************************************
  *     usb_device_id
@@ -179,6 +176,8 @@
 	.name =		driver_name,
 	.probe =	kaweth_probe,
 	.disconnect =	kaweth_disconnect,
+	.suspend =	kaweth_suspend,
+	.resume =	kaweth_resume,
 	.id_table =     usb_klsi_table,
 };
 
@@ -222,6 +221,7 @@
 	int suspend_lowmem_rx;
 	int suspend_lowmem_ctrl;
 	int linkstate;
+	int opened;
 	struct work_struct lowmem_work;
 
 	struct usb_device *dev;
@@ -265,17 +265,17 @@
 {
 	struct usb_ctrlrequest *dr;
 
-	kaweth_dbg("kaweth_control()");
+	dbg("kaweth_control()");
 
 	if(in_interrupt()) {
-		kaweth_dbg("in_interrupt()");
+		dbg("in_interrupt()");
 		return -EBUSY;
 	}
 
 	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
 
 	if (!dr) {
-		kaweth_dbg("kmalloc() failed");
+		dbg("kmalloc() failed");
 		return -ENOMEM;
 	}
 
@@ -300,7 +300,7 @@
 {
 	int retval;
 
-	kaweth_dbg("Reading kaweth configuration");
+	dbg("Reading kaweth configuration");
 
 	retval = kaweth_control(kaweth,
 				usb_rcvctrlpipe(kaweth->dev, 0),
@@ -322,7 +322,7 @@
 {
 	int retval;
 
-	kaweth_dbg("Setting URB size to %d", (unsigned)urb_size);
+	dbg("Setting URB size to %d", (unsigned)urb_size);
 
 	retval = kaweth_control(kaweth,
 				usb_sndctrlpipe(kaweth->dev, 0),
@@ -344,7 +344,7 @@
 {
 	int retval;
 
-	kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
+	dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
 
 	retval = kaweth_control(kaweth,
 				usb_sndctrlpipe(kaweth->dev, 0),
@@ -367,7 +367,7 @@
 {
 	int retval;
 
-	kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter);
+	dbg("Set receive filter to %d", (unsigned)receive_filter);
 
 	retval = kaweth_control(kaweth,
 				usb_sndctrlpipe(kaweth->dev, 0),
@@ -392,7 +392,7 @@
 				    __u8 type)
 {
 	if(data_len > KAWETH_FIRMWARE_BUF_SIZE)	{
-		kaweth_err("Firmware too big: %d", data_len);
+		err("Firmware too big: %d", data_len);
 		return -ENOSPC;
 	}
 
@@ -403,13 +403,13 @@
 	kaweth->firmware_buf[4] = type;
 	kaweth->firmware_buf[5] = interrupt;
 
-	kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
+	dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
 		   kaweth->firmware_buf[2]);
 
-	kaweth_dbg("Downloading firmware at %p to kaweth device at %p",
+	dbg("Downloading firmware at %p to kaweth device at %p",
 	    data,
 	    kaweth);
-	kaweth_dbg("Firmware length: %d", data_len);
+	dbg("Firmware length: %d", data_len);
 
 	return kaweth_control(kaweth,
 		              usb_sndctrlpipe(kaweth->dev, 0),
@@ -437,7 +437,7 @@
 	kaweth->firmware_buf[6] = 0x00;
 	kaweth->firmware_buf[7] = 0x00;
 
-	kaweth_dbg("Triggering firmware");
+	dbg("Triggering firmware");
 
 	return kaweth_control(kaweth,
 			      usb_sndctrlpipe(kaweth->dev, 0),
@@ -457,7 +457,7 @@
 {
 	int result;
 
-	kaweth_dbg("kaweth_reset(%p)", kaweth);
+	dbg("kaweth_reset(%p)", kaweth);
 	result = kaweth_control(kaweth,
 				usb_sndctrlpipe(kaweth->dev, 0),
 				USB_REQ_SET_CONFIGURATION,
@@ -470,12 +470,12 @@
 
 	mdelay(10);
 
-	kaweth_dbg("kaweth_reset() returns %d.",result);
+	dbg("kaweth_reset() returns %d.",result);
 
 	return result;
 }
 
-static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
+static void kaweth_usb_receive(struct urb *);
 static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
 
 /****************************************************************
@@ -500,7 +500,7 @@
 				kaweth->dev->devpath, status);
 }
 
-static void int_callback(struct urb *u, struct pt_regs *regs)
+static void int_callback(struct urb *u)
 {
 	struct kaweth_device *kaweth = u->context;
 	int act_state;
@@ -534,7 +534,7 @@
 {
 	struct kaweth_device *kaweth = (struct kaweth_device *)d;
 
-	if (kaweth->status | KAWETH_STATUS_CLOSING)
+	if (IS_BLOCKED(kaweth->status))
 		return;
 
 	if (kaweth->suspend_lowmem_rx)
@@ -568,7 +568,7 @@
 			kaweth->suspend_lowmem_rx = 1;
 			schedule_delayed_work(&kaweth->lowmem_work, HZ/4);
 		}
-		kaweth_err("resubmitting rx_urb %d failed", result);
+		err("resubmitting rx_urb %d failed", result);
 	} else {
 		kaweth->suspend_lowmem_rx = 0;
 	}
@@ -581,7 +581,7 @@
 /****************************************************************
  *     kaweth_usb_receive
  ****************************************************************/
-static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
+static void kaweth_usb_receive(struct urb *urb)
 {
 	struct kaweth_device *kaweth = urb->context;
 	struct net_device *net = kaweth->net;
@@ -601,11 +601,15 @@
 		return;
 	}
 
-	if (kaweth->status & KAWETH_STATUS_CLOSING)
+	spin_lock(&kaweth->device_lock);
+	if (IS_BLOCKED(kaweth->status)) {
+		spin_unlock(&kaweth->device_lock);
 		return;
+	}
+	spin_unlock(&kaweth->device_lock);
 
 	if(urb->status && urb->status != -EREMOTEIO && count != 1) {
-		kaweth_err("%s RX status: %d count: %d packet_len: %d",
+		err("%s RX status: %d count: %d packet_len: %d",
                            net->name,
 			   urb->status,
 			   count,
@@ -616,9 +620,9 @@
 
 	if(kaweth->net && (count > 2)) {
 		if(pkt_len > (count - 2)) {
-			kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
-			kaweth_err("Packet len & 2047: %x", pkt_len & 2047);
-			kaweth_err("Count 2: %x", count2);
+			err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
+			err("Packet len & 2047: %x", pkt_len & 2047);
+			err("Count 2: %x", count2);
 		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
                         return;
                 }
@@ -655,7 +659,7 @@
 	struct kaweth_device *kaweth = netdev_priv(net);
 	int res;
 
-	kaweth_dbg("Opening network device.");
+	dbg("Opening network device.");
 
 	res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
 	if (res)
@@ -678,6 +682,7 @@
 		usb_kill_urb(kaweth->rx_urb);
 		return -EIO;
 	}
+	kaweth->opened = 1;
 
 	netif_start_queue(net);
 
@@ -688,14 +693,8 @@
 /****************************************************************
  *     kaweth_close
  ****************************************************************/
-static int kaweth_close(struct net_device *net)
+static void kaweth_kill_urbs(struct kaweth_device *kaweth)
 {
-	struct kaweth_device *kaweth = netdev_priv(net);
-
-	netif_stop_queue(net);
-
-	kaweth->status |= KAWETH_STATUS_CLOSING;
-
 	usb_kill_urb(kaweth->irq_urb);
 	usb_kill_urb(kaweth->rx_urb);
 	usb_kill_urb(kaweth->tx_urb);
@@ -706,6 +705,21 @@
 	   we hit them again */
 	usb_kill_urb(kaweth->irq_urb);
 	usb_kill_urb(kaweth->rx_urb);
+}
+
+/****************************************************************
+ *     kaweth_close
+ ****************************************************************/
+static int kaweth_close(struct net_device *net)
+{
+	struct kaweth_device *kaweth = netdev_priv(net);
+
+	netif_stop_queue(net);
+	kaweth->opened = 0;
+
+	kaweth->status |= KAWETH_STATUS_CLOSING;
+
+	kaweth_kill_urbs(kaweth);
 
 	kaweth->status &= ~KAWETH_STATUS_CLOSING;
 
@@ -725,14 +739,14 @@
 /****************************************************************
  *     kaweth_usb_transmit_complete
  ****************************************************************/
-static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs)
+static void kaweth_usb_transmit_complete(struct urb *urb)
 {
 	struct kaweth_device *kaweth = urb->context;
 	struct sk_buff *skb = kaweth->tx_skb;
 
 	if (unlikely(urb->status != 0))
 		if (urb->status != -ENOENT)
-			kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
+			dbg("%s: TX status %d.", kaweth->net->name, urb->status);
 
 	netif_wake_queue(kaweth->net);
 	dev_kfree_skb_irq(skb);
@@ -752,6 +766,9 @@
 
 	kaweth_async_set_rx_mode(kaweth);
 	netif_stop_queue(net);
+	if (IS_BLOCKED(kaweth->status)) {
+		goto skip;
+	}
 
 	/* We now decide whether we can put our special header into the sk_buff */
 	if (skb_cloned(skb) || skb_headroom(skb) < 2) {
@@ -783,7 +800,8 @@
 
 	if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
 	{
-		kaweth_warn("kaweth failed tx_urb %d", res);
+		warn("kaweth failed tx_urb %d", res);
+skip:
 		kaweth->stats.tx_errors++;
 
 		netif_start_queue(net);
@@ -812,7 +830,7 @@
                                      KAWETH_PACKET_FILTER_BROADCAST |
 		                     KAWETH_PACKET_FILTER_MULTICAST;
 
-	kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap);
+	dbg("Setting Rx mode to %d", packet_filter_bitmap);
 
 	netif_stop_queue(net);
 
@@ -850,10 +868,10 @@
 				KAWETH_CONTROL_TIMEOUT);
 
 	if(result < 0) {
-		kaweth_err("Failed to set Rx mode: %d", result);
+		err("Failed to set Rx mode: %d", result);
 	}
 	else {
-		kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap);
+		dbg("Set Rx mode to %d", packet_filter_bitmap);
 	}
 	}
 }
@@ -874,7 +892,7 @@
 {
 	struct kaweth_device *kaweth = netdev_priv(net);
 
-	kaweth_warn("%s: Tx timed out. Resetting.", net->name);
+	warn("%s: Tx timed out. Resetting.", net->name);
 	kaweth->stats.tx_errors++;
 	net->trans_start = jiffies;
 
@@ -882,6 +900,42 @@
 }
 
 /****************************************************************
+ *     kaweth_suspend
+ ****************************************************************/
+static int kaweth_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct kaweth_device *kaweth = usb_get_intfdata(intf);
+	unsigned long flags;
+
+	spin_lock_irqsave(&kaweth->device_lock, flags);
+	kaweth->status |= KAWETH_STATUS_SUSPENDING;
+	spin_unlock_irqrestore(&kaweth->device_lock, flags);
+
+	kaweth_kill_urbs(kaweth);
+	return 0;
+}
+
+/****************************************************************
+ *     kaweth_resume
+ ****************************************************************/
+static int kaweth_resume(struct usb_interface *intf)
+{
+	struct kaweth_device *kaweth = usb_get_intfdata(intf);
+	unsigned long flags;
+
+	spin_lock_irqsave(&kaweth->device_lock, flags);
+	kaweth->status &= ~KAWETH_STATUS_SUSPENDING;
+	spin_unlock_irqrestore(&kaweth->device_lock, flags);
+
+	if (!kaweth->opened)
+		return 0;
+	kaweth_resubmit_rx_urb(kaweth, GFP_NOIO);
+	kaweth_resubmit_int_urb(kaweth, GFP_NOIO);
+
+	return 0;
+}
+
+/****************************************************************
  *     kaweth_probe
  ****************************************************************/
 static int kaweth_probe(
@@ -895,15 +949,15 @@
 	const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 	int result = 0;
 
-	kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
+	dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
 		 dev->devnum,
 		 le16_to_cpu(dev->descriptor.idVendor),
 		 le16_to_cpu(dev->descriptor.idProduct),
 		 le16_to_cpu(dev->descriptor.bcdDevice));
 
-	kaweth_dbg("Device at %p", dev);
+	dbg("Device at %p", dev);
 
-	kaweth_dbg("Descriptor length: %x type: %x",
+	dbg("Descriptor length: %x type: %x",
 		 (int)dev->descriptor.bLength,
 		 (int)dev->descriptor.bDescriptorType);
 
@@ -918,7 +972,7 @@
 	spin_lock_init(&kaweth->device_lock);
 	init_waitqueue_head(&kaweth->term_wait);
 
-	kaweth_dbg("Resetting.");
+	dbg("Resetting.");
 
 	kaweth_reset(kaweth);
 
@@ -928,17 +982,17 @@
 	 */
 
 	if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) {
-		kaweth_info("Firmware present in device.");
+		info("Firmware present in device.");
 	} else {
 		/* Download the firmware */
-		kaweth_info("Downloading firmware...");
+		info("Downloading firmware...");
 		kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
 		if ((result = kaweth_download_firmware(kaweth,
 						      kaweth_new_code,
 						      len_kaweth_new_code,
 						      100,
 						      2)) < 0) {
-			kaweth_err("Error downloading firmware (%d)", result);
+			err("Error downloading firmware (%d)", result);
 			goto err_fw;
 		}
 
@@ -947,7 +1001,7 @@
 						      len_kaweth_new_code_fix,
 						      100,
 						      3)) < 0) {
-			kaweth_err("Error downloading firmware fix (%d)", result);
+			err("Error downloading firmware fix (%d)", result);
 			goto err_fw;
 		}
 
@@ -956,7 +1010,7 @@
 						      len_kaweth_trigger_code,
 						      126,
 						      2)) < 0) {
-			kaweth_err("Error downloading trigger code (%d)", result);
+			err("Error downloading trigger code (%d)", result);
 			goto err_fw;
 
 		}
@@ -966,18 +1020,18 @@
 						      len_kaweth_trigger_code_fix,
 						      126,
 						      3)) < 0) {
-			kaweth_err("Error downloading trigger code fix (%d)", result);
+			err("Error downloading trigger code fix (%d)", result);
 			goto err_fw;
 		}
 
 
 		if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
-			kaweth_err("Error triggering firmware (%d)", result);
+			err("Error triggering firmware (%d)", result);
 			goto err_fw;
 		}
 
 		/* Device will now disappear for a moment...  */
-		kaweth_info("Firmware loaded.  I'll be back...");
+		info("Firmware loaded.  I'll be back...");
 err_fw:
 		free_page((unsigned long)kaweth->firmware_buf);
 		free_netdev(netdev);
@@ -987,14 +1041,14 @@
 	result = kaweth_read_configuration(kaweth);
 
 	if(result < 0) {
-		kaweth_err("Error reading configuration (%d), no net device created", result);
+		err("Error reading configuration (%d), no net device created", result);
 		goto err_free_netdev;
 	}
 
-	kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask);
-	kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
-	kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size));
-	kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+	info("Statistics collection: %x", kaweth->configuration.statistics_mask);
+	info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
+	info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size));
+	info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
 		 (int)kaweth->configuration.hw_addr[0],
 		 (int)kaweth->configuration.hw_addr[1],
 		 (int)kaweth->configuration.hw_addr[2],
@@ -1005,17 +1059,17 @@
 	if(!memcmp(&kaweth->configuration.hw_addr,
                    &bcast_addr,
 		   sizeof(bcast_addr))) {
-		kaweth_err("Firmware not functioning properly, no net device created");
+		err("Firmware not functioning properly, no net device created");
 		goto err_free_netdev;
 	}
 
 	if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
-		kaweth_dbg("Error setting URB size");
+		dbg("Error setting URB size");
 		goto err_free_netdev;
 	}
 
 	if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
-		kaweth_err("Error setting SOFS wait");
+		err("Error setting SOFS wait");
 		goto err_free_netdev;
 	}
 
@@ -1025,11 +1079,11 @@
                                            KAWETH_PACKET_FILTER_MULTICAST);
 
 	if(result < 0) {
-		kaweth_err("Error setting receive filter");
+		err("Error setting receive filter");
 		goto err_free_netdev;
 	}
 
-	kaweth_dbg("Initializing net device.");
+	dbg("Initializing net device.");
 
 	kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!kaweth->tx_urb)
@@ -1086,13 +1140,13 @@
 
 	SET_NETDEV_DEV(netdev, &intf->dev);
 	if (register_netdev(netdev) != 0) {
-		kaweth_err("Error registering netdev.");
+		err("Error registering netdev.");
 		goto err_intfdata;
 	}
 
-	kaweth_info("kaweth interface created at %s", kaweth->net->name);
+	info("kaweth interface created at %s", kaweth->net->name);
 
-	kaweth_dbg("Kaweth probe returning.");
+	dbg("Kaweth probe returning.");
 
 	return 0;
 
@@ -1121,16 +1175,16 @@
 	struct kaweth_device *kaweth = usb_get_intfdata(intf);
 	struct net_device *netdev;
 
-	kaweth_info("Unregistering");
+	info("Unregistering");
 
 	usb_set_intfdata(intf, NULL);
 	if (!kaweth) {
-		kaweth_warn("unregistering non-existant device");
+		warn("unregistering non-existant device");
 		return;
 	}
 	netdev = kaweth->net;
 
-	kaweth_dbg("Unregistering net device");
+	dbg("Unregistering net device");
 	unregister_netdev(netdev);
 
 	usb_free_urb(kaweth->rx_urb);
@@ -1154,7 +1208,7 @@
 /*-------------------------------------------------------------------*
  * completion handler for compatibility wrappers (sync control/bulk) *
  *-------------------------------------------------------------------*/
-static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
+static void usb_api_blocking_completion(struct urb *urb)
 {
         struct usb_api_data *awd = (struct usb_api_data *)urb->context;
 
@@ -1185,7 +1239,7 @@
 
 	if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
                 // timeout
-                kaweth_warn("usb_control/bulk_msg: timeout");
+                warn("usb_control/bulk_msg: timeout");
                 usb_kill_urb(urb);  // remove urb safely
                 status = -ETIMEDOUT;
         }
@@ -1234,7 +1288,7 @@
  ****************************************************************/
 static int __init kaweth_init(void)
 {
-	kaweth_dbg("Driver loading");
+	dbg("Driver loading");
 	return usb_register(&kaweth_driver);
 }
 
diff --git a/drivers/usb/net/mcs7830.c b/drivers/usb/net/mcs7830.c
new file mode 100644
index 0000000..6240b97
--- /dev/null
+++ b/drivers/usb/net/mcs7830.c
@@ -0,0 +1,534 @@
+/*
+ * MosChips MCS7830 based USB 2.0 Ethernet Devices
+ *
+ * based on usbnet.c, asix.c and the vendor provided mcs7830 driver
+ *
+ * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (c) 2002-2003 TiVo 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 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/crc32.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+/* requests */
+#define MCS7830_RD_BMREQ	(USB_DIR_IN  | USB_TYPE_VENDOR | \
+				 USB_RECIP_DEVICE)
+#define MCS7830_WR_BMREQ	(USB_DIR_OUT | USB_TYPE_VENDOR | \
+				 USB_RECIP_DEVICE)
+#define MCS7830_RD_BREQ		0x0E
+#define MCS7830_WR_BREQ		0x0D
+
+#define MCS7830_CTRL_TIMEOUT	1000
+#define MCS7830_MAX_MCAST	64
+
+#define MCS7830_VENDOR_ID	0x9710
+#define MCS7830_PRODUCT_ID	0x7830
+
+#define MCS7830_MII_ADVERTISE	(ADVERTISE_PAUSE_CAP | ADVERTISE_100FULL | \
+				 ADVERTISE_100HALF | ADVERTISE_10FULL | \
+				 ADVERTISE_10HALF | ADVERTISE_CSMA)
+
+/* HIF_REG_XX coressponding index value */
+enum {
+	HIF_REG_MULTICAST_HASH			= 0x00,
+	HIF_REG_PACKET_GAP1			= 0x08,
+	HIF_REG_PACKET_GAP2			= 0x09,
+	HIF_REG_PHY_DATA			= 0x0a,
+	HIF_REG_PHY_CMD1			= 0x0c,
+	   HIF_REG_PHY_CMD1_READ		= 0x40,
+	   HIF_REG_PHY_CMD1_WRITE		= 0x20,
+	   HIF_REG_PHY_CMD1_PHYADDR		= 0x01,
+	HIF_REG_PHY_CMD2			= 0x0d,
+	   HIF_REG_PHY_CMD2_PEND_FLAG_BIT	= 0x80,
+	   HIF_REG_PHY_CMD2_READY_FLAG_BIT	= 0x40,
+	HIF_REG_CONFIG				= 0x0e,
+	   HIF_REG_CONFIG_CFG			= 0x80,
+	   HIF_REG_CONFIG_SPEED100		= 0x40,
+	   HIF_REG_CONFIG_FULLDUPLEX_ENABLE	= 0x20,
+	   HIF_REG_CONFIG_RXENABLE		= 0x10,
+	   HIF_REG_CONFIG_TXENABLE		= 0x08,
+	   HIF_REG_CONFIG_SLEEPMODE		= 0x04,
+	   HIF_REG_CONFIG_ALLMULTICAST		= 0x02,
+	   HIF_REG_CONFIG_PROMISCIOUS		= 0x01,
+	HIF_REG_ETHERNET_ADDR			= 0x0f,
+	HIF_REG_22				= 0x15,
+	HIF_REG_PAUSE_THRESHOLD			= 0x16,
+	   HIF_REG_PAUSE_THRESHOLD_DEFAULT	= 0,
+};
+
+struct mcs7830_data {
+	u8 multi_filter[8];
+	u8 config;
+};
+
+static const char driver_name[] = "MOSCHIP usb-ethernet driver";
+
+static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
+{
+	struct usb_device *xdev = dev->udev;
+	int ret;
+
+	ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ,
+			      MCS7830_RD_BMREQ, 0x0000, index, data,
+			      size, msecs_to_jiffies(MCS7830_CTRL_TIMEOUT));
+	return ret;
+}
+
+static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data)
+{
+	struct usb_device *xdev = dev->udev;
+	int ret;
+
+	ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ,
+			      MCS7830_WR_BMREQ, 0x0000, index, data,
+			      size, msecs_to_jiffies(MCS7830_CTRL_TIMEOUT));
+	return ret;
+}
+
+static void mcs7830_async_cmd_callback(struct urb *urb)
+{
+	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+
+	if (urb->status < 0)
+		printk(KERN_DEBUG "mcs7830_async_cmd_callback() failed with %d",
+			urb->status);
+
+	kfree(req);
+	usb_free_urb(urb);
+}
+
+static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data)
+{
+	struct usb_ctrlrequest *req;
+	int ret;
+	struct urb *urb;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		dev_dbg(&dev->udev->dev, "Error allocating URB "
+				"in write_cmd_async!");
+		return;
+	}
+
+	req = kmalloc(sizeof *req, GFP_ATOMIC);
+	if (!req) {
+		dev_err(&dev->udev->dev, "Failed to allocate memory for "
+				"control request");
+		goto out;
+	}
+	req->bRequestType = MCS7830_WR_BMREQ;
+	req->bRequest = MCS7830_WR_BREQ;
+	req->wValue = 0;
+	req->wIndex = cpu_to_le16(index);
+	req->wLength = cpu_to_le16(size);
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, data, size,
+			     mcs7830_async_cmd_callback, req);
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret < 0) {
+		dev_err(&dev->udev->dev, "Error submitting the control "
+				"message: ret=%d", ret);
+		goto out;
+	}
+	return;
+out:
+	kfree(req);
+	usb_free_urb(urb);
+}
+
+static int mcs7830_get_address(struct usbnet *dev)
+{
+	int ret;
+	ret = mcs7830_get_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN,
+				   dev->net->dev_addr);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int mcs7830_read_phy(struct usbnet *dev, u8 index)
+{
+	int ret;
+	int i;
+	__le16 val;
+
+	u8 cmd[2] = {
+		HIF_REG_PHY_CMD1_READ | HIF_REG_PHY_CMD1_PHYADDR,
+		HIF_REG_PHY_CMD2_PEND_FLAG_BIT | index,
+	};
+
+	mutex_lock(&dev->phy_mutex);
+	/* write the MII command */
+	ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
+	if (ret < 0)
+		goto out;
+
+	/* wait for the data to become valid, should be within < 1ms */
+	for (i = 0; i < 10; i++) {
+		ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
+		if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT))
+			break;
+		ret = -EIO;
+		msleep(1);
+	}
+	if (ret < 0)
+		goto out;
+
+	/* read actual register contents */
+	ret = mcs7830_get_reg(dev, HIF_REG_PHY_DATA, 2, &val);
+	if (ret < 0)
+		goto out;
+	ret = le16_to_cpu(val);
+	dev_dbg(&dev->udev->dev, "read PHY reg %02x: %04x (%d tries)\n",
+		index, val, i);
+out:
+	mutex_unlock(&dev->phy_mutex);
+	return ret;
+}
+
+static int mcs7830_write_phy(struct usbnet *dev, u8 index, u16 val)
+{
+	int ret;
+	int i;
+	__le16 le_val;
+
+	u8 cmd[2] = {
+		HIF_REG_PHY_CMD1_WRITE | HIF_REG_PHY_CMD1_PHYADDR,
+		HIF_REG_PHY_CMD2_PEND_FLAG_BIT | (index & 0x1F),
+	};
+
+	mutex_lock(&dev->phy_mutex);
+
+	/* write the new register contents */
+	le_val = cpu_to_le16(val);
+	ret = mcs7830_set_reg(dev, HIF_REG_PHY_DATA, 2, &le_val);
+	if (ret < 0)
+		goto out;
+
+	/* write the MII command */
+	ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
+	if (ret < 0)
+		goto out;
+
+	/* wait for the command to be accepted by the PHY */
+	for (i = 0; i < 10; i++) {
+		ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
+		if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT))
+			break;
+		ret = -EIO;
+		msleep(1);
+	}
+	if (ret < 0)
+		goto out;
+
+	ret = 0;
+	dev_dbg(&dev->udev->dev, "write PHY reg %02x: %04x (%d tries)\n",
+		index, val, i);
+out:
+	mutex_unlock(&dev->phy_mutex);
+	return ret;
+}
+
+/*
+ * This algorithm comes from the original mcs7830 version 1.4 driver,
+ * not sure if it is needed.
+ */
+static int mcs7830_set_autoneg(struct usbnet *dev, int ptrUserPhyMode)
+{
+	int ret;
+	/* Enable all media types */
+	ret = mcs7830_write_phy(dev, MII_ADVERTISE, MCS7830_MII_ADVERTISE);
+
+	/* First reset BMCR */
+	if (!ret)
+		ret = mcs7830_write_phy(dev, MII_BMCR, 0x0000);
+	/* Enable Auto Neg */
+	if (!ret)
+		ret = mcs7830_write_phy(dev, MII_BMCR, BMCR_ANENABLE);
+	/* Restart Auto Neg (Keep the Enable Auto Neg Bit Set) */
+	if (!ret)
+		ret = mcs7830_write_phy(dev, MII_BMCR,
+				BMCR_ANENABLE | BMCR_ANRESTART	);
+	return ret < 0 ? : 0;
+}
+
+
+/*
+ * if we can read register 22, the chip revision is C or higher
+ */
+static int mcs7830_get_rev(struct usbnet *dev)
+{
+	u8 dummy[2];
+	int ret;
+	ret = mcs7830_get_reg(dev, HIF_REG_22, 2, dummy);
+	if (ret > 0)
+		return 2; /* Rev C or later */
+	return 1; /* earlier revision */
+}
+
+/*
+ * On rev. C we need to set the pause threshold
+ */
+static void mcs7830_rev_C_fixup(struct usbnet *dev)
+{
+	u8 pause_threshold = HIF_REG_PAUSE_THRESHOLD_DEFAULT;
+	int retry;
+
+	for (retry = 0; retry < 2; retry++) {
+		if (mcs7830_get_rev(dev) == 2) {
+			dev_info(&dev->udev->dev, "applying rev.C fixup\n");
+			mcs7830_set_reg(dev, HIF_REG_PAUSE_THRESHOLD,
+					1, &pause_threshold);
+		}
+		msleep(1);
+	}
+}
+
+static int mcs7830_init_dev(struct usbnet *dev)
+{
+	int ret;
+	int retry;
+
+	/* Read MAC address from EEPROM */
+	ret = -EINVAL;
+	for (retry = 0; retry < 5 && ret; retry++)
+		ret = mcs7830_get_address(dev);
+	if (ret) {
+		dev_warn(&dev->udev->dev, "Cannot read MAC address\n");
+		goto out;
+	}
+
+	/* Set up PHY */
+	ret = mcs7830_set_autoneg(dev, 0);
+	if (ret) {
+		dev_info(&dev->udev->dev, "Cannot set autoneg\n");
+		goto out;
+	}
+
+	mcs7830_rev_C_fixup(dev);
+	ret = 0;
+out:
+	return ret;
+}
+
+static int mcs7830_mdio_read(struct net_device *netdev, int phy_id,
+			     int location)
+{
+	struct usbnet *dev = netdev->priv;
+	return mcs7830_read_phy(dev, location);
+}
+
+static void mcs7830_mdio_write(struct net_device *netdev, int phy_id,
+				int location, int val)
+{
+	struct usbnet *dev = netdev->priv;
+	mcs7830_write_phy(dev, location, val);
+}
+
+static int mcs7830_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+	struct usbnet *dev = netdev_priv(net);
+	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+/* credits go to asix_set_multicast */
+static void mcs7830_set_multicast(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct mcs7830_data *data = (struct mcs7830_data *)&dev->data;
+
+	data->config = HIF_REG_CONFIG_TXENABLE;
+
+	/* this should not be needed, but it doesn't work otherwise */
+	data->config |= HIF_REG_CONFIG_ALLMULTICAST;
+
+	if (net->flags & IFF_PROMISC) {
+		data->config |= HIF_REG_CONFIG_PROMISCIOUS;
+	} else if (net->flags & IFF_ALLMULTI
+		   || net->mc_count > MCS7830_MAX_MCAST) {
+		data->config |= HIF_REG_CONFIG_ALLMULTICAST;
+	} else if (net->mc_count == 0) {
+		/* just broadcast and directed */
+	} else {
+		/* We use the 20 byte dev->data
+		 * for our 8 byte filter buffer
+		 * to avoid allocating memory that
+		 * is tricky to free later */
+		struct dev_mc_list *mc_list = net->mc_list;
+		u32 crc_bits;
+		int i;
+
+		memset(data->multi_filter, 0, sizeof data->multi_filter);
+
+		/* Build the multicast hash filter. */
+		for (i = 0; i < net->mc_count; i++) {
+			crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26;
+			data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7);
+			mc_list = mc_list->next;
+		}
+
+		mcs7830_set_reg_async(dev, HIF_REG_MULTICAST_HASH,
+				sizeof data->multi_filter,
+				data->multi_filter);
+	}
+
+	mcs7830_set_reg_async(dev, HIF_REG_CONFIG, 1, &data->config);
+}
+
+static int mcs7830_get_regs_len(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	switch (mcs7830_get_rev(dev)) {
+	case 1:
+		return 21;
+	case 2:
+		return 32;
+	}
+	return 0;
+}
+
+static void mcs7830_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *drvinfo)
+{
+	usbnet_get_drvinfo(net, drvinfo);
+	drvinfo->regdump_len = mcs7830_get_regs_len(net);
+}
+
+static void mcs7830_get_regs(struct net_device *net, struct ethtool_regs *regs, void *data)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	regs->version = mcs7830_get_rev(dev);
+	mcs7830_get_reg(dev, 0, regs->len, data);
+}
+
+static struct ethtool_ops mcs7830_ethtool_ops = {
+	.get_drvinfo		= mcs7830_get_drvinfo,
+	.get_regs_len		= mcs7830_get_regs_len,
+	.get_regs		= mcs7830_get_regs,
+
+	/* common usbnet calls */
+	.get_link		= usbnet_get_link,
+	.get_msglevel		= usbnet_get_msglevel,
+	.set_msglevel		= usbnet_set_msglevel,
+	.get_settings		= usbnet_get_settings,
+	.set_settings		= usbnet_set_settings,
+	.nway_reset		= usbnet_nway_reset,
+};
+
+static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev)
+{
+	struct net_device *net = dev->net;
+	int ret;
+
+	ret = mcs7830_init_dev(dev);
+	if (ret)
+		goto out;
+
+	net->do_ioctl = mcs7830_ioctl;
+	net->ethtool_ops = &mcs7830_ethtool_ops;
+	net->set_multicast_list = mcs7830_set_multicast;
+	mcs7830_set_multicast(net);
+
+	/* reserve space for the status byte on rx */
+	dev->rx_urb_size = ETH_FRAME_LEN + 1;
+
+	dev->mii.mdio_read = mcs7830_mdio_read;
+	dev->mii.mdio_write = mcs7830_mdio_write;
+	dev->mii.dev = net;
+	dev->mii.phy_id_mask = 0x3f;
+	dev->mii.reg_num_mask = 0x1f;
+	dev->mii.phy_id = *((u8 *) net->dev_addr + 1);
+
+	ret = usbnet_get_endpoints(dev, udev);
+out:
+	return ret;
+}
+
+/* The chip always appends a status bytes that we need to strip */
+static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	u8 status;
+
+	if (skb->len == 0) {
+		dev_err(&dev->udev->dev, "unexpected empty rx frame\n");
+		return 0;
+	}
+
+	skb_trim(skb, skb->len - 1);
+	status = skb->data[skb->len];
+
+	if (status != 0x20)
+		dev_dbg(&dev->udev->dev, "rx fixup status %x\n", status);
+
+	return skb->len > 0;
+}
+
+static const struct driver_info moschip_info = {
+	.description	= "MOSCHIP 7830 usb-NET adapter",
+	.bind		= mcs7830_bind,
+	.rx_fixup	= mcs7830_rx_fixup,
+	.flags		= FLAG_ETHER,
+	.in		= 1,
+	.out		= 2,
+};
+
+static const struct usb_device_id products[] = {
+	{
+		USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID),
+		.driver_info = (unsigned long) &moschip_info,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver mcs7830_driver = {
+	.name = driver_name,
+	.id_table = products,
+	.probe = usbnet_probe,
+	.disconnect = usbnet_disconnect,
+	.suspend = usbnet_suspend,
+	.resume = usbnet_resume,
+};
+
+static int __init mcs7830_init(void)
+{
+	return usb_register(&mcs7830_driver);
+}
+module_init(mcs7830_init);
+
+static void __exit mcs7830_exit(void)
+{
+	usb_deregister(&mcs7830_driver);
+}
+module_exit(mcs7830_exit);
+
+MODULE_DESCRIPTION("USB to network adapter MCS7830)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index 301baa7..ce00de8 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -368,7 +368,7 @@
 	return 0;
 }
 
-static void nc_flush_complete(struct urb *urb, struct pt_regs *regs)
+static void nc_flush_complete(struct urb *urb)
 {
 	kfree(urb->context);
 	usb_free_urb(urb);
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 918cf5a..33abbd2 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -96,7 +96,7 @@
 
 static int update_eth_regs_async(pegasus_t *);
 /* Aargh!!! I _really_ hate such tweaks */
-static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
+static void ctrl_callback(struct urb *urb)
 {
 	pegasus_t *pegasus = urb->context;
 
@@ -605,7 +605,7 @@
 	return NULL;
 }
 
-static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void read_bulk_callback(struct urb *urb)
 {
 	pegasus_t *pegasus = urb->context;
 	struct net_device *net;
@@ -764,7 +764,7 @@
 	spin_unlock_irqrestore(&pegasus->rx_pool_lock, flags);
 }
 
-static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void write_bulk_callback(struct urb *urb)
 {
 	pegasus_t *pegasus = urb->context;
 	struct net_device *net = pegasus->net;
@@ -801,7 +801,7 @@
 	netif_wake_queue(net);
 }
 
-static void intr_callback(struct urb *urb, struct pt_regs *regs)
+static void intr_callback(struct urb *urb)
 {
 	pegasus_t *pegasus = urb->context;
 	struct net_device *net;
@@ -1226,7 +1226,7 @@
 	}
 
 	pegasus->flags |= ETH_REGS_CHANGE;
-	ctrl_callback(pegasus->ctrl_urb, NULL);
+	ctrl_callback(pegasus->ctrl_urb);
 }
 
 static __u8 mii_phy_probe(pegasus_t * pegasus)
@@ -1433,11 +1433,11 @@
 	if (netif_running(pegasus->net)) {
 		pegasus->rx_urb->status = 0;
 		pegasus->rx_urb->actual_length = 0;
-		read_bulk_callback(pegasus->rx_urb, NULL);
+		read_bulk_callback(pegasus->rx_urb);
 
 		pegasus->intr_urb->status = 0;
 		pegasus->intr_urb->actual_length = 0;
-		intr_callback(pegasus->intr_urb, NULL);
+		intr_callback(pegasus->intr_urb);
 	}
 	queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
 				CARRIER_CHECK_DELAY);
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 2364c20..72171f9 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -208,7 +208,7 @@
 			       indx, 0, data, size, 500);
 }
 
-static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
+static void ctrl_callback(struct urb *urb)
 {
 	rtl8150_t *dev;
 
@@ -415,7 +415,7 @@
 	return NULL;
 }
 
-static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void read_bulk_callback(struct urb *urb)
 {
 	rtl8150_t *dev;
 	unsigned pkt_len, res;
@@ -525,7 +525,7 @@
 	tasklet_schedule(&dev->tl);
 }
 
-static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void write_bulk_callback(struct urb *urb)
 {
 	rtl8150_t *dev;
 
@@ -541,7 +541,7 @@
 	netif_wake_queue(dev->netdev);
 }
 
-static void intr_callback(struct urb *urb, struct pt_regs *regs)
+static void intr_callback(struct urb *urb)
 {
 	rtl8150_t *dev;
 	__u8 *d;
@@ -617,11 +617,11 @@
 	if (netif_running(dev->netdev)) {
 		dev->rx_urb->status = 0;
 		dev->rx_urb->actual_length = 0;
-		read_bulk_callback(dev->rx_urb, NULL);
+		read_bulk_callback(dev->rx_urb);
 
 		dev->intr_urb->status = 0;
 		dev->intr_urb->actual_length = 0;
-		intr_callback(dev->intr_urb, NULL);
+		intr_callback(dev->intr_urb);
 	}
 	return 0;
 }
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 98a522f..cf3d20e 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -158,7 +158,7 @@
 }
 EXPORT_SYMBOL_GPL(usbnet_get_endpoints);
 
-static void intr_complete (struct urb *urb, struct pt_regs *regs);
+static void intr_complete (struct urb *urb);
 
 static int init_status (struct usbnet *dev, struct usb_interface *intf)
 {
@@ -295,7 +295,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void rx_complete (struct urb *urb, struct pt_regs *regs);
+static void rx_complete (struct urb *urb);
 
 static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
 {
@@ -383,7 +383,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void rx_complete (struct urb *urb, struct pt_regs *regs)
+static void rx_complete (struct urb *urb)
 {
 	struct sk_buff		*skb = (struct sk_buff *) urb->context;
 	struct skb_data		*entry = (struct skb_data *) skb->cb;
@@ -467,7 +467,7 @@
 		devdbg (dev, "no read resubmitted");
 }
 
-static void intr_complete (struct urb *urb, struct pt_regs *regs)
+static void intr_complete (struct urb *urb)
 {
 	struct usbnet	*dev = urb->context;
 	int		status = urb->status;
@@ -669,6 +669,37 @@
  * they'll probably want to use this base set.
  */
 
+int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	if (!dev->mii.mdio_read)
+		return -EOPNOTSUPP;
+
+	return mii_ethtool_gset(&dev->mii, cmd);
+}
+EXPORT_SYMBOL_GPL(usbnet_get_settings);
+
+int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd)
+{
+	struct usbnet *dev = netdev_priv(net);
+	int retval;
+
+	if (!dev->mii.mdio_write)
+		return -EOPNOTSUPP;
+
+	retval = mii_ethtool_sset(&dev->mii, cmd);
+
+	/* link speed/duplex might have changed */
+	if (dev->driver_info->link_reset)
+		dev->driver_info->link_reset(dev);
+
+	return retval;
+
+}
+EXPORT_SYMBOL_GPL(usbnet_set_settings);
+
+
 void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -682,7 +713,7 @@
 }
 EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
 
-static u32 usbnet_get_link (struct net_device *net)
+u32 usbnet_get_link (struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
 
@@ -690,9 +721,14 @@
 	if (dev->driver_info->check_connect)
 		return dev->driver_info->check_connect (dev) == 0;
 
+	/* if the device has mii operations, use those */
+	if (dev->mii.mdio_read)
+		return mii_link_ok(&dev->mii);
+
 	/* Otherwise, say we're up (to avoid breaking scripts) */
 	return 1;
 }
+EXPORT_SYMBOL_GPL(usbnet_get_link);
 
 u32 usbnet_get_msglevel (struct net_device *net)
 {
@@ -710,10 +746,24 @@
 }
 EXPORT_SYMBOL_GPL(usbnet_set_msglevel);
 
+int usbnet_nway_reset(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+
+	if (!dev->mii.mdio_write)
+		return -EOPNOTSUPP;
+
+	return mii_nway_restart(&dev->mii);
+}
+EXPORT_SYMBOL_GPL(usbnet_nway_reset);
+
 /* drivers may override default ethtool_ops in their bind() routine */
 static struct ethtool_ops usbnet_ethtool_ops = {
+	.get_settings		= usbnet_get_settings,
+	.set_settings		= usbnet_set_settings,
 	.get_drvinfo		= usbnet_get_drvinfo,
 	.get_link		= usbnet_get_link,
+	.nway_reset		= usbnet_nway_reset,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
 };
@@ -797,7 +847,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void tx_complete (struct urb *urb, struct pt_regs *regs)
+static void tx_complete (struct urb *urb)
 {
 	struct sk_buff		*skb = (struct sk_buff *) urb->context;
 	struct skb_data		*entry = (struct skb_data *) skb->cb;
@@ -1094,6 +1144,7 @@
 	dev->delay.function = usbnet_bh;
 	dev->delay.data = (unsigned long) dev;
 	init_timer (&dev->delay);
+	mutex_init (&dev->phy_mutex);
 
 	SET_MODULE_OWNER (net);
 	dev->net = net;
@@ -1225,7 +1276,7 @@
 static int __init usbnet_init(void)
 {
 	/* compiler should optimize this out */
-	BUG_ON (sizeof (((struct sk_buff *)0)->cb)
+	BUILD_BUG_ON (sizeof (((struct sk_buff *)0)->cb)
 			< sizeof (struct skb_data));
 
 	random_ether_addr(node_id);
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
index c0746f0..07c70ab 100644
--- a/drivers/usb/net/usbnet.h
+++ b/drivers/usb/net/usbnet.h
@@ -30,6 +30,7 @@
 	struct usb_device	*udev;
 	struct driver_info	*driver_info;
 	wait_queue_head_t	*wait;
+	struct mutex		phy_mutex;
 
 	/* i/o info: pipes etc */
 	unsigned		in, out;
@@ -168,9 +169,13 @@
 extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
 extern void usbnet_unlink_rx_urbs(struct usbnet *);
 
+extern int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd);
+extern int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd);
+extern u32 usbnet_get_link (struct net_device *net);
 extern u32 usbnet_get_msglevel (struct net_device *);
 extern void usbnet_set_msglevel (struct net_device *, u32);
 extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
+extern int usbnet_nway_reset(struct net_device *net);
 
 /* messaging support includes the interface name, so it must not be
  * used before it has one ... notably, in minidriver bind() calls.
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 5076b9d..9a6ec1b 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -422,6 +422,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mct_u232.
 
+config USB_SERIAL_MOS7720
+	tristate "USB Moschip 7720 Single Port Serial Driver"
+	depends on USB_SERIAL
+	---help---
+	  Say Y here if you want to use a USB Serial single port adapter from
+	  Moschip Semiconductor Tech.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mos7720.
+
 config USB_SERIAL_MOS7840
 	tristate "USB Moschip 7840/7820 USB Serial Driver"
 	depends on USB_SERIAL
@@ -527,8 +537,7 @@
 	  The USB bus on these cards is not accessible externally.
 
 	  Supported devices include (some of?) those made by:
-	  Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or
-	  Anydata.
+	  Option, Huawei, Audiovox, Novatel Wireless, or Anydata.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called option.
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 8dce833..a5047dc 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)		+= kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)		+= mct_u232.o
+obj-$(CONFIG_USB_SERIAL_MOS7720)		+= mos7720.o
 obj-$(CONFIG_USB_SERIAL_MOS7840)		+= mos7840.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)			+= navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)		+= omninet.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 2ccd9de..8122755 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -403,7 +403,7 @@
 
 }
 
-static void aircable_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void aircable_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	int result;
@@ -444,7 +444,7 @@
 	aircable_send(port);
 }
 
-static void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void aircable_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct aircable_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 6e1a84a..7f5d546 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -18,12 +18,8 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
-	{ USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */
-	{ USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
-	{ USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
-	{ USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+	{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -46,7 +42,7 @@
 	struct urb *read_urbp[NUM_READ_URBS];
 };
 
-static void airprime_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void airprime_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -80,7 +76,7 @@
 	return;
 }
 
-static void airprime_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void airprime_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct airprime_private *priv = usb_get_serial_port_data(port);
@@ -133,6 +129,7 @@
 		}
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!urb) {
+			kfree(buffer);
 			dev_err(&port->dev, "%s - no more urbs?\n",
 				__FUNCTION__);
 			result = -ENOMEM;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 70ece9e..8835bb5 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -91,7 +91,7 @@
 static void belkin_sa_shutdown		(struct usb_serial *serial);
 static int  belkin_sa_open		(struct usb_serial_port *port, struct file *filp);
 static void belkin_sa_close		(struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs);
+static void belkin_sa_read_int_callback (struct urb *urb);
 static void belkin_sa_set_termios	(struct usb_serial_port *port, struct termios * old);
 static int  belkin_sa_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void belkin_sa_break_ctl		(struct usb_serial_port *port, int break_state );
@@ -248,7 +248,7 @@
 } /* belkin_sa_close */
 
 
-static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void belkin_sa_read_int_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct belkin_sa_private *priv;
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 486c741..bbf6532 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -65,6 +65,7 @@
 	{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
 	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ } /* Terminating Entry */
 };
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index d954ec3..a63c328 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -63,9 +63,9 @@
 static void cyberjack_close (struct usb_serial_port *port, struct file *filp);
 static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count);
 static int cyberjack_write_room( struct usb_serial_port *port );
-static void cyberjack_read_int_callback (struct urb *urb, struct pt_regs *regs);
-static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
+static void cyberjack_read_int_callback (struct urb *urb);
+static void cyberjack_read_bulk_callback (struct urb *urb);
+static void cyberjack_write_bulk_callback (struct urb *urb);
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
@@ -299,7 +299,7 @@
 	return CYBERJACK_LOCAL_BUF_SIZE;
 }
 
-static void cyberjack_read_int_callback( struct urb *urb, struct pt_regs *regs )
+static void cyberjack_read_int_callback( struct urb *urb )
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -356,7 +356,7 @@
 	dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
 }
 
-static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void cyberjack_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -406,7 +406,7 @@
 	}
 }
 
-static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void cyberjack_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index e1173c1..f2e89a0 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -172,8 +172,8 @@
 static void cypress_throttle		(struct usb_serial_port *port);
 static void cypress_unthrottle		(struct usb_serial_port *port);
 static void cypress_set_dead		(struct usb_serial_port *port);
-static void cypress_read_int_callback	(struct urb *urb, struct pt_regs *regs);
-static void cypress_write_int_callback	(struct urb *urb, struct pt_regs *regs);
+static void cypress_read_int_callback	(struct urb *urb);
+static void cypress_write_int_callback	(struct urb *urb);
 /* baud helper functions */
 static int	 mask_to_rate		(unsigned mask);
 static unsigned  rate_to_mask		(int rate);
@@ -1275,7 +1275,7 @@
 }
 
 
-static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
+static void cypress_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
@@ -1426,7 +1426,7 @@
 } /* cypress_read_int_callback */
 
 
-static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs)
+static void cypress_write_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 9b22518..bdb5810 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -456,7 +456,7 @@
 static int digi_tiocmset( struct usb_serial_port *port, struct file *file,
 	unsigned int set, unsigned int clear );
 static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count );
-static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs );
+static void digi_write_bulk_callback( struct urb *urb );
 static int digi_write_room( struct usb_serial_port *port );
 static int digi_chars_in_buffer( struct usb_serial_port *port );
 static int digi_open( struct usb_serial_port *port, struct file *filp );
@@ -464,7 +464,7 @@
 static int digi_startup_device( struct usb_serial *serial );
 static int digi_startup( struct usb_serial *serial );
 static void digi_shutdown( struct usb_serial *serial );
-static void digi_read_bulk_callback( struct urb *urb, struct pt_regs *regs );
+static void digi_read_bulk_callback( struct urb *urb );
 static int digi_read_inb_callback( struct urb *urb );
 static int digi_read_oob_callback( struct urb *urb );
 
@@ -1336,7 +1336,7 @@
 } 
 
 
-static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs )
+static void digi_write_bulk_callback( struct urb *urb )
 {
 
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -1754,7 +1754,7 @@
 }
 
 
-static void digi_read_bulk_callback( struct urb *urb, struct pt_regs *regs )
+static void digi_read_bulk_callback( struct urb *urb )
 {
 
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index daafe40..4ce10a8 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -93,8 +93,8 @@
 					unsigned int cmd,
 					unsigned long arg);
 static void empeg_set_termios		(struct usb_serial_port *port, struct termios *old_termios);
-static void empeg_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void empeg_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
+static void empeg_write_bulk_callback	(struct urb *urb);
+static void empeg_read_bulk_callback	(struct urb *urb);
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
@@ -323,7 +323,7 @@
 }
 
 
-static void empeg_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void empeg_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 
@@ -338,7 +338,7 @@
 }
 
 
-static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void empeg_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct tty_struct *tty;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index e774a27..bd76b4c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1,16 +1,16 @@
 /*
  * USB FTDI SIO driver
  *
- * 	Copyright (C) 1999 - 2001
- * 	    Greg Kroah-Hartman (greg@kroah.com)
+ *	Copyright (C) 1999 - 2001
+ *	    Greg Kroah-Hartman (greg@kroah.com)
  *          Bill Ryder (bryder@sgi.com)
  *	Copyright (C) 2002
  *	    Kuba Ober (kuba@mareimbrium.org)
  *
- * 	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 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.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
@@ -32,7 +32,7 @@
  *      Changed full name of USB-UIRT device to avoid "/" character.
  *      Added FTDI's alternate PID (0x6006) for FT232/245 devices.
  *      Added PID for "ELV USB Module UO100" from Stefan Frings.
- * 
+ *
  * (21/Oct/2003) Ian Abbott
  *      Renamed some VID/PID macros for Matrix Orbital and Perle Systems
  *      devices.  Removed Matrix Orbital and Perle Systems devices from the
@@ -69,7 +69,7 @@
  *	does not incure any measurable overhead.  This also relies on the fact
  *	that we have proper reference counting logic for urbs.  I nicked this
  *	from Greg KH's Visor driver.
- *      
+ *
  * (23/Jun/2003) Ian Abbott
  *      Reduced flip buffer pushes and corrected a data length test in
  *      ftdi_read_bulk_callback.
@@ -77,7 +77,7 @@
  *
  * (21/Jun/2003) Erik Nygren
  *      Added support for Home Electronics Tira-1 IR transceiver using FT232BM chip.
- *      See <http://www.home-electro.com/tira1.htm>.  Only operates properly 
+ *      See <http://www.home-electro.com/tira1.htm>.  Only operates properly
  *      at 100000 and RTS-CTS, so set custom divisor mode on startup.
  *      Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
  *
@@ -137,17 +137,17 @@
  * (17/Feb/2003) Bill Ryder
  *      Added write urb buffer pool on a per device basis
  *      Added more checking for open file on callbacks (fixed OOPS)
- *      Added CrystalFontz 632 and 634 PIDs 
+ *      Added CrystalFontz 632 and 634 PIDs
  *         (thanx to CrystalFontz for the sample devices - they flushed out
  *           some driver bugs)
  *      Minor debugging message changes
  *      Added throttle, unthrottle and chars_in_buffer functions
  *      Fixed FTDI_SIO (the original device) bug
  *      Fixed some shutdown handling
- *      
- * 
- * 
- * 
+ *
+ *
+ *
+ *
  * (07/Jun/2002) Kuba Ober
  *	Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor
  *	function. It was getting too complex.
@@ -158,7 +158,7 @@
  *
  * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
  *      Not tested by me but it doesn't break anything I use.
- * 
+ *
  * (04/Jan/2002) Kuba Ober
  *	Implemented 38400 baudrate kludge, where it can be substituted with other
  *	  values. That's the only way to set custom baudrates.
@@ -179,7 +179,7 @@
  *        (the previous version caused panics)
  *	Removed port iteration code since the device only has one I/O port and it
  *	  was wrong anyway.
- * 
+ *
  * (31/May/2001) gkh
  *	Switched from using spinlock to a semaphore, which fixes lots of problems.
  *
@@ -188,16 +188,16 @@
  *	Cleaned up comments for 8U232
  *	Added parity, framing and overrun error handling
  *	Added receive break handling.
- * 
+ *
  * (04/08/2001) gb
  *	Identify version on module load.
- *       
+ *
  * (18/March/2001) Bill Ryder
  *	(Not released)
  *	Added send break handling. (requires kernel patch too)
  *	Fixed 8U232AM hardware RTS/CTS etc status reporting.
  *	Added flipbuf fix copied from generic device
- * 
+ *
  * (12/3/2000) Bill Ryder
  *	Added support for 8U232AM device.
  *	Moved PID and VIDs into header file only.
@@ -211,14 +211,14 @@
  *	Cleaned up comments. Removed multiple PID/VID definitions.
  *	Factorised cts/dtr code
  *	Made use of __FUNCTION__ in dbg's
- *      
+ *
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
- * 
+ *
  * (10/05/2000) gkh
  *	Fixed bug with urb->dev not being set properly, now that the usb
  *	core needs it.
- * 
+ *
  * (09/11/2000) gkh
  *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
  *
@@ -226,11 +226,11 @@
  *	Added module_init and module_exit functions to handle the fact that this
  *	driver is a loadable module now.
  *
- * (04/04/2000) Bill Ryder 
+ * (04/04/2000) Bill Ryder
  *	Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
  *        handled elsewhere in the tty io driver chain).
  *
- * (03/30/2000) Bill Ryder 
+ * (03/30/2000) Bill Ryder
  *	Implemented lots of ioctls
  *	Fixed a race condition in write
  *	Changed some dbg's to errs
@@ -444,13 +444,13 @@
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */
- 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
- 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
- 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
- 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) },
- 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
- 	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
- 	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
+	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
+	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
+	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
+	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) },
+	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
 	{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
 	{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
@@ -522,7 +522,7 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
+	.no_dynamic_id =	1,
 };
 
 static const char *ftdi_chip_name[] = {
@@ -548,13 +548,13 @@
 	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
 	__u16 last_set_data_urb_value ;
 				/* the last data state set - needed for doing a break */
-        int write_offset;       /* This is the offset in the usb data block to write the serial data - 
+        int write_offset;       /* This is the offset in the usb data block to write the serial data -
 				 * it is different between devices
 				 */
 	int flags;		/* some ASYNC_xxxx flags are supported */
 	unsigned long last_dtr_rts;	/* saved modem control outputs */
         wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- 	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
 	__u8 rx_flags;		/* receive state flags (throttling) */
 	spinlock_t rx_lock;	/* spinlock for receive state */
 	struct work_struct rx_work;
@@ -589,8 +589,8 @@
 static int  ftdi_write			(struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  ftdi_write_room		(struct usb_serial_port *port);
 static int  ftdi_chars_in_buffer	(struct usb_serial_port *port);
-static void ftdi_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void ftdi_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
+static void ftdi_write_bulk_callback	(struct urb *urb);
+static void ftdi_read_bulk_callback	(struct urb *urb);
 static void ftdi_process_read		(void *param);
 static void ftdi_set_termios		(struct usb_serial_port *port, struct termios * old);
 static int  ftdi_tiocmget               (struct usb_serial_port *port, struct file *file);
@@ -721,7 +721,7 @@
 		urb_value |= FTDI_SIO_SET_RTS_HIGH;
 	rv = usb_control_msg(port->serial->dev,
 			       usb_sndctrlpipe(port->serial->dev, 0),
-			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			       FTDI_SIO_SET_MODEM_CTRL_REQUEST,
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
 			       urb_value, priv->interface,
 			       buf, 0, WDR_TIMEOUT);
@@ -768,7 +768,7 @@
 	if (priv->interface) {	/* FT2232C */
 		urb_index = (__u16)((urb_index << 8) | priv->interface);
 	}
-	
+
 	rv = usb_control_msg(port->serial->dev,
 			    usb_sndctrlpipe(port->serial->dev, 0),
 			    FTDI_SIO_SET_BAUDRATE_REQUEST,
@@ -827,7 +827,7 @@
 
 	/* 3. Convert baudrate to device-specific divisor */
 
-	if (!baud) baud = 9600;	
+	if (!baud) baud = 9600;
 	switch(priv->chip_type) {
 	case SIO: /* SIO chip */
 		switch(baud) {
@@ -843,7 +843,7 @@
 		case 115200: div_value = ftdi_sio_b115200; break;
 		} /* baud */
 		if (div_value == 0) {
-  			dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__,  baud);
+			dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__,  baud);
 			div_value = ftdi_sio_b9600;
 			div_okay = 0;
 		}
@@ -925,7 +925,7 @@
 	/* Make the changes - these are privileged changes! */
 
 	priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
-	               (new_serial.flags & ASYNC_FLAGS));	
+	               (new_serial.flags & ASYNC_FLAGS));
 	priv->custom_divisor = new_serial.custom_divisor;
 
 	port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
@@ -950,7 +950,7 @@
 	     (old_priv.custom_divisor != priv->custom_divisor))) {
 		change_speed(port);
 	}
-	
+
 	return (0);
 
 } /* set_serial_info */
@@ -1022,18 +1022,18 @@
 	struct usb_device *udev;
 	unsigned short latency = 0;
 	int rv = 0;
-	
+
 	udev = to_usb_device(dev);
-	
+
 	dbg("%s",__FUNCTION__);
-	
+
 	rv = usb_control_msg(udev,
 			     usb_rcvctrlpipe(udev, 0),
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
-			     0, priv->interface, 
+			     0, priv->interface,
 			     (char*) &latency, 1, WDR_TIMEOUT);
-	
+
 	if (rv < 0) {
 		dev_err(dev, "Unable to read latency timer: %i", rv);
 		return -EIO;
@@ -1051,23 +1051,23 @@
 	char buf[1];
 	int v = simple_strtoul(valbuf, NULL, 10);
 	int rv = 0;
-	
+
 	udev = to_usb_device(dev);
-	
+
 	dbg("%s: setting latency timer = %i", __FUNCTION__, v);
-	
+
 	rv = usb_control_msg(udev,
 			     usb_sndctrlpipe(udev, 0),
 			     FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
 			     FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
-			     v, priv->interface, 
+			     v, priv->interface,
 			     buf, 0, WDR_TIMEOUT);
-	
+
 	if (rv < 0) {
 		dev_err(dev, "Unable to write latency timer: %i", rv);
 		return -EIO;
 	}
-	
+
 	return count;
 }
 
@@ -1082,23 +1082,23 @@
 	char buf[1];
 	int v = simple_strtoul(valbuf, NULL, 10);
 	int rv = 0;
-	
+
 	udev = to_usb_device(dev);
-	
+
 	dbg("%s: setting event char = %i", __FUNCTION__, v);
-	
+
 	rv = usb_control_msg(udev,
 			     usb_sndctrlpipe(udev, 0),
 			     FTDI_SIO_SET_EVENT_CHAR_REQUEST,
 			     FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE,
-			     v, priv->interface, 
+			     v, priv->interface,
 			     buf, 0, WDR_TIMEOUT);
-	
+
 	if (rv < 0) {
 		dbg("Unable to write event character: %i", rv);
 		return -EIO;
 	}
-	
+
 	return count;
 }
 
@@ -1135,11 +1135,11 @@
 	struct ftdi_private *priv;
 	struct usb_device *udev;
 
-	dbg("%s",__FUNCTION__);	
+	dbg("%s",__FUNCTION__);
 
 	priv = usb_get_serial_port_data(serial->port[0]);
 	udev = serial->dev;
-	
+
 	/* XXX see create_sysfs_attrs */
 	if (priv->chip_type != SIO) {
 		device_remove_file(&udev->dev, &dev_attr_event_char);
@@ -1147,7 +1147,7 @@
 			device_remove_file(&udev->dev, &dev_attr_latency_timer);
 		}
 	}
-	
+
 }
 
 /*
@@ -1258,7 +1258,7 @@
 } /* ftdi_HE_TIRA1_setup */
 
 
-/* ftdi_shutdown is called from usbserial:usb_serial_disconnect 
+/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
  *   it is called when the usb device is disconnected
  *
  *   usbserial:usb_serial_disconnect
@@ -1269,16 +1269,16 @@
 
 static void ftdi_shutdown (struct usb_serial *serial)
 { /* ftdi_shutdown */
-	
+
 	struct usb_serial_port *port = serial->port[0];
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
 	dbg("%s", __FUNCTION__);
 
 	remove_sysfs_attrs(serial);
-	
-	/* all open ports are closed at this point 
-         *    (by usbserial.c:__serial_close, which calls ftdi_close)  
+
+	/* all open ports are closed at this point
+         *    (by usbserial.c:__serial_close, which calls ftdi_close)
 	 */
 
 	if (priv) {
@@ -1293,7 +1293,7 @@
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	
+
 	int result = 0;
 	char buf[1]; /* Needed for the usb_control_msg I think */
 
@@ -1312,8 +1312,8 @@
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
-			FTDI_SIO_RESET_SIO, 
+			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE,
+			FTDI_SIO_RESET_SIO,
 			priv->interface, buf, 0, WDR_TIMEOUT);
 
 	/* Termios defaults are set by usb_serial_init. We don't change
@@ -1350,12 +1350,12 @@
 
 
 
-/* 
+/*
  * usbserial:__serial_close  only calls ftdi_close if the point is open
  *
  *   This only gets called when it is the last close
- *   
- *   
+ *
+ *
  */
 
 static void ftdi_close (struct usb_serial_port *port, struct file *filp)
@@ -1368,14 +1368,14 @@
 
 	if (c_cflag & HUPCL){
 		/* Disable flow control */
-		if (usb_control_msg(port->serial->dev, 
+		if (usb_control_msg(port->serial->dev,
 				    usb_sndctrlpipe(port->serial->dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 				    0, priv->interface, buf, 0,
 				    WDR_TIMEOUT) < 0) {
 			err("error from flowcontrol urb");
-		}	    
+		}
 
 		/* drop RTS and DTR */
 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
@@ -1384,14 +1384,14 @@
 	/* cancel any scheduled reading */
 	cancel_delayed_work(&priv->rx_work);
 	flush_scheduled_work();
-	
+
 	/* shutdown our bulk read */
 	if (port->read_urb)
 		usb_kill_urb(port->read_urb);
 } /* ftdi_close */
 
 
-  
+
 /* The SIO requires the first byte to have:
  *  B0 1
  *  B1 0
@@ -1423,7 +1423,7 @@
 		return 0;
 	}
 	spin_unlock_irqrestore(&priv->tx_lock, flags);
-	
+
 	data_offset = priv->write_offset;
         dbg("data_offset set to %d",data_offset);
 
@@ -1462,7 +1462,7 @@
 				user_pktsz = todo;
 			}
 			/* Write the control byte at the front of the packet*/
-			*first_byte = 1 | ((user_pktsz) << 2); 
+			*first_byte = 1 | ((user_pktsz) << 2);
 			/* Copy data for packet */
 			memcpy (first_byte + data_offset,
 				current_position, user_pktsz);
@@ -1479,7 +1479,7 @@
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);
 
 	/* fill the buffer and send it */
-	usb_fill_bulk_urb(urb, port->serial->dev, 
+	usb_fill_bulk_urb(urb, port->serial->dev,
 		      usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
 		      buffer, transfer_size,
 		      ftdi_write_bulk_callback, port);
@@ -1508,7 +1508,7 @@
 
 /* This function may get called when the device is closed */
 
-static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void ftdi_write_bulk_callback (struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -1520,7 +1520,7 @@
 	kfree (urb->transfer_buffer);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
+
 	if (urb->status) {
 		dbg("nonzero write bulk status received: %d", urb->status);
 		return;
@@ -1591,7 +1591,7 @@
 
 
 
-static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void ftdi_read_bulk_callback (struct urb *urb)
 { /* ftdi_read_bulk_callback */
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct tty_struct *tty;
@@ -1651,7 +1651,7 @@
 	struct tty_struct *tty;
 	struct ftdi_private *priv;
 	char error_flag;
-       	unsigned char *data;
+	unsigned char *data;
 
 	int i;
 	int result;
@@ -1759,7 +1759,7 @@
 		}
 		if (length > 0) {
 			for (i = 2; i < length+2; i++) {
-				/* Note that the error flag is duplicated for 
+				/* Note that the error flag is duplicated for
 				   every character received since we don't know
 				   which character it applied to */
 				tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
@@ -1773,7 +1773,7 @@
 		   This doesn't work well since the application receives a never
 		   ending stream of bad data - even though new data hasn't been sent.
 		   Therefore I (bill) have taken this out.
-		   However - this might make sense for framing errors and so on 
+		   However - this might make sense for framing errors and so on
 		   so I am leaving the code in for now.
 		*/
 		else {
@@ -1827,7 +1827,7 @@
 	/* if the port is closed stop trying to read */
 	if (port->open_count > 0){
 		/* Continue trying to always read  */
-		usb_fill_bulk_urb(port->read_urb, port->serial->dev, 
+		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
 			      usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
 			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
 			      ftdi_read_bulk_callback, port);
@@ -1844,9 +1844,9 @@
 static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	__u16 urb_value = 0; 
+	__u16 urb_value = 0;
 	char buf[1];
-	
+
 	/* break_state = -1 to turn on break, and 0 to turn off break */
 	/* see drivers/char/tty_io.c to see it used */
 	/* last_set_data_urb_value NEVER has the break bit set in it */
@@ -1854,20 +1854,20 @@
 	if (break_state) {
 		urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
 	} else {
-		urb_value = priv->last_set_data_urb_value; 
+		urb_value = priv->last_set_data_urb_value;
 	}
 
-	
+
 	if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
-			    FTDI_SIO_SET_DATA_REQUEST, 
+			    FTDI_SIO_SET_DATA_REQUEST,
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
 			    urb_value , priv->interface,
 			    buf, 0, WDR_TIMEOUT) < 0) {
 		err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
-	}	   
+	}
 
 	dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value);
-	
+
 }
 
 
@@ -1883,12 +1883,12 @@
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	__u16 urb_value; /* will hold the new flags */
 	char buf[1]; /* Perhaps I should dynamically alloc this? */
-	
+
 	// Added for xon/xoff support
 	unsigned int iflag = port->tty->termios->c_iflag;
 	unsigned char vstop;
 	unsigned char vstart;
-	
+
 	dbg("%s", __FUNCTION__);
 
 	/* Force baud rate if this device requires it, unless it is set to B0. */
@@ -1906,20 +1906,20 @@
 
 	cflag = port->tty->termios->c_cflag;
 
-	/* FIXME -For this cut I don't care if the line is really changing or 
-	   not  - so just do the change regardless  - should be able to 
+	/* FIXME -For this cut I don't care if the line is really changing or
+	   not  - so just do the change regardless  - should be able to
 	   compare old_termios and tty->termios */
-	/* NOTE These routines can get interrupted by 
-	   ftdi_sio_read_bulk_callback  - need to examine what this 
+	/* NOTE These routines can get interrupted by
+	   ftdi_sio_read_bulk_callback  - need to examine what this
            means - don't see any problems yet */
-	
+
 	/* Set number of data bits, parity, stop bits */
-	
+
 	urb_value = 0;
 	urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
 		      FTDI_SIO_SET_DATA_STOP_BITS_1);
-	urb_value |= (cflag & PARENB ? 
-		      (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : 
+	urb_value |= (cflag & PARENB ?
+		      (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD :
 		       FTDI_SIO_SET_DATA_PARITY_EVEN) :
 		      FTDI_SIO_SET_DATA_PARITY_NONE);
 	if (cflag & CSIZE) {
@@ -1936,25 +1936,25 @@
 	/* This is needed by the break command since it uses the same command - but is
 	 *  or'ed with this value  */
 	priv->last_set_data_urb_value = urb_value;
-	
+
 	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			    FTDI_SIO_SET_DATA_REQUEST, 
+			    FTDI_SIO_SET_DATA_REQUEST,
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
 			    urb_value , priv->interface,
 			    buf, 0, WDR_SHORT_TIMEOUT) < 0) {
 		err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
-	}	   
+	}
 
 	/* Now do the baudrate */
 	if ((cflag & CBAUD) == B0 ) {
 		/* Disable flow control */
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, priv->interface, 
+				    0, priv->interface,
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("%s error from disable flowcontrol urb", __FUNCTION__);
-		}	    
+		}
 		/* Drop RTS and DTR */
 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	} else {
@@ -1972,16 +1972,16 @@
 	/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
 	if (cflag & CRTSCTS) {
 		dbg("%s Setting to CRTSCTS flow control", __FUNCTION__);
-		if (usb_control_msg(dev, 
+		if (usb_control_msg(dev,
 				    usb_sndctrlpipe(dev, 0),
-				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 				    0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("urb failed to set to rts/cts flow control");
-		}		
-		
-	} else { 
+		}
+
+	} else {
 		/*
 		 * Xon/Xoff code
 		 *
@@ -2011,16 +2011,16 @@
 			/* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
 			/* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
 			dbg("%s Turning off hardware flow control", __FUNCTION__);
-			if (usb_control_msg(dev, 
+			if (usb_control_msg(dev,
 					    usb_sndctrlpipe(dev, 0),
-					    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    0, priv->interface, 
+					    0, priv->interface,
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to clear flow control");
-			}				
+			}
 		}
-		
+
 	}
 	return;
 } /* ftdi_termios */
@@ -2036,11 +2036,11 @@
 	switch (priv->chip_type) {
 	case SIO:
 		/* Request the status from the device */
-		if ((ret = usb_control_msg(port->serial->dev, 
+		if ((ret = usb_control_msg(port->serial->dev,
 					   usb_rcvctrlpipe(port->serial->dev, 0),
-					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+					   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, 0, 
+					   0, 0,
 					   buf, 1, WDR_TIMEOUT)) < 0 ) {
 			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
 			    ret);
@@ -2052,11 +2052,11 @@
 	case FT2232C:
 		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
 		   format as the data returned from the in point */
-		if ((ret = usb_control_msg(port->serial->dev, 
+		if ((ret = usb_control_msg(port->serial->dev,
 					   usb_rcvctrlpipe(port->serial->dev, 0),
-					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+					   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, priv->interface, 
+					   0, priv->interface,
 					   buf, 2, WDR_TIMEOUT)) < 0 ) {
 			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
 			    ret);
@@ -2067,12 +2067,12 @@
 		return -EFAULT;
 		break;
 	}
-	
+
 	return  (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
 		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
 		(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
 		(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
-		priv->last_dtr_rts;			
+		priv->last_dtr_rts;
 }
 
 static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
@@ -2138,11 +2138,11 @@
 		break;
 	default:
 		break;
-		
+
 	}
 
 
-	/* This is not necessarily an error - turns out the higher layers will do 
+	/* This is not necessarily an error - turns out the higher layers will do
 	 *  some ioctls itself (see comment above)
 	 */
 	dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd);
@@ -2199,7 +2199,7 @@
 	if (retval)
 		goto failed_sio_register;
 	retval = usb_register(&ftdi_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 
 	info(DRIVER_VERSION ":" DRIVER_DESC);
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 4b1196a..4543152 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1031,7 +1031,7 @@
 }
 
 
-static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void garmin_write_bulk_callback (struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -1274,7 +1274,7 @@
 }
 
 
-static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void garmin_read_bulk_callback (struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -1330,7 +1330,7 @@
 }
 
 
-static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void garmin_read_int_callback (struct urb *urb)
 {
 	unsigned long flags;
 	int status;
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 21cbaa0..3604293 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -248,7 +248,7 @@
 	return (chars);
 }
 
-void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+void usb_serial_generic_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = port->serial;
@@ -287,7 +287,7 @@
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
-void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+void usb_serial_generic_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index c49976c..91bd301 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -216,10 +216,10 @@
 /* local function prototypes */
 
 /* function prototypes for all URB callbacks */
-static void edge_interrupt_callback	(struct urb *urb, struct pt_regs *regs);
-static void edge_bulk_in_callback	(struct urb *urb, struct pt_regs *regs);
-static void edge_bulk_out_data_callback	(struct urb *urb, struct pt_regs *regs);
-static void edge_bulk_out_cmd_callback	(struct urb *urb, struct pt_regs *regs);
+static void edge_interrupt_callback	(struct urb *urb);
+static void edge_bulk_in_callback	(struct urb *urb);
+static void edge_bulk_out_data_callback	(struct urb *urb);
+static void edge_bulk_out_cmd_callback	(struct urb *urb);
 
 /* function prototypes for the usbserial callbacks */
 static int  edge_open			(struct usb_serial_port *port, struct file *filp);
@@ -534,7 +534,7 @@
  *	this is the callback function for when we have received data on the 
  *	interrupt endpoint.
  *****************************************************************************/
-static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_interrupt_callback (struct urb *urb)
 {
 	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;
 	struct edgeport_port *edge_port;
@@ -631,7 +631,7 @@
  *	this is the callback function for when we have received data on the 
  *	bulk in endpoint.
  *****************************************************************************/
-static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_bulk_in_callback (struct urb *urb)
 {
 	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;
 	unsigned char		*data = urb->transfer_buffer;
@@ -687,7 +687,7 @@
  *	this is the callback function for when we have finished sending serial data
  *	on the bulk out endpoint.
  *****************************************************************************/
-static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_bulk_out_data_callback (struct urb *urb)
 {
 	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
 	struct tty_struct *tty;
@@ -718,7 +718,7 @@
  *	this is the callback function for when we have finished sending a command
  *	on the bulk out endpoint.
  *****************************************************************************/
-static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_bulk_out_cmd_callback (struct urb *urb)
 {
 	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
 	struct tty_struct *tty;
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 17c5b1d..ee0c921 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1697,7 +1697,7 @@
 }
 
 
-static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_interrupt_callback (struct urb *urb)
 {
 	struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
 	struct usb_serial_port *port;
@@ -1787,7 +1787,7 @@
 			 __FUNCTION__, status);
 }
 
-static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_bulk_in_callback (struct urb *urb)
 {
 	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -1879,7 +1879,7 @@
 	tty_flip_buffer_push(tty);
 }
 
-static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs)
+static void edge_bulk_out_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index cbc725a..6238aff 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -83,8 +83,8 @@
 static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
 			   int count);
 static void ipaq_write_gather(struct usb_serial_port *port);
-static void ipaq_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs);
+static void ipaq_read_bulk_callback (struct urb *urb);
+static void ipaq_write_bulk_callback(struct urb *urb);
 static int ipaq_write_room(struct usb_serial_port *port);
 static int ipaq_chars_in_buffer(struct usb_serial_port *port);
 static void ipaq_destroy_lists(struct usb_serial_port *port);
@@ -721,7 +721,7 @@
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
 }
 
-static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void ipaq_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
 	struct tty_struct	*tty;
@@ -859,7 +859,7 @@
 	return;
 }
 
-static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void ipaq_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 812bc21..2a4bb66 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -161,7 +161,7 @@
 
 static int debug;
 
-static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void ipw_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -367,7 +367,7 @@
 	usb_kill_urb(port->write_urb);
 }
 
-static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void ipw_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 1b348df..331bf81 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -105,8 +105,8 @@
 static int  ir_open (struct usb_serial_port *port, struct file *filep);
 static void ir_close (struct usb_serial_port *port, struct file *filep);
 static int  ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
+static void ir_write_bulk_callback (struct urb *urb);
+static void ir_read_bulk_callback (struct urb *urb);
 static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios);
 
 static u8 ir_baud = 0;
@@ -388,7 +388,7 @@
 	return result;
 }
 
-static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void ir_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 
@@ -410,7 +410,7 @@
 	usb_serial_port_softint(port);
 }
 
-static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void ir_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct tty_struct *tty;
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 015ad6c..53be824 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -412,7 +412,7 @@
 	return count - left;
 }
 
-static void	usa26_indat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa26_indat_callback(struct urb *urb)
 {
 	int			i, err;
 	int			endpoint;
@@ -470,7 +470,7 @@
 }
 
  	/* Outdat handling is common for all devices */
-static void	usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa2x_outdat_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
 	struct keyspan_port_private *p_priv;
@@ -483,13 +483,13 @@
 		usb_serial_port_softint(port);
 }
 
-static void	usa26_inack_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa26_inack_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__); 
 	
 }
 
-static void	usa26_outcont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa26_outcont_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
 	struct keyspan_port_private *p_priv;
@@ -503,7 +503,7 @@
 	}
 }
 
-static void	usa26_instat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa26_instat_callback(struct urb *urb)
 {
 	unsigned char 				*data = urb->transfer_buffer;
 	struct keyspan_usa26_portStatusMessage	*msg;
@@ -565,14 +565,14 @@
 exit: ;
 }
 
-static void	usa26_glocont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa26_glocont_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__);
 	
 }
 
 
-static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
+static void usa28_indat_callback(struct urb *urb)
 {
 	int                     i, err;
 	struct usb_serial_port  *port;
@@ -620,12 +620,12 @@
 	} while (urb->status != -EINPROGRESS);
 }
 
-static void	usa28_inack_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa28_inack_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__);
 }
 
-static void	usa28_outcont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa28_outcont_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
 	struct keyspan_port_private *p_priv;
@@ -639,7 +639,7 @@
 	}
 }
 
-static void	usa28_instat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa28_instat_callback(struct urb *urb)
 {
 	int					err;
 	unsigned char 				*data = urb->transfer_buffer;
@@ -700,13 +700,13 @@
 exit: ;
 }
 
-static void	usa28_glocont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa28_glocont_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__);
 }
 
 
-static void	usa49_glocont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa49_glocont_callback(struct urb *urb)
 {
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
@@ -730,7 +730,7 @@
 
 	/* This is actually called glostat in the Keyspan
 	   doco */
-static void	usa49_instat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa49_instat_callback(struct urb *urb)
 {
 	int					err;
 	unsigned char 				*data = urb->transfer_buffer;
@@ -793,12 +793,12 @@
 exit:	;
 }
 
-static void	usa49_inack_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa49_inack_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__);
 }
 
-static void	usa49_indat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa49_indat_callback(struct urb *urb)
 {
 	int			i, err;
 	int			endpoint;
@@ -851,12 +851,12 @@
 }
 
 /* not used, usa-49 doesn't have per-port control endpoints */
-static void	usa49_outcont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa49_outcont_callback(struct urb *urb)
 {
 	dbg ("%s", __FUNCTION__);
 }
 
-static void	usa90_indat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa90_indat_callback(struct urb *urb)
 {
 	int			i, err;
 	int			endpoint;
@@ -930,7 +930,7 @@
 }
 
 
-static void	usa90_instat_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa90_instat_callback(struct urb *urb)
 {
 	unsigned char 				*data = urb->transfer_buffer;
 	struct keyspan_usa90_portStatusMessage	*msg;
@@ -981,7 +981,7 @@
 	;
 }
 
-static void	usa90_outcont_callback(struct urb *urb, struct pt_regs *regs)
+static void	usa90_outcont_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
 	struct keyspan_port_private *p_priv;
@@ -1277,7 +1277,7 @@
 /* Helper functions used by keyspan_setup_urbs */
 static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
 				      int dir, void *ctx, char *buf, int len,
-				      void (*callback)(struct urb *, struct pt_regs *regs))
+				      void (*callback)(struct urb *))
 {
 	struct urb *urb;
 
@@ -1300,12 +1300,12 @@
 }
 
 static struct callbacks {
-	void	(*instat_callback)(struct urb *, struct pt_regs *regs);
-	void	(*glocont_callback)(struct urb *, struct pt_regs *regs);
-	void	(*indat_callback)(struct urb *, struct pt_regs *regs);
-	void	(*outdat_callback)(struct urb *, struct pt_regs *regs);
-	void	(*inack_callback)(struct urb *, struct pt_regs *regs);
-	void	(*outcont_callback)(struct urb *, struct pt_regs *regs);
+	void	(*instat_callback)(struct urb *);
+	void	(*glocont_callback)(struct urb *);
+	void	(*indat_callback)(struct urb *);
+	void	(*outdat_callback)(struct urb *);
+	void	(*inack_callback)(struct urb *);
+	void	(*outcont_callback)(struct urb *);
 } keyspan_callbacks[] = {
 	{
 		/* msg_usa26 callbacks */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 59e777f..9090051 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -210,7 +210,7 @@
 }
 
 
-static void keyspan_pda_rx_interrupt (struct urb *urb, struct pt_regs *regs)
+static void keyspan_pda_rx_interrupt (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        	struct tty_struct *tty = port->tty;
@@ -601,7 +601,7 @@
 }
 
 
-static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void keyspan_pda_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct keyspan_pda_private *priv;
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 2a2f3e2..17e2056 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -80,11 +80,11 @@
 static int  klsi_105_write	         (struct usb_serial_port *port,
 					  const unsigned char *buf,
 					  int count);
-static void klsi_105_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
+static void klsi_105_write_bulk_callback (struct urb *urb);
 static int  klsi_105_chars_in_buffer     (struct usb_serial_port *port);
 static int  klsi_105_write_room          (struct usb_serial_port *port);
 
-static void klsi_105_read_bulk_callback  (struct urb *urb, struct pt_regs *regs);
+static void klsi_105_read_bulk_callback  (struct urb *urb);
 static void klsi_105_set_termios         (struct usb_serial_port *port,
 					  struct termios * old);
 static int  klsi_105_ioctl	         (struct usb_serial_port *port,
@@ -556,7 +556,7 @@
 	return bytes_sent;	/* that's how much we wrote */
 } /* klsi_105_write */
 
-static void klsi_105_write_bulk_callback ( struct urb *urb, struct pt_regs *regs)
+static void klsi_105_write_bulk_callback ( struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 
@@ -616,7 +616,7 @@
 
 
 
-static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void klsi_105_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index d50dce0..ff03331 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -80,8 +80,8 @@
 static int  kobil_tiocmget(struct usb_serial_port *port, struct file *file);
 static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
 			   unsigned int set, unsigned int clear);
-static void kobil_read_int_callback( struct urb *urb, struct pt_regs *regs );
-static void kobil_write_callback( struct urb *purb, struct pt_regs *regs );
+static void kobil_read_int_callback( struct urb *urb );
+static void kobil_write_callback( struct urb *purb );
 
 
 static struct usb_device_id id_table [] = {
@@ -360,7 +360,7 @@
 }
 
 
-static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
+static void kobil_read_int_callback( struct urb *purb)
 {
 	int result;
 	struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
@@ -405,7 +405,7 @@
 }
 
 
-static void kobil_write_callback( struct urb *purb, struct pt_regs *regs )
+static void kobil_write_callback( struct urb *purb )
 {
 }
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index f4d4305..b7582cc 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -96,7 +96,7 @@
 					  struct file *filp);
 static void mct_u232_close	         (struct usb_serial_port *port,
 					  struct file *filp);
-static void mct_u232_read_int_callback   (struct urb *urb, struct pt_regs *regs);
+static void mct_u232_read_int_callback   (struct urb *urb);
 static void mct_u232_set_termios         (struct usb_serial_port *port,
 					  struct termios * old);
 static int  mct_u232_ioctl	         (struct usb_serial_port *port,
@@ -466,7 +466,7 @@
 } /* mct_u232_close */
 
 
-static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void mct_u232_read_int_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
new file mode 100644
index 0000000..82cd15b
--- /dev/null
+++ b/drivers/usb/serial/mos7720.c
@@ -0,0 +1,1683 @@
+/*
+ * mos7720.c
+ *   Controls the Moschip 7720 usb to dual port serial convertor
+ *
+ * Copyright 2006 Moschip Semiconductor Tech. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * Developed by:
+ * 	VijayaKumar.G.N. <vijaykumar@aspirecom.net>
+ *	AjayKumar <ajay@aspirecom.net>
+ *	Gurudeva.N. <gurudev@aspirecom.net>
+ *
+ * Cleaned up from the original by:
+ *	Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * Originally based on drivers/usb/serial/io_edgeport.c which is:
+ *	Copyright (C) 2000 Inside Out Networks, All rights reserved.
+ *	Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.0.0.4F"
+#define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
+#define DRIVER_DESC "Moschip USB Serial Driver"
+
+/* default urb timeout */
+#define MOS_WDR_TIMEOUT	(HZ * 5)
+
+#define MOS_PORT1	0x0200
+#define MOS_PORT2	0x0300
+#define MOS_VENREG	0x0000
+#define MOS_MAX_PORT	0x02
+#define MOS_WRITE	0x0E
+#define MOS_READ	0x0D
+
+/* Interrupt Rotinue Defines	*/
+#define SERIAL_IIR_RLS	0x06
+#define SERIAL_IIR_RDA	0x04
+#define SERIAL_IIR_CTI	0x0c
+#define SERIAL_IIR_THR	0x02
+#define SERIAL_IIR_MS	0x00
+
+#define NUM_URBS			16	/* URB Count */
+#define URB_TRANSFER_BUFFER_SIZE	32	/* URB Size */
+
+/* This structure holds all of the local port information */
+struct moschip_port
+{
+	__u8	shadowLCR;		/* last LCR value received */
+	__u8	shadowMCR;		/* last MCR value received */
+	__u8	shadowMSR;		/* last MSR value received */
+	char			open;
+	struct async_icount	icount;
+	struct usb_serial_port	*port;	/* loop back to the owner */
+	struct urb		*write_urb_pool[NUM_URBS];
+};
+
+/* This structure holds all of the individual serial device information */
+struct moschip_serial
+{
+	int interrupt_started;
+};
+
+static int debug;
+
+#define USB_VENDOR_ID_MOSCHIP		0x9710
+#define MOSCHIP_DEVICE_ID_7720		0x7720
+#define MOSCHIP_DEVICE_ID_7715		0x7715
+
+static struct usb_device_id moschip_port_id_table [] = {
+	{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) },
+	{ } /* terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
+
+
+/*
+ * mos7720_interrupt_callback
+ *	this is the callback function for when we have received data on the
+ *	interrupt endpoint.
+ */
+static void mos7720_interrupt_callback(struct urb *urb)
+{
+	int result;
+	int length;
+	__u32 *data;
+	unsigned int status;
+	__u8 sp1;
+	__u8 sp2;
+	__u8 st;
+
+	dbg("%s"," : Entering\n");
+
+	if (!urb) {
+		dbg("%s","Invalid Pointer !!!!:\n");
+		return;
+	}
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+		    urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+		    urb->status);
+		goto exit;
+	}
+
+	length = urb->actual_length;
+	data = urb->transfer_buffer;
+
+	/* Moschip get 4 bytes
+	 * Byte 1 IIR Port 1 (port.number is 0)
+	 * Byte 2 IIR Port 2 (port.number is 1)
+	 * Byte 3 --------------
+	 * Byte 4 FIFO status for both */
+	if (length && length > 4) {
+		dbg("Wrong data !!!");
+		return;
+	}
+
+	status = *data;
+
+	sp1 = (status & 0xff000000)>>24;
+	sp2 = (status & 0x00ff0000)>>16;
+	st = status & 0x000000ff;
+
+	if ((sp1 & 0x01) || (sp2 & 0x01)) {
+		/* No Interrupt Pending in both the ports */
+		dbg("No Interrupt !!!");
+	} else {
+		switch (sp1 & 0x0f) {
+		case SERIAL_IIR_RLS:
+			dbg("Serial Port 1: Receiver status error or address "
+			    "bit detected in 9-bit mode\n");
+			break;
+		case SERIAL_IIR_CTI:
+			dbg("Serial Port 1: Receiver time out");
+			break;
+		case SERIAL_IIR_MS:
+			dbg("Serial Port 1: Modem status change");
+			break;
+		}
+
+		switch (sp2 & 0x0f) {
+		case SERIAL_IIR_RLS:
+			dbg("Serial Port 2: Receiver status error or address "
+			    "bit detected in 9-bit mode");
+			break;
+		case SERIAL_IIR_CTI:
+			dbg("Serial Port 2: Receiver time out");
+			break;
+		case SERIAL_IIR_MS:
+			dbg("Serial Port 2: Modem status change");
+			break;
+		}
+	}
+
+exit:
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting control urb\n",
+			__FUNCTION__, result);
+	return;
+}
+
+/*
+ * mos7720_bulk_in_callback
+ *	this is the callback function for when we have received data on the
+ *	bulk in endpoint.
+ */
+static void mos7720_bulk_in_callback(struct urb *urb)
+{
+	int status;
+	unsigned char *data ;
+	struct usb_serial_port *port;
+	struct moschip_port *mos7720_port;
+	struct tty_struct *tty;
+
+	if (urb->status) {
+		dbg("nonzero read bulk status received: %d",urb->status);
+		return;
+	}
+
+	mos7720_port = urb->context;
+	if (!mos7720_port) {
+		dbg("%s","NULL mos7720_port pointer \n");
+		return ;
+	}
+
+	port = mos7720_port->port;
+
+	dbg("Entering...%s", __FUNCTION__);
+
+	data = urb->transfer_buffer;
+
+	tty = port->tty;
+	if (tty && urb->actual_length) {
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
+		tty_flip_buffer_push(tty);
+	}
+
+	if (!port->read_urb) {
+		dbg("URB KILLED !!!");
+		return;
+	}
+
+	if (port->read_urb->status != -EINPROGRESS) {
+		port->read_urb->dev = port->serial->dev;
+
+		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (status)
+			dbg("usb_submit_urb(read bulk) failed, status = %d",
+			    status);
+	}
+}
+
+/*
+ * mos7720_bulk_out_data_callback
+ *	this is the callback function for when we have finished sending serial
+ *	data on the bulk out endpoint.
+ */
+static void mos7720_bulk_out_data_callback(struct urb *urb)
+{
+	struct moschip_port *mos7720_port;
+	struct tty_struct *tty;
+
+	if (urb->status) {
+		dbg("nonzero write bulk status received:%d", urb->status);
+		return;
+	}
+
+	mos7720_port = urb->context;
+	if (!mos7720_port) {
+		dbg("NULL mos7720_port pointer");
+		return ;
+	}
+
+	dbg("Entering .........");
+
+	tty = mos7720_port->port->tty;
+
+	if (tty && mos7720_port->open) {
+		/* let the tty driver wakeup if it has a special *
+		 * write_wakeup function */
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		     tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+
+		/* tell the tty driver that something has changed */
+		wake_up_interruptible(&tty->write_wait);
+	}
+
+	/* schedule_work(&mos7720_port->port->work); */
+}
+
+/*
+ * send_mos_cmd
+ *	this function will be used for sending command to device
+ */
+static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
+			__u16 index, void *data)
+{
+	int status;
+	unsigned int pipe;
+	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
+	__u8 requesttype;
+	__u16 size = 0x0000;
+
+	if (value < MOS_MAX_PORT) {
+		if (product == MOSCHIP_DEVICE_ID_7715) {
+			value = value*0x100+0x100;
+		} else {
+			value = value*0x100+0x200;
+		}
+	} else {
+		value = 0x0000;
+		if ((product == MOSCHIP_DEVICE_ID_7715) &&
+		    (index != 0x08)) {
+			dbg("serial->product== MOSCHIP_DEVICE_ID_7715");
+			//index = 0x01 ;
+		}
+	}
+
+	if (request == MOS_WRITE) {
+		request = (__u8)MOS_WRITE;
+		requesttype = (__u8)0x40;
+		value  = value + (__u16)*((unsigned char *)data);
+		data = NULL;
+		pipe = usb_sndctrlpipe(serial->dev, 0);
+	} else {
+		request = (__u8)MOS_READ;
+		requesttype = (__u8)0xC0;
+		size = 0x01;
+		pipe = usb_rcvctrlpipe(serial->dev,0);
+	}
+
+	status = usb_control_msg(serial->dev, pipe, request, requesttype,
+				 value, index, data, size, MOS_WDR_TIMEOUT);
+
+	if (status < 0)
+		dbg("Command Write failed Value %x index %x\n",value,index);
+
+	return status;
+}
+
+static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+{
+	struct usb_serial *serial;
+	struct usb_serial_port *port0;
+	struct urb *urb;
+	struct moschip_serial *mos7720_serial;
+	struct moschip_port *mos7720_port;
+	int response;
+	int port_number;
+	char data;
+	int j;
+
+	serial = port->serial;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL)
+		return -ENODEV;
+
+	port0 = serial->port[0];
+
+	mos7720_serial = usb_get_serial_data(serial);
+
+	if (mos7720_serial == NULL || port0 == NULL)
+		return -ENODEV;
+
+	usb_clear_halt(serial->dev, port->write_urb->pipe);
+	usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+	/* Initialising the write urb pool */
+	for (j = 0; j < NUM_URBS; ++j) {
+		urb = usb_alloc_urb(0,SLAB_ATOMIC);
+		mos7720_port->write_urb_pool[j] = urb;
+
+		if (urb == NULL) {
+			err("No more urbs???");
+			continue;
+		}
+
+		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+					       GFP_KERNEL);
+		if (!urb->transfer_buffer) {
+			err("%s-out of memory for urb buffers.", __FUNCTION__);
+			continue;
+		}
+	}
+
+	 /* Initialize MCS7720 -- Write Init values to corresponding Registers
+	  *
+	  * Register Index
+	  * 1 : IER
+	  * 2 : FCR
+	  * 3 : LCR
+	  * 4 : MCR
+	  *
+	  * 0x08 : SP1/2 Control Reg
+	  */
+	port_number = port->number - port->serial->minor;
+	send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
+	dbg("SS::%p LSR:%x\n",mos7720_port, data);
+
+	dbg("Check:Sending Command ..........");
+
+	data = 0x02;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x01, &data);
+	data = 0x02;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x02, &data);
+
+	data = 0x00;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+	data = 0x00;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
+
+	data = 0xCF;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
+	data = 0x03;
+        mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
+	data = 0x0b;
+        mos7720_port->shadowMCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+	data = 0x0b;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+
+	data = 0x00;
+	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
+	data = 0x00;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
+
+/*	data = 0x00;
+	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, port_number + 1, &data);
+	data = 0x03;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
+	data = 0x00;
+	send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
+*/
+	data = 0x00;
+	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
+
+	data = data | (port->number - port->serial->minor + 1);
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
+
+	data = 0x83;
+        mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
+	data = 0x0c;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
+	data = 0x00;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+	data = 0x03;
+        mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
+	data = 0x0c;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+	data = 0x0c;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+
+//Matrix
+
+	/* force low_latency on so that our tty_push actually forces *
+	 * the data through,otherwise it is scheduled, and with      *
+	 * high data rates (like with OHCI) data can get lost.       */
+
+	if (port->tty)
+		port->tty->low_latency = 1;
+
+	/* see if we've set up our endpoint info yet   *
+	 * (can't set it up in mos7720_startup as the  *
+	 * structures were not set up at that time.)   */
+	if (!mos7720_serial->interrupt_started) {
+		dbg("Interrupt buffer NULL !!!");
+
+		/* not set up yet, so do it now */
+		mos7720_serial->interrupt_started = 1;
+
+		dbg("To Submit URB !!!");
+
+		/* set up our interrupt urb */
+		usb_fill_int_urb(port0->interrupt_in_urb, serial->dev,
+				 usb_rcvintpipe(serial->dev,
+				 		port->interrupt_in_endpointAddress),
+				 port0->interrupt_in_buffer,
+				 port0->interrupt_in_urb->transfer_buffer_length,
+				 mos7720_interrupt_callback, mos7720_port,
+				 port0->interrupt_in_urb->interval);
+
+		/* start interrupt read for this mos7720 this interrupt *
+	         * will continue as long as the mos7720 is connected    */
+		dbg("Submit URB over !!!");
+		response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL);
+		if (response)
+			dev_err(&port->dev,
+				"%s - Error %d submitting control urb",
+				__FUNCTION__, response);
+	}
+
+	/* set up our bulk in urb */
+	usb_fill_bulk_urb(port->read_urb, serial->dev,
+			  usb_rcvbulkpipe(serial->dev,
+			  		  port->bulk_in_endpointAddress),
+			  port->bulk_in_buffer,
+			  port->read_urb->transfer_buffer_length,
+			  mos7720_bulk_in_callback, mos7720_port);
+	response = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (response)
+		dev_err(&port->dev,
+			"%s - Error %d submitting read urb", __FUNCTION__, response);
+
+	/* initialize our icount structure */
+	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
+
+	/* initialize our port settings */
+	mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
+
+	/* send a open port command */
+	mos7720_port->open = 1;
+
+	return 0;
+}
+
+/*
+ * mos7720_chars_in_buffer
+ *	this function is called by the tty driver when it wants to know how many
+ *	bytes of data we currently have outstanding in the port (data that has
+ *	been written, but hasn't made it out the port yet)
+ *	If successful, we return the number of bytes left to be written in the
+ *	system,
+ *	Otherwise we return a negative error number.
+ */
+static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+{
+	int i;
+	int chars = 0;
+	struct moschip_port *mos7720_port;
+
+	dbg("%s:entering ...........", __FUNCTION__);
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL) {
+		dbg("%s:leaving ...........", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+			chars += URB_TRANSFER_BUFFER_SIZE;
+	}
+	dbg("%s - returns %d", __FUNCTION__, chars);
+	return chars;
+}
+
+static void mos7720_close(struct usb_serial_port *port, struct file *filp)
+{
+	struct usb_serial *serial;
+	struct moschip_port *mos7720_port;
+	char data;
+	int j;
+
+	dbg("mos7720_close:entering...");
+
+	serial = port->serial;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL)
+		return;
+
+	for (j = 0; j < NUM_URBS; ++j)
+		usb_kill_urb(mos7720_port->write_urb_pool[j]);
+
+	/* Freeing Write URBs */
+	for (j = 0; j < NUM_URBS; ++j) {
+		if (mos7720_port->write_urb_pool[j]) {
+			kfree(mos7720_port->write_urb_pool[j]->transfer_buffer);
+			usb_free_urb(mos7720_port->write_urb_pool[j]);
+		}
+	}
+
+	/* While closing port, shutdown all bulk read, write  *
+	 * and interrupt read if they exists                  */
+	if (serial->dev) {
+		dbg("Shutdown bulk write");
+		usb_kill_urb(port->write_urb);
+		dbg("Shutdown bulk read");
+		usb_kill_urb(port->read_urb);
+	}
+
+	data = 0x00;
+	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+		     0x04, &data);
+
+	data = 0x00;
+	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+		     0x01, &data);
+
+	mos7720_port->open = 0;
+
+	dbg("Leaving %s", __FUNCTION__);
+}
+
+static void mos7720_break(struct usb_serial_port *port, int break_state)
+{
+        unsigned char data;
+	struct usb_serial *serial;
+	struct moschip_port *mos7720_port;
+
+	dbg("Entering %s", __FUNCTION__);
+
+	serial = port->serial;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL)
+		return;
+
+	if (break_state == -1)
+		data = mos7720_port->shadowLCR | UART_LCR_SBC;
+	else
+		data = mos7720_port->shadowLCR & ~UART_LCR_SBC;
+
+	mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+		     0x03, &data);
+
+	return;
+}
+
+/*
+ * mos7720_write_room
+ *	this function is called by the tty driver when it wants to know how many
+ *	bytes of data we can accept for a specific port.
+ *	If successful, we return the amount of room that we have for this port
+ *	Otherwise we return a negative error number.
+ */
+static int mos7720_write_room(struct usb_serial_port *port)
+{
+	struct moschip_port *mos7720_port;
+	int room = 0;
+	int i;
+
+	dbg("%s:entering ...........", __FUNCTION__);
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL) {
+		dbg("%s:leaving ...........", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+			room += URB_TRANSFER_BUFFER_SIZE;
+	}
+
+	dbg("%s - returns %d", __FUNCTION__, room);
+	return room;
+}
+
+static int mos7720_write(struct usb_serial_port *port,
+			 const unsigned char *data, int count)
+{
+	int status;
+	int i;
+	int bytes_sent = 0;
+	int transfer_size;
+
+	struct moschip_port *mos7720_port;
+	struct usb_serial *serial;
+	struct urb    *urb;
+	const unsigned char *current_position = data;
+
+	dbg("%s:entering ...........", __FUNCTION__);
+
+	serial = port->serial;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL) {
+		dbg("mos7720_port is NULL");
+		return -ENODEV;
+	}
+
+	/* try to find a free urb in the list */
+	urb = NULL;
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
+			urb = mos7720_port->write_urb_pool[i];
+			dbg("URB:%d",i);
+			break;
+		}
+	}
+
+	if (urb == NULL) {
+		dbg("%s - no more free urbs", __FUNCTION__);
+		goto exit;
+	}
+
+	if (urb->transfer_buffer == NULL) {
+		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+					       GFP_KERNEL);
+		if (urb->transfer_buffer == NULL) {
+			err("%s no more kernel memory...", __FUNCTION__);
+			goto exit;
+		}
+	}
+	transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+
+	memcpy(urb->transfer_buffer, current_position, transfer_size);
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size,
+			      urb->transfer_buffer);
+
+	/* fill urb with data and submit  */
+	usb_fill_bulk_urb(urb, serial->dev,
+			  usb_sndbulkpipe(serial->dev,
+			  		  port->bulk_out_endpointAddress),
+			  urb->transfer_buffer, transfer_size,
+			  mos7720_bulk_out_data_callback, mos7720_port);
+
+	/* send it down the pipe */
+	status = usb_submit_urb(urb,GFP_ATOMIC);
+	if (status) {
+		err("%s - usb_submit_urb(write bulk) failed with status = %d",
+		    __FUNCTION__, status);
+		bytes_sent = status;
+		goto exit;
+	}
+	bytes_sent = transfer_size;
+
+exit:
+	return bytes_sent;
+}
+
+static void mos7720_throttle(struct usb_serial_port *port)
+{
+	struct moschip_port *mos7720_port;
+	struct tty_struct *tty;
+	int status;
+
+	dbg("%s- port %d\n", __FUNCTION__, port->number);
+
+	mos7720_port = usb_get_serial_port_data(port);
+
+	if (mos7720_port == NULL)
+		return;
+
+	if (!mos7720_port->open) {
+		dbg("port not opened");
+		return;
+	}
+
+	dbg("%s: Entering ..........", __FUNCTION__);
+
+	tty = port->tty;
+	if (!tty) {
+		dbg("%s - no tty available", __FUNCTION__);
+		return;
+	}
+
+	/* if we are implementing XON/XOFF, send the stop character */
+	if (I_IXOFF(tty)) {
+		unsigned char stop_char = STOP_CHAR(tty);
+		status = mos7720_write(port, &stop_char, 1);
+		if (status <= 0)
+			return;
+	}
+
+	/* if we are implementing RTS/CTS, toggle that line */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		mos7720_port->shadowMCR &= ~UART_MCR_RTS;
+		status = send_mos_cmd(port->serial, MOS_WRITE,
+				      port->number - port->serial->minor,
+				      UART_MCR, &mos7720_port->shadowMCR);
+		if (status != 0)
+			return;
+	}
+}
+
+static void mos7720_unthrottle(struct usb_serial_port *port)
+{
+	struct tty_struct *tty;
+	int status;
+	struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
+
+	if (mos7720_port == NULL)
+		return;
+
+	if (!mos7720_port->open) {
+		dbg("%s - port not opened", __FUNCTION__);
+		return;
+	}
+
+	dbg("%s: Entering ..........", __FUNCTION__);
+
+	tty = port->tty;
+	if (!tty) {
+		dbg("%s - no tty available", __FUNCTION__);
+		return;
+	}
+
+	/* if we are implementing XON/XOFF, send the start character */
+	if (I_IXOFF(tty)) {
+		unsigned char start_char = START_CHAR(tty);
+		status = mos7720_write(port, &start_char, 1);
+		if (status <= 0)
+			return;
+	}
+
+	/* if we are implementing RTS/CTS, toggle that line */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		mos7720_port->shadowMCR |= UART_MCR_RTS;
+		status = send_mos_cmd(port->serial, MOS_WRITE,
+				      port->number - port->serial->minor,
+				      UART_MCR, &mos7720_port->shadowMCR);
+		if (status != 0)
+			return;
+	}
+}
+
+static int set_higher_rates(struct moschip_port *mos7720_port,
+			    unsigned int baud)
+{
+	unsigned char data;
+	struct usb_serial_port *port;
+	struct usb_serial *serial;
+	int port_number;
+
+	if (mos7720_port == NULL)
+		return -EINVAL;
+
+	port = mos7720_port->port;
+	serial = port->serial;
+
+        /***********************************************
+         *      Init Sequence for higher rates
+         ***********************************************/
+	dbg("Sending Setting Commands ..........");
+	port_number = port->number - port->serial->minor;
+
+	data = 0x000;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+	data = 0x000;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
+	data = 0x0CF;
+	send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data);
+	data = 0x00b;
+        mos7720_port->shadowMCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+	data = 0x00b;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+
+	data = 0x000;
+	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
+	data = 0x000;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
+
+
+        /***********************************************
+         *              Set for higher rates           *
+         ***********************************************/
+
+	data = baud * 0x10;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data);
+
+	data = 0x003;
+	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
+	data = 0x003;
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
+
+	data = 0x02b;
+        mos7720_port->shadowMCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+	data = 0x02b;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+
+        /***********************************************
+         *              Set DLL/DLM
+         ***********************************************/
+
+	data = mos7720_port->shadowLCR | UART_LCR_DLAB;
+        mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
+
+	data =  0x001; /* DLL */
+        send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
+	data =  0x000; /* DLM */
+        send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+
+	data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
+        mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
+
+	return 0;
+}
+
+/* baud rate information */
+struct divisor_table_entry
+{
+	__u32  baudrate;
+	__u16  divisor;
+};
+
+/* Define table of divisors for moschip 7720 hardware	   *
+ * These assume a 3.6864MHz crystal, the standard /16, and *
+ * MCR.7 = 0.						   */
+static struct divisor_table_entry divisor_table[] = {
+	{   50,		2304},
+	{   110,	1047},	/* 2094.545455 => 230450   => .0217 % over */
+	{   134,	857},	/* 1713.011152 => 230398.5 => .00065% under */
+	{   150,	768},
+	{   300,	384},
+	{   600,	192},
+	{   1200,	96},
+	{   1800,	64},
+	{   2400,	48},
+	{   4800,	24},
+	{   7200,	16},
+	{   9600,	12},
+	{   19200,	6},
+	{   38400,	3},
+	{   57600,	2},
+	{   115200,	1},
+};
+
+/*****************************************************************************
+ * calc_baud_rate_divisor
+ *	this function calculates the proper baud rate divisor for the specified
+ *	baud rate.
+ *****************************************************************************/
+static int calc_baud_rate_divisor(int baudrate, int *divisor)
+{
+	int i;
+	__u16 custom;
+	__u16 round1;
+	__u16 round;
+
+
+	dbg("%s - %d", __FUNCTION__, baudrate);
+
+	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
+		if (divisor_table[i].baudrate == baudrate) {
+			*divisor = divisor_table[i].divisor;
+			return 0;
+		}
+	}
+
+        /* After trying for all the standard baud rates    *
+         * Try calculating the divisor for this baud rate  */
+	if (baudrate > 75 &&  baudrate < 230400) {
+		/* get the divisor */
+		custom = (__u16)(230400L  / baudrate);
+
+		/* Check for round off */
+		round1 = (__u16)(2304000L / baudrate);
+		round = (__u16)(round1 - (custom * 10));
+		if (round > 4)
+			custom++;
+		*divisor = custom;
+
+		dbg("Baud %d = %d",baudrate, custom);
+		return 0;
+	}
+
+	dbg("Baud calculation Failed...");
+	return -EINVAL;
+}
+
+/*
+ * send_cmd_write_baud_rate
+ *	this function sends the proper command to change the baud rate of the
+ *	specified port.
+ */
+static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
+				    int baudrate)
+{
+	struct usb_serial_port *port;
+	struct usb_serial *serial;
+	int divisor;
+	int status;
+	unsigned char data;
+	unsigned char number;
+
+	if (mos7720_port == NULL)
+		return -1;
+
+	port = mos7720_port->port;
+	serial = port->serial;
+
+	dbg("%s: Entering ..........", __FUNCTION__);
+
+	number = port->number - port->serial->minor;
+	dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate);
+
+        /* Calculate the Divisor */
+	status = calc_baud_rate_divisor(baudrate, &divisor);
+	if (status) {
+		err("%s - bad baud rate", __FUNCTION__);
+		return status;
+	}
+
+        /* Enable access to divisor latch */
+        data = mos7720_port->shadowLCR | UART_LCR_DLAB;
+        mos7720_port->shadowLCR  = data;
+        send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
+
+	/* Write the divisor */
+	data = ((unsigned char)(divisor & 0xff));
+        send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
+
+	data = ((unsigned char)((divisor & 0xff00) >> 8));
+        send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
+
+        /* Disable access to divisor latch */
+        data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
+        mos7720_port->shadowLCR = data;
+        send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
+
+	return status;
+}
+
+/*
+ * change_port_settings
+ *	This routine is called to set the UART on the device to match
+ *      the specified new settings.
+ */
+static void change_port_settings(struct moschip_port *mos7720_port,
+				 struct termios *old_termios)
+{
+	struct usb_serial_port *port;
+	struct usb_serial *serial;
+	struct tty_struct *tty;
+	int baud;
+	unsigned cflag;
+	unsigned iflag;
+	__u8 mask = 0xff;
+	__u8 lData;
+	__u8 lParity;
+	__u8 lStop;
+	int status;
+	int port_number;
+	char data;
+
+	if (mos7720_port == NULL)
+		return ;
+
+	port = mos7720_port->port;
+	serial = port->serial;
+	port_number = port->number - port->serial->minor;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (!mos7720_port->open) {
+		dbg("%s - port not opened", __FUNCTION__);
+		return;
+	}
+
+	tty = mos7720_port->port->tty;
+
+	if ((!tty) || (!tty->termios)) {
+		dbg("%s - no tty structures", __FUNCTION__);
+		return;
+	}
+
+	dbg("%s: Entering ..........", __FUNCTION__);
+
+	lData = UART_LCR_WLEN8;
+	lStop = 0x00;	/* 1 stop bit */
+	lParity = 0x00;	/* No parity */
+
+	cflag = tty->termios->c_cflag;
+	iflag = tty->termios->c_iflag;
+
+	/* Change the number of bits */
+	switch (cflag & CSIZE) {
+	case CS5:
+		lData = UART_LCR_WLEN5;
+		mask = 0x1f;
+		break;
+
+	case CS6:
+		lData = UART_LCR_WLEN6;
+		mask = 0x3f;
+		break;
+
+	case CS7:
+		lData = UART_LCR_WLEN7;
+		mask = 0x7f;
+		break;
+	default:
+	case CS8:
+		lData = UART_LCR_WLEN8;
+		break;
+	}
+
+	/* Change the Parity bit */
+	if (cflag & PARENB) {
+		if (cflag & PARODD) {
+			lParity = UART_LCR_PARITY;
+			dbg("%s - parity = odd", __FUNCTION__);
+		} else {
+			lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
+			dbg("%s - parity = even", __FUNCTION__);
+		}
+
+	} else {
+		dbg("%s - parity = none", __FUNCTION__);
+	}
+
+	if (cflag & CMSPAR)
+		lParity = lParity | 0x20;
+
+	/* Change the Stop bit */
+	if (cflag & CSTOPB) {
+		lStop = UART_LCR_STOP;
+		dbg("%s - stop bits = 2", __FUNCTION__);
+	} else {
+		lStop = 0x00;
+		dbg("%s - stop bits = 1", __FUNCTION__);
+	}
+
+#define LCR_BITS_MASK		0x03	/* Mask for bits/char field */
+#define LCR_STOP_MASK		0x04	/* Mask for stop bits field */
+#define LCR_PAR_MASK		0x38	/* Mask for parity field */
+
+	/* Update the LCR with the correct value */
+	mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+	mos7720_port->shadowLCR |= (lData | lParity | lStop);
+
+
+	/* Disable Interrupts */
+	data = 0x00;
+        send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data);
+
+	data = 0x00;
+        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+
+	data = 0xcf;
+        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+
+	/* Send the updated LCR value to the mos7720 */
+	data = mos7720_port->shadowLCR;
+        send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
+
+        data = 0x00b;
+        mos7720_port->shadowMCR = data;
+        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+        data = 0x00b;
+        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+
+	/* set up the MCR register and send it to the mos7720 */
+	mos7720_port->shadowMCR = UART_MCR_OUT2;
+	if (cflag & CBAUD)
+		mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS);
+
+	if (cflag & CRTSCTS) {
+		mos7720_port->shadowMCR |= (UART_MCR_XONANY);
+
+                /* To set hardware flow control to the specified *
+                 * serial port, in SP1/2_CONTROL_REG             */
+		if (port->number) {
+			data = 0x001;
+			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
+				     0x08, &data);
+		} else {
+			data = 0x002;
+			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
+				     0x08, &data);
+		}
+	} else {
+		mos7720_port->shadowMCR &= ~(UART_MCR_XONANY);
+	}
+
+	data = mos7720_port->shadowMCR;
+	send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data);
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(tty);
+	if (!baud) {
+		/* pick a default, any default... */
+		dbg("Picked default baud...");
+		baud = 9600;
+	}
+
+	if (baud >= 230400) {
+		set_higher_rates(mos7720_port, baud);
+		/* Enable Interrupts */
+		data = 0x0c;
+		send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);
+		return;
+	}
+
+	dbg("%s - baud rate = %d", __FUNCTION__, baud);
+	status = send_cmd_write_baud_rate(mos7720_port, baud);
+
+	/* Enable Interrupts */
+	data = 0x0c;
+	send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);
+
+	if (port->read_urb->status != -EINPROGRESS) {
+		port->read_urb->dev = serial->dev;
+
+		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (status)
+			dbg("usb_submit_urb(read bulk) failed, status = %d",
+			    status);
+	}
+	return;
+}
+
+/*
+ * mos7720_set_termios
+ *	this function is called by the tty driver when it wants to change the
+ *	termios structure.
+ */
+static void mos7720_set_termios(struct usb_serial_port *port,
+				struct termios *old_termios)
+{
+	int status;
+	unsigned int cflag;
+	struct usb_serial *serial;
+	struct moschip_port *mos7720_port;
+	struct tty_struct *tty;
+
+	serial = port->serial;
+
+	mos7720_port = usb_get_serial_port_data(port);
+
+	if (mos7720_port == NULL)
+		return;
+
+	tty = port->tty;
+
+	if (!port->tty || !port->tty->termios) {
+		dbg("%s - no tty or termios", __FUNCTION__);
+		return;
+	}
+
+	if (!mos7720_port->open) {
+		dbg("%s - port not opened", __FUNCTION__);
+		return;
+	}
+
+	dbg("%s\n","setting termios - ASPIRE");
+
+	cflag = tty->termios->c_cflag;
+
+	if (!cflag) {
+		printk("%s %s\n",__FUNCTION__,"cflag is NULL");
+		return;
+	}
+
+	/* check that they really want us to change something */
+	if (old_termios) {
+		if ((cflag == old_termios->c_cflag) &&
+		    (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+		     RELEVANT_IFLAG(old_termios->c_iflag))) {
+			dbg("Nothing to change");
+			return;
+		}
+	}
+
+	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+	    tty->termios->c_cflag,
+	    RELEVANT_IFLAG(tty->termios->c_iflag));
+
+	if (old_termios)
+		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+		    old_termios->c_cflag,
+		    RELEVANT_IFLAG(old_termios->c_iflag));
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* change the port settings to the new ones specified */
+	change_port_settings(mos7720_port, old_termios);
+
+	if(!port->read_urb) {
+		dbg("%s","URB KILLED !!!!!\n");
+		return;
+	}
+
+	if(port->read_urb->status != -EINPROGRESS) {
+		port->read_urb->dev = serial->dev;
+		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (status)
+			dbg("usb_submit_urb(read bulk) failed, status = %d",
+			    status);
+	}
+	return;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct moschip_port *mos7720_port,
+			unsigned int __user *value)
+{
+	int count;
+	unsigned int result = 0;
+
+	count = mos7720_chars_in_buffer(mos7720_port->port);
+	if (count == 0) {
+		dbg("%s -- Empty", __FUNCTION__);
+		result = TIOCSER_TEMT;
+	}
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * get_number_bytes_avail - get number of bytes available
+ *
+ * Purpose: Let user call ioctl to get the count of number of bytes available.
+ */
+static int get_number_bytes_avail(struct moschip_port *mos7720_port,
+				  unsigned int __user *value)
+{
+	unsigned int result = 0;
+	struct tty_struct *tty = mos7720_port->port->tty;
+
+	if (!tty)
+		return -ENOIOCTLCMD;
+
+	result = tty->read_cnt;
+
+	dbg("%s(%d) = %d", __FUNCTION__,  mos7720_port->port->number, result);
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+
+	return -ENOIOCTLCMD;
+}
+
+static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
+			  unsigned int __user *value)
+{
+	unsigned int mcr ;
+	unsigned int arg;
+	unsigned char data;
+
+	struct usb_serial_port *port;
+
+	if (mos7720_port == NULL)
+		return -1;
+
+	port = (struct usb_serial_port*)mos7720_port->port;
+	mcr = mos7720_port->shadowMCR;
+
+	if (copy_from_user(&arg, value, sizeof(int)))
+		return -EFAULT;
+
+	switch (cmd) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS)
+			mcr |= UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			mcr |= UART_MCR_RTS;
+		if (arg & TIOCM_LOOP)
+			mcr |= UART_MCR_LOOP;
+		break;
+
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			mcr &= ~UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			mcr &= ~UART_MCR_RTS;
+		if (arg & TIOCM_LOOP)
+			mcr &= ~UART_MCR_LOOP;
+		break;
+
+	case TIOCMSET:
+		/* turn off the RTS and DTR and LOOPBACK
+		 * and then only turn on what was asked to */
+		mcr &=  ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_LOOP);
+		mcr |= ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0);
+		mcr |= ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);
+		mcr |= ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0);
+		break;
+	}
+
+	mos7720_port->shadowMCR = mcr;
+
+	data = mos7720_port->shadowMCR;
+	send_mos_cmd(port->serial, MOS_WRITE,
+		     port->number - port->serial->minor, UART_MCR, &data);
+
+	return 0;
+}
+
+static int get_modem_info(struct moschip_port *mos7720_port,
+			  unsigned int __user *value)
+{
+	unsigned int result = 0;
+	unsigned int msr = mos7720_port->shadowMSR;
+	unsigned int mcr = mos7720_port->shadowMCR;
+
+	result = ((mcr & UART_MCR_DTR)	? TIOCM_DTR: 0)	  /* 0x002 */
+		  | ((mcr & UART_MCR_RTS)	? TIOCM_RTS: 0)   /* 0x004 */
+		  | ((msr & UART_MSR_CTS)	? TIOCM_CTS: 0)   /* 0x020 */
+		  | ((msr & UART_MSR_DCD)	? TIOCM_CAR: 0)   /* 0x040 */
+		  | ((msr & UART_MSR_RI)	? TIOCM_RI:  0)   /* 0x080 */
+		  | ((msr & UART_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */
+
+
+	dbg("%s -- %x", __FUNCTION__, result);
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+static int get_serial_info(struct moschip_port *mos7720_port,
+			   struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	tmp.type		= PORT_16550A;
+	tmp.line		= mos7720_port->port->serial->minor;
+	tmp.port		= mos7720_port->port->number;
+	tmp.irq			= 0;
+	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+        tmp.xmit_fifo_size	= NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
+	tmp.baud_base		= 9600;
+	tmp.close_delay		= 5*HZ;
+	tmp.closing_wait	= 30*HZ;
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	struct moschip_port *mos7720_port;
+	struct async_icount cnow;
+	struct async_icount cprev;
+	struct serial_icounter_struct icount;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	if (mos7720_port == NULL)
+		return -ENODEV;
+
+	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+
+	switch (cmd) {
+	case TIOCINQ:
+		/* return number of bytes available */
+		dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
+		return get_number_bytes_avail(mos7720_port,
+					      (unsigned int __user *)arg);
+		break;
+
+	case TIOCSERGETLSR:
+		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
+		return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
+		return 0;
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+		    port->number);
+		return set_modem_info(mos7720_port, cmd,
+				      (unsigned int __user *)arg);
+
+	case TIOCMGET:
+		dbg("%s (%d) TIOCMGET", __FUNCTION__,  port->number);
+		return get_modem_info(mos7720_port,
+				      (unsigned int __user *)arg);
+
+	case TIOCGSERIAL:
+		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
+		return get_serial_info(mos7720_port,
+				       (struct serial_struct __user *)arg);
+
+	case TIOCSSERIAL:
+		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
+		break;
+
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
+		cprev = mos7720_port->icount;
+		while (1) {
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			cnow = mos7720_port->icount;
+			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+				return -EIO; /* no change => error */
+			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+				return 0;
+			}
+			cprev = cnow;
+		}
+		/* NOTREACHED */
+		break;
+
+	case TIOCGICOUNT:
+		cnow = mos7720_port->icount;
+		icount.cts = cnow.cts;
+		icount.dsr = cnow.dsr;
+		icount.rng = cnow.rng;
+		icount.dcd = cnow.dcd;
+		icount.rx = cnow.rx;
+		icount.tx = cnow.tx;
+		icount.frame = cnow.frame;
+		icount.overrun = cnow.overrun;
+		icount.parity = cnow.parity;
+		icount.brk = cnow.brk;
+		icount.buf_overrun = cnow.buf_overrun;
+
+		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+		    port->number, icount.rx, icount.tx );
+		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
+			return -EFAULT;
+		return 0;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int mos7720_startup(struct usb_serial *serial)
+{
+	struct moschip_serial *mos7720_serial;
+	struct moschip_port *mos7720_port;
+	struct usb_device *dev;
+	int i;
+	char data;
+
+	dbg("%s: Entering ..........", __FUNCTION__);
+
+	if (!serial) {
+		dbg("Invalid Handler");
+		return -ENODEV;
+	}
+
+	dev = serial->dev;
+
+	/* create our private serial structure */
+	mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);
+	if (mos7720_serial == NULL) {
+		err("%s - Out of memory", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	usb_set_serial_data(serial, mos7720_serial);
+
+	/* we set up the pointers to the endpoints in the mos7720_open *
+	 * function, as the structures aren't created yet.             */
+
+	/* set up port private structures */
+	for (i = 0; i < serial->num_ports; ++i) {
+		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+		if (mos7720_port == NULL) {
+			err("%s - Out of memory", __FUNCTION__);
+			usb_set_serial_data(serial, NULL);
+			kfree(mos7720_serial);
+			return -ENOMEM;
+		}
+
+		/* Initialize all port interrupt end point to port 0 int
+		 * endpoint.  Our device has only one interrupt endpoint
+		 * comman to all ports */
+		serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;
+
+		mos7720_port->port = serial->port[i];
+		usb_set_serial_port_data(serial->port[i], mos7720_port);
+
+		dbg("port number is %d", serial->port[i]->number);
+		dbg("serial number is %d", serial->minor);
+	}
+
+
+	/* setting configuration feature to one */
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			(__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ);
+
+	send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data);  // LSR For Port 1
+	dbg("LSR:%x",data);
+
+	send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data);  // LSR For Port 2
+	dbg("LSR:%x",data);
+
+	return 0;
+}
+
+static void mos7720_shutdown(struct usb_serial *serial)
+{
+	int i;
+
+	/* free private structure allocated for serial port */
+	for (i=0; i < serial->num_ports; ++i) {
+		kfree(usb_get_serial_port_data(serial->port[i]));
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+
+	/* free private structure allocated for serial device */
+	kfree(usb_get_serial_data(serial));
+	usb_set_serial_data(serial, NULL);
+}
+
+static struct usb_serial_driver moschip7720_2port_driver = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"moschip7720",
+	},
+	.description		= "Moschip 2 port adapter",
+	.id_table		= moschip_port_id_table,
+	.num_interrupt_in	= 1,
+	.num_bulk_in		= 2,
+	.num_bulk_out		= 2,
+	.num_ports		= 2,
+	.open			= mos7720_open,
+	.close			= mos7720_close,
+	.throttle		= mos7720_throttle,
+	.unthrottle		= mos7720_unthrottle,
+	.attach			= mos7720_startup,
+	.shutdown		= mos7720_shutdown,
+	.ioctl			= mos7720_ioctl,
+	.set_termios		= mos7720_set_termios,
+	.write			= mos7720_write,
+	.write_room		= mos7720_write_room,
+	.chars_in_buffer	= mos7720_chars_in_buffer,
+	.break_ctl		= mos7720_break,
+	.read_bulk_callback	= mos7720_bulk_in_callback,
+};
+
+static struct usb_driver usb_driver = {
+	.name =		"moschip7720",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	moschip_port_id_table,
+};
+
+static int __init moschip7720_init(void)
+{
+	int retval;
+
+	dbg("%s: Entering ..........", __FUNCTION__);
+
+	/* Register with the usb serial */
+	retval = usb_serial_register(&moschip7720_2port_driver);
+	if (retval)
+		goto failed_port_device_register;
+
+	info(DRIVER_DESC " " DRIVER_VERSION);
+
+	/* Register with the usb */
+	retval = usb_register(&usb_driver);
+	if (retval)
+		goto failed_usb_register;
+
+	return 0;
+
+failed_usb_register:
+	usb_serial_deregister(&moschip7720_2port_driver);
+
+failed_port_device_register:
+	return retval;
+}
+
+static void __exit moschip7720_exit(void)
+{
+	usb_deregister(&usb_driver);
+	usb_serial_deregister(&moschip7720_2port_driver);
+}
+
+module_init(moschip7720_init);
+module_exit(moschip7720_exit);
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 95bf571..5b71962 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -421,7 +421,7 @@
 /************************************************************************/
 /************************************************************************/
 
-static void mos7840_control_callback(struct urb *urb, struct pt_regs *regs)
+static void mos7840_control_callback(struct urb *urb)
 {
 	unsigned char *data;
 	struct moschip_port *mos7840_port;
@@ -497,7 +497,7 @@
  *	interrupt endpoint.
  *****************************************************************************/
 
-static void mos7840_interrupt_callback(struct urb *urb, struct pt_regs *regs)
+static void mos7840_interrupt_callback(struct urb *urb)
 {
 	int result;
 	int length;
@@ -647,7 +647,7 @@
  *	bulk in endpoint.
  *****************************************************************************/
 
-static void mos7840_bulk_in_callback(struct urb *urb, struct pt_regs *regs)
+static void mos7840_bulk_in_callback(struct urb *urb)
 {
 	int status;
 	unsigned char *data;
@@ -726,8 +726,7 @@
  *	on the bulk out endpoint.
  *****************************************************************************/
 
-static void mos7840_bulk_out_data_callback(struct urb *urb,
-					   struct pt_regs *regs)
+static void mos7840_bulk_out_data_callback(struct urb *urb)
 {
 	struct moschip_port *mos7840_port;
 	struct tty_struct *tty;
@@ -1088,7 +1087,7 @@
 	mos7840_port->icount.tx = 0;
 	mos7840_port->icount.rx = 0;
 
-	dbg("\n\nusb_serial serial:%x       mos7840_port:%x\n      usb_serial_port port:%x\n\n", (unsigned int)serial, (unsigned int)mos7840_port, (unsigned int)port);
+	dbg("\n\nusb_serial serial:%p       mos7840_port:%p\n      usb_serial_port port:%p\n\n", serial, mos7840_port, port);
 
 	return 0;
 
@@ -1421,7 +1420,6 @@
 	int i;
 	int bytes_sent = 0;
 	int transfer_size;
-	int from_user = 0;
 
 	struct moschip_port *mos7840_port;
 	struct usb_serial *serial;
@@ -1512,15 +1510,7 @@
 	}
 	transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
 
-	if (from_user) {
-		if (copy_from_user
-		    (urb->transfer_buffer, current_position, transfer_size)) {
-			bytes_sent = -EFAULT;
-			goto exit;
-		}
-	} else {
-		memcpy(urb->transfer_buffer, current_position, transfer_size);
-	}
+	memcpy(urb->transfer_buffer, current_position, transfer_size);
 
 	/* fill urb with data and submit  */
 	usb_fill_bulk_urb(urb,
@@ -2226,7 +2216,7 @@
  *****************************************************************************/
 
 static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
-				unsigned int *value)
+				unsigned int __user *value)
 {
 	int count;
 	unsigned int result = 0;
@@ -2249,7 +2239,7 @@
  *****************************************************************************/
 
 static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
-				   unsigned int *value)
+				   unsigned int __user *value)
 {
 	unsigned int result = 0;
 	struct tty_struct *tty = mos7840_port->port->tty;
@@ -2272,7 +2262,7 @@
  *****************************************************************************/
 
 static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
-				  unsigned int cmd, unsigned int *value)
+				  unsigned int cmd, unsigned int __user *value)
 {
 	unsigned int mcr;
 	unsigned int arg;
@@ -2342,7 +2332,7 @@
  *****************************************************************************/
 
 static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
-				  unsigned int *value)
+				  unsigned int __user *value)
 {
 	unsigned int result = 0;
 	__u16 msr;
@@ -2371,7 +2361,7 @@
  *****************************************************************************/
 
 static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
-				   struct serial_struct *retinfo)
+				   struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
 
@@ -2406,6 +2396,7 @@
 static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
 	struct moschip_port *mos7840_port;
 	struct tty_struct *tty;
 
@@ -2422,11 +2413,12 @@
 	}
 
 	mos7840_port = mos7840_get_port_private(port);
-	tty = mos7840_port->port->tty;
 
 	if (mos7840_port == NULL)
 		return -1;
 
+	tty = mos7840_port->port->tty;
+
 	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
 
 	switch (cmd) {
@@ -2434,16 +2426,13 @@
 
 	case TIOCINQ:
 		dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
-		return mos7840_get_bytes_avail(mos7840_port,
-					       (unsigned int *)arg);
-		break;
+		return mos7840_get_bytes_avail(mos7840_port, argp);
 
 	case TIOCOUTQ:
 		dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
 		return put_user(tty->driver->chars_in_buffer ?
 				tty->driver->chars_in_buffer(tty) : 0,
 				(int __user *)arg);
-		break;
 
 	case TCFLSH:
 		retval = tty_check_change(tty);
@@ -2473,13 +2462,13 @@
 
 	case TCGETS:
 		if (kernel_termios_to_user_termios
-		    ((struct termios __user *)arg, tty->termios))
+		    ((struct termios __user *)argp, tty->termios))
 			return -EFAULT;
 		return 0;
 
 	case TIOCSERGETLSR:
 		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
-		return mos7840_get_lsr_info(mos7840_port, (unsigned int *)arg);
+		return mos7840_get_lsr_info(mos7840_port, argp);
 		return 0;
 
 	case TIOCMBIS:
@@ -2488,19 +2477,16 @@
 		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
 		    port->number);
 		mosret =
-		    mos7840_set_modem_info(mos7840_port, cmd,
-					   (unsigned int *)arg);
+		    mos7840_set_modem_info(mos7840_port, cmd, argp);
 		return mosret;
 
 	case TIOCMGET:
 		dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
-		return mos7840_get_modem_info(mos7840_port,
-					      (unsigned int *)arg);
+		return mos7840_get_modem_info(mos7840_port, argp);
 
 	case TIOCGSERIAL:
 		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
-		return mos7840_get_serial_info(mos7840_port,
-					       (struct serial_struct *)arg);
+		return mos7840_get_serial_info(mos7840_port, argp);
 
 	case TIOCSSERIAL:
 		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
@@ -2550,7 +2536,7 @@
 
 		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
 		    port->number, icount.rx, icount.tx);
-		if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+		if (copy_to_user(argp, &icount, sizeof(icount)))
 			return -EFAULT;
 		return 0;
 
@@ -2818,7 +2804,7 @@
 
 	/* setting configuration feature to one */
 	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			(__u8) 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 5 * HZ);
+			(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ);
 	return 0;
 }
 
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index ac3f8b5..0610409 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -32,7 +32,7 @@
 	.no_dynamic_id = 	1,
 };
 
-static void navman_read_int_callback(struct urb *urb, struct pt_regs *regs)
+static void navman_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index a764ff4..bc91d3b 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -64,8 +64,8 @@
 /* function prototypes */
 static int  omninet_open		(struct usb_serial_port *port, struct file *filp);
 static void omninet_close		(struct usb_serial_port *port, struct file *filp);
-static void omninet_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void omninet_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
+static void omninet_read_bulk_callback	(struct urb *urb);
+static void omninet_write_bulk_callback	(struct urb *urb);
 static int  omninet_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  omninet_write_room		(struct usb_serial_port *port);
 static void omninet_shutdown		(struct usb_serial *serial);
@@ -194,7 +194,7 @@
 #define OMNINET_HEADERLEN	sizeof(struct omninet_header)
 #define OMNINET_BULKOUTSIZE 	(64 - OMNINET_HEADERLEN)
 
-static void omninet_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void omninet_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port 	*port 	= (struct usb_serial_port *)urb->context;
 	unsigned char 		*data 	= urb->transfer_buffer;
@@ -306,7 +306,7 @@
 	return (room);
 }
 
-static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void omninet_write_bulk_callback (struct urb *urb)
 {
 /*	struct omninet_header	*header = (struct omninet_header  *) urb->transfer_buffer; */
 	struct usb_serial_port 	*port   = (struct usb_serial_port *) urb->context;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c856e6f..130afbb 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -50,7 +50,7 @@
 static void option_rx_unthrottle(struct usb_serial_port *port);
 static int  option_write_room(struct usb_serial_port *port);
 
-static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
+static void option_instat_callback(struct urb *urb);
 
 static int option_write(struct usb_serial_port *port,
 			const unsigned char *buf, int count);
@@ -337,7 +337,7 @@
 	return count;
 }
 
-static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
+static void option_indat_callback(struct urb *urb)
 {
 	int err;
 	int endpoint;
@@ -374,7 +374,7 @@
 	return;
 }
 
-static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
+static void option_outdat_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
 
@@ -385,7 +385,7 @@
 	usb_serial_port_softint(port);
 }
 
-static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
+static void option_instat_callback(struct urb *urb)
 {
 	int err;
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
@@ -565,7 +565,7 @@
 /* Helper functions used by option_setup_urbs */
 static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
 		int dir, void *ctx, char *buf, int len,
-		void (*callback)(struct urb *, struct pt_regs *regs))
+		void (*callback)(struct urb *))
 {
 	struct urb *urb;
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 9c18173..bc800c8 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -948,7 +948,7 @@
 	wake_up_interruptible(&priv->delta_msr_wait);
 }
 
-static void pl2303_read_int_callback(struct urb *urb, struct pt_regs *regs)
+static void pl2303_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -987,7 +987,7 @@
 			__FUNCTION__, status);
 }
 
-static void pl2303_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void pl2303_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -1070,7 +1070,7 @@
 	return;
 }
 
-static void pl2303_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void pl2303_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 1e07dfa..30b7ebc 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -204,7 +204,7 @@
 	return fcs;
 }
 
-static void safe_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void safe_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	unsigned char *data = urb->transfer_buffer;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index d29638d..ea16572 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1,21 +1,35 @@
 /*
- * Sierra Wireless CDMA Wireless Serial USB driver
- *
- * Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com>
- * Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
- *
- *	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.
- */
+  USB Driver for Sierra Wireless
+
+  Copyright (C) 2006  Kevin Lloyd <linux@sierrawireless.com>
+
+  IMPORTANT DISCLAIMER: This driver is not commercially supported by
+  Sierra Wireless. Use at your own risk.
+
+  This driver is free software; you can redistribute it and/or modify
+  it under the terms of Version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
+  Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
+
+  History:
+*/
+
+#define DRIVER_VERSION "v.1.0.5"
+#define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
+#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
 #include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/errno.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
+
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x1199, 0x0018) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
@@ -23,53 +37,674 @@
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6803) },	/* Sierra Wireless MC8765 */
+	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 for Europe */
 	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 */
 	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
-	/* Following devices are supported in the airprime.c driver */
-	/* { USB_DEVICE(0x1199, 0x0112) }, */	/* Sierra Wireless AirCard 580 */
-	/* { USB_DEVICE(0x0F3D, 0x0112) }, */	/* AirPrime/Sierra PC 5220 */
+
+	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
+	{ USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
+static struct usb_device_id id_table_1port [] = {
+	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
+	{ USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
+	{ }
+};
+
+static struct usb_device_id id_table_3port [] = {
+	{ USB_DEVICE(0x1199, 0x0018) },	/* Sierra Wireless MC5720 */
+	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
+	{ USB_DEVICE(0x1199, 0x0017) },	/* Sierra Wireless EM5625 */
+	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
+	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
+	{ USB_DEVICE(0x1199, 0x6803) },	/* Sierra Wireless MC8765 */
+	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 */
+	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
+	{ }
+};
+
 static struct usb_driver sierra_driver = {
-	.name =		"sierra_wireless",
-	.probe =	usb_serial_probe,
-	.disconnect =	usb_serial_disconnect,
-	.id_table =	id_table,
+	.name       = "sierra",
+	.probe      = usb_serial_probe,
+	.disconnect = usb_serial_disconnect,
+	.id_table   = id_table,
+	.no_dynamic_id = 	1,
 };
 
-static struct usb_serial_driver sierra_device = {
+
+static int debug;
+
+/* per port private data */
+#define N_IN_URB	4
+#define N_OUT_URB	1
+#define IN_BUFLEN	4096
+#define OUT_BUFLEN	128
+
+struct sierra_port_private {
+	/* Input endpoints and buffer for this port */
+	struct urb *in_urbs[N_IN_URB];
+	char in_buffer[N_IN_URB][IN_BUFLEN];
+	/* Output endpoints and buffer for this port */
+	struct urb *out_urbs[N_OUT_URB];
+	char out_buffer[N_OUT_URB][OUT_BUFLEN];
+
+	/* Settings for the port */
+	int rts_state;	/* Handshaking pins (outputs) */
+	int dtr_state;
+	int cts_state;	/* Handshaking pins (inputs) */
+	int dsr_state;
+	int dcd_state;
+	int ri_state;
+
+	unsigned long tx_start_time[N_OUT_URB];
+};
+
+static int sierra_send_setup(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct sierra_port_private *portdata;
+
+	dbg("%s", __FUNCTION__);
+
+	portdata = usb_get_serial_port_data(port);
+
+	if (port->tty) {
+		int val = 0;
+		if (portdata->dtr_state)
+			val |= 0x01;
+		if (portdata->rts_state)
+			val |= 0x02;
+
+		return usb_control_msg(serial->dev,
+				usb_rcvctrlpipe(serial->dev, 0),
+				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+	}
+
+	return 0;
+}
+
+static void sierra_rx_throttle(struct usb_serial_port *port)
+{
+	dbg("%s", __FUNCTION__);
+}
+
+static void sierra_rx_unthrottle(struct usb_serial_port *port)
+{
+	dbg("%s", __FUNCTION__);
+}
+
+static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
+{
+	/* Unfortunately, I don't know how to send a break */
+	dbg("%s", __FUNCTION__);
+}
+
+static void sierra_set_termios(struct usb_serial_port *port,
+			struct termios *old_termios)
+{
+	dbg("%s", __FUNCTION__);
+
+	sierra_send_setup(port);
+}
+
+static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	unsigned int value;
+	struct sierra_port_private *portdata;
+
+	portdata = usb_get_serial_port_data(port);
+
+	value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
+		((portdata->dtr_state) ? TIOCM_DTR : 0) |
+		((portdata->cts_state) ? TIOCM_CTS : 0) |
+		((portdata->dsr_state) ? TIOCM_DSR : 0) |
+		((portdata->dcd_state) ? TIOCM_CAR : 0) |
+		((portdata->ri_state) ? TIOCM_RNG : 0);
+
+	return value;
+}
+
+static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
+			unsigned int set, unsigned int clear)
+{
+	struct sierra_port_private *portdata;
+
+	portdata = usb_get_serial_port_data(port);
+
+	if (set & TIOCM_RTS)
+		portdata->rts_state = 1;
+	if (set & TIOCM_DTR)
+		portdata->dtr_state = 1;
+
+	if (clear & TIOCM_RTS)
+		portdata->rts_state = 0;
+	if (clear & TIOCM_DTR)
+		portdata->dtr_state = 0;
+	return sierra_send_setup(port);
+}
+
+static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	return -ENOIOCTLCMD;
+}
+
+/* Write */
+static int sierra_write(struct usb_serial_port *port,
+			const unsigned char *buf, int count)
+{
+	struct sierra_port_private *portdata;
+	int i;
+	int left, todo;
+	struct urb *this_urb = NULL; /* spurious */
+	int err;
+
+	portdata = usb_get_serial_port_data(port);
+
+	dbg("%s: write (%d chars)", __FUNCTION__, count);
+
+	i = 0;
+	left = count;
+	for (i=0; left > 0 && i < N_OUT_URB; i++) {
+		todo = left;
+		if (todo > OUT_BUFLEN)
+			todo = OUT_BUFLEN;
+
+		this_urb = portdata->out_urbs[i];
+		if (this_urb->status == -EINPROGRESS) {
+			if (time_before(jiffies,
+					portdata->tx_start_time[i] + 10 * HZ))
+				continue;
+			usb_unlink_urb(this_urb);
+			continue;
+		}
+		if (this_urb->status != 0)
+			dbg("usb_write %p failed (err=%d)",
+				this_urb, this_urb->status);
+
+		dbg("%s: endpoint %d buf %d", __FUNCTION__,
+			usb_pipeendpoint(this_urb->pipe), i);
+
+		/* send the data */
+		memcpy (this_urb->transfer_buffer, buf, todo);
+		this_urb->transfer_buffer_length = todo;
+
+		this_urb->dev = port->serial->dev;
+		err = usb_submit_urb(this_urb, GFP_ATOMIC);
+		if (err) {
+			dbg("usb_submit_urb %p (write bulk) failed "
+				"(%d, has %d)", this_urb,
+				err, this_urb->status);
+			continue;
+		}
+		portdata->tx_start_time[i] = jiffies;
+		buf += todo;
+		left -= todo;
+	}
+
+	count -= left;
+	dbg("%s: wrote (did %d)", __FUNCTION__, count);
+	return count;
+}
+
+static void sierra_indat_callback(struct urb *urb)
+{
+	int err;
+	int endpoint;
+	struct usb_serial_port *port;
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+
+	dbg("%s: %p", __FUNCTION__, urb);
+
+	endpoint = usb_pipeendpoint(urb->pipe);
+	port = (struct usb_serial_port *) urb->context;
+
+	if (urb->status) {
+		dbg("%s: nonzero status: %d on endpoint %02x.",
+		    __FUNCTION__, urb->status, endpoint);
+	} else {
+		tty = port->tty;
+		if (urb->actual_length) {
+			tty_buffer_request_room(tty, urb->actual_length);
+			tty_insert_flip_string(tty, data, urb->actual_length);
+			tty_flip_buffer_push(tty);
+		} else {
+			dbg("%s: empty read urb received", __FUNCTION__);
+		}
+
+		/* Resubmit urb so we continue receiving */
+		if (port->open_count && urb->status != -ESHUTDOWN) {
+			err = usb_submit_urb(urb, GFP_ATOMIC);
+			if (err)
+				printk(KERN_ERR "%s: resubmit read urb failed. "
+					"(%d)", __FUNCTION__, err);
+		}
+	}
+	return;
+}
+
+static void sierra_outdat_callback(struct urb *urb)
+{
+	struct usb_serial_port *port;
+
+	dbg("%s", __FUNCTION__);
+
+	port = (struct usb_serial_port *) urb->context;
+
+	usb_serial_port_softint(port);
+}
+
+static void sierra_instat_callback(struct urb *urb)
+{
+	int err;
+	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+	struct usb_serial *serial = port->serial;
+
+	dbg("%s", __FUNCTION__);
+	dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
+
+	if (urb->status == 0) {
+		struct usb_ctrlrequest *req_pkt =
+				(struct usb_ctrlrequest *)urb->transfer_buffer;
+
+		if (!req_pkt) {
+			dbg("%s: NULL req_pkt\n", __FUNCTION__);
+			return;
+		}
+		if ((req_pkt->bRequestType == 0xA1) &&
+				(req_pkt->bRequest == 0x20)) {
+			int old_dcd_state;
+			unsigned char signals = *((unsigned char *)
+					urb->transfer_buffer +
+					sizeof(struct usb_ctrlrequest));
+
+			dbg("%s: signal x%x", __FUNCTION__, signals);
+
+			old_dcd_state = portdata->dcd_state;
+			portdata->cts_state = 1;
+			portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
+			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
+			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
+
+			if (port->tty && !C_CLOCAL(port->tty) &&
+					old_dcd_state && !portdata->dcd_state)
+				tty_hangup(port->tty);
+		} else {
+			dbg("%s: type %x req %x", __FUNCTION__,
+				req_pkt->bRequestType,req_pkt->bRequest);
+		}
+	} else
+		dbg("%s: error %d", __FUNCTION__, urb->status);
+
+	/* Resubmit urb so we continue receiving IRQ data */
+	if (urb->status != -ESHUTDOWN) {
+		urb->dev = serial->dev;
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err)
+			dbg("%s: resubmit intr urb failed. (%d)",
+				__FUNCTION__, err);
+	}
+}
+
+static int sierra_write_room(struct usb_serial_port *port)
+{
+	struct sierra_port_private *portdata;
+	int i;
+	int data_len = 0;
+	struct urb *this_urb;
+
+	portdata = usb_get_serial_port_data(port);
+
+	for (i=0; i < N_OUT_URB; i++) {
+		this_urb = portdata->out_urbs[i];
+		if (this_urb && this_urb->status != -EINPROGRESS)
+			data_len += OUT_BUFLEN;
+	}
+
+	dbg("%s: %d", __FUNCTION__, data_len);
+	return data_len;
+}
+
+static int sierra_chars_in_buffer(struct usb_serial_port *port)
+{
+	struct sierra_port_private *portdata;
+	int i;
+	int data_len = 0;
+	struct urb *this_urb;
+
+	portdata = usb_get_serial_port_data(port);
+
+	for (i=0; i < N_OUT_URB; i++) {
+		this_urb = portdata->out_urbs[i];
+		if (this_urb && this_urb->status == -EINPROGRESS)
+			data_len += this_urb->transfer_buffer_length;
+	}
+	dbg("%s: %d", __FUNCTION__, data_len);
+	return data_len;
+}
+
+static int sierra_open(struct usb_serial_port *port, struct file *filp)
+{
+	struct sierra_port_private *portdata;
+	struct usb_serial *serial = port->serial;
+	int i, err;
+	struct urb *urb;
+
+	portdata = usb_get_serial_port_data(port);
+
+	dbg("%s", __FUNCTION__);
+
+	/* Set some sane defaults */
+	portdata->rts_state = 1;
+	portdata->dtr_state = 1;
+
+	/* Reset low level data toggle and start reading from endpoints */
+	for (i = 0; i < N_IN_URB; i++) {
+		urb = portdata->in_urbs[i];
+		if (! urb)
+			continue;
+		if (urb->dev != serial->dev) {
+			dbg("%s: dev %p != %p", __FUNCTION__,
+				urb->dev, serial->dev);
+			continue;
+		}
+
+		/*
+		 * make sure endpoint data toggle is synchronized with the
+		 * device
+		 */
+		usb_clear_halt(urb->dev, urb->pipe);
+
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err) {
+			dbg("%s: submit urb %d failed (%d) %d",
+				__FUNCTION__, i, err,
+				urb->transfer_buffer_length);
+		}
+	}
+
+	/* Reset low level data toggle on out endpoints */
+	for (i = 0; i < N_OUT_URB; i++) {
+		urb = portdata->out_urbs[i];
+		if (! urb)
+			continue;
+		urb->dev = serial->dev;
+		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+				usb_pipeout(urb->pipe), 0); */
+	}
+
+	port->tty->low_latency = 1;
+
+	sierra_send_setup(port);
+
+	return (0);
+}
+
+static inline void stop_urb(struct urb *urb)
+{
+	if (urb && urb->status == -EINPROGRESS)
+		usb_kill_urb(urb);
+}
+
+static void sierra_close(struct usb_serial_port *port, struct file *filp)
+{
+	int i;
+	struct usb_serial *serial = port->serial;
+	struct sierra_port_private *portdata;
+
+	dbg("%s", __FUNCTION__);
+	portdata = usb_get_serial_port_data(port);
+
+	portdata->rts_state = 0;
+	portdata->dtr_state = 0;
+
+	if (serial->dev) {
+		sierra_send_setup(port);
+
+		/* Stop reading/writing urbs */
+		for (i = 0; i < N_IN_URB; i++)
+			stop_urb(portdata->in_urbs[i]);
+		for (i = 0; i < N_OUT_URB; i++)
+			stop_urb(portdata->out_urbs[i]);
+	}
+	port->tty = NULL;
+}
+
+/* Helper functions used by sierra_setup_urbs */
+static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
+				    int dir, void *ctx, char *buf, int len,
+				    usb_complete_t callback)
+{
+	struct urb *urb;
+
+	if (endpoint == -1)
+		return NULL;		/* endpoint not needed */
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
+	if (urb == NULL) {
+		dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
+		return NULL;
+	}
+
+		/* Fill URB using supplied data. */
+	usb_fill_bulk_urb(urb, serial->dev,
+		      usb_sndbulkpipe(serial->dev, endpoint) | dir,
+		      buf, len, callback, ctx);
+
+	return urb;
+}
+
+/* Setup urbs */
+static void sierra_setup_urbs(struct usb_serial *serial)
+{
+	int i,j;
+	struct usb_serial_port *port;
+	struct sierra_port_private *portdata;
+
+	dbg("%s", __FUNCTION__);
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port = serial->port[i];
+		portdata = usb_get_serial_port_data(port);
+
+	/* Do indat endpoints first */
+		for (j = 0; j < N_IN_URB; ++j) {
+			portdata->in_urbs[j] = sierra_setup_urb (serial,
+                  	port->bulk_in_endpointAddress, USB_DIR_IN, port,
+                  	portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback);
+		}
+
+		/* outdat endpoints */
+		for (j = 0; j < N_OUT_URB; ++j) {
+			portdata->out_urbs[j] = sierra_setup_urb (serial,
+                  	port->bulk_out_endpointAddress, USB_DIR_OUT, port,
+                  	portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback);
+		}
+	}
+}
+
+static int sierra_startup(struct usb_serial *serial)
+{
+	int i, err;
+	struct usb_serial_port *port;
+	struct sierra_port_private *portdata;
+
+	dbg("%s", __FUNCTION__);
+
+	/* Now setup per port private data */
+	for (i = 0; i < serial->num_ports; i++) {
+		port = serial->port[i];
+		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+		if (!portdata) {
+			dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
+					__FUNCTION__, i);
+			return (1);
+		}
+
+		usb_set_serial_port_data(port, portdata);
+
+		if (! port->interrupt_in_urb)
+			continue;
+		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+		if (err)
+			dbg("%s: submit irq_in urb failed %d",
+				__FUNCTION__, err);
+	}
+
+	sierra_setup_urbs(serial);
+
+	return (0);
+}
+
+static void sierra_shutdown(struct usb_serial *serial)
+{
+	int i, j;
+	struct usb_serial_port *port;
+	struct sierra_port_private *portdata;
+
+	dbg("%s", __FUNCTION__);
+
+	/* Stop reading/writing urbs */
+	for (i = 0; i < serial->num_ports; ++i) {
+		port = serial->port[i];
+		portdata = usb_get_serial_port_data(port);
+		for (j = 0; j < N_IN_URB; j++)
+			stop_urb(portdata->in_urbs[j]);
+		for (j = 0; j < N_OUT_URB; j++)
+			stop_urb(portdata->out_urbs[j]);
+	}
+
+	/* Now free them */
+	for (i = 0; i < serial->num_ports; ++i) {
+		port = serial->port[i];
+		portdata = usb_get_serial_port_data(port);
+
+		for (j = 0; j < N_IN_URB; j++) {
+			if (portdata->in_urbs[j]) {
+				usb_free_urb(portdata->in_urbs[j]);
+				portdata->in_urbs[j] = NULL;
+			}
+		}
+		for (j = 0; j < N_OUT_URB; j++) {
+			if (portdata->out_urbs[j]) {
+				usb_free_urb(portdata->out_urbs[j]);
+				portdata->out_urbs[j] = NULL;
+			}
+		}
+	}
+
+	/* Now free per port private data */
+	for (i = 0; i < serial->num_ports; i++) {
+		port = serial->port[i];
+		kfree(usb_get_serial_port_data(port));
+	}
+}
+
+static struct usb_serial_driver sierra_1port_device = {
 	.driver = {
-	.owner =		THIS_MODULE,
-	.name =			"Sierra_Wireless",
+		.owner =	THIS_MODULE,
+		.name =		"sierra1",
 	},
-	.id_table =		id_table,
-	.num_interrupt_in =	NUM_DONT_CARE,
-	.num_bulk_in =		NUM_DONT_CARE,
-	.num_bulk_out =		NUM_DONT_CARE,
-	.num_ports =		3,
+	.description       = "Sierra USB modem (1 port)",
+	.id_table          = id_table_1port,
+	.num_interrupt_in  = NUM_DONT_CARE,
+	.num_bulk_in       = 1,
+	.num_bulk_out      = 1,
+	.num_ports         = 1,
+	.open              = sierra_open,
+	.close             = sierra_close,
+	.write             = sierra_write,
+	.write_room        = sierra_write_room,
+	.chars_in_buffer   = sierra_chars_in_buffer,
+	.throttle          = sierra_rx_throttle,
+	.unthrottle        = sierra_rx_unthrottle,
+	.ioctl             = sierra_ioctl,
+	.set_termios       = sierra_set_termios,
+	.break_ctl         = sierra_break_ctl,
+	.tiocmget          = sierra_tiocmget,
+	.tiocmset          = sierra_tiocmset,
+	.attach            = sierra_startup,
+	.shutdown          = sierra_shutdown,
+	.read_int_callback = sierra_instat_callback,
 };
 
+static struct usb_serial_driver sierra_3port_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"sierra3",
+	},
+	.description       = "Sierra USB modem (3 port)",
+	.id_table          = id_table_3port,
+	.num_interrupt_in  = NUM_DONT_CARE,
+	.num_bulk_in       = 3,
+	.num_bulk_out      = 3,
+	.num_ports         = 3,
+	.open              = sierra_open,
+	.close             = sierra_close,
+	.write             = sierra_write,
+	.write_room        = sierra_write_room,
+	.chars_in_buffer   = sierra_chars_in_buffer,
+	.throttle          = sierra_rx_throttle,
+	.unthrottle        = sierra_rx_unthrottle,
+	.ioctl             = sierra_ioctl,
+	.set_termios       = sierra_set_termios,
+	.break_ctl         = sierra_break_ctl,
+	.tiocmget          = sierra_tiocmget,
+	.tiocmset          = sierra_tiocmset,
+	.attach            = sierra_startup,
+	.shutdown          = sierra_shutdown,
+	.read_int_callback = sierra_instat_callback,
+};
+
+/* Functions used by new usb-serial code. */
 static int __init sierra_init(void)
 {
 	int retval;
-
-	retval = usb_serial_register(&sierra_device);
+	retval = usb_serial_register(&sierra_1port_device);
 	if (retval)
-		return retval;
+		goto failed_1port_device_register;
+	retval = usb_serial_register(&sierra_3port_device);
+	if (retval)
+		goto failed_3port_device_register;
+
+
 	retval = usb_register(&sierra_driver);
 	if (retval)
-		usb_serial_deregister(&sierra_device);
+		goto failed_driver_register;
+
+	info(DRIVER_DESC ": " DRIVER_VERSION);
+
+	return 0;
+
+failed_driver_register:
+	usb_serial_deregister(&sierra_3port_device);
+failed_3port_device_register:
+	usb_serial_deregister(&sierra_1port_device);
+failed_1port_device_register:
 	return retval;
 }
 
 static void __exit sierra_exit(void)
 {
-	usb_deregister(&sierra_driver);
-	usb_serial_deregister(&sierra_device);
+	usb_deregister (&sierra_driver);
+	usb_serial_deregister(&sierra_1port_device);
+	usb_serial_deregister(&sierra_3port_device);
 }
 
 module_init(sierra_init);
 module_exit(sierra_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_USB_DEBUG
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages");
+#endif
+
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index ac9b8ee..07400c0 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -166,9 +166,9 @@
 static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
 	unsigned int set, unsigned int clear);
 static void ti_break(struct usb_serial_port *port, int break_state);
-static void ti_interrupt_callback(struct urb *urb, struct pt_regs *regs);
-static void ti_bulk_in_callback(struct urb *urb, struct pt_regs *regs);
-static void ti_bulk_out_callback(struct urb *urb, struct pt_regs *regs);
+static void ti_interrupt_callback(struct urb *urb);
+static void ti_bulk_in_callback(struct urb *urb);
+static void ti_bulk_out_callback(struct urb *urb);
 
 static void ti_recv(struct device *dev, struct tty_struct *tty,
 	unsigned char *data, int length);
@@ -1098,7 +1098,7 @@
 }
 
 
-static void ti_interrupt_callback(struct urb *urb, struct pt_regs *regs)
+static void ti_interrupt_callback(struct urb *urb)
 {
 	struct ti_device *tdev = (struct ti_device *)urb->context;
 	struct usb_serial_port *port;
@@ -1178,7 +1178,7 @@
 }
 
 
-static void ti_bulk_in_callback(struct urb *urb, struct pt_regs *regs)
+static void ti_bulk_in_callback(struct urb *urb)
 {
 	struct ti_port *tport = (struct ti_port *)urb->context;
 	struct usb_serial_port *port = tport->tp_port;
@@ -1241,7 +1241,7 @@
 }
 
 
-static void ti_bulk_out_callback(struct urb *urb, struct pt_regs *regs)
+static void ti_bulk_out_callback(struct urb *urb)
 {
 	struct ti_port *tport = (struct ti_port *)urb->context;
 	struct usb_serial_port *port = tport->tp_port;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 88949f7..befe2e1 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -47,9 +47,9 @@
 static void visor_shutdown	(struct usb_serial *serial);
 static int  visor_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void visor_set_termios	(struct usb_serial_port *port, struct termios *old_termios);
-static void visor_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void visor_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void visor_read_int_callback	(struct urb *urb, struct pt_regs *regs);
+static void visor_write_bulk_callback	(struct urb *urb);
+static void visor_read_bulk_callback	(struct urb *urb);
+static void visor_read_int_callback	(struct urb *urb);
 static int  clie_3_5_startup	(struct usb_serial *serial);
 static int  treo_attach		(struct usb_serial *serial);
 static int clie_5_attach (struct usb_serial *serial);
@@ -471,7 +471,7 @@
 }
 
 
-static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void visor_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct visor_private *priv = usb_get_serial_port_data(port);
@@ -494,7 +494,7 @@
 }
 
 
-static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void visor_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct visor_private *priv = usb_get_serial_port_data(port);
@@ -539,7 +539,7 @@
 	return;
 }
 
-static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void visor_read_int_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	int result;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 6e6c793..4d1cd7a 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -152,8 +152,8 @@
 static int  whiteheat_chars_in_buffer	(struct usb_serial_port *port);
 static void whiteheat_throttle		(struct usb_serial_port *port);
 static void whiteheat_unthrottle	(struct usb_serial_port *port);
-static void whiteheat_read_callback	(struct urb *urb, struct pt_regs *regs);
-static void whiteheat_write_callback	(struct urb *urb, struct pt_regs *regs);
+static void whiteheat_read_callback	(struct urb *urb);
+static void whiteheat_write_callback	(struct urb *urb);
 
 static struct usb_serial_driver whiteheat_fake_device = {
 	.driver = {
@@ -235,8 +235,8 @@
 /* local function prototypes */
 static int start_command_port(struct usb_serial *serial);
 static void stop_command_port(struct usb_serial *serial);
-static void command_port_write_callback(struct urb *urb, struct pt_regs *regs);
-static void command_port_read_callback(struct urb *urb, struct pt_regs *regs);
+static void command_port_write_callback(struct urb *urb);
+static void command_port_read_callback(struct urb *urb);
 
 static int start_port_read(struct usb_serial_port *port);
 static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
@@ -958,7 +958,7 @@
 /*****************************************************************************
  * Connect Tech's White Heat callback routines
  *****************************************************************************/
-static void command_port_write_callback (struct urb *urb, struct pt_regs *regs)
+static void command_port_write_callback (struct urb *urb)
 {
 	dbg("%s", __FUNCTION__);
 
@@ -969,7 +969,7 @@
 }
 
 
-static void command_port_read_callback (struct urb *urb, struct pt_regs *regs)
+static void command_port_read_callback (struct urb *urb)
 {
 	struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
 	struct whiteheat_command_private *command_info;
@@ -1019,7 +1019,7 @@
 }
 
 
-static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs)
+static void whiteheat_read_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct whiteheat_urb_wrap *wrap;
@@ -1061,7 +1061,7 @@
 }
 
 
-static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs)
+static void whiteheat_write_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index f843a0b..3baf448 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -53,7 +53,7 @@
 	unsigned int is_open:1;
 };
 
-static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
+static void usb_onetouch_irq(struct urb *urb)
 {
 	struct usb_onetouch *onetouch = urb->context;
 	signed char *data = onetouch->data;
@@ -72,7 +72,6 @@
 		goto resubmit;
 	}
 
-	input_regs(dev, regs);
 	input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02);
 	input_sync(dev);
 
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index f23514c..47644b5 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -108,7 +108,7 @@
 /* This is the completion handler which will wake us up when an URB
  * completes.
  */
-static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs)
+static void usb_stor_blocking_completion(struct urb *urb)
 {
 	struct completion *urb_done_ptr = (struct completion *)urb->context;
 
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c9a8d50..37ed8e0 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -55,7 +55,8 @@
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_IGNORE_RESIDUE),
 
-UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0100,
+/* modified by Tobias Lorenz <tobias.lorenz@gmx.net> */
+UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0200,
 		"Mitsumi",
 		"USB FDD",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -182,6 +183,20 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
+/* Reported by Bardur Arantsson <bardur@scientician.net> */
+UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0370,
+		"Nokia",
+		"6131",
+		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",
+		"6234",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_MAX_SECTORS_64 ),
+
 /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
 UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
 		"SMSC",
@@ -1291,6 +1306,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
+/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
+		"Sony Ericsson",
+		"P990i",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
  * Entry is needed only for the initializer function override.
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 1b51d31..296b091 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -158,7 +158,7 @@
 	return retval;
 }
 
-static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+static void skel_write_bulk_callback(struct urb *urb)
 {
 	struct usb_skel *dev;
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index daaa486..7a43020 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -701,7 +701,6 @@
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_NVIDIA_I2C
 	select I2C if FB_NVIDIA_I2C
-	select FB_DDC if FB_NVIDIA_I2C
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index f1ba54f..a4e3fca 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1144,7 +1144,7 @@
 	 */
 
 static int flash_cursor(void);
-static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t amifb_interrupt(int irq, void *dev_id);
 static u_long chipalloc(u_long size);
 static void chipfree(void);
 
@@ -2492,7 +2492,7 @@
 	 * VBlank Display Interrupt
 	 */
 
-static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t amifb_interrupt(int irq, void *dev_id)
 {
 	if (do_vmode_pan || do_vmode_full)
 		ami_update_display();
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 70dd811..ab34b96 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -218,8 +218,7 @@
 	return -EINVAL;
 }
 
-static irqreturn_t arcfb_interrupt(int vec, void *dev_instance,
-		struct pt_regs *regs)
+static irqreturn_t arcfb_interrupt(int vec, void *dev_instance)
 {
 	struct fb_info *info = dev_instance;
 	unsigned char ctl2status;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 5831893..02c41a6 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -1521,7 +1521,7 @@
 }
 
 
-static irqreturn_t falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp )
+static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
 {
 	struct falcon_hw *hw = &f_new_mode;
 
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index b45c9fd..b77b309 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -1532,7 +1532,7 @@
 	return (0);
 }
 
-static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t aty_irq(int irq, void *dev_id)
 {
 	struct atyfb_par *par = dev_id;
 	int handled = 0;
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index c6a5f0c..dbf4ec3 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1545,7 +1545,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs)
+static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
 {
 	/* Nothing to do for now, just clear any pending interrupt */
 	lcd->intstatus = lcd->intstatus;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 8c041da..302174b 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -204,7 +204,7 @@
  */
 static int vbl_detected;
 
-static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t fb_vbl_detect(int irq, void *dummy)
 {
 	vbl_detected++;
 	return IRQ_HANDLED;
@@ -414,7 +414,7 @@
 
 #if defined(CONFIG_ATARI) || defined(CONFIG_MAC)
 static int cursor_blink_rate;
-static irqreturn_t fb_vbl_handler(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t fb_vbl_handler(int irq, void *dev_id)
 {
 	struct fb_info *info = dev_id;
 
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 8cc6c0e..04c6d92 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -415,13 +415,15 @@
 	full = p->total_vram == 0x400000;
 
 	/* Try to pick a video mode out of NVRAM if we have one. */
+#ifdef CONFIG_NVRAM
 	if (default_cmode == CMODE_NVRAM){
 		cmode = nvram_read_byte(NV_CMODE);
 		if(cmode < CMODE_8 || cmode > CMODE_32)
 			cmode = CMODE_8;
 	} else
+#endif
 		cmode=default_cmode;
-
+#ifdef CONFIG_NVRAM
 	if (default_vmode == VMODE_NVRAM) {
 		vmode = nvram_read_byte(NV_VMODE);
 		if (vmode < 1 || vmode > VMODE_MAX ||
@@ -432,7 +434,9 @@
 			if (control_mac_modes[vmode - 1].m[full] < cmode)
 				vmode = VMODE_640_480_60;
 		}
-	} else {
+	} else
+#endif
+	{
 		vmode=default_vmode;
 		if (control_mac_modes[vmode - 1].m[full] < cmode) {
 			if (cmode > CMODE_8)
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 3afb472..3dc4942 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/hd64461.h>
 #include <asm/cpu/dac.h>
-#include <asm/hp6xx/hp6xx.h>
 
 #define	WIDTH 640
 
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 67f384f..e6df492c 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -573,3 +573,10 @@
 
 module_init(igafb_init);
 MODULE_LICENSE("GPL");
+static struct pci_device_id igafb_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, igafb_pci_tbl);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index f887f1e..eeeeff9 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -1952,7 +1952,7 @@
 }
 
 static irqreturn_t
-intelfbhw_irq(int irq, void *dev_id, struct pt_regs *fp) {
+intelfbhw_irq(int irq, void *dev_id) {
 	int handled = 0;
 	u16 tmp;
 	struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 7acf01c..e9b4115 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -198,7 +198,7 @@
 	}
 }
 
-static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t matrox_irq(int irq, void *dev_id)
 {
 	u_int32_t status;
 	int handled = 0;
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index e48de3c..19eef3a 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -160,12 +160,51 @@
 
 }
 
+static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
+{
+	u8 start = 0x0;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = 0x50,
+		 .len = 1,
+		 .buf = &start,
+		 }, {
+		     .addr = 0x50,
+		     .flags = I2C_M_RD,
+		     .len = EDID_LENGTH,
+		     },
+	};
+	u8 *buf;
+
+	if (!chan->par)
+		return NULL;
+
+	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!buf) {
+		dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n");
+		return NULL;
+	}
+	msgs[1].buf = buf;
+
+	if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
+		return buf;
+	dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n");
+	kfree(buf);
+	return NULL;
+}
+
 int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
 {
 	struct nvidia_par *par = info->par;
-	u8 *edid;
+	u8 *edid = NULL;
+	int i;
 
-	edid = fb_ddc_read(&par->chan[conn - 1].adapter);
+	for (i = 0; i < 3; i++) {
+		/* Do the real work */
+		edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]);
+		if (edid)
+			break;
+	}
 
 	if (!edid && conn == 1) {
 		/* try to get from firmware */
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 983be3e..fdb33cd 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -339,11 +339,12 @@
 
 	sense = read_platinum_sense(pinfo);
 	printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense);
-
 	if (default_vmode == VMODE_NVRAM) {
+#ifdef CONFIG_NVRAM
 		default_vmode = nvram_read_byte(NV_VMODE);
 		if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
 		    !platinum_reg_init[default_vmode-1])
+#endif
 			default_vmode = VMODE_CHOOSE;
 	}
 	if (default_vmode == VMODE_CHOOSE) {
@@ -351,8 +352,10 @@
 	}
 	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
 		default_vmode = VMODE_640_480_60;
+#ifdef CONFIG_NVRAM
 	if (default_cmode == CMODE_NVRAM)
 		default_cmode = nvram_read_byte(NV_CMODE);
+#endif
 	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
 		default_cmode = CMODE_8;
 	/*
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 78dc59a..c7bc809 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -209,7 +209,7 @@
 static void pvr2_update_display(struct fb_info *info);
 static void pvr2_init_display(struct fb_info *info);
 static void pvr2_do_blank(void);
-static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id);
 static int pvr2_init_cable(void);
 static int pvr2_get_param(const struct pvr2_params *p, const char *s,
                             int val, int size);
@@ -626,7 +626,7 @@
 	is_blanked = do_blank > 0 ? do_blank : 0;
 }
 
-static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id)
 {
 	struct fb_info *info = dev_id;
 
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 3bc5da4..8a8ae55 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -846,7 +846,7 @@
 /*
  *  pxafb_handle_irq: Handle 'LCD DONE' interrupts.
  */
-static irqreturn_t pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
 {
 	struct pxafb_info *fbi = dev_id;
 	unsigned int lcsr = LCSR;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ad3bdd6..5940734 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -614,7 +614,7 @@
 	}
 }
 
-static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
+static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
 {
 	struct s3c2410fb_info *fbi = dev_id;
 	unsigned long lcdirq = readl(S3C2410_LCDINTPND);
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index a2e6e72..cd10b18 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1085,7 +1085,7 @@
 /*
  *  sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
  */
-static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
 {
 	struct sa1100fb_info *fbi = dev_id;
 	unsigned int lcsr = LCSR;
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 47f2792..06fc19a 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -284,7 +284,7 @@
 	printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense);
 
 	/* Try to pick a video mode out of NVRAM if we have one. */
-#ifndef CONFIG_MAC
+#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
 	if (default_vmode == VMODE_NVRAM) {
 		default_vmode = nvram_read_byte(NV_VMODE);
 		if (default_vmode <= 0
@@ -297,7 +297,7 @@
 		default_vmode = mac_map_monitor_sense(p->sense);
 	if (!valkyrie_reg_init[default_vmode - 1])
 		default_vmode = VMODE_640_480_67;
-#ifndef CONFIG_MAC
+#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
 	if (default_cmode == CMODE_NVRAM)
 		default_cmode = nvram_read_byte(NV_CMODE);
 #endif
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 27c9d05..c287a9a 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -2,7 +2,6 @@
 
 config W1
 	tristate "Dallas's 1-wire support"
-	depends on CONNECTOR
 	---help---
 	  Dallas' 1-wire bus is useful to connect slow 1-pin devices
 	  such as iButtons and thermal sensors.
diff --git a/fs/Kconfig b/fs/Kconfig
index 599de54..fee318e 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -140,6 +140,73 @@
 	  If you are not using a security module that requires using
 	  extended attributes for file security labels, say N.
 
+config EXT4DEV_FS
+	tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select JBD2
+	help
+	  Ext4dev is a predecessor filesystem of the next generation
+	  extended fs ext4, based on ext3 filesystem code. It will be
+	  renamed ext4 fs later, once ext4dev is mature and stabilized.
+
+	  Unlike the change from ext2 filesystem to ext3 filesystem,
+	  the on-disk format of ext4dev is not the same as ext3 any more:
+	  it is based on extent maps and it supports 48-bit physical block
+	  numbers. These combined on-disk format changes will allow
+	  ext4dev/ext4 to handle more than 16 TB filesystem volumes --
+	  a hard limit that ext3 cannot overcome without changing the
+	  on-disk format.
+
+	  Other than extent maps and 48-bit block numbers, ext4dev also is
+	  likely to have other new features such as persistent preallocation,
+	  high resolution time stamps, and larger file support etc.  These
+	  features will be added to ext4dev gradually.
+
+	  To compile this file system support as a module, choose M here. The
+	  module will be called ext4dev.  Be aware, however, that the filesystem
+	  of your root partition (the one containing the directory /) cannot
+	  be compiled as a module, and so this could be dangerous.
+
+	  If unsure, say N.
+
+config EXT4DEV_FS_XATTR
+	bool "Ext4dev extended attributes"
+	depends on EXT4DEV_FS
+	default y
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
+
+	  If unsure, say N.
+
+	  You need this for POSIX ACL support on ext4dev/ext4.
+
+config EXT4DEV_FS_POSIX_ACL
+	bool "Ext4dev POSIX Access Control Lists"
+	depends on EXT4DEV_FS_XATTR
+	select FS_POSIX_ACL
+	help
+	  POSIX Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
+
+	  To learn more about Access Control Lists, visit the POSIX ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  If you don't know what Access Control Lists are, say N
+
+config EXT4DEV_FS_SECURITY
+	bool "Ext4dev Security Labels"
+	depends on EXT4DEV_FS_XATTR
+	help
+	  Security labels support alternative access control models
+	  implemented by security modules like SELinux.  This option
+	  enables an extended attribute handler for file security
+	  labels in the ext4dev/ext4 filesystem.
+
+	  If you are not using a security module that requires using
+	  extended attributes for file security labels, say N.
+
 config JBD
 	tristate
 	help
@@ -172,12 +239,44 @@
 	  generated.  To turn debugging off again, do
 	  "echo 0 > /proc/sys/fs/jbd-debug".
 
-config FS_MBCACHE
-# Meta block cache for Extended Attributes (ext2/ext3)
+config JBD2
 	tristate
-	depends on EXT2_FS_XATTR || EXT3_FS_XATTR
-	default y if EXT2_FS=y || EXT3_FS=y
-	default m if EXT2_FS=m || EXT3_FS=m
+	help
+	  This is a generic journaling layer for block devices that support
+	  both 32-bit and 64-bit block numbers.  It is currently used by
+	  the ext4dev/ext4 filesystem, but it could also be used to add
+	  journal support to other file systems or block devices such
+	  as RAID or LVM.
+
+	  If you are using ext4dev/ext4, you need to say Y here. If you are not
+	  using ext4dev/ext4 then you will probably want to say N.
+
+	  To compile this device as a module, choose M here. The module will be
+	  called jbd2.  If you are compiling ext4dev/ext4 into the kernel,
+	  you cannot compile this code as a module.
+
+config JBD2_DEBUG
+	bool "JBD2 (ext4dev/ext4) debugging support"
+	depends on JBD2
+	help
+	  If you are using the ext4dev/ext4 journaled file system (or
+	  potentially any other filesystem/device using JBD2), this option
+	  allows you to enable debugging output while the system is running,
+	  in order to help track down any problems you are having.
+	  By default, the debugging output will be turned off.
+
+	  If you select Y here, then you will be able to turn on debugging
+	  with "echo N > /proc/sys/fs/jbd2-debug", where N is a number between
+	  1 and 5. The higher the number, the more debugging output is
+	  generated.  To turn debugging off again, do
+	  "echo 0 > /proc/sys/fs/jbd2-debug".
+
+config FS_MBCACHE
+# Meta block cache for Extended Attributes (ext2/ext3/ext4)
+	tristate
+	depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR
+	default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y
+	default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m
 
 config REISERFS_FS
 	tristate "Reiserfs support"
@@ -535,6 +634,10 @@
 	  If you want to develop a userspace FS, or if you want to use
 	  a filesystem based on FUSE, answer Y or M.
 
+config GENERIC_ACL
+	bool
+	select FS_POSIX_ACL
+
 if BLOCK
 menu "CD-ROM/DVD Filesystems"
 
@@ -1887,7 +1990,7 @@
 config CIFS_UPCALL
 	  bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
 	  depends on CIFS_EXPERIMENTAL
-	  select CONNECTOR
+	  depends on CONNECTOR
 	  help
 	    Enables an upcall mechanism for CIFS which will be used to contact
 	    userspace helper utilities to provide SPNEGO packaged Kerberos
@@ -1981,10 +2084,6 @@
 
 	  If unsure, say N.
 
-config GENERIC_ACL
-	bool
-	select FS_POSIX_ACL
-
 endmenu
 
 if BLOCK
diff --git a/fs/Makefile b/fs/Makefile
index df614ea..9a5ce93 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -62,7 +62,9 @@
 # Do not add any filesystems before this line
 obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
 obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before ext2 so root fs can be ext3
+obj-$(CONFIG_EXT4DEV_FS)	+= ext4/ # Before ext2 so root fs can be ext4dev
 obj-$(CONFIG_JBD)		+= jbd/
+obj-$(CONFIG_JBD2)		+= jbd2/
 obj-$(CONFIG_EXT2_FS)		+= ext2/
 obj-$(CONFIG_CRAMFS)		+= cramfs/
 obj-$(CONFIG_RAMFS)		+= ramfs/
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index cf8a2cb..a6ec75c 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -211,8 +211,8 @@
 {
 	_enter("{%lu}", inode->i_ino);
 
-	BUG_ON(sizeof(union afs_dir_block) != 2048);
-	BUG_ON(sizeof(union afs_dirent) != 32);
+	BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
+	BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
 
 	if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED)
 		return -ENOENT;
@@ -446,8 +446,8 @@
 	_enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name);
 
 	/* insanity checks first */
-	BUG_ON(sizeof(union afs_dir_block) != 2048);
-	BUG_ON(sizeof(union afs_dirent) != 32);
+	BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
+	BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
 
 	if (dentry->d_name.len > 255) {
 		_leave(" = -ENAMETOOLONG");
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index c7700d9..906ba5c 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -149,6 +149,7 @@
 /* Initializing function */
 
 int autofs_fill_super(struct super_block *, void *, int);
+void autofs_kill_sb(struct super_block *sb);
 
 /* Queue management functions */
 
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c
index 3fded38..bf8c8af 100644
--- a/fs/autofs/dirhash.c
+++ b/fs/autofs/dirhash.c
@@ -246,5 +246,4 @@
 			kfree(ent);
 		}
 	}
-	shrink_dcache_sb(sbi->sb);
 }
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index aca1237..cea5219 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -24,7 +24,7 @@
 	.owner		= THIS_MODULE,
 	.name		= "autofs",
 	.get_sb		= autofs_get_sb,
-	.kill_sb	= kill_anon_super,
+	.kill_sb	= autofs_kill_sb,
 };
 
 static int __init init_autofs_fs(void)
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 2c9759b..54c518c 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -20,7 +20,7 @@
 #include "autofs_i.h"
 #include <linux/module.h>
 
-static void autofs_put_super(struct super_block *sb)
+void autofs_kill_sb(struct super_block *sb)
 {
 	struct autofs_sb_info *sbi = autofs_sbi(sb);
 	unsigned int n;
@@ -37,13 +37,13 @@
 	kfree(sb->s_fs_info);
 
 	DPRINTK(("autofs: shutting down\n"));
+	kill_anon_super(sb);
 }
 
 static void autofs_read_inode(struct inode *inode);
 
 static struct super_operations autofs_sops = {
 	.read_inode	= autofs_read_inode,
-	.put_super	= autofs_put_super,
 	.statfs		= simple_statfs,
 };
 
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 480ab17..b13f32c 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -94,7 +94,6 @@
 
 struct autofs_sb_info {
 	u32 magic;
-	struct dentry *root;
 	int pipefd;
 	struct file *pipe;
 	pid_t oz_pgrp;
@@ -229,4 +228,4 @@
 }
 
 void autofs4_dentry_release(struct dentry *);
-
+extern void autofs4_kill_sb(struct super_block *);
diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c
index 5d91933..723a1c5e 100644
--- a/fs/autofs4/init.c
+++ b/fs/autofs4/init.c
@@ -24,7 +24,7 @@
 	.owner		= THIS_MODULE,
 	.name		= "autofs",
 	.get_sb		= autofs_get_sb,
-	.kill_sb	= kill_anon_super,
+	.kill_sb	= autofs4_kill_sb,
 };
 
 static int __init init_autofs4_fs(void)
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 800ce87..51fd859 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -96,7 +96,7 @@
  */
 static void autofs4_force_release(struct autofs_sb_info *sbi)
 {
-	struct dentry *this_parent = sbi->root;
+	struct dentry *this_parent = sbi->sb->s_root;
 	struct list_head *next;
 
 	spin_lock(&dcache_lock);
@@ -127,7 +127,7 @@
 		spin_lock(&dcache_lock);
 	}
 
-	if (this_parent != sbi->root) {
+	if (this_parent != sbi->sb->s_root) {
 		struct dentry *dentry = this_parent;
 
 		next = this_parent->d_u.d_child.next;
@@ -140,15 +140,9 @@
 		goto resume;
 	}
 	spin_unlock(&dcache_lock);
-
-	dput(sbi->root);
-	sbi->root = NULL;
-	shrink_dcache_sb(sbi->sb);
-
-	return;
 }
 
-static void autofs4_put_super(struct super_block *sb)
+void autofs4_kill_sb(struct super_block *sb)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(sb);
 
@@ -163,6 +157,7 @@
 	kfree(sbi);
 
 	DPRINTK("shutting down");
+	kill_anon_super(sb);
 }
 
 static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
@@ -189,7 +184,6 @@
 }
 
 static struct super_operations autofs4_sops = {
-	.put_super	= autofs4_put_super,
 	.statfs		= simple_statfs,
 	.show_options	= autofs4_show_options,
 };
@@ -315,7 +309,6 @@
 
 	s->s_fs_info = sbi;
 	sbi->magic = AUTOFS_SBI_MAGIC;
-	sbi->root = NULL;
 	sbi->pipefd = -1;
 	sbi->catatonic = 0;
 	sbi->exp_timeout = 0;
@@ -397,13 +390,6 @@
 	sbi->pipefd = pipefd;
 
 	/*
-	 * Take a reference to the root dentry so we get a chance to
-	 * clean up the dentry tree on umount.
-	 * See autofs4_force_release.
-	 */
-	sbi->root = dget(root);
-
-	/*
 	 * Success! Install the root dentry now to indicate completion.
 	 */
 	s->s_root = root;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index ce103e7..c0a6c8d 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -45,7 +45,6 @@
 		fput(sbi->pipe);	/* Close the pipe */
 		sbi->pipe = NULL;
 	}
-	shrink_dcache_sb(sbi->sb);
 }
 
 static int autofs4_write(struct file *file, const void *addr, int bytes)
diff --git a/fs/befs/befs.h b/fs/befs/befs.h
index 057a2c3..d9a40ab 100644
--- a/fs/befs/befs.h
+++ b/fs/befs/befs.h
@@ -94,7 +94,7 @@
 
 void befs_dump_super_block(const struct super_block *sb, befs_super_block *);
 void befs_dump_inode(const struct super_block *sb, befs_inode *);
-void befs_dump_index_entry(const struct super_block *sb, befs_btree_super *);
+void befs_dump_index_entry(const struct super_block *sb, befs_disk_btree_super *);
 void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
 /****************************/
 
@@ -136,7 +136,7 @@
 static inline unsigned int
 befs_iaddrs_per_block(struct super_block *sb)
 {
-	return BEFS_SB(sb)->block_size / sizeof (befs_inode_addr);
+	return BEFS_SB(sb)->block_size / sizeof (befs_disk_inode_addr);
 }
 
 static inline int
@@ -151,4 +151,6 @@
 	return BEFS_SB(sb)->block_size * run.len;
 }
 
+#include "endian.h"
+
 #endif				/* _LINUX_BEFS_H */
diff --git a/fs/befs/befs_fs_types.h b/fs/befs/befs_fs_types.h
index 63ef1e1..e2595c2 100644
--- a/fs/befs/befs_fs_types.h
+++ b/fs/befs/befs_fs_types.h
@@ -79,17 +79,27 @@
  * On-Disk datastructures of BeFS
  */
 
+typedef u64 __bitwise fs64;
+typedef u32 __bitwise fs32;
+typedef u16 __bitwise fs16;
+
 typedef u64 befs_off_t;
-typedef u64 befs_time_t;
-typedef void befs_binode_etc;
+typedef fs64 befs_time_t;
 
 /* Block runs */
 typedef struct {
+	fs32 allocation_group;
+	fs16 start;
+	fs16 len;
+} PACKED befs_disk_block_run;
+
+typedef struct {
 	u32 allocation_group;
 	u16 start;
 	u16 len;
 } PACKED befs_block_run;
 
+typedef befs_disk_block_run befs_disk_inode_addr;
 typedef befs_block_run befs_inode_addr;
 
 /*
@@ -97,31 +107,31 @@
  */
 typedef struct {
 	char name[B_OS_NAME_LENGTH];
-	u32 magic1;
-	u32 fs_byte_order;
+	fs32 magic1;
+	fs32 fs_byte_order;
 
-	u32 block_size;
-	u32 block_shift;
+	fs32 block_size;
+	fs32 block_shift;
 
-	befs_off_t num_blocks;
-	befs_off_t used_blocks;
+	fs64 num_blocks;
+	fs64 used_blocks;
 
-	u32 inode_size;
+	fs32 inode_size;
 
-	u32 magic2;
-	u32 blocks_per_ag;
-	u32 ag_shift;
-	u32 num_ags;
+	fs32 magic2;
+	fs32 blocks_per_ag;
+	fs32 ag_shift;
+	fs32 num_ags;
 
-	u32 flags;
+	fs32 flags;
 
-	befs_block_run log_blocks;
-	befs_off_t log_start;
-	befs_off_t log_end;
+	befs_disk_block_run log_blocks;
+	fs64 log_start;
+	fs64 log_end;
 
-	u32 magic3;
-	befs_inode_addr root_dir;
-	befs_inode_addr indices;
+	fs32 magic3;
+	befs_disk_inode_addr root_dir;
+	befs_disk_inode_addr indices;
 
 } PACKED befs_super_block;
 
@@ -130,6 +140,16 @@
  * be longer than one block!
  */
 typedef struct {
+	befs_disk_block_run direct[BEFS_NUM_DIRECT_BLOCKS];
+	fs64 max_direct_range;
+	befs_disk_block_run indirect;
+	fs64 max_indirect_range;
+	befs_disk_block_run double_indirect;
+	fs64 max_double_indirect_range;
+	fs64 size;
+} PACKED befs_disk_data_stream;
+
+typedef struct {
 	befs_block_run direct[BEFS_NUM_DIRECT_BLOCKS];
 	befs_off_t max_direct_range;
 	befs_block_run indirect;
@@ -141,35 +161,35 @@
 
 /* Attribute */
 typedef struct {
-	u32 type;
-	u16 name_size;
-	u16 data_size;
+	fs32 type;
+	fs16 name_size;
+	fs16 data_size;
 	char name[1];
 } PACKED befs_small_data;
 
 /* Inode structure */
 typedef struct {
-	u32 magic1;
-	befs_inode_addr inode_num;
-	u32 uid;
-	u32 gid;
-	u32 mode;
-	u32 flags;
+	fs32 magic1;
+	befs_disk_inode_addr inode_num;
+	fs32 uid;
+	fs32 gid;
+	fs32 mode;
+	fs32 flags;
 	befs_time_t create_time;
 	befs_time_t last_modified_time;
-	befs_inode_addr parent;
-	befs_inode_addr attributes;
-	u32 type;
+	befs_disk_inode_addr parent;
+	befs_disk_inode_addr attributes;
+	fs32 type;
 
-	u32 inode_size;
-	u32 etc;		/* not use */
+	fs32 inode_size;
+	fs32 etc;		/* not use */
 
 	union {
-		befs_data_stream datastream;
+		befs_disk_data_stream datastream;
 		char symlink[BEFS_SYMLINK_LEN];
 	} data;
 
-	u32 pad[4];		/* not use */
+	fs32 pad[4];		/* not use */
 	befs_small_data small_data[1];
 } PACKED befs_inode;
 
@@ -190,6 +210,16 @@
 };
 
 typedef struct {
+	fs32 magic;
+	fs32 node_size;
+	fs32 max_depth;
+	fs32 data_type;
+	fs64 root_node_ptr;
+	fs64 free_node_ptr;
+	fs64 max_size;
+} PACKED befs_disk_btree_super;
+
+typedef struct {
 	u32 magic;
 	u32 node_size;
 	u32 max_depth;
@@ -203,11 +233,19 @@
  * Header stucture of each btree node
  */
 typedef struct {
+	fs64 left;
+	fs64 right;
+	fs64 overflow;
+	fs16 all_key_count;
+	fs16 all_key_length;
+} PACKED befs_btree_nodehead;
+
+typedef struct {
 	befs_off_t left;
 	befs_off_t right;
 	befs_off_t overflow;
 	u16 all_key_count;
 	u16 all_key_length;
-} PACKED befs_btree_nodehead;
+} PACKED befs_host_btree_nodehead;
 
 #endif				/* _LINUX_BEFS_FS_TYPES */
diff --git a/fs/befs/btree.c b/fs/befs/btree.c
index 76e2197..81b042e 100644
--- a/fs/befs/btree.c
+++ b/fs/befs/btree.c
@@ -30,7 +30,6 @@
 #include "befs.h"
 #include "btree.h"
 #include "datastream.h"
-#include "endian.h"
 
 /*
  * The btree functions in this file are built on top of the
@@ -80,7 +79,7 @@
  * In memory structure of each btree node
  */
 typedef struct {
-	befs_btree_nodehead head;	/* head of node converted to cpu byteorder */
+	befs_host_btree_nodehead head;	/* head of node converted to cpu byteorder */
 	struct buffer_head *bh;
 	befs_btree_nodehead *od_node;	/* on disk node */
 } befs_btree_node;
@@ -102,9 +101,9 @@
 
 static int befs_leafnode(befs_btree_node * node);
 
-static u16 *befs_bt_keylen_index(befs_btree_node * node);
+static fs16 *befs_bt_keylen_index(befs_btree_node * node);
 
-static befs_off_t *befs_bt_valarray(befs_btree_node * node);
+static fs64 *befs_bt_valarray(befs_btree_node * node);
 
 static char *befs_bt_keydata(befs_btree_node * node);
 
@@ -136,7 +135,7 @@
 		   befs_btree_super * sup)
 {
 	struct buffer_head *bh = NULL;
-	befs_btree_super *od_sup = NULL;
+	befs_disk_btree_super *od_sup = NULL;
 
 	befs_debug(sb, "---> befs_btree_read_super()");
 
@@ -146,7 +145,7 @@
 		befs_error(sb, "Couldn't read index header.");
 		goto error;
 	}
-	od_sup = (befs_btree_super *) bh->b_data;
+	od_sup = (befs_disk_btree_super *) bh->b_data;
 	befs_dump_index_entry(sb, od_sup);
 
 	sup->magic = fs32_to_cpu(sb, od_sup->magic);
@@ -342,7 +341,7 @@
 	u16 keylen;
 	int findkey_len;
 	char *thiskey;
-	befs_off_t *valarray;
+	fs64 *valarray;
 
 	befs_debug(sb, "---> befs_find_key() %s", findkey);
 
@@ -422,7 +421,7 @@
 	befs_btree_super bt_super;
 	befs_off_t node_off = 0;
 	int cur_key;
-	befs_off_t *valarray;
+	fs64 *valarray;
 	char *keystart;
 	u16 keylen;
 	int res;
@@ -572,7 +571,7 @@
 				   this_node->head.overflow);
 			*node_off = this_node->head.overflow;
 		} else {
-			befs_off_t *valarray = befs_bt_valarray(this_node);
+			fs64 *valarray = befs_bt_valarray(this_node);
 			*node_off = fs64_to_cpu(sb, valarray[0]);
 		}
 		if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) {
@@ -622,7 +621,7 @@
  *
  * Except that rounding up to 8 works, and rounding up to 4 doesn't.
  */
-static u16 *
+static fs16 *
 befs_bt_keylen_index(befs_btree_node * node)
 {
 	const int keylen_align = 8;
@@ -633,7 +632,7 @@
 	if (tmp)
 		off += keylen_align - tmp;
 
-	return (u16 *) ((void *) node->od_node + off);
+	return (fs16 *) ((void *) node->od_node + off);
 }
 
 /**
@@ -643,13 +642,13 @@
  * Returns a pointer to the start of the value array
  * of the node pointed to by the node header
  */
-static befs_off_t *
+static fs64 *
 befs_bt_valarray(befs_btree_node * node)
 {
 	void *keylen_index_start = (void *) befs_bt_keylen_index(node);
-	size_t keylen_index_size = node->head.all_key_count * sizeof (u16);
+	size_t keylen_index_size = node->head.all_key_count * sizeof (fs16);
 
-	return (befs_off_t *) (keylen_index_start + keylen_index_size);
+	return (fs64 *) (keylen_index_start + keylen_index_size);
 }
 
 /**
@@ -681,7 +680,7 @@
 {
 	int prev_key_end;
 	char *keystart;
-	u16 *keylen_index;
+	fs16 *keylen_index;
 
 	if (index < 0 || index > node->head.all_key_count) {
 		*keylen = 0;
diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c
index b7d6b92..aacb4da 100644
--- a/fs/befs/datastream.c
+++ b/fs/befs/datastream.c
@@ -18,7 +18,6 @@
 #include "befs.h"
 #include "datastream.h"
 #include "io.h"
-#include "endian.h"
 
 const befs_inode_addr BAD_IADDR = { 0, 0, 0 };
 
@@ -312,7 +311,7 @@
 	befs_blocknr_t indir_start_blk;
 	befs_blocknr_t search_blk;
 	struct buffer_head *indirblock;
-	befs_block_run *array;
+	befs_disk_block_run *array;
 
 	befs_block_run indirect = data->indirect;
 	befs_blocknr_t indirblockno = iaddr2blockno(sb, &indirect);
@@ -334,7 +333,7 @@
 			return BEFS_ERR;
 		}
 
-		array = (befs_block_run *) indirblock->b_data;
+		array = (befs_disk_block_run *) indirblock->b_data;
 
 		for (j = 0; j < arraylen; ++j) {
 			int len = fs16_to_cpu(sb, array[j].len);
@@ -427,7 +426,7 @@
 	struct buffer_head *dbl_indir_block;
 	struct buffer_head *indir_block;
 	befs_block_run indir_run;
-	befs_inode_addr *iaddr_array = NULL;
+	befs_disk_inode_addr *iaddr_array = NULL;
 	befs_sb_info *befs_sb = BEFS_SB(sb);
 
 	befs_blocknr_t indir_start_blk =
@@ -482,7 +481,7 @@
 
 	dbl_block_indx =
 	    dblindir_indx - (dbl_which_block * befs_iaddrs_per_block(sb));
-	iaddr_array = (befs_inode_addr *) dbl_indir_block->b_data;
+	iaddr_array = (befs_disk_inode_addr *) dbl_indir_block->b_data;
 	indir_run = fsrun_to_cpu(sb, iaddr_array[dbl_block_indx]);
 	brelse(dbl_indir_block);
 	iaddr_array = NULL;
@@ -507,7 +506,7 @@
 	}
 
 	block_indx = indir_indx - (which_block * befs_iaddrs_per_block(sb));
-	iaddr_array = (befs_inode_addr *) indir_block->b_data;
+	iaddr_array = (befs_disk_inode_addr *) indir_block->b_data;
 	*run = fsrun_to_cpu(sb, iaddr_array[block_indx]);
 	brelse(indir_block);
 	iaddr_array = NULL;
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index 875cc0a..e831a8f 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -21,7 +21,6 @@
 #endif				/* __KERNEL__ */
 
 #include "befs.h"
-#include "endian.h"
 
 #define ERRBUFSIZE 1024
 
@@ -125,7 +124,7 @@
 	befs_debug(sb, "  type %08x", fs32_to_cpu(sb, inode->type));
 	befs_debug(sb, "  inode_size %u", fs32_to_cpu(sb, inode->inode_size));
 
-	if (S_ISLNK(inode->mode)) {
+	if (S_ISLNK(fs32_to_cpu(sb, inode->mode))) {
 		befs_debug(sb, "  Symbolic link [%s]", inode->data.symlink);
 	} else {
 		int i;
@@ -231,21 +230,20 @@
 
 /* unused */
 void
-befs_dump_run(const struct super_block *sb, befs_block_run run)
+befs_dump_run(const struct super_block *sb, befs_disk_block_run run)
 {
 #ifdef CONFIG_BEFS_DEBUG
 
-	run = fsrun_to_cpu(sb, run);
+	befs_block_run n = fsrun_to_cpu(sb, run);
 
-	befs_debug(sb, "[%u, %hu, %hu]",
-		   run.allocation_group, run.start, run.len);
+	befs_debug(sb, "[%u, %hu, %hu]", n.allocation_group, n.start, n.len);
 
 #endif				//CONFIG_BEFS_DEBUG
 }
 #endif  /*  0  */
 
 void
-befs_dump_index_entry(const struct super_block *sb, befs_btree_super * super)
+befs_dump_index_entry(const struct super_block *sb, befs_disk_btree_super * super)
 {
 #ifdef CONFIG_BEFS_DEBUG
 
diff --git a/fs/befs/endian.h b/fs/befs/endian.h
index 9ecaea4..e254a20 100644
--- a/fs/befs/endian.h
+++ b/fs/befs/endian.h
@@ -10,85 +10,84 @@
 #define LINUX_BEFS_ENDIAN
 
 #include <linux/byteorder/generic.h>
-#include "befs.h"
 
 static inline u64
-fs64_to_cpu(const struct super_block *sb, u64 n)
+fs64_to_cpu(const struct super_block *sb, fs64 n)
 {
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
-		return le64_to_cpu(n);
+		return le64_to_cpu((__force __le64)n);
 	else
-		return be64_to_cpu(n);
+		return be64_to_cpu((__force __be64)n);
 }
 
-static inline u64
+static inline fs64
 cpu_to_fs64(const struct super_block *sb, u64 n)
 {
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
-		return cpu_to_le64(n);
+		return (__force fs64)cpu_to_le64(n);
 	else
-		return cpu_to_be64(n);
+		return (__force fs64)cpu_to_be64(n);
 }
 
 static inline u32
-fs32_to_cpu(const struct super_block *sb, u32 n)
+fs32_to_cpu(const struct super_block *sb, fs32 n)
 {
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
-		return le32_to_cpu(n);
+		return le32_to_cpu((__force __le32)n);
 	else
-		return be32_to_cpu(n);
+		return be32_to_cpu((__force __be32)n);
 }
 
-static inline u32
+static inline fs32
 cpu_to_fs32(const struct super_block *sb, u32 n)
 {
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
-		return cpu_to_le32(n);
+		return (__force fs32)cpu_to_le32(n);
 	else
-		return cpu_to_be32(n);
+		return (__force fs32)cpu_to_be32(n);
 }
 
 static inline u16
-fs16_to_cpu(const struct super_block *sb, u16 n)
+fs16_to_cpu(const struct super_block *sb, fs16 n)
 {
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
-		return le16_to_cpu(n);
+		return le16_to_cpu((__force __le16)n);
 	else
-		return be16_to_cpu(n);
+		return be16_to_cpu((__force __be16)n);
 }
 
-static inline u16
+static inline fs16
 cpu_to_fs16(const struct super_block *sb, u16 n)
 {
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
-		return cpu_to_le16(n);
+		return (__force fs16)cpu_to_le16(n);
 	else
-		return cpu_to_be16(n);
+		return (__force fs16)cpu_to_be16(n);
 }
 
 /* Composite types below here */
 
 static inline befs_block_run
-fsrun_to_cpu(const struct super_block *sb, befs_block_run n)
+fsrun_to_cpu(const struct super_block *sb, befs_disk_block_run n)
 {
 	befs_block_run run;
 
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE) {
-		run.allocation_group = le32_to_cpu(n.allocation_group);
-		run.start = le16_to_cpu(n.start);
-		run.len = le16_to_cpu(n.len);
+		run.allocation_group = le32_to_cpu((__force __le32)n.allocation_group);
+		run.start = le16_to_cpu((__force __le16)n.start);
+		run.len = le16_to_cpu((__force __le16)n.len);
 	} else {
-		run.allocation_group = be32_to_cpu(n.allocation_group);
-		run.start = be16_to_cpu(n.start);
-		run.len = be16_to_cpu(n.len);
+		run.allocation_group = be32_to_cpu((__force __be32)n.allocation_group);
+		run.start = be16_to_cpu((__force __be16)n.start);
+		run.len = be16_to_cpu((__force __be16)n.len);
 	}
 	return run;
 }
 
-static inline befs_block_run
+static inline befs_disk_block_run
 cpu_to_fsrun(const struct super_block *sb, befs_block_run n)
 {
-	befs_block_run run;
+	befs_disk_block_run run;
 
 	if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE) {
 		run.allocation_group = cpu_to_le32(n.allocation_group);
@@ -103,7 +102,7 @@
 }
 
 static inline befs_data_stream
-fsds_to_cpu(const struct super_block *sb, befs_data_stream n)
+fsds_to_cpu(const struct super_block *sb, befs_disk_data_stream n)
 {
 	befs_data_stream data;
 	int i;
diff --git a/fs/befs/inode.c b/fs/befs/inode.c
index d41c924..94c17f9 100644
--- a/fs/befs/inode.c
+++ b/fs/befs/inode.c
@@ -8,7 +8,6 @@
 
 #include "befs.h"
 #include "inode.h"
-#include "endian.h"
 
 /*
 	Validates the correctness of the befs inode
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 57020c7..07f7144 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -22,7 +22,6 @@
 #include "datastream.h"
 #include "super.h"
 #include "io.h"
-#include "endian.h"
 
 MODULE_DESCRIPTION("BeOS File System (BeFS) driver");
 MODULE_AUTHOR("Will Dyson");
diff --git a/fs/befs/super.c b/fs/befs/super.c
index 4557acb..8c3401f 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -11,7 +11,6 @@
 
 #include "befs.h"
 #include "super.h"
-#include "endian.h"
 
 /**
  * load_befs_sb -- Read from disk and properly byteswap all the fields
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 06435f3..79b05a1 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1152,7 +1152,7 @@
 static int dump_seek(struct file *file, loff_t off)
 {
 	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
-		if (file->f_op->llseek(file, off, 1) != off)
+		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
 			return 0;
 	} else {
 		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
@@ -1220,7 +1220,7 @@
 
 static int alignfile(struct file *file, loff_t *foffset)
 {
-	char buf[4] = { 0, };
+	static const char buf[4] = { 0, };
 	DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
 	return 1;
 }
@@ -1569,7 +1569,8 @@
 
 	DUMP_WRITE(elf, sizeof(*elf));
 	offset += sizeof(*elf);				/* Elf header */
-	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
+	offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */
+	foffset = offset;
 
 	/* Write notes phdr entry */
 	{
@@ -1586,8 +1587,6 @@
 		DUMP_WRITE(&phdr, sizeof(phdr));
 	}
 
-	foffset = offset;
-
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
 	/* Write program headers for segments dump */
@@ -1612,7 +1611,6 @@
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
 		DUMP_WRITE(&phdr, sizeof(phdr));
-		foffset += sizeof(phdr);
 	}
 
 #ifdef ELF_CORE_WRITE_EXTRA_PHDRS
diff --git a/fs/bio.c b/fs/bio.c
index 8f93e93..f95c874 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -79,7 +79,6 @@
 static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
 {
 	struct bio_vec *bvl;
-	struct biovec_slab *bp;
 
 	/*
 	 * see comment near bvec_array define!
@@ -98,10 +97,12 @@
 	 * idx now points to the pool we want to allocate from
 	 */
 
-	bp = bvec_slabs + *idx;
 	bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
-	if (bvl)
+	if (bvl) {
+		struct biovec_slab *bp = bvec_slabs + *idx;
+
 		memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
+	}
 
 	return bvl;
 }
@@ -166,7 +167,7 @@
 
 		bio_init(bio);
 		if (likely(nr_iovecs)) {
-			unsigned long idx;
+			unsigned long idx = 0; /* shut up gcc */
 
 			bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
 			if (unlikely(!bvl)) {
diff --git a/fs/buffer.c b/fs/buffer.c
index 16cfbcd..35527dc 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -452,6 +452,7 @@
 			       bdevname(bh->b_bdev, b));
 		}
 		set_bit(AS_EIO, &page->mapping->flags);
+		set_buffer_write_io_error(bh);
 		clear_buffer_uptodate(bh);
 		SetPageError(page);
 	}
@@ -571,6 +572,10 @@
 static inline void __remove_assoc_queue(struct buffer_head *bh)
 {
 	list_del_init(&bh->b_assoc_buffers);
+	WARN_ON(!bh->b_assoc_map);
+	if (buffer_write_io_error(bh))
+		set_bit(AS_EIO, &bh->b_assoc_map->flags);
+	bh->b_assoc_map = NULL;
 }
 
 int inode_has_buffers(struct inode *inode)
@@ -669,6 +674,7 @@
 		spin_lock(&buffer_mapping->private_lock);
 		list_move_tail(&bh->b_assoc_buffers,
 				&mapping->private_list);
+		bh->b_assoc_map = mapping;
 		spin_unlock(&buffer_mapping->private_lock);
 	}
 }
@@ -701,7 +707,10 @@
  */
 int __set_page_dirty_buffers(struct page *page)
 {
-	struct address_space * const mapping = page->mapping;
+	struct address_space * const mapping = page_mapping(page);
+
+	if (unlikely(!mapping))
+		return !TestSetPageDirty(page);
 
 	spin_lock(&mapping->private_lock);
 	if (page_has_buffers(page)) {
@@ -762,7 +771,7 @@
 	spin_lock(lock);
 	while (!list_empty(list)) {
 		bh = BH_ENTRY(list->next);
-		list_del_init(&bh->b_assoc_buffers);
+		__remove_assoc_queue(bh);
 		if (buffer_dirty(bh) || buffer_locked(bh)) {
 			list_add(&bh->b_assoc_buffers, &tmp);
 			if (buffer_dirty(bh)) {
@@ -783,7 +792,7 @@
 
 	while (!list_empty(&tmp)) {
 		bh = BH_ENTRY(tmp.prev);
-		__remove_assoc_queue(bh);
+		list_del_init(&bh->b_assoc_buffers);
 		get_bh(bh);
 		spin_unlock(lock);
 		wait_on_buffer(bh);
@@ -1039,8 +1048,21 @@
 	} while ((size << sizebits) < PAGE_SIZE);
 
 	index = block >> sizebits;
-	block = index << sizebits;
 
+	/*
+	 * Check for a block which wants to lie outside our maximum possible
+	 * pagecache index.  (this comparison is done using sector_t types).
+	 */
+	if (unlikely(index != block >> sizebits)) {
+		char b[BDEVNAME_SIZE];
+
+		printk(KERN_ERR "%s: requested out-of-range block %llu for "
+			"device %s\n",
+			__FUNCTION__, (unsigned long long)block,
+			bdevname(bdev, b));
+		return -EIO;
+	}
+	block = index << sizebits;
 	/* Create a page with the proper size buffers.. */
 	page = grow_dev_page(bdev, block, index, size);
 	if (!page)
@@ -1067,12 +1089,16 @@
 
 	for (;;) {
 		struct buffer_head * bh;
+		int ret;
 
 		bh = __find_get_block(bdev, block, size);
 		if (bh)
 			return bh;
 
-		if (!grow_buffers(bdev, block, size))
+		ret = grow_buffers(bdev, block, size);
+		if (ret < 0)
+			return NULL;
+		if (ret == 0)
 			free_more_memory();
 	}
 }
@@ -1147,6 +1173,7 @@
 
 		spin_lock(&buffer_mapping->private_lock);
 		list_del_init(&bh->b_assoc_buffers);
+		bh->b_assoc_map = NULL;
 		spin_unlock(&buffer_mapping->private_lock);
 	}
 	__brelse(bh);
@@ -1834,6 +1861,7 @@
 			clear_buffer_new(bh);
 			kaddr = kmap_atomic(page, KM_USER0);
 			memset(kaddr+block_start, 0, bh->b_size);
+			flush_dcache_page(page);
 			kunmap_atomic(kaddr, KM_USER0);
 			set_buffer_uptodate(bh);
 			mark_buffer_dirty(bh);
@@ -2340,6 +2368,7 @@
 	 */
 	kaddr = kmap_atomic(page, KM_USER0);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
+	flush_dcache_page(page);
 	kunmap_atomic(kaddr, KM_USER0);
 	SetPageUptodate(page);
 	set_page_dirty(page);
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index d0776ac..5eff35d 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -31,8 +31,8 @@
 } __attribute__((packed));
 
 /* everyone */
-extern const struct cifs_sid sid_everyone;
+/* extern const struct cifs_sid sid_everyone;*/
 /* group users */
-extern const struct cifs_sid sid_user;
+/* extern const struct cifs_sid sid_user;*/
 
 #endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
index 03e359b..152fa2d 100644
--- a/fs/cifs/cifsencrypt.h
+++ b/fs/cifs/cifsencrypt.h
@@ -27,8 +27,6 @@
 /* smbdes.c */
 extern void E_P16(unsigned char *p14, unsigned char *p16);
 extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
-extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
-extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *);
 
 
 
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c00c654..84976cd 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -63,6 +63,7 @@
 struct task_struct * oplockThread = NULL;
 extern struct task_struct * dnotifyThread; /* remove sparse warning */
 struct task_struct * dnotifyThread = NULL;
+static struct super_operations cifs_super_ops; 
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
 module_param(CIFSMaxBufSize, int, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -198,10 +199,12 @@
     /* Only need to call the old QFSInfo if failed
     on newer one */
     if(rc)
-	rc = CIFSSMBQFSInfo(xid, pTcon, buf);
+	if(pTcon->ses->capabilities & CAP_NT_SMBS)
+		rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
 
-	/* Old Windows servers do not support level 103, retry with level 
-	   one if old server failed the previous call */ 
+	/* Some old Windows servers also do not support level 103, retry with
+	   older level one if old server failed the previous call or we
+	   bypassed it because we detected that this was an older LANMAN sess */
 	if(rc)
 		rc = SMBOldQFSInfo(xid, pTcon, buf);
 	/*     
@@ -435,13 +438,21 @@
 	return;
 }
 
+#ifdef CONFIG_CIFS_STATS2
+static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
+{
+	/* BB FIXME */
+	return 0;
+}
+#endif
+
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
 	*flags |= MS_NODIRATIME;
 	return 0;
 }
 
-struct super_operations cifs_super_ops = {
+static struct super_operations cifs_super_ops = {
 	.read_inode = cifs_read_inode,
 	.put_super = cifs_put_super,
 	.statfs = cifs_statfs,
@@ -454,6 +465,9 @@
 	.show_options = cifs_show_options,
 	.umount_begin   = cifs_umount_begin,
 	.remount_fs = cifs_remount,
+#ifdef CONFIG_CIFS_STATS2
+	.show_stats = cifs_show_stats,
+#endif
 };
 
 static int
@@ -495,7 +509,7 @@
 static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 {
 	/* origin == SEEK_END => we must revalidate the cached file length */
-	if (origin == 2) {
+	if (origin == SEEK_END) {
 		int retval = cifs_revalidate(file->f_dentry);
 		if (retval < 0)
 			return (loff_t)retval;
@@ -903,7 +917,7 @@
 #ifdef CONFIG_PROC_FS
 	cifs_proc_init();
 #endif
-	INIT_LIST_HEAD(&GlobalServerList);	/* BB not implemented yet */
+/*	INIT_LIST_HEAD(&GlobalServerList);*/	/* BB not implemented yet */
 	INIT_LIST_HEAD(&GlobalSMBSessionList);
 	INIT_LIST_HEAD(&GlobalTreeConnectionList);
 	INIT_LIST_HEAD(&GlobalOplock_Q);
@@ -931,6 +945,7 @@
 	GlobalCurrentXid = 0;
 	GlobalTotalActiveXid = 0;
 	GlobalMaxActiveXid = 0;
+	memset(Local_System_Name, 0, 15);
 	rwlock_init(&GlobalSMBSeslock);
 	spin_lock_init(&GlobalMid_Lock);
 
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index bea875d..a243f77 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,7 +36,7 @@
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
-extern struct super_operations cifs_super_ops;
+/* extern struct super_operations cifs_super_ops;*/
 extern void cifs_read_inode(struct inode *);
 extern void cifs_delete_inode(struct inode *);
 /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b24006c..74d3ccb 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -153,7 +153,7 @@
 	char sessid[4];		/* unique token id for this session */
 	/* (returned on Negotiate */
 	int capabilities; /* allow selective disabling of caps by smb sess */
-	__u16 timeZone;
+	int timeAdj;  /* Adjust for difference in server time zone in sec */
 	__u16 CurrentMid;         /* multiplex id - rotating counter */
 	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
 	/* 16th byte of RFC1001 workstation name is always null */
@@ -203,9 +203,14 @@
 	char * domainName;
 	char * password;
 };
-/* session flags */
+/* no more than one of the following three session flags may be set */
 #define CIFS_SES_NT4 1
-
+#define CIFS_SES_OS2 2
+#define CIFS_SES_W9X 4
+/* following flag is set for old servers such as OS2 (and Win95?)
+   which do not negotiate NTLM or POSIX dialects, but instead
+   negotiate one of the older LANMAN dialects */
+#define CIFS_SES_LANMAN 8
 /*
  * there is one of these for each connection to a resource on a particular
  * session 
@@ -512,7 +517,8 @@
  * This list helps improve performance and eliminate the messages indicating
  * that we had a communications error talking to the server in this list. 
  */
-GLOBAL_EXTERN struct servers_not_supported *NotSuppList;	/*@z4a */
+/* Feature not supported */
+/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
 
 /*
  * The following is a hash table of all the users we know about.
@@ -568,7 +574,6 @@
 GLOBAL_EXTERN unsigned int extended_security;	/* if on, session setup sent 
 				with more secure ntlmssp2 challenge/resp */
 GLOBAL_EXTERN unsigned int sign_CIFS_PDUs;  /* enable smb packet signing */
-GLOBAL_EXTERN unsigned int secFlags;
 GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
 GLOBAL_EXTERN unsigned int CIFSMaxBufSize;  /* max size not including hdr */
 GLOBAL_EXTERN unsigned int cifs_min_rcv;    /* min size of big ntwrk buf pool */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 81df2bf..6df9dad 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -26,7 +26,8 @@
 
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 #define LANMAN_PROT 0
-#define CIFS_PROT   1
+#define LANMAN2_PROT 1
+#define CIFS_PROT   2
 #else
 #define CIFS_PROT   0
 #endif
@@ -408,6 +409,8 @@
 
 /* Dialect index is 13 for LANMAN */
 
+#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
+
 typedef struct lanman_neg_rsp {
 	struct smb_hdr hdr;	/* wct = 13 */
 	__le16 DialectIndex;
@@ -417,7 +420,10 @@
 	__le16 MaxNumberVcs;
 	__le16 RawMode;
 	__le32 SessionKey;
-	__le32 ServerTime;
+	struct {
+		__le16 Time;
+		__le16 Date;
+	} __attribute__((packed)) SrvTime;
 	__le16 ServerTimeZone;
 	__le16 EncryptionKeyLength;
 	__le16 Reserved;
@@ -674,7 +680,7 @@
 typedef struct smb_com_close_req {
 	struct smb_hdr hdr;	/* wct = 3 */
 	__u16 FileID;
-	__u32 LastWriteTime;	/* should be zero */
+	__u32 LastWriteTime;	/* should be zero or -1 */
 	__u16 ByteCount;	/* 0 */
 } __attribute__((packed)) CLOSE_REQ;
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b35c55c..f1f8225 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,12 +50,12 @@
 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
 			struct kvec *, int /* nvec to send */, 
 			int * /* type of buf returned */ , const int long_op);
-extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
+extern int SendReceiveBlockingLock(const unsigned int /* xid */ , 
+					struct cifsTconInfo *,
 				struct smb_hdr * /* input */ ,
 				struct smb_hdr * /* out */ ,
 				int * /* bytes returned */);
-extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
-extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
+extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
 extern int is_size_safe_to_change(struct cifsInodeInfo *);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
@@ -80,6 +80,9 @@
 extern void DeleteOplockQEntry(struct oplock_q_entry *);
 extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
 extern u64 cifs_UnixTimeToNT(struct timespec);
+extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
+extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
+
 extern int cifs_get_inode_info(struct inode **pinode,
 			const unsigned char *search_path, 
 			FILE_ALL_INFO * pfile_info,
@@ -116,6 +119,7 @@
 extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName,
 			FILE_ALL_INFO * findData,
+			int legacy /* whether to use old info level */,
 			const struct nls_table *nls_codepage, int remap);
 extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
                         const unsigned char *searchName,
@@ -279,8 +283,6 @@
 extern struct cifsTconInfo *tconInfoAlloc(void);
 extern void tconInfoFree(struct cifsTconInfo *);
 
-extern int cifs_reconnect(struct TCP_Server_Info *server);
-
 extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
 extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 075d8fb..098790e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -46,6 +46,7 @@
 } protocols[] = {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 	{LANMAN_PROT, "\2LM1.2X002"},
+	{LANMAN2_PROT, "\2LANMAN2.1"},
 #endif /* weak password hashing for legacy clients */
 	{CIFS_PROT, "\2NT LM 0.12"}, 
 	{POSIX_PROT, "\2POSIX 2"},
@@ -58,6 +59,7 @@
 } protocols[] = {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 	{LANMAN_PROT, "\2LM1.2X002"},
+	{LANMAN2_PROT, "\2LANMAN2.1"},
 #endif /* weak password hashing for legacy clients */
 	{CIFS_PROT, "\2NT LM 0.12"}, 
 	{BAD_PROT, "\2"}
@@ -67,13 +69,13 @@
 /* define the number of elements in the cifs dialect array */
 #ifdef CONFIG_CIFS_POSIX
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
-#define CIFS_NUM_PROT 3
+#define CIFS_NUM_PROT 4
 #else
 #define CIFS_NUM_PROT 2
 #endif /* CIFS_WEAK_PW_HASH */
 #else /* not posix */
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
-#define CIFS_NUM_PROT 2
+#define CIFS_NUM_PROT 3
 #else
 #define CIFS_NUM_PROT 1
 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
@@ -397,6 +399,7 @@
 	struct TCP_Server_Info * server;
 	u16 count;
 	unsigned int secFlags;
+	u16 dialect;
 
 	if(ses->server)
 		server = ses->server;
@@ -436,9 +439,10 @@
 	if (rc != 0) 
 		goto neg_err_exit;
 
-	cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
+	dialect = le16_to_cpu(pSMBr->DialectIndex);
+	cFYI(1,("Dialect: %d", dialect));
 	/* Check wct = 1 error case */
-	if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
+	if((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
 		/* core returns wct = 1, but we do not ask for core - otherwise
 		small wct just comes when dialect index is -1 indicating we 
 		could not negotiate a common dialect */
@@ -446,7 +450,9 @@
 		goto neg_err_exit;
 #ifdef CONFIG_CIFS_WEAK_PW_HASH 
 	} else if((pSMBr->hdr.WordCount == 13)
-			&& (pSMBr->DialectIndex == LANMAN_PROT)) {
+			&& ((dialect == LANMAN_PROT)
+				|| (dialect == LANMAN2_PROT))) {
+		__s16 tmp;
 		struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
 
 		if((secFlags & CIFSSEC_MAY_LANMAN) || 
@@ -472,12 +478,44 @@
 			server->maxRw = 0;/* we do not need to use raw anyway */
 			server->capabilities = CAP_MPX_MODE;
 		}
-		server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
+		tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
+		if (tmp == -1) {
+			/* OS/2 often does not set timezone therefore
+			 * we must use server time to calc time zone.
+			 * Could deviate slightly from the right zone.
+			 * Smallest defined timezone difference is 15 minutes
+			 * (i.e. Nepal).  Rounding up/down is done to match
+			 * this requirement.
+			 */
+			int val, seconds, remain, result;
+			struct timespec ts, utc;
+			utc = CURRENT_TIME;
+			ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
+						le16_to_cpu(rsp->SrvTime.Time));
+			cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
+				(int)ts.tv_sec, (int)utc.tv_sec, 
+				(int)(utc.tv_sec - ts.tv_sec)));
+			val = (int)(utc.tv_sec - ts.tv_sec);
+			seconds = val < 0 ? -val : val;
+			result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
+			remain = seconds % MIN_TZ_ADJ;
+			if(remain >= (MIN_TZ_ADJ / 2))
+				result += MIN_TZ_ADJ;
+			if(val < 0)
+				result = - result;
+			server->timeAdj = result;
+		} else {
+			server->timeAdj = (int)tmp;
+			server->timeAdj *= 60; /* also in seconds */
+		}
+		cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
+
 
 		/* BB get server time for time conversions and add
 		code to use it and timezone since this is not UTC */	
 
-		if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
+		if (rsp->EncryptionKeyLength == 
+				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
 			memcpy(server->cryptKey, rsp->EncryptionKey,
 				CIFS_CRYPTO_KEY_SIZE);
 		} else if (server->secMode & SECMODE_PW_ENCRYPT) {
@@ -531,7 +569,8 @@
 	cFYI(0, ("Max buf = %d", ses->server->maxBuf));
 	GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
 	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
-	server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
+	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
+	server->timeAdj *= 60;
 	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
 		memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
 		       CIFS_CRYPTO_KEY_SIZE);
@@ -1617,7 +1656,7 @@
 	pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
 
 	pSMB->FileID = (__u16) smb_file_id;
-	pSMB->LastWriteTime = 0;
+	pSMB->LastWriteTime = 0xFFFFFFFF;
 	pSMB->ByteCount = 0;
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -2773,9 +2812,11 @@
 
 
 /* security id for everyone */
-const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
+const static struct cifs_sid sid_everyone = 
+		{1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
 /* group users */
-const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
+const static struct cifs_sid sid_user = 
+		{1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
 
 /* Convert CIFS ACL to POSIX form */
 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
@@ -2856,7 +2897,6 @@
 	return rc;
 }
 
-
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -2898,7 +2938,16 @@
 	if (rc) {
 		cFYI(1, ("Send error in QueryInfo = %d", rc));
 	} else if (pFinfo) {            /* decode response */
+		struct timespec ts;
+		__u32 time = le32_to_cpu(pSMBr->last_write_time);
+		/* BB FIXME - add time zone adjustment BB */
 		memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
+		ts.tv_nsec = 0;
+		ts.tv_sec = time;
+		/* decode time fields */
+		pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
+		pFinfo->LastWriteTime = pFinfo->ChangeTime;
+		pFinfo->LastAccessTime = 0;
 		pFinfo->AllocationSize =
 			cpu_to_le64(le32_to_cpu(pSMBr->size));
 		pFinfo->EndOfFile = pFinfo->AllocationSize;
@@ -2922,6 +2971,7 @@
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 		 const unsigned char *searchName,
 		 FILE_ALL_INFO * pFindData,
+		 int legacy /* old style infolevel */,
 		 const struct nls_table *nls_codepage, int remap)
 {
 /* level 263 SMB_QUERY_FILE_ALL_INFO */
@@ -2970,7 +3020,10 @@
 	byte_count = params + 1 /* pad */ ;
 	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
-	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+	if(legacy)
+		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+	else
+		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
 	pSMB->Reserved4 = 0;
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
@@ -2982,13 +3035,24 @@
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
-		if (rc || (pSMBr->ByteCount < 40)) 
+		if (rc) /* BB add auto retry on EOPNOTSUPP? */
+			rc = -EIO;
+		else if (!legacy && (pSMBr->ByteCount < 40)) 
 			rc = -EIO;	/* bad smb */
+		else if(legacy && (pSMBr->ByteCount < 24))
+			rc = -EIO;  /* 24 or 26 expected but we do not read last field */
 		else if (pFindData){
+			int size;
 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			if(legacy) /* we do not read the last field, EAsize, fortunately
+					   since it varies by subdialect and on Set vs. Get, is  
+					   two bytes or 4 bytes depending but we don't care here */
+				size = sizeof(FILE_INFO_STANDARD);
+			else
+				size = sizeof(FILE_ALL_INFO);
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       data_offset, sizeof (FILE_ALL_INFO));
+			       data_offset, size);
 		} else
 		    rc = -ENOMEM;
 	}
@@ -3613,6 +3677,14 @@
 		strncpy(pSMB->RequestFileName, searchName, name_len);
 	}
 
+	if(ses->server) {
+		if(ses->server->secMode &
+		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	}
+
+        pSMB->hdr.Uid = ses->Suid;
+
 	params = 2 /* level */  + name_len /*includes null */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->DataCount = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c787620..4093d53 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -109,7 +109,7 @@
 	 * wake up waiters on reconnection? - (not needed currently)
 	 */
 
-int
+static int
 cifs_reconnect(struct TCP_Server_Info *server)
 {
 	int rc = 0;
@@ -771,13 +771,18 @@
 	separator[0] = ',';
 	separator[1] = 0; 
 
-	memset(vol->source_rfc1001_name,0x20,15);
-	for(i=0;i < strnlen(utsname()->nodename,15);i++) {
-		/* does not have to be a perfect mapping since the field is
-		informational, only used for servers that do not support
-		port 445 and it can be overridden at mount time */
-		vol->source_rfc1001_name[i] = 
-			toupper(utsname()->nodename[i]);
+	if (Local_System_Name[0] != 0)
+		memcpy(vol->source_rfc1001_name, Local_System_Name,15);
+	else {
+		char *nodename = utsname()->nodename;
+		int n = strnlen(nodename,15);
+		memset(vol->source_rfc1001_name,0x20,15);
+		for(i=0 ; i < n ; i++) {
+			/* does not have to be perfect mapping since field is
+			informational, only used for servers that do not support
+			port 445 and it can be overridden at mount time */
+			vol->source_rfc1001_name[i] = toupper(nodename[i]);
+		}
 	}
 	vol->source_rfc1001_name[15] = 0;
 	/* null target name indicates to use *SMBSERVR default called name
@@ -3215,7 +3220,9 @@
 			}
 			/* else do not bother copying these informational fields */
 		}
-		if(smb_buffer_response->WordCount == 3)
+		if((smb_buffer_response->WordCount == 3) ||
+			 (smb_buffer_response->WordCount == 7))
+			/* field is in same location */
 			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
 		else
 			tcon->Flags = 0;
@@ -3312,19 +3319,21 @@
 		first_time = 1;
 	}
 	if (!rc) {
+		pSesInfo->flags = 0;
 		pSesInfo->capabilities = pSesInfo->server->capabilities;
 		if(linuxExtEnabled == 0)
 			pSesInfo->capabilities &= (~CAP_UNIX);
 	/*	pSesInfo->sequence_number = 0;*/
-		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
+		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
 			pSesInfo->server->secMode,
 			pSesInfo->server->capabilities,
-			pSesInfo->server->timeZone));
+			pSesInfo->server->timeAdj));
 		if(experimEnabled < 2)
 			rc = CIFS_SessSetup(xid, pSesInfo,
 					    first_time, nls_info);
 		else if (extended_security
-				&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
+				&& (pSesInfo->capabilities 
+					& CAP_EXTENDED_SECURITY)
 				&& (pSesInfo->server->secType == NTLMSSP)) {
 			rc = -EOPNOTSUPP;
 		} else if (extended_security
@@ -3338,7 +3347,7 @@
 			if (!rc) {
 				if(ntlmv2_flag) {
 					char * v2_response;
-					cFYI(1,("Can use more secure NTLM version 2 password hash"));
+					cFYI(1,("more secure NTLM ver2 hash"));
 					if(CalcNTLMv2_partial_mac_key(pSesInfo, 
 						nls_info)) {
 						rc = -ENOMEM;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 6b90ef9..35d54bb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -337,6 +337,7 @@
 		pfindData = (FILE_ALL_INFO *)buf;
 		/* could do find first instead but this returns more info */
 		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
+			      0 /* not legacy */,
 			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
 		/* BB optimize code so we do not make the above call
@@ -384,8 +385,10 @@
 		/* get new inode */
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
-			if (*pinode == NULL)
+			if (*pinode == NULL) {
+				kfree(buf);
 				return -ENOMEM;
+			}
 			/* Is an i_ino of zero legal? Can we use that to check
 			   if the server supports returning inode numbers?  Are
 			   there other sanity checks we can use to ensure that
@@ -431,8 +434,11 @@
 		(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
 
 		/* Linux can not store file creation time so ignore it */
-		inode->i_atime =
-		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+		if(pfindData->LastAccessTime)
+			inode->i_atime = cifs_NTtimeToUnix
+				(le64_to_cpu(pfindData->LastAccessTime));
+		else /* do not need to use current_fs_time - time not stored */
+			inode->i_atime = CURRENT_TIME;
 		inode->i_mtime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
 		inode->i_ctime =
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index a57f5d6..0bee8b7 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -254,7 +254,11 @@
 				tmpbuffer,
 				len - 1,
 				cifs_sb->local_nls);
-	else {
+	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+		cERROR(1,("SFU style symlinks not implemented yet"));
+		/* add open and read as in fs/cifs/inode.c */
+	
+	} else {
 		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
 				OPEN_REPARSE_POINT,&fid, &oplock, NULL, 
 				cifs_sb->local_nls, 
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
index 7aa2349..ccebf9b 100644
--- a/fs/cifs/md5.c
+++ b/fs/cifs/md5.c
@@ -252,10 +252,11 @@
 	buf[3] += d;
 }
 
+#if 0   /* currently unused */
 /***********************************************************************
  the rfc 2104 version of hmac_md5 initialisation.
 ***********************************************************************/
-void
+static void
 hmac_md5_init_rfc2104(unsigned char *key, int key_len,
 		      struct HMACMD5Context *ctx)
 {
@@ -289,6 +290,7 @@
 	MD5Init(&ctx->ctx);
 	MD5Update(&ctx->ctx, ctx->k_ipad, 64);
 }
+#endif
 
 /***********************************************************************
  the microsoft version of hmac_md5 initialisation.
@@ -350,7 +352,8 @@
  single function to calculate an HMAC MD5 digest from data.
  use the microsoft hmacmd5 init method because the key is 16 bytes.
 ************************************************************/
-void
+#if 0 /* currently unused */
+static void
 hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
 	 unsigned char *digest)
 {
@@ -361,3 +364,4 @@
 	}
 	hmac_md5_final(digest, &ctx);
 }
+#endif
diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h
index 00e1c53..f7d4f41 100644
--- a/fs/cifs/md5.h
+++ b/fs/cifs/md5.h
@@ -27,12 +27,12 @@
 
 /* The following definitions come from lib/hmacmd5.c  */
 
-void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
-			struct HMACMD5Context *ctx);
+/* void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
+			struct HMACMD5Context *ctx);*/
 void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
 			struct HMACMD5Context *ctx);
 void hmac_md5_update(const unsigned char *text, int text_len,
 			struct HMACMD5Context *ctx);
 void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
-void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
-			unsigned char *digest);
+/* void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
+			unsigned char *digest);*/
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 22c937e..bbc9cd3 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -389,7 +389,7 @@
 	return;
 }
 
-int
+static int
 checkSMBhdr(struct smb_hdr *smb, __u16 mid)
 {
 	/* Make sure that this really is an SMB, that it is a response, 
@@ -418,26 +418,42 @@
 }
 
 int
-checkSMB(struct smb_hdr *smb, __u16 mid, int length)
+checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
 {
 	__u32 len = smb->smb_buf_length;
 	__u32 clc_len;  /* calculated length */
 	cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
-	if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
-	    (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
-		if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
-			if (((unsigned int)length >= 
-				sizeof (struct smb_hdr) - 1)
+
+	if (length < 2 + sizeof (struct smb_hdr)) {
+		if ((length >= sizeof (struct smb_hdr) - 1)
 			    && (smb->Status.CifsError != 0)) {
-				smb->WordCount = 0;
-				/* some error cases do not return wct and bcc */
+			smb->WordCount = 0;
+			/* some error cases do not return wct and bcc */
+			return 0;
+		} else if ((length == sizeof(struct smb_hdr) + 1) && 
+				(smb->WordCount == 0)) {
+			char * tmp = (char *)smb;
+			/* Need to work around a bug in two servers here */
+			/* First, check if the part of bcc they sent was zero */
+			if (tmp[sizeof(struct smb_hdr)] == 0) {
+				/* some servers return only half of bcc
+				 * on simple responses (wct, bcc both zero)
+				 * in particular have seen this on
+				 * ulogoffX and FindClose. This leaves
+				 * one byte of bcc potentially unitialized
+				 */
+				/* zero rest of bcc */
+				tmp[sizeof(struct smb_hdr)+1] = 0;
 				return 0;
-			} else {
-				cERROR(1, ("Length less than smb header size"));
 			}
+			cERROR(1,("rcvd invalid byte count (bcc)"));
+		} else {
+			cERROR(1, ("Length less than smb header size"));
 		}
-		if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
-			cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
+		return 1;
+	}
+	if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
 				   smb->Mid));
 		return 1;
 	}
@@ -446,7 +462,7 @@
 		return 1;
 	clc_len = smbCalcSize_LE(smb);
 
-	if(4 + len != (unsigned int)length) {
+	if(4 + len != length) {
 		cERROR(1, ("Length read does not match RFC1001 length %d",len));
 		return 1;
 	}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index ce87550..992e80e 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -909,3 +909,61 @@
 	/* Convert to 100ns intervals and then add the NTFS time offset. */
 	return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
 }
+
+static int total_days_of_prev_months[] =
+{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+
+__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
+{
+	return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
+}
+
+struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
+{
+	struct timespec ts;
+	int sec, min, days, month, year;
+	SMB_TIME * st = (SMB_TIME *)&time;
+	SMB_DATE * sd = (SMB_DATE *)&date;
+
+	cFYI(1,("date %d time %d",date, time));
+
+	sec = 2 * st->TwoSeconds;
+	min = st->Minutes;
+	if((sec > 59) || (min > 59))
+		cERROR(1,("illegal time min %d sec %d", min, sec));
+	sec += (min * 60);
+	sec += 60 * 60 * st->Hours;
+	if(st->Hours > 24)
+		cERROR(1,("illegal hours %d",st->Hours));
+	days = sd->Day;
+	month = sd->Month;
+	if((days > 31) || (month > 12))
+		cERROR(1,("illegal date, month %d day: %d", month, days));
+	month -= 1;
+	days += total_days_of_prev_months[month];
+	days += 3652; /* account for difference in days between 1980 and 1970 */
+	year = sd->Year;
+	days += year * 365;
+	days += (year/4); /* leap year */
+	/* generalized leap year calculation is more complex, ie no leap year
+	for years/100 except for years/400, but since the maximum number for DOS
+	 year is 2**7, the last year is 1980+127, which means we need only
+	 consider 2 special case years, ie the years 2000 and 2100, and only
+	 adjust for the lack of leap year for the year 2100, as 2000 was a 
+	 leap year (divisable by 400) */
+	if(year >= 120)  /* the year 2100 */
+		days = days - 1;  /* do not count leap year for the year 2100 */
+
+	/* adjust for leap year where we are still before leap day */
+	if(year != 120)
+		days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
+	sec += 24 * 60 * 60 * days; 
+
+	ts.tv_sec = sec;
+
+	/* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
+
+	ts.tv_nsec = 0;
+	return ts;
+} 
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b27b345..b5b0a2a 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -106,6 +106,17 @@
 	return rc;
 }
 
+static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
+{
+	if((tcon) && (tcon->ses) && (tcon->ses->server)) {
+		inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
+		inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
+		inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
+	}
+	return;
+}
+
+
 static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 		char * buf, int *pobject_type, int isNewInode)
 {
@@ -135,16 +146,23 @@
 		tmp_inode->i_ctime =
 		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
 	} else { /* legacy, OS2 and DOS style */
+/*		struct timespec ts;*/
 		FIND_FILE_STANDARD_INFO * pfindData = 
 			(FIND_FILE_STANDARD_INFO *)buf;
 
+		tmp_inode->i_mtime = cnvrtDosUnixTm(
+				le16_to_cpu(pfindData->LastWriteDate),
+				le16_to_cpu(pfindData->LastWriteTime));
+		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));
+		AdjustForTZ(cifs_sb->tcon, tmp_inode);
 		attr = le16_to_cpu(pfindData->Attributes);
 		allocation_size = le32_to_cpu(pfindData->AllocationSize);
 		end_of_file = le32_to_cpu(pfindData->DataSize);
-		tmp_inode->i_atime = CURRENT_TIME;
-		/* tmp_inode->i_mtime =  BB FIXME - add dos time handling
-		tmp_inode->i_ctime = 0;   BB FIXME */
-
 	}
 
 	/* Linux can not store file creation time unfortunately so ignore it */
@@ -938,6 +956,7 @@
 		filename = &pFindData->FileName[0];
 		/* one byte length, no name conversion */
 		len = (unsigned int)pFindData->FileNameLength;
+		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
 	} else {
 		cFYI(1,("Unknown findfirst level %d",level));
 		return -EINVAL;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 22b4c35..a8a0835 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -268,6 +268,10 @@
 	ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
 	if(ses->serverOS)
 		strncpy(ses->serverOS, bcc_ptr, len);
+	if(strncmp(ses->serverOS, "OS/2",4) == 0) {
+			cFYI(1,("OS/2 server"));
+			ses->flags |= CIFS_SES_OS2;
+	}
 
 	bcc_ptr += len + 1;
 	bleft -= len + 1;
@@ -290,16 +294,11 @@
         if(len > bleft)
                 return rc;
 
-        if(ses->serverDomain)
-                kfree(ses->serverDomain);
-
-        ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
-        if(ses->serverOS)
-                strncpy(ses->serverOS, bcc_ptr, len);
-
-        bcc_ptr += len + 1;
-	bleft -= len + 1;
-
+	/* No domain field in LANMAN case. Domain is
+	   returned by old servers in the SMB negprot response */
+	/* BB For newer servers which do not support Unicode,
+	   but thus do return domain here we could add parsing
+	   for it later, but it is not very important */
 	cFYI(1,("ascii: bytes left %d",bleft));
 
 	return rc;
@@ -366,6 +365,8 @@
 	str_area = kmalloc(2000, GFP_KERNEL);
 	bcc_ptr = str_area;
 
+	ses->flags &= ~CIFS_SES_LANMAN;
+
 	if(type == LANMAN) {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 		char lnm_session_key[CIFS_SESS_KEY_SIZE];
@@ -377,7 +378,7 @@
 		/* and copy into bcc */
 
 		calc_lanman_hash(ses, lnm_session_key);
-
+		ses->flags |= CIFS_SES_LANMAN; 
 /* #ifdef CONFIG_CIFS_DEBUG2
 		cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
 			CIFS_SESS_KEY_SIZE);
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index efaa044..7a1b2b9 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -364,20 +364,20 @@
 	smbhash(p24 + 16, c8, p21 + 14, 1);
 }
 
-void
+#if 0 /* currently unsued */
+static void
 D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
 {
 	smbhash(out, in, p14, 0);
 	smbhash(out + 8, in + 8, p14 + 7, 0);
 }
 
-void
+static void
 E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
 {
 	smbhash(out, in, p14, 1);
 	smbhash(out + 8, in + 8, p14 + 7, 1);
 }
-#if 0
 /* these routines are currently unneeded, but may be
 	needed later */
 void
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index f518c5e..4b25ba9 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -51,11 +51,8 @@
 
 void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
 void E_md4hash(const unsigned char *passwd, unsigned char *p16);
-void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
 static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
 		   unsigned char p24[24]);
-void NTLMSSPOWFencrypt(unsigned char passwd[8],
-		       unsigned char *ntlmchalresp, unsigned char p24[24]);
 void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
 
 /*
@@ -144,8 +141,9 @@
 	memset(wpwd,0,129 * 2);
 }
 
+#if 0 /* currently unused */
 /* Does both the NT and LM owfs of a user's password */
-void
+static void
 nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
 {
 	char passwd[514];
@@ -171,6 +169,7 @@
 	/* clear out local copy of user's password (just being paranoid). */
 	memset(passwd, '\0', sizeof (passwd));
 }
+#endif
 
 /* Does the NTLMv2 owfs of a user's password */
 #if 0  /* function not needed yet - but will be soon */
@@ -223,7 +222,8 @@
 }
 
 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
-void
+#if 0 /* currently unused */
+static void
 NTLMSSPOWFencrypt(unsigned char passwd[8],
 		  unsigned char *ntlmchalresp, unsigned char p24[24])
 {
@@ -235,6 +235,7 @@
 
 	E_P24(p21, ntlmchalresp, p24);
 }
+#endif
 
 /* Does the NT MD4 hash then des encryption. */
 
diff --git a/fs/compat.c b/fs/compat.c
index 4d3fbcb..50624d4 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1316,7 +1316,7 @@
 		    unsigned int nr_segs, unsigned int flags)
 {
 	unsigned i;
-	struct iovec *iov;
+	struct iovec __user *iov;
 	if (nr_segs > UIO_MAXIOV)
 		return -EINVAL;
 	iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 27ca1aa..a91f262 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -2438,13 +2438,17 @@
 HANDLE_IOCTL(BLKFRAGET, w_long)
 HANDLE_IOCTL(BLKSECTGET, w_long)
 HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
 HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_WCACHE, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_ACOUSTIC, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_ADDRESS, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_BUSSTATE, hdio_ioctl_trans)
 HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans)
 HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans)
 HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans)
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index e6d5754..cf33fac 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -275,13 +275,14 @@
 	 * it in file->private_data for easy access.
 	 */
 	buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
-	if (buffer) {
-		init_MUTEX(&buffer->sem);
-		buffer->needs_read_fill = 1;
-		buffer->ops = ops;
-		file->private_data = buffer;
-	} else
+	if (!buffer) {
 		error = -ENOMEM;
+		goto Enomem;
+	}
+	init_MUTEX(&buffer->sem);
+	buffer->needs_read_fill = 1;
+	buffer->ops = ops;
+	file->private_data = buffer;
 	goto Done;
 
  Einval:
@@ -289,6 +290,7 @@
 	goto Done;
  Eaccess:
 	error = -EACCES;
+ Enomem:
 	module_put(attr->ca_owner);
  Done:
 	if (error && item)
diff --git a/fs/dcache.c b/fs/dcache.c
index 2355bdd..a1ff91e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -549,6 +549,136 @@
 }
 
 /*
+ * destroy a single subtree of dentries for unmount
+ * - see the comments on shrink_dcache_for_umount() for a description of the
+ *   locking
+ */
+static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
+{
+	struct dentry *parent;
+
+	BUG_ON(!IS_ROOT(dentry));
+
+	/* detach this root from the system */
+	spin_lock(&dcache_lock);
+	if (!list_empty(&dentry->d_lru)) {
+		dentry_stat.nr_unused--;
+		list_del_init(&dentry->d_lru);
+	}
+	__d_drop(dentry);
+	spin_unlock(&dcache_lock);
+
+	for (;;) {
+		/* descend to the first leaf in the current subtree */
+		while (!list_empty(&dentry->d_subdirs)) {
+			struct dentry *loop;
+
+			/* this is a branch with children - detach all of them
+			 * from the system in one go */
+			spin_lock(&dcache_lock);
+			list_for_each_entry(loop, &dentry->d_subdirs,
+					    d_u.d_child) {
+				if (!list_empty(&loop->d_lru)) {
+					dentry_stat.nr_unused--;
+					list_del_init(&loop->d_lru);
+				}
+
+				__d_drop(loop);
+				cond_resched_lock(&dcache_lock);
+			}
+			spin_unlock(&dcache_lock);
+
+			/* move to the first child */
+			dentry = list_entry(dentry->d_subdirs.next,
+					    struct dentry, d_u.d_child);
+		}
+
+		/* consume the dentries from this leaf up through its parents
+		 * until we find one with children or run out altogether */
+		do {
+			struct inode *inode;
+
+			if (atomic_read(&dentry->d_count) != 0) {
+				printk(KERN_ERR
+				       "BUG: Dentry %p{i=%lx,n=%s}"
+				       " still in use (%d)"
+				       " [unmount of %s %s]\n",
+				       dentry,
+				       dentry->d_inode ?
+				       dentry->d_inode->i_ino : 0UL,
+				       dentry->d_name.name,
+				       atomic_read(&dentry->d_count),
+				       dentry->d_sb->s_type->name,
+				       dentry->d_sb->s_id);
+				BUG();
+			}
+
+			parent = dentry->d_parent;
+			if (parent == dentry)
+				parent = NULL;
+			else
+				atomic_dec(&parent->d_count);
+
+			list_del(&dentry->d_u.d_child);
+			dentry_stat.nr_dentry--;	/* For d_free, below */
+
+			inode = dentry->d_inode;
+			if (inode) {
+				dentry->d_inode = NULL;
+				list_del_init(&dentry->d_alias);
+				if (dentry->d_op && dentry->d_op->d_iput)
+					dentry->d_op->d_iput(dentry, inode);
+				else
+					iput(inode);
+			}
+
+			d_free(dentry);
+
+			/* finished when we fall off the top of the tree,
+			 * otherwise we ascend to the parent and move to the
+			 * next sibling if there is one */
+			if (!parent)
+				return;
+
+			dentry = parent;
+
+		} while (list_empty(&dentry->d_subdirs));
+
+		dentry = list_entry(dentry->d_subdirs.next,
+				    struct dentry, d_u.d_child);
+	}
+}
+
+/*
+ * destroy the dentries attached to a superblock on unmounting
+ * - we don't need to use dentry->d_lock, and only need dcache_lock when
+ *   removing the dentry from the system lists and hashes because:
+ *   - the superblock is detached from all mountings and open files, so the
+ *     dentry trees will not be rearranged by the VFS
+ *   - s_umount is write-locked, so the memory pressure shrinker will ignore
+ *     any dentries belonging to this superblock that it comes across
+ *   - the filesystem itself is no longer permitted to rearrange the dentries
+ *     in this superblock
+ */
+void shrink_dcache_for_umount(struct super_block *sb)
+{
+	struct dentry *dentry;
+
+	if (down_read_trylock(&sb->s_umount))
+		BUG();
+
+	dentry = sb->s_root;
+	sb->s_root = NULL;
+	atomic_dec(&dentry->d_count);
+	shrink_dcache_for_umount_subtree(dentry);
+
+	while (!hlist_empty(&sb->s_anon)) {
+		dentry = hlist_entry(sb->s_anon.first, struct dentry, d_hash);
+		shrink_dcache_for_umount_subtree(dentry);
+	}
+}
+
+/*
  * Search for at least 1 mount point in the dentry's subdirs.
  * We descend to the next level whenever the d_subdirs
  * list is non-empty and continue searching.
@@ -1339,23 +1469,21 @@
  * deleted it.
  */
  
-/**
- * d_move - move a dentry
+/*
+ * d_move_locked - move a dentry
  * @dentry: entry to move
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
  * dcache entries should not be moved in this way.
  */
-
-void d_move(struct dentry * dentry, struct dentry * target)
+static void d_move_locked(struct dentry * dentry, struct dentry * target)
 {
 	struct hlist_head *list;
 
 	if (!dentry->d_inode)
 		printk(KERN_WARNING "VFS: moving negative dcache entry\n");
 
-	spin_lock(&dcache_lock);
 	write_seqlock(&rename_lock);
 	/*
 	 * XXXX: do we really need to take target->d_lock?
@@ -1406,10 +1534,84 @@
 	fsnotify_d_move(dentry);
 	spin_unlock(&dentry->d_lock);
 	write_sequnlock(&rename_lock);
+}
+
+/**
+ * d_move - move a dentry
+ * @dentry: entry to move
+ * @target: new dentry
+ *
+ * Update the dcache to reflect the move of a file name. Negative
+ * dcache entries should not be moved in this way.
+ */
+
+void d_move(struct dentry * dentry, struct dentry * target)
+{
+	spin_lock(&dcache_lock);
+	d_move_locked(dentry, target);
 	spin_unlock(&dcache_lock);
 }
 
 /*
+ * Helper that returns 1 if p1 is a parent of p2, else 0
+ */
+static int d_isparent(struct dentry *p1, struct dentry *p2)
+{
+	struct dentry *p;
+
+	for (p = p2; p->d_parent != p; p = p->d_parent) {
+		if (p->d_parent == p1)
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * This helper attempts to cope with remotely renamed directories
+ *
+ * It assumes that the caller is already holding
+ * dentry->d_parent->d_inode->i_mutex and the dcache_lock
+ *
+ * Note: If ever the locking in lock_rename() changes, then please
+ * remember to update this too...
+ *
+ * On return, dcache_lock will have been unlocked.
+ */
+static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)
+{
+	struct mutex *m1 = NULL, *m2 = NULL;
+	struct dentry *ret;
+
+	/* If alias and dentry share a parent, then no extra locks required */
+	if (alias->d_parent == dentry->d_parent)
+		goto out_unalias;
+
+	/* Check for loops */
+	ret = ERR_PTR(-ELOOP);
+	if (d_isparent(alias, dentry))
+		goto out_err;
+
+	/* See lock_rename() */
+	ret = ERR_PTR(-EBUSY);
+	if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
+		goto out_err;
+	m1 = &dentry->d_sb->s_vfs_rename_mutex;
+	if (!mutex_trylock(&alias->d_parent->d_inode->i_mutex))
+		goto out_err;
+	m2 = &alias->d_parent->d_inode->i_mutex;
+out_unalias:
+	d_move_locked(alias, dentry);
+	ret = alias;
+out_err:
+	spin_unlock(&dcache_lock);
+	if (m2)
+		mutex_unlock(m2);
+	if (m1)
+		mutex_unlock(m1);
+	return ret;
+}
+
+/*
  * Prepare an anonymous dentry for life in the superblock's dentry tree as a
  * named dentry in place of the dentry to be replaced.
  */
@@ -1451,7 +1653,7 @@
  */
 struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
 {
-	struct dentry *alias, *actual;
+	struct dentry *actual;
 
 	BUG_ON(!d_unhashed(dentry));
 
@@ -1463,26 +1665,27 @@
 		goto found_lock;
 	}
 
-	/* See if a disconnected directory already exists as an anonymous root
-	 * that we should splice into the tree instead */
-	if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) {
-		spin_lock(&alias->d_lock);
+	if (S_ISDIR(inode->i_mode)) {
+		struct dentry *alias;
 
-		/* Is this a mountpoint that we could splice into our tree? */
-		if (IS_ROOT(alias))
-			goto connect_mountpoint;
-
-		if (alias->d_name.len == dentry->d_name.len &&
-		    alias->d_parent == dentry->d_parent &&
-		    memcmp(alias->d_name.name,
-			   dentry->d_name.name,
-			   dentry->d_name.len) == 0)
-			goto replace_with_alias;
-
-		spin_unlock(&alias->d_lock);
-
-		/* Doh! Seem to be aliasing directories for some reason... */
-		dput(alias);
+		/* Does an aliased dentry already exist? */
+		alias = __d_find_alias(inode, 0);
+		if (alias) {
+			actual = alias;
+			/* Is this an anonymous mountpoint that we could splice
+			 * into our tree? */
+			if (IS_ROOT(alias)) {
+				spin_lock(&alias->d_lock);
+				__d_materialise_dentry(dentry, alias);
+				__d_drop(alias);
+				goto found;
+			}
+			/* Nope, but we must(!) avoid directory aliasing */
+			actual = __d_unalias(dentry, alias);
+			if (IS_ERR(actual))
+				dput(alias);
+			goto out_nolock;
+		}
 	}
 
 	/* Add a unique reference */
@@ -1498,7 +1701,7 @@
 	_d_rehash(actual);
 	spin_unlock(&actual->d_lock);
 	spin_unlock(&dcache_lock);
-
+out_nolock:
 	if (actual == dentry) {
 		security_d_instantiate(dentry, inode);
 		return NULL;
@@ -1507,16 +1710,6 @@
 	iput(inode);
 	return actual;
 
-	/* Convert the anonymous/root alias into an ordinary dentry */
-connect_mountpoint:
-	__d_materialise_dentry(dentry, alias);
-
-	/* Replace the candidate dentry with the alias in the tree */
-replace_with_alias:
-	__d_drop(alias);
-	actual = alias;
-	goto found;
-
 shouldnt_be_hashed:
 	spin_unlock(&dcache_lock);
 	BUG();
diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig
index 490f85b..81b2c64 100644
--- a/fs/dlm/Kconfig
+++ b/fs/dlm/Kconfig
@@ -1,10 +1,9 @@
 menu "Distributed Lock Manager"
-	depends on INET && EXPERIMENTAL
+	depends on INET && IP_SCTP && EXPERIMENTAL
 
 config DLM
 	tristate "Distributed Lock Manager (DLM)"
 	depends on IPV6 || IPV6=n
-	depends on IP_SCTP
 	select CONFIGFS_FS
 	help
 	A general purpose distributed lock manager for kernel or userspace
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 23f5ce1..6da6b14 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -174,7 +174,7 @@
 	return 0;
 }
 
-static struct nodeinfo *nodeid2nodeinfo(int nodeid, int alloc)
+static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc)
 {
 	struct nodeinfo *ni;
 	int r;
@@ -519,6 +519,7 @@
 	msg.msg_flags = 0;
 	msg.msg_control = incmsg;
 	msg.msg_controllen = sizeof(incmsg);
+	msg.msg_iovlen = 1;
 
 	/* I don't see why this circular buffer stuff is necessary for SCTP
 	 * which is a packet-based protocol, but the whole thing breaks under
@@ -548,7 +549,7 @@
 	}
 	len = iov[0].iov_len + iov[1].iov_len;
 
-	r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, 1, len,
+	r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, msg.msg_iovlen, len,
 				 MSG_NOSIGNAL | MSG_DONTWAIT);
 	if (ret <= 0)
 		goto out_close;
@@ -726,7 +727,7 @@
 }
 
 
-static struct writequeue_entry *new_writequeue_entry(int allocation)
+static struct writequeue_entry *new_writequeue_entry(gfp_t allocation)
 {
 	struct writequeue_entry *entry;
 
@@ -748,7 +749,7 @@
 	return entry;
 }
 
-void *dlm_lowcomms_get_buffer(int nodeid, int len, int allocation, char **ppc)
+void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 {
 	struct writequeue_entry *e;
 	int offset = 0;
diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h
index 6c04bb09..2d045e0 100644
--- a/fs/dlm/lowcomms.h
+++ b/fs/dlm/lowcomms.h
@@ -19,7 +19,7 @@
 int dlm_lowcomms_start(void);
 void dlm_lowcomms_stop(void);
 int dlm_lowcomms_close(int nodeid);
-void *dlm_lowcomms_get_buffer(int nodeid, int len, int allocation, char **ppc);
+void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc);
 void dlm_lowcomms_commit_buffer(void *mh);
 
 #endif				/* __LOWCOMMS_DOT_H__ */
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 7a11b8a..5938a23 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -104,10 +104,7 @@
 		inode->i_op = &ecryptfs_dir_iops;
 	if (S_ISDIR(lower_inode->i_mode))
 		inode->i_fop = &ecryptfs_dir_fops;
-	/* TODO: Is there a better way to identify if the inode is
-	 * special? */
-	if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
-	    S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
+	if (special_file(lower_inode->i_mode))
 		init_special_inode(inode, lower_inode->i_mode,
 				   lower_inode->i_rdev);
 	dentry->d_op = &ecryptfs_dops;
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 557d5b6..ae228ec 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -105,6 +105,8 @@
 /* Maximum msec timeout value storeable in a long int */
 #define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ)
 
+#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
+
 
 struct epoll_filefd {
 	struct file *file;
@@ -497,7 +499,7 @@
  */
 asmlinkage long sys_epoll_create(int size)
 {
-	int error, fd;
+	int error, fd = -1;
 	struct eventpoll *ep;
 	struct inode *inode;
 	struct file *file;
@@ -640,7 +642,6 @@
 	return error;
 }
 
-#define MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
 
 /*
  * Implement the event wait interface for the eventpoll file. It is the kernel
@@ -657,7 +658,7 @@
 		     current, epfd, events, maxevents, timeout));
 
 	/* The maximum number of event must be greater than zero */
-	if (maxevents <= 0 || maxevents > MAX_EVENTS)
+	if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
 		return -EINVAL;
 
 	/* Verify that the area passed by the user is writeable */
@@ -699,6 +700,55 @@
 }
 
 
+#ifdef TIF_RESTORE_SIGMASK
+
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_pwait(2).
+ */
+asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
+		int maxevents, int timeout, const sigset_t __user *sigmask,
+		size_t sigsetsize)
+{
+	int error;
+	sigset_t ksigmask, sigsaved;
+
+	/*
+	 * If the caller wants a certain signal mask to be set during the wait,
+	 * we apply it here.
+	 */
+	if (sigmask) {
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+	/*
+	 * If we changed the signal mask, we need to restore the original one.
+	 * In case we've got a signal while waiting, we do not restore the
+	 * signal mask yet, and we allow do_signal() to deliver the signal on
+	 * the way back to userspace, before the signal mask is restored.
+	 */
+	if (sigmask) {
+		if (error == -EINTR) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+				sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		} else
+			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+	}
+
+	return error;
+}
+
+#endif /* #ifdef TIF_RESTORE_SIGMASK */
+
+
 /*
  * Creates the file descriptor to be used by the epoll interface.
  */
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 513cd42..d8b9abd 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -364,7 +364,6 @@
 {
 	char * p;
 	substring_t args[MAX_OPT_ARGS];
-	unsigned long kind = EXT2_MOUNT_ERRORS_CONT;
 	int option;
 
 	if (!options)
@@ -404,13 +403,19 @@
 			/* *sb_block = match_int(&args[0]); */
 			break;
 		case Opt_err_panic:
-			kind = EXT2_MOUNT_ERRORS_PANIC;
+			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+			clear_opt (sbi->s_mount_opt, ERRORS_RO);
+			set_opt (sbi->s_mount_opt, ERRORS_PANIC);
 			break;
 		case Opt_err_ro:
-			kind = EXT2_MOUNT_ERRORS_RO;
+			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+			set_opt (sbi->s_mount_opt, ERRORS_RO);
 			break;
 		case Opt_err_cont:
-			kind = EXT2_MOUNT_ERRORS_CONT;
+			clear_opt (sbi->s_mount_opt, ERRORS_RO);
+			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+			set_opt (sbi->s_mount_opt, ERRORS_CONT);
 			break;
 		case Opt_nouid32:
 			set_opt (sbi->s_mount_opt, NO_UID32);
@@ -489,7 +494,6 @@
 			return 0;
 		}
 	}
-	sbi->s_mount_opt |= kind;
 	return 1;
 }
 
@@ -715,6 +719,8 @@
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
 	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_RO)
 		set_opt(sbi->s_mount_opt, ERRORS_RO);
+	else
+		set_opt(sbi->s_mount_opt, ERRORS_CONT);
 
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 8bfd56e..afc2d4f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1470,6 +1470,8 @@
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
 	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_RO)
 		set_opt(sbi->s_mount_opt, ERRORS_RO);
+	else
+		set_opt(sbi->s_mount_opt, ERRORS_CONT);
 
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
new file mode 100644
index 0000000..a6acb96
--- /dev/null
+++ b/fs/ext4/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux ext4-filesystem routines.
+#
+
+obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o
+
+ext4dev-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+	   ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o
+
+ext4dev-$(CONFIG_EXT4DEV_FS_XATTR)	+= xattr.o xattr_user.o xattr_trusted.o
+ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL)	+= acl.o
+ext4dev-$(CONFIG_EXT4DEV_FS_SECURITY)	+= xattr_security.o
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
new file mode 100644
index 0000000..9e88254
--- /dev/null
+++ b/fs/ext4/acl.c
@@ -0,0 +1,551 @@
+/*
+ * linux/fs/ext4/acl.c
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/ext4_fs.h>
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Convert from filesystem to in-memory representation.
+ */
+static struct posix_acl *
+ext4_acl_from_disk(const void *value, size_t size)
+{
+	const char *end = (char *)value + size;
+	int n, count;
+	struct posix_acl *acl;
+
+	if (!value)
+		return NULL;
+	if (size < sizeof(ext4_acl_header))
+		 return ERR_PTR(-EINVAL);
+	if (((ext4_acl_header *)value)->a_version !=
+	    cpu_to_le32(EXT4_ACL_VERSION))
+		return ERR_PTR(-EINVAL);
+	value = (char *)value + sizeof(ext4_acl_header);
+	count = ext4_acl_count(size);
+	if (count < 0)
+		return ERR_PTR(-EINVAL);
+	if (count == 0)
+		return NULL;
+	acl = posix_acl_alloc(count, GFP_KERNEL);
+	if (!acl)
+		return ERR_PTR(-ENOMEM);
+	for (n=0; n < count; n++) {
+		ext4_acl_entry *entry =
+			(ext4_acl_entry *)value;
+		if ((char *)value + sizeof(ext4_acl_entry_short) > end)
+			goto fail;
+		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
+		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
+		switch(acl->a_entries[n].e_tag) {
+			case ACL_USER_OBJ:
+			case ACL_GROUP_OBJ:
+			case ACL_MASK:
+			case ACL_OTHER:
+				value = (char *)value +
+					sizeof(ext4_acl_entry_short);
+				acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
+				break;
+
+			case ACL_USER:
+			case ACL_GROUP:
+				value = (char *)value + sizeof(ext4_acl_entry);
+				if ((char *)value > end)
+					goto fail;
+				acl->a_entries[n].e_id =
+					le32_to_cpu(entry->e_id);
+				break;
+
+			default:
+				goto fail;
+		}
+	}
+	if (value != end)
+		goto fail;
+	return acl;
+
+fail:
+	posix_acl_release(acl);
+	return ERR_PTR(-EINVAL);
+}
+
+/*
+ * Convert from in-memory to filesystem representation.
+ */
+static void *
+ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
+{
+	ext4_acl_header *ext_acl;
+	char *e;
+	size_t n;
+
+	*size = ext4_acl_size(acl->a_count);
+	ext_acl = kmalloc(sizeof(ext4_acl_header) + acl->a_count *
+			sizeof(ext4_acl_entry), GFP_KERNEL);
+	if (!ext_acl)
+		return ERR_PTR(-ENOMEM);
+	ext_acl->a_version = cpu_to_le32(EXT4_ACL_VERSION);
+	e = (char *)ext_acl + sizeof(ext4_acl_header);
+	for (n=0; n < acl->a_count; n++) {
+		ext4_acl_entry *entry = (ext4_acl_entry *)e;
+		entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
+		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
+		switch(acl->a_entries[n].e_tag) {
+			case ACL_USER:
+			case ACL_GROUP:
+				entry->e_id =
+					cpu_to_le32(acl->a_entries[n].e_id);
+				e += sizeof(ext4_acl_entry);
+				break;
+
+			case ACL_USER_OBJ:
+			case ACL_GROUP_OBJ:
+			case ACL_MASK:
+			case ACL_OTHER:
+				e += sizeof(ext4_acl_entry_short);
+				break;
+
+			default:
+				goto fail;
+		}
+	}
+	return (char *)ext_acl;
+
+fail:
+	kfree(ext_acl);
+	return ERR_PTR(-EINVAL);
+}
+
+static inline struct posix_acl *
+ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+	struct posix_acl *acl = EXT4_ACL_NOT_CACHED;
+
+	spin_lock(&inode->i_lock);
+	if (*i_acl != EXT4_ACL_NOT_CACHED)
+		acl = posix_acl_dup(*i_acl);
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
+static inline void
+ext4_iset_acl(struct inode *inode, struct posix_acl **i_acl,
+		struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	if (*i_acl != EXT4_ACL_NOT_CACHED)
+		posix_acl_release(*i_acl);
+	*i_acl = posix_acl_dup(acl);
+	spin_unlock(&inode->i_lock);
+}
+
+/*
+ * Inode operation get_posix_acl().
+ *
+ * inode->i_mutex: don't care
+ */
+static struct posix_acl *
+ext4_get_acl(struct inode *inode, int type)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	int name_index;
+	char *value = NULL;
+	struct posix_acl *acl;
+	int retval;
+
+	if (!test_opt(inode->i_sb, POSIX_ACL))
+		return NULL;
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			acl = ext4_iget_acl(inode, &ei->i_acl);
+			if (acl != EXT4_ACL_NOT_CACHED)
+				return acl;
+			name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			acl = ext4_iget_acl(inode, &ei->i_default_acl);
+			if (acl != EXT4_ACL_NOT_CACHED)
+				return acl;
+			name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
+			break;
+
+		default:
+			return ERR_PTR(-EINVAL);
+	}
+	retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
+	if (retval > 0) {
+		value = kmalloc(retval, GFP_KERNEL);
+		if (!value)
+			return ERR_PTR(-ENOMEM);
+		retval = ext4_xattr_get(inode, name_index, "", value, retval);
+	}
+	if (retval > 0)
+		acl = ext4_acl_from_disk(value, retval);
+	else if (retval == -ENODATA || retval == -ENOSYS)
+		acl = NULL;
+	else
+		acl = ERR_PTR(retval);
+	kfree(value);
+
+	if (!IS_ERR(acl)) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ext4_iset_acl(inode, &ei->i_acl, acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ext4_iset_acl(inode, &ei->i_default_acl, acl);
+				break;
+		}
+	}
+	return acl;
+}
+
+/*
+ * Set the access or default ACL of an inode.
+ *
+ * inode->i_mutex: down unless called from ext4_new_inode
+ */
+static int
+ext4_set_acl(handle_t *handle, struct inode *inode, int type,
+	     struct posix_acl *acl)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	int name_index;
+	void *value = NULL;
+	size_t size = 0;
+	int error;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
+			if (acl) {
+				mode_t mode = inode->i_mode;
+				error = posix_acl_equiv_mode(acl, &mode);
+				if (error < 0)
+					return error;
+				else {
+					inode->i_mode = mode;
+					ext4_mark_inode_dirty(handle, inode);
+					if (error == 0)
+						acl = NULL;
+				}
+			}
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
+			if (!S_ISDIR(inode->i_mode))
+				return acl ? -EACCES : 0;
+			break;
+
+		default:
+			return -EINVAL;
+	}
+	if (acl) {
+		value = ext4_acl_to_disk(acl, &size);
+		if (IS_ERR(value))
+			return (int)PTR_ERR(value);
+	}
+
+	error = ext4_xattr_set_handle(handle, inode, name_index, "",
+				      value, size, 0);
+
+	kfree(value);
+	if (!error) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ext4_iset_acl(inode, &ei->i_acl, acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ext4_iset_acl(inode, &ei->i_default_acl, acl);
+				break;
+		}
+	}
+	return error;
+}
+
+static int
+ext4_check_acl(struct inode *inode, int mask)
+{
+	struct posix_acl *acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
+
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (acl) {
+		int error = posix_acl_permission(inode, acl, mask);
+		posix_acl_release(acl);
+		return error;
+	}
+
+	return -EAGAIN;
+}
+
+int
+ext4_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	return generic_permission(inode, mask, ext4_check_acl);
+}
+
+/*
+ * Initialize the ACLs of a new inode. Called from ext4_new_inode.
+ *
+ * dir->i_mutex: down
+ * inode->i_mutex: up (access to inode is still exclusive)
+ */
+int
+ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+{
+	struct posix_acl *acl = NULL;
+	int error = 0;
+
+	if (!S_ISLNK(inode->i_mode)) {
+		if (test_opt(dir->i_sb, POSIX_ACL)) {
+			acl = ext4_get_acl(dir, ACL_TYPE_DEFAULT);
+			if (IS_ERR(acl))
+				return PTR_ERR(acl);
+		}
+		if (!acl)
+			inode->i_mode &= ~current->fs->umask;
+	}
+	if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
+		struct posix_acl *clone;
+		mode_t mode;
+
+		if (S_ISDIR(inode->i_mode)) {
+			error = ext4_set_acl(handle, inode,
+					     ACL_TYPE_DEFAULT, acl);
+			if (error)
+				goto cleanup;
+		}
+		clone = posix_acl_clone(acl, GFP_KERNEL);
+		error = -ENOMEM;
+		if (!clone)
+			goto cleanup;
+
+		mode = inode->i_mode;
+		error = posix_acl_create_masq(clone, &mode);
+		if (error >= 0) {
+			inode->i_mode = mode;
+			if (error > 0) {
+				/* This is an extended ACL */
+				error = ext4_set_acl(handle, inode,
+						     ACL_TYPE_ACCESS, clone);
+			}
+		}
+		posix_acl_release(clone);
+	}
+cleanup:
+	posix_acl_release(acl);
+	return error;
+}
+
+/*
+ * Does chmod for an inode that may have an Access Control List. The
+ * inode->i_mode field must be updated to the desired value by the caller
+ * before calling this function.
+ * Returns 0 on success, or a negative error number.
+ *
+ * We change the ACL rather than storing some ACL entries in the file
+ * mode permission bits (which would be more efficient), because that
+ * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
+ * for directories) are added. There are no more bits available in the
+ * file mode.
+ *
+ * inode->i_mutex: down
+ */
+int
+ext4_acl_chmod(struct inode *inode)
+{
+	struct posix_acl *acl, *clone;
+	int error;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+	if (!test_opt(inode->i_sb, POSIX_ACL))
+		return 0;
+	acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl) || !acl)
+		return PTR_ERR(acl);
+	clone = posix_acl_clone(acl, GFP_KERNEL);
+	posix_acl_release(acl);
+	if (!clone)
+		return -ENOMEM;
+	error = posix_acl_chmod_masq(clone, inode->i_mode);
+	if (!error) {
+		handle_t *handle;
+		int retries = 0;
+
+	retry:
+		handle = ext4_journal_start(inode,
+				EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+		if (IS_ERR(handle)) {
+			error = PTR_ERR(handle);
+			ext4_std_error(inode->i_sb, error);
+			goto out;
+		}
+		error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
+		ext4_journal_stop(handle);
+		if (error == -ENOSPC &&
+		    ext4_should_retry_alloc(inode->i_sb, &retries))
+			goto retry;
+	}
+out:
+	posix_acl_release(clone);
+	return error;
+}
+
+/*
+ * Extended attribute handlers
+ */
+static size_t
+ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
+			   const char *name, size_t name_len)
+{
+	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
+
+	if (!test_opt(inode->i_sb, POSIX_ACL))
+		return 0;
+	if (list && size <= list_len)
+		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
+	return size;
+}
+
+static size_t
+ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
+			    const char *name, size_t name_len)
+{
+	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
+
+	if (!test_opt(inode->i_sb, POSIX_ACL))
+		return 0;
+	if (list && size <= list_len)
+		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
+	return size;
+}
+
+static int
+ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+{
+	struct posix_acl *acl;
+	int error;
+
+	if (!test_opt(inode->i_sb, POSIX_ACL))
+		return -EOPNOTSUPP;
+
+	acl = ext4_get_acl(inode, type);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (acl == NULL)
+		return -ENODATA;
+	error = posix_acl_to_xattr(acl, buffer, size);
+	posix_acl_release(acl);
+
+	return error;
+}
+
+static int
+ext4_xattr_get_acl_access(struct inode *inode, const char *name,
+			  void *buffer, size_t size)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return ext4_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int
+ext4_xattr_get_acl_default(struct inode *inode, const char *name,
+			   void *buffer, size_t size)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return ext4_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+static int
+ext4_xattr_set_acl(struct inode *inode, int type, const void *value,
+		   size_t size)
+{
+	handle_t *handle;
+	struct posix_acl *acl;
+	int error, retries = 0;
+
+	if (!test_opt(inode->i_sb, POSIX_ACL))
+		return -EOPNOTSUPP;
+	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		return -EPERM;
+
+	if (value) {
+		acl = posix_acl_from_xattr(value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		else if (acl) {
+			error = posix_acl_valid(acl);
+			if (error)
+				goto release_and_out;
+		}
+	} else
+		acl = NULL;
+
+retry:
+	handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	error = ext4_set_acl(handle, inode, type, acl);
+	ext4_journal_stop(handle);
+	if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+		goto retry;
+
+release_and_out:
+	posix_acl_release(acl);
+	return error;
+}
+
+static int
+ext4_xattr_set_acl_access(struct inode *inode, const char *name,
+			  const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return ext4_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
+}
+
+static int
+ext4_xattr_set_acl_default(struct inode *inode, const char *name,
+			   const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return ext4_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
+}
+
+struct xattr_handler ext4_xattr_acl_access_handler = {
+	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.list	= ext4_xattr_list_acl_access,
+	.get	= ext4_xattr_get_acl_access,
+	.set	= ext4_xattr_set_acl_access,
+};
+
+struct xattr_handler ext4_xattr_acl_default_handler = {
+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.list	= ext4_xattr_list_acl_default,
+	.get	= ext4_xattr_get_acl_default,
+	.set	= ext4_xattr_set_acl_default,
+};
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
new file mode 100644
index 0000000..26a5c1a
--- /dev/null
+++ b/fs/ext4/acl.h
@@ -0,0 +1,81 @@
+/*
+  File: fs/ext4/acl.h
+
+  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
+*/
+
+#include <linux/posix_acl_xattr.h>
+
+#define EXT4_ACL_VERSION	0x0001
+
+typedef struct {
+	__le16		e_tag;
+	__le16		e_perm;
+	__le32		e_id;
+} ext4_acl_entry;
+
+typedef struct {
+	__le16		e_tag;
+	__le16		e_perm;
+} ext4_acl_entry_short;
+
+typedef struct {
+	__le32		a_version;
+} ext4_acl_header;
+
+static inline size_t ext4_acl_size(int count)
+{
+	if (count <= 4) {
+		return sizeof(ext4_acl_header) +
+		       count * sizeof(ext4_acl_entry_short);
+	} else {
+		return sizeof(ext4_acl_header) +
+		       4 * sizeof(ext4_acl_entry_short) +
+		       (count - 4) * sizeof(ext4_acl_entry);
+	}
+}
+
+static inline int ext4_acl_count(size_t size)
+{
+	ssize_t s;
+	size -= sizeof(ext4_acl_header);
+	s = size - 4 * sizeof(ext4_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(ext4_acl_entry_short))
+			return -1;
+		return size / sizeof(ext4_acl_entry_short);
+	} else {
+		if (s % sizeof(ext4_acl_entry))
+			return -1;
+		return s / sizeof(ext4_acl_entry) + 4;
+	}
+}
+
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+
+/* Value for inode->u.ext4_i.i_acl and inode->u.ext4_i.i_default_acl
+   if the ACL has not been cached */
+#define EXT4_ACL_NOT_CACHED ((void *)-1)
+
+/* acl.c */
+extern int ext4_permission (struct inode *, int, struct nameidata *);
+extern int ext4_acl_chmod (struct inode *);
+extern int ext4_init_acl (handle_t *, struct inode *, struct inode *);
+
+#else  /* CONFIG_EXT4DEV_FS_POSIX_ACL */
+#include <linux/sched.h>
+#define ext4_permission NULL
+
+static inline int
+ext4_acl_chmod(struct inode *inode)
+{
+	return 0;
+}
+
+static inline int
+ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+{
+	return 0;
+}
+#endif  /* CONFIG_EXT4DEV_FS_POSIX_ACL */
+
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
new file mode 100644
index 0000000..5d45582
--- /dev/null
+++ b/fs/ext4/balloc.c
@@ -0,0 +1,1833 @@
+/*
+ *  linux/fs/ext4/balloc.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  Enhanced block allocation by Stephen Tweedie (sct@redhat.com), 1993
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ */
+
+#include <linux/time.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/quotaops.h>
+#include <linux/buffer_head.h>
+
+/*
+ * balloc.c contains the blocks allocation and deallocation routines
+ */
+
+/*
+ * Calculate the block group number and offset, given a block number
+ */
+void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+		unsigned long *blockgrpp, ext4_grpblk_t *offsetp)
+{
+        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+	ext4_grpblk_t offset;
+
+        blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
+	offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
+	if (offsetp)
+		*offsetp = offset;
+	if (blockgrpp)
+	        *blockgrpp = blocknr;
+
+}
+
+/*
+ * The free blocks are managed by bitmaps.  A file system contains several
+ * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
+ * block for inodes, N blocks for the inode table and data blocks.
+ *
+ * The file system contains group descriptors which are located after the
+ * super block.  Each descriptor contains the number of the bitmap block and
+ * the free blocks count in the block.  The descriptors are loaded in memory
+ * when a file system is mounted (see ext4_read_super).
+ */
+
+
+#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
+
+/**
+ * ext4_get_group_desc() -- load group descriptor from disk
+ * @sb:			super block
+ * @block_group:	given block group
+ * @bh:			pointer to the buffer head to store the block
+ *			group descriptor
+ */
+struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+					     unsigned int block_group,
+					     struct buffer_head ** bh)
+{
+	unsigned long group_desc;
+	unsigned long offset;
+	struct ext4_group_desc * desc;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+	if (block_group >= sbi->s_groups_count) {
+		ext4_error (sb, "ext4_get_group_desc",
+			    "block_group >= groups_count - "
+			    "block_group = %d, groups_count = %lu",
+			    block_group, sbi->s_groups_count);
+
+		return NULL;
+	}
+	smp_rmb();
+
+	group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
+	offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
+	if (!sbi->s_group_desc[group_desc]) {
+		ext4_error (sb, "ext4_get_group_desc",
+			    "Group descriptor not loaded - "
+			    "block_group = %d, group_desc = %lu, desc = %lu",
+			     block_group, group_desc, offset);
+		return NULL;
+	}
+
+	desc = (struct ext4_group_desc *)(
+		(__u8 *)sbi->s_group_desc[group_desc]->b_data +
+		offset * EXT4_DESC_SIZE(sb));
+	if (bh)
+		*bh = sbi->s_group_desc[group_desc];
+	return desc;
+}
+
+/**
+ * read_block_bitmap()
+ * @sb:			super block
+ * @block_group:	given block group
+ *
+ * Read the bitmap for a given block_group, reading into the specified
+ * slot in the superblock's bitmap cache.
+ *
+ * Return buffer_head on success or NULL in case of failure.
+ */
+static struct buffer_head *
+read_block_bitmap(struct super_block *sb, unsigned int block_group)
+{
+	struct ext4_group_desc * desc;
+	struct buffer_head * bh = NULL;
+
+	desc = ext4_get_group_desc (sb, block_group, NULL);
+	if (!desc)
+		goto error_out;
+	bh = sb_bread(sb, ext4_block_bitmap(sb, desc));
+	if (!bh)
+		ext4_error (sb, "read_block_bitmap",
+			    "Cannot read block bitmap - "
+			    "block_group = %d, block_bitmap = %llu",
+			    block_group,
+			    ext4_block_bitmap(sb, desc));
+error_out:
+	return bh;
+}
+/*
+ * The reservation window structure operations
+ * --------------------------------------------
+ * Operations include:
+ * dump, find, add, remove, is_empty, find_next_reservable_window, etc.
+ *
+ * We use a red-black tree to represent per-filesystem reservation
+ * windows.
+ *
+ */
+
+/**
+ * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
+ * @rb_root:		root of per-filesystem reservation rb tree
+ * @verbose:		verbose mode
+ * @fn:			function which wishes to dump the reservation map
+ *
+ * If verbose is turned on, it will print the whole block reservation
+ * windows(start, end).	Otherwise, it will only print out the "bad" windows,
+ * those windows that overlap with their immediate neighbors.
+ */
+#if 1
+static void __rsv_window_dump(struct rb_root *root, int verbose,
+			      const char *fn)
+{
+	struct rb_node *n;
+	struct ext4_reserve_window_node *rsv, *prev;
+	int bad;
+
+restart:
+	n = rb_first(root);
+	bad = 0;
+	prev = NULL;
+
+	printk("Block Allocation Reservation Windows Map (%s):\n", fn);
+	while (n) {
+		rsv = list_entry(n, struct ext4_reserve_window_node, rsv_node);
+		if (verbose)
+			printk("reservation window 0x%p "
+			       "start:  %llu, end:  %llu\n",
+			       rsv, rsv->rsv_start, rsv->rsv_end);
+		if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
+			printk("Bad reservation %p (start >= end)\n",
+			       rsv);
+			bad = 1;
+		}
+		if (prev && prev->rsv_end >= rsv->rsv_start) {
+			printk("Bad reservation %p (prev->end >= start)\n",
+			       rsv);
+			bad = 1;
+		}
+		if (bad) {
+			if (!verbose) {
+				printk("Restarting reservation walk in verbose mode\n");
+				verbose = 1;
+				goto restart;
+			}
+		}
+		n = rb_next(n);
+		prev = rsv;
+	}
+	printk("Window map complete.\n");
+	if (bad)
+		BUG();
+}
+#define rsv_window_dump(root, verbose) \
+	__rsv_window_dump((root), (verbose), __FUNCTION__)
+#else
+#define rsv_window_dump(root, verbose) do {} while (0)
+#endif
+
+/**
+ * goal_in_my_reservation()
+ * @rsv:		inode's reservation window
+ * @grp_goal:		given goal block relative to the allocation block group
+ * @group:		the current allocation block group
+ * @sb:			filesystem super block
+ *
+ * Test if the given goal block (group relative) is within the file's
+ * own block reservation window range.
+ *
+ * If the reservation window is outside the goal allocation group, return 0;
+ * grp_goal (given goal block) could be -1, which means no specific
+ * goal block. In this case, always return 1.
+ * If the goal block is within the reservation window, return 1;
+ * otherwise, return 0;
+ */
+static int
+goal_in_my_reservation(struct ext4_reserve_window *rsv, ext4_grpblk_t grp_goal,
+			unsigned int group, struct super_block * sb)
+{
+	ext4_fsblk_t group_first_block, group_last_block;
+
+	group_first_block = ext4_group_first_block_no(sb, group);
+	group_last_block = group_first_block + (EXT4_BLOCKS_PER_GROUP(sb) - 1);
+
+	if ((rsv->_rsv_start > group_last_block) ||
+	    (rsv->_rsv_end < group_first_block))
+		return 0;
+	if ((grp_goal >= 0) && ((grp_goal + group_first_block < rsv->_rsv_start)
+		|| (grp_goal + group_first_block > rsv->_rsv_end)))
+		return 0;
+	return 1;
+}
+
+/**
+ * search_reserve_window()
+ * @rb_root:		root of reservation tree
+ * @goal:		target allocation block
+ *
+ * Find the reserved window which includes the goal, or the previous one
+ * if the goal is not in any window.
+ * Returns NULL if there are no windows or if all windows start after the goal.
+ */
+static struct ext4_reserve_window_node *
+search_reserve_window(struct rb_root *root, ext4_fsblk_t goal)
+{
+	struct rb_node *n = root->rb_node;
+	struct ext4_reserve_window_node *rsv;
+
+	if (!n)
+		return NULL;
+
+	do {
+		rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
+
+		if (goal < rsv->rsv_start)
+			n = n->rb_left;
+		else if (goal > rsv->rsv_end)
+			n = n->rb_right;
+		else
+			return rsv;
+	} while (n);
+	/*
+	 * We've fallen off the end of the tree: the goal wasn't inside
+	 * any particular node.  OK, the previous node must be to one
+	 * side of the interval containing the goal.  If it's the RHS,
+	 * we need to back up one.
+	 */
+	if (rsv->rsv_start > goal) {
+		n = rb_prev(&rsv->rsv_node);
+		rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
+	}
+	return rsv;
+}
+
+/**
+ * ext4_rsv_window_add() -- Insert a window to the block reservation rb tree.
+ * @sb:			super block
+ * @rsv:		reservation window to add
+ *
+ * Must be called with rsv_lock hold.
+ */
+void ext4_rsv_window_add(struct super_block *sb,
+		    struct ext4_reserve_window_node *rsv)
+{
+	struct rb_root *root = &EXT4_SB(sb)->s_rsv_window_root;
+	struct rb_node *node = &rsv->rsv_node;
+	ext4_fsblk_t start = rsv->rsv_start;
+
+	struct rb_node ** p = &root->rb_node;
+	struct rb_node * parent = NULL;
+	struct ext4_reserve_window_node *this;
+
+	while (*p)
+	{
+		parent = *p;
+		this = rb_entry(parent, struct ext4_reserve_window_node, rsv_node);
+
+		if (start < this->rsv_start)
+			p = &(*p)->rb_left;
+		else if (start > this->rsv_end)
+			p = &(*p)->rb_right;
+		else {
+			rsv_window_dump(root, 1);
+			BUG();
+		}
+	}
+
+	rb_link_node(node, parent, p);
+	rb_insert_color(node, root);
+}
+
+/**
+ * ext4_rsv_window_remove() -- unlink a window from the reservation rb tree
+ * @sb:			super block
+ * @rsv:		reservation window to remove
+ *
+ * Mark the block reservation window as not allocated, and unlink it
+ * from the filesystem reservation window rb tree. Must be called with
+ * rsv_lock hold.
+ */
+static void rsv_window_remove(struct super_block *sb,
+			      struct ext4_reserve_window_node *rsv)
+{
+	rsv->rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+	rsv->rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+	rsv->rsv_alloc_hit = 0;
+	rb_erase(&rsv->rsv_node, &EXT4_SB(sb)->s_rsv_window_root);
+}
+
+/*
+ * rsv_is_empty() -- Check if the reservation window is allocated.
+ * @rsv:		given reservation window to check
+ *
+ * returns 1 if the end block is EXT4_RESERVE_WINDOW_NOT_ALLOCATED.
+ */
+static inline int rsv_is_empty(struct ext4_reserve_window *rsv)
+{
+	/* a valid reservation end block could not be 0 */
+	return rsv->_rsv_end == EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+}
+
+/**
+ * ext4_init_block_alloc_info()
+ * @inode:		file inode structure
+ *
+ * Allocate and initialize the	reservation window structure, and
+ * link the window to the ext4 inode structure at last
+ *
+ * The reservation window structure is only dynamically allocated
+ * and linked to ext4 inode the first time the open file
+ * needs a new block. So, before every ext4_new_block(s) call, for
+ * regular files, we should check whether the reservation window
+ * structure exists or not. In the latter case, this function is called.
+ * Fail to do so will result in block reservation being turned off for that
+ * open file.
+ *
+ * This function is called from ext4_get_blocks_handle(), also called
+ * when setting the reservation window size through ioctl before the file
+ * is open for write (needs block allocation).
+ *
+ * Needs truncate_mutex protection prior to call this function.
+ */
+void ext4_init_block_alloc_info(struct inode *inode)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct ext4_block_alloc_info *block_i = ei->i_block_alloc_info;
+	struct super_block *sb = inode->i_sb;
+
+	block_i = kmalloc(sizeof(*block_i), GFP_NOFS);
+	if (block_i) {
+		struct ext4_reserve_window_node *rsv = &block_i->rsv_window_node;
+
+		rsv->rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+		rsv->rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+
+		/*
+		 * if filesystem is mounted with NORESERVATION, the goal
+		 * reservation window size is set to zero to indicate
+		 * block reservation is off
+		 */
+		if (!test_opt(sb, RESERVATION))
+			rsv->rsv_goal_size = 0;
+		else
+			rsv->rsv_goal_size = EXT4_DEFAULT_RESERVE_BLOCKS;
+		rsv->rsv_alloc_hit = 0;
+		block_i->last_alloc_logical_block = 0;
+		block_i->last_alloc_physical_block = 0;
+	}
+	ei->i_block_alloc_info = block_i;
+}
+
+/**
+ * ext4_discard_reservation()
+ * @inode:		inode
+ *
+ * Discard(free) block reservation window on last file close, or truncate
+ * or at last iput().
+ *
+ * It is being called in three cases:
+ *	ext4_release_file(): last writer close the file
+ *	ext4_clear_inode(): last iput(), when nobody link to this file.
+ *	ext4_truncate(): when the block indirect map is about to change.
+ *
+ */
+void ext4_discard_reservation(struct inode *inode)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct ext4_block_alloc_info *block_i = ei->i_block_alloc_info;
+	struct ext4_reserve_window_node *rsv;
+	spinlock_t *rsv_lock = &EXT4_SB(inode->i_sb)->s_rsv_window_lock;
+
+	if (!block_i)
+		return;
+
+	rsv = &block_i->rsv_window_node;
+	if (!rsv_is_empty(&rsv->rsv_window)) {
+		spin_lock(rsv_lock);
+		if (!rsv_is_empty(&rsv->rsv_window))
+			rsv_window_remove(inode->i_sb, rsv);
+		spin_unlock(rsv_lock);
+	}
+}
+
+/**
+ * ext4_free_blocks_sb() -- Free given blocks and update quota
+ * @handle:			handle to this transaction
+ * @sb:				super block
+ * @block:			start physcial block to free
+ * @count:			number of blocks to free
+ * @pdquot_freed_blocks:	pointer to quota
+ */
+void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+			 ext4_fsblk_t block, unsigned long count,
+			 unsigned long *pdquot_freed_blocks)
+{
+	struct buffer_head *bitmap_bh = NULL;
+	struct buffer_head *gd_bh;
+	unsigned long block_group;
+	ext4_grpblk_t bit;
+	unsigned long i;
+	unsigned long overflow;
+	struct ext4_group_desc * desc;
+	struct ext4_super_block * es;
+	struct ext4_sb_info *sbi;
+	int err = 0, ret;
+	ext4_grpblk_t group_freed;
+
+	*pdquot_freed_blocks = 0;
+	sbi = EXT4_SB(sb);
+	es = sbi->s_es;
+	if (block < le32_to_cpu(es->s_first_data_block) ||
+	    block + count < block ||
+	    block + count > ext4_blocks_count(es)) {
+		ext4_error (sb, "ext4_free_blocks",
+			    "Freeing blocks not in datazone - "
+			    "block = %llu, count = %lu", block, count);
+		goto error_return;
+	}
+
+	ext4_debug ("freeing block(s) %llu-%llu\n", block, block + count - 1);
+
+do_more:
+	overflow = 0;
+	ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
+	/*
+	 * Check to see if we are freeing blocks across a group
+	 * boundary.
+	 */
+	if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
+		overflow = bit + count - EXT4_BLOCKS_PER_GROUP(sb);
+		count -= overflow;
+	}
+	brelse(bitmap_bh);
+	bitmap_bh = read_block_bitmap(sb, block_group);
+	if (!bitmap_bh)
+		goto error_return;
+	desc = ext4_get_group_desc (sb, block_group, &gd_bh);
+	if (!desc)
+		goto error_return;
+
+	if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
+	    in_range(ext4_inode_bitmap(sb, desc), block, count) ||
+	    in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
+	    in_range(block + count - 1, ext4_inode_table(sb, desc),
+		     sbi->s_itb_per_group))
+		ext4_error (sb, "ext4_free_blocks",
+			    "Freeing blocks in system zones - "
+			    "Block = %llu, count = %lu",
+			    block, count);
+
+	/*
+	 * We are about to start releasing blocks in the bitmap,
+	 * so we need undo access.
+	 */
+	/* @@@ check errors */
+	BUFFER_TRACE(bitmap_bh, "getting undo access");
+	err = ext4_journal_get_undo_access(handle, bitmap_bh);
+	if (err)
+		goto error_return;
+
+	/*
+	 * We are about to modify some metadata.  Call the journal APIs
+	 * to unshare ->b_data if a currently-committing transaction is
+	 * using it
+	 */
+	BUFFER_TRACE(gd_bh, "get_write_access");
+	err = ext4_journal_get_write_access(handle, gd_bh);
+	if (err)
+		goto error_return;
+
+	jbd_lock_bh_state(bitmap_bh);
+
+	for (i = 0, group_freed = 0; i < count; i++) {
+		/*
+		 * An HJ special.  This is expensive...
+		 */
+#ifdef CONFIG_JBD_DEBUG
+		jbd_unlock_bh_state(bitmap_bh);
+		{
+			struct buffer_head *debug_bh;
+			debug_bh = sb_find_get_block(sb, block + i);
+			if (debug_bh) {
+				BUFFER_TRACE(debug_bh, "Deleted!");
+				if (!bh2jh(bitmap_bh)->b_committed_data)
+					BUFFER_TRACE(debug_bh,
+						"No commited data in bitmap");
+				BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap");
+				__brelse(debug_bh);
+			}
+		}
+		jbd_lock_bh_state(bitmap_bh);
+#endif
+		if (need_resched()) {
+			jbd_unlock_bh_state(bitmap_bh);
+			cond_resched();
+			jbd_lock_bh_state(bitmap_bh);
+		}
+		/* @@@ This prevents newly-allocated data from being
+		 * freed and then reallocated within the same
+		 * transaction.
+		 *
+		 * Ideally we would want to allow that to happen, but to
+		 * do so requires making jbd2_journal_forget() capable of
+		 * revoking the queued write of a data block, which
+		 * implies blocking on the journal lock.  *forget()
+		 * cannot block due to truncate races.
+		 *
+		 * Eventually we can fix this by making jbd2_journal_forget()
+		 * return a status indicating whether or not it was able
+		 * to revoke the buffer.  On successful revoke, it is
+		 * safe not to set the allocation bit in the committed
+		 * bitmap, because we know that there is no outstanding
+		 * activity on the buffer any more and so it is safe to
+		 * reallocate it.
+		 */
+		BUFFER_TRACE(bitmap_bh, "set in b_committed_data");
+		J_ASSERT_BH(bitmap_bh,
+				bh2jh(bitmap_bh)->b_committed_data != NULL);
+		ext4_set_bit_atomic(sb_bgl_lock(sbi, block_group), bit + i,
+				bh2jh(bitmap_bh)->b_committed_data);
+
+		/*
+		 * We clear the bit in the bitmap after setting the committed
+		 * data bit, because this is the reverse order to that which
+		 * the allocator uses.
+		 */
+		BUFFER_TRACE(bitmap_bh, "clear bit");
+		if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+						bit + i, bitmap_bh->b_data)) {
+			jbd_unlock_bh_state(bitmap_bh);
+			ext4_error(sb, __FUNCTION__,
+				   "bit already cleared for block %llu",
+				   (ext4_fsblk_t)(block + i));
+			jbd_lock_bh_state(bitmap_bh);
+			BUFFER_TRACE(bitmap_bh, "bit already cleared");
+		} else {
+			group_freed++;
+		}
+	}
+	jbd_unlock_bh_state(bitmap_bh);
+
+	spin_lock(sb_bgl_lock(sbi, block_group));
+	desc->bg_free_blocks_count =
+		cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
+			group_freed);
+	spin_unlock(sb_bgl_lock(sbi, block_group));
+	percpu_counter_mod(&sbi->s_freeblocks_counter, count);
+
+	/* We dirtied the bitmap block */
+	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
+	err = ext4_journal_dirty_metadata(handle, bitmap_bh);
+
+	/* And the group descriptor block */
+	BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
+	ret = ext4_journal_dirty_metadata(handle, gd_bh);
+	if (!err) err = ret;
+	*pdquot_freed_blocks += group_freed;
+
+	if (overflow && !err) {
+		block += count;
+		count = overflow;
+		goto do_more;
+	}
+	sb->s_dirt = 1;
+error_return:
+	brelse(bitmap_bh);
+	ext4_std_error(sb, err);
+	return;
+}
+
+/**
+ * ext4_free_blocks() -- Free given blocks and update quota
+ * @handle:		handle for this transaction
+ * @inode:		inode
+ * @block:		start physical block to free
+ * @count:		number of blocks to count
+ */
+void ext4_free_blocks(handle_t *handle, struct inode *inode,
+			ext4_fsblk_t block, unsigned long count)
+{
+	struct super_block * sb;
+	unsigned long dquot_freed_blocks;
+
+	sb = inode->i_sb;
+	if (!sb) {
+		printk ("ext4_free_blocks: nonexistent device");
+		return;
+	}
+	ext4_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
+	if (dquot_freed_blocks)
+		DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+	return;
+}
+
+/**
+ * ext4_test_allocatable()
+ * @nr:			given allocation block group
+ * @bh:			bufferhead contains the bitmap of the given block group
+ *
+ * For ext4 allocations, we must not reuse any blocks which are
+ * allocated in the bitmap buffer's "last committed data" copy.  This
+ * prevents deletes from freeing up the page for reuse until we have
+ * committed the delete transaction.
+ *
+ * If we didn't do this, then deleting something and reallocating it as
+ * data would allow the old block to be overwritten before the
+ * transaction committed (because we force data to disk before commit).
+ * This would lead to corruption if we crashed between overwriting the
+ * data and committing the delete.
+ *
+ * @@@ We may want to make this allocation behaviour conditional on
+ * data-writes at some point, and disable it for metadata allocations or
+ * sync-data inodes.
+ */
+static int ext4_test_allocatable(ext4_grpblk_t nr, struct buffer_head *bh)
+{
+	int ret;
+	struct journal_head *jh = bh2jh(bh);
+
+	if (ext4_test_bit(nr, bh->b_data))
+		return 0;
+
+	jbd_lock_bh_state(bh);
+	if (!jh->b_committed_data)
+		ret = 1;
+	else
+		ret = !ext4_test_bit(nr, jh->b_committed_data);
+	jbd_unlock_bh_state(bh);
+	return ret;
+}
+
+/**
+ * bitmap_search_next_usable_block()
+ * @start:		the starting block (group relative) of the search
+ * @bh:			bufferhead contains the block group bitmap
+ * @maxblocks:		the ending block (group relative) of the reservation
+ *
+ * The bitmap search --- search forward alternately through the actual
+ * bitmap on disk and the last-committed copy in journal, until we find a
+ * bit free in both bitmaps.
+ */
+static ext4_grpblk_t
+bitmap_search_next_usable_block(ext4_grpblk_t start, struct buffer_head *bh,
+					ext4_grpblk_t maxblocks)
+{
+	ext4_grpblk_t next;
+	struct journal_head *jh = bh2jh(bh);
+
+	while (start < maxblocks) {
+		next = ext4_find_next_zero_bit(bh->b_data, maxblocks, start);
+		if (next >= maxblocks)
+			return -1;
+		if (ext4_test_allocatable(next, bh))
+			return next;
+		jbd_lock_bh_state(bh);
+		if (jh->b_committed_data)
+			start = ext4_find_next_zero_bit(jh->b_committed_data,
+							maxblocks, next);
+		jbd_unlock_bh_state(bh);
+	}
+	return -1;
+}
+
+/**
+ * find_next_usable_block()
+ * @start:		the starting block (group relative) to find next
+ *			allocatable block in bitmap.
+ * @bh:			bufferhead contains the block group bitmap
+ * @maxblocks:		the ending block (group relative) for the search
+ *
+ * Find an allocatable block in a bitmap.  We honor both the bitmap and
+ * its last-committed copy (if that exists), and perform the "most
+ * appropriate allocation" algorithm of looking for a free block near
+ * the initial goal; then for a free byte somewhere in the bitmap; then
+ * for any free bit in the bitmap.
+ */
+static ext4_grpblk_t
+find_next_usable_block(ext4_grpblk_t start, struct buffer_head *bh,
+			ext4_grpblk_t maxblocks)
+{
+	ext4_grpblk_t here, next;
+	char *p, *r;
+
+	if (start > 0) {
+		/*
+		 * The goal was occupied; search forward for a free
+		 * block within the next XX blocks.
+		 *
+		 * end_goal is more or less random, but it has to be
+		 * less than EXT4_BLOCKS_PER_GROUP. Aligning up to the
+		 * next 64-bit boundary is simple..
+		 */
+		ext4_grpblk_t end_goal = (start + 63) & ~63;
+		if (end_goal > maxblocks)
+			end_goal = maxblocks;
+		here = ext4_find_next_zero_bit(bh->b_data, end_goal, start);
+		if (here < end_goal && ext4_test_allocatable(here, bh))
+			return here;
+		ext4_debug("Bit not found near goal\n");
+	}
+
+	here = start;
+	if (here < 0)
+		here = 0;
+
+	p = ((char *)bh->b_data) + (here >> 3);
+	r = memscan(p, 0, (maxblocks - here + 7) >> 3);
+	next = (r - ((char *)bh->b_data)) << 3;
+
+	if (next < maxblocks && next >= start && ext4_test_allocatable(next, bh))
+		return next;
+
+	/*
+	 * The bitmap search --- search forward alternately through the actual
+	 * bitmap and the last-committed copy until we find a bit free in
+	 * both
+	 */
+	here = bitmap_search_next_usable_block(here, bh, maxblocks);
+	return here;
+}
+
+/**
+ * claim_block()
+ * @block:		the free block (group relative) to allocate
+ * @bh:			the bufferhead containts the block group bitmap
+ *
+ * We think we can allocate this block in this bitmap.  Try to set the bit.
+ * If that succeeds then check that nobody has allocated and then freed the
+ * block since we saw that is was not marked in b_committed_data.  If it _was_
+ * allocated and freed then clear the bit in the bitmap again and return
+ * zero (failure).
+ */
+static inline int
+claim_block(spinlock_t *lock, ext4_grpblk_t block, struct buffer_head *bh)
+{
+	struct journal_head *jh = bh2jh(bh);
+	int ret;
+
+	if (ext4_set_bit_atomic(lock, block, bh->b_data))
+		return 0;
+	jbd_lock_bh_state(bh);
+	if (jh->b_committed_data && ext4_test_bit(block,jh->b_committed_data)) {
+		ext4_clear_bit_atomic(lock, block, bh->b_data);
+		ret = 0;
+	} else {
+		ret = 1;
+	}
+	jbd_unlock_bh_state(bh);
+	return ret;
+}
+
+/**
+ * ext4_try_to_allocate()
+ * @sb:			superblock
+ * @handle:		handle to this transaction
+ * @group:		given allocation block group
+ * @bitmap_bh:		bufferhead holds the block bitmap
+ * @grp_goal:		given target block within the group
+ * @count:		target number of blocks to allocate
+ * @my_rsv:		reservation window
+ *
+ * Attempt to allocate blocks within a give range. Set the range of allocation
+ * first, then find the first free bit(s) from the bitmap (within the range),
+ * and at last, allocate the blocks by claiming the found free bit as allocated.
+ *
+ * To set the range of this allocation:
+ *	if there is a reservation window, only try to allocate block(s) from the
+ *	file's own reservation window;
+ *	Otherwise, the allocation range starts from the give goal block, ends at
+ *	the block group's last block.
+ *
+ * If we failed to allocate the desired block then we may end up crossing to a
+ * new bitmap.  In that case we must release write access to the old one via
+ * ext4_journal_release_buffer(), else we'll run out of credits.
+ */
+static ext4_grpblk_t
+ext4_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
+			struct buffer_head *bitmap_bh, ext4_grpblk_t grp_goal,
+			unsigned long *count, struct ext4_reserve_window *my_rsv)
+{
+	ext4_fsblk_t group_first_block;
+	ext4_grpblk_t start, end;
+	unsigned long num = 0;
+
+	/* we do allocation within the reservation window if we have a window */
+	if (my_rsv) {
+		group_first_block = ext4_group_first_block_no(sb, group);
+		if (my_rsv->_rsv_start >= group_first_block)
+			start = my_rsv->_rsv_start - group_first_block;
+		else
+			/* reservation window cross group boundary */
+			start = 0;
+		end = my_rsv->_rsv_end - group_first_block + 1;
+		if (end > EXT4_BLOCKS_PER_GROUP(sb))
+			/* reservation window crosses group boundary */
+			end = EXT4_BLOCKS_PER_GROUP(sb);
+		if ((start <= grp_goal) && (grp_goal < end))
+			start = grp_goal;
+		else
+			grp_goal = -1;
+	} else {
+		if (grp_goal > 0)
+			start = grp_goal;
+		else
+			start = 0;
+		end = EXT4_BLOCKS_PER_GROUP(sb);
+	}
+
+	BUG_ON(start > EXT4_BLOCKS_PER_GROUP(sb));
+
+repeat:
+	if (grp_goal < 0 || !ext4_test_allocatable(grp_goal, bitmap_bh)) {
+		grp_goal = find_next_usable_block(start, bitmap_bh, end);
+		if (grp_goal < 0)
+			goto fail_access;
+		if (!my_rsv) {
+			int i;
+
+			for (i = 0; i < 7 && grp_goal > start &&
+					ext4_test_allocatable(grp_goal - 1,
+								bitmap_bh);
+					i++, grp_goal--)
+				;
+		}
+	}
+	start = grp_goal;
+
+	if (!claim_block(sb_bgl_lock(EXT4_SB(sb), group),
+		grp_goal, bitmap_bh)) {
+		/*
+		 * The block was allocated by another thread, or it was
+		 * allocated and then freed by another thread
+		 */
+		start++;
+		grp_goal++;
+		if (start >= end)
+			goto fail_access;
+		goto repeat;
+	}
+	num++;
+	grp_goal++;
+	while (num < *count && grp_goal < end
+		&& ext4_test_allocatable(grp_goal, bitmap_bh)
+		&& claim_block(sb_bgl_lock(EXT4_SB(sb), group),
+				grp_goal, bitmap_bh)) {
+		num++;
+		grp_goal++;
+	}
+	*count = num;
+	return grp_goal - num;
+fail_access:
+	*count = num;
+	return -1;
+}
+
+/**
+ *	find_next_reservable_window():
+ *		find a reservable space within the given range.
+ *		It does not allocate the reservation window for now:
+ *		alloc_new_reservation() will do the work later.
+ *
+ *	@search_head: the head of the searching list;
+ *		This is not necessarily the list head of the whole filesystem
+ *
+ *		We have both head and start_block to assist the search
+ *		for the reservable space. The list starts from head,
+ *		but we will shift to the place where start_block is,
+ *		then start from there, when looking for a reservable space.
+ *
+ *	@size: the target new reservation window size
+ *
+ *	@group_first_block: the first block we consider to start
+ *			the real search from
+ *
+ *	@last_block:
+ *		the maximum block number that our goal reservable space
+ *		could start from. This is normally the last block in this
+ *		group. The search will end when we found the start of next
+ *		possible reservable space is out of this boundary.
+ *		This could handle the cross boundary reservation window
+ *		request.
+ *
+ *	basically we search from the given range, rather than the whole
+ *	reservation double linked list, (start_block, last_block)
+ *	to find a free region that is of my size and has not
+ *	been reserved.
+ *
+ */
+static int find_next_reservable_window(
+				struct ext4_reserve_window_node *search_head,
+				struct ext4_reserve_window_node *my_rsv,
+				struct super_block * sb,
+				ext4_fsblk_t start_block,
+				ext4_fsblk_t last_block)
+{
+	struct rb_node *next;
+	struct ext4_reserve_window_node *rsv, *prev;
+	ext4_fsblk_t cur;
+	int size = my_rsv->rsv_goal_size;
+
+	/* TODO: make the start of the reservation window byte-aligned */
+	/* cur = *start_block & ~7;*/
+	cur = start_block;
+	rsv = search_head;
+	if (!rsv)
+		return -1;
+
+	while (1) {
+		if (cur <= rsv->rsv_end)
+			cur = rsv->rsv_end + 1;
+
+		/* TODO?
+		 * in the case we could not find a reservable space
+		 * that is what is expected, during the re-search, we could
+		 * remember what's the largest reservable space we could have
+		 * and return that one.
+		 *
+		 * For now it will fail if we could not find the reservable
+		 * space with expected-size (or more)...
+		 */
+		if (cur > last_block)
+			return -1;		/* fail */
+
+		prev = rsv;
+		next = rb_next(&rsv->rsv_node);
+		rsv = list_entry(next,struct ext4_reserve_window_node,rsv_node);
+
+		/*
+		 * Reached the last reservation, we can just append to the
+		 * previous one.
+		 */
+		if (!next)
+			break;
+
+		if (cur + size <= rsv->rsv_start) {
+			/*
+			 * Found a reserveable space big enough.  We could
+			 * have a reservation across the group boundary here
+			 */
+			break;
+		}
+	}
+	/*
+	 * we come here either :
+	 * when we reach the end of the whole list,
+	 * and there is empty reservable space after last entry in the list.
+	 * append it to the end of the list.
+	 *
+	 * or we found one reservable space in the middle of the list,
+	 * return the reservation window that we could append to.
+	 * succeed.
+	 */
+
+	if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window)))
+		rsv_window_remove(sb, my_rsv);
+
+	/*
+	 * Let's book the whole avaliable window for now.  We will check the
+	 * disk bitmap later and then, if there are free blocks then we adjust
+	 * the window size if it's larger than requested.
+	 * Otherwise, we will remove this node from the tree next time
+	 * call find_next_reservable_window.
+	 */
+	my_rsv->rsv_start = cur;
+	my_rsv->rsv_end = cur + size - 1;
+	my_rsv->rsv_alloc_hit = 0;
+
+	if (prev != my_rsv)
+		ext4_rsv_window_add(sb, my_rsv);
+
+	return 0;
+}
+
+/**
+ *	alloc_new_reservation()--allocate a new reservation window
+ *
+ *		To make a new reservation, we search part of the filesystem
+ *		reservation list (the list that inside the group). We try to
+ *		allocate a new reservation window near the allocation goal,
+ *		or the beginning of the group, if there is no goal.
+ *
+ *		We first find a reservable space after the goal, then from
+ *		there, we check the bitmap for the first free block after
+ *		it. If there is no free block until the end of group, then the
+ *		whole group is full, we failed. Otherwise, check if the free
+ *		block is inside the expected reservable space, if so, we
+ *		succeed.
+ *		If the first free block is outside the reservable space, then
+ *		start from the first free block, we search for next available
+ *		space, and go on.
+ *
+ *	on succeed, a new reservation will be found and inserted into the list
+ *	It contains at least one free block, and it does not overlap with other
+ *	reservation windows.
+ *
+ *	failed: we failed to find a reservation window in this group
+ *
+ *	@rsv: the reservation
+ *
+ *	@grp_goal: The goal (group-relative).  It is where the search for a
+ *		free reservable space should start from.
+ *		if we have a grp_goal(grp_goal >0 ), then start from there,
+ *		no grp_goal(grp_goal = -1), we start from the first block
+ *		of the group.
+ *
+ *	@sb: the super block
+ *	@group: the group we are trying to allocate in
+ *	@bitmap_bh: the block group block bitmap
+ *
+ */
+static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv,
+		ext4_grpblk_t grp_goal, struct super_block *sb,
+		unsigned int group, struct buffer_head *bitmap_bh)
+{
+	struct ext4_reserve_window_node *search_head;
+	ext4_fsblk_t group_first_block, group_end_block, start_block;
+	ext4_grpblk_t first_free_block;
+	struct rb_root *fs_rsv_root = &EXT4_SB(sb)->s_rsv_window_root;
+	unsigned long size;
+	int ret;
+	spinlock_t *rsv_lock = &EXT4_SB(sb)->s_rsv_window_lock;
+
+	group_first_block = ext4_group_first_block_no(sb, group);
+	group_end_block = group_first_block + (EXT4_BLOCKS_PER_GROUP(sb) - 1);
+
+	if (grp_goal < 0)
+		start_block = group_first_block;
+	else
+		start_block = grp_goal + group_first_block;
+
+	size = my_rsv->rsv_goal_size;
+
+	if (!rsv_is_empty(&my_rsv->rsv_window)) {
+		/*
+		 * if the old reservation is cross group boundary
+		 * and if the goal is inside the old reservation window,
+		 * we will come here when we just failed to allocate from
+		 * the first part of the window. We still have another part
+		 * that belongs to the next group. In this case, there is no
+		 * point to discard our window and try to allocate a new one
+		 * in this group(which will fail). we should
+		 * keep the reservation window, just simply move on.
+		 *
+		 * Maybe we could shift the start block of the reservation
+		 * window to the first block of next group.
+		 */
+
+		if ((my_rsv->rsv_start <= group_end_block) &&
+				(my_rsv->rsv_end > group_end_block) &&
+				(start_block >= my_rsv->rsv_start))
+			return -1;
+
+		if ((my_rsv->rsv_alloc_hit >
+		     (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {
+			/*
+			 * if the previously allocation hit ratio is
+			 * greater than 1/2, then we double the size of
+			 * the reservation window the next time,
+			 * otherwise we keep the same size window
+			 */
+			size = size * 2;
+			if (size > EXT4_MAX_RESERVE_BLOCKS)
+				size = EXT4_MAX_RESERVE_BLOCKS;
+			my_rsv->rsv_goal_size= size;
+		}
+	}
+
+	spin_lock(rsv_lock);
+	/*
+	 * shift the search start to the window near the goal block
+	 */
+	search_head = search_reserve_window(fs_rsv_root, start_block);
+
+	/*
+	 * find_next_reservable_window() simply finds a reservable window
+	 * inside the given range(start_block, group_end_block).
+	 *
+	 * To make sure the reservation window has a free bit inside it, we
+	 * need to check the bitmap after we found a reservable window.
+	 */
+retry:
+	ret = find_next_reservable_window(search_head, my_rsv, sb,
+						start_block, group_end_block);
+
+	if (ret == -1) {
+		if (!rsv_is_empty(&my_rsv->rsv_window))
+			rsv_window_remove(sb, my_rsv);
+		spin_unlock(rsv_lock);
+		return -1;
+	}
+
+	/*
+	 * On success, find_next_reservable_window() returns the
+	 * reservation window where there is a reservable space after it.
+	 * Before we reserve this reservable space, we need
+	 * to make sure there is at least a free block inside this region.
+	 *
+	 * searching the first free bit on the block bitmap and copy of
+	 * last committed bitmap alternatively, until we found a allocatable
+	 * block. Search start from the start block of the reservable space
+	 * we just found.
+	 */
+	spin_unlock(rsv_lock);
+	first_free_block = bitmap_search_next_usable_block(
+			my_rsv->rsv_start - group_first_block,
+			bitmap_bh, group_end_block - group_first_block + 1);
+
+	if (first_free_block < 0) {
+		/*
+		 * no free block left on the bitmap, no point
+		 * to reserve the space. return failed.
+		 */
+		spin_lock(rsv_lock);
+		if (!rsv_is_empty(&my_rsv->rsv_window))
+			rsv_window_remove(sb, my_rsv);
+		spin_unlock(rsv_lock);
+		return -1;		/* failed */
+	}
+
+	start_block = first_free_block + group_first_block;
+	/*
+	 * check if the first free block is within the
+	 * free space we just reserved
+	 */
+	if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end)
+		return 0;		/* success */
+	/*
+	 * if the first free bit we found is out of the reservable space
+	 * continue search for next reservable space,
+	 * start from where the free block is,
+	 * we also shift the list head to where we stopped last time
+	 */
+	search_head = my_rsv;
+	spin_lock(rsv_lock);
+	goto retry;
+}
+
+/**
+ * try_to_extend_reservation()
+ * @my_rsv:		given reservation window
+ * @sb:			super block
+ * @size:		the delta to extend
+ *
+ * Attempt to expand the reservation window large enough to have
+ * required number of free blocks
+ *
+ * Since ext4_try_to_allocate() will always allocate blocks within
+ * the reservation window range, if the window size is too small,
+ * multiple blocks allocation has to stop at the end of the reservation
+ * window. To make this more efficient, given the total number of
+ * blocks needed and the current size of the window, we try to
+ * expand the reservation window size if necessary on a best-effort
+ * basis before ext4_new_blocks() tries to allocate blocks,
+ */
+static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv,
+			struct super_block *sb, int size)
+{
+	struct ext4_reserve_window_node *next_rsv;
+	struct rb_node *next;
+	spinlock_t *rsv_lock = &EXT4_SB(sb)->s_rsv_window_lock;
+
+	if (!spin_trylock(rsv_lock))
+		return;
+
+	next = rb_next(&my_rsv->rsv_node);
+
+	if (!next)
+		my_rsv->rsv_end += size;
+	else {
+		next_rsv = list_entry(next, struct ext4_reserve_window_node, rsv_node);
+
+		if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
+			my_rsv->rsv_end += size;
+		else
+			my_rsv->rsv_end = next_rsv->rsv_start - 1;
+	}
+	spin_unlock(rsv_lock);
+}
+
+/**
+ * ext4_try_to_allocate_with_rsv()
+ * @sb:			superblock
+ * @handle:		handle to this transaction
+ * @group:		given allocation block group
+ * @bitmap_bh:		bufferhead holds the block bitmap
+ * @grp_goal:		given target block within the group
+ * @count:		target number of blocks to allocate
+ * @my_rsv:		reservation window
+ * @errp:		pointer to store the error code
+ *
+ * This is the main function used to allocate a new block and its reservation
+ * window.
+ *
+ * Each time when a new block allocation is need, first try to allocate from
+ * its own reservation.  If it does not have a reservation window, instead of
+ * looking for a free bit on bitmap first, then look up the reservation list to
+ * see if it is inside somebody else's reservation window, we try to allocate a
+ * reservation window for it starting from the goal first. Then do the block
+ * allocation within the reservation window.
+ *
+ * This will avoid keeping on searching the reservation list again and
+ * again when somebody is looking for a free block (without
+ * reservation), and there are lots of free blocks, but they are all
+ * being reserved.
+ *
+ * We use a red-black tree for the per-filesystem reservation list.
+ *
+ */
+static ext4_grpblk_t
+ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
+			unsigned int group, struct buffer_head *bitmap_bh,
+			ext4_grpblk_t grp_goal,
+			struct ext4_reserve_window_node * my_rsv,
+			unsigned long *count, int *errp)
+{
+	ext4_fsblk_t group_first_block, group_last_block;
+	ext4_grpblk_t ret = 0;
+	int fatal;
+	unsigned long num = *count;
+
+	*errp = 0;
+
+	/*
+	 * Make sure we use undo access for the bitmap, because it is critical
+	 * that we do the frozen_data COW on bitmap buffers in all cases even
+	 * if the buffer is in BJ_Forget state in the committing transaction.
+	 */
+	BUFFER_TRACE(bitmap_bh, "get undo access for new block");
+	fatal = ext4_journal_get_undo_access(handle, bitmap_bh);
+	if (fatal) {
+		*errp = fatal;
+		return -1;
+	}
+
+	/*
+	 * we don't deal with reservation when
+	 * filesystem is mounted without reservation
+	 * or the file is not a regular file
+	 * or last attempt to allocate a block with reservation turned on failed
+	 */
+	if (my_rsv == NULL ) {
+		ret = ext4_try_to_allocate(sb, handle, group, bitmap_bh,
+						grp_goal, count, NULL);
+		goto out;
+	}
+	/*
+	 * grp_goal is a group relative block number (if there is a goal)
+	 * 0 < grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
+	 * first block is a filesystem wide block number
+	 * first block is the block number of the first block in this group
+	 */
+	group_first_block = ext4_group_first_block_no(sb, group);
+	group_last_block = group_first_block + (EXT4_BLOCKS_PER_GROUP(sb) - 1);
+
+	/*
+	 * Basically we will allocate a new block from inode's reservation
+	 * window.
+	 *
+	 * We need to allocate a new reservation window, if:
+	 * a) inode does not have a reservation window; or
+	 * b) last attempt to allocate a block from existing reservation
+	 *    failed; or
+	 * c) we come here with a goal and with a reservation window
+	 *
+	 * We do not need to allocate a new reservation window if we come here
+	 * at the beginning with a goal and the goal is inside the window, or
+	 * we don't have a goal but already have a reservation window.
+	 * then we could go to allocate from the reservation window directly.
+	 */
+	while (1) {
+		if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
+			!goal_in_my_reservation(&my_rsv->rsv_window,
+						grp_goal, group, sb)) {
+			if (my_rsv->rsv_goal_size < *count)
+				my_rsv->rsv_goal_size = *count;
+			ret = alloc_new_reservation(my_rsv, grp_goal, sb,
+							group, bitmap_bh);
+			if (ret < 0)
+				break;			/* failed */
+
+			if (!goal_in_my_reservation(&my_rsv->rsv_window,
+							grp_goal, group, sb))
+				grp_goal = -1;
+		} else if (grp_goal > 0 &&
+			  (my_rsv->rsv_end-grp_goal+1) < *count)
+			try_to_extend_reservation(my_rsv, sb,
+					*count-my_rsv->rsv_end + grp_goal - 1);
+
+		if ((my_rsv->rsv_start > group_last_block) ||
+				(my_rsv->rsv_end < group_first_block)) {
+			rsv_window_dump(&EXT4_SB(sb)->s_rsv_window_root, 1);
+			BUG();
+		}
+		ret = ext4_try_to_allocate(sb, handle, group, bitmap_bh,
+					   grp_goal, &num, &my_rsv->rsv_window);
+		if (ret >= 0) {
+			my_rsv->rsv_alloc_hit += num;
+			*count = num;
+			break;				/* succeed */
+		}
+		num = *count;
+	}
+out:
+	if (ret >= 0) {
+		BUFFER_TRACE(bitmap_bh, "journal_dirty_metadata for "
+					"bitmap block");
+		fatal = ext4_journal_dirty_metadata(handle, bitmap_bh);
+		if (fatal) {
+			*errp = fatal;
+			return -1;
+		}
+		return ret;
+	}
+
+	BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
+	ext4_journal_release_buffer(handle, bitmap_bh);
+	return ret;
+}
+
+/**
+ * ext4_has_free_blocks()
+ * @sbi:		in-core super block structure.
+ *
+ * Check if filesystem has at least 1 free block available for allocation.
+ */
+static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
+{
+	ext4_fsblk_t free_blocks, root_blocks;
+
+	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+	root_blocks = ext4_r_blocks_count(sbi->s_es);
+	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
+		sbi->s_resuid != current->fsuid &&
+		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+		return 0;
+	}
+	return 1;
+}
+
+/**
+ * ext4_should_retry_alloc()
+ * @sb:			super block
+ * @retries		number of attemps has been made
+ *
+ * ext4_should_retry_alloc() is called when ENOSPC is returned, and if
+ * it is profitable to retry the operation, this function will wait
+ * for the current or commiting transaction to complete, and then
+ * return TRUE.
+ *
+ * if the total number of retries exceed three times, return FALSE.
+ */
+int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+{
+	if (!ext4_has_free_blocks(EXT4_SB(sb)) || (*retries)++ > 3)
+		return 0;
+
+	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
+
+	return jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
+}
+
+/**
+ * ext4_new_blocks() -- core block(s) allocation function
+ * @handle:		handle to this transaction
+ * @inode:		file inode
+ * @goal:		given target block(filesystem wide)
+ * @count:		target number of blocks to allocate
+ * @errp:		error code
+ *
+ * ext4_new_blocks uses a goal block to assist allocation.  It tries to
+ * allocate block(s) from the block group contains the goal block first. If that
+ * fails, it will try to allocate block(s) from other block groups without
+ * any specific goal block.
+ *
+ */
+ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
+			ext4_fsblk_t goal, unsigned long *count, int *errp)
+{
+	struct buffer_head *bitmap_bh = NULL;
+	struct buffer_head *gdp_bh;
+	unsigned long group_no;
+	int goal_group;
+	ext4_grpblk_t grp_target_blk;	/* blockgroup relative goal block */
+	ext4_grpblk_t grp_alloc_blk;	/* blockgroup-relative allocated block*/
+	ext4_fsblk_t ret_block;		/* filesyetem-wide allocated block */
+	int bgi;			/* blockgroup iteration index */
+	int fatal = 0, err;
+	int performed_allocation = 0;
+	ext4_grpblk_t free_blocks;	/* number of free blocks in a group */
+	struct super_block *sb;
+	struct ext4_group_desc *gdp;
+	struct ext4_super_block *es;
+	struct ext4_sb_info *sbi;
+	struct ext4_reserve_window_node *my_rsv = NULL;
+	struct ext4_block_alloc_info *block_i;
+	unsigned short windowsz = 0;
+#ifdef EXT4FS_DEBUG
+	static int goal_hits, goal_attempts;
+#endif
+	unsigned long ngroups;
+	unsigned long num = *count;
+
+	*errp = -ENOSPC;
+	sb = inode->i_sb;
+	if (!sb) {
+		printk("ext4_new_block: nonexistent device");
+		return 0;
+	}
+
+	/*
+	 * Check quota for allocation of this block.
+	 */
+	if (DQUOT_ALLOC_BLOCK(inode, num)) {
+		*errp = -EDQUOT;
+		return 0;
+	}
+
+	sbi = EXT4_SB(sb);
+	es = EXT4_SB(sb)->s_es;
+	ext4_debug("goal=%lu.\n", goal);
+	/*
+	 * Allocate a block from reservation only when
+	 * filesystem is mounted with reservation(default,-o reservation), and
+	 * it's a regular file, and
+	 * the desired window size is greater than 0 (One could use ioctl
+	 * command EXT4_IOC_SETRSVSZ to set the window size to 0 to turn off
+	 * reservation on that particular file)
+	 */
+	block_i = EXT4_I(inode)->i_block_alloc_info;
+	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
+		my_rsv = &block_i->rsv_window_node;
+
+	if (!ext4_has_free_blocks(sbi)) {
+		*errp = -ENOSPC;
+		goto out;
+	}
+
+	/*
+	 * First, test whether the goal block is free.
+	 */
+	if (goal < le32_to_cpu(es->s_first_data_block) ||
+	    goal >= ext4_blocks_count(es))
+		goal = le32_to_cpu(es->s_first_data_block);
+	ext4_get_group_no_and_offset(sb, goal, &group_no, &grp_target_blk);
+	goal_group = group_no;
+retry_alloc:
+	gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
+	if (!gdp)
+		goto io_error;
+
+	free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
+	/*
+	 * if there is not enough free blocks to make a new resevation
+	 * turn off reservation for this allocation
+	 */
+	if (my_rsv && (free_blocks < windowsz)
+		&& (rsv_is_empty(&my_rsv->rsv_window)))
+		my_rsv = NULL;
+
+	if (free_blocks > 0) {
+		bitmap_bh = read_block_bitmap(sb, group_no);
+		if (!bitmap_bh)
+			goto io_error;
+		grp_alloc_blk = ext4_try_to_allocate_with_rsv(sb, handle,
+					group_no, bitmap_bh, grp_target_blk,
+					my_rsv,	&num, &fatal);
+		if (fatal)
+			goto out;
+		if (grp_alloc_blk >= 0)
+			goto allocated;
+	}
+
+	ngroups = EXT4_SB(sb)->s_groups_count;
+	smp_rmb();
+
+	/*
+	 * Now search the rest of the groups.  We assume that
+	 * i and gdp correctly point to the last group visited.
+	 */
+	for (bgi = 0; bgi < ngroups; bgi++) {
+		group_no++;
+		if (group_no >= ngroups)
+			group_no = 0;
+		gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
+		if (!gdp) {
+			*errp = -EIO;
+			goto out;
+		}
+		free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
+		/*
+		 * skip this group if the number of
+		 * free blocks is less than half of the reservation
+		 * window size.
+		 */
+		if (free_blocks <= (windowsz/2))
+			continue;
+
+		brelse(bitmap_bh);
+		bitmap_bh = read_block_bitmap(sb, group_no);
+		if (!bitmap_bh)
+			goto io_error;
+		/*
+		 * try to allocate block(s) from this group, without a goal(-1).
+		 */
+		grp_alloc_blk = ext4_try_to_allocate_with_rsv(sb, handle,
+					group_no, bitmap_bh, -1, my_rsv,
+					&num, &fatal);
+		if (fatal)
+			goto out;
+		if (grp_alloc_blk >= 0)
+			goto allocated;
+	}
+	/*
+	 * We may end up a bogus ealier ENOSPC error due to
+	 * filesystem is "full" of reservations, but
+	 * there maybe indeed free blocks avaliable on disk
+	 * In this case, we just forget about the reservations
+	 * just do block allocation as without reservations.
+	 */
+	if (my_rsv) {
+		my_rsv = NULL;
+		group_no = goal_group;
+		goto retry_alloc;
+	}
+	/* No space left on the device */
+	*errp = -ENOSPC;
+	goto out;
+
+allocated:
+
+	ext4_debug("using block group %d(%d)\n",
+			group_no, gdp->bg_free_blocks_count);
+
+	BUFFER_TRACE(gdp_bh, "get_write_access");
+	fatal = ext4_journal_get_write_access(handle, gdp_bh);
+	if (fatal)
+		goto out;
+
+	ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
+
+	if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+	    in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+	    in_range(ret_block, ext4_inode_table(sb, gdp),
+		     EXT4_SB(sb)->s_itb_per_group) ||
+	    in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
+		     EXT4_SB(sb)->s_itb_per_group))
+		ext4_error(sb, "ext4_new_block",
+			    "Allocating block in system zone - "
+			    "blocks from %llu, length %lu",
+			     ret_block, num);
+
+	performed_allocation = 1;
+
+#ifdef CONFIG_JBD_DEBUG
+	{
+		struct buffer_head *debug_bh;
+
+		/* Record bitmap buffer state in the newly allocated block */
+		debug_bh = sb_find_get_block(sb, ret_block);
+		if (debug_bh) {
+			BUFFER_TRACE(debug_bh, "state when allocated");
+			BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap state");
+			brelse(debug_bh);
+		}
+	}
+	jbd_lock_bh_state(bitmap_bh);
+	spin_lock(sb_bgl_lock(sbi, group_no));
+	if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data) {
+		int i;
+
+		for (i = 0; i < num; i++) {
+			if (ext4_test_bit(grp_alloc_blk+i,
+					bh2jh(bitmap_bh)->b_committed_data)) {
+				printk("%s: block was unexpectedly set in "
+					"b_committed_data\n", __FUNCTION__);
+			}
+		}
+	}
+	ext4_debug("found bit %d\n", grp_alloc_blk);
+	spin_unlock(sb_bgl_lock(sbi, group_no));
+	jbd_unlock_bh_state(bitmap_bh);
+#endif
+
+	if (ret_block + num - 1 >= ext4_blocks_count(es)) {
+		ext4_error(sb, "ext4_new_block",
+			    "block(%llu) >= blocks count(%llu) - "
+			    "block_group = %lu, es == %p ", ret_block,
+			ext4_blocks_count(es), group_no, es);
+		goto out;
+	}
+
+	/*
+	 * It is up to the caller to add the new buffer to a journal
+	 * list of some description.  We don't know in advance whether
+	 * the caller wants to use it as metadata or data.
+	 */
+	ext4_debug("allocating block %lu. Goal hits %d of %d.\n",
+			ret_block, goal_hits, goal_attempts);
+
+	spin_lock(sb_bgl_lock(sbi, group_no));
+	gdp->bg_free_blocks_count =
+			cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
+	spin_unlock(sb_bgl_lock(sbi, group_no));
+	percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
+
+	BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
+	err = ext4_journal_dirty_metadata(handle, gdp_bh);
+	if (!fatal)
+		fatal = err;
+
+	sb->s_dirt = 1;
+	if (fatal)
+		goto out;
+
+	*errp = 0;
+	brelse(bitmap_bh);
+	DQUOT_FREE_BLOCK(inode, *count-num);
+	*count = num;
+	return ret_block;
+
+io_error:
+	*errp = -EIO;
+out:
+	if (fatal) {
+		*errp = fatal;
+		ext4_std_error(sb, fatal);
+	}
+	/*
+	 * Undo the block allocation
+	 */
+	if (!performed_allocation)
+		DQUOT_FREE_BLOCK(inode, *count);
+	brelse(bitmap_bh);
+	return 0;
+}
+
+ext4_fsblk_t ext4_new_block(handle_t *handle, struct inode *inode,
+			ext4_fsblk_t goal, int *errp)
+{
+	unsigned long count = 1;
+
+	return ext4_new_blocks(handle, inode, goal, &count, errp);
+}
+
+/**
+ * ext4_count_free_blocks() -- count filesystem free blocks
+ * @sb:		superblock
+ *
+ * Adds up the number of free blocks from each block group.
+ */
+ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+{
+	ext4_fsblk_t desc_count;
+	struct ext4_group_desc *gdp;
+	int i;
+	unsigned long ngroups = EXT4_SB(sb)->s_groups_count;
+#ifdef EXT4FS_DEBUG
+	struct ext4_super_block *es;
+	ext4_fsblk_t bitmap_count;
+	unsigned long x;
+	struct buffer_head *bitmap_bh = NULL;
+
+	es = EXT4_SB(sb)->s_es;
+	desc_count = 0;
+	bitmap_count = 0;
+	gdp = NULL;
+
+	smp_rmb();
+	for (i = 0; i < ngroups; i++) {
+		gdp = ext4_get_group_desc(sb, i, NULL);
+		if (!gdp)
+			continue;
+		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
+		brelse(bitmap_bh);
+		bitmap_bh = read_block_bitmap(sb, i);
+		if (bitmap_bh == NULL)
+			continue;
+
+		x = ext4_count_free(bitmap_bh, sb->s_blocksize);
+		printk("group %d: stored = %d, counted = %lu\n",
+			i, le16_to_cpu(gdp->bg_free_blocks_count), x);
+		bitmap_count += x;
+	}
+	brelse(bitmap_bh);
+	printk("ext4_count_free_blocks: stored = %llu"
+		", computed = %llu, %llu\n",
+	       EXT4_FREE_BLOCKS_COUNT(es),
+		desc_count, bitmap_count);
+	return bitmap_count;
+#else
+	desc_count = 0;
+	smp_rmb();
+	for (i = 0; i < ngroups; i++) {
+		gdp = ext4_get_group_desc(sb, i, NULL);
+		if (!gdp)
+			continue;
+		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
+	}
+
+	return desc_count;
+#endif
+}
+
+static inline int
+block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map)
+{
+	ext4_grpblk_t offset;
+
+	ext4_get_group_no_and_offset(sb, block, NULL, &offset);
+	return ext4_test_bit (offset, map);
+}
+
+static inline int test_root(int a, int b)
+{
+	int num = b;
+
+	while (a > num)
+		num *= b;
+	return num == a;
+}
+
+static int ext4_group_sparse(int group)
+{
+	if (group <= 1)
+		return 1;
+	if (!(group & 1))
+		return 0;
+	return (test_root(group, 7) || test_root(group, 5) ||
+		test_root(group, 3));
+}
+
+/**
+ *	ext4_bg_has_super - number of blocks used by the superblock in group
+ *	@sb: superblock for filesystem
+ *	@group: group number to check
+ *
+ *	Return the number of blocks used by the superblock (primary or backup)
+ *	in this group.  Currently this will be only 0 or 1.
+ */
+int ext4_bg_has_super(struct super_block *sb, int group)
+{
+	if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+				EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
+			!ext4_group_sparse(group))
+		return 0;
+	return 1;
+}
+
+static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, int group)
+{
+	unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
+	unsigned long first = metagroup * EXT4_DESC_PER_BLOCK(sb);
+	unsigned long last = first + EXT4_DESC_PER_BLOCK(sb) - 1;
+
+	if (group == first || group == first + 1 || group == last)
+		return 1;
+	return 0;
+}
+
+static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, int group)
+{
+	if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+				EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
+			!ext4_group_sparse(group))
+		return 0;
+	return EXT4_SB(sb)->s_gdb_count;
+}
+
+/**
+ *	ext4_bg_num_gdb - number of blocks used by the group table in group
+ *	@sb: superblock for filesystem
+ *	@group: group number to check
+ *
+ *	Return the number of blocks used by the group descriptor table
+ *	(primary or backup) in this group.  In the future there may be a
+ *	different number of descriptor blocks in each group.
+ */
+unsigned long ext4_bg_num_gdb(struct super_block *sb, int group)
+{
+	unsigned long first_meta_bg =
+			le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
+	unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
+
+	if (!EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) ||
+			metagroup < first_meta_bg)
+		return ext4_bg_num_gdb_nometa(sb,group);
+
+	return ext4_bg_num_gdb_meta(sb,group);
+
+}
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
new file mode 100644
index 0000000..11e93c1
--- /dev/null
+++ b/fs/ext4/bitmap.c
@@ -0,0 +1,32 @@
+/*
+ *  linux/fs/ext4/bitmap.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+
+#ifdef EXT4FS_DEBUG
+
+static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+
+unsigned long ext4_count_free (struct buffer_head * map, unsigned int numchars)
+{
+	unsigned int i;
+	unsigned long sum = 0;
+
+	if (!map)
+		return (0);
+	for (i = 0; i < numchars; i++)
+		sum += nibblemap[map->b_data[i] & 0xf] +
+			nibblemap[(map->b_data[i] >> 4) & 0xf];
+	return (sum);
+}
+
+#endif  /*  EXT4FS_DEBUG  */
+
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
new file mode 100644
index 0000000..f859578
--- /dev/null
+++ b/fs/ext4/dir.c
@@ -0,0 +1,518 @@
+/*
+ *  linux/fs/ext4/dir.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/dir.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  ext4 directory handling functions
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *
+ * Hash Tree Directory indexing (c) 2001  Daniel Phillips
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/rbtree.h>
+
+static unsigned char ext4_filetype_table[] = {
+	DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
+};
+
+static int ext4_readdir(struct file *, void *, filldir_t);
+static int ext4_dx_readdir(struct file * filp,
+			   void * dirent, filldir_t filldir);
+static int ext4_release_dir (struct inode * inode,
+				struct file * filp);
+
+const struct file_operations ext4_dir_operations = {
+	.llseek		= generic_file_llseek,
+	.read		= generic_read_dir,
+	.readdir	= ext4_readdir,		/* we take BKL. needed?*/
+	.ioctl		= ext4_ioctl,		/* BKL held */
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext4_compat_ioctl,
+#endif
+	.fsync		= ext4_sync_file,	/* BKL held */
+#ifdef CONFIG_EXT4_INDEX
+	.release	= ext4_release_dir,
+#endif
+};
+
+
+static unsigned char get_dtype(struct super_block *sb, int filetype)
+{
+	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FILETYPE) ||
+	    (filetype >= EXT4_FT_MAX))
+		return DT_UNKNOWN;
+
+	return (ext4_filetype_table[filetype]);
+}
+
+
+int ext4_check_dir_entry (const char * function, struct inode * dir,
+			  struct ext4_dir_entry_2 * de,
+			  struct buffer_head * bh,
+			  unsigned long offset)
+{
+	const char * error_msg = NULL;
+	const int rlen = le16_to_cpu(de->rec_len);
+
+	if (rlen < EXT4_DIR_REC_LEN(1))
+		error_msg = "rec_len is smaller than minimal";
+	else if (rlen % 4 != 0)
+		error_msg = "rec_len % 4 != 0";
+	else if (rlen < EXT4_DIR_REC_LEN(de->name_len))
+		error_msg = "rec_len is too small for name_len";
+	else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
+		error_msg = "directory entry across blocks";
+	else if (le32_to_cpu(de->inode) >
+			le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))
+		error_msg = "inode out of bounds";
+
+	if (error_msg != NULL)
+		ext4_error (dir->i_sb, function,
+			"bad entry in directory #%lu: %s - "
+			"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+			dir->i_ino, error_msg, offset,
+			(unsigned long) le32_to_cpu(de->inode),
+			rlen, de->name_len);
+	return error_msg == NULL ? 1 : 0;
+}
+
+static int ext4_readdir(struct file * filp,
+			 void * dirent, filldir_t filldir)
+{
+	int error = 0;
+	unsigned long offset;
+	int i, stored;
+	struct ext4_dir_entry_2 *de;
+	struct super_block *sb;
+	int err;
+	struct inode *inode = filp->f_dentry->d_inode;
+	int ret = 0;
+
+	sb = inode->i_sb;
+
+#ifdef CONFIG_EXT4_INDEX
+	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				    EXT4_FEATURE_COMPAT_DIR_INDEX) &&
+	    ((EXT4_I(inode)->i_flags & EXT4_INDEX_FL) ||
+	     ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
+		err = ext4_dx_readdir(filp, dirent, filldir);
+		if (err != ERR_BAD_DX_DIR) {
+			ret = err;
+			goto out;
+		}
+		/*
+		 * We don't set the inode dirty flag since it's not
+		 * critical that it get flushed back to the disk.
+		 */
+		EXT4_I(filp->f_dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
+	}
+#endif
+	stored = 0;
+	offset = filp->f_pos & (sb->s_blocksize - 1);
+
+	while (!error && !stored && filp->f_pos < inode->i_size) {
+		unsigned long blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
+		struct buffer_head map_bh;
+		struct buffer_head *bh = NULL;
+
+		map_bh.b_state = 0;
+		err = ext4_get_blocks_wrap(NULL, inode, blk, 1, &map_bh, 0, 0);
+		if (err > 0) {
+			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
+				&filp->f_ra,
+				filp,
+				map_bh.b_blocknr >>
+					(PAGE_CACHE_SHIFT - inode->i_blkbits),
+				1);
+			bh = ext4_bread(NULL, inode, blk, 0, &err);
+		}
+
+		/*
+		 * We ignore I/O errors on directories so users have a chance
+		 * of recovering data when there's a bad sector
+		 */
+		if (!bh) {
+			ext4_error (sb, "ext4_readdir",
+				"directory #%lu contains a hole at offset %lu",
+				inode->i_ino, (unsigned long)filp->f_pos);
+			filp->f_pos += sb->s_blocksize - offset;
+			continue;
+		}
+
+revalidate:
+		/* If the dir block has changed since the last call to
+		 * readdir(2), then we might be pointing to an invalid
+		 * dirent right now.  Scan from the start of the block
+		 * to make sure. */
+		if (filp->f_version != inode->i_version) {
+			for (i = 0; i < sb->s_blocksize && i < offset; ) {
+				de = (struct ext4_dir_entry_2 *)
+					(bh->b_data + i);
+				/* It's too expensive to do a full
+				 * dirent test each time round this
+				 * loop, but we do have to test at
+				 * least that it is non-zero.  A
+				 * failure will be detected in the
+				 * dirent test below. */
+				if (le16_to_cpu(de->rec_len) <
+						EXT4_DIR_REC_LEN(1))
+					break;
+				i += le16_to_cpu(de->rec_len);
+			}
+			offset = i;
+			filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
+				| offset;
+			filp->f_version = inode->i_version;
+		}
+
+		while (!error && filp->f_pos < inode->i_size
+		       && offset < sb->s_blocksize) {
+			de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
+			if (!ext4_check_dir_entry ("ext4_readdir", inode, de,
+						   bh, offset)) {
+				/*
+				 * On error, skip the f_pos to the next block
+				 */
+				filp->f_pos = (filp->f_pos |
+						(sb->s_blocksize - 1)) + 1;
+				brelse (bh);
+				ret = stored;
+				goto out;
+			}
+			offset += le16_to_cpu(de->rec_len);
+			if (le32_to_cpu(de->inode)) {
+				/* We might block in the next section
+				 * if the data destination is
+				 * currently swapped out.  So, use a
+				 * version stamp to detect whether or
+				 * not the directory has been modified
+				 * during the copy operation.
+				 */
+				unsigned long version = filp->f_version;
+
+				error = filldir(dirent, de->name,
+						de->name_len,
+						filp->f_pos,
+						le32_to_cpu(de->inode),
+						get_dtype(sb, de->file_type));
+				if (error)
+					break;
+				if (version != filp->f_version)
+					goto revalidate;
+				stored ++;
+			}
+			filp->f_pos += le16_to_cpu(de->rec_len);
+		}
+		offset = 0;
+		brelse (bh);
+	}
+out:
+	return ret;
+}
+
+#ifdef CONFIG_EXT4_INDEX
+/*
+ * These functions convert from the major/minor hash to an f_pos
+ * value.
+ *
+ * Currently we only use major hash numer.  This is unfortunate, but
+ * on 32-bit machines, the same VFS interface is used for lseek and
+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of
+ * lseek/telldir/seekdir will blow out spectacularly, and from within
+ * the ext2 low-level routine, we don't know if we're being called by
+ * a 64-bit version of the system call or the 32-bit version of the
+ * system call.  Worse yet, NFSv2 only allows for a 32-bit readdir
+ * cookie.  Sigh.
+ */
+#define hash2pos(major, minor)	(major >> 1)
+#define pos2maj_hash(pos)	((pos << 1) & 0xffffffff)
+#define pos2min_hash(pos)	(0)
+
+/*
+ * This structure holds the nodes of the red-black tree used to store
+ * the directory entry in hash order.
+ */
+struct fname {
+	__u32		hash;
+	__u32		minor_hash;
+	struct rb_node	rb_hash;
+	struct fname	*next;
+	__u32		inode;
+	__u8		name_len;
+	__u8		file_type;
+	char		name[0];
+};
+
+/*
+ * This functoin implements a non-recursive way of freeing all of the
+ * nodes in the red-black tree.
+ */
+static void free_rb_tree_fname(struct rb_root *root)
+{
+	struct rb_node	*n = root->rb_node;
+	struct rb_node	*parent;
+	struct fname	*fname;
+
+	while (n) {
+		/* Do the node's children first */
+		if ((n)->rb_left) {
+			n = n->rb_left;
+			continue;
+		}
+		if (n->rb_right) {
+			n = n->rb_right;
+			continue;
+		}
+		/*
+		 * The node has no children; free it, and then zero
+		 * out parent's link to it.  Finally go to the
+		 * beginning of the loop and try to free the parent
+		 * node.
+		 */
+		parent = rb_parent(n);
+		fname = rb_entry(n, struct fname, rb_hash);
+		while (fname) {
+			struct fname * old = fname;
+			fname = fname->next;
+			kfree (old);
+		}
+		if (!parent)
+			root->rb_node = NULL;
+		else if (parent->rb_left == n)
+			parent->rb_left = NULL;
+		else if (parent->rb_right == n)
+			parent->rb_right = NULL;
+		n = parent;
+	}
+	root->rb_node = NULL;
+}
+
+
+static struct dir_private_info *create_dir_info(loff_t pos)
+{
+	struct dir_private_info *p;
+
+	p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL);
+	if (!p)
+		return NULL;
+	p->root.rb_node = NULL;
+	p->curr_node = NULL;
+	p->extra_fname = NULL;
+	p->last_pos = 0;
+	p->curr_hash = pos2maj_hash(pos);
+	p->curr_minor_hash = pos2min_hash(pos);
+	p->next_hash = 0;
+	return p;
+}
+
+void ext4_htree_free_dir_info(struct dir_private_info *p)
+{
+	free_rb_tree_fname(&p->root);
+	kfree(p);
+}
+
+/*
+ * Given a directory entry, enter it into the fname rb tree.
+ */
+int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+			     __u32 minor_hash,
+			     struct ext4_dir_entry_2 *dirent)
+{
+	struct rb_node **p, *parent = NULL;
+	struct fname * fname, *new_fn;
+	struct dir_private_info *info;
+	int len;
+
+	info = (struct dir_private_info *) dir_file->private_data;
+	p = &info->root.rb_node;
+
+	/* Create and allocate the fname structure */
+	len = sizeof(struct fname) + dirent->name_len + 1;
+	new_fn = kzalloc(len, GFP_KERNEL);
+	if (!new_fn)
+		return -ENOMEM;
+	new_fn->hash = hash;
+	new_fn->minor_hash = minor_hash;
+	new_fn->inode = le32_to_cpu(dirent->inode);
+	new_fn->name_len = dirent->name_len;
+	new_fn->file_type = dirent->file_type;
+	memcpy(new_fn->name, dirent->name, dirent->name_len);
+	new_fn->name[dirent->name_len] = 0;
+
+	while (*p) {
+		parent = *p;
+		fname = rb_entry(parent, struct fname, rb_hash);
+
+		/*
+		 * If the hash and minor hash match up, then we put
+		 * them on a linked list.  This rarely happens...
+		 */
+		if ((new_fn->hash == fname->hash) &&
+		    (new_fn->minor_hash == fname->minor_hash)) {
+			new_fn->next = fname->next;
+			fname->next = new_fn;
+			return 0;
+		}
+
+		if (new_fn->hash < fname->hash)
+			p = &(*p)->rb_left;
+		else if (new_fn->hash > fname->hash)
+			p = &(*p)->rb_right;
+		else if (new_fn->minor_hash < fname->minor_hash)
+			p = &(*p)->rb_left;
+		else /* if (new_fn->minor_hash > fname->minor_hash) */
+			p = &(*p)->rb_right;
+	}
+
+	rb_link_node(&new_fn->rb_hash, parent, p);
+	rb_insert_color(&new_fn->rb_hash, &info->root);
+	return 0;
+}
+
+
+
+/*
+ * This is a helper function for ext4_dx_readdir.  It calls filldir
+ * for all entres on the fname linked list.  (Normally there is only
+ * one entry on the linked list, unless there are 62 bit hash collisions.)
+ */
+static int call_filldir(struct file * filp, void * dirent,
+			filldir_t filldir, struct fname *fname)
+{
+	struct dir_private_info *info = filp->private_data;
+	loff_t	curr_pos;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block * sb;
+	int error;
+
+	sb = inode->i_sb;
+
+	if (!fname) {
+		printk("call_filldir: called with null fname?!?\n");
+		return 0;
+	}
+	curr_pos = hash2pos(fname->hash, fname->minor_hash);
+	while (fname) {
+		error = filldir(dirent, fname->name,
+				fname->name_len, curr_pos,
+				fname->inode,
+				get_dtype(sb, fname->file_type));
+		if (error) {
+			filp->f_pos = curr_pos;
+			info->extra_fname = fname->next;
+			return error;
+		}
+		fname = fname->next;
+	}
+	return 0;
+}
+
+static int ext4_dx_readdir(struct file * filp,
+			 void * dirent, filldir_t filldir)
+{
+	struct dir_private_info *info = filp->private_data;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct fname *fname;
+	int	ret;
+
+	if (!info) {
+		info = create_dir_info(filp->f_pos);
+		if (!info)
+			return -ENOMEM;
+		filp->private_data = info;
+	}
+
+	if (filp->f_pos == EXT4_HTREE_EOF)
+		return 0;	/* EOF */
+
+	/* Some one has messed with f_pos; reset the world */
+	if (info->last_pos != filp->f_pos) {
+		free_rb_tree_fname(&info->root);
+		info->curr_node = NULL;
+		info->extra_fname = NULL;
+		info->curr_hash = pos2maj_hash(filp->f_pos);
+		info->curr_minor_hash = pos2min_hash(filp->f_pos);
+	}
+
+	/*
+	 * If there are any leftover names on the hash collision
+	 * chain, return them first.
+	 */
+	if (info->extra_fname &&
+	    call_filldir(filp, dirent, filldir, info->extra_fname))
+		goto finished;
+
+	if (!info->curr_node)
+		info->curr_node = rb_first(&info->root);
+
+	while (1) {
+		/*
+		 * Fill the rbtree if we have no more entries,
+		 * or the inode has changed since we last read in the
+		 * cached entries.
+		 */
+		if ((!info->curr_node) ||
+		    (filp->f_version != inode->i_version)) {
+			info->curr_node = NULL;
+			free_rb_tree_fname(&info->root);
+			filp->f_version = inode->i_version;
+			ret = ext4_htree_fill_tree(filp, info->curr_hash,
+						   info->curr_minor_hash,
+						   &info->next_hash);
+			if (ret < 0)
+				return ret;
+			if (ret == 0) {
+				filp->f_pos = EXT4_HTREE_EOF;
+				break;
+			}
+			info->curr_node = rb_first(&info->root);
+		}
+
+		fname = rb_entry(info->curr_node, struct fname, rb_hash);
+		info->curr_hash = fname->hash;
+		info->curr_minor_hash = fname->minor_hash;
+		if (call_filldir(filp, dirent, filldir, fname))
+			break;
+
+		info->curr_node = rb_next(info->curr_node);
+		if (!info->curr_node) {
+			if (info->next_hash == ~0) {
+				filp->f_pos = EXT4_HTREE_EOF;
+				break;
+			}
+			info->curr_hash = info->next_hash;
+			info->curr_minor_hash = 0;
+		}
+	}
+finished:
+	info->last_pos = filp->f_pos;
+	return 0;
+}
+
+static int ext4_release_dir (struct inode * inode, struct file * filp)
+{
+	if (filp->private_data)
+		ext4_htree_free_dir_info(filp->private_data);
+
+	return 0;
+}
+
+#endif
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
new file mode 100644
index 0000000..2608dce
--- /dev/null
+++ b/fs/ext4/extents.c
@@ -0,0 +1,2152 @@
+/*
+ * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ *
+ * Architecture independence:
+ *   Copyright (c) 2005, Bull S.A.
+ *   Written by Pierre Peiffer <pierre.peiffer@bull.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+ */
+
+/*
+ * Extents support for EXT4
+ *
+ * TODO:
+ *   - ext4*_error() should be used in some situations
+ *   - analyze all BUG()/BUG_ON(), use -EIO where appropriate
+ *   - smart tree reduction
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/jbd.h>
+#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/ext4_fs_extents.h>
+#include <asm/uaccess.h>
+
+
+/*
+ * ext_pblock:
+ * combine low and high parts of physical block number into ext4_fsblk_t
+ */
+static inline ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
+{
+	ext4_fsblk_t block;
+
+	block = le32_to_cpu(ex->ee_start);
+	block |= ((ext4_fsblk_t) le16_to_cpu(ex->ee_start_hi) << 31) << 1;
+	return block;
+}
+
+/*
+ * idx_pblock:
+ * combine low and high parts of a leaf physical block number into ext4_fsblk_t
+ */
+static inline ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
+{
+	ext4_fsblk_t block;
+
+	block = le32_to_cpu(ix->ei_leaf);
+	block |= ((ext4_fsblk_t) le16_to_cpu(ix->ei_leaf_hi) << 31) << 1;
+	return block;
+}
+
+/*
+ * ext4_ext_store_pblock:
+ * stores a large physical block number into an extent struct,
+ * breaking it into parts
+ */
+static inline void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb)
+{
+	ex->ee_start = cpu_to_le32((unsigned long) (pb & 0xffffffff));
+	ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
+}
+
+/*
+ * ext4_idx_store_pblock:
+ * stores a large physical block number into an index struct,
+ * breaking it into parts
+ */
+static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix, ext4_fsblk_t pb)
+{
+	ix->ei_leaf = cpu_to_le32((unsigned long) (pb & 0xffffffff));
+	ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
+}
+
+static int ext4_ext_check_header(const char *function, struct inode *inode,
+				struct ext4_extent_header *eh)
+{
+	const char *error_msg = NULL;
+
+	if (unlikely(eh->eh_magic != EXT4_EXT_MAGIC)) {
+		error_msg = "invalid magic";
+		goto corrupted;
+	}
+	if (unlikely(eh->eh_max == 0)) {
+		error_msg = "invalid eh_max";
+		goto corrupted;
+	}
+	if (unlikely(le16_to_cpu(eh->eh_entries) > le16_to_cpu(eh->eh_max))) {
+		error_msg = "invalid eh_entries";
+		goto corrupted;
+	}
+	return 0;
+
+corrupted:
+	ext4_error(inode->i_sb, function,
+			"bad header in inode #%lu: %s - magic %x, "
+			"entries %u, max %u, depth %u",
+			inode->i_ino, error_msg, le16_to_cpu(eh->eh_magic),
+			le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
+			le16_to_cpu(eh->eh_depth));
+
+	return -EIO;
+}
+
+static handle_t *ext4_ext_journal_restart(handle_t *handle, int needed)
+{
+	int err;
+
+	if (handle->h_buffer_credits > needed)
+		return handle;
+	if (!ext4_journal_extend(handle, needed))
+		return handle;
+	err = ext4_journal_restart(handle, needed);
+
+	return handle;
+}
+
+/*
+ * could return:
+ *  - EROFS
+ *  - ENOMEM
+ */
+static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
+				struct ext4_ext_path *path)
+{
+	if (path->p_bh) {
+		/* path points to block */
+		return ext4_journal_get_write_access(handle, path->p_bh);
+	}
+	/* path points to leaf/index in inode body */
+	/* we use in-core data, no need to protect them */
+	return 0;
+}
+
+/*
+ * could return:
+ *  - EROFS
+ *  - ENOMEM
+ *  - EIO
+ */
+static int ext4_ext_dirty(handle_t *handle, struct inode *inode,
+				struct ext4_ext_path *path)
+{
+	int err;
+	if (path->p_bh) {
+		/* path points to block */
+		err = ext4_journal_dirty_metadata(handle, path->p_bh);
+	} else {
+		/* path points to leaf/index in inode body */
+		err = ext4_mark_inode_dirty(handle, inode);
+	}
+	return err;
+}
+
+static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
+			      struct ext4_ext_path *path,
+			      ext4_fsblk_t block)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	ext4_fsblk_t bg_start;
+	ext4_grpblk_t colour;
+	int depth;
+
+	if (path) {
+		struct ext4_extent *ex;
+		depth = path->p_depth;
+
+		/* try to predict block placement */
+		if ((ex = path[depth].p_ext))
+			return ext_pblock(ex)+(block-le32_to_cpu(ex->ee_block));
+
+		/* it looks like index is empty;
+		 * try to find starting block from index itself */
+		if (path[depth].p_bh)
+			return path[depth].p_bh->b_blocknr;
+	}
+
+	/* OK. use inode's group */
+	bg_start = (ei->i_block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) +
+		le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_first_data_block);
+	colour = (current->pid % 16) *
+			(EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+	return bg_start + colour + block;
+}
+
+static ext4_fsblk_t
+ext4_ext_new_block(handle_t *handle, struct inode *inode,
+			struct ext4_ext_path *path,
+			struct ext4_extent *ex, int *err)
+{
+	ext4_fsblk_t goal, newblock;
+
+	goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block));
+	newblock = ext4_new_block(handle, inode, goal, err);
+	return newblock;
+}
+
+static inline int ext4_ext_space_block(struct inode *inode)
+{
+	int size;
+
+	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
+			/ sizeof(struct ext4_extent);
+#ifdef AGRESSIVE_TEST
+	if (size > 6)
+		size = 6;
+#endif
+	return size;
+}
+
+static inline int ext4_ext_space_block_idx(struct inode *inode)
+{
+	int size;
+
+	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
+			/ sizeof(struct ext4_extent_idx);
+#ifdef AGRESSIVE_TEST
+	if (size > 5)
+		size = 5;
+#endif
+	return size;
+}
+
+static inline int ext4_ext_space_root(struct inode *inode)
+{
+	int size;
+
+	size = sizeof(EXT4_I(inode)->i_data);
+	size -= sizeof(struct ext4_extent_header);
+	size /= sizeof(struct ext4_extent);
+#ifdef AGRESSIVE_TEST
+	if (size > 3)
+		size = 3;
+#endif
+	return size;
+}
+
+static inline int ext4_ext_space_root_idx(struct inode *inode)
+{
+	int size;
+
+	size = sizeof(EXT4_I(inode)->i_data);
+	size -= sizeof(struct ext4_extent_header);
+	size /= sizeof(struct ext4_extent_idx);
+#ifdef AGRESSIVE_TEST
+	if (size > 4)
+		size = 4;
+#endif
+	return size;
+}
+
+#ifdef EXT_DEBUG
+static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
+{
+	int k, l = path->p_depth;
+
+	ext_debug("path:");
+	for (k = 0; k <= l; k++, path++) {
+		if (path->p_idx) {
+		  ext_debug("  %d->%llu", le32_to_cpu(path->p_idx->ei_block),
+			    idx_pblock(path->p_idx));
+		} else if (path->p_ext) {
+			ext_debug("  %d:%d:%llu ",
+				  le32_to_cpu(path->p_ext->ee_block),
+				  le16_to_cpu(path->p_ext->ee_len),
+				  ext_pblock(path->p_ext));
+		} else
+			ext_debug("  []");
+	}
+	ext_debug("\n");
+}
+
+static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path)
+{
+	int depth = ext_depth(inode);
+	struct ext4_extent_header *eh;
+	struct ext4_extent *ex;
+	int i;
+
+	if (!path)
+		return;
+
+	eh = path[depth].p_hdr;
+	ex = EXT_FIRST_EXTENT(eh);
+
+	for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ex++) {
+		ext_debug("%d:%d:%llu ", le32_to_cpu(ex->ee_block),
+			  le16_to_cpu(ex->ee_len), ext_pblock(ex));
+	}
+	ext_debug("\n");
+}
+#else
+#define ext4_ext_show_path(inode,path)
+#define ext4_ext_show_leaf(inode,path)
+#endif
+
+static void ext4_ext_drop_refs(struct ext4_ext_path *path)
+{
+	int depth = path->p_depth;
+	int i;
+
+	for (i = 0; i <= depth; i++, path++)
+		if (path->p_bh) {
+			brelse(path->p_bh);
+			path->p_bh = NULL;
+		}
+}
+
+/*
+ * ext4_ext_binsearch_idx:
+ * binary search for the closest index of the given block
+ */
+static void
+ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int block)
+{
+	struct ext4_extent_header *eh = path->p_hdr;
+	struct ext4_extent_idx *r, *l, *m;
+
+	BUG_ON(eh->eh_magic != EXT4_EXT_MAGIC);
+	BUG_ON(le16_to_cpu(eh->eh_entries) > le16_to_cpu(eh->eh_max));
+	BUG_ON(le16_to_cpu(eh->eh_entries) <= 0);
+
+	ext_debug("binsearch for %d(idx):  ", block);
+
+	l = EXT_FIRST_INDEX(eh) + 1;
+	r = EXT_FIRST_INDEX(eh) + le16_to_cpu(eh->eh_entries) - 1;
+	while (l <= r) {
+		m = l + (r - l) / 2;
+		if (block < le32_to_cpu(m->ei_block))
+			r = m - 1;
+		else
+			l = m + 1;
+		ext_debug("%p(%u):%p(%u):%p(%u) ", l, l->ei_block,
+				m, m->ei_block, r, r->ei_block);
+	}
+
+	path->p_idx = l - 1;
+	ext_debug("  -> %d->%lld ", le32_to_cpu(path->p_idx->ei_block),
+		  idx_block(path->p_idx));
+
+#ifdef CHECK_BINSEARCH
+	{
+		struct ext4_extent_idx *chix, *ix;
+		int k;
+
+		chix = ix = EXT_FIRST_INDEX(eh);
+		for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ix++) {
+		  if (k != 0 &&
+		      le32_to_cpu(ix->ei_block) <= le32_to_cpu(ix[-1].ei_block)) {
+				printk("k=%d, ix=0x%p, first=0x%p\n", k,
+					ix, EXT_FIRST_INDEX(eh));
+				printk("%u <= %u\n",
+				       le32_to_cpu(ix->ei_block),
+				       le32_to_cpu(ix[-1].ei_block));
+			}
+			BUG_ON(k && le32_to_cpu(ix->ei_block)
+				           <= le32_to_cpu(ix[-1].ei_block));
+			if (block < le32_to_cpu(ix->ei_block))
+				break;
+			chix = ix;
+		}
+		BUG_ON(chix != path->p_idx);
+	}
+#endif
+
+}
+
+/*
+ * ext4_ext_binsearch:
+ * binary search for closest extent of the given block
+ */
+static void
+ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block)
+{
+	struct ext4_extent_header *eh = path->p_hdr;
+	struct ext4_extent *r, *l, *m;
+
+	BUG_ON(eh->eh_magic != EXT4_EXT_MAGIC);
+	BUG_ON(le16_to_cpu(eh->eh_entries) > le16_to_cpu(eh->eh_max));
+
+	if (eh->eh_entries == 0) {
+		/*
+		 * this leaf is empty:
+		 * we get such a leaf in split/add case
+		 */
+		return;
+	}
+
+	ext_debug("binsearch for %d:  ", block);
+
+	l = EXT_FIRST_EXTENT(eh) + 1;
+	r = EXT_FIRST_EXTENT(eh) + le16_to_cpu(eh->eh_entries) - 1;
+
+	while (l <= r) {
+		m = l + (r - l) / 2;
+		if (block < le32_to_cpu(m->ee_block))
+			r = m - 1;
+		else
+			l = m + 1;
+		ext_debug("%p(%u):%p(%u):%p(%u) ", l, l->ee_block,
+				m, m->ee_block, r, r->ee_block);
+	}
+
+	path->p_ext = l - 1;
+	ext_debug("  -> %d:%llu:%d ",
+		        le32_to_cpu(path->p_ext->ee_block),
+		        ext_pblock(path->p_ext),
+			le16_to_cpu(path->p_ext->ee_len));
+
+#ifdef CHECK_BINSEARCH
+	{
+		struct ext4_extent *chex, *ex;
+		int k;
+
+		chex = ex = EXT_FIRST_EXTENT(eh);
+		for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ex++) {
+			BUG_ON(k && le32_to_cpu(ex->ee_block)
+				          <= le32_to_cpu(ex[-1].ee_block));
+			if (block < le32_to_cpu(ex->ee_block))
+				break;
+			chex = ex;
+		}
+		BUG_ON(chex != path->p_ext);
+	}
+#endif
+
+}
+
+int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
+{
+	struct ext4_extent_header *eh;
+
+	eh = ext_inode_hdr(inode);
+	eh->eh_depth = 0;
+	eh->eh_entries = 0;
+	eh->eh_magic = EXT4_EXT_MAGIC;
+	eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode));
+	ext4_mark_inode_dirty(handle, inode);
+	ext4_ext_invalidate_cache(inode);
+	return 0;
+}
+
+struct ext4_ext_path *
+ext4_ext_find_extent(struct inode *inode, int block, struct ext4_ext_path *path)
+{
+	struct ext4_extent_header *eh;
+	struct buffer_head *bh;
+	short int depth, i, ppos = 0, alloc = 0;
+
+	eh = ext_inode_hdr(inode);
+	BUG_ON(eh == NULL);
+	if (ext4_ext_check_header(__FUNCTION__, inode, eh))
+		return ERR_PTR(-EIO);
+
+	i = depth = ext_depth(inode);
+
+	/* account possible depth increase */
+	if (!path) {
+		path = kmalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+				GFP_NOFS);
+		if (!path)
+			return ERR_PTR(-ENOMEM);
+		alloc = 1;
+	}
+	memset(path, 0, sizeof(struct ext4_ext_path) * (depth + 1));
+	path[0].p_hdr = eh;
+
+	/* walk through the tree */
+	while (i) {
+		ext_debug("depth %d: num %d, max %d\n",
+			  ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
+		ext4_ext_binsearch_idx(inode, path + ppos, block);
+		path[ppos].p_block = idx_pblock(path[ppos].p_idx);
+		path[ppos].p_depth = i;
+		path[ppos].p_ext = NULL;
+
+		bh = sb_bread(inode->i_sb, path[ppos].p_block);
+		if (!bh)
+			goto err;
+
+		eh = ext_block_hdr(bh);
+		ppos++;
+		BUG_ON(ppos > depth);
+		path[ppos].p_bh = bh;
+		path[ppos].p_hdr = eh;
+		i--;
+
+		if (ext4_ext_check_header(__FUNCTION__, inode, eh))
+			goto err;
+	}
+
+	path[ppos].p_depth = i;
+	path[ppos].p_hdr = eh;
+	path[ppos].p_ext = NULL;
+	path[ppos].p_idx = NULL;
+
+	if (ext4_ext_check_header(__FUNCTION__, inode, eh))
+		goto err;
+
+	/* find extent */
+	ext4_ext_binsearch(inode, path + ppos, block);
+
+	ext4_ext_show_path(inode, path);
+
+	return path;
+
+err:
+	ext4_ext_drop_refs(path);
+	if (alloc)
+		kfree(path);
+	return ERR_PTR(-EIO);
+}
+
+/*
+ * ext4_ext_insert_index:
+ * insert new index [@logical;@ptr] into the block at @curp;
+ * check where to insert: before @curp or after @curp
+ */
+static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
+				struct ext4_ext_path *curp,
+				int logical, ext4_fsblk_t ptr)
+{
+	struct ext4_extent_idx *ix;
+	int len, err;
+
+	if ((err = ext4_ext_get_access(handle, inode, curp)))
+		return err;
+
+	BUG_ON(logical == le32_to_cpu(curp->p_idx->ei_block));
+	len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
+	if (logical > le32_to_cpu(curp->p_idx->ei_block)) {
+		/* insert after */
+		if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
+			len = (len - 1) * sizeof(struct ext4_extent_idx);
+			len = len < 0 ? 0 : len;
+			ext_debug("insert new index %d after: %d. "
+					"move %d from 0x%p to 0x%p\n",
+					logical, ptr, len,
+					(curp->p_idx + 1), (curp->p_idx + 2));
+			memmove(curp->p_idx + 2, curp->p_idx + 1, len);
+		}
+		ix = curp->p_idx + 1;
+	} else {
+		/* insert before */
+		len = len * sizeof(struct ext4_extent_idx);
+		len = len < 0 ? 0 : len;
+		ext_debug("insert new index %d before: %d. "
+				"move %d from 0x%p to 0x%p\n",
+				logical, ptr, len,
+				curp->p_idx, (curp->p_idx + 1));
+		memmove(curp->p_idx + 1, curp->p_idx, len);
+		ix = curp->p_idx;
+	}
+
+	ix->ei_block = cpu_to_le32(logical);
+	ext4_idx_store_pblock(ix, ptr);
+	curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1);
+
+	BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries)
+	                     > le16_to_cpu(curp->p_hdr->eh_max));
+	BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr));
+
+	err = ext4_ext_dirty(handle, inode, curp);
+	ext4_std_error(inode->i_sb, err);
+
+	return err;
+}
+
+/*
+ * ext4_ext_split:
+ * inserts new subtree into the path, using free index entry
+ * at depth @at:
+ * - allocates all needed blocks (new leaf and all intermediate index blocks)
+ * - makes decision where to split
+ * - moves remaining extents and index entries (right to the split point)
+ *   into the newly allocated blocks
+ * - initializes subtree
+ */
+static int ext4_ext_split(handle_t *handle, struct inode *inode,
+				struct ext4_ext_path *path,
+				struct ext4_extent *newext, int at)
+{
+	struct buffer_head *bh = NULL;
+	int depth = ext_depth(inode);
+	struct ext4_extent_header *neh;
+	struct ext4_extent_idx *fidx;
+	struct ext4_extent *ex;
+	int i = at, k, m, a;
+	ext4_fsblk_t newblock, oldblock;
+	__le32 border;
+	ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */
+	int err = 0;
+
+	/* make decision: where to split? */
+	/* FIXME: now decision is simplest: at current extent */
+
+	/* if current leaf will be split, then we should use
+	 * border from split point */
+	BUG_ON(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr));
+	if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
+		border = path[depth].p_ext[1].ee_block;
+		ext_debug("leaf will be split."
+				" next leaf starts at %d\n",
+			          le32_to_cpu(border));
+	} else {
+		border = newext->ee_block;
+		ext_debug("leaf will be added."
+				" next leaf starts at %d\n",
+			        le32_to_cpu(border));
+	}
+
+	/*
+	 * If error occurs, then we break processing
+	 * and mark filesystem read-only. index won't
+	 * be inserted and tree will be in consistent
+	 * state. Next mount will repair buffers too.
+	 */
+
+	/*
+	 * Get array to track all allocated blocks.
+	 * We need this to handle errors and free blocks
+	 * upon them.
+	 */
+	ablocks = kmalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS);
+	if (!ablocks)
+		return -ENOMEM;
+	memset(ablocks, 0, sizeof(ext4_fsblk_t) * depth);
+
+	/* allocate all needed blocks */
+	ext_debug("allocate %d blocks for indexes/leaf\n", depth - at);
+	for (a = 0; a < depth - at; a++) {
+		newblock = ext4_ext_new_block(handle, inode, path, newext, &err);
+		if (newblock == 0)
+			goto cleanup;
+		ablocks[a] = newblock;
+	}
+
+	/* initialize new leaf */
+	newblock = ablocks[--a];
+	BUG_ON(newblock == 0);
+	bh = sb_getblk(inode->i_sb, newblock);
+	if (!bh) {
+		err = -EIO;
+		goto cleanup;
+	}
+	lock_buffer(bh);
+
+	if ((err = ext4_journal_get_create_access(handle, bh)))
+		goto cleanup;
+
+	neh = ext_block_hdr(bh);
+	neh->eh_entries = 0;
+	neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode));
+	neh->eh_magic = EXT4_EXT_MAGIC;
+	neh->eh_depth = 0;
+	ex = EXT_FIRST_EXTENT(neh);
+
+	/* move remainder of path[depth] to the new leaf */
+	BUG_ON(path[depth].p_hdr->eh_entries != path[depth].p_hdr->eh_max);
+	/* start copy from next extent */
+	/* TODO: we could do it by single memmove */
+	m = 0;
+	path[depth].p_ext++;
+	while (path[depth].p_ext <=
+			EXT_MAX_EXTENT(path[depth].p_hdr)) {
+		ext_debug("move %d:%llu:%d in new leaf %llu\n",
+			        le32_to_cpu(path[depth].p_ext->ee_block),
+			        ext_pblock(path[depth].p_ext),
+			        le16_to_cpu(path[depth].p_ext->ee_len),
+				newblock);
+		/*memmove(ex++, path[depth].p_ext++,
+				sizeof(struct ext4_extent));
+		neh->eh_entries++;*/
+		path[depth].p_ext++;
+		m++;
+	}
+	if (m) {
+		memmove(ex, path[depth].p_ext-m, sizeof(struct ext4_extent)*m);
+		neh->eh_entries = cpu_to_le16(le16_to_cpu(neh->eh_entries)+m);
+	}
+
+	set_buffer_uptodate(bh);
+	unlock_buffer(bh);
+
+	if ((err = ext4_journal_dirty_metadata(handle, bh)))
+		goto cleanup;
+	brelse(bh);
+	bh = NULL;
+
+	/* correct old leaf */
+	if (m) {
+		if ((err = ext4_ext_get_access(handle, inode, path + depth)))
+			goto cleanup;
+		path[depth].p_hdr->eh_entries =
+		     cpu_to_le16(le16_to_cpu(path[depth].p_hdr->eh_entries)-m);
+		if ((err = ext4_ext_dirty(handle, inode, path + depth)))
+			goto cleanup;
+
+	}
+
+	/* create intermediate indexes */
+	k = depth - at - 1;
+	BUG_ON(k < 0);
+	if (k)
+		ext_debug("create %d intermediate indices\n", k);
+	/* insert new index into current index block */
+	/* current depth stored in i var */
+	i = depth - 1;
+	while (k--) {
+		oldblock = newblock;
+		newblock = ablocks[--a];
+		bh = sb_getblk(inode->i_sb, (ext4_fsblk_t)newblock);
+		if (!bh) {
+			err = -EIO;
+			goto cleanup;
+		}
+		lock_buffer(bh);
+
+		if ((err = ext4_journal_get_create_access(handle, bh)))
+			goto cleanup;
+
+		neh = ext_block_hdr(bh);
+		neh->eh_entries = cpu_to_le16(1);
+		neh->eh_magic = EXT4_EXT_MAGIC;
+		neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode));
+		neh->eh_depth = cpu_to_le16(depth - i);
+		fidx = EXT_FIRST_INDEX(neh);
+		fidx->ei_block = border;
+		ext4_idx_store_pblock(fidx, oldblock);
+
+		ext_debug("int.index at %d (block %llu): %lu -> %llu\n", i,
+				newblock, (unsigned long) le32_to_cpu(border),
+				oldblock);
+		/* copy indexes */
+		m = 0;
+		path[i].p_idx++;
+
+		ext_debug("cur 0x%p, last 0x%p\n", path[i].p_idx,
+				EXT_MAX_INDEX(path[i].p_hdr));
+		BUG_ON(EXT_MAX_INDEX(path[i].p_hdr) !=
+				EXT_LAST_INDEX(path[i].p_hdr));
+		while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+			ext_debug("%d: move %d:%d in new index %llu\n", i,
+				        le32_to_cpu(path[i].p_idx->ei_block),
+				        idx_pblock(path[i].p_idx),
+				        newblock);
+			/*memmove(++fidx, path[i].p_idx++,
+					sizeof(struct ext4_extent_idx));
+			neh->eh_entries++;
+			BUG_ON(neh->eh_entries > neh->eh_max);*/
+			path[i].p_idx++;
+			m++;
+		}
+		if (m) {
+			memmove(++fidx, path[i].p_idx - m,
+				sizeof(struct ext4_extent_idx) * m);
+			neh->eh_entries =
+				cpu_to_le16(le16_to_cpu(neh->eh_entries) + m);
+		}
+		set_buffer_uptodate(bh);
+		unlock_buffer(bh);
+
+		if ((err = ext4_journal_dirty_metadata(handle, bh)))
+			goto cleanup;
+		brelse(bh);
+		bh = NULL;
+
+		/* correct old index */
+		if (m) {
+			err = ext4_ext_get_access(handle, inode, path + i);
+			if (err)
+				goto cleanup;
+			path[i].p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path[i].p_hdr->eh_entries)-m);
+			err = ext4_ext_dirty(handle, inode, path + i);
+			if (err)
+				goto cleanup;
+		}
+
+		i--;
+	}
+
+	/* insert new index */
+	if (err)
+		goto cleanup;
+
+	err = ext4_ext_insert_index(handle, inode, path + at,
+				    le32_to_cpu(border), newblock);
+
+cleanup:
+	if (bh) {
+		if (buffer_locked(bh))
+			unlock_buffer(bh);
+		brelse(bh);
+	}
+
+	if (err) {
+		/* free all allocated blocks in error case */
+		for (i = 0; i < depth; i++) {
+			if (!ablocks[i])
+				continue;
+			ext4_free_blocks(handle, inode, ablocks[i], 1);
+		}
+	}
+	kfree(ablocks);
+
+	return err;
+}
+
+/*
+ * ext4_ext_grow_indepth:
+ * implements tree growing procedure:
+ * - allocates new block
+ * - moves top-level data (index block or leaf) into the new block
+ * - initializes new top-level, creating index that points to the
+ *   just created block
+ */
+static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+					struct ext4_ext_path *path,
+					struct ext4_extent *newext)
+{
+	struct ext4_ext_path *curp = path;
+	struct ext4_extent_header *neh;
+	struct ext4_extent_idx *fidx;
+	struct buffer_head *bh;
+	ext4_fsblk_t newblock;
+	int err = 0;
+
+	newblock = ext4_ext_new_block(handle, inode, path, newext, &err);
+	if (newblock == 0)
+		return err;
+
+	bh = sb_getblk(inode->i_sb, newblock);
+	if (!bh) {
+		err = -EIO;
+		ext4_std_error(inode->i_sb, err);
+		return err;
+	}
+	lock_buffer(bh);
+
+	if ((err = ext4_journal_get_create_access(handle, bh))) {
+		unlock_buffer(bh);
+		goto out;
+	}
+
+	/* move top-level index/leaf into new block */
+	memmove(bh->b_data, curp->p_hdr, sizeof(EXT4_I(inode)->i_data));
+
+	/* set size of new block */
+	neh = ext_block_hdr(bh);
+	/* old root could have indexes or leaves
+	 * so calculate e_max right way */
+	if (ext_depth(inode))
+	  neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode));
+	else
+	  neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode));
+	neh->eh_magic = EXT4_EXT_MAGIC;
+	set_buffer_uptodate(bh);
+	unlock_buffer(bh);
+
+	if ((err = ext4_journal_dirty_metadata(handle, bh)))
+		goto out;
+
+	/* create index in new top-level index: num,max,pointer */
+	if ((err = ext4_ext_get_access(handle, inode, curp)))
+		goto out;
+
+	curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
+	curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode));
+	curp->p_hdr->eh_entries = cpu_to_le16(1);
+	curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
+	/* FIXME: it works, but actually path[0] can be index */
+	curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
+	ext4_idx_store_pblock(curp->p_idx, newblock);
+
+	neh = ext_inode_hdr(inode);
+	fidx = EXT_FIRST_INDEX(neh);
+	ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n",
+		  le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max),
+		  le32_to_cpu(fidx->ei_block), idx_pblock(fidx));
+
+	neh->eh_depth = cpu_to_le16(path->p_depth + 1);
+	err = ext4_ext_dirty(handle, inode, curp);
+out:
+	brelse(bh);
+
+	return err;
+}
+
+/*
+ * ext4_ext_create_new_leaf:
+ * finds empty index and adds new leaf.
+ * if no free index is found, then it requests in-depth growing.
+ */
+static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+					struct ext4_ext_path *path,
+					struct ext4_extent *newext)
+{
+	struct ext4_ext_path *curp;
+	int depth, i, err = 0;
+
+repeat:
+	i = depth = ext_depth(inode);
+
+	/* walk up to the tree and look for free index entry */
+	curp = path + depth;
+	while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
+		i--;
+		curp--;
+	}
+
+	/* we use already allocated block for index block,
+	 * so subsequent data blocks should be contiguous */
+	if (EXT_HAS_FREE_INDEX(curp)) {
+		/* if we found index with free entry, then use that
+		 * entry: create all needed subtree and add new leaf */
+		err = ext4_ext_split(handle, inode, path, newext, i);
+
+		/* refill path */
+		ext4_ext_drop_refs(path);
+		path = ext4_ext_find_extent(inode,
+					    le32_to_cpu(newext->ee_block),
+					    path);
+		if (IS_ERR(path))
+			err = PTR_ERR(path);
+	} else {
+		/* tree is full, time to grow in depth */
+		err = ext4_ext_grow_indepth(handle, inode, path, newext);
+		if (err)
+			goto out;
+
+		/* refill path */
+		ext4_ext_drop_refs(path);
+		path = ext4_ext_find_extent(inode,
+					    le32_to_cpu(newext->ee_block),
+					    path);
+		if (IS_ERR(path)) {
+			err = PTR_ERR(path);
+			goto out;
+		}
+
+		/*
+		 * only first (depth 0 -> 1) produces free space;
+		 * in all other cases we have to split the grown tree
+		 */
+		depth = ext_depth(inode);
+		if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
+			/* now we need to split */
+			goto repeat;
+		}
+	}
+
+out:
+	return err;
+}
+
+/*
+ * ext4_ext_next_allocated_block:
+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK.
+ * NOTE: it considers block number from index entry as
+ * allocated block. Thus, index entries have to be consistent
+ * with leaves.
+ */
+static unsigned long
+ext4_ext_next_allocated_block(struct ext4_ext_path *path)
+{
+	int depth;
+
+	BUG_ON(path == NULL);
+	depth = path->p_depth;
+
+	if (depth == 0 && path->p_ext == NULL)
+		return EXT_MAX_BLOCK;
+
+	while (depth >= 0) {
+		if (depth == path->p_depth) {
+			/* leaf */
+			if (path[depth].p_ext !=
+					EXT_LAST_EXTENT(path[depth].p_hdr))
+			  return le32_to_cpu(path[depth].p_ext[1].ee_block);
+		} else {
+			/* index */
+			if (path[depth].p_idx !=
+					EXT_LAST_INDEX(path[depth].p_hdr))
+			  return le32_to_cpu(path[depth].p_idx[1].ei_block);
+		}
+		depth--;
+	}
+
+	return EXT_MAX_BLOCK;
+}
+
+/*
+ * ext4_ext_next_leaf_block:
+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ */
+static unsigned ext4_ext_next_leaf_block(struct inode *inode,
+					struct ext4_ext_path *path)
+{
+	int depth;
+
+	BUG_ON(path == NULL);
+	depth = path->p_depth;
+
+	/* zero-tree has no leaf blocks at all */
+	if (depth == 0)
+		return EXT_MAX_BLOCK;
+
+	/* go to index block */
+	depth--;
+
+	while (depth >= 0) {
+		if (path[depth].p_idx !=
+				EXT_LAST_INDEX(path[depth].p_hdr))
+		  return le32_to_cpu(path[depth].p_idx[1].ei_block);
+		depth--;
+	}
+
+	return EXT_MAX_BLOCK;
+}
+
+/*
+ * ext4_ext_correct_indexes:
+ * if leaf gets modified and modified extent is first in the leaf,
+ * then we have to correct all indexes above.
+ * TODO: do we need to correct tree in all cases?
+ */
+int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
+				struct ext4_ext_path *path)
+{
+	struct ext4_extent_header *eh;
+	int depth = ext_depth(inode);
+	struct ext4_extent *ex;
+	__le32 border;
+	int k, err = 0;
+
+	eh = path[depth].p_hdr;
+	ex = path[depth].p_ext;
+	BUG_ON(ex == NULL);
+	BUG_ON(eh == NULL);
+
+	if (depth == 0) {
+		/* there is no tree at all */
+		return 0;
+	}
+
+	if (ex != EXT_FIRST_EXTENT(eh)) {
+		/* we correct tree if first leaf got modified only */
+		return 0;
+	}
+
+	/*
+	 * TODO: we need correction if border is smaller than current one
+	 */
+	k = depth - 1;
+	border = path[depth].p_ext->ee_block;
+	if ((err = ext4_ext_get_access(handle, inode, path + k)))
+		return err;
+	path[k].p_idx->ei_block = border;
+	if ((err = ext4_ext_dirty(handle, inode, path + k)))
+		return err;
+
+	while (k--) {
+		/* change all left-side indexes */
+		if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
+			break;
+		if ((err = ext4_ext_get_access(handle, inode, path + k)))
+			break;
+		path[k].p_idx->ei_block = border;
+		if ((err = ext4_ext_dirty(handle, inode, path + k)))
+			break;
+	}
+
+	return err;
+}
+
+static int inline
+ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
+				struct ext4_extent *ex2)
+{
+	if (le32_to_cpu(ex1->ee_block) + le16_to_cpu(ex1->ee_len) !=
+			le32_to_cpu(ex2->ee_block))
+		return 0;
+
+	/*
+	 * To allow future support for preallocated extents to be added
+	 * as an RO_COMPAT feature, refuse to merge to extents if
+	 * this can result in the top bit of ee_len being set.
+	 */
+	if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN)
+		return 0;
+#ifdef AGRESSIVE_TEST
+	if (le16_to_cpu(ex1->ee_len) >= 4)
+		return 0;
+#endif
+
+	if (ext_pblock(ex1) + le16_to_cpu(ex1->ee_len) == ext_pblock(ex2))
+		return 1;
+	return 0;
+}
+
+/*
+ * ext4_ext_insert_extent:
+ * tries to merge requsted extent into the existing extent or
+ * inserts requested extent as new one into the tree,
+ * creating new leaf in the no-space case.
+ */
+int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+				struct ext4_ext_path *path,
+				struct ext4_extent *newext)
+{
+	struct ext4_extent_header * eh;
+	struct ext4_extent *ex, *fex;
+	struct ext4_extent *nearex; /* nearest extent */
+	struct ext4_ext_path *npath = NULL;
+	int depth, len, err, next;
+
+	BUG_ON(newext->ee_len == 0);
+	depth = ext_depth(inode);
+	ex = path[depth].p_ext;
+	BUG_ON(path[depth].p_hdr == NULL);
+
+	/* try to insert block into found extent and return */
+	if (ex && ext4_can_extents_be_merged(inode, ex, newext)) {
+		ext_debug("append %d block to %d:%d (from %llu)\n",
+				le16_to_cpu(newext->ee_len),
+				le32_to_cpu(ex->ee_block),
+				le16_to_cpu(ex->ee_len), ext_pblock(ex));
+		if ((err = ext4_ext_get_access(handle, inode, path + depth)))
+			return err;
+		ex->ee_len = cpu_to_le16(le16_to_cpu(ex->ee_len)
+					 + le16_to_cpu(newext->ee_len));
+		eh = path[depth].p_hdr;
+		nearex = ex;
+		goto merge;
+	}
+
+repeat:
+	depth = ext_depth(inode);
+	eh = path[depth].p_hdr;
+	if (le16_to_cpu(eh->eh_entries) < le16_to_cpu(eh->eh_max))
+		goto has_space;
+
+	/* probably next leaf has space for us? */
+	fex = EXT_LAST_EXTENT(eh);
+	next = ext4_ext_next_leaf_block(inode, path);
+	if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block)
+	    && next != EXT_MAX_BLOCK) {
+		ext_debug("next leaf block - %d\n", next);
+		BUG_ON(npath != NULL);
+		npath = ext4_ext_find_extent(inode, next, NULL);
+		if (IS_ERR(npath))
+			return PTR_ERR(npath);
+		BUG_ON(npath->p_depth != path->p_depth);
+		eh = npath[depth].p_hdr;
+		if (le16_to_cpu(eh->eh_entries) < le16_to_cpu(eh->eh_max)) {
+			ext_debug("next leaf isnt full(%d)\n",
+				  le16_to_cpu(eh->eh_entries));
+			path = npath;
+			goto repeat;
+		}
+		ext_debug("next leaf has no free space(%d,%d)\n",
+			  le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
+	}
+
+	/*
+	 * There is no free space in the found leaf.
+	 * We're gonna add a new leaf in the tree.
+	 */
+	err = ext4_ext_create_new_leaf(handle, inode, path, newext);
+	if (err)
+		goto cleanup;
+	depth = ext_depth(inode);
+	eh = path[depth].p_hdr;
+
+has_space:
+	nearex = path[depth].p_ext;
+
+	if ((err = ext4_ext_get_access(handle, inode, path + depth)))
+		goto cleanup;
+
+	if (!nearex) {
+		/* there is no extent in this leaf, create first one */
+		ext_debug("first extent in the leaf: %d:%llu:%d\n",
+			        le32_to_cpu(newext->ee_block),
+			        ext_pblock(newext),
+			        le16_to_cpu(newext->ee_len));
+		path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+	} else if (le32_to_cpu(newext->ee_block)
+		           > le32_to_cpu(nearex->ee_block)) {
+/*		BUG_ON(newext->ee_block == nearex->ee_block); */
+		if (nearex != EXT_LAST_EXTENT(eh)) {
+			len = EXT_MAX_EXTENT(eh) - nearex;
+			len = (len - 1) * sizeof(struct ext4_extent);
+			len = len < 0 ? 0 : len;
+			ext_debug("insert %d:%llu:%d after: nearest 0x%p, "
+					"move %d from 0x%p to 0x%p\n",
+				        le32_to_cpu(newext->ee_block),
+				        ext_pblock(newext),
+				        le16_to_cpu(newext->ee_len),
+					nearex, len, nearex + 1, nearex + 2);
+			memmove(nearex + 2, nearex + 1, len);
+		}
+		path[depth].p_ext = nearex + 1;
+	} else {
+		BUG_ON(newext->ee_block == nearex->ee_block);
+		len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext4_extent);
+		len = len < 0 ? 0 : len;
+		ext_debug("insert %d:%llu:%d before: nearest 0x%p, "
+				"move %d from 0x%p to 0x%p\n",
+				le32_to_cpu(newext->ee_block),
+				ext_pblock(newext),
+				le16_to_cpu(newext->ee_len),
+				nearex, len, nearex + 1, nearex + 2);
+		memmove(nearex + 1, nearex, len);
+		path[depth].p_ext = nearex;
+	}
+
+	eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)+1);
+	nearex = path[depth].p_ext;
+	nearex->ee_block = newext->ee_block;
+	nearex->ee_start = newext->ee_start;
+	nearex->ee_start_hi = newext->ee_start_hi;
+	nearex->ee_len = newext->ee_len;
+
+merge:
+	/* try to merge extents to the right */
+	while (nearex < EXT_LAST_EXTENT(eh)) {
+		if (!ext4_can_extents_be_merged(inode, nearex, nearex + 1))
+			break;
+		/* merge with next extent! */
+		nearex->ee_len = cpu_to_le16(le16_to_cpu(nearex->ee_len)
+					     + le16_to_cpu(nearex[1].ee_len));
+		if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
+			len = (EXT_LAST_EXTENT(eh) - nearex - 1)
+					* sizeof(struct ext4_extent);
+			memmove(nearex + 1, nearex + 2, len);
+		}
+		eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1);
+		BUG_ON(eh->eh_entries == 0);
+	}
+
+	/* try to merge extents to the left */
+
+	/* time to correct all indexes above */
+	err = ext4_ext_correct_indexes(handle, inode, path);
+	if (err)
+		goto cleanup;
+
+	err = ext4_ext_dirty(handle, inode, path + depth);
+
+cleanup:
+	if (npath) {
+		ext4_ext_drop_refs(npath);
+		kfree(npath);
+	}
+	ext4_ext_tree_changed(inode);
+	ext4_ext_invalidate_cache(inode);
+	return err;
+}
+
+int ext4_ext_walk_space(struct inode *inode, unsigned long block,
+			unsigned long num, ext_prepare_callback func,
+			void *cbdata)
+{
+	struct ext4_ext_path *path = NULL;
+	struct ext4_ext_cache cbex;
+	struct ext4_extent *ex;
+	unsigned long next, start = 0, end = 0;
+	unsigned long last = block + num;
+	int depth, exists, err = 0;
+
+	BUG_ON(func == NULL);
+	BUG_ON(inode == NULL);
+
+	while (block < last && block != EXT_MAX_BLOCK) {
+		num = last - block;
+		/* find extent for this block */
+		path = ext4_ext_find_extent(inode, block, path);
+		if (IS_ERR(path)) {
+			err = PTR_ERR(path);
+			path = NULL;
+			break;
+		}
+
+		depth = ext_depth(inode);
+		BUG_ON(path[depth].p_hdr == NULL);
+		ex = path[depth].p_ext;
+		next = ext4_ext_next_allocated_block(path);
+
+		exists = 0;
+		if (!ex) {
+			/* there is no extent yet, so try to allocate
+			 * all requested space */
+			start = block;
+			end = block + num;
+		} else if (le32_to_cpu(ex->ee_block) > block) {
+			/* need to allocate space before found extent */
+			start = block;
+			end = le32_to_cpu(ex->ee_block);
+			if (block + num < end)
+				end = block + num;
+		} else if (block >=
+			     le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len)) {
+			/* need to allocate space after found extent */
+			start = block;
+			end = block + num;
+			if (end >= next)
+				end = next;
+		} else if (block >= le32_to_cpu(ex->ee_block)) {
+			/*
+			 * some part of requested space is covered
+			 * by found extent
+			 */
+			start = block;
+			end = le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len);
+			if (block + num < end)
+				end = block + num;
+			exists = 1;
+		} else {
+			BUG();
+		}
+		BUG_ON(end <= start);
+
+		if (!exists) {
+			cbex.ec_block = start;
+			cbex.ec_len = end - start;
+			cbex.ec_start = 0;
+			cbex.ec_type = EXT4_EXT_CACHE_GAP;
+		} else {
+		        cbex.ec_block = le32_to_cpu(ex->ee_block);
+		        cbex.ec_len = le16_to_cpu(ex->ee_len);
+		        cbex.ec_start = ext_pblock(ex);
+			cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
+		}
+
+		BUG_ON(cbex.ec_len == 0);
+		err = func(inode, path, &cbex, cbdata);
+		ext4_ext_drop_refs(path);
+
+		if (err < 0)
+			break;
+		if (err == EXT_REPEAT)
+			continue;
+		else if (err == EXT_BREAK) {
+			err = 0;
+			break;
+		}
+
+		if (ext_depth(inode) != depth) {
+			/* depth was changed. we have to realloc path */
+			kfree(path);
+			path = NULL;
+		}
+
+		block = cbex.ec_block + cbex.ec_len;
+	}
+
+	if (path) {
+		ext4_ext_drop_refs(path);
+		kfree(path);
+	}
+
+	return err;
+}
+
+static inline void
+ext4_ext_put_in_cache(struct inode *inode, __u32 block,
+			__u32 len, __u32 start, int type)
+{
+	struct ext4_ext_cache *cex;
+	BUG_ON(len == 0);
+	cex = &EXT4_I(inode)->i_cached_extent;
+	cex->ec_type = type;
+	cex->ec_block = block;
+	cex->ec_len = len;
+	cex->ec_start = start;
+}
+
+/*
+ * ext4_ext_put_gap_in_cache:
+ * calculate boundaries of the gap that the requested block fits into
+ * and cache this gap
+ */
+static inline void
+ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
+				unsigned long block)
+{
+	int depth = ext_depth(inode);
+	unsigned long lblock, len;
+	struct ext4_extent *ex;
+
+	ex = path[depth].p_ext;
+	if (ex == NULL) {
+		/* there is no extent yet, so gap is [0;-] */
+		lblock = 0;
+		len = EXT_MAX_BLOCK;
+		ext_debug("cache gap(whole file):");
+	} else if (block < le32_to_cpu(ex->ee_block)) {
+		lblock = block;
+		len = le32_to_cpu(ex->ee_block) - block;
+		ext_debug("cache gap(before): %lu [%lu:%lu]",
+				(unsigned long) block,
+			        (unsigned long) le32_to_cpu(ex->ee_block),
+			        (unsigned long) le16_to_cpu(ex->ee_len));
+	} else if (block >= le32_to_cpu(ex->ee_block)
+		            + le16_to_cpu(ex->ee_len)) {
+	        lblock = le32_to_cpu(ex->ee_block)
+		         + le16_to_cpu(ex->ee_len);
+		len = ext4_ext_next_allocated_block(path);
+		ext_debug("cache gap(after): [%lu:%lu] %lu",
+			        (unsigned long) le32_to_cpu(ex->ee_block),
+			        (unsigned long) le16_to_cpu(ex->ee_len),
+				(unsigned long) block);
+		BUG_ON(len == lblock);
+		len = len - lblock;
+	} else {
+		lblock = len = 0;
+		BUG();
+	}
+
+	ext_debug(" -> %lu:%lu\n", (unsigned long) lblock, len);
+	ext4_ext_put_in_cache(inode, lblock, len, 0, EXT4_EXT_CACHE_GAP);
+}
+
+static inline int
+ext4_ext_in_cache(struct inode *inode, unsigned long block,
+			struct ext4_extent *ex)
+{
+	struct ext4_ext_cache *cex;
+
+	cex = &EXT4_I(inode)->i_cached_extent;
+
+	/* has cache valid data? */
+	if (cex->ec_type == EXT4_EXT_CACHE_NO)
+		return EXT4_EXT_CACHE_NO;
+
+	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
+			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
+	if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+	        ex->ee_block = cpu_to_le32(cex->ec_block);
+		ext4_ext_store_pblock(ex, cex->ec_start);
+	        ex->ee_len = cpu_to_le16(cex->ec_len);
+		ext_debug("%lu cached by %lu:%lu:%llu\n",
+				(unsigned long) block,
+				(unsigned long) cex->ec_block,
+				(unsigned long) cex->ec_len,
+				cex->ec_start);
+		return cex->ec_type;
+	}
+
+	/* not in cache */
+	return EXT4_EXT_CACHE_NO;
+}
+
+/*
+ * ext4_ext_rm_idx:
+ * removes index from the index block.
+ * It's used in truncate case only, thus all requests are for
+ * last index in the block only.
+ */
+int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
+			struct ext4_ext_path *path)
+{
+	struct buffer_head *bh;
+	int err;
+	ext4_fsblk_t leaf;
+
+	/* free index block */
+	path--;
+	leaf = idx_pblock(path->p_idx);
+	BUG_ON(path->p_hdr->eh_entries == 0);
+	if ((err = ext4_ext_get_access(handle, inode, path)))
+		return err;
+	path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
+	if ((err = ext4_ext_dirty(handle, inode, path)))
+		return err;
+	ext_debug("index is empty, remove it, free block %llu\n", leaf);
+	bh = sb_find_get_block(inode->i_sb, leaf);
+	ext4_forget(handle, 1, inode, bh, leaf);
+	ext4_free_blocks(handle, inode, leaf, 1);
+	return err;
+}
+
+/*
+ * ext4_ext_calc_credits_for_insert:
+ * This routine returns max. credits that the extent tree can consume.
+ * It should be OK for low-performance paths like ->writepage()
+ * To allow many writing processes to fit into a single transaction,
+ * the caller should calculate credits under truncate_mutex and
+ * pass the actual path.
+ */
+int inline ext4_ext_calc_credits_for_insert(struct inode *inode,
+						struct ext4_ext_path *path)
+{
+	int depth, needed;
+
+	if (path) {
+		/* probably there is space in leaf? */
+		depth = ext_depth(inode);
+		if (le16_to_cpu(path[depth].p_hdr->eh_entries)
+				< le16_to_cpu(path[depth].p_hdr->eh_max))
+			return 1;
+	}
+
+	/*
+	 * given 32-bit logical block (4294967296 blocks), max. tree
+	 * can be 4 levels in depth -- 4 * 340^4 == 53453440000.
+	 * Let's also add one more level for imbalance.
+	 */
+	depth = 5;
+
+	/* allocation of new data block(s) */
+	needed = 2;
+
+	/*
+	 * tree can be full, so it would need to grow in depth:
+	 * allocation + old root + new root
+	 */
+	needed += 2 + 1 + 1;
+
+	/*
+	 * Index split can happen, we would need:
+	 *    allocate intermediate indexes (bitmap + group)
+	 *  + change two blocks at each level, but root (already included)
+	 */
+	needed = (depth * 2) + (depth * 2);
+
+	/* any allocation modifies superblock */
+	needed += 1;
+
+	return needed;
+}
+
+static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+				struct ext4_extent *ex,
+				unsigned long from, unsigned long to)
+{
+	struct buffer_head *bh;
+	int i;
+
+#ifdef EXTENTS_STATS
+	{
+		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+		unsigned short ee_len =  le16_to_cpu(ex->ee_len);
+		spin_lock(&sbi->s_ext_stats_lock);
+		sbi->s_ext_blocks += ee_len;
+		sbi->s_ext_extents++;
+		if (ee_len < sbi->s_ext_min)
+			sbi->s_ext_min = ee_len;
+		if (ee_len > sbi->s_ext_max)
+			sbi->s_ext_max = ee_len;
+		if (ext_depth(inode) > sbi->s_depth_max)
+			sbi->s_depth_max = ext_depth(inode);
+		spin_unlock(&sbi->s_ext_stats_lock);
+	}
+#endif
+	if (from >= le32_to_cpu(ex->ee_block)
+	    && to == le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - 1) {
+		/* tail removal */
+		unsigned long num;
+		ext4_fsblk_t start;
+		num = le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - from;
+		start = ext_pblock(ex) + le16_to_cpu(ex->ee_len) - num;
+		ext_debug("free last %lu blocks starting %llu\n", num, start);
+		for (i = 0; i < num; i++) {
+			bh = sb_find_get_block(inode->i_sb, start + i);
+			ext4_forget(handle, 0, inode, bh, start + i);
+		}
+		ext4_free_blocks(handle, inode, start, num);
+	} else if (from == le32_to_cpu(ex->ee_block)
+		   && to <= le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - 1) {
+		printk("strange request: removal %lu-%lu from %u:%u\n",
+		       from, to, le32_to_cpu(ex->ee_block), le16_to_cpu(ex->ee_len));
+	} else {
+		printk("strange request: removal(2) %lu-%lu from %u:%u\n",
+		       from, to, le32_to_cpu(ex->ee_block), le16_to_cpu(ex->ee_len));
+	}
+	return 0;
+}
+
+static int
+ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+		struct ext4_ext_path *path, unsigned long start)
+{
+	int err = 0, correct_index = 0;
+	int depth = ext_depth(inode), credits;
+	struct ext4_extent_header *eh;
+	unsigned a, b, block, num;
+	unsigned long ex_ee_block;
+	unsigned short ex_ee_len;
+	struct ext4_extent *ex;
+
+	ext_debug("truncate since %lu in leaf\n", start);
+	if (!path[depth].p_hdr)
+		path[depth].p_hdr = ext_block_hdr(path[depth].p_bh);
+	eh = path[depth].p_hdr;
+	BUG_ON(eh == NULL);
+	BUG_ON(le16_to_cpu(eh->eh_entries) > le16_to_cpu(eh->eh_max));
+	BUG_ON(eh->eh_magic != EXT4_EXT_MAGIC);
+
+	/* find where to start removing */
+	ex = EXT_LAST_EXTENT(eh);
+
+	ex_ee_block = le32_to_cpu(ex->ee_block);
+	ex_ee_len = le16_to_cpu(ex->ee_len);
+
+	while (ex >= EXT_FIRST_EXTENT(eh) &&
+			ex_ee_block + ex_ee_len > start) {
+		ext_debug("remove ext %lu:%u\n", ex_ee_block, ex_ee_len);
+		path[depth].p_ext = ex;
+
+		a = ex_ee_block > start ? ex_ee_block : start;
+		b = ex_ee_block + ex_ee_len - 1 < EXT_MAX_BLOCK ?
+			ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCK;
+
+		ext_debug("  border %u:%u\n", a, b);
+
+		if (a != ex_ee_block && b != ex_ee_block + ex_ee_len - 1) {
+			block = 0;
+			num = 0;
+			BUG();
+		} else if (a != ex_ee_block) {
+			/* remove tail of the extent */
+			block = ex_ee_block;
+			num = a - block;
+		} else if (b != ex_ee_block + ex_ee_len - 1) {
+			/* remove head of the extent */
+			block = a;
+			num = b - a;
+			/* there is no "make a hole" API yet */
+			BUG();
+		} else {
+			/* remove whole extent: excellent! */
+			block = ex_ee_block;
+			num = 0;
+			BUG_ON(a != ex_ee_block);
+			BUG_ON(b != ex_ee_block + ex_ee_len - 1);
+		}
+
+		/* at present, extent can't cross block group: */
+		/* leaf + bitmap + group desc + sb + inode */
+		credits = 5;
+		if (ex == EXT_FIRST_EXTENT(eh)) {
+			correct_index = 1;
+			credits += (ext_depth(inode)) + 1;
+		}
+#ifdef CONFIG_QUOTA
+		credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
+#endif
+
+		handle = ext4_ext_journal_restart(handle, credits);
+		if (IS_ERR(handle)) {
+			err = PTR_ERR(handle);
+			goto out;
+		}
+
+		err = ext4_ext_get_access(handle, inode, path + depth);
+		if (err)
+			goto out;
+
+		err = ext4_remove_blocks(handle, inode, ex, a, b);
+		if (err)
+			goto out;
+
+		if (num == 0) {
+			/* this extent is removed; mark slot entirely unused */
+			ext4_ext_store_pblock(ex, 0);
+			eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1);
+		}
+
+		ex->ee_block = cpu_to_le32(block);
+		ex->ee_len = cpu_to_le16(num);
+
+		err = ext4_ext_dirty(handle, inode, path + depth);
+		if (err)
+			goto out;
+
+		ext_debug("new extent: %u:%u:%llu\n", block, num,
+				ext_pblock(ex));
+		ex--;
+		ex_ee_block = le32_to_cpu(ex->ee_block);
+		ex_ee_len = le16_to_cpu(ex->ee_len);
+	}
+
+	if (correct_index && eh->eh_entries)
+		err = ext4_ext_correct_indexes(handle, inode, path);
+
+	/* if this leaf is free, then we should
+	 * remove it from index block above */
+	if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
+		err = ext4_ext_rm_idx(handle, inode, path + depth);
+
+out:
+	return err;
+}
+
+/*
+ * ext4_ext_more_to_rm:
+ * returns 1 if current index has to be freed (even partial)
+ */
+static int inline
+ext4_ext_more_to_rm(struct ext4_ext_path *path)
+{
+	BUG_ON(path->p_idx == NULL);
+
+	if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
+		return 0;
+
+	/*
+	 * if truncate on deeper level happened, it wasn't partial,
+	 * so we have to consider current index for truncation
+	 */
+	if (le16_to_cpu(path->p_hdr->eh_entries) == path->p_block)
+		return 0;
+	return 1;
+}
+
+int ext4_ext_remove_space(struct inode *inode, unsigned long start)
+{
+	struct super_block *sb = inode->i_sb;
+	int depth = ext_depth(inode);
+	struct ext4_ext_path *path;
+	handle_t *handle;
+	int i = 0, err = 0;
+
+	ext_debug("truncate since %lu\n", start);
+
+	/* probably first extent we're gonna free will be last in block */
+	handle = ext4_journal_start(inode, depth + 1);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	ext4_ext_invalidate_cache(inode);
+
+	/*
+	 * We start scanning from right side, freeing all the blocks
+	 * after i_size and walking into the tree depth-wise.
+	 */
+	path = kmalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
+	if (path == NULL) {
+		ext4_journal_stop(handle);
+		return -ENOMEM;
+	}
+	memset(path, 0, sizeof(struct ext4_ext_path) * (depth + 1));
+	path[0].p_hdr = ext_inode_hdr(inode);
+	if (ext4_ext_check_header(__FUNCTION__, inode, path[0].p_hdr)) {
+		err = -EIO;
+		goto out;
+	}
+	path[0].p_depth = depth;
+
+	while (i >= 0 && err == 0) {
+		if (i == depth) {
+			/* this is leaf block */
+			err = ext4_ext_rm_leaf(handle, inode, path, start);
+			/* root level has p_bh == NULL, brelse() eats this */
+			brelse(path[i].p_bh);
+			path[i].p_bh = NULL;
+			i--;
+			continue;
+		}
+
+		/* this is index block */
+		if (!path[i].p_hdr) {
+			ext_debug("initialize header\n");
+			path[i].p_hdr = ext_block_hdr(path[i].p_bh);
+			if (ext4_ext_check_header(__FUNCTION__, inode,
+							path[i].p_hdr)) {
+				err = -EIO;
+				goto out;
+			}
+		}
+
+		BUG_ON(le16_to_cpu(path[i].p_hdr->eh_entries)
+			   > le16_to_cpu(path[i].p_hdr->eh_max));
+		BUG_ON(path[i].p_hdr->eh_magic != EXT4_EXT_MAGIC);
+
+		if (!path[i].p_idx) {
+			/* this level hasn't been touched yet */
+			path[i].p_idx = EXT_LAST_INDEX(path[i].p_hdr);
+			path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries)+1;
+			ext_debug("init index ptr: hdr 0x%p, num %d\n",
+				  path[i].p_hdr,
+				  le16_to_cpu(path[i].p_hdr->eh_entries));
+		} else {
+			/* we were already here, see at next index */
+			path[i].p_idx--;
+		}
+
+		ext_debug("level %d - index, first 0x%p, cur 0x%p\n",
+				i, EXT_FIRST_INDEX(path[i].p_hdr),
+				path[i].p_idx);
+		if (ext4_ext_more_to_rm(path + i)) {
+			/* go to the next level */
+			ext_debug("move to level %d (block %llu)\n",
+				  i + 1, idx_pblock(path[i].p_idx));
+			memset(path + i + 1, 0, sizeof(*path));
+			path[i+1].p_bh =
+				sb_bread(sb, idx_pblock(path[i].p_idx));
+			if (!path[i+1].p_bh) {
+				/* should we reset i_size? */
+				err = -EIO;
+				break;
+			}
+
+			/* save actual number of indexes since this
+			 * number is changed at the next iteration */
+			path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries);
+			i++;
+		} else {
+			/* we finished processing this index, go up */
+			if (path[i].p_hdr->eh_entries == 0 && i > 0) {
+				/* index is empty, remove it;
+				 * handle must be already prepared by the
+				 * truncatei_leaf() */
+				err = ext4_ext_rm_idx(handle, inode, path + i);
+			}
+			/* root level has p_bh == NULL, brelse() eats this */
+			brelse(path[i].p_bh);
+			path[i].p_bh = NULL;
+			i--;
+			ext_debug("return to level %d\n", i);
+		}
+	}
+
+	/* TODO: flexible tree reduction should be here */
+	if (path->p_hdr->eh_entries == 0) {
+		/*
+		 * truncate to zero freed all the tree,
+		 * so we need to correct eh_depth
+		 */
+		err = ext4_ext_get_access(handle, inode, path);
+		if (err == 0) {
+			ext_inode_hdr(inode)->eh_depth = 0;
+			ext_inode_hdr(inode)->eh_max =
+				cpu_to_le16(ext4_ext_space_root(inode));
+			err = ext4_ext_dirty(handle, inode, path);
+		}
+	}
+out:
+	ext4_ext_tree_changed(inode);
+	ext4_ext_drop_refs(path);
+	kfree(path);
+	ext4_journal_stop(handle);
+
+	return err;
+}
+
+/*
+ * called at mount time
+ */
+void ext4_ext_init(struct super_block *sb)
+{
+	/*
+	 * possible initialization would be here
+	 */
+
+	if (test_opt(sb, EXTENTS)) {
+		printk("EXT4-fs: file extents enabled");
+#ifdef AGRESSIVE_TEST
+		printk(", agressive tests");
+#endif
+#ifdef CHECK_BINSEARCH
+		printk(", check binsearch");
+#endif
+#ifdef EXTENTS_STATS
+		printk(", stats");
+#endif
+		printk("\n");
+#ifdef EXTENTS_STATS
+		spin_lock_init(&EXT4_SB(sb)->s_ext_stats_lock);
+		EXT4_SB(sb)->s_ext_min = 1 << 30;
+		EXT4_SB(sb)->s_ext_max = 0;
+#endif
+	}
+}
+
+/*
+ * called at umount time
+ */
+void ext4_ext_release(struct super_block *sb)
+{
+	if (!test_opt(sb, EXTENTS))
+		return;
+
+#ifdef EXTENTS_STATS
+	if (EXT4_SB(sb)->s_ext_blocks && EXT4_SB(sb)->s_ext_extents) {
+		struct ext4_sb_info *sbi = EXT4_SB(sb);
+		printk(KERN_ERR "EXT4-fs: %lu blocks in %lu extents (%lu ave)\n",
+			sbi->s_ext_blocks, sbi->s_ext_extents,
+			sbi->s_ext_blocks / sbi->s_ext_extents);
+		printk(KERN_ERR "EXT4-fs: extents: %lu min, %lu max, max depth %lu\n",
+			sbi->s_ext_min, sbi->s_ext_max, sbi->s_depth_max);
+	}
+#endif
+}
+
+int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+			ext4_fsblk_t iblock,
+			unsigned long max_blocks, struct buffer_head *bh_result,
+			int create, int extend_disksize)
+{
+	struct ext4_ext_path *path = NULL;
+	struct ext4_extent newex, *ex;
+	ext4_fsblk_t goal, newblock;
+	int err = 0, depth;
+	unsigned long allocated = 0;
+
+	__clear_bit(BH_New, &bh_result->b_state);
+	ext_debug("blocks %d/%lu requested for inode %u\n", (int) iblock,
+			max_blocks, (unsigned) inode->i_ino);
+	mutex_lock(&EXT4_I(inode)->truncate_mutex);
+
+	/* check in cache */
+	if ((goal = ext4_ext_in_cache(inode, iblock, &newex))) {
+		if (goal == EXT4_EXT_CACHE_GAP) {
+			if (!create) {
+				/* block isn't allocated yet and
+				 * user doesn't want to allocate it */
+				goto out2;
+			}
+			/* we should allocate requested block */
+		} else if (goal == EXT4_EXT_CACHE_EXTENT) {
+			/* block is already allocated */
+		        newblock = iblock
+		                   - le32_to_cpu(newex.ee_block)
+			           + ext_pblock(&newex);
+			/* number of remaining blocks in the extent */
+			allocated = le16_to_cpu(newex.ee_len) -
+					(iblock - le32_to_cpu(newex.ee_block));
+			goto out;
+		} else {
+			BUG();
+		}
+	}
+
+	/* find extent for this block */
+	path = ext4_ext_find_extent(inode, iblock, NULL);
+	if (IS_ERR(path)) {
+		err = PTR_ERR(path);
+		path = NULL;
+		goto out2;
+	}
+
+	depth = ext_depth(inode);
+
+	/*
+	 * consistent leaf must not be empty;
+	 * this situation is possible, though, _during_ tree modification;
+	 * this is why assert can't be put in ext4_ext_find_extent()
+	 */
+	BUG_ON(path[depth].p_ext == NULL && depth != 0);
+
+	if ((ex = path[depth].p_ext)) {
+	        unsigned long ee_block = le32_to_cpu(ex->ee_block);
+		ext4_fsblk_t ee_start = ext_pblock(ex);
+		unsigned short ee_len  = le16_to_cpu(ex->ee_len);
+
+		/*
+		 * Allow future support for preallocated extents to be added
+		 * as an RO_COMPAT feature:
+		 * Uninitialized extents are treated as holes, except that
+		 * we avoid (fail) allocating new blocks during a write.
+		 */
+		if (ee_len > EXT_MAX_LEN)
+			goto out2;
+		/* if found extent covers block, simply return it */
+	        if (iblock >= ee_block && iblock < ee_block + ee_len) {
+			newblock = iblock - ee_block + ee_start;
+			/* number of remaining blocks in the extent */
+			allocated = ee_len - (iblock - ee_block);
+			ext_debug("%d fit into %lu:%d -> %llu\n", (int) iblock,
+					ee_block, ee_len, newblock);
+			ext4_ext_put_in_cache(inode, ee_block, ee_len,
+						ee_start, EXT4_EXT_CACHE_EXTENT);
+			goto out;
+		}
+	}
+
+	/*
+	 * requested block isn't allocated yet;
+	 * we couldn't try to create block if create flag is zero
+	 */
+	if (!create) {
+		/* put just found gap into cache to speed up
+		 * subsequent requests */
+		ext4_ext_put_gap_in_cache(inode, path, iblock);
+		goto out2;
+	}
+	/*
+	 * Okay, we need to do block allocation.  Lazily initialize the block
+	 * allocation info here if necessary.
+	 */
+	if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info))
+		ext4_init_block_alloc_info(inode);
+
+	/* allocate new block */
+	goal = ext4_ext_find_goal(inode, path, iblock);
+	allocated = max_blocks;
+	newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err);
+	if (!newblock)
+		goto out2;
+	ext_debug("allocate new block: goal %llu, found %llu/%lu\n",
+			goal, newblock, allocated);
+
+	/* try to insert new extent into found leaf and return */
+	newex.ee_block = cpu_to_le32(iblock);
+	ext4_ext_store_pblock(&newex, newblock);
+	newex.ee_len = cpu_to_le16(allocated);
+	err = ext4_ext_insert_extent(handle, inode, path, &newex);
+	if (err)
+		goto out2;
+
+	if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize)
+		EXT4_I(inode)->i_disksize = inode->i_size;
+
+	/* previous routine could use block we allocated */
+	newblock = ext_pblock(&newex);
+	__set_bit(BH_New, &bh_result->b_state);
+
+	ext4_ext_put_in_cache(inode, iblock, allocated, newblock,
+				EXT4_EXT_CACHE_EXTENT);
+out:
+	if (allocated > max_blocks)
+		allocated = max_blocks;
+	ext4_ext_show_leaf(inode, path);
+	__set_bit(BH_Mapped, &bh_result->b_state);
+	bh_result->b_bdev = inode->i_sb->s_bdev;
+	bh_result->b_blocknr = newblock;
+out2:
+	if (path) {
+		ext4_ext_drop_refs(path);
+		kfree(path);
+	}
+	mutex_unlock(&EXT4_I(inode)->truncate_mutex);
+
+	return err ? err : allocated;
+}
+
+void ext4_ext_truncate(struct inode * inode, struct page *page)
+{
+	struct address_space *mapping = inode->i_mapping;
+	struct super_block *sb = inode->i_sb;
+	unsigned long last_block;
+	handle_t *handle;
+	int err = 0;
+
+	/*
+	 * probably first extent we're gonna free will be last in block
+	 */
+	err = ext4_writepage_trans_blocks(inode) + 3;
+	handle = ext4_journal_start(inode, err);
+	if (IS_ERR(handle)) {
+		if (page) {
+			clear_highpage(page);
+			flush_dcache_page(page);
+			unlock_page(page);
+			page_cache_release(page);
+		}
+		return;
+	}
+
+	if (page)
+		ext4_block_truncate_page(handle, page, mapping, inode->i_size);
+
+	mutex_lock(&EXT4_I(inode)->truncate_mutex);
+	ext4_ext_invalidate_cache(inode);
+
+	/*
+	 * TODO: optimization is possible here.
+	 * Probably we need not scan at all,
+	 * because page truncation is enough.
+	 */
+	if (ext4_orphan_add(handle, inode))
+		goto out_stop;
+
+	/* we have to know where to truncate from in crash case */
+	EXT4_I(inode)->i_disksize = inode->i_size;
+	ext4_mark_inode_dirty(handle, inode);
+
+	last_block = (inode->i_size + sb->s_blocksize - 1)
+			>> EXT4_BLOCK_SIZE_BITS(sb);
+	err = ext4_ext_remove_space(inode, last_block);
+
+	/* In a multi-transaction truncate, we only make the final
+	 * transaction synchronous. */
+	if (IS_SYNC(inode))
+		handle->h_sync = 1;
+
+out_stop:
+	/*
+	 * If this was a simple ftruncate() and the file will remain alive,
+	 * then we need to clear up the orphan record which we created above.
+	 * However, if this was a real unlink then we were called by
+	 * ext4_delete_inode(), and we allow that function to clean up the
+	 * orphan info for us.
+	 */
+	if (inode->i_nlink)
+		ext4_orphan_del(handle, inode);
+
+	mutex_unlock(&EXT4_I(inode)->truncate_mutex);
+	ext4_journal_stop(handle);
+}
+
+/*
+ * ext4_ext_writepage_trans_blocks:
+ * calculate max number of blocks we could modify
+ * in order to allocate new block for an inode
+ */
+int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
+{
+	int needed;
+
+	needed = ext4_ext_calc_credits_for_insert(inode, NULL);
+
+	/* caller wants to allocate num blocks, but note it includes sb */
+	needed = needed * num - (num - 1);
+
+#ifdef CONFIG_QUOTA
+	needed += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
+#endif
+
+	return needed;
+}
+
+EXPORT_SYMBOL(ext4_mark_inode_dirty);
+EXPORT_SYMBOL(ext4_ext_invalidate_cache);
+EXPORT_SYMBOL(ext4_ext_insert_extent);
+EXPORT_SYMBOL(ext4_ext_walk_space);
+EXPORT_SYMBOL(ext4_ext_find_goal);
+EXPORT_SYMBOL(ext4_ext_calc_credits_for_insert);
+
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
new file mode 100644
index 0000000..0b622c0
--- /dev/null
+++ b/fs/ext4/file.c
@@ -0,0 +1,139 @@
+/*
+ *  linux/fs/ext4/file.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/file.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  ext4 fs regular file handling primitives
+ *
+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
+ *	(jj@sunsite.ms.mff.cuni.cz)
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Called when an inode is released. Note that this is different
+ * from ext4_file_open: open gets called at every open, but release
+ * gets called only when /all/ the files are closed.
+ */
+static int ext4_release_file (struct inode * inode, struct file * filp)
+{
+	/* if we are the last writer on the inode, drop the block reservation */
+	if ((filp->f_mode & FMODE_WRITE) &&
+			(atomic_read(&inode->i_writecount) == 1))
+	{
+		mutex_lock(&EXT4_I(inode)->truncate_mutex);
+		ext4_discard_reservation(inode);
+		mutex_unlock(&EXT4_I(inode)->truncate_mutex);
+	}
+	if (is_dx(inode) && filp->private_data)
+		ext4_htree_free_dir_info(filp->private_data);
+
+	return 0;
+}
+
+static ssize_t
+ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+		unsigned long nr_segs, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+	struct inode *inode = file->f_dentry->d_inode;
+	ssize_t ret;
+	int err;
+
+	ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+
+	/*
+	 * Skip flushing if there was an error, or if nothing was written.
+	 */
+	if (ret <= 0)
+		return ret;
+
+	/*
+	 * If the inode is IS_SYNC, or is O_SYNC and we are doing data
+	 * journalling then we need to make sure that we force the transaction
+	 * to disk to keep all metadata uptodate synchronously.
+	 */
+	if (file->f_flags & O_SYNC) {
+		/*
+		 * If we are non-data-journaled, then the dirty data has
+		 * already been flushed to backing store by generic_osync_inode,
+		 * and the inode has been flushed too if there have been any
+		 * modifications other than mere timestamp updates.
+		 *
+		 * Open question --- do we care about flushing timestamps too
+		 * if the inode is IS_SYNC?
+		 */
+		if (!ext4_should_journal_data(inode))
+			return ret;
+
+		goto force_commit;
+	}
+
+	/*
+	 * So we know that there has been no forced data flush.  If the inode
+	 * is marked IS_SYNC, we need to force one ourselves.
+	 */
+	if (!IS_SYNC(inode))
+		return ret;
+
+	/*
+	 * Open question #2 --- should we force data to disk here too?  If we
+	 * don't, the only impact is that data=writeback filesystems won't
+	 * flush data to disk automatically on IS_SYNC, only metadata (but
+	 * historically, that is what ext2 has done.)
+	 */
+
+force_commit:
+	err = ext4_force_commit(inode->i_sb);
+	if (err)
+		return err;
+	return ret;
+}
+
+const struct file_operations ext4_file_operations = {
+	.llseek		= generic_file_llseek,
+	.read		= do_sync_read,
+	.write		= do_sync_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= ext4_file_write,
+	.ioctl		= ext4_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext4_compat_ioctl,
+#endif
+	.mmap		= generic_file_mmap,
+	.open		= generic_file_open,
+	.release	= ext4_release_file,
+	.fsync		= ext4_sync_file,
+	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
+	.splice_write	= generic_file_splice_write,
+};
+
+struct inode_operations ext4_file_inode_operations = {
+	.truncate	= ext4_truncate,
+	.setattr	= ext4_setattr,
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= ext4_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+	.permission	= ext4_permission,
+};
+
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
new file mode 100644
index 0000000..2a167d7
--- /dev/null
+++ b/fs/ext4/fsync.c
@@ -0,0 +1,88 @@
+/*
+ *  linux/fs/ext4/fsync.c
+ *
+ *  Copyright (C) 1993  Stephen Tweedie (sct@redhat.com)
+ *  from
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
+ *                      Laboratoire MASI - Institut Blaise Pascal
+ *                      Universite Pierre et Marie Curie (Paris VI)
+ *  from
+ *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  ext4fs fsync primitive
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *
+ *  Removed unnecessary code duplication for little endian machines
+ *  and excessive __inline__s.
+ *        Andi Kleen, 1997
+ *
+ * Major simplications and cleanup - we only need to do the metadata, because
+ * we can depend on generic_block_fdatasync() to sync the data blocks.
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/writeback.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+
+/*
+ * akpm: A new design for ext4_sync_file().
+ *
+ * This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
+ * There cannot be a transaction open by this task.
+ * Another task could have dirtied this inode.  Its data can be in any
+ * state in the journalling system.
+ *
+ * What we do is just kick off a commit and wait on it.  This will snapshot the
+ * inode to disk.
+ */
+
+int ext4_sync_file(struct file * file, struct dentry *dentry, int datasync)
+{
+	struct inode *inode = dentry->d_inode;
+	int ret = 0;
+
+	J_ASSERT(ext4_journal_current_handle() == 0);
+
+	/*
+	 * data=writeback:
+	 *  The caller's filemap_fdatawrite()/wait will sync the data.
+	 *  sync_inode() will sync the metadata
+	 *
+	 * data=ordered:
+	 *  The caller's filemap_fdatawrite() will write the data and
+	 *  sync_inode() will write the inode if it is dirty.  Then the caller's
+	 *  filemap_fdatawait() will wait on the pages.
+	 *
+	 * data=journal:
+	 *  filemap_fdatawrite won't do anything (the buffers are clean).
+	 *  ext4_force_commit will write the file data into the journal and
+	 *  will wait on that.
+	 *  filemap_fdatawait() will encounter a ton of newly-dirtied pages
+	 *  (they were dirtied by commit).  But that's OK - the blocks are
+	 *  safe in-journal, which is all fsync() needs to ensure.
+	 */
+	if (ext4_should_journal_data(inode)) {
+		ret = ext4_force_commit(inode->i_sb);
+		goto out;
+	}
+
+	/*
+	 * The VFS has written the file data.  If the inode is unaltered
+	 * then we need not start a commit.
+	 */
+	if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) {
+		struct writeback_control wbc = {
+			.sync_mode = WB_SYNC_ALL,
+			.nr_to_write = 0, /* sys_fsync did this */
+		};
+		ret = sync_inode(inode, &wbc);
+	}
+out:
+	return ret;
+}
diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
new file mode 100644
index 0000000..a679663
--- /dev/null
+++ b/fs/ext4/hash.c
@@ -0,0 +1,152 @@
+/*
+ *  linux/fs/ext4/hash.c
+ *
+ * Copyright (C) 2002 by Theodore Ts'o
+ *
+ * This file is released under the GPL v2.
+ *
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ */
+
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/sched.h>
+#include <linux/ext4_fs.h>
+#include <linux/cryptohash.h>
+
+#define DELTA 0x9E3779B9
+
+static void TEA_transform(__u32 buf[4], __u32 const in[])
+{
+	__u32	sum = 0;
+	__u32	b0 = buf[0], b1 = buf[1];
+	__u32	a = in[0], b = in[1], c = in[2], d = in[3];
+	int	n = 16;
+
+	do {
+		sum += DELTA;
+		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
+		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
+	} while(--n);
+
+	buf[0] += b0;
+	buf[1] += b1;
+}
+
+
+/* The old legacy hash */
+static __u32 dx_hack_hash (const char *name, int len)
+{
+	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
+	while (len--) {
+		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
+
+		if (hash & 0x80000000) hash -= 0x7fffffff;
+		hash1 = hash0;
+		hash0 = hash;
+	}
+	return (hash0 << 1);
+}
+
+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
+{
+	__u32	pad, val;
+	int	i;
+
+	pad = (__u32)len | ((__u32)len << 8);
+	pad |= pad << 16;
+
+	val = pad;
+	if (len > num*4)
+		len = num * 4;
+	for (i=0; i < len; i++) {
+		if ((i % 4) == 0)
+			val = pad;
+		val = msg[i] + (val << 8);
+		if ((i % 4) == 3) {
+			*buf++ = val;
+			val = pad;
+			num--;
+		}
+	}
+	if (--num >= 0)
+		*buf++ = val;
+	while (--num >= 0)
+		*buf++ = pad;
+}
+
+/*
+ * Returns the hash of a filename.  If len is 0 and name is NULL, then
+ * this function can be used to test whether or not a hash version is
+ * supported.
+ *
+ * The seed is an 4 longword (32 bits) "secret" which can be used to
+ * uniquify a hash.  If the seed is all zero's, then some default seed
+ * may be used.
+ *
+ * A particular hash version specifies whether or not the seed is
+ * represented, and whether or not the returned hash is 32 bits or 64
+ * bits.  32 bit hashes will return 0 for the minor hash.
+ */
+int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+{
+	__u32	hash;
+	__u32	minor_hash = 0;
+	const char	*p;
+	int		i;
+	__u32		in[8], buf[4];
+
+	/* Initialize the default seed for the hash checksum functions */
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+
+	/* Check to see if the seed is all zero's */
+	if (hinfo->seed) {
+		for (i=0; i < 4; i++) {
+			if (hinfo->seed[i])
+				break;
+		}
+		if (i < 4)
+			memcpy(buf, hinfo->seed, sizeof(buf));
+	}
+
+	switch (hinfo->hash_version) {
+	case DX_HASH_LEGACY:
+		hash = dx_hack_hash(name, len);
+		break;
+	case DX_HASH_HALF_MD4:
+		p = name;
+		while (len > 0) {
+			str2hashbuf(p, len, in, 8);
+			half_md4_transform(buf, in);
+			len -= 32;
+			p += 32;
+		}
+		minor_hash = buf[2];
+		hash = buf[1];
+		break;
+	case DX_HASH_TEA:
+		p = name;
+		while (len > 0) {
+			str2hashbuf(p, len, in, 4);
+			TEA_transform(buf, in);
+			len -= 16;
+			p += 16;
+		}
+		hash = buf[0];
+		minor_hash = buf[1];
+		break;
+	default:
+		hinfo->hash = 0;
+		return -1;
+	}
+	hash = hash & ~1;
+	if (hash == (EXT4_HTREE_EOF << 1))
+		hash = (EXT4_HTREE_EOF-1) << 1;
+	hinfo->hash = hash;
+	hinfo->minor_hash = minor_hash;
+	return 0;
+}
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
new file mode 100644
index 0000000..c88b439
--- /dev/null
+++ b/fs/ext4/ialloc.c
@@ -0,0 +1,772 @@
+/*
+ *  linux/fs/ext4/ialloc.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  BSD ufs-inspired inode and directory allocation by
+ *  Stephen Tweedie (sct@redhat.com), 1993
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/quotaops.h>
+#include <linux/buffer_head.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <linux/blkdev.h>
+#include <asm/byteorder.h>
+
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * ialloc.c contains the inodes allocation and deallocation routines
+ */
+
+/*
+ * The free inodes are managed by bitmaps.  A file system contains several
+ * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
+ * block for inodes, N blocks for the inode table and data blocks.
+ *
+ * The file system contains group descriptors which are located after the
+ * super block.  Each descriptor contains the number of the bitmap block and
+ * the free blocks count in the block.
+ */
+
+
+/*
+ * Read the inode allocation bitmap for a given block_group, reading
+ * into the specified slot in the superblock's bitmap cache.
+ *
+ * Return buffer_head of bitmap on success or NULL.
+ */
+static struct buffer_head *
+read_inode_bitmap(struct super_block * sb, unsigned long block_group)
+{
+	struct ext4_group_desc *desc;
+	struct buffer_head *bh = NULL;
+
+	desc = ext4_get_group_desc(sb, block_group, NULL);
+	if (!desc)
+		goto error_out;
+
+	bh = sb_bread(sb, ext4_inode_bitmap(sb, desc));
+	if (!bh)
+		ext4_error(sb, "read_inode_bitmap",
+			    "Cannot read inode bitmap - "
+			    "block_group = %lu, inode_bitmap = %llu",
+			    block_group, ext4_inode_bitmap(sb, desc));
+error_out:
+	return bh;
+}
+
+/*
+ * NOTE! When we get the inode, we're the only people
+ * that have access to it, and as such there are no
+ * race conditions we have to worry about. The inode
+ * is not on the hash-lists, and it cannot be reached
+ * through the filesystem because the directory entry
+ * has been deleted earlier.
+ *
+ * HOWEVER: we must make sure that we get no aliases,
+ * which means that we have to call "clear_inode()"
+ * _before_ we mark the inode not in use in the inode
+ * bitmaps. Otherwise a newly created file might use
+ * the same inode number (not actually the same pointer
+ * though), and then we'd have two inodes sharing the
+ * same inode number and space on the harddisk.
+ */
+void ext4_free_inode (handle_t *handle, struct inode * inode)
+{
+	struct super_block * sb = inode->i_sb;
+	int is_directory;
+	unsigned long ino;
+	struct buffer_head *bitmap_bh = NULL;
+	struct buffer_head *bh2;
+	unsigned long block_group;
+	unsigned long bit;
+	struct ext4_group_desc * gdp;
+	struct ext4_super_block * es;
+	struct ext4_sb_info *sbi;
+	int fatal = 0, err;
+
+	if (atomic_read(&inode->i_count) > 1) {
+		printk ("ext4_free_inode: inode has count=%d\n",
+					atomic_read(&inode->i_count));
+		return;
+	}
+	if (inode->i_nlink) {
+		printk ("ext4_free_inode: inode has nlink=%d\n",
+			inode->i_nlink);
+		return;
+	}
+	if (!sb) {
+		printk("ext4_free_inode: inode on nonexistent device\n");
+		return;
+	}
+	sbi = EXT4_SB(sb);
+
+	ino = inode->i_ino;
+	ext4_debug ("freeing inode %lu\n", ino);
+
+	/*
+	 * Note: we must free any quota before locking the superblock,
+	 * as writing the quota to disk may need the lock as well.
+	 */
+	DQUOT_INIT(inode);
+	ext4_xattr_delete_inode(handle, inode);
+	DQUOT_FREE_INODE(inode);
+	DQUOT_DROP(inode);
+
+	is_directory = S_ISDIR(inode->i_mode);
+
+	/* Do this BEFORE marking the inode not in use or returning an error */
+	clear_inode (inode);
+
+	es = EXT4_SB(sb)->s_es;
+	if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
+		ext4_error (sb, "ext4_free_inode",
+			    "reserved or nonexistent inode %lu", ino);
+		goto error_return;
+	}
+	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+	bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
+	bitmap_bh = read_inode_bitmap(sb, block_group);
+	if (!bitmap_bh)
+		goto error_return;
+
+	BUFFER_TRACE(bitmap_bh, "get_write_access");
+	fatal = ext4_journal_get_write_access(handle, bitmap_bh);
+	if (fatal)
+		goto error_return;
+
+	/* Ok, now we can actually update the inode bitmaps.. */
+	if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+					bit, bitmap_bh->b_data))
+		ext4_error (sb, "ext4_free_inode",
+			      "bit already cleared for inode %lu", ino);
+	else {
+		gdp = ext4_get_group_desc (sb, block_group, &bh2);
+
+		BUFFER_TRACE(bh2, "get_write_access");
+		fatal = ext4_journal_get_write_access(handle, bh2);
+		if (fatal) goto error_return;
+
+		if (gdp) {
+			spin_lock(sb_bgl_lock(sbi, block_group));
+			gdp->bg_free_inodes_count = cpu_to_le16(
+				le16_to_cpu(gdp->bg_free_inodes_count) + 1);
+			if (is_directory)
+				gdp->bg_used_dirs_count = cpu_to_le16(
+				  le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+			spin_unlock(sb_bgl_lock(sbi, block_group));
+			percpu_counter_inc(&sbi->s_freeinodes_counter);
+			if (is_directory)
+				percpu_counter_dec(&sbi->s_dirs_counter);
+
+		}
+		BUFFER_TRACE(bh2, "call ext4_journal_dirty_metadata");
+		err = ext4_journal_dirty_metadata(handle, bh2);
+		if (!fatal) fatal = err;
+	}
+	BUFFER_TRACE(bitmap_bh, "call ext4_journal_dirty_metadata");
+	err = ext4_journal_dirty_metadata(handle, bitmap_bh);
+	if (!fatal)
+		fatal = err;
+	sb->s_dirt = 1;
+error_return:
+	brelse(bitmap_bh);
+	ext4_std_error(sb, fatal);
+}
+
+/*
+ * There are two policies for allocating an inode.  If the new inode is
+ * a directory, then a forward search is made for a block group with both
+ * free space and a low directory-to-inode ratio; if that fails, then of
+ * the groups with above-average free space, that group with the fewest
+ * directories already is chosen.
+ *
+ * For other inodes, search forward from the parent directory\'s block
+ * group to find a free inode.
+ */
+static int find_group_dir(struct super_block *sb, struct inode *parent)
+{
+	int ngroups = EXT4_SB(sb)->s_groups_count;
+	unsigned int freei, avefreei;
+	struct ext4_group_desc *desc, *best_desc = NULL;
+	struct buffer_head *bh;
+	int group, best_group = -1;
+
+	freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter);
+	avefreei = freei / ngroups;
+
+	for (group = 0; group < ngroups; group++) {
+		desc = ext4_get_group_desc (sb, group, &bh);
+		if (!desc || !desc->bg_free_inodes_count)
+			continue;
+		if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
+			continue;
+		if (!best_desc ||
+		    (le16_to_cpu(desc->bg_free_blocks_count) >
+		     le16_to_cpu(best_desc->bg_free_blocks_count))) {
+			best_group = group;
+			best_desc = desc;
+		}
+	}
+	return best_group;
+}
+
+/*
+ * Orlov's allocator for directories.
+ *
+ * We always try to spread first-level directories.
+ *
+ * If there are blockgroups with both free inodes and free blocks counts
+ * not worse than average we return one with smallest directory count.
+ * Otherwise we simply return a random group.
+ *
+ * For the rest rules look so:
+ *
+ * It's OK to put directory into a group unless
+ * it has too many directories already (max_dirs) or
+ * it has too few free inodes left (min_inodes) or
+ * it has too few free blocks left (min_blocks) or
+ * it's already running too large debt (max_debt).
+ * Parent's group is prefered, if it doesn't satisfy these
+ * conditions we search cyclically through the rest. If none
+ * of the groups look good we just look for a group with more
+ * free inodes than average (starting at parent's group).
+ *
+ * Debt is incremented each time we allocate a directory and decremented
+ * when we allocate an inode, within 0--255.
+ */
+
+#define INODE_COST 64
+#define BLOCK_COST 256
+
+static int find_group_orlov(struct super_block *sb, struct inode *parent)
+{
+	int parent_group = EXT4_I(parent)->i_block_group;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_super_block *es = sbi->s_es;
+	int ngroups = sbi->s_groups_count;
+	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
+	unsigned int freei, avefreei;
+	ext4_fsblk_t freeb, avefreeb;
+	ext4_fsblk_t blocks_per_dir;
+	unsigned int ndirs;
+	int max_debt, max_dirs, min_inodes;
+	ext4_grpblk_t min_blocks;
+	int group = -1, i;
+	struct ext4_group_desc *desc;
+	struct buffer_head *bh;
+
+	freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
+	avefreei = freei / ngroups;
+	freeb = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+	avefreeb = freeb;
+	do_div(avefreeb, ngroups);
+	ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
+
+	if ((parent == sb->s_root->d_inode) ||
+	    (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) {
+		int best_ndir = inodes_per_group;
+		int best_group = -1;
+
+		get_random_bytes(&group, sizeof(group));
+		parent_group = (unsigned)group % ngroups;
+		for (i = 0; i < ngroups; i++) {
+			group = (parent_group + i) % ngroups;
+			desc = ext4_get_group_desc (sb, group, &bh);
+			if (!desc || !desc->bg_free_inodes_count)
+				continue;
+			if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir)
+				continue;
+			if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
+				continue;
+			if (le16_to_cpu(desc->bg_free_blocks_count) < avefreeb)
+				continue;
+			best_group = group;
+			best_ndir = le16_to_cpu(desc->bg_used_dirs_count);
+		}
+		if (best_group >= 0)
+			return best_group;
+		goto fallback;
+	}
+
+	blocks_per_dir = ext4_blocks_count(es) - freeb;
+	do_div(blocks_per_dir, ndirs);
+
+	max_dirs = ndirs / ngroups + inodes_per_group / 16;
+	min_inodes = avefreei - inodes_per_group / 4;
+	min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb) / 4;
+
+	max_debt = EXT4_BLOCKS_PER_GROUP(sb);
+	max_debt /= max_t(int, blocks_per_dir, BLOCK_COST);
+	if (max_debt * INODE_COST > inodes_per_group)
+		max_debt = inodes_per_group / INODE_COST;
+	if (max_debt > 255)
+		max_debt = 255;
+	if (max_debt == 0)
+		max_debt = 1;
+
+	for (i = 0; i < ngroups; i++) {
+		group = (parent_group + i) % ngroups;
+		desc = ext4_get_group_desc (sb, group, &bh);
+		if (!desc || !desc->bg_free_inodes_count)
+			continue;
+		if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs)
+			continue;
+		if (le16_to_cpu(desc->bg_free_inodes_count) < min_inodes)
+			continue;
+		if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks)
+			continue;
+		return group;
+	}
+
+fallback:
+	for (i = 0; i < ngroups; i++) {
+		group = (parent_group + i) % ngroups;
+		desc = ext4_get_group_desc (sb, group, &bh);
+		if (!desc || !desc->bg_free_inodes_count)
+			continue;
+		if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
+			return group;
+	}
+
+	if (avefreei) {
+		/*
+		 * The free-inodes counter is approximate, and for really small
+		 * filesystems the above test can fail to find any blockgroups
+		 */
+		avefreei = 0;
+		goto fallback;
+	}
+
+	return -1;
+}
+
+static int find_group_other(struct super_block *sb, struct inode *parent)
+{
+	int parent_group = EXT4_I(parent)->i_block_group;
+	int ngroups = EXT4_SB(sb)->s_groups_count;
+	struct ext4_group_desc *desc;
+	struct buffer_head *bh;
+	int group, i;
+
+	/*
+	 * Try to place the inode in its parent directory
+	 */
+	group = parent_group;
+	desc = ext4_get_group_desc (sb, group, &bh);
+	if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
+			le16_to_cpu(desc->bg_free_blocks_count))
+		return group;
+
+	/*
+	 * We're going to place this inode in a different blockgroup from its
+	 * parent.  We want to cause files in a common directory to all land in
+	 * the same blockgroup.  But we want files which are in a different
+	 * directory which shares a blockgroup with our parent to land in a
+	 * different blockgroup.
+	 *
+	 * So add our directory's i_ino into the starting point for the hash.
+	 */
+	group = (group + parent->i_ino) % ngroups;
+
+	/*
+	 * Use a quadratic hash to find a group with a free inode and some free
+	 * blocks.
+	 */
+	for (i = 1; i < ngroups; i <<= 1) {
+		group += i;
+		if (group >= ngroups)
+			group -= ngroups;
+		desc = ext4_get_group_desc (sb, group, &bh);
+		if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
+				le16_to_cpu(desc->bg_free_blocks_count))
+			return group;
+	}
+
+	/*
+	 * That failed: try linear search for a free inode, even if that group
+	 * has no free blocks.
+	 */
+	group = parent_group;
+	for (i = 0; i < ngroups; i++) {
+		if (++group >= ngroups)
+			group = 0;
+		desc = ext4_get_group_desc (sb, group, &bh);
+		if (desc && le16_to_cpu(desc->bg_free_inodes_count))
+			return group;
+	}
+
+	return -1;
+}
+
+/*
+ * There are two policies for allocating an inode.  If the new inode is
+ * a directory, then a forward search is made for a block group with both
+ * free space and a low directory-to-inode ratio; if that fails, then of
+ * the groups with above-average free space, that group with the fewest
+ * directories already is chosen.
+ *
+ * For other inodes, search forward from the parent directory's block
+ * group to find a free inode.
+ */
+struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+{
+	struct super_block *sb;
+	struct buffer_head *bitmap_bh = NULL;
+	struct buffer_head *bh2;
+	int group;
+	unsigned long ino = 0;
+	struct inode * inode;
+	struct ext4_group_desc * gdp = NULL;
+	struct ext4_super_block * es;
+	struct ext4_inode_info *ei;
+	struct ext4_sb_info *sbi;
+	int err = 0;
+	struct inode *ret;
+	int i;
+
+	/* Cannot create files in a deleted directory */
+	if (!dir || !dir->i_nlink)
+		return ERR_PTR(-EPERM);
+
+	sb = dir->i_sb;
+	inode = new_inode(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	ei = EXT4_I(inode);
+
+	sbi = EXT4_SB(sb);
+	es = sbi->s_es;
+	if (S_ISDIR(mode)) {
+		if (test_opt (sb, OLDALLOC))
+			group = find_group_dir(sb, dir);
+		else
+			group = find_group_orlov(sb, dir);
+	} else
+		group = find_group_other(sb, dir);
+
+	err = -ENOSPC;
+	if (group == -1)
+		goto out;
+
+	for (i = 0; i < sbi->s_groups_count; i++) {
+		err = -EIO;
+
+		gdp = ext4_get_group_desc(sb, group, &bh2);
+		if (!gdp)
+			goto fail;
+
+		brelse(bitmap_bh);
+		bitmap_bh = read_inode_bitmap(sb, group);
+		if (!bitmap_bh)
+			goto fail;
+
+		ino = 0;
+
+repeat_in_this_group:
+		ino = ext4_find_next_zero_bit((unsigned long *)
+				bitmap_bh->b_data, EXT4_INODES_PER_GROUP(sb), ino);
+		if (ino < EXT4_INODES_PER_GROUP(sb)) {
+
+			BUFFER_TRACE(bitmap_bh, "get_write_access");
+			err = ext4_journal_get_write_access(handle, bitmap_bh);
+			if (err)
+				goto fail;
+
+			if (!ext4_set_bit_atomic(sb_bgl_lock(sbi, group),
+						ino, bitmap_bh->b_data)) {
+				/* we won it */
+				BUFFER_TRACE(bitmap_bh,
+					"call ext4_journal_dirty_metadata");
+				err = ext4_journal_dirty_metadata(handle,
+								bitmap_bh);
+				if (err)
+					goto fail;
+				goto got;
+			}
+			/* we lost it */
+			jbd2_journal_release_buffer(handle, bitmap_bh);
+
+			if (++ino < EXT4_INODES_PER_GROUP(sb))
+				goto repeat_in_this_group;
+		}
+
+		/*
+		 * This case is possible in concurrent environment.  It is very
+		 * rare.  We cannot repeat the find_group_xxx() call because
+		 * that will simply return the same blockgroup, because the
+		 * group descriptor metadata has not yet been updated.
+		 * So we just go onto the next blockgroup.
+		 */
+		if (++group == sbi->s_groups_count)
+			group = 0;
+	}
+	err = -ENOSPC;
+	goto out;
+
+got:
+	ino += group * EXT4_INODES_PER_GROUP(sb) + 1;
+	if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
+		ext4_error (sb, "ext4_new_inode",
+			    "reserved inode or inode > inodes count - "
+			    "block_group = %d, inode=%lu", group, ino);
+		err = -EIO;
+		goto fail;
+	}
+
+	BUFFER_TRACE(bh2, "get_write_access");
+	err = ext4_journal_get_write_access(handle, bh2);
+	if (err) goto fail;
+	spin_lock(sb_bgl_lock(sbi, group));
+	gdp->bg_free_inodes_count =
+		cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
+	if (S_ISDIR(mode)) {
+		gdp->bg_used_dirs_count =
+			cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
+	}
+	spin_unlock(sb_bgl_lock(sbi, group));
+	BUFFER_TRACE(bh2, "call ext4_journal_dirty_metadata");
+	err = ext4_journal_dirty_metadata(handle, bh2);
+	if (err) goto fail;
+
+	percpu_counter_dec(&sbi->s_freeinodes_counter);
+	if (S_ISDIR(mode))
+		percpu_counter_inc(&sbi->s_dirs_counter);
+	sb->s_dirt = 1;
+
+	inode->i_uid = current->fsuid;
+	if (test_opt (sb, GRPID))
+		inode->i_gid = dir->i_gid;
+	else if (dir->i_mode & S_ISGID) {
+		inode->i_gid = dir->i_gid;
+		if (S_ISDIR(mode))
+			mode |= S_ISGID;
+	} else
+		inode->i_gid = current->fsgid;
+	inode->i_mode = mode;
+
+	inode->i_ino = ino;
+	/* This is the optimal IO size (for stat), not the fs block size */
+	inode->i_blocks = 0;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+
+	memset(ei->i_data, 0, sizeof(ei->i_data));
+	ei->i_dir_start_lookup = 0;
+	ei->i_disksize = 0;
+
+	ei->i_flags = EXT4_I(dir)->i_flags & ~EXT4_INDEX_FL;
+	if (S_ISLNK(mode))
+		ei->i_flags &= ~(EXT4_IMMUTABLE_FL|EXT4_APPEND_FL);
+	/* dirsync only applies to directories */
+	if (!S_ISDIR(mode))
+		ei->i_flags &= ~EXT4_DIRSYNC_FL;
+#ifdef EXT4_FRAGMENTS
+	ei->i_faddr = 0;
+	ei->i_frag_no = 0;
+	ei->i_frag_size = 0;
+#endif
+	ei->i_file_acl = 0;
+	ei->i_dir_acl = 0;
+	ei->i_dtime = 0;
+	ei->i_block_alloc_info = NULL;
+	ei->i_block_group = group;
+
+	ext4_set_inode_flags(inode);
+	if (IS_DIRSYNC(inode))
+		handle->h_sync = 1;
+	insert_inode_hash(inode);
+	spin_lock(&sbi->s_next_gen_lock);
+	inode->i_generation = sbi->s_next_generation++;
+	spin_unlock(&sbi->s_next_gen_lock);
+
+	ei->i_state = EXT4_STATE_NEW;
+	ei->i_extra_isize =
+		(EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) ?
+		sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE : 0;
+
+	ret = inode;
+	if(DQUOT_ALLOC_INODE(inode)) {
+		err = -EDQUOT;
+		goto fail_drop;
+	}
+
+	err = ext4_init_acl(handle, inode, dir);
+	if (err)
+		goto fail_free_drop;
+
+	err = ext4_init_security(handle,inode, dir);
+	if (err)
+		goto fail_free_drop;
+
+	err = ext4_mark_inode_dirty(handle, inode);
+	if (err) {
+		ext4_std_error(sb, err);
+		goto fail_free_drop;
+	}
+	if (test_opt(sb, EXTENTS)) {
+		EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
+		ext4_ext_tree_init(handle, inode);
+		if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+			err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+			if (err) goto fail;
+			EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS);
+			BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "call ext4_journal_dirty_metadata");
+			err = ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
+		}
+	}
+
+	ext4_debug("allocating inode %lu\n", inode->i_ino);
+	goto really_out;
+fail:
+	ext4_std_error(sb, err);
+out:
+	iput(inode);
+	ret = ERR_PTR(err);
+really_out:
+	brelse(bitmap_bh);
+	return ret;
+
+fail_free_drop:
+	DQUOT_FREE_INODE(inode);
+
+fail_drop:
+	DQUOT_DROP(inode);
+	inode->i_flags |= S_NOQUOTA;
+	inode->i_nlink = 0;
+	iput(inode);
+	brelse(bitmap_bh);
+	return ERR_PTR(err);
+}
+
+/* Verify that we are loading a valid orphan from disk */
+struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+{
+	unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
+	unsigned long block_group;
+	int bit;
+	struct buffer_head *bitmap_bh = NULL;
+	struct inode *inode = NULL;
+
+	/* Error cases - e2fsck has already cleaned up for us */
+	if (ino > max_ino) {
+		ext4_warning(sb, __FUNCTION__,
+			     "bad orphan ino %lu!  e2fsck was run?", ino);
+		goto out;
+	}
+
+	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+	bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
+	bitmap_bh = read_inode_bitmap(sb, block_group);
+	if (!bitmap_bh) {
+		ext4_warning(sb, __FUNCTION__,
+			     "inode bitmap error for orphan %lu", ino);
+		goto out;
+	}
+
+	/* Having the inode bit set should be a 100% indicator that this
+	 * is a valid orphan (no e2fsck run on fs).  Orphans also include
+	 * inodes that were being truncated, so we can't check i_nlink==0.
+	 */
+	if (!ext4_test_bit(bit, bitmap_bh->b_data) ||
+			!(inode = iget(sb, ino)) || is_bad_inode(inode) ||
+			NEXT_ORPHAN(inode) > max_ino) {
+		ext4_warning(sb, __FUNCTION__,
+			     "bad orphan inode %lu!  e2fsck was run?", ino);
+		printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+		       bit, (unsigned long long)bitmap_bh->b_blocknr,
+		       ext4_test_bit(bit, bitmap_bh->b_data));
+		printk(KERN_NOTICE "inode=%p\n", inode);
+		if (inode) {
+			printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
+			       is_bad_inode(inode));
+			printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
+			       NEXT_ORPHAN(inode));
+			printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
+		}
+		/* Avoid freeing blocks if we got a bad deleted inode */
+		if (inode && inode->i_nlink == 0)
+			inode->i_blocks = 0;
+		iput(inode);
+		inode = NULL;
+	}
+out:
+	brelse(bitmap_bh);
+	return inode;
+}
+
+unsigned long ext4_count_free_inodes (struct super_block * sb)
+{
+	unsigned long desc_count;
+	struct ext4_group_desc *gdp;
+	int i;
+#ifdef EXT4FS_DEBUG
+	struct ext4_super_block *es;
+	unsigned long bitmap_count, x;
+	struct buffer_head *bitmap_bh = NULL;
+
+	es = EXT4_SB(sb)->s_es;
+	desc_count = 0;
+	bitmap_count = 0;
+	gdp = NULL;
+	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+		gdp = ext4_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
+		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+		brelse(bitmap_bh);
+		bitmap_bh = read_inode_bitmap(sb, i);
+		if (!bitmap_bh)
+			continue;
+
+		x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8);
+		printk("group %d: stored = %d, counted = %lu\n",
+			i, le16_to_cpu(gdp->bg_free_inodes_count), x);
+		bitmap_count += x;
+	}
+	brelse(bitmap_bh);
+	printk("ext4_count_free_inodes: stored = %u, computed = %lu, %lu\n",
+		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
+	return desc_count;
+#else
+	desc_count = 0;
+	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+		gdp = ext4_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
+		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+		cond_resched();
+	}
+	return desc_count;
+#endif
+}
+
+/* Called at mount-time, super-block is locked */
+unsigned long ext4_count_dirs (struct super_block * sb)
+{
+	unsigned long count = 0;
+	int i;
+
+	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+		struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
+		count += le16_to_cpu(gdp->bg_used_dirs_count);
+	}
+	return count;
+}
+
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
new file mode 100644
index 0000000..0a60ec5
--- /dev/null
+++ b/fs/ext4/inode.c
@@ -0,0 +1,3233 @@
+/*
+ *  linux/fs/ext4/inode.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/inode.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Goal-directed block allocation by Stephen Tweedie
+ *	(sct@redhat.com), 1993, 1998
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
+ *	(jj@sunsite.ms.mff.cuni.cz)
+ *
+ *  Assorted race fixes, rewrite of ext4_get_block() by Al Viro, 2000
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/jbd2.h>
+#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/string.h>
+#include <linux/buffer_head.h>
+#include <linux/writeback.h>
+#include <linux/mpage.h>
+#include <linux/uio.h>
+#include <linux/bio.h>
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Test whether an inode is a fast symlink.
+ */
+static int ext4_inode_is_fast_symlink(struct inode *inode)
+{
+	int ea_blocks = EXT4_I(inode)->i_file_acl ?
+		(inode->i_sb->s_blocksize >> 9) : 0;
+
+	return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
+}
+
+/*
+ * The ext4 forget function must perform a revoke if we are freeing data
+ * which has been journaled.  Metadata (eg. indirect blocks) must be
+ * revoked in all cases.
+ *
+ * "bh" may be NULL: a metadata block may have been freed from memory
+ * but there may still be a record of it in the journal, and that record
+ * still needs to be revoked.
+ */
+int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+			struct buffer_head *bh, ext4_fsblk_t blocknr)
+{
+	int err;
+
+	might_sleep();
+
+	BUFFER_TRACE(bh, "enter");
+
+	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
+		  "data mode %lx\n",
+		  bh, is_metadata, inode->i_mode,
+		  test_opt(inode->i_sb, DATA_FLAGS));
+
+	/* Never use the revoke function if we are doing full data
+	 * journaling: there is no need to, and a V1 superblock won't
+	 * support it.  Otherwise, only skip the revoke on un-journaled
+	 * data blocks. */
+
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
+	    (!is_metadata && !ext4_should_journal_data(inode))) {
+		if (bh) {
+			BUFFER_TRACE(bh, "call jbd2_journal_forget");
+			return ext4_journal_forget(handle, bh);
+		}
+		return 0;
+	}
+
+	/*
+	 * data!=journal && (is_metadata || should_journal_data(inode))
+	 */
+	BUFFER_TRACE(bh, "call ext4_journal_revoke");
+	err = ext4_journal_revoke(handle, blocknr, bh);
+	if (err)
+		ext4_abort(inode->i_sb, __FUNCTION__,
+			   "error %d when attempting revoke", err);
+	BUFFER_TRACE(bh, "exit");
+	return err;
+}
+
+/*
+ * Work out how many blocks we need to proceed with the next chunk of a
+ * truncate transaction.
+ */
+static unsigned long blocks_for_truncate(struct inode *inode)
+{
+	unsigned long needed;
+
+	needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
+
+	/* Give ourselves just enough room to cope with inodes in which
+	 * i_blocks is corrupt: we've seen disk corruptions in the past
+	 * which resulted in random data in an inode which looked enough
+	 * like a regular file for ext4 to try to delete it.  Things
+	 * will go a bit crazy if that happens, but at least we should
+	 * try not to panic the whole kernel. */
+	if (needed < 2)
+		needed = 2;
+
+	/* But we need to bound the transaction so we don't overflow the
+	 * journal. */
+	if (needed > EXT4_MAX_TRANS_DATA)
+		needed = EXT4_MAX_TRANS_DATA;
+
+	return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
+}
+
+/*
+ * Truncate transactions can be complex and absolutely huge.  So we need to
+ * be able to restart the transaction at a conventient checkpoint to make
+ * sure we don't overflow the journal.
+ *
+ * start_transaction gets us a new handle for a truncate transaction,
+ * and extend_transaction tries to extend the existing one a bit.  If
+ * extend fails, we need to propagate the failure up and restart the
+ * transaction in the top-level truncate loop. --sct
+ */
+static handle_t *start_transaction(struct inode *inode)
+{
+	handle_t *result;
+
+	result = ext4_journal_start(inode, blocks_for_truncate(inode));
+	if (!IS_ERR(result))
+		return result;
+
+	ext4_std_error(inode->i_sb, PTR_ERR(result));
+	return result;
+}
+
+/*
+ * Try to extend this transaction for the purposes of truncation.
+ *
+ * Returns 0 if we managed to create more room.  If we can't create more
+ * room, and the transaction must be restarted we return 1.
+ */
+static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
+{
+	if (handle->h_buffer_credits > EXT4_RESERVE_TRANS_BLOCKS)
+		return 0;
+	if (!ext4_journal_extend(handle, blocks_for_truncate(inode)))
+		return 0;
+	return 1;
+}
+
+/*
+ * Restart the transaction associated with *handle.  This does a commit,
+ * so before we call here everything must be consistently dirtied against
+ * this transaction.
+ */
+static int ext4_journal_test_restart(handle_t *handle, struct inode *inode)
+{
+	jbd_debug(2, "restarting handle %p\n", handle);
+	return ext4_journal_restart(handle, blocks_for_truncate(inode));
+}
+
+/*
+ * Called at the last iput() if i_nlink is zero.
+ */
+void ext4_delete_inode (struct inode * inode)
+{
+	handle_t *handle;
+
+	truncate_inode_pages(&inode->i_data, 0);
+
+	if (is_bad_inode(inode))
+		goto no_delete;
+
+	handle = start_transaction(inode);
+	if (IS_ERR(handle)) {
+		/*
+		 * If we're going to skip the normal cleanup, we still need to
+		 * make sure that the in-core orphan linked list is properly
+		 * cleaned up.
+		 */
+		ext4_orphan_del(NULL, inode);
+		goto no_delete;
+	}
+
+	if (IS_SYNC(inode))
+		handle->h_sync = 1;
+	inode->i_size = 0;
+	if (inode->i_blocks)
+		ext4_truncate(inode);
+	/*
+	 * Kill off the orphan record which ext4_truncate created.
+	 * AKPM: I think this can be inside the above `if'.
+	 * Note that ext4_orphan_del() has to be able to cope with the
+	 * deletion of a non-existent orphan - this is because we don't
+	 * know if ext4_truncate() actually created an orphan record.
+	 * (Well, we could do this if we need to, but heck - it works)
+	 */
+	ext4_orphan_del(handle, inode);
+	EXT4_I(inode)->i_dtime	= get_seconds();
+
+	/*
+	 * One subtle ordering requirement: if anything has gone wrong
+	 * (transaction abort, IO errors, whatever), then we can still
+	 * do these next steps (the fs will already have been marked as
+	 * having errors), but we can't free the inode if the mark_dirty
+	 * fails.
+	 */
+	if (ext4_mark_inode_dirty(handle, inode))
+		/* If that failed, just do the required in-core inode clear. */
+		clear_inode(inode);
+	else
+		ext4_free_inode(handle, inode);
+	ext4_journal_stop(handle);
+	return;
+no_delete:
+	clear_inode(inode);	/* We must guarantee clearing of inode... */
+}
+
+typedef struct {
+	__le32	*p;
+	__le32	key;
+	struct buffer_head *bh;
+} Indirect;
+
+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
+{
+	p->key = *(p->p = v);
+	p->bh = bh;
+}
+
+static int verify_chain(Indirect *from, Indirect *to)
+{
+	while (from <= to && from->key == *from->p)
+		from++;
+	return (from > to);
+}
+
+/**
+ *	ext4_block_to_path - parse the block number into array of offsets
+ *	@inode: inode in question (we are only interested in its superblock)
+ *	@i_block: block number to be parsed
+ *	@offsets: array to store the offsets in
+ *      @boundary: set this non-zero if the referred-to block is likely to be
+ *             followed (on disk) by an indirect block.
+ *
+ *	To store the locations of file's data ext4 uses a data structure common
+ *	for UNIX filesystems - tree of pointers anchored in the inode, with
+ *	data blocks at leaves and indirect blocks in intermediate nodes.
+ *	This function translates the block number into path in that tree -
+ *	return value is the path length and @offsets[n] is the offset of
+ *	pointer to (n+1)th node in the nth one. If @block is out of range
+ *	(negative or too large) warning is printed and zero returned.
+ *
+ *	Note: function doesn't find node addresses, so no IO is needed. All
+ *	we need to know is the capacity of indirect blocks (taken from the
+ *	inode->i_sb).
+ */
+
+/*
+ * Portability note: the last comparison (check that we fit into triple
+ * indirect block) is spelled differently, because otherwise on an
+ * architecture with 32-bit longs and 8Kb pages we might get into trouble
+ * if our filesystem had 8Kb blocks. We might use long long, but that would
+ * kill us on x86. Oh, well, at least the sign propagation does not matter -
+ * i_block would have to be negative in the very beginning, so we would not
+ * get there at all.
+ */
+
+static int ext4_block_to_path(struct inode *inode,
+			long i_block, int offsets[4], int *boundary)
+{
+	int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+	int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb);
+	const long direct_blocks = EXT4_NDIR_BLOCKS,
+		indirect_blocks = ptrs,
+		double_blocks = (1 << (ptrs_bits * 2));
+	int n = 0;
+	int final = 0;
+
+	if (i_block < 0) {
+		ext4_warning (inode->i_sb, "ext4_block_to_path", "block < 0");
+	} else if (i_block < direct_blocks) {
+		offsets[n++] = i_block;
+		final = direct_blocks;
+	} else if ( (i_block -= direct_blocks) < indirect_blocks) {
+		offsets[n++] = EXT4_IND_BLOCK;
+		offsets[n++] = i_block;
+		final = ptrs;
+	} else if ((i_block -= indirect_blocks) < double_blocks) {
+		offsets[n++] = EXT4_DIND_BLOCK;
+		offsets[n++] = i_block >> ptrs_bits;
+		offsets[n++] = i_block & (ptrs - 1);
+		final = ptrs;
+	} else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
+		offsets[n++] = EXT4_TIND_BLOCK;
+		offsets[n++] = i_block >> (ptrs_bits * 2);
+		offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
+		offsets[n++] = i_block & (ptrs - 1);
+		final = ptrs;
+	} else {
+		ext4_warning(inode->i_sb, "ext4_block_to_path", "block > big");
+	}
+	if (boundary)
+		*boundary = final - 1 - (i_block & (ptrs - 1));
+	return n;
+}
+
+/**
+ *	ext4_get_branch - read the chain of indirect blocks leading to data
+ *	@inode: inode in question
+ *	@depth: depth of the chain (1 - direct pointer, etc.)
+ *	@offsets: offsets of pointers in inode/indirect blocks
+ *	@chain: place to store the result
+ *	@err: here we store the error value
+ *
+ *	Function fills the array of triples <key, p, bh> and returns %NULL
+ *	if everything went OK or the pointer to the last filled triple
+ *	(incomplete one) otherwise. Upon the return chain[i].key contains
+ *	the number of (i+1)-th block in the chain (as it is stored in memory,
+ *	i.e. little-endian 32-bit), chain[i].p contains the address of that
+ *	number (it points into struct inode for i==0 and into the bh->b_data
+ *	for i>0) and chain[i].bh points to the buffer_head of i-th indirect
+ *	block for i>0 and NULL for i==0. In other words, it holds the block
+ *	numbers of the chain, addresses they were taken from (and where we can
+ *	verify that chain did not change) and buffer_heads hosting these
+ *	numbers.
+ *
+ *	Function stops when it stumbles upon zero pointer (absent block)
+ *		(pointer to last triple returned, *@err == 0)
+ *	or when it gets an IO error reading an indirect block
+ *		(ditto, *@err == -EIO)
+ *	or when it notices that chain had been changed while it was reading
+ *		(ditto, *@err == -EAGAIN)
+ *	or when it reads all @depth-1 indirect blocks successfully and finds
+ *	the whole chain, all way to the data (returns %NULL, *err == 0).
+ */
+static Indirect *ext4_get_branch(struct inode *inode, int depth, int *offsets,
+				 Indirect chain[4], int *err)
+{
+	struct super_block *sb = inode->i_sb;
+	Indirect *p = chain;
+	struct buffer_head *bh;
+
+	*err = 0;
+	/* i_data is not going away, no lock needed */
+	add_chain (chain, NULL, EXT4_I(inode)->i_data + *offsets);
+	if (!p->key)
+		goto no_block;
+	while (--depth) {
+		bh = sb_bread(sb, le32_to_cpu(p->key));
+		if (!bh)
+			goto failure;
+		/* Reader: pointers */
+		if (!verify_chain(chain, p))
+			goto changed;
+		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
+		/* Reader: end */
+		if (!p->key)
+			goto no_block;
+	}
+	return NULL;
+
+changed:
+	brelse(bh);
+	*err = -EAGAIN;
+	goto no_block;
+failure:
+	*err = -EIO;
+no_block:
+	return p;
+}
+
+/**
+ *	ext4_find_near - find a place for allocation with sufficient locality
+ *	@inode: owner
+ *	@ind: descriptor of indirect block.
+ *
+ *	This function returns the prefered place for block allocation.
+ *	It is used when heuristic for sequential allocation fails.
+ *	Rules are:
+ *	  + if there is a block to the left of our position - allocate near it.
+ *	  + if pointer will live in indirect block - allocate near that block.
+ *	  + if pointer will live in inode - allocate in the same
+ *	    cylinder group.
+ *
+ * In the latter case we colour the starting block by the callers PID to
+ * prevent it from clashing with concurrent allocations for a different inode
+ * in the same block group.   The PID is used here so that functionally related
+ * files will be close-by on-disk.
+ *
+ *	Caller must make sure that @ind is valid and will stay that way.
+ */
+static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	__le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data;
+	__le32 *p;
+	ext4_fsblk_t bg_start;
+	ext4_grpblk_t colour;
+
+	/* Try to find previous block */
+	for (p = ind->p - 1; p >= start; p--) {
+		if (*p)
+			return le32_to_cpu(*p);
+	}
+
+	/* No such thing, so let's try location of indirect block */
+	if (ind->bh)
+		return ind->bh->b_blocknr;
+
+	/*
+	 * It is going to be referred to from the inode itself? OK, just put it
+	 * into the same cylinder group then.
+	 */
+	bg_start = ext4_group_first_block_no(inode->i_sb, ei->i_block_group);
+	colour = (current->pid % 16) *
+			(EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+	return bg_start + colour;
+}
+
+/**
+ *	ext4_find_goal - find a prefered place for allocation.
+ *	@inode: owner
+ *	@block:  block we want
+ *	@chain:  chain of indirect blocks
+ *	@partial: pointer to the last triple within a chain
+ *	@goal:	place to store the result.
+ *
+ *	Normally this function find the prefered place for block allocation,
+ *	stores it in *@goal and returns zero.
+ */
+
+static ext4_fsblk_t ext4_find_goal(struct inode *inode, long block,
+		Indirect chain[4], Indirect *partial)
+{
+	struct ext4_block_alloc_info *block_i;
+
+	block_i =  EXT4_I(inode)->i_block_alloc_info;
+
+	/*
+	 * try the heuristic for sequential allocation,
+	 * failing that at least try to get decent locality.
+	 */
+	if (block_i && (block == block_i->last_alloc_logical_block + 1)
+		&& (block_i->last_alloc_physical_block != 0)) {
+		return block_i->last_alloc_physical_block + 1;
+	}
+
+	return ext4_find_near(inode, partial);
+}
+
+/**
+ *	ext4_blks_to_allocate: Look up the block map and count the number
+ *	of direct blocks need to be allocated for the given branch.
+ *
+ *	@branch: chain of indirect blocks
+ *	@k: number of blocks need for indirect blocks
+ *	@blks: number of data blocks to be mapped.
+ *	@blocks_to_boundary:  the offset in the indirect block
+ *
+ *	return the total number of blocks to be allocate, including the
+ *	direct and indirect blocks.
+ */
+static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
+		int blocks_to_boundary)
+{
+	unsigned long count = 0;
+
+	/*
+	 * Simple case, [t,d]Indirect block(s) has not allocated yet
+	 * then it's clear blocks on that path have not allocated
+	 */
+	if (k > 0) {
+		/* right now we don't handle cross boundary allocation */
+		if (blks < blocks_to_boundary + 1)
+			count += blks;
+		else
+			count += blocks_to_boundary + 1;
+		return count;
+	}
+
+	count++;
+	while (count < blks && count <= blocks_to_boundary &&
+		le32_to_cpu(*(branch[0].p + count)) == 0) {
+		count++;
+	}
+	return count;
+}
+
+/**
+ *	ext4_alloc_blocks: multiple allocate blocks needed for a branch
+ *	@indirect_blks: the number of blocks need to allocate for indirect
+ *			blocks
+ *
+ *	@new_blocks: on return it will store the new block numbers for
+ *	the indirect blocks(if needed) and the first direct block,
+ *	@blks:	on return it will store the total number of allocated
+ *		direct blocks
+ */
+static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+			ext4_fsblk_t goal, int indirect_blks, int blks,
+			ext4_fsblk_t new_blocks[4], int *err)
+{
+	int target, i;
+	unsigned long count = 0;
+	int index = 0;
+	ext4_fsblk_t current_block = 0;
+	int ret = 0;
+
+	/*
+	 * Here we try to allocate the requested multiple blocks at once,
+	 * on a best-effort basis.
+	 * To build a branch, we should allocate blocks for
+	 * the indirect blocks(if not allocated yet), and at least
+	 * the first direct block of this branch.  That's the
+	 * minimum number of blocks need to allocate(required)
+	 */
+	target = blks + indirect_blks;
+
+	while (1) {
+		count = target;
+		/* allocating blocks for indirect blocks and direct blocks */
+		current_block = ext4_new_blocks(handle,inode,goal,&count,err);
+		if (*err)
+			goto failed_out;
+
+		target -= count;
+		/* allocate blocks for indirect blocks */
+		while (index < indirect_blks && count) {
+			new_blocks[index++] = current_block++;
+			count--;
+		}
+
+		if (count > 0)
+			break;
+	}
+
+	/* save the new block number for the first direct block */
+	new_blocks[index] = current_block;
+
+	/* total number of blocks allocated for direct blocks */
+	ret = count;
+	*err = 0;
+	return ret;
+failed_out:
+	for (i = 0; i <index; i++)
+		ext4_free_blocks(handle, inode, new_blocks[i], 1);
+	return ret;
+}
+
+/**
+ *	ext4_alloc_branch - allocate and set up a chain of blocks.
+ *	@inode: owner
+ *	@indirect_blks: number of allocated indirect blocks
+ *	@blks: number of allocated direct blocks
+ *	@offsets: offsets (in the blocks) to store the pointers to next.
+ *	@branch: place to store the chain in.
+ *
+ *	This function allocates blocks, zeroes out all but the last one,
+ *	links them into chain and (if we are synchronous) writes them to disk.
+ *	In other words, it prepares a branch that can be spliced onto the
+ *	inode. It stores the information about that chain in the branch[], in
+ *	the same format as ext4_get_branch() would do. We are calling it after
+ *	we had read the existing part of chain and partial points to the last
+ *	triple of that (one with zero ->key). Upon the exit we have the same
+ *	picture as after the successful ext4_get_block(), except that in one
+ *	place chain is disconnected - *branch->p is still zero (we did not
+ *	set the last link), but branch->key contains the number that should
+ *	be placed into *branch->p to fill that gap.
+ *
+ *	If allocation fails we free all blocks we've allocated (and forget
+ *	their buffer_heads) and return the error value the from failed
+ *	ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain
+ *	as described above and return 0.
+ */
+static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+			int indirect_blks, int *blks, ext4_fsblk_t goal,
+			int *offsets, Indirect *branch)
+{
+	int blocksize = inode->i_sb->s_blocksize;
+	int i, n = 0;
+	int err = 0;
+	struct buffer_head *bh;
+	int num;
+	ext4_fsblk_t new_blocks[4];
+	ext4_fsblk_t current_block;
+
+	num = ext4_alloc_blocks(handle, inode, goal, indirect_blks,
+				*blks, new_blocks, &err);
+	if (err)
+		return err;
+
+	branch[0].key = cpu_to_le32(new_blocks[0]);
+	/*
+	 * metadata blocks and data blocks are allocated.
+	 */
+	for (n = 1; n <= indirect_blks;  n++) {
+		/*
+		 * Get buffer_head for parent block, zero it out
+		 * and set the pointer to new one, then send
+		 * parent to disk.
+		 */
+		bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
+		branch[n].bh = bh;
+		lock_buffer(bh);
+		BUFFER_TRACE(bh, "call get_create_access");
+		err = ext4_journal_get_create_access(handle, bh);
+		if (err) {
+			unlock_buffer(bh);
+			brelse(bh);
+			goto failed;
+		}
+
+		memset(bh->b_data, 0, blocksize);
+		branch[n].p = (__le32 *) bh->b_data + offsets[n];
+		branch[n].key = cpu_to_le32(new_blocks[n]);
+		*branch[n].p = branch[n].key;
+		if ( n == indirect_blks) {
+			current_block = new_blocks[n];
+			/*
+			 * End of chain, update the last new metablock of
+			 * the chain to point to the new allocated
+			 * data blocks numbers
+			 */
+			for (i=1; i < num; i++)
+				*(branch[n].p + i) = cpu_to_le32(++current_block);
+		}
+		BUFFER_TRACE(bh, "marking uptodate");
+		set_buffer_uptodate(bh);
+		unlock_buffer(bh);
+
+		BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+		err = ext4_journal_dirty_metadata(handle, bh);
+		if (err)
+			goto failed;
+	}
+	*blks = num;
+	return err;
+failed:
+	/* Allocation failed, free what we already allocated */
+	for (i = 1; i <= n ; i++) {
+		BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
+		ext4_journal_forget(handle, branch[i].bh);
+	}
+	for (i = 0; i <indirect_blks; i++)
+		ext4_free_blocks(handle, inode, new_blocks[i], 1);
+
+	ext4_free_blocks(handle, inode, new_blocks[i], num);
+
+	return err;
+}
+
+/**
+ * ext4_splice_branch - splice the allocated branch onto inode.
+ * @inode: owner
+ * @block: (logical) number of block we are adding
+ * @chain: chain of indirect blocks (with a missing link - see
+ *	ext4_alloc_branch)
+ * @where: location of missing link
+ * @num:   number of indirect blocks we are adding
+ * @blks:  number of direct blocks we are adding
+ *
+ * This function fills the missing link and does all housekeeping needed in
+ * inode (->i_blocks, etc.). In case of success we end up with the full
+ * chain to new block and return 0.
+ */
+static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+			long block, Indirect *where, int num, int blks)
+{
+	int i;
+	int err = 0;
+	struct ext4_block_alloc_info *block_i;
+	ext4_fsblk_t current_block;
+
+	block_i = EXT4_I(inode)->i_block_alloc_info;
+	/*
+	 * If we're splicing into a [td]indirect block (as opposed to the
+	 * inode) then we need to get write access to the [td]indirect block
+	 * before the splice.
+	 */
+	if (where->bh) {
+		BUFFER_TRACE(where->bh, "get_write_access");
+		err = ext4_journal_get_write_access(handle, where->bh);
+		if (err)
+			goto err_out;
+	}
+	/* That's it */
+
+	*where->p = where->key;
+
+	/*
+	 * Update the host buffer_head or inode to point to more just allocated
+	 * direct blocks blocks
+	 */
+	if (num == 0 && blks > 1) {
+		current_block = le32_to_cpu(where->key) + 1;
+		for (i = 1; i < blks; i++)
+			*(where->p + i ) = cpu_to_le32(current_block++);
+	}
+
+	/*
+	 * update the most recently allocated logical & physical block
+	 * in i_block_alloc_info, to assist find the proper goal block for next
+	 * allocation
+	 */
+	if (block_i) {
+		block_i->last_alloc_logical_block = block + blks - 1;
+		block_i->last_alloc_physical_block =
+				le32_to_cpu(where[num].key) + blks - 1;
+	}
+
+	/* We are done with atomic stuff, now do the rest of housekeeping */
+
+	inode->i_ctime = CURRENT_TIME_SEC;
+	ext4_mark_inode_dirty(handle, inode);
+
+	/* had we spliced it onto indirect block? */
+	if (where->bh) {
+		/*
+		 * If we spliced it onto an indirect block, we haven't
+		 * altered the inode.  Note however that if it is being spliced
+		 * onto an indirect block at the very end of the file (the
+		 * file is growing) then we *will* alter the inode to reflect
+		 * the new i_size.  But that is not done here - it is done in
+		 * generic_commit_write->__mark_inode_dirty->ext4_dirty_inode.
+		 */
+		jbd_debug(5, "splicing indirect only\n");
+		BUFFER_TRACE(where->bh, "call ext4_journal_dirty_metadata");
+		err = ext4_journal_dirty_metadata(handle, where->bh);
+		if (err)
+			goto err_out;
+	} else {
+		/*
+		 * OK, we spliced it into the inode itself on a direct block.
+		 * Inode was dirtied above.
+		 */
+		jbd_debug(5, "splicing direct\n");
+	}
+	return err;
+
+err_out:
+	for (i = 1; i <= num; i++) {
+		BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget");
+		ext4_journal_forget(handle, where[i].bh);
+		ext4_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1);
+	}
+	ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks);
+
+	return err;
+}
+
+/*
+ * Allocation strategy is simple: if we have to allocate something, we will
+ * have to go the whole way to leaf. So let's do it before attaching anything
+ * to tree, set linkage between the newborn blocks, write them if sync is
+ * required, recheck the path, free and repeat if check fails, otherwise
+ * set the last missing link (that will protect us from any truncate-generated
+ * removals - all blocks on the path are immune now) and possibly force the
+ * write on the parent block.
+ * That has a nice additional property: no special recovery from the failed
+ * allocations is needed - we simply release blocks and do not touch anything
+ * reachable from inode.
+ *
+ * `handle' can be NULL if create == 0.
+ *
+ * The BKL may not be held on entry here.  Be sure to take it early.
+ * return > 0, # of blocks mapped or allocated.
+ * return = 0, if plain lookup failed.
+ * return < 0, error case.
+ */
+int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+		sector_t iblock, unsigned long maxblocks,
+		struct buffer_head *bh_result,
+		int create, int extend_disksize)
+{
+	int err = -EIO;
+	int offsets[4];
+	Indirect chain[4];
+	Indirect *partial;
+	ext4_fsblk_t goal;
+	int indirect_blks;
+	int blocks_to_boundary = 0;
+	int depth;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	int count = 0;
+	ext4_fsblk_t first_block = 0;
+
+
+	J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
+	J_ASSERT(handle != NULL || create == 0);
+	depth = ext4_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
+
+	if (depth == 0)
+		goto out;
+
+	partial = ext4_get_branch(inode, depth, offsets, chain, &err);
+
+	/* Simplest case - block found, no allocation needed */
+	if (!partial) {
+		first_block = le32_to_cpu(chain[depth - 1].key);
+		clear_buffer_new(bh_result);
+		count++;
+		/*map more blocks*/
+		while (count < maxblocks && count <= blocks_to_boundary) {
+			ext4_fsblk_t blk;
+
+			if (!verify_chain(chain, partial)) {
+				/*
+				 * Indirect block might be removed by
+				 * truncate while we were reading it.
+				 * Handling of that case: forget what we've
+				 * got now. Flag the err as EAGAIN, so it
+				 * will reread.
+				 */
+				err = -EAGAIN;
+				count = 0;
+				break;
+			}
+			blk = le32_to_cpu(*(chain[depth-1].p + count));
+
+			if (blk == first_block + count)
+				count++;
+			else
+				break;
+		}
+		if (err != -EAGAIN)
+			goto got_it;
+	}
+
+	/* Next simple case - plain lookup or failed read of indirect block */
+	if (!create || err == -EIO)
+		goto cleanup;
+
+	mutex_lock(&ei->truncate_mutex);
+
+	/*
+	 * If the indirect block is missing while we are reading
+	 * the chain(ext4_get_branch() returns -EAGAIN err), or
+	 * if the chain has been changed after we grab the semaphore,
+	 * (either because another process truncated this branch, or
+	 * another get_block allocated this branch) re-grab the chain to see if
+	 * the request block has been allocated or not.
+	 *
+	 * Since we already block the truncate/other get_block
+	 * at this point, we will have the current copy of the chain when we
+	 * splice the branch into the tree.
+	 */
+	if (err == -EAGAIN || !verify_chain(chain, partial)) {
+		while (partial > chain) {
+			brelse(partial->bh);
+			partial--;
+		}
+		partial = ext4_get_branch(inode, depth, offsets, chain, &err);
+		if (!partial) {
+			count++;
+			mutex_unlock(&ei->truncate_mutex);
+			if (err)
+				goto cleanup;
+			clear_buffer_new(bh_result);
+			goto got_it;
+		}
+	}
+
+	/*
+	 * Okay, we need to do block allocation.  Lazily initialize the block
+	 * allocation info here if necessary
+	*/
+	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
+		ext4_init_block_alloc_info(inode);
+
+	goal = ext4_find_goal(inode, iblock, chain, partial);
+
+	/* the number of blocks need to allocate for [d,t]indirect blocks */
+	indirect_blks = (chain + depth) - partial - 1;
+
+	/*
+	 * Next look up the indirect map to count the totoal number of
+	 * direct blocks to allocate for this branch.
+	 */
+	count = ext4_blks_to_allocate(partial, indirect_blks,
+					maxblocks, blocks_to_boundary);
+	/*
+	 * Block out ext4_truncate while we alter the tree
+	 */
+	err = ext4_alloc_branch(handle, inode, indirect_blks, &count, goal,
+				offsets + (partial - chain), partial);
+
+	/*
+	 * The ext4_splice_branch call will free and forget any buffers
+	 * on the new chain if there is a failure, but that risks using
+	 * up transaction credits, especially for bitmaps where the
+	 * credits cannot be returned.  Can we handle this somehow?  We
+	 * may need to return -EAGAIN upwards in the worst case.  --sct
+	 */
+	if (!err)
+		err = ext4_splice_branch(handle, inode, iblock,
+					partial, indirect_blks, count);
+	/*
+	 * i_disksize growing is protected by truncate_mutex.  Don't forget to
+	 * protect it if you're about to implement concurrent
+	 * ext4_get_block() -bzzz
+	*/
+	if (!err && extend_disksize && inode->i_size > ei->i_disksize)
+		ei->i_disksize = inode->i_size;
+	mutex_unlock(&ei->truncate_mutex);
+	if (err)
+		goto cleanup;
+
+	set_buffer_new(bh_result);
+got_it:
+	map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
+	if (count > blocks_to_boundary)
+		set_buffer_boundary(bh_result);
+	err = count;
+	/* Clean up and exit */
+	partial = chain + depth - 1;	/* the whole chain */
+cleanup:
+	while (partial > chain) {
+		BUFFER_TRACE(partial->bh, "call brelse");
+		brelse(partial->bh);
+		partial--;
+	}
+	BUFFER_TRACE(bh_result, "returned");
+out:
+	return err;
+}
+
+#define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32)
+
+static int ext4_get_block(struct inode *inode, sector_t iblock,
+			struct buffer_head *bh_result, int create)
+{
+	handle_t *handle = journal_current_handle();
+	int ret = 0;
+	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+
+	if (!create)
+		goto get_block;		/* A read */
+
+	if (max_blocks == 1)
+		goto get_block;		/* A single block get */
+
+	if (handle->h_transaction->t_state == T_LOCKED) {
+		/*
+		 * Huge direct-io writes can hold off commits for long
+		 * periods of time.  Let this commit run.
+		 */
+		ext4_journal_stop(handle);
+		handle = ext4_journal_start(inode, DIO_CREDITS);
+		if (IS_ERR(handle))
+			ret = PTR_ERR(handle);
+		goto get_block;
+	}
+
+	if (handle->h_buffer_credits <= EXT4_RESERVE_TRANS_BLOCKS) {
+		/*
+		 * Getting low on buffer credits...
+		 */
+		ret = ext4_journal_extend(handle, DIO_CREDITS);
+		if (ret > 0) {
+			/*
+			 * Couldn't extend the transaction.  Start a new one.
+			 */
+			ret = ext4_journal_restart(handle, DIO_CREDITS);
+		}
+	}
+
+get_block:
+	if (ret == 0) {
+		ret = ext4_get_blocks_wrap(handle, inode, iblock,
+					max_blocks, bh_result, create, 0);
+		if (ret > 0) {
+			bh_result->b_size = (ret << inode->i_blkbits);
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
+/*
+ * `handle' can be NULL if create is zero
+ */
+struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+				long block, int create, int *errp)
+{
+	struct buffer_head dummy;
+	int fatal = 0, err;
+
+	J_ASSERT(handle != NULL || create == 0);
+
+	dummy.b_state = 0;
+	dummy.b_blocknr = -1000;
+	buffer_trace_init(&dummy.b_history);
+	err = ext4_get_blocks_wrap(handle, inode, block, 1,
+					&dummy, create, 1);
+	/*
+	 * ext4_get_blocks_handle() returns number of blocks
+	 * mapped. 0 in case of a HOLE.
+	 */
+	if (err > 0) {
+		if (err > 1)
+			WARN_ON(1);
+		err = 0;
+	}
+	*errp = err;
+	if (!err && buffer_mapped(&dummy)) {
+		struct buffer_head *bh;
+		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
+		if (!bh) {
+			*errp = -EIO;
+			goto err;
+		}
+		if (buffer_new(&dummy)) {
+			J_ASSERT(create != 0);
+			J_ASSERT(handle != 0);
+
+			/*
+			 * Now that we do not always journal data, we should
+			 * keep in mind whether this should always journal the
+			 * new buffer as metadata.  For now, regular file
+			 * writes use ext4_get_block instead, so it's not a
+			 * problem.
+			 */
+			lock_buffer(bh);
+			BUFFER_TRACE(bh, "call get_create_access");
+			fatal = ext4_journal_get_create_access(handle, bh);
+			if (!fatal && !buffer_uptodate(bh)) {
+				memset(bh->b_data,0,inode->i_sb->s_blocksize);
+				set_buffer_uptodate(bh);
+			}
+			unlock_buffer(bh);
+			BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+			err = ext4_journal_dirty_metadata(handle, bh);
+			if (!fatal)
+				fatal = err;
+		} else {
+			BUFFER_TRACE(bh, "not a new buffer");
+		}
+		if (fatal) {
+			*errp = fatal;
+			brelse(bh);
+			bh = NULL;
+		}
+		return bh;
+	}
+err:
+	return NULL;
+}
+
+struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+			       int block, int create, int *err)
+{
+	struct buffer_head * bh;
+
+	bh = ext4_getblk(handle, inode, block, create, err);
+	if (!bh)
+		return bh;
+	if (buffer_uptodate(bh))
+		return bh;
+	ll_rw_block(READ_META, 1, &bh);
+	wait_on_buffer(bh);
+	if (buffer_uptodate(bh))
+		return bh;
+	put_bh(bh);
+	*err = -EIO;
+	return NULL;
+}
+
+static int walk_page_buffers(	handle_t *handle,
+				struct buffer_head *head,
+				unsigned from,
+				unsigned to,
+				int *partial,
+				int (*fn)(	handle_t *handle,
+						struct buffer_head *bh))
+{
+	struct buffer_head *bh;
+	unsigned block_start, block_end;
+	unsigned blocksize = head->b_size;
+	int err, ret = 0;
+	struct buffer_head *next;
+
+	for (	bh = head, block_start = 0;
+		ret == 0 && (bh != head || !block_start);
+		block_start = block_end, bh = next)
+	{
+		next = bh->b_this_page;
+		block_end = block_start + blocksize;
+		if (block_end <= from || block_start >= to) {
+			if (partial && !buffer_uptodate(bh))
+				*partial = 1;
+			continue;
+		}
+		err = (*fn)(handle, bh);
+		if (!ret)
+			ret = err;
+	}
+	return ret;
+}
+
+/*
+ * To preserve ordering, it is essential that the hole instantiation and
+ * the data write be encapsulated in a single transaction.  We cannot
+ * close off a transaction and start a new one between the ext4_get_block()
+ * and the commit_write().  So doing the jbd2_journal_start at the start of
+ * prepare_write() is the right place.
+ *
+ * Also, this function can nest inside ext4_writepage() ->
+ * block_write_full_page(). In that case, we *know* that ext4_writepage()
+ * has generated enough buffer credits to do the whole page.  So we won't
+ * block on the journal in that case, which is good, because the caller may
+ * be PF_MEMALLOC.
+ *
+ * By accident, ext4 can be reentered when a transaction is open via
+ * quota file writes.  If we were to commit the transaction while thus
+ * reentered, there can be a deadlock - we would be holding a quota
+ * lock, and the commit would never complete if another thread had a
+ * transaction open and was blocking on the quota lock - a ranking
+ * violation.
+ *
+ * So what we do is to rely on the fact that jbd2_journal_stop/journal_start
+ * will _not_ run commit under these circumstances because handle->h_ref
+ * is elevated.  We'll still have enough credits for the tiny quotafile
+ * write.
+ */
+static int do_journal_get_write_access(handle_t *handle,
+					struct buffer_head *bh)
+{
+	if (!buffer_mapped(bh) || buffer_freed(bh))
+		return 0;
+	return ext4_journal_get_write_access(handle, bh);
+}
+
+static int ext4_prepare_write(struct file *file, struct page *page,
+			      unsigned from, unsigned to)
+{
+	struct inode *inode = page->mapping->host;
+	int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
+	handle_t *handle;
+	int retries = 0;
+
+retry:
+	handle = ext4_journal_start(inode, needed_blocks);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto out;
+	}
+	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+		ret = nobh_prepare_write(page, from, to, ext4_get_block);
+	else
+		ret = block_prepare_write(page, from, to, ext4_get_block);
+	if (ret)
+		goto prepare_write_failed;
+
+	if (ext4_should_journal_data(inode)) {
+		ret = walk_page_buffers(handle, page_buffers(page),
+				from, to, NULL, do_journal_get_write_access);
+	}
+prepare_write_failed:
+	if (ret)
+		ext4_journal_stop(handle);
+	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+		goto retry;
+out:
+	return ret;
+}
+
+int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
+{
+	int err = jbd2_journal_dirty_data(handle, bh);
+	if (err)
+		ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
+						bh, handle,err);
+	return err;
+}
+
+/* For commit_write() in data=journal mode */
+static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
+{
+	if (!buffer_mapped(bh) || buffer_freed(bh))
+		return 0;
+	set_buffer_uptodate(bh);
+	return ext4_journal_dirty_metadata(handle, bh);
+}
+
+/*
+ * We need to pick up the new inode size which generic_commit_write gave us
+ * `file' can be NULL - eg, when called from page_symlink().
+ *
+ * ext4 never places buffers on inode->i_mapping->private_list.  metadata
+ * buffers are managed internally.
+ */
+static int ext4_ordered_commit_write(struct file *file, struct page *page,
+			     unsigned from, unsigned to)
+{
+	handle_t *handle = ext4_journal_current_handle();
+	struct inode *inode = page->mapping->host;
+	int ret = 0, ret2;
+
+	ret = walk_page_buffers(handle, page_buffers(page),
+		from, to, NULL, ext4_journal_dirty_data);
+
+	if (ret == 0) {
+		/*
+		 * generic_commit_write() will run mark_inode_dirty() if i_size
+		 * changes.  So let's piggyback the i_disksize mark_inode_dirty
+		 * into that.
+		 */
+		loff_t new_i_size;
+
+		new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+		if (new_i_size > EXT4_I(inode)->i_disksize)
+			EXT4_I(inode)->i_disksize = new_i_size;
+		ret = generic_commit_write(file, page, from, to);
+	}
+	ret2 = ext4_journal_stop(handle);
+	if (!ret)
+		ret = ret2;
+	return ret;
+}
+
+static int ext4_writeback_commit_write(struct file *file, struct page *page,
+			     unsigned from, unsigned to)
+{
+	handle_t *handle = ext4_journal_current_handle();
+	struct inode *inode = page->mapping->host;
+	int ret = 0, ret2;
+	loff_t new_i_size;
+
+	new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+	if (new_i_size > EXT4_I(inode)->i_disksize)
+		EXT4_I(inode)->i_disksize = new_i_size;
+
+	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+		ret = nobh_commit_write(file, page, from, to);
+	else
+		ret = generic_commit_write(file, page, from, to);
+
+	ret2 = ext4_journal_stop(handle);
+	if (!ret)
+		ret = ret2;
+	return ret;
+}
+
+static int ext4_journalled_commit_write(struct file *file,
+			struct page *page, unsigned from, unsigned to)
+{
+	handle_t *handle = ext4_journal_current_handle();
+	struct inode *inode = page->mapping->host;
+	int ret = 0, ret2;
+	int partial = 0;
+	loff_t pos;
+
+	/*
+	 * Here we duplicate the generic_commit_write() functionality
+	 */
+	pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+
+	ret = walk_page_buffers(handle, page_buffers(page), from,
+				to, &partial, commit_write_fn);
+	if (!partial)
+		SetPageUptodate(page);
+	if (pos > inode->i_size)
+		i_size_write(inode, pos);
+	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+	if (inode->i_size > EXT4_I(inode)->i_disksize) {
+		EXT4_I(inode)->i_disksize = inode->i_size;
+		ret2 = ext4_mark_inode_dirty(handle, inode);
+		if (!ret)
+			ret = ret2;
+	}
+	ret2 = ext4_journal_stop(handle);
+	if (!ret)
+		ret = ret2;
+	return ret;
+}
+
+/*
+ * bmap() is special.  It gets used by applications such as lilo and by
+ * the swapper to find the on-disk block of a specific piece of data.
+ *
+ * Naturally, this is dangerous if the block concerned is still in the
+ * journal.  If somebody makes a swapfile on an ext4 data-journaling
+ * filesystem and enables swap, then they may get a nasty shock when the
+ * data getting swapped to that swapfile suddenly gets overwritten by
+ * the original zero's written out previously to the journal and
+ * awaiting writeback in the kernel's buffer cache.
+ *
+ * So, if we see any bmap calls here on a modified, data-journaled file,
+ * take extra steps to flush any blocks which might be in the cache.
+ */
+static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+{
+	struct inode *inode = mapping->host;
+	journal_t *journal;
+	int err;
+
+	if (EXT4_I(inode)->i_state & EXT4_STATE_JDATA) {
+		/*
+		 * This is a REALLY heavyweight approach, but the use of
+		 * bmap on dirty files is expected to be extremely rare:
+		 * only if we run lilo or swapon on a freshly made file
+		 * do we expect this to happen.
+		 *
+		 * (bmap requires CAP_SYS_RAWIO so this does not
+		 * represent an unprivileged user DOS attack --- we'd be
+		 * in trouble if mortal users could trigger this path at
+		 * will.)
+		 *
+		 * NB. EXT4_STATE_JDATA is not set on files other than
+		 * regular files.  If somebody wants to bmap a directory
+		 * or symlink and gets confused because the buffer
+		 * hasn't yet been flushed to disk, they deserve
+		 * everything they get.
+		 */
+
+		EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA;
+		journal = EXT4_JOURNAL(inode);
+		jbd2_journal_lock_updates(journal);
+		err = jbd2_journal_flush(journal);
+		jbd2_journal_unlock_updates(journal);
+
+		if (err)
+			return 0;
+	}
+
+	return generic_block_bmap(mapping,block,ext4_get_block);
+}
+
+static int bget_one(handle_t *handle, struct buffer_head *bh)
+{
+	get_bh(bh);
+	return 0;
+}
+
+static int bput_one(handle_t *handle, struct buffer_head *bh)
+{
+	put_bh(bh);
+	return 0;
+}
+
+static int jbd2_journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
+{
+	if (buffer_mapped(bh))
+		return ext4_journal_dirty_data(handle, bh);
+	return 0;
+}
+
+/*
+ * Note that we always start a transaction even if we're not journalling
+ * data.  This is to preserve ordering: any hole instantiation within
+ * __block_write_full_page -> ext4_get_block() should be journalled
+ * along with the data so we don't crash and then get metadata which
+ * refers to old data.
+ *
+ * In all journalling modes block_write_full_page() will start the I/O.
+ *
+ * Problem:
+ *
+ *	ext4_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() ->
+ *		ext4_writepage()
+ *
+ * Similar for:
+ *
+ *	ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ...
+ *
+ * Same applies to ext4_get_block().  We will deadlock on various things like
+ * lock_journal and i_truncate_mutex.
+ *
+ * Setting PF_MEMALLOC here doesn't work - too many internal memory
+ * allocations fail.
+ *
+ * 16May01: If we're reentered then journal_current_handle() will be
+ *	    non-zero. We simply *return*.
+ *
+ * 1 July 2001: @@@ FIXME:
+ *   In journalled data mode, a data buffer may be metadata against the
+ *   current transaction.  But the same file is part of a shared mapping
+ *   and someone does a writepage() on it.
+ *
+ *   We will move the buffer onto the async_data list, but *after* it has
+ *   been dirtied. So there's a small window where we have dirty data on
+ *   BJ_Metadata.
+ *
+ *   Note that this only applies to the last partial page in the file.  The
+ *   bit which block_write_full_page() uses prepare/commit for.  (That's
+ *   broken code anyway: it's wrong for msync()).
+ *
+ *   It's a rare case: affects the final partial page, for journalled data
+ *   where the file is subject to bith write() and writepage() in the same
+ *   transction.  To fix it we'll need a custom block_write_full_page().
+ *   We'll probably need that anyway for journalling writepage() output.
+ *
+ * We don't honour synchronous mounts for writepage().  That would be
+ * disastrous.  Any write() or metadata operation will sync the fs for
+ * us.
+ *
+ * AKPM2: if all the page's buffers are mapped to disk and !data=journal,
+ * we don't need to open a transaction here.
+ */
+static int ext4_ordered_writepage(struct page *page,
+				struct writeback_control *wbc)
+{
+	struct inode *inode = page->mapping->host;
+	struct buffer_head *page_bufs;
+	handle_t *handle = NULL;
+	int ret = 0;
+	int err;
+
+	J_ASSERT(PageLocked(page));
+
+	/*
+	 * We give up here if we're reentered, because it might be for a
+	 * different filesystem.
+	 */
+	if (ext4_journal_current_handle())
+		goto out_fail;
+
+	handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
+
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto out_fail;
+	}
+
+	if (!page_has_buffers(page)) {
+		create_empty_buffers(page, inode->i_sb->s_blocksize,
+				(1 << BH_Dirty)|(1 << BH_Uptodate));
+	}
+	page_bufs = page_buffers(page);
+	walk_page_buffers(handle, page_bufs, 0,
+			PAGE_CACHE_SIZE, NULL, bget_one);
+
+	ret = block_write_full_page(page, ext4_get_block, wbc);
+
+	/*
+	 * The page can become unlocked at any point now, and
+	 * truncate can then come in and change things.  So we
+	 * can't touch *page from now on.  But *page_bufs is
+	 * safe due to elevated refcount.
+	 */
+
+	/*
+	 * And attach them to the current transaction.  But only if
+	 * block_write_full_page() succeeded.  Otherwise they are unmapped,
+	 * and generally junk.
+	 */
+	if (ret == 0) {
+		err = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE,
+					NULL, jbd2_journal_dirty_data_fn);
+		if (!ret)
+			ret = err;
+	}
+	walk_page_buffers(handle, page_bufs, 0,
+			PAGE_CACHE_SIZE, NULL, bput_one);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+
+out_fail:
+	redirty_page_for_writepage(wbc, page);
+	unlock_page(page);
+	return ret;
+}
+
+static int ext4_writeback_writepage(struct page *page,
+				struct writeback_control *wbc)
+{
+	struct inode *inode = page->mapping->host;
+	handle_t *handle = NULL;
+	int ret = 0;
+	int err;
+
+	if (ext4_journal_current_handle())
+		goto out_fail;
+
+	handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto out_fail;
+	}
+
+	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+		ret = nobh_writepage(page, ext4_get_block, wbc);
+	else
+		ret = block_write_full_page(page, ext4_get_block, wbc);
+
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+
+out_fail:
+	redirty_page_for_writepage(wbc, page);
+	unlock_page(page);
+	return ret;
+}
+
+static int ext4_journalled_writepage(struct page *page,
+				struct writeback_control *wbc)
+{
+	struct inode *inode = page->mapping->host;
+	handle_t *handle = NULL;
+	int ret = 0;
+	int err;
+
+	if (ext4_journal_current_handle())
+		goto no_write;
+
+	handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto no_write;
+	}
+
+	if (!page_has_buffers(page) || PageChecked(page)) {
+		/*
+		 * It's mmapped pagecache.  Add buffers and journal it.  There
+		 * doesn't seem much point in redirtying the page here.
+		 */
+		ClearPageChecked(page);
+		ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
+					ext4_get_block);
+		if (ret != 0) {
+			ext4_journal_stop(handle);
+			goto out_unlock;
+		}
+		ret = walk_page_buffers(handle, page_buffers(page), 0,
+			PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
+
+		err = walk_page_buffers(handle, page_buffers(page), 0,
+				PAGE_CACHE_SIZE, NULL, commit_write_fn);
+		if (ret == 0)
+			ret = err;
+		EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+		unlock_page(page);
+	} else {
+		/*
+		 * It may be a page full of checkpoint-mode buffers.  We don't
+		 * really know unless we go poke around in the buffer_heads.
+		 * But block_write_full_page will do the right thing.
+		 */
+		ret = block_write_full_page(page, ext4_get_block, wbc);
+	}
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+out:
+	return ret;
+
+no_write:
+	redirty_page_for_writepage(wbc, page);
+out_unlock:
+	unlock_page(page);
+	goto out;
+}
+
+static int ext4_readpage(struct file *file, struct page *page)
+{
+	return mpage_readpage(page, ext4_get_block);
+}
+
+static int
+ext4_readpages(struct file *file, struct address_space *mapping,
+		struct list_head *pages, unsigned nr_pages)
+{
+	return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
+}
+
+static void ext4_invalidatepage(struct page *page, unsigned long offset)
+{
+	journal_t *journal = EXT4_JOURNAL(page->mapping->host);
+
+	/*
+	 * If it's a full truncate we just forget about the pending dirtying
+	 */
+	if (offset == 0)
+		ClearPageChecked(page);
+
+	jbd2_journal_invalidatepage(journal, page, offset);
+}
+
+static int ext4_releasepage(struct page *page, gfp_t wait)
+{
+	journal_t *journal = EXT4_JOURNAL(page->mapping->host);
+
+	WARN_ON(PageChecked(page));
+	if (!page_has_buffers(page))
+		return 0;
+	return jbd2_journal_try_to_free_buffers(journal, page, wait);
+}
+
+/*
+ * If the O_DIRECT write will extend the file then add this inode to the
+ * orphan list.  So recovery will truncate it back to the original size
+ * if the machine crashes during the write.
+ *
+ * If the O_DIRECT write is intantiating holes inside i_size and the machine
+ * crashes then stale disk data _may_ be exposed inside the file.
+ */
+static ssize_t ext4_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;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	handle_t *handle = NULL;
+	ssize_t ret;
+	int orphan = 0;
+	size_t count = iov_length(iov, nr_segs);
+
+	if (rw == WRITE) {
+		loff_t final_size = offset + count;
+
+		handle = ext4_journal_start(inode, DIO_CREDITS);
+		if (IS_ERR(handle)) {
+			ret = PTR_ERR(handle);
+			goto out;
+		}
+		if (final_size > inode->i_size) {
+			ret = ext4_orphan_add(handle, inode);
+			if (ret)
+				goto out_stop;
+			orphan = 1;
+			ei->i_disksize = inode->i_size;
+		}
+	}
+
+	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+				 offset, nr_segs,
+				 ext4_get_block, NULL);
+
+	/*
+	 * Reacquire the handle: ext4_get_block() can restart the transaction
+	 */
+	handle = journal_current_handle();
+
+out_stop:
+	if (handle) {
+		int err;
+
+		if (orphan && inode->i_nlink)
+			ext4_orphan_del(handle, inode);
+		if (orphan && ret > 0) {
+			loff_t end = offset + ret;
+			if (end > inode->i_size) {
+				ei->i_disksize = end;
+				i_size_write(inode, end);
+				/*
+				 * We're going to return a positive `ret'
+				 * here due to non-zero-length I/O, so there's
+				 * no way of reporting error returns from
+				 * ext4_mark_inode_dirty() to userspace.  So
+				 * ignore it.
+				 */
+				ext4_mark_inode_dirty(handle, inode);
+			}
+		}
+		err = ext4_journal_stop(handle);
+		if (ret == 0)
+			ret = err;
+	}
+out:
+	return ret;
+}
+
+/*
+ * Pages can be marked dirty completely asynchronously from ext4's journalling
+ * activity.  By filemap_sync_pte(), try_to_unmap_one(), etc.  We cannot do
+ * much here because ->set_page_dirty is called under VFS locks.  The page is
+ * not necessarily locked.
+ *
+ * We cannot just dirty the page and leave attached buffers clean, because the
+ * buffers' dirty state is "definitive".  We cannot just set the buffers dirty
+ * or jbddirty because all the journalling code will explode.
+ *
+ * So what we do is to mark the page "pending dirty" and next time writepage
+ * is called, propagate that into the buffers appropriately.
+ */
+static int ext4_journalled_set_page_dirty(struct page *page)
+{
+	SetPageChecked(page);
+	return __set_page_dirty_nobuffers(page);
+}
+
+static const struct address_space_operations ext4_ordered_aops = {
+	.readpage	= ext4_readpage,
+	.readpages	= ext4_readpages,
+	.writepage	= ext4_ordered_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= ext4_prepare_write,
+	.commit_write	= ext4_ordered_commit_write,
+	.bmap		= ext4_bmap,
+	.invalidatepage	= ext4_invalidatepage,
+	.releasepage	= ext4_releasepage,
+	.direct_IO	= ext4_direct_IO,
+	.migratepage	= buffer_migrate_page,
+};
+
+static const struct address_space_operations ext4_writeback_aops = {
+	.readpage	= ext4_readpage,
+	.readpages	= ext4_readpages,
+	.writepage	= ext4_writeback_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= ext4_prepare_write,
+	.commit_write	= ext4_writeback_commit_write,
+	.bmap		= ext4_bmap,
+	.invalidatepage	= ext4_invalidatepage,
+	.releasepage	= ext4_releasepage,
+	.direct_IO	= ext4_direct_IO,
+	.migratepage	= buffer_migrate_page,
+};
+
+static const struct address_space_operations ext4_journalled_aops = {
+	.readpage	= ext4_readpage,
+	.readpages	= ext4_readpages,
+	.writepage	= ext4_journalled_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= ext4_prepare_write,
+	.commit_write	= ext4_journalled_commit_write,
+	.set_page_dirty	= ext4_journalled_set_page_dirty,
+	.bmap		= ext4_bmap,
+	.invalidatepage	= ext4_invalidatepage,
+	.releasepage	= ext4_releasepage,
+};
+
+void ext4_set_aops(struct inode *inode)
+{
+	if (ext4_should_order_data(inode))
+		inode->i_mapping->a_ops = &ext4_ordered_aops;
+	else if (ext4_should_writeback_data(inode))
+		inode->i_mapping->a_ops = &ext4_writeback_aops;
+	else
+		inode->i_mapping->a_ops = &ext4_journalled_aops;
+}
+
+/*
+ * ext4_block_truncate_page() zeroes out a mapping from file offset `from'
+ * up to the end of the block which corresponds to `from'.
+ * This required during truncate. We need to physically zero the tail end
+ * of that block so it doesn't yield old data if the file is later grown.
+ */
+int ext4_block_truncate_page(handle_t *handle, struct page *page,
+		struct address_space *mapping, loff_t from)
+{
+	ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT;
+	unsigned offset = from & (PAGE_CACHE_SIZE-1);
+	unsigned blocksize, iblock, length, pos;
+	struct inode *inode = mapping->host;
+	struct buffer_head *bh;
+	int err = 0;
+	void *kaddr;
+
+	blocksize = inode->i_sb->s_blocksize;
+	length = blocksize - (offset & (blocksize - 1));
+	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+
+	/*
+	 * For "nobh" option,  we can only work if we don't need to
+	 * read-in the page - otherwise we create buffers to do the IO.
+	 */
+	if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
+	     ext4_should_writeback_data(inode) && PageUptodate(page)) {
+		kaddr = kmap_atomic(page, KM_USER0);
+		memset(kaddr + offset, 0, length);
+		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
+		set_page_dirty(page);
+		goto unlock;
+	}
+
+	if (!page_has_buffers(page))
+		create_empty_buffers(page, blocksize, 0);
+
+	/* Find the buffer that contains "offset" */
+	bh = page_buffers(page);
+	pos = blocksize;
+	while (offset >= pos) {
+		bh = bh->b_this_page;
+		iblock++;
+		pos += blocksize;
+	}
+
+	err = 0;
+	if (buffer_freed(bh)) {
+		BUFFER_TRACE(bh, "freed: skip");
+		goto unlock;
+	}
+
+	if (!buffer_mapped(bh)) {
+		BUFFER_TRACE(bh, "unmapped");
+		ext4_get_block(inode, iblock, bh, 0);
+		/* unmapped? It's a hole - nothing to do */
+		if (!buffer_mapped(bh)) {
+			BUFFER_TRACE(bh, "still unmapped");
+			goto unlock;
+		}
+	}
+
+	/* Ok, it's mapped. Make sure it's up-to-date */
+	if (PageUptodate(page))
+		set_buffer_uptodate(bh);
+
+	if (!buffer_uptodate(bh)) {
+		err = -EIO;
+		ll_rw_block(READ, 1, &bh);
+		wait_on_buffer(bh);
+		/* Uhhuh. Read error. Complain and punt. */
+		if (!buffer_uptodate(bh))
+			goto unlock;
+	}
+
+	if (ext4_should_journal_data(inode)) {
+		BUFFER_TRACE(bh, "get write access");
+		err = ext4_journal_get_write_access(handle, bh);
+		if (err)
+			goto unlock;
+	}
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + offset, 0, length);
+	flush_dcache_page(page);
+	kunmap_atomic(kaddr, KM_USER0);
+
+	BUFFER_TRACE(bh, "zeroed end of block");
+
+	err = 0;
+	if (ext4_should_journal_data(inode)) {
+		err = ext4_journal_dirty_metadata(handle, bh);
+	} else {
+		if (ext4_should_order_data(inode))
+			err = ext4_journal_dirty_data(handle, bh);
+		mark_buffer_dirty(bh);
+	}
+
+unlock:
+	unlock_page(page);
+	page_cache_release(page);
+	return err;
+}
+
+/*
+ * Probably it should be a library function... search for first non-zero word
+ * or memcmp with zero_page, whatever is better for particular architecture.
+ * Linus?
+ */
+static inline int all_zeroes(__le32 *p, __le32 *q)
+{
+	while (p < q)
+		if (*p++)
+			return 0;
+	return 1;
+}
+
+/**
+ *	ext4_find_shared - find the indirect blocks for partial truncation.
+ *	@inode:	  inode in question
+ *	@depth:	  depth of the affected branch
+ *	@offsets: offsets of pointers in that branch (see ext4_block_to_path)
+ *	@chain:	  place to store the pointers to partial indirect blocks
+ *	@top:	  place to the (detached) top of branch
+ *
+ *	This is a helper function used by ext4_truncate().
+ *
+ *	When we do truncate() we may have to clean the ends of several
+ *	indirect blocks but leave the blocks themselves alive. Block is
+ *	partially truncated if some data below the new i_size is refered
+ *	from it (and it is on the path to the first completely truncated
+ *	data block, indeed).  We have to free the top of that path along
+ *	with everything to the right of the path. Since no allocation
+ *	past the truncation point is possible until ext4_truncate()
+ *	finishes, we may safely do the latter, but top of branch may
+ *	require special attention - pageout below the truncation point
+ *	might try to populate it.
+ *
+ *	We atomically detach the top of branch from the tree, store the
+ *	block number of its root in *@top, pointers to buffer_heads of
+ *	partially truncated blocks - in @chain[].bh and pointers to
+ *	their last elements that should not be removed - in
+ *	@chain[].p. Return value is the pointer to last filled element
+ *	of @chain.
+ *
+ *	The work left to caller to do the actual freeing of subtrees:
+ *		a) free the subtree starting from *@top
+ *		b) free the subtrees whose roots are stored in
+ *			(@chain[i].p+1 .. end of @chain[i].bh->b_data)
+ *		c) free the subtrees growing from the inode past the @chain[0].
+ *			(no partially truncated stuff there).  */
+
+static Indirect *ext4_find_shared(struct inode *inode, int depth,
+			int offsets[4], Indirect chain[4], __le32 *top)
+{
+	Indirect *partial, *p;
+	int k, err;
+
+	*top = 0;
+	/* Make k index the deepest non-null offest + 1 */
+	for (k = depth; k > 1 && !offsets[k-1]; k--)
+		;
+	partial = ext4_get_branch(inode, k, offsets, chain, &err);
+	/* Writer: pointers */
+	if (!partial)
+		partial = chain + k-1;
+	/*
+	 * If the branch acquired continuation since we've looked at it -
+	 * fine, it should all survive and (new) top doesn't belong to us.
+	 */
+	if (!partial->key && *partial->p)
+		/* Writer: end */
+		goto no_top;
+	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
+		;
+	/*
+	 * OK, we've found the last block that must survive. The rest of our
+	 * branch should be detached before unlocking. However, if that rest
+	 * of branch is all ours and does not grow immediately from the inode
+	 * it's easier to cheat and just decrement partial->p.
+	 */
+	if (p == chain + k - 1 && p > chain) {
+		p->p--;
+	} else {
+		*top = *p->p;
+		/* Nope, don't do this in ext4.  Must leave the tree intact */
+#if 0
+		*p->p = 0;
+#endif
+	}
+	/* Writer: end */
+
+	while(partial > p) {
+		brelse(partial->bh);
+		partial--;
+	}
+no_top:
+	return partial;
+}
+
+/*
+ * Zero a number of block pointers in either an inode or an indirect block.
+ * If we restart the transaction we must again get write access to the
+ * indirect block for further modification.
+ *
+ * We release `count' blocks on disk, but (last - first) may be greater
+ * than `count' because there can be holes in there.
+ */
+static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+		struct buffer_head *bh, ext4_fsblk_t block_to_free,
+		unsigned long count, __le32 *first, __le32 *last)
+{
+	__le32 *p;
+	if (try_to_extend_transaction(handle, inode)) {
+		if (bh) {
+			BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+			ext4_journal_dirty_metadata(handle, bh);
+		}
+		ext4_mark_inode_dirty(handle, inode);
+		ext4_journal_test_restart(handle, inode);
+		if (bh) {
+			BUFFER_TRACE(bh, "retaking write access");
+			ext4_journal_get_write_access(handle, bh);
+		}
+	}
+
+	/*
+	 * Any buffers which are on the journal will be in memory. We find
+	 * them on the hash table so jbd2_journal_revoke() will run jbd2_journal_forget()
+	 * on them.  We've already detached each block from the file, so
+	 * bforget() in jbd2_journal_forget() should be safe.
+	 *
+	 * AKPM: turn on bforget in jbd2_journal_forget()!!!
+	 */
+	for (p = first; p < last; p++) {
+		u32 nr = le32_to_cpu(*p);
+		if (nr) {
+			struct buffer_head *bh;
+
+			*p = 0;
+			bh = sb_find_get_block(inode->i_sb, nr);
+			ext4_forget(handle, 0, inode, bh, nr);
+		}
+	}
+
+	ext4_free_blocks(handle, inode, block_to_free, count);
+}
+
+/**
+ * ext4_free_data - free a list of data blocks
+ * @handle:	handle for this transaction
+ * @inode:	inode we are dealing with
+ * @this_bh:	indirect buffer_head which contains *@first and *@last
+ * @first:	array of block numbers
+ * @last:	points immediately past the end of array
+ *
+ * We are freeing all blocks refered from that array (numbers are stored as
+ * little-endian 32-bit) and updating @inode->i_blocks appropriately.
+ *
+ * We accumulate contiguous runs of blocks to free.  Conveniently, if these
+ * blocks are contiguous then releasing them at one time will only affect one
+ * or two bitmap blocks (+ group descriptor(s) and superblock) and we won't
+ * actually use a lot of journal space.
+ *
+ * @this_bh will be %NULL if @first and @last point into the inode's direct
+ * block pointers.
+ */
+static void ext4_free_data(handle_t *handle, struct inode *inode,
+			   struct buffer_head *this_bh,
+			   __le32 *first, __le32 *last)
+{
+	ext4_fsblk_t block_to_free = 0;    /* Starting block # of a run */
+	unsigned long count = 0;	    /* Number of blocks in the run */
+	__le32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
+					       corresponding to
+					       block_to_free */
+	ext4_fsblk_t nr;		    /* Current block # */
+	__le32 *p;			    /* Pointer into inode/ind
+					       for current block */
+	int err;
+
+	if (this_bh) {				/* For indirect block */
+		BUFFER_TRACE(this_bh, "get_write_access");
+		err = ext4_journal_get_write_access(handle, this_bh);
+		/* Important: if we can't update the indirect pointers
+		 * to the blocks, we can't free them. */
+		if (err)
+			return;
+	}
+
+	for (p = first; p < last; p++) {
+		nr = le32_to_cpu(*p);
+		if (nr) {
+			/* accumulate blocks to free if they're contiguous */
+			if (count == 0) {
+				block_to_free = nr;
+				block_to_free_p = p;
+				count = 1;
+			} else if (nr == block_to_free + count) {
+				count++;
+			} else {
+				ext4_clear_blocks(handle, inode, this_bh,
+						  block_to_free,
+						  count, block_to_free_p, p);
+				block_to_free = nr;
+				block_to_free_p = p;
+				count = 1;
+			}
+		}
+	}
+
+	if (count > 0)
+		ext4_clear_blocks(handle, inode, this_bh, block_to_free,
+				  count, block_to_free_p, p);
+
+	if (this_bh) {
+		BUFFER_TRACE(this_bh, "call ext4_journal_dirty_metadata");
+		ext4_journal_dirty_metadata(handle, this_bh);
+	}
+}
+
+/**
+ *	ext4_free_branches - free an array of branches
+ *	@handle: JBD handle for this transaction
+ *	@inode:	inode we are dealing with
+ *	@parent_bh: the buffer_head which contains *@first and *@last
+ *	@first:	array of block numbers
+ *	@last:	pointer immediately past the end of array
+ *	@depth:	depth of the branches to free
+ *
+ *	We are freeing all blocks refered from these branches (numbers are
+ *	stored as little-endian 32-bit) and updating @inode->i_blocks
+ *	appropriately.
+ */
+static void ext4_free_branches(handle_t *handle, struct inode *inode,
+			       struct buffer_head *parent_bh,
+			       __le32 *first, __le32 *last, int depth)
+{
+	ext4_fsblk_t nr;
+	__le32 *p;
+
+	if (is_handle_aborted(handle))
+		return;
+
+	if (depth--) {
+		struct buffer_head *bh;
+		int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+		p = last;
+		while (--p >= first) {
+			nr = le32_to_cpu(*p);
+			if (!nr)
+				continue;		/* A hole */
+
+			/* Go read the buffer for the next level down */
+			bh = sb_bread(inode->i_sb, nr);
+
+			/*
+			 * A read failure? Report error and clear slot
+			 * (should be rare).
+			 */
+			if (!bh) {
+				ext4_error(inode->i_sb, "ext4_free_branches",
+					   "Read failure, inode=%lu, block=%llu",
+					   inode->i_ino, nr);
+				continue;
+			}
+
+			/* This zaps the entire block.  Bottom up. */
+			BUFFER_TRACE(bh, "free child branches");
+			ext4_free_branches(handle, inode, bh,
+					   (__le32*)bh->b_data,
+					   (__le32*)bh->b_data + addr_per_block,
+					   depth);
+
+			/*
+			 * We've probably journalled the indirect block several
+			 * times during the truncate.  But it's no longer
+			 * needed and we now drop it from the transaction via
+			 * jbd2_journal_revoke().
+			 *
+			 * That's easy if it's exclusively part of this
+			 * transaction.  But if it's part of the committing
+			 * transaction then jbd2_journal_forget() will simply
+			 * brelse() it.  That means that if the underlying
+			 * block is reallocated in ext4_get_block(),
+			 * unmap_underlying_metadata() will find this block
+			 * and will try to get rid of it.  damn, damn.
+			 *
+			 * If this block has already been committed to the
+			 * journal, a revoke record will be written.  And
+			 * revoke records must be emitted *before* clearing
+			 * this block's bit in the bitmaps.
+			 */
+			ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
+
+			/*
+			 * Everything below this this pointer has been
+			 * released.  Now let this top-of-subtree go.
+			 *
+			 * We want the freeing of this indirect block to be
+			 * atomic in the journal with the updating of the
+			 * bitmap block which owns it.  So make some room in
+			 * the journal.
+			 *
+			 * We zero the parent pointer *after* freeing its
+			 * pointee in the bitmaps, so if extend_transaction()
+			 * for some reason fails to put the bitmap changes and
+			 * the release into the same transaction, recovery
+			 * will merely complain about releasing a free block,
+			 * rather than leaking blocks.
+			 */
+			if (is_handle_aborted(handle))
+				return;
+			if (try_to_extend_transaction(handle, inode)) {
+				ext4_mark_inode_dirty(handle, inode);
+				ext4_journal_test_restart(handle, inode);
+			}
+
+			ext4_free_blocks(handle, inode, nr, 1);
+
+			if (parent_bh) {
+				/*
+				 * The block which we have just freed is
+				 * pointed to by an indirect block: journal it
+				 */
+				BUFFER_TRACE(parent_bh, "get_write_access");
+				if (!ext4_journal_get_write_access(handle,
+								   parent_bh)){
+					*p = 0;
+					BUFFER_TRACE(parent_bh,
+					"call ext4_journal_dirty_metadata");
+					ext4_journal_dirty_metadata(handle,
+								    parent_bh);
+				}
+			}
+		}
+	} else {
+		/* We have reached the bottom of the tree. */
+		BUFFER_TRACE(parent_bh, "free data blocks");
+		ext4_free_data(handle, inode, parent_bh, first, last);
+	}
+}
+
+/*
+ * ext4_truncate()
+ *
+ * We block out ext4_get_block() block instantiations across the entire
+ * transaction, and VFS/VM ensures that ext4_truncate() cannot run
+ * simultaneously on behalf of the same inode.
+ *
+ * As we work through the truncate and commmit bits of it to the journal there
+ * is one core, guiding principle: the file's tree must always be consistent on
+ * disk.  We must be able to restart the truncate after a crash.
+ *
+ * The file's tree may be transiently inconsistent in memory (although it
+ * probably isn't), but whenever we close off and commit a journal transaction,
+ * the contents of (the filesystem + the journal) must be consistent and
+ * restartable.  It's pretty simple, really: bottom up, right to left (although
+ * left-to-right works OK too).
+ *
+ * Note that at recovery time, journal replay occurs *before* the restart of
+ * truncate against the orphan inode list.
+ *
+ * The committed inode has the new, desired i_size (which is the same as
+ * i_disksize in this case).  After a crash, ext4_orphan_cleanup() will see
+ * that this inode's truncate did not complete and it will again call
+ * ext4_truncate() to have another go.  So there will be instantiated blocks
+ * to the right of the truncation point in a crashed ext4 filesystem.  But
+ * that's fine - as long as they are linked from the inode, the post-crash
+ * ext4_truncate() run will find them and release them.
+ */
+void ext4_truncate(struct inode *inode)
+{
+	handle_t *handle;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	__le32 *i_data = ei->i_data;
+	int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+	struct address_space *mapping = inode->i_mapping;
+	int offsets[4];
+	Indirect chain[4];
+	Indirect *partial;
+	__le32 nr = 0;
+	int n;
+	long last_block;
+	unsigned blocksize = inode->i_sb->s_blocksize;
+	struct page *page;
+
+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+	    S_ISLNK(inode->i_mode)))
+		return;
+	if (ext4_inode_is_fast_symlink(inode))
+		return;
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return;
+
+	/*
+	 * We have to lock the EOF page here, because lock_page() nests
+	 * outside jbd2_journal_start().
+	 */
+	if ((inode->i_size & (blocksize - 1)) == 0) {
+		/* Block boundary? Nothing to do */
+		page = NULL;
+	} else {
+		page = grab_cache_page(mapping,
+				inode->i_size >> PAGE_CACHE_SHIFT);
+		if (!page)
+			return;
+	}
+
+	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+		return ext4_ext_truncate(inode, page);
+
+	handle = start_transaction(inode);
+	if (IS_ERR(handle)) {
+		if (page) {
+			clear_highpage(page);
+			flush_dcache_page(page);
+			unlock_page(page);
+			page_cache_release(page);
+		}
+		return;		/* AKPM: return what? */
+	}
+
+	last_block = (inode->i_size + blocksize-1)
+					>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
+
+	if (page)
+		ext4_block_truncate_page(handle, page, mapping, inode->i_size);
+
+	n = ext4_block_to_path(inode, last_block, offsets, NULL);
+	if (n == 0)
+		goto out_stop;	/* error */
+
+	/*
+	 * OK.  This truncate is going to happen.  We add the inode to the
+	 * orphan list, so that if this truncate spans multiple transactions,
+	 * and we crash, we will resume the truncate when the filesystem
+	 * recovers.  It also marks the inode dirty, to catch the new size.
+	 *
+	 * Implication: the file must always be in a sane, consistent
+	 * truncatable state while each transaction commits.
+	 */
+	if (ext4_orphan_add(handle, inode))
+		goto out_stop;
+
+	/*
+	 * The orphan list entry will now protect us from any crash which
+	 * occurs before the truncate completes, so it is now safe to propagate
+	 * the new, shorter inode size (held for now in i_size) into the
+	 * on-disk inode. We do this via i_disksize, which is the value which
+	 * ext4 *really* writes onto the disk inode.
+	 */
+	ei->i_disksize = inode->i_size;
+
+	/*
+	 * From here we block out all ext4_get_block() callers who want to
+	 * modify the block allocation tree.
+	 */
+	mutex_lock(&ei->truncate_mutex);
+
+	if (n == 1) {		/* direct blocks */
+		ext4_free_data(handle, inode, NULL, i_data+offsets[0],
+			       i_data + EXT4_NDIR_BLOCKS);
+		goto do_indirects;
+	}
+
+	partial = ext4_find_shared(inode, n, offsets, chain, &nr);
+	/* Kill the top of shared branch (not detached) */
+	if (nr) {
+		if (partial == chain) {
+			/* Shared branch grows from the inode */
+			ext4_free_branches(handle, inode, NULL,
+					   &nr, &nr+1, (chain+n-1) - partial);
+			*partial->p = 0;
+			/*
+			 * We mark the inode dirty prior to restart,
+			 * and prior to stop.  No need for it here.
+			 */
+		} else {
+			/* Shared branch grows from an indirect block */
+			BUFFER_TRACE(partial->bh, "get_write_access");
+			ext4_free_branches(handle, inode, partial->bh,
+					partial->p,
+					partial->p+1, (chain+n-1) - partial);
+		}
+	}
+	/* Clear the ends of indirect blocks on the shared branch */
+	while (partial > chain) {
+		ext4_free_branches(handle, inode, partial->bh, partial->p + 1,
+				   (__le32*)partial->bh->b_data+addr_per_block,
+				   (chain+n-1) - partial);
+		BUFFER_TRACE(partial->bh, "call brelse");
+		brelse (partial->bh);
+		partial--;
+	}
+do_indirects:
+	/* Kill the remaining (whole) subtrees */
+	switch (offsets[0]) {
+	default:
+		nr = i_data[EXT4_IND_BLOCK];
+		if (nr) {
+			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
+			i_data[EXT4_IND_BLOCK] = 0;
+		}
+	case EXT4_IND_BLOCK:
+		nr = i_data[EXT4_DIND_BLOCK];
+		if (nr) {
+			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
+			i_data[EXT4_DIND_BLOCK] = 0;
+		}
+	case EXT4_DIND_BLOCK:
+		nr = i_data[EXT4_TIND_BLOCK];
+		if (nr) {
+			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
+			i_data[EXT4_TIND_BLOCK] = 0;
+		}
+	case EXT4_TIND_BLOCK:
+		;
+	}
+
+	ext4_discard_reservation(inode);
+
+	mutex_unlock(&ei->truncate_mutex);
+	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+	ext4_mark_inode_dirty(handle, inode);
+
+	/*
+	 * In a multi-transaction truncate, we only make the final transaction
+	 * synchronous
+	 */
+	if (IS_SYNC(inode))
+		handle->h_sync = 1;
+out_stop:
+	/*
+	 * If this was a simple ftruncate(), and the file will remain alive
+	 * then we need to clear up the orphan record which we created above.
+	 * However, if this was a real unlink then we were called by
+	 * ext4_delete_inode(), and we allow that function to clean up the
+	 * orphan info for us.
+	 */
+	if (inode->i_nlink)
+		ext4_orphan_del(handle, inode);
+
+	ext4_journal_stop(handle);
+}
+
+static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
+		unsigned long ino, struct ext4_iloc *iloc)
+{
+	unsigned long desc, group_desc, block_group;
+	unsigned long offset;
+	ext4_fsblk_t block;
+	struct buffer_head *bh;
+	struct ext4_group_desc * gdp;
+
+	if (!ext4_valid_inum(sb, ino)) {
+		/*
+		 * This error is already checked for in namei.c unless we are
+		 * looking at an NFS filehandle, in which case no error
+		 * report is needed
+		 */
+		return 0;
+	}
+
+	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+	if (block_group >= EXT4_SB(sb)->s_groups_count) {
+		ext4_error(sb,"ext4_get_inode_block","group >= groups count");
+		return 0;
+	}
+	smp_rmb();
+	group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
+	desc = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
+	bh = EXT4_SB(sb)->s_group_desc[group_desc];
+	if (!bh) {
+		ext4_error (sb, "ext4_get_inode_block",
+			    "Descriptor not loaded");
+		return 0;
+	}
+
+	gdp = (struct ext4_group_desc *)((__u8 *)bh->b_data +
+		desc * EXT4_DESC_SIZE(sb));
+	/*
+	 * Figure out the offset within the block group inode table
+	 */
+	offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
+		EXT4_INODE_SIZE(sb);
+	block = ext4_inode_table(sb, gdp) +
+		(offset >> EXT4_BLOCK_SIZE_BITS(sb));
+
+	iloc->block_group = block_group;
+	iloc->offset = offset & (EXT4_BLOCK_SIZE(sb) - 1);
+	return block;
+}
+
+/*
+ * ext4_get_inode_loc returns with an extra refcount against the inode's
+ * underlying buffer_head on success. If 'in_mem' is true, we have all
+ * data in memory that is needed to recreate the on-disk version of this
+ * inode.
+ */
+static int __ext4_get_inode_loc(struct inode *inode,
+				struct ext4_iloc *iloc, int in_mem)
+{
+	ext4_fsblk_t block;
+	struct buffer_head *bh;
+
+	block = ext4_get_inode_block(inode->i_sb, inode->i_ino, iloc);
+	if (!block)
+		return -EIO;
+
+	bh = sb_getblk(inode->i_sb, block);
+	if (!bh) {
+		ext4_error (inode->i_sb, "ext4_get_inode_loc",
+				"unable to read inode block - "
+				"inode=%lu, block=%llu",
+				 inode->i_ino, block);
+		return -EIO;
+	}
+	if (!buffer_uptodate(bh)) {
+		lock_buffer(bh);
+		if (buffer_uptodate(bh)) {
+			/* someone brought it uptodate while we waited */
+			unlock_buffer(bh);
+			goto has_buffer;
+		}
+
+		/*
+		 * If we have all information of the inode in memory and this
+		 * is the only valid inode in the block, we need not read the
+		 * block.
+		 */
+		if (in_mem) {
+			struct buffer_head *bitmap_bh;
+			struct ext4_group_desc *desc;
+			int inodes_per_buffer;
+			int inode_offset, i;
+			int block_group;
+			int start;
+
+			block_group = (inode->i_ino - 1) /
+					EXT4_INODES_PER_GROUP(inode->i_sb);
+			inodes_per_buffer = bh->b_size /
+				EXT4_INODE_SIZE(inode->i_sb);
+			inode_offset = ((inode->i_ino - 1) %
+					EXT4_INODES_PER_GROUP(inode->i_sb));
+			start = inode_offset & ~(inodes_per_buffer - 1);
+
+			/* Is the inode bitmap in cache? */
+			desc = ext4_get_group_desc(inode->i_sb,
+						block_group, NULL);
+			if (!desc)
+				goto make_io;
+
+			bitmap_bh = sb_getblk(inode->i_sb,
+				ext4_inode_bitmap(inode->i_sb, desc));
+			if (!bitmap_bh)
+				goto make_io;
+
+			/*
+			 * If the inode bitmap isn't in cache then the
+			 * optimisation may end up performing two reads instead
+			 * of one, so skip it.
+			 */
+			if (!buffer_uptodate(bitmap_bh)) {
+				brelse(bitmap_bh);
+				goto make_io;
+			}
+			for (i = start; i < start + inodes_per_buffer; i++) {
+				if (i == inode_offset)
+					continue;
+				if (ext4_test_bit(i, bitmap_bh->b_data))
+					break;
+			}
+			brelse(bitmap_bh);
+			if (i == start + inodes_per_buffer) {
+				/* all other inodes are free, so skip I/O */
+				memset(bh->b_data, 0, bh->b_size);
+				set_buffer_uptodate(bh);
+				unlock_buffer(bh);
+				goto has_buffer;
+			}
+		}
+
+make_io:
+		/*
+		 * There are other valid inodes in the buffer, this inode
+		 * has in-inode xattrs, or we don't have this inode in memory.
+		 * Read the block from disk.
+		 */
+		get_bh(bh);
+		bh->b_end_io = end_buffer_read_sync;
+		submit_bh(READ_META, bh);
+		wait_on_buffer(bh);
+		if (!buffer_uptodate(bh)) {
+			ext4_error(inode->i_sb, "ext4_get_inode_loc",
+					"unable to read inode block - "
+					"inode=%lu, block=%llu",
+					inode->i_ino, block);
+			brelse(bh);
+			return -EIO;
+		}
+	}
+has_buffer:
+	iloc->bh = bh;
+	return 0;
+}
+
+int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
+{
+	/* We have all inode data except xattrs in memory here. */
+	return __ext4_get_inode_loc(inode, iloc,
+		!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR));
+}
+
+void ext4_set_inode_flags(struct inode *inode)
+{
+	unsigned int flags = EXT4_I(inode)->i_flags;
+
+	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+	if (flags & EXT4_SYNC_FL)
+		inode->i_flags |= S_SYNC;
+	if (flags & EXT4_APPEND_FL)
+		inode->i_flags |= S_APPEND;
+	if (flags & EXT4_IMMUTABLE_FL)
+		inode->i_flags |= S_IMMUTABLE;
+	if (flags & EXT4_NOATIME_FL)
+		inode->i_flags |= S_NOATIME;
+	if (flags & EXT4_DIRSYNC_FL)
+		inode->i_flags |= S_DIRSYNC;
+}
+
+void ext4_read_inode(struct inode * inode)
+{
+	struct ext4_iloc iloc;
+	struct ext4_inode *raw_inode;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct buffer_head *bh;
+	int block;
+
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+	ei->i_acl = EXT4_ACL_NOT_CACHED;
+	ei->i_default_acl = EXT4_ACL_NOT_CACHED;
+#endif
+	ei->i_block_alloc_info = NULL;
+
+	if (__ext4_get_inode_loc(inode, &iloc, 0))
+		goto bad_inode;
+	bh = iloc.bh;
+	raw_inode = ext4_raw_inode(&iloc);
+	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
+	inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
+	if(!(test_opt (inode->i_sb, NO_UID32))) {
+		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
+		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
+	}
+	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+	inode->i_size = le32_to_cpu(raw_inode->i_size);
+	inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
+	inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
+	inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
+	inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
+
+	ei->i_state = 0;
+	ei->i_dir_start_lookup = 0;
+	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
+	/* We now have enough fields to check if the inode was active or not.
+	 * This is needed because nfsd might try to access dead inodes
+	 * the test is that same one that e2fsck uses
+	 * NeilBrown 1999oct15
+	 */
+	if (inode->i_nlink == 0) {
+		if (inode->i_mode == 0 ||
+		    !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) {
+			/* this inode is deleted */
+			brelse (bh);
+			goto bad_inode;
+		}
+		/* The only unlinked inodes we let through here have
+		 * valid i_mode and are being read by the orphan
+		 * recovery code: that's fine, we're about to complete
+		 * the process of deleting those. */
+	}
+	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
+#ifdef EXT4_FRAGMENTS
+	ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
+	ei->i_frag_no = raw_inode->i_frag;
+	ei->i_frag_size = raw_inode->i_fsize;
+#endif
+	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
+	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+	    cpu_to_le32(EXT4_OS_HURD))
+		ei->i_file_acl |=
+			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
+	if (!S_ISREG(inode->i_mode)) {
+		ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+	} else {
+		inode->i_size |=
+			((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
+	}
+	ei->i_disksize = inode->i_size;
+	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
+	ei->i_block_group = iloc.block_group;
+	/*
+	 * NOTE! The in-memory inode i_data array is in little-endian order
+	 * even on big-endian machines: we do NOT byteswap the block numbers!
+	 */
+	for (block = 0; block < EXT4_N_BLOCKS; block++)
+		ei->i_data[block] = raw_inode->i_block[block];
+	INIT_LIST_HEAD(&ei->i_orphan);
+
+	if (inode->i_ino >= EXT4_FIRST_INO(inode->i_sb) + 1 &&
+	    EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+		/*
+		 * When mke2fs creates big inodes it does not zero out
+		 * the unused bytes above EXT4_GOOD_OLD_INODE_SIZE,
+		 * so ignore those first few inodes.
+		 */
+		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
+		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
+		    EXT4_INODE_SIZE(inode->i_sb))
+			goto bad_inode;
+		if (ei->i_extra_isize == 0) {
+			/* The extra space is currently unused. Use it. */
+			ei->i_extra_isize = sizeof(struct ext4_inode) -
+					    EXT4_GOOD_OLD_INODE_SIZE;
+		} else {
+			__le32 *magic = (void *)raw_inode +
+					EXT4_GOOD_OLD_INODE_SIZE +
+					ei->i_extra_isize;
+			if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
+				 ei->i_state |= EXT4_STATE_XATTR;
+		}
+	} else
+		ei->i_extra_isize = 0;
+
+	if (S_ISREG(inode->i_mode)) {
+		inode->i_op = &ext4_file_inode_operations;
+		inode->i_fop = &ext4_file_operations;
+		ext4_set_aops(inode);
+	} else if (S_ISDIR(inode->i_mode)) {
+		inode->i_op = &ext4_dir_inode_operations;
+		inode->i_fop = &ext4_dir_operations;
+	} else if (S_ISLNK(inode->i_mode)) {
+		if (ext4_inode_is_fast_symlink(inode))
+			inode->i_op = &ext4_fast_symlink_inode_operations;
+		else {
+			inode->i_op = &ext4_symlink_inode_operations;
+			ext4_set_aops(inode);
+		}
+	} else {
+		inode->i_op = &ext4_special_inode_operations;
+		if (raw_inode->i_block[0])
+			init_special_inode(inode, inode->i_mode,
+			   old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
+		else
+			init_special_inode(inode, inode->i_mode,
+			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
+	}
+	brelse (iloc.bh);
+	ext4_set_inode_flags(inode);
+	return;
+
+bad_inode:
+	make_bad_inode(inode);
+	return;
+}
+
+/*
+ * Post the struct inode info into an on-disk inode location in the
+ * buffer-cache.  This gobbles the caller's reference to the
+ * buffer_head in the inode location struct.
+ *
+ * The caller must have write access to iloc->bh.
+ */
+static int ext4_do_update_inode(handle_t *handle,
+				struct inode *inode,
+				struct ext4_iloc *iloc)
+{
+	struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct buffer_head *bh = iloc->bh;
+	int err = 0, rc, block;
+
+	/* For fields not not tracking in the in-memory inode,
+	 * initialise them to zero for new inodes. */
+	if (ei->i_state & EXT4_STATE_NEW)
+		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
+
+	raw_inode->i_mode = cpu_to_le16(inode->i_mode);
+	if(!(test_opt(inode->i_sb, NO_UID32))) {
+		raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
+		raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
+/*
+ * Fix up interoperability with old kernels. Otherwise, old inodes get
+ * re-used with the upper 16 bits of the uid/gid intact
+ */
+		if(!ei->i_dtime) {
+			raw_inode->i_uid_high =
+				cpu_to_le16(high_16_bits(inode->i_uid));
+			raw_inode->i_gid_high =
+				cpu_to_le16(high_16_bits(inode->i_gid));
+		} else {
+			raw_inode->i_uid_high = 0;
+			raw_inode->i_gid_high = 0;
+		}
+	} else {
+		raw_inode->i_uid_low =
+			cpu_to_le16(fs_high2lowuid(inode->i_uid));
+		raw_inode->i_gid_low =
+			cpu_to_le16(fs_high2lowgid(inode->i_gid));
+		raw_inode->i_uid_high = 0;
+		raw_inode->i_gid_high = 0;
+	}
+	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
+	raw_inode->i_size = cpu_to_le32(ei->i_disksize);
+	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
+	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
+	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
+	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
+	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
+	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
+#ifdef EXT4_FRAGMENTS
+	raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
+	raw_inode->i_frag = ei->i_frag_no;
+	raw_inode->i_fsize = ei->i_frag_size;
+#endif
+	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+	    cpu_to_le32(EXT4_OS_HURD))
+		raw_inode->i_file_acl_high =
+			cpu_to_le16(ei->i_file_acl >> 32);
+	raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
+	if (!S_ISREG(inode->i_mode)) {
+		raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
+	} else {
+		raw_inode->i_size_high =
+			cpu_to_le32(ei->i_disksize >> 32);
+		if (ei->i_disksize > 0x7fffffffULL) {
+			struct super_block *sb = inode->i_sb;
+			if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
+					EXT4_FEATURE_RO_COMPAT_LARGE_FILE) ||
+			    EXT4_SB(sb)->s_es->s_rev_level ==
+					cpu_to_le32(EXT4_GOOD_OLD_REV)) {
+			       /* If this is the first large file
+				* created, add a flag to the superblock.
+				*/
+				err = ext4_journal_get_write_access(handle,
+						EXT4_SB(sb)->s_sbh);
+				if (err)
+					goto out_brelse;
+				ext4_update_dynamic_rev(sb);
+				EXT4_SET_RO_COMPAT_FEATURE(sb,
+					EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
+				sb->s_dirt = 1;
+				handle->h_sync = 1;
+				err = ext4_journal_dirty_metadata(handle,
+						EXT4_SB(sb)->s_sbh);
+			}
+		}
+	}
+	raw_inode->i_generation = cpu_to_le32(inode->i_generation);
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+		if (old_valid_dev(inode->i_rdev)) {
+			raw_inode->i_block[0] =
+				cpu_to_le32(old_encode_dev(inode->i_rdev));
+			raw_inode->i_block[1] = 0;
+		} else {
+			raw_inode->i_block[0] = 0;
+			raw_inode->i_block[1] =
+				cpu_to_le32(new_encode_dev(inode->i_rdev));
+			raw_inode->i_block[2] = 0;
+		}
+	} else for (block = 0; block < EXT4_N_BLOCKS; block++)
+		raw_inode->i_block[block] = ei->i_data[block];
+
+	if (ei->i_extra_isize)
+		raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
+
+	BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+	rc = ext4_journal_dirty_metadata(handle, bh);
+	if (!err)
+		err = rc;
+	ei->i_state &= ~EXT4_STATE_NEW;
+
+out_brelse:
+	brelse (bh);
+	ext4_std_error(inode->i_sb, err);
+	return err;
+}
+
+/*
+ * ext4_write_inode()
+ *
+ * We are called from a few places:
+ *
+ * - Within generic_file_write() for O_SYNC files.
+ *   Here, there will be no transaction running. We wait for any running
+ *   trasnaction to commit.
+ *
+ * - Within sys_sync(), kupdate and such.
+ *   We wait on commit, if tol to.
+ *
+ * - Within prune_icache() (PF_MEMALLOC == true)
+ *   Here we simply return.  We can't afford to block kswapd on the
+ *   journal commit.
+ *
+ * In all cases it is actually safe for us to return without doing anything,
+ * because the inode has been copied into a raw inode buffer in
+ * ext4_mark_inode_dirty().  This is a correctness thing for O_SYNC and for
+ * knfsd.
+ *
+ * Note that we are absolutely dependent upon all inode dirtiers doing the
+ * right thing: they *must* call mark_inode_dirty() after dirtying info in
+ * which we are interested.
+ *
+ * It would be a bug for them to not do this.  The code:
+ *
+ *	mark_inode_dirty(inode)
+ *	stuff();
+ *	inode->i_size = expr;
+ *
+ * is in error because a kswapd-driven write_inode() could occur while
+ * `stuff()' is running, and the new i_size will be lost.  Plus the inode
+ * will no longer be on the superblock's dirty inode list.
+ */
+int ext4_write_inode(struct inode *inode, int wait)
+{
+	if (current->flags & PF_MEMALLOC)
+		return 0;
+
+	if (ext4_journal_current_handle()) {
+		jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n");
+		dump_stack();
+		return -EIO;
+	}
+
+	if (!wait)
+		return 0;
+
+	return ext4_force_commit(inode->i_sb);
+}
+
+/*
+ * ext4_setattr()
+ *
+ * Called from notify_change.
+ *
+ * We want to trap VFS attempts to truncate the file as soon as
+ * possible.  In particular, we want to make sure that when the VFS
+ * shrinks i_size, we put the inode on the orphan list and modify
+ * i_disksize immediately, so that during the subsequent flushing of
+ * dirty pages and freeing of disk blocks, we can guarantee that any
+ * commit will leave the blocks being flushed in an unused state on
+ * disk.  (On recovery, the inode will get truncated and the blocks will
+ * be freed, so we have a strong guarantee that no future commit will
+ * leave these blocks visible to the user.)
+ *
+ * Called with inode->sem down.
+ */
+int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	int error, rc = 0;
+	const unsigned int ia_valid = attr->ia_valid;
+
+	error = inode_change_ok(inode, attr);
+	if (error)
+		return error;
+
+	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+		(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+		handle_t *handle;
+
+		/* (user+group)*(old+new) structure, inode write (sb,
+		 * inode block, ? - but truncate inode update has it) */
+		handle = ext4_journal_start(inode, 2*(EXT4_QUOTA_INIT_BLOCKS(inode->i_sb)+
+					EXT4_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
+		if (IS_ERR(handle)) {
+			error = PTR_ERR(handle);
+			goto err_out;
+		}
+		error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+		if (error) {
+			ext4_journal_stop(handle);
+			return error;
+		}
+		/* Update corresponding info in inode so that everything is in
+		 * one transaction */
+		if (attr->ia_valid & ATTR_UID)
+			inode->i_uid = attr->ia_uid;
+		if (attr->ia_valid & ATTR_GID)
+			inode->i_gid = attr->ia_gid;
+		error = ext4_mark_inode_dirty(handle, inode);
+		ext4_journal_stop(handle);
+	}
+
+	if (S_ISREG(inode->i_mode) &&
+	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
+		handle_t *handle;
+
+		handle = ext4_journal_start(inode, 3);
+		if (IS_ERR(handle)) {
+			error = PTR_ERR(handle);
+			goto err_out;
+		}
+
+		error = ext4_orphan_add(handle, inode);
+		EXT4_I(inode)->i_disksize = attr->ia_size;
+		rc = ext4_mark_inode_dirty(handle, inode);
+		if (!error)
+			error = rc;
+		ext4_journal_stop(handle);
+	}
+
+	rc = inode_setattr(inode, attr);
+
+	/* If inode_setattr's call to ext4_truncate failed to get a
+	 * transaction handle at all, we need to clean up the in-core
+	 * orphan list manually. */
+	if (inode->i_nlink)
+		ext4_orphan_del(NULL, inode);
+
+	if (!rc && (ia_valid & ATTR_MODE))
+		rc = ext4_acl_chmod(inode);
+
+err_out:
+	ext4_std_error(inode->i_sb, error);
+	if (!error)
+		error = rc;
+	return error;
+}
+
+
+/*
+ * How many blocks doth make a writepage()?
+ *
+ * With N blocks per page, it may be:
+ * N data blocks
+ * 2 indirect block
+ * 2 dindirect
+ * 1 tindirect
+ * N+5 bitmap blocks (from the above)
+ * N+5 group descriptor summary blocks
+ * 1 inode block
+ * 1 superblock.
+ * 2 * EXT4_SINGLEDATA_TRANS_BLOCKS for the quote files
+ *
+ * 3 * (N + 5) + 2 + 2 * EXT4_SINGLEDATA_TRANS_BLOCKS
+ *
+ * With ordered or writeback data it's the same, less the N data blocks.
+ *
+ * If the inode's direct blocks can hold an integral number of pages then a
+ * page cannot straddle two indirect blocks, and we can only touch one indirect
+ * and dindirect block, and the "5" above becomes "3".
+ *
+ * This still overestimates under most circumstances.  If we were to pass the
+ * start and end offsets in here as well we could do block_to_path() on each
+ * block and work out the exact number of indirects which are touched.  Pah.
+ */
+
+int ext4_writepage_trans_blocks(struct inode *inode)
+{
+	int bpp = ext4_journal_blocks_per_page(inode);
+	int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3;
+	int ret;
+
+	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+		return ext4_ext_writepage_trans_blocks(inode, bpp);
+
+	if (ext4_should_journal_data(inode))
+		ret = 3 * (bpp + indirects) + 2;
+	else
+		ret = 2 * (bpp + indirects) + 2;
+
+#ifdef CONFIG_QUOTA
+	/* We know that structure was already allocated during DQUOT_INIT so
+	 * we will be updating only the data blocks + inodes */
+	ret += 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
+#endif
+
+	return ret;
+}
+
+/*
+ * The caller must have previously called ext4_reserve_inode_write().
+ * Give this, we know that the caller already has write access to iloc->bh.
+ */
+int ext4_mark_iloc_dirty(handle_t *handle,
+		struct inode *inode, struct ext4_iloc *iloc)
+{
+	int err = 0;
+
+	/* the do_update_inode consumes one bh->b_count */
+	get_bh(iloc->bh);
+
+	/* ext4_do_update_inode() does jbd2_journal_dirty_metadata */
+	err = ext4_do_update_inode(handle, inode, iloc);
+	put_bh(iloc->bh);
+	return err;
+}
+
+/*
+ * On success, We end up with an outstanding reference count against
+ * iloc->bh.  This _must_ be cleaned up later.
+ */
+
+int
+ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
+			 struct ext4_iloc *iloc)
+{
+	int err = 0;
+	if (handle) {
+		err = ext4_get_inode_loc(inode, iloc);
+		if (!err) {
+			BUFFER_TRACE(iloc->bh, "get_write_access");
+			err = ext4_journal_get_write_access(handle, iloc->bh);
+			if (err) {
+				brelse(iloc->bh);
+				iloc->bh = NULL;
+			}
+		}
+	}
+	ext4_std_error(inode->i_sb, err);
+	return err;
+}
+
+/*
+ * What we do here is to mark the in-core inode as clean with respect to inode
+ * dirtiness (it may still be data-dirty).
+ * This means that the in-core inode may be reaped by prune_icache
+ * without having to perform any I/O.  This is a very good thing,
+ * because *any* task may call prune_icache - even ones which
+ * have a transaction open against a different journal.
+ *
+ * Is this cheating?  Not really.  Sure, we haven't written the
+ * inode out, but prune_icache isn't a user-visible syncing function.
+ * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync)
+ * we start and wait on commits.
+ *
+ * Is this efficient/effective?  Well, we're being nice to the system
+ * by cleaning up our inodes proactively so they can be reaped
+ * without I/O.  But we are potentially leaving up to five seconds'
+ * worth of inodes floating about which prune_icache wants us to
+ * write out.  One way to fix that would be to get prune_icache()
+ * to do a write_super() to free up some memory.  It has the desired
+ * effect.
+ */
+int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+{
+	struct ext4_iloc iloc;
+	int err;
+
+	might_sleep();
+	err = ext4_reserve_inode_write(handle, inode, &iloc);
+	if (!err)
+		err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+	return err;
+}
+
+/*
+ * ext4_dirty_inode() is called from __mark_inode_dirty()
+ *
+ * We're really interested in the case where a file is being extended.
+ * i_size has been changed by generic_commit_write() and we thus need
+ * to include the updated inode in the current transaction.
+ *
+ * Also, DQUOT_ALLOC_SPACE() will always dirty the inode when blocks
+ * are allocated to the file.
+ *
+ * If the inode is marked synchronous, we don't honour that here - doing
+ * so would cause a commit on atime updates, which we don't bother doing.
+ * We handle synchronous inodes at the highest possible level.
+ */
+void ext4_dirty_inode(struct inode *inode)
+{
+	handle_t *current_handle = ext4_journal_current_handle();
+	handle_t *handle;
+
+	handle = ext4_journal_start(inode, 2);
+	if (IS_ERR(handle))
+		goto out;
+	if (current_handle &&
+		current_handle->h_transaction != handle->h_transaction) {
+		/* This task has a transaction open against a different fs */
+		printk(KERN_EMERG "%s: transactions do not match!\n",
+		       __FUNCTION__);
+	} else {
+		jbd_debug(5, "marking dirty.  outer handle=%p\n",
+				current_handle);
+		ext4_mark_inode_dirty(handle, inode);
+	}
+	ext4_journal_stop(handle);
+out:
+	return;
+}
+
+#if 0
+/*
+ * Bind an inode's backing buffer_head into this transaction, to prevent
+ * it from being flushed to disk early.  Unlike
+ * ext4_reserve_inode_write, this leaves behind no bh reference and
+ * returns no iloc structure, so the caller needs to repeat the iloc
+ * lookup to mark the inode dirty later.
+ */
+static int ext4_pin_inode(handle_t *handle, struct inode *inode)
+{
+	struct ext4_iloc iloc;
+
+	int err = 0;
+	if (handle) {
+		err = ext4_get_inode_loc(inode, &iloc);
+		if (!err) {
+			BUFFER_TRACE(iloc.bh, "get_write_access");
+			err = jbd2_journal_get_write_access(handle, iloc.bh);
+			if (!err)
+				err = ext4_journal_dirty_metadata(handle,
+								  iloc.bh);
+			brelse(iloc.bh);
+		}
+	}
+	ext4_std_error(inode->i_sb, err);
+	return err;
+}
+#endif
+
+int ext4_change_inode_journal_flag(struct inode *inode, int val)
+{
+	journal_t *journal;
+	handle_t *handle;
+	int err;
+
+	/*
+	 * We have to be very careful here: changing a data block's
+	 * journaling status dynamically is dangerous.  If we write a
+	 * data block to the journal, change the status and then delete
+	 * that block, we risk forgetting to revoke the old log record
+	 * from the journal and so a subsequent replay can corrupt data.
+	 * So, first we make sure that the journal is empty and that
+	 * nobody is changing anything.
+	 */
+
+	journal = EXT4_JOURNAL(inode);
+	if (is_journal_aborted(journal) || IS_RDONLY(inode))
+		return -EROFS;
+
+	jbd2_journal_lock_updates(journal);
+	jbd2_journal_flush(journal);
+
+	/*
+	 * OK, there are no updates running now, and all cached data is
+	 * synced to disk.  We are now in a completely consistent state
+	 * which doesn't have anything in the journal, and we know that
+	 * no filesystem updates are running, so it is safe to modify
+	 * the inode's in-core data-journaling state flag now.
+	 */
+
+	if (val)
+		EXT4_I(inode)->i_flags |= EXT4_JOURNAL_DATA_FL;
+	else
+		EXT4_I(inode)->i_flags &= ~EXT4_JOURNAL_DATA_FL;
+	ext4_set_aops(inode);
+
+	jbd2_journal_unlock_updates(journal);
+
+	/* Finally we can mark the inode as dirty. */
+
+	handle = ext4_journal_start(inode, 1);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	err = ext4_mark_inode_dirty(handle, inode);
+	handle->h_sync = 1;
+	ext4_journal_stop(handle);
+	ext4_std_error(inode->i_sb, err);
+
+	return err;
+}
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
new file mode 100644
index 0000000..22a737c
--- /dev/null
+++ b/fs/ext4/ioctl.c
@@ -0,0 +1,306 @@
+/*
+ * linux/fs/ext4/ioctl.c
+ *
+ * Copyright (C) 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ */
+
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/capability.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/time.h>
+#include <linux/compat.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+		unsigned long arg)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	unsigned int flags;
+	unsigned short rsv_window_size;
+
+	ext4_debug ("cmd = %u, arg = %lu\n", cmd, arg);
+
+	switch (cmd) {
+	case EXT4_IOC_GETFLAGS:
+		flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
+		return put_user(flags, (int __user *) arg);
+	case EXT4_IOC_SETFLAGS: {
+		handle_t *handle = NULL;
+		int err;
+		struct ext4_iloc iloc;
+		unsigned int oldflags;
+		unsigned int jflag;
+
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EACCES;
+
+		if (get_user(flags, (int __user *) arg))
+			return -EFAULT;
+
+		if (!S_ISDIR(inode->i_mode))
+			flags &= ~EXT4_DIRSYNC_FL;
+
+		mutex_lock(&inode->i_mutex);
+		oldflags = ei->i_flags;
+
+		/* The JOURNAL_DATA flag is modifiable only by root */
+		jflag = flags & EXT4_JOURNAL_DATA_FL;
+
+		/*
+		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
+		 * the relevant capability.
+		 *
+		 * This test looks nicer. Thanks to Pauline Middelink
+		 */
+		if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
+			if (!capable(CAP_LINUX_IMMUTABLE)) {
+				mutex_unlock(&inode->i_mutex);
+				return -EPERM;
+			}
+		}
+
+		/*
+		 * The JOURNAL_DATA flag can only be changed by
+		 * the relevant capability.
+		 */
+		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+			if (!capable(CAP_SYS_RESOURCE)) {
+				mutex_unlock(&inode->i_mutex);
+				return -EPERM;
+			}
+		}
+
+
+		handle = ext4_journal_start(inode, 1);
+		if (IS_ERR(handle)) {
+			mutex_unlock(&inode->i_mutex);
+			return PTR_ERR(handle);
+		}
+		if (IS_SYNC(inode))
+			handle->h_sync = 1;
+		err = ext4_reserve_inode_write(handle, inode, &iloc);
+		if (err)
+			goto flags_err;
+
+		flags = flags & EXT4_FL_USER_MODIFIABLE;
+		flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE;
+		ei->i_flags = flags;
+
+		ext4_set_inode_flags(inode);
+		inode->i_ctime = CURRENT_TIME_SEC;
+
+		err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+flags_err:
+		ext4_journal_stop(handle);
+		if (err) {
+			mutex_unlock(&inode->i_mutex);
+			return err;
+		}
+
+		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
+			err = ext4_change_inode_journal_flag(inode, jflag);
+		mutex_unlock(&inode->i_mutex);
+		return err;
+	}
+	case EXT4_IOC_GETVERSION:
+	case EXT4_IOC_GETVERSION_OLD:
+		return put_user(inode->i_generation, (int __user *) arg);
+	case EXT4_IOC_SETVERSION:
+	case EXT4_IOC_SETVERSION_OLD: {
+		handle_t *handle;
+		struct ext4_iloc iloc;
+		__u32 generation;
+		int err;
+
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EPERM;
+		if (IS_RDONLY(inode))
+			return -EROFS;
+		if (get_user(generation, (int __user *) arg))
+			return -EFAULT;
+
+		handle = ext4_journal_start(inode, 1);
+		if (IS_ERR(handle))
+			return PTR_ERR(handle);
+		err = ext4_reserve_inode_write(handle, inode, &iloc);
+		if (err == 0) {
+			inode->i_ctime = CURRENT_TIME_SEC;
+			inode->i_generation = generation;
+			err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+		}
+		ext4_journal_stop(handle);
+		return err;
+	}
+#ifdef CONFIG_JBD_DEBUG
+	case EXT4_IOC_WAIT_FOR_READONLY:
+		/*
+		 * This is racy - by the time we're woken up and running,
+		 * the superblock could be released.  And the module could
+		 * have been unloaded.  So sue me.
+		 *
+		 * Returns 1 if it slept, else zero.
+		 */
+		{
+			struct super_block *sb = inode->i_sb;
+			DECLARE_WAITQUEUE(wait, current);
+			int ret = 0;
+
+			set_current_state(TASK_INTERRUPTIBLE);
+			add_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
+			if (timer_pending(&EXT4_SB(sb)->turn_ro_timer)) {
+				schedule();
+				ret = 1;
+			}
+			remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
+			return ret;
+		}
+#endif
+	case EXT4_IOC_GETRSVSZ:
+		if (test_opt(inode->i_sb, RESERVATION)
+			&& S_ISREG(inode->i_mode)
+			&& ei->i_block_alloc_info) {
+			rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
+			return put_user(rsv_window_size, (int __user *)arg);
+		}
+		return -ENOTTY;
+	case EXT4_IOC_SETRSVSZ: {
+
+		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+			return -ENOTTY;
+
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EACCES;
+
+		if (get_user(rsv_window_size, (int __user *)arg))
+			return -EFAULT;
+
+		if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS)
+			rsv_window_size = EXT4_MAX_RESERVE_BLOCKS;
+
+		/*
+		 * need to allocate reservation structure for this inode
+		 * before set the window size
+		 */
+		mutex_lock(&ei->truncate_mutex);
+		if (!ei->i_block_alloc_info)
+			ext4_init_block_alloc_info(inode);
+
+		if (ei->i_block_alloc_info){
+			struct ext4_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
+			rsv->rsv_goal_size = rsv_window_size;
+		}
+		mutex_unlock(&ei->truncate_mutex);
+		return 0;
+	}
+	case EXT4_IOC_GROUP_EXTEND: {
+		ext4_fsblk_t n_blocks_count;
+		struct super_block *sb = inode->i_sb;
+		int err;
+
+		if (!capable(CAP_SYS_RESOURCE))
+			return -EPERM;
+
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if (get_user(n_blocks_count, (__u32 __user *)arg))
+			return -EFAULT;
+
+		err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
+		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+		jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+
+		return err;
+	}
+	case EXT4_IOC_GROUP_ADD: {
+		struct ext4_new_group_data input;
+		struct super_block *sb = inode->i_sb;
+		int err;
+
+		if (!capable(CAP_SYS_RESOURCE))
+			return -EPERM;
+
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
+				sizeof(input)))
+			return -EFAULT;
+
+		err = ext4_group_add(sb, &input);
+		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+		jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+
+		return err;
+	}
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+#ifdef CONFIG_COMPAT
+long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret;
+
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT4_IOC32_GETFLAGS:
+		cmd = EXT4_IOC_GETFLAGS;
+		break;
+	case EXT4_IOC32_SETFLAGS:
+		cmd = EXT4_IOC_SETFLAGS;
+		break;
+	case EXT4_IOC32_GETVERSION:
+		cmd = EXT4_IOC_GETVERSION;
+		break;
+	case EXT4_IOC32_SETVERSION:
+		cmd = EXT4_IOC_SETVERSION;
+		break;
+	case EXT4_IOC32_GROUP_EXTEND:
+		cmd = EXT4_IOC_GROUP_EXTEND;
+		break;
+	case EXT4_IOC32_GETVERSION_OLD:
+		cmd = EXT4_IOC_GETVERSION_OLD;
+		break;
+	case EXT4_IOC32_SETVERSION_OLD:
+		cmd = EXT4_IOC_SETVERSION_OLD;
+		break;
+#ifdef CONFIG_JBD_DEBUG
+	case EXT4_IOC32_WAIT_FOR_READONLY:
+		cmd = EXT4_IOC_WAIT_FOR_READONLY;
+		break;
+#endif
+	case EXT4_IOC32_GETRSVSZ:
+		cmd = EXT4_IOC_GETRSVSZ;
+		break;
+	case EXT4_IOC32_SETRSVSZ:
+		cmd = EXT4_IOC_SETRSVSZ;
+		break;
+	case EXT4_IOC_GROUP_ADD:
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	lock_kernel();
+	ret = ext4_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+	unlock_kernel();
+	return ret;
+}
+#endif
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
new file mode 100644
index 0000000..8b1bd03
--- /dev/null
+++ b/fs/ext4/namei.c
@@ -0,0 +1,2395 @@
+/*
+ *  linux/fs/ext4/namei.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/namei.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *  Directory entry file type support and forward compatibility hooks
+ *	for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
+ *  Hash Tree Directory indexing (c)
+ *	Daniel Phillips, 2001
+ *  Hash Tree Directory indexing porting
+ *	Christopher Li, 2002
+ *  Hash Tree Directory indexing cleanup
+ *	Theodore Ts'o, 2002
+ */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/jbd2.h>
+#include <linux/time.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/quotaops.h>
+#include <linux/buffer_head.h>
+#include <linux/bio.h>
+#include <linux/smp_lock.h>
+
+#include "namei.h"
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * define how far ahead to read directories while searching them.
+ */
+#define NAMEI_RA_CHUNKS  2
+#define NAMEI_RA_BLOCKS  4
+#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
+
+static struct buffer_head *ext4_append(handle_t *handle,
+					struct inode *inode,
+					u32 *block, int *err)
+{
+	struct buffer_head *bh;
+
+	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+
+	if ((bh = ext4_bread(handle, inode, *block, 1, err))) {
+		inode->i_size += inode->i_sb->s_blocksize;
+		EXT4_I(inode)->i_disksize = inode->i_size;
+		ext4_journal_get_write_access(handle,bh);
+	}
+	return bh;
+}
+
+#ifndef assert
+#define assert(test) J_ASSERT(test)
+#endif
+
+#ifndef swap
+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
+#endif
+
+#ifdef DX_DEBUG
+#define dxtrace(command) command
+#else
+#define dxtrace(command)
+#endif
+
+struct fake_dirent
+{
+	__le32 inode;
+	__le16 rec_len;
+	u8 name_len;
+	u8 file_type;
+};
+
+struct dx_countlimit
+{
+	__le16 limit;
+	__le16 count;
+};
+
+struct dx_entry
+{
+	__le32 hash;
+	__le32 block;
+};
+
+/*
+ * dx_root_info is laid out so that if it should somehow get overlaid by a
+ * dirent the two low bits of the hash version will be zero.  Therefore, the
+ * hash version mod 4 should never be 0.  Sincerely, the paranoia department.
+ */
+
+struct dx_root
+{
+	struct fake_dirent dot;
+	char dot_name[4];
+	struct fake_dirent dotdot;
+	char dotdot_name[4];
+	struct dx_root_info
+	{
+		__le32 reserved_zero;
+		u8 hash_version;
+		u8 info_length; /* 8 */
+		u8 indirect_levels;
+		u8 unused_flags;
+	}
+	info;
+	struct dx_entry	entries[0];
+};
+
+struct dx_node
+{
+	struct fake_dirent fake;
+	struct dx_entry	entries[0];
+};
+
+
+struct dx_frame
+{
+	struct buffer_head *bh;
+	struct dx_entry *entries;
+	struct dx_entry *at;
+};
+
+struct dx_map_entry
+{
+	u32 hash;
+	u32 offs;
+};
+
+#ifdef CONFIG_EXT4_INDEX
+static inline unsigned dx_get_block (struct dx_entry *entry);
+static void dx_set_block (struct dx_entry *entry, unsigned value);
+static inline unsigned dx_get_hash (struct dx_entry *entry);
+static void dx_set_hash (struct dx_entry *entry, unsigned value);
+static unsigned dx_get_count (struct dx_entry *entries);
+static unsigned dx_get_limit (struct dx_entry *entries);
+static void dx_set_count (struct dx_entry *entries, unsigned value);
+static void dx_set_limit (struct dx_entry *entries, unsigned value);
+static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
+static unsigned dx_node_limit (struct inode *dir);
+static struct dx_frame *dx_probe(struct dentry *dentry,
+				 struct inode *dir,
+				 struct dx_hash_info *hinfo,
+				 struct dx_frame *frame,
+				 int *err);
+static void dx_release (struct dx_frame *frames);
+static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
+			struct dx_hash_info *hinfo, struct dx_map_entry map[]);
+static void dx_sort_map(struct dx_map_entry *map, unsigned count);
+static struct ext4_dir_entry_2 *dx_move_dirents (char *from, char *to,
+		struct dx_map_entry *offsets, int count);
+static struct ext4_dir_entry_2* dx_pack_dirents (char *base, int size);
+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
+static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+				 struct dx_frame *frame,
+				 struct dx_frame *frames,
+				 __u32 *start_hash);
+static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+		       struct ext4_dir_entry_2 **res_dir, int *err);
+static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+			     struct inode *inode);
+
+/*
+ * Future: use high four bits of block for coalesce-on-delete flags
+ * Mask them off for now.
+ */
+
+static inline unsigned dx_get_block (struct dx_entry *entry)
+{
+	return le32_to_cpu(entry->block) & 0x00ffffff;
+}
+
+static inline void dx_set_block (struct dx_entry *entry, unsigned value)
+{
+	entry->block = cpu_to_le32(value);
+}
+
+static inline unsigned dx_get_hash (struct dx_entry *entry)
+{
+	return le32_to_cpu(entry->hash);
+}
+
+static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
+{
+	entry->hash = cpu_to_le32(value);
+}
+
+static inline unsigned dx_get_count (struct dx_entry *entries)
+{
+	return le16_to_cpu(((struct dx_countlimit *) entries)->count);
+}
+
+static inline unsigned dx_get_limit (struct dx_entry *entries)
+{
+	return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
+}
+
+static inline void dx_set_count (struct dx_entry *entries, unsigned value)
+{
+	((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
+}
+
+static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
+{
+	((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
+}
+
+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
+{
+	unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) -
+		EXT4_DIR_REC_LEN(2) - infosize;
+	return 0? 20: entry_space / sizeof(struct dx_entry);
+}
+
+static inline unsigned dx_node_limit (struct inode *dir)
+{
+	unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
+	return 0? 22: entry_space / sizeof(struct dx_entry);
+}
+
+/*
+ * Debug
+ */
+#ifdef DX_DEBUG
+static void dx_show_index (char * label, struct dx_entry *entries)
+{
+	int i, n = dx_get_count (entries);
+        printk("%s index ", label);
+	for (i = 0; i < n; i++) {
+		printk("%x->%u ", i? dx_get_hash(entries + i) :
+				0, dx_get_block(entries + i));
+	}
+	printk("\n");
+}
+
+struct stats
+{
+	unsigned names;
+	unsigned space;
+	unsigned bcount;
+};
+
+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_entry_2 *de,
+				 int size, int show_names)
+{
+	unsigned names = 0, space = 0;
+	char *base = (char *) de;
+	struct dx_hash_info h = *hinfo;
+
+	printk("names: ");
+	while ((char *) de < base + size)
+	{
+		if (de->inode)
+		{
+			if (show_names)
+			{
+				int len = de->name_len;
+				char *name = de->name;
+				while (len--) printk("%c", *name++);
+				ext4fs_dirhash(de->name, de->name_len, &h);
+				printk(":%x.%u ", h.hash,
+				       ((char *) de - base));
+			}
+			space += EXT4_DIR_REC_LEN(de->name_len);
+			names++;
+		}
+		de = (struct ext4_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+	}
+	printk("(%i)\n", names);
+	return (struct stats) { names, space, 1 };
+}
+
+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+			     struct dx_entry *entries, int levels)
+{
+	unsigned blocksize = dir->i_sb->s_blocksize;
+	unsigned count = dx_get_count (entries), names = 0, space = 0, i;
+	unsigned bcount = 0;
+	struct buffer_head *bh;
+	int err;
+	printk("%i indexed blocks...\n", count);
+	for (i = 0; i < count; i++, entries++)
+	{
+		u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0;
+		u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
+		struct stats stats;
+		printk("%s%3u:%03u hash %8x/%8x ",levels?"":"   ", i, block, hash, range);
+		if (!(bh = ext4_bread (NULL,dir, block, 0,&err))) continue;
+		stats = levels?
+		   dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
+		   dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0);
+		names += stats.names;
+		space += stats.space;
+		bcount += stats.bcount;
+		brelse (bh);
+	}
+	if (bcount)
+		printk("%snames %u, fullness %u (%u%%)\n", levels?"":"   ",
+			names, space/bcount,(space/bcount)*100/blocksize);
+	return (struct stats) { names, space, bcount};
+}
+#endif /* DX_DEBUG */
+
+/*
+ * Probe for a directory leaf block to search.
+ *
+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
+ * error in the directory index, and the caller should fall back to
+ * searching the directory normally.  The callers of dx_probe **MUST**
+ * check for this error code, and make sure it never gets reflected
+ * back to userspace.
+ */
+static struct dx_frame *
+dx_probe(struct dentry *dentry, struct inode *dir,
+	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+{
+	unsigned count, indirect;
+	struct dx_entry *at, *entries, *p, *q, *m;
+	struct dx_root *root;
+	struct buffer_head *bh;
+	struct dx_frame *frame = frame_in;
+	u32 hash;
+
+	frame->bh = NULL;
+	if (dentry)
+		dir = dentry->d_parent->d_inode;
+	if (!(bh = ext4_bread (NULL,dir, 0, 0, err)))
+		goto fail;
+	root = (struct dx_root *) bh->b_data;
+	if (root->info.hash_version != DX_HASH_TEA &&
+	    root->info.hash_version != DX_HASH_HALF_MD4 &&
+	    root->info.hash_version != DX_HASH_LEGACY) {
+		ext4_warning(dir->i_sb, __FUNCTION__,
+			     "Unrecognised inode hash code %d",
+			     root->info.hash_version);
+		brelse(bh);
+		*err = ERR_BAD_DX_DIR;
+		goto fail;
+	}
+	hinfo->hash_version = root->info.hash_version;
+	hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+	if (dentry)
+		ext4fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
+	hash = hinfo->hash;
+
+	if (root->info.unused_flags & 1) {
+		ext4_warning(dir->i_sb, __FUNCTION__,
+			     "Unimplemented inode hash flags: %#06x",
+			     root->info.unused_flags);
+		brelse(bh);
+		*err = ERR_BAD_DX_DIR;
+		goto fail;
+	}
+
+	if ((indirect = root->info.indirect_levels) > 1) {
+		ext4_warning(dir->i_sb, __FUNCTION__,
+			     "Unimplemented inode hash depth: %#06x",
+			     root->info.indirect_levels);
+		brelse(bh);
+		*err = ERR_BAD_DX_DIR;
+		goto fail;
+	}
+
+	entries = (struct dx_entry *) (((char *)&root->info) +
+				       root->info.info_length);
+	assert(dx_get_limit(entries) == dx_root_limit(dir,
+						      root->info.info_length));
+	dxtrace (printk("Look up %x", hash));
+	while (1)
+	{
+		count = dx_get_count(entries);
+		assert (count && count <= dx_get_limit(entries));
+		p = entries + 1;
+		q = entries + count - 1;
+		while (p <= q)
+		{
+			m = p + (q - p)/2;
+			dxtrace(printk("."));
+			if (dx_get_hash(m) > hash)
+				q = m - 1;
+			else
+				p = m + 1;
+		}
+
+		if (0) // linear search cross check
+		{
+			unsigned n = count - 1;
+			at = entries;
+			while (n--)
+			{
+				dxtrace(printk(","));
+				if (dx_get_hash(++at) > hash)
+				{
+					at--;
+					break;
+				}
+			}
+			assert (at == p - 1);
+		}
+
+		at = p - 1;
+		dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
+		frame->bh = bh;
+		frame->entries = entries;
+		frame->at = at;
+		if (!indirect--) return frame;
+		if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
+			goto fail2;
+		at = entries = ((struct dx_node *) bh->b_data)->entries;
+		assert (dx_get_limit(entries) == dx_node_limit (dir));
+		frame++;
+	}
+fail2:
+	while (frame >= frame_in) {
+		brelse(frame->bh);
+		frame--;
+	}
+fail:
+	return NULL;
+}
+
+static void dx_release (struct dx_frame *frames)
+{
+	if (frames[0].bh == NULL)
+		return;
+
+	if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
+		brelse(frames[1].bh);
+	brelse(frames[0].bh);
+}
+
+/*
+ * This function increments the frame pointer to search the next leaf
+ * block, and reads in the necessary intervening nodes if the search
+ * should be necessary.  Whether or not the search is necessary is
+ * controlled by the hash parameter.  If the hash value is even, then
+ * the search is only continued if the next block starts with that
+ * hash value.  This is used if we are searching for a specific file.
+ *
+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block.
+ *
+ * This function returns 1 if the caller should continue to search,
+ * or 0 if it should not.  If there is an error reading one of the
+ * index blocks, it will a negative error code.
+ *
+ * If start_hash is non-null, it will be filled in with the starting
+ * hash of the next page.
+ */
+static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+				 struct dx_frame *frame,
+				 struct dx_frame *frames,
+				 __u32 *start_hash)
+{
+	struct dx_frame *p;
+	struct buffer_head *bh;
+	int err, num_frames = 0;
+	__u32 bhash;
+
+	p = frame;
+	/*
+	 * Find the next leaf page by incrementing the frame pointer.
+	 * If we run out of entries in the interior node, loop around and
+	 * increment pointer in the parent node.  When we break out of
+	 * this loop, num_frames indicates the number of interior
+	 * nodes need to be read.
+	 */
+	while (1) {
+		if (++(p->at) < p->entries + dx_get_count(p->entries))
+			break;
+		if (p == frames)
+			return 0;
+		num_frames++;
+		p--;
+	}
+
+	/*
+	 * If the hash is 1, then continue only if the next page has a
+	 * continuation hash of any value.  This is used for readdir
+	 * handling.  Otherwise, check to see if the hash matches the
+	 * desired contiuation hash.  If it doesn't, return since
+	 * there's no point to read in the successive index pages.
+	 */
+	bhash = dx_get_hash(p->at);
+	if (start_hash)
+		*start_hash = bhash;
+	if ((hash & 1) == 0) {
+		if ((bhash & ~1) != hash)
+			return 0;
+	}
+	/*
+	 * If the hash is HASH_NB_ALWAYS, we always go to the next
+	 * block so no check is necessary
+	 */
+	while (num_frames--) {
+		if (!(bh = ext4_bread(NULL, dir, dx_get_block(p->at),
+				      0, &err)))
+			return err; /* Failure */
+		p++;
+		brelse (p->bh);
+		p->bh = bh;
+		p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
+	}
+	return 1;
+}
+
+
+/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ext4_dir_entry_2 *ext4_next_entry(struct ext4_dir_entry_2 *p)
+{
+	return (struct ext4_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
+}
+
+/*
+ * This function fills a red-black tree with information from a
+ * directory block.  It returns the number directory entries loaded
+ * into the tree.  If there is an error it is returned in err.
+ */
+static int htree_dirblock_to_tree(struct file *dir_file,
+				  struct inode *dir, int block,
+				  struct dx_hash_info *hinfo,
+				  __u32 start_hash, __u32 start_minor_hash)
+{
+	struct buffer_head *bh;
+	struct ext4_dir_entry_2 *de, *top;
+	int err, count = 0;
+
+	dxtrace(printk("In htree dirblock_to_tree: block %d\n", block));
+	if (!(bh = ext4_bread (NULL, dir, block, 0, &err)))
+		return err;
+
+	de = (struct ext4_dir_entry_2 *) bh->b_data;
+	top = (struct ext4_dir_entry_2 *) ((char *) de +
+					   dir->i_sb->s_blocksize -
+					   EXT4_DIR_REC_LEN(0));
+	for (; de < top; de = ext4_next_entry(de)) {
+		ext4fs_dirhash(de->name, de->name_len, hinfo);
+		if ((hinfo->hash < start_hash) ||
+		    ((hinfo->hash == start_hash) &&
+		     (hinfo->minor_hash < start_minor_hash)))
+			continue;
+		if (de->inode == 0)
+			continue;
+		if ((err = ext4_htree_store_dirent(dir_file,
+				   hinfo->hash, hinfo->minor_hash, de)) != 0) {
+			brelse(bh);
+			return err;
+		}
+		count++;
+	}
+	brelse(bh);
+	return count;
+}
+
+
+/*
+ * This function fills a red-black tree with information from a
+ * directory.  We start scanning the directory in hash order, starting
+ * at start_hash and start_minor_hash.
+ *
+ * This function returns the number of entries inserted into the tree,
+ * or a negative error code.
+ */
+int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+			 __u32 start_minor_hash, __u32 *next_hash)
+{
+	struct dx_hash_info hinfo;
+	struct ext4_dir_entry_2 *de;
+	struct dx_frame frames[2], *frame;
+	struct inode *dir;
+	int block, err;
+	int count = 0;
+	int ret;
+	__u32 hashval;
+
+	dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
+		       start_minor_hash));
+	dir = dir_file->f_dentry->d_inode;
+	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
+		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
+		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
+					       start_hash, start_minor_hash);
+		*next_hash = ~0;
+		return count;
+	}
+	hinfo.hash = start_hash;
+	hinfo.minor_hash = 0;
+	frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
+	if (!frame)
+		return err;
+
+	/* Add '.' and '..' from the htree header */
+	if (!start_hash && !start_minor_hash) {
+		de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
+		if ((err = ext4_htree_store_dirent(dir_file, 0, 0, de)) != 0)
+			goto errout;
+		count++;
+	}
+	if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
+		de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
+		de = ext4_next_entry(de);
+		if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0)
+			goto errout;
+		count++;
+	}
+
+	while (1) {
+		block = dx_get_block(frame->at);
+		ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
+					     start_hash, start_minor_hash);
+		if (ret < 0) {
+			err = ret;
+			goto errout;
+		}
+		count += ret;
+		hashval = ~0;
+		ret = ext4_htree_next_block(dir, HASH_NB_ALWAYS,
+					    frame, frames, &hashval);
+		*next_hash = hashval;
+		if (ret < 0) {
+			err = ret;
+			goto errout;
+		}
+		/*
+		 * Stop if:  (a) there are no more entries, or
+		 * (b) we have inserted at least one entry and the
+		 * next hash value is not a continuation
+		 */
+		if ((ret == 0) ||
+		    (count && ((hashval & 1) == 0)))
+			break;
+	}
+	dx_release(frames);
+	dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n",
+		       count, *next_hash));
+	return count;
+errout:
+	dx_release(frames);
+	return (err);
+}
+
+
+/*
+ * Directory block splitting, compacting
+ */
+
+static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
+			struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
+{
+	int count = 0;
+	char *base = (char *) de;
+	struct dx_hash_info h = *hinfo;
+
+	while ((char *) de < base + size)
+	{
+		if (de->name_len && de->inode) {
+			ext4fs_dirhash(de->name, de->name_len, &h);
+			map_tail--;
+			map_tail->hash = h.hash;
+			map_tail->offs = (u32) ((char *) de - base);
+			count++;
+			cond_resched();
+		}
+		/* XXX: do we need to check rec_len == 0 case? -Chris */
+		de = (struct ext4_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+	}
+	return count;
+}
+
+static void dx_sort_map (struct dx_map_entry *map, unsigned count)
+{
+	struct dx_map_entry *p, *q, *top = map + count - 1;
+	int more;
+	/* Combsort until bubble sort doesn't suck */
+	while (count > 2) {
+		count = count*10/13;
+		if (count - 9 < 2) /* 9, 10 -> 11 */
+			count = 11;
+		for (p = top, q = p - count; q >= map; p--, q--)
+			if (p->hash < q->hash)
+				swap(*p, *q);
+	}
+	/* Garden variety bubble sort */
+	do {
+		more = 0;
+		q = top;
+		while (q-- > map) {
+			if (q[1].hash >= q[0].hash)
+				continue;
+			swap(*(q+1), *q);
+			more = 1;
+		}
+	} while(more);
+}
+
+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
+{
+	struct dx_entry *entries = frame->entries;
+	struct dx_entry *old = frame->at, *new = old + 1;
+	int count = dx_get_count(entries);
+
+	assert(count < dx_get_limit(entries));
+	assert(old < entries + count);
+	memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
+	dx_set_hash(new, hash);
+	dx_set_block(new, block);
+	dx_set_count(entries, count + 1);
+}
+#endif
+
+
+static void ext4_update_dx_flag(struct inode *inode)
+{
+	if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				     EXT4_FEATURE_COMPAT_DIR_INDEX))
+		EXT4_I(inode)->i_flags &= ~EXT4_INDEX_FL;
+}
+
+/*
+ * NOTE! unlike strncmp, ext4_match returns 1 for success, 0 for failure.
+ *
+ * `len <= EXT4_NAME_LEN' is guaranteed by caller.
+ * `de != NULL' is guaranteed by caller.
+ */
+static inline int ext4_match (int len, const char * const name,
+			      struct ext4_dir_entry_2 * de)
+{
+	if (len != de->name_len)
+		return 0;
+	if (!de->inode)
+		return 0;
+	return !memcmp(name, de->name, len);
+}
+
+/*
+ * Returns 0 if not found, -1 on failure, and 1 on success
+ */
+static inline int search_dirblock(struct buffer_head * bh,
+				  struct inode *dir,
+				  struct dentry *dentry,
+				  unsigned long offset,
+				  struct ext4_dir_entry_2 ** res_dir)
+{
+	struct ext4_dir_entry_2 * de;
+	char * dlimit;
+	int de_len;
+	const char *name = dentry->d_name.name;
+	int namelen = dentry->d_name.len;
+
+	de = (struct ext4_dir_entry_2 *) bh->b_data;
+	dlimit = bh->b_data + dir->i_sb->s_blocksize;
+	while ((char *) de < dlimit) {
+		/* this code is executed quadratically often */
+		/* do minimal checking `by hand' */
+
+		if ((char *) de + namelen <= dlimit &&
+		    ext4_match (namelen, name, de)) {
+			/* found a match - just to be sure, do a full check */
+			if (!ext4_check_dir_entry("ext4_find_entry",
+						  dir, de, bh, offset))
+				return -1;
+			*res_dir = de;
+			return 1;
+		}
+		/* prevent looping on a bad block */
+		de_len = le16_to_cpu(de->rec_len);
+		if (de_len <= 0)
+			return -1;
+		offset += de_len;
+		de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);
+	}
+	return 0;
+}
+
+
+/*
+ *	ext4_find_entry()
+ *
+ * finds an entry in the specified directory with the wanted name. It
+ * returns the cache buffer in which the entry was found, and the entry
+ * itself (as a parameter - res_dir). It does NOT read the inode of the
+ * entry - you'll have to do that yourself if you want to.
+ *
+ * The returned buffer_head has ->b_count elevated.  The caller is expected
+ * to brelse() it when appropriate.
+ */
+static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+					struct ext4_dir_entry_2 ** res_dir)
+{
+	struct super_block * sb;
+	struct buffer_head * bh_use[NAMEI_RA_SIZE];
+	struct buffer_head * bh, *ret = NULL;
+	unsigned long start, block, b;
+	int ra_max = 0;		/* Number of bh's in the readahead
+				   buffer, bh_use[] */
+	int ra_ptr = 0;		/* Current index into readahead
+				   buffer */
+	int num = 0;
+	int nblocks, i, err;
+	struct inode *dir = dentry->d_parent->d_inode;
+	int namelen;
+	const u8 *name;
+	unsigned blocksize;
+
+	*res_dir = NULL;
+	sb = dir->i_sb;
+	blocksize = sb->s_blocksize;
+	namelen = dentry->d_name.len;
+	name = dentry->d_name.name;
+	if (namelen > EXT4_NAME_LEN)
+		return NULL;
+#ifdef CONFIG_EXT4_INDEX
+	if (is_dx(dir)) {
+		bh = ext4_dx_find_entry(dentry, res_dir, &err);
+		/*
+		 * On success, or if the error was file not found,
+		 * return.  Otherwise, fall back to doing a search the
+		 * old fashioned way.
+		 */
+		if (bh || (err != ERR_BAD_DX_DIR))
+			return bh;
+		dxtrace(printk("ext4_find_entry: dx failed, falling back\n"));
+	}
+#endif
+	nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb);
+	start = EXT4_I(dir)->i_dir_start_lookup;
+	if (start >= nblocks)
+		start = 0;
+	block = start;
+restart:
+	do {
+		/*
+		 * We deal with the read-ahead logic here.
+		 */
+		if (ra_ptr >= ra_max) {
+			/* Refill the readahead buffer */
+			ra_ptr = 0;
+			b = block;
+			for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
+				/*
+				 * Terminate if we reach the end of the
+				 * directory and must wrap, or if our
+				 * search has finished at this block.
+				 */
+				if (b >= nblocks || (num && block == start)) {
+					bh_use[ra_max] = NULL;
+					break;
+				}
+				num++;
+				bh = ext4_getblk(NULL, dir, b++, 0, &err);
+				bh_use[ra_max] = bh;
+				if (bh)
+					ll_rw_block(READ_META, 1, &bh);
+			}
+		}
+		if ((bh = bh_use[ra_ptr++]) == NULL)
+			goto next;
+		wait_on_buffer(bh);
+		if (!buffer_uptodate(bh)) {
+			/* read error, skip block & hope for the best */
+			ext4_error(sb, __FUNCTION__, "reading directory #%lu "
+				   "offset %lu", dir->i_ino, block);
+			brelse(bh);
+			goto next;
+		}
+		i = search_dirblock(bh, dir, dentry,
+			    block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
+		if (i == 1) {
+			EXT4_I(dir)->i_dir_start_lookup = block;
+			ret = bh;
+			goto cleanup_and_exit;
+		} else {
+			brelse(bh);
+			if (i < 0)
+				goto cleanup_and_exit;
+		}
+	next:
+		if (++block >= nblocks)
+			block = 0;
+	} while (block != start);
+
+	/*
+	 * If the directory has grown while we were searching, then
+	 * search the last part of the directory before giving up.
+	 */
+	block = nblocks;
+	nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb);
+	if (block < nblocks) {
+		start = 0;
+		goto restart;
+	}
+
+cleanup_and_exit:
+	/* Clean up the read-ahead blocks */
+	for (; ra_ptr < ra_max; ra_ptr++)
+		brelse (bh_use[ra_ptr]);
+	return ret;
+}
+
+#ifdef CONFIG_EXT4_INDEX
+static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+		       struct ext4_dir_entry_2 **res_dir, int *err)
+{
+	struct super_block * sb;
+	struct dx_hash_info	hinfo;
+	u32 hash;
+	struct dx_frame frames[2], *frame;
+	struct ext4_dir_entry_2 *de, *top;
+	struct buffer_head *bh;
+	unsigned long block;
+	int retval;
+	int namelen = dentry->d_name.len;
+	const u8 *name = dentry->d_name.name;
+	struct inode *dir = dentry->d_parent->d_inode;
+
+	sb = dir->i_sb;
+	/* NFS may look up ".." - look at dx_root directory block */
+	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
+		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
+			return NULL;
+	} else {
+		frame = frames;
+		frame->bh = NULL;			/* for dx_release() */
+		frame->at = (struct dx_entry *)frames;	/* hack for zero entry*/
+		dx_set_block(frame->at, 0);		/* dx_root block is 0 */
+	}
+	hash = hinfo.hash;
+	do {
+		block = dx_get_block(frame->at);
+		if (!(bh = ext4_bread (NULL,dir, block, 0, err)))
+			goto errout;
+		de = (struct ext4_dir_entry_2 *) bh->b_data;
+		top = (struct ext4_dir_entry_2 *) ((char *) de + sb->s_blocksize -
+				       EXT4_DIR_REC_LEN(0));
+		for (; de < top; de = ext4_next_entry(de))
+		if (ext4_match (namelen, name, de)) {
+			if (!ext4_check_dir_entry("ext4_find_entry",
+						  dir, de, bh,
+				  (block<<EXT4_BLOCK_SIZE_BITS(sb))
+					  +((char *)de - bh->b_data))) {
+				brelse (bh);
+				goto errout;
+			}
+			*res_dir = de;
+			dx_release (frames);
+			return bh;
+		}
+		brelse (bh);
+		/* Check to see if we should continue to search */
+		retval = ext4_htree_next_block(dir, hash, frame,
+					       frames, NULL);
+		if (retval < 0) {
+			ext4_warning(sb, __FUNCTION__,
+			     "error reading index page in directory #%lu",
+			     dir->i_ino);
+			*err = retval;
+			goto errout;
+		}
+	} while (retval == 1);
+
+	*err = -ENOENT;
+errout:
+	dxtrace(printk("%s not found\n", name));
+	dx_release (frames);
+	return NULL;
+}
+#endif
+
+static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+{
+	struct inode * inode;
+	struct ext4_dir_entry_2 * de;
+	struct buffer_head * bh;
+
+	if (dentry->d_name.len > EXT4_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	bh = ext4_find_entry(dentry, &de);
+	inode = NULL;
+	if (bh) {
+		unsigned long ino = le32_to_cpu(de->inode);
+		brelse (bh);
+		if (!ext4_valid_inum(dir->i_sb, ino)) {
+			ext4_error(dir->i_sb, "ext4_lookup",
+				   "bad inode number: %lu", ino);
+			inode = NULL;
+		} else
+			inode = iget(dir->i_sb, ino);
+
+		if (!inode)
+			return ERR_PTR(-EACCES);
+	}
+	return d_splice_alias(inode, dentry);
+}
+
+
+struct dentry *ext4_get_parent(struct dentry *child)
+{
+	unsigned long ino;
+	struct dentry *parent;
+	struct inode *inode;
+	struct dentry dotdot;
+	struct ext4_dir_entry_2 * de;
+	struct buffer_head *bh;
+
+	dotdot.d_name.name = "..";
+	dotdot.d_name.len = 2;
+	dotdot.d_parent = child; /* confusing, isn't it! */
+
+	bh = ext4_find_entry(&dotdot, &de);
+	inode = NULL;
+	if (!bh)
+		return ERR_PTR(-ENOENT);
+	ino = le32_to_cpu(de->inode);
+	brelse(bh);
+
+	if (!ext4_valid_inum(child->d_inode->i_sb, ino)) {
+		ext4_error(child->d_inode->i_sb, "ext4_get_parent",
+			   "bad inode number: %lu", ino);
+		inode = NULL;
+	} else
+		inode = iget(child->d_inode->i_sb, ino);
+
+	if (!inode)
+		return ERR_PTR(-EACCES);
+
+	parent = d_alloc_anon(inode);
+	if (!parent) {
+		iput(inode);
+		parent = ERR_PTR(-ENOMEM);
+	}
+	return parent;
+}
+
+#define S_SHIFT 12
+static unsigned char ext4_type_by_mode[S_IFMT >> S_SHIFT] = {
+	[S_IFREG >> S_SHIFT]	= EXT4_FT_REG_FILE,
+	[S_IFDIR >> S_SHIFT]	= EXT4_FT_DIR,
+	[S_IFCHR >> S_SHIFT]	= EXT4_FT_CHRDEV,
+	[S_IFBLK >> S_SHIFT]	= EXT4_FT_BLKDEV,
+	[S_IFIFO >> S_SHIFT]	= EXT4_FT_FIFO,
+	[S_IFSOCK >> S_SHIFT]	= EXT4_FT_SOCK,
+	[S_IFLNK >> S_SHIFT]	= EXT4_FT_SYMLINK,
+};
+
+static inline void ext4_set_de_type(struct super_block *sb,
+				struct ext4_dir_entry_2 *de,
+				umode_t mode) {
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FILETYPE))
+		de->file_type = ext4_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
+}
+
+#ifdef CONFIG_EXT4_INDEX
+static struct ext4_dir_entry_2 *
+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
+{
+	unsigned rec_len = 0;
+
+	while (count--) {
+		struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *) (from + map->offs);
+		rec_len = EXT4_DIR_REC_LEN(de->name_len);
+		memcpy (to, de, rec_len);
+		((struct ext4_dir_entry_2 *) to)->rec_len =
+				cpu_to_le16(rec_len);
+		de->inode = 0;
+		map++;
+		to += rec_len;
+	}
+	return (struct ext4_dir_entry_2 *) (to - rec_len);
+}
+
+static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
+{
+	struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
+	unsigned rec_len = 0;
+
+	prev = to = de;
+	while ((char*)de < base + size) {
+		next = (struct ext4_dir_entry_2 *) ((char *) de +
+						    le16_to_cpu(de->rec_len));
+		if (de->inode && de->name_len) {
+			rec_len = EXT4_DIR_REC_LEN(de->name_len);
+			if (de > to)
+				memmove(to, de, rec_len);
+			to->rec_len = cpu_to_le16(rec_len);
+			prev = to;
+			to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len);
+		}
+		de = next;
+	}
+	return prev;
+}
+
+static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+			struct buffer_head **bh,struct dx_frame *frame,
+			struct dx_hash_info *hinfo, int *error)
+{
+	unsigned blocksize = dir->i_sb->s_blocksize;
+	unsigned count, continued;
+	struct buffer_head *bh2;
+	u32 newblock;
+	u32 hash2;
+	struct dx_map_entry *map;
+	char *data1 = (*bh)->b_data, *data2;
+	unsigned split;
+	struct ext4_dir_entry_2 *de = NULL, *de2;
+	int	err;
+
+	bh2 = ext4_append (handle, dir, &newblock, error);
+	if (!(bh2)) {
+		brelse(*bh);
+		*bh = NULL;
+		goto errout;
+	}
+
+	BUFFER_TRACE(*bh, "get_write_access");
+	err = ext4_journal_get_write_access(handle, *bh);
+	if (err) {
+	journal_error:
+		brelse(*bh);
+		brelse(bh2);
+		*bh = NULL;
+		ext4_std_error(dir->i_sb, err);
+		goto errout;
+	}
+	BUFFER_TRACE(frame->bh, "get_write_access");
+	err = ext4_journal_get_write_access(handle, frame->bh);
+	if (err)
+		goto journal_error;
+
+	data2 = bh2->b_data;
+
+	/* create map in the end of data2 block */
+	map = (struct dx_map_entry *) (data2 + blocksize);
+	count = dx_make_map ((struct ext4_dir_entry_2 *) data1,
+			     blocksize, hinfo, map);
+	map -= count;
+	split = count/2; // need to adjust to actual middle
+	dx_sort_map (map, count);
+	hash2 = map[split].hash;
+	continued = hash2 == map[split - 1].hash;
+	dxtrace(printk("Split block %i at %x, %i/%i\n",
+		dx_get_block(frame->at), hash2, split, count-split));
+
+	/* Fancy dance to stay within two buffers */
+	de2 = dx_move_dirents(data1, data2, map + split, count - split);
+	de = dx_pack_dirents(data1,blocksize);
+	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+	de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+	dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1));
+	dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
+
+	/* Which block gets the new entry? */
+	if (hinfo->hash >= hash2)
+	{
+		swap(*bh, bh2);
+		de = de2;
+	}
+	dx_insert_block (frame, hash2 + continued, newblock);
+	err = ext4_journal_dirty_metadata (handle, bh2);
+	if (err)
+		goto journal_error;
+	err = ext4_journal_dirty_metadata (handle, frame->bh);
+	if (err)
+		goto journal_error;
+	brelse (bh2);
+	dxtrace(dx_show_index ("frame", frame->entries));
+errout:
+	return de;
+}
+#endif
+
+
+/*
+ * Add a new entry into a directory (leaf) block.  If de is non-NULL,
+ * it points to a directory entry which is guaranteed to be large
+ * enough for new directory entry.  If de is NULL, then
+ * add_dirent_to_buf will attempt search the directory block for
+ * space.  It will return -ENOSPC if no space is available, and -EIO
+ * and -EEXIST if directory entry already exists.
+ *
+ * NOTE!  bh is NOT released in the case where ENOSPC is returned.  In
+ * all other cases bh is released.
+ */
+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+			     struct inode *inode, struct ext4_dir_entry_2 *de,
+			     struct buffer_head * bh)
+{
+	struct inode	*dir = dentry->d_parent->d_inode;
+	const char	*name = dentry->d_name.name;
+	int		namelen = dentry->d_name.len;
+	unsigned long	offset = 0;
+	unsigned short	reclen;
+	int		nlen, rlen, err;
+	char		*top;
+
+	reclen = EXT4_DIR_REC_LEN(namelen);
+	if (!de) {
+		de = (struct ext4_dir_entry_2 *)bh->b_data;
+		top = bh->b_data + dir->i_sb->s_blocksize - reclen;
+		while ((char *) de <= top) {
+			if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
+						  bh, offset)) {
+				brelse (bh);
+				return -EIO;
+			}
+			if (ext4_match (namelen, name, de)) {
+				brelse (bh);
+				return -EEXIST;
+			}
+			nlen = EXT4_DIR_REC_LEN(de->name_len);
+			rlen = le16_to_cpu(de->rec_len);
+			if ((de->inode? rlen - nlen: rlen) >= reclen)
+				break;
+			de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
+			offset += rlen;
+		}
+		if ((char *) de > top)
+			return -ENOSPC;
+	}
+	BUFFER_TRACE(bh, "get_write_access");
+	err = ext4_journal_get_write_access(handle, bh);
+	if (err) {
+		ext4_std_error(dir->i_sb, err);
+		brelse(bh);
+		return err;
+	}
+
+	/* By now the buffer is marked for journaling */
+	nlen = EXT4_DIR_REC_LEN(de->name_len);
+	rlen = le16_to_cpu(de->rec_len);
+	if (de->inode) {
+		struct ext4_dir_entry_2 *de1 = (struct ext4_dir_entry_2 *)((char *)de + nlen);
+		de1->rec_len = cpu_to_le16(rlen - nlen);
+		de->rec_len = cpu_to_le16(nlen);
+		de = de1;
+	}
+	de->file_type = EXT4_FT_UNKNOWN;
+	if (inode) {
+		de->inode = cpu_to_le32(inode->i_ino);
+		ext4_set_de_type(dir->i_sb, de, inode->i_mode);
+	} else
+		de->inode = 0;
+	de->name_len = namelen;
+	memcpy (de->name, name, namelen);
+	/*
+	 * XXX shouldn't update any times until successful
+	 * completion of syscall, but too many callers depend
+	 * on this.
+	 *
+	 * XXX similarly, too many callers depend on
+	 * ext4_new_inode() setting the times, but error
+	 * recovery deletes the inode, so the worst that can
+	 * happen is that the times are slightly out of date
+	 * and/or different from the directory change time.
+	 */
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+	ext4_update_dx_flag(dir);
+	dir->i_version++;
+	ext4_mark_inode_dirty(handle, dir);
+	BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+	err = ext4_journal_dirty_metadata(handle, bh);
+	if (err)
+		ext4_std_error(dir->i_sb, err);
+	brelse(bh);
+	return 0;
+}
+
+#ifdef CONFIG_EXT4_INDEX
+/*
+ * This converts a one block unindexed directory to a 3 block indexed
+ * directory, and adds the dentry to the indexed directory.
+ */
+static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+			    struct inode *inode, struct buffer_head *bh)
+{
+	struct inode	*dir = dentry->d_parent->d_inode;
+	const char	*name = dentry->d_name.name;
+	int		namelen = dentry->d_name.len;
+	struct buffer_head *bh2;
+	struct dx_root	*root;
+	struct dx_frame	frames[2], *frame;
+	struct dx_entry *entries;
+	struct ext4_dir_entry_2	*de, *de2;
+	char		*data1, *top;
+	unsigned	len;
+	int		retval;
+	unsigned	blocksize;
+	struct dx_hash_info hinfo;
+	u32		block;
+	struct fake_dirent *fde;
+
+	blocksize =  dir->i_sb->s_blocksize;
+	dxtrace(printk("Creating index\n"));
+	retval = ext4_journal_get_write_access(handle, bh);
+	if (retval) {
+		ext4_std_error(dir->i_sb, retval);
+		brelse(bh);
+		return retval;
+	}
+	root = (struct dx_root *) bh->b_data;
+
+	bh2 = ext4_append (handle, dir, &block, &retval);
+	if (!(bh2)) {
+		brelse(bh);
+		return retval;
+	}
+	EXT4_I(dir)->i_flags |= EXT4_INDEX_FL;
+	data1 = bh2->b_data;
+
+	/* The 0th block becomes the root, move the dirents out */
+	fde = &root->dotdot;
+	de = (struct ext4_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
+	len = ((char *) root) + blocksize - (char *) de;
+	memcpy (data1, de, len);
+	de = (struct ext4_dir_entry_2 *) data1;
+	top = data1 + len;
+	while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
+		de = de2;
+	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+	/* Initialize the root; the dot dirents already exist */
+	de = (struct ext4_dir_entry_2 *) (&root->dotdot);
+	de->rec_len = cpu_to_le16(blocksize - EXT4_DIR_REC_LEN(2));
+	memset (&root->info, 0, sizeof(root->info));
+	root->info.info_length = sizeof(root->info);
+	root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
+	entries = root->entries;
+	dx_set_block (entries, 1);
+	dx_set_count (entries, 1);
+	dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
+
+	/* Initialize as for dx_probe */
+	hinfo.hash_version = root->info.hash_version;
+	hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+	ext4fs_dirhash(name, namelen, &hinfo);
+	frame = frames;
+	frame->entries = entries;
+	frame->at = entries;
+	frame->bh = bh;
+	bh = bh2;
+	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
+	dx_release (frames);
+	if (!(de))
+		return retval;
+
+	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+}
+#endif
+
+/*
+ *	ext4_add_entry()
+ *
+ * adds a file entry to the specified directory, using the same
+ * semantics as ext4_find_entry(). It returns NULL if it failed.
+ *
+ * NOTE!! The inode part of 'de' is left at 0 - which means you
+ * may not sleep between calling this and putting something into
+ * the entry, as someone else might have used it while you slept.
+ */
+static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
+	struct inode *inode)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+	unsigned long offset;
+	struct buffer_head * bh;
+	struct ext4_dir_entry_2 *de;
+	struct super_block * sb;
+	int	retval;
+#ifdef CONFIG_EXT4_INDEX
+	int	dx_fallback=0;
+#endif
+	unsigned blocksize;
+	u32 block, blocks;
+
+	sb = dir->i_sb;
+	blocksize = sb->s_blocksize;
+	if (!dentry->d_name.len)
+		return -EINVAL;
+#ifdef CONFIG_EXT4_INDEX
+	if (is_dx(dir)) {
+		retval = ext4_dx_add_entry(handle, dentry, inode);
+		if (!retval || (retval != ERR_BAD_DX_DIR))
+			return retval;
+		EXT4_I(dir)->i_flags &= ~EXT4_INDEX_FL;
+		dx_fallback++;
+		ext4_mark_inode_dirty(handle, dir);
+	}
+#endif
+	blocks = dir->i_size >> sb->s_blocksize_bits;
+	for (block = 0, offset = 0; block < blocks; block++) {
+		bh = ext4_bread(handle, dir, block, 0, &retval);
+		if(!bh)
+			return retval;
+		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+		if (retval != -ENOSPC)
+			return retval;
+
+#ifdef CONFIG_EXT4_INDEX
+		if (blocks == 1 && !dx_fallback &&
+		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
+			return make_indexed_dir(handle, dentry, inode, bh);
+#endif
+		brelse(bh);
+	}
+	bh = ext4_append(handle, dir, &block, &retval);
+	if (!bh)
+		return retval;
+	de = (struct ext4_dir_entry_2 *) bh->b_data;
+	de->inode = 0;
+	de->rec_len = cpu_to_le16(blocksize);
+	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+}
+
+#ifdef CONFIG_EXT4_INDEX
+/*
+ * Returns 0 for success, or a negative error value
+ */
+static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+			     struct inode *inode)
+{
+	struct dx_frame frames[2], *frame;
+	struct dx_entry *entries, *at;
+	struct dx_hash_info hinfo;
+	struct buffer_head * bh;
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct super_block * sb = dir->i_sb;
+	struct ext4_dir_entry_2 *de;
+	int err;
+
+	frame = dx_probe(dentry, NULL, &hinfo, frames, &err);
+	if (!frame)
+		return err;
+	entries = frame->entries;
+	at = frame->at;
+
+	if (!(bh = ext4_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
+		goto cleanup;
+
+	BUFFER_TRACE(bh, "get_write_access");
+	err = ext4_journal_get_write_access(handle, bh);
+	if (err)
+		goto journal_error;
+
+	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+	if (err != -ENOSPC) {
+		bh = NULL;
+		goto cleanup;
+	}
+
+	/* Block full, should compress but for now just split */
+	dxtrace(printk("using %u of %u node entries\n",
+		       dx_get_count(entries), dx_get_limit(entries)));
+	/* Need to split index? */
+	if (dx_get_count(entries) == dx_get_limit(entries)) {
+		u32 newblock;
+		unsigned icount = dx_get_count(entries);
+		int levels = frame - frames;
+		struct dx_entry *entries2;
+		struct dx_node *node2;
+		struct buffer_head *bh2;
+
+		if (levels && (dx_get_count(frames->entries) ==
+			       dx_get_limit(frames->entries))) {
+			ext4_warning(sb, __FUNCTION__,
+				     "Directory index full!");
+			err = -ENOSPC;
+			goto cleanup;
+		}
+		bh2 = ext4_append (handle, dir, &newblock, &err);
+		if (!(bh2))
+			goto cleanup;
+		node2 = (struct dx_node *)(bh2->b_data);
+		entries2 = node2->entries;
+		node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+		node2->fake.inode = 0;
+		BUFFER_TRACE(frame->bh, "get_write_access");
+		err = ext4_journal_get_write_access(handle, frame->bh);
+		if (err)
+			goto journal_error;
+		if (levels) {
+			unsigned icount1 = icount/2, icount2 = icount - icount1;
+			unsigned hash2 = dx_get_hash(entries + icount1);
+			dxtrace(printk("Split index %i/%i\n", icount1, icount2));
+
+			BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
+			err = ext4_journal_get_write_access(handle,
+							     frames[0].bh);
+			if (err)
+				goto journal_error;
+
+			memcpy ((char *) entries2, (char *) (entries + icount1),
+				icount2 * sizeof(struct dx_entry));
+			dx_set_count (entries, icount1);
+			dx_set_count (entries2, icount2);
+			dx_set_limit (entries2, dx_node_limit(dir));
+
+			/* Which index block gets the new entry? */
+			if (at - entries >= icount1) {
+				frame->at = at = at - entries - icount1 + entries2;
+				frame->entries = entries = entries2;
+				swap(frame->bh, bh2);
+			}
+			dx_insert_block (frames + 0, hash2, newblock);
+			dxtrace(dx_show_index ("node", frames[1].entries));
+			dxtrace(dx_show_index ("node",
+			       ((struct dx_node *) bh2->b_data)->entries));
+			err = ext4_journal_dirty_metadata(handle, bh2);
+			if (err)
+				goto journal_error;
+			brelse (bh2);
+		} else {
+			dxtrace(printk("Creating second level index...\n"));
+			memcpy((char *) entries2, (char *) entries,
+			       icount * sizeof(struct dx_entry));
+			dx_set_limit(entries2, dx_node_limit(dir));
+
+			/* Set up root */
+			dx_set_count(entries, 1);
+			dx_set_block(entries + 0, newblock);
+			((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
+
+			/* Add new access path frame */
+			frame = frames + 1;
+			frame->at = at = at - entries + entries2;
+			frame->entries = entries = entries2;
+			frame->bh = bh2;
+			err = ext4_journal_get_write_access(handle,
+							     frame->bh);
+			if (err)
+				goto journal_error;
+		}
+		ext4_journal_dirty_metadata(handle, frames[0].bh);
+	}
+	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
+	if (!de)
+		goto cleanup;
+	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
+	bh = NULL;
+	goto cleanup;
+
+journal_error:
+	ext4_std_error(dir->i_sb, err);
+cleanup:
+	if (bh)
+		brelse(bh);
+	dx_release(frames);
+	return err;
+}
+#endif
+
+/*
+ * ext4_delete_entry deletes a directory entry by merging it with the
+ * previous entry
+ */
+static int ext4_delete_entry (handle_t *handle,
+			      struct inode * dir,
+			      struct ext4_dir_entry_2 * de_del,
+			      struct buffer_head * bh)
+{
+	struct ext4_dir_entry_2 * de, * pde;
+	int i;
+
+	i = 0;
+	pde = NULL;
+	de = (struct ext4_dir_entry_2 *) bh->b_data;
+	while (i < bh->b_size) {
+		if (!ext4_check_dir_entry("ext4_delete_entry", dir, de, bh, i))
+			return -EIO;
+		if (de == de_del)  {
+			BUFFER_TRACE(bh, "get_write_access");
+			ext4_journal_get_write_access(handle, bh);
+			if (pde)
+				pde->rec_len =
+					cpu_to_le16(le16_to_cpu(pde->rec_len) +
+						    le16_to_cpu(de->rec_len));
+			else
+				de->inode = 0;
+			dir->i_version++;
+			BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+			ext4_journal_dirty_metadata(handle, bh);
+			return 0;
+		}
+		i += le16_to_cpu(de->rec_len);
+		pde = de;
+		de = (struct ext4_dir_entry_2 *)
+			((char *) de + le16_to_cpu(de->rec_len));
+	}
+	return -ENOENT;
+}
+
+/*
+ * ext4_mark_inode_dirty is somewhat expensive, so unlike ext2 we
+ * do not perform it in these functions.  We perform it at the call site,
+ * if it is needed.
+ */
+static inline void ext4_inc_count(handle_t *handle, struct inode *inode)
+{
+	inc_nlink(inode);
+}
+
+static inline void ext4_dec_count(handle_t *handle, struct inode *inode)
+{
+	drop_nlink(inode);
+}
+
+static int ext4_add_nondir(handle_t *handle,
+		struct dentry *dentry, struct inode *inode)
+{
+	int err = ext4_add_entry(handle, dentry, inode);
+	if (!err) {
+		ext4_mark_inode_dirty(handle, inode);
+		d_instantiate(dentry, inode);
+		return 0;
+	}
+	ext4_dec_count(handle, inode);
+	iput(inode);
+	return err;
+}
+
+/*
+ * By the time this is called, we already have created
+ * the directory cache entry for the new file, but it
+ * is so far negative - it has no inode.
+ *
+ * If the create succeeds, we fill in the inode information
+ * with d_instantiate().
+ */
+static int ext4_create (struct inode * dir, struct dentry * dentry, int mode,
+		struct nameidata *nd)
+{
+	handle_t *handle;
+	struct inode * inode;
+	int err, retries = 0;
+
+retry:
+	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	inode = ext4_new_inode (handle, dir, mode);
+	err = PTR_ERR(inode);
+	if (!IS_ERR(inode)) {
+		inode->i_op = &ext4_file_inode_operations;
+		inode->i_fop = &ext4_file_operations;
+		ext4_set_aops(inode);
+		err = ext4_add_nondir(handle, dentry, inode);
+	}
+	ext4_journal_stop(handle);
+	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
+	return err;
+}
+
+static int ext4_mknod (struct inode * dir, struct dentry *dentry,
+			int mode, dev_t rdev)
+{
+	handle_t *handle;
+	struct inode *inode;
+	int err, retries = 0;
+
+	if (!new_valid_dev(rdev))
+		return -EINVAL;
+
+retry:
+	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	inode = ext4_new_inode (handle, dir, mode);
+	err = PTR_ERR(inode);
+	if (!IS_ERR(inode)) {
+		init_special_inode(inode, inode->i_mode, rdev);
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+		inode->i_op = &ext4_special_inode_operations;
+#endif
+		err = ext4_add_nondir(handle, dentry, inode);
+	}
+	ext4_journal_stop(handle);
+	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
+	return err;
+}
+
+static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+{
+	handle_t *handle;
+	struct inode * inode;
+	struct buffer_head * dir_block;
+	struct ext4_dir_entry_2 * de;
+	int err, retries = 0;
+
+	if (dir->i_nlink >= EXT4_LINK_MAX)
+		return -EMLINK;
+
+retry:
+	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	inode = ext4_new_inode (handle, dir, S_IFDIR | mode);
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
+		goto out_stop;
+
+	inode->i_op = &ext4_dir_inode_operations;
+	inode->i_fop = &ext4_dir_operations;
+	inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
+	dir_block = ext4_bread (handle, inode, 0, 1, &err);
+	if (!dir_block) {
+		drop_nlink(inode); /* is this nlink == 0? */
+		ext4_mark_inode_dirty(handle, inode);
+		iput (inode);
+		goto out_stop;
+	}
+	BUFFER_TRACE(dir_block, "get_write_access");
+	ext4_journal_get_write_access(handle, dir_block);
+	de = (struct ext4_dir_entry_2 *) dir_block->b_data;
+	de->inode = cpu_to_le32(inode->i_ino);
+	de->name_len = 1;
+	de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(de->name_len));
+	strcpy (de->name, ".");
+	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
+	de = (struct ext4_dir_entry_2 *)
+			((char *) de + le16_to_cpu(de->rec_len));
+	de->inode = cpu_to_le32(dir->i_ino);
+	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT4_DIR_REC_LEN(1));
+	de->name_len = 2;
+	strcpy (de->name, "..");
+	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
+	inode->i_nlink = 2;
+	BUFFER_TRACE(dir_block, "call ext4_journal_dirty_metadata");
+	ext4_journal_dirty_metadata(handle, dir_block);
+	brelse (dir_block);
+	ext4_mark_inode_dirty(handle, inode);
+	err = ext4_add_entry (handle, dentry, inode);
+	if (err) {
+		inode->i_nlink = 0;
+		ext4_mark_inode_dirty(handle, inode);
+		iput (inode);
+		goto out_stop;
+	}
+	inc_nlink(dir);
+	ext4_update_dx_flag(dir);
+	ext4_mark_inode_dirty(handle, dir);
+	d_instantiate(dentry, inode);
+out_stop:
+	ext4_journal_stop(handle);
+	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
+	return err;
+}
+
+/*
+ * routine to check that the specified directory is empty (for rmdir)
+ */
+static int empty_dir (struct inode * inode)
+{
+	unsigned long offset;
+	struct buffer_head * bh;
+	struct ext4_dir_entry_2 * de, * de1;
+	struct super_block * sb;
+	int err = 0;
+
+	sb = inode->i_sb;
+	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
+	    !(bh = ext4_bread (NULL, inode, 0, 0, &err))) {
+		if (err)
+			ext4_error(inode->i_sb, __FUNCTION__,
+				   "error %d reading directory #%lu offset 0",
+				   err, inode->i_ino);
+		else
+			ext4_warning(inode->i_sb, __FUNCTION__,
+				     "bad directory (dir #%lu) - no data block",
+				     inode->i_ino);
+		return 1;
+	}
+	de = (struct ext4_dir_entry_2 *) bh->b_data;
+	de1 = (struct ext4_dir_entry_2 *)
+			((char *) de + le16_to_cpu(de->rec_len));
+	if (le32_to_cpu(de->inode) != inode->i_ino ||
+			!le32_to_cpu(de1->inode) ||
+			strcmp (".", de->name) ||
+			strcmp ("..", de1->name)) {
+		ext4_warning (inode->i_sb, "empty_dir",
+			      "bad directory (dir #%lu) - no `.' or `..'",
+			      inode->i_ino);
+		brelse (bh);
+		return 1;
+	}
+	offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+	de = (struct ext4_dir_entry_2 *)
+			((char *) de1 + le16_to_cpu(de1->rec_len));
+	while (offset < inode->i_size ) {
+		if (!bh ||
+			(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+			err = 0;
+			brelse (bh);
+			bh = ext4_bread (NULL, inode,
+				offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
+			if (!bh) {
+				if (err)
+					ext4_error(sb, __FUNCTION__,
+						   "error %d reading directory"
+						   " #%lu offset %lu",
+						   err, inode->i_ino, offset);
+				offset += sb->s_blocksize;
+				continue;
+			}
+			de = (struct ext4_dir_entry_2 *) bh->b_data;
+		}
+		if (!ext4_check_dir_entry("empty_dir", inode, de, bh, offset)) {
+			de = (struct ext4_dir_entry_2 *)(bh->b_data +
+							 sb->s_blocksize);
+			offset = (offset | (sb->s_blocksize - 1)) + 1;
+			continue;
+		}
+		if (le32_to_cpu(de->inode)) {
+			brelse (bh);
+			return 0;
+		}
+		offset += le16_to_cpu(de->rec_len);
+		de = (struct ext4_dir_entry_2 *)
+				((char *) de + le16_to_cpu(de->rec_len));
+	}
+	brelse (bh);
+	return 1;
+}
+
+/* ext4_orphan_add() links an unlinked or truncated inode into a list of
+ * such inodes, starting at the superblock, in case we crash before the
+ * file is closed/deleted, or in case the inode truncate spans multiple
+ * transactions and the last transaction is not recovered after a crash.
+ *
+ * At filesystem recovery time, we walk this list deleting unlinked
+ * inodes and truncating linked inodes in ext4_orphan_cleanup().
+ */
+int ext4_orphan_add(handle_t *handle, struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct ext4_iloc iloc;
+	int err = 0, rc;
+
+	lock_super(sb);
+	if (!list_empty(&EXT4_I(inode)->i_orphan))
+		goto out_unlock;
+
+	/* Orphan handling is only valid for files with data blocks
+	 * being truncated, or files being unlinked. */
+
+	/* @@@ FIXME: Observation from aviro:
+	 * I think I can trigger J_ASSERT in ext4_orphan_add().  We block
+	 * here (on lock_super()), so race with ext4_link() which might bump
+	 * ->i_nlink. For, say it, character device. Not a regular file,
+	 * not a directory, not a symlink and ->i_nlink > 0.
+	 */
+	J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+		S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
+
+	BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
+	err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+	if (err)
+		goto out_unlock;
+
+	err = ext4_reserve_inode_write(handle, inode, &iloc);
+	if (err)
+		goto out_unlock;
+
+	/* Insert this inode at the head of the on-disk orphan list... */
+	NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan);
+	EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
+	err = ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
+	rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
+	if (!err)
+		err = rc;
+
+	/* Only add to the head of the in-memory list if all the
+	 * previous operations succeeded.  If the orphan_add is going to
+	 * fail (possibly taking the journal offline), we can't risk
+	 * leaving the inode on the orphan list: stray orphan-list
+	 * entries can cause panics at unmount time.
+	 *
+	 * This is safe: on error we're going to ignore the orphan list
+	 * anyway on the next recovery. */
+	if (!err)
+		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
+
+	jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
+	jbd_debug(4, "orphan inode %lu will point to %d\n",
+			inode->i_ino, NEXT_ORPHAN(inode));
+out_unlock:
+	unlock_super(sb);
+	ext4_std_error(inode->i_sb, err);
+	return err;
+}
+
+/*
+ * ext4_orphan_del() removes an unlinked or truncated inode from the list
+ * of such inodes stored on disk, because it is finally being cleaned up.
+ */
+int ext4_orphan_del(handle_t *handle, struct inode *inode)
+{
+	struct list_head *prev;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct ext4_sb_info *sbi;
+	unsigned long ino_next;
+	struct ext4_iloc iloc;
+	int err = 0;
+
+	lock_super(inode->i_sb);
+	if (list_empty(&ei->i_orphan)) {
+		unlock_super(inode->i_sb);
+		return 0;
+	}
+
+	ino_next = NEXT_ORPHAN(inode);
+	prev = ei->i_orphan.prev;
+	sbi = EXT4_SB(inode->i_sb);
+
+	jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
+
+	list_del_init(&ei->i_orphan);
+
+	/* If we're on an error path, we may not have a valid
+	 * transaction handle with which to update the orphan list on
+	 * disk, but we still need to remove the inode from the linked
+	 * list in memory. */
+	if (!handle)
+		goto out;
+
+	err = ext4_reserve_inode_write(handle, inode, &iloc);
+	if (err)
+		goto out_err;
+
+	if (prev == &sbi->s_orphan) {
+		jbd_debug(4, "superblock will point to %lu\n", ino_next);
+		BUFFER_TRACE(sbi->s_sbh, "get_write_access");
+		err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+		if (err)
+			goto out_brelse;
+		sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
+		err = ext4_journal_dirty_metadata(handle, sbi->s_sbh);
+	} else {
+		struct ext4_iloc iloc2;
+		struct inode *i_prev =
+			&list_entry(prev, struct ext4_inode_info, i_orphan)->vfs_inode;
+
+		jbd_debug(4, "orphan inode %lu will point to %lu\n",
+			  i_prev->i_ino, ino_next);
+		err = ext4_reserve_inode_write(handle, i_prev, &iloc2);
+		if (err)
+			goto out_brelse;
+		NEXT_ORPHAN(i_prev) = ino_next;
+		err = ext4_mark_iloc_dirty(handle, i_prev, &iloc2);
+	}
+	if (err)
+		goto out_brelse;
+	NEXT_ORPHAN(inode) = 0;
+	err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+
+out_err:
+	ext4_std_error(inode->i_sb, err);
+out:
+	unlock_super(inode->i_sb);
+	return err;
+
+out_brelse:
+	brelse(iloc.bh);
+	goto out_err;
+}
+
+static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
+{
+	int retval;
+	struct inode * inode;
+	struct buffer_head * bh;
+	struct ext4_dir_entry_2 * de;
+	handle_t *handle;
+
+	/* Initialize quotas before so that eventual writes go in
+	 * separate transaction */
+	DQUOT_INIT(dentry->d_inode);
+	handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	retval = -ENOENT;
+	bh = ext4_find_entry (dentry, &de);
+	if (!bh)
+		goto end_rmdir;
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	inode = dentry->d_inode;
+
+	retval = -EIO;
+	if (le32_to_cpu(de->inode) != inode->i_ino)
+		goto end_rmdir;
+
+	retval = -ENOTEMPTY;
+	if (!empty_dir (inode))
+		goto end_rmdir;
+
+	retval = ext4_delete_entry(handle, dir, de, bh);
+	if (retval)
+		goto end_rmdir;
+	if (inode->i_nlink != 2)
+		ext4_warning (inode->i_sb, "ext4_rmdir",
+			      "empty directory has nlink!=2 (%d)",
+			      inode->i_nlink);
+	inode->i_version++;
+	clear_nlink(inode);
+	/* There's no need to set i_disksize: the fact that i_nlink is
+	 * zero will ensure that the right thing happens during any
+	 * recovery. */
+	inode->i_size = 0;
+	ext4_orphan_add(handle, inode);
+	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+	ext4_mark_inode_dirty(handle, inode);
+	drop_nlink(dir);
+	ext4_update_dx_flag(dir);
+	ext4_mark_inode_dirty(handle, dir);
+
+end_rmdir:
+	ext4_journal_stop(handle);
+	brelse (bh);
+	return retval;
+}
+
+static int ext4_unlink(struct inode * dir, struct dentry *dentry)
+{
+	int retval;
+	struct inode * inode;
+	struct buffer_head * bh;
+	struct ext4_dir_entry_2 * de;
+	handle_t *handle;
+
+	/* Initialize quotas before so that eventual writes go
+	 * in separate transaction */
+	DQUOT_INIT(dentry->d_inode);
+	handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	retval = -ENOENT;
+	bh = ext4_find_entry (dentry, &de);
+	if (!bh)
+		goto end_unlink;
+
+	inode = dentry->d_inode;
+
+	retval = -EIO;
+	if (le32_to_cpu(de->inode) != inode->i_ino)
+		goto end_unlink;
+
+	if (!inode->i_nlink) {
+		ext4_warning (inode->i_sb, "ext4_unlink",
+			      "Deleting nonexistent file (%lu), %d",
+			      inode->i_ino, inode->i_nlink);
+		inode->i_nlink = 1;
+	}
+	retval = ext4_delete_entry(handle, dir, de, bh);
+	if (retval)
+		goto end_unlink;
+	dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+	ext4_update_dx_flag(dir);
+	ext4_mark_inode_dirty(handle, dir);
+	drop_nlink(inode);
+	if (!inode->i_nlink)
+		ext4_orphan_add(handle, inode);
+	inode->i_ctime = dir->i_ctime;
+	ext4_mark_inode_dirty(handle, inode);
+	retval = 0;
+
+end_unlink:
+	ext4_journal_stop(handle);
+	brelse (bh);
+	return retval;
+}
+
+static int ext4_symlink (struct inode * dir,
+		struct dentry *dentry, const char * symname)
+{
+	handle_t *handle;
+	struct inode * inode;
+	int l, err, retries = 0;
+
+	l = strlen(symname)+1;
+	if (l > dir->i_sb->s_blocksize)
+		return -ENAMETOOLONG;
+
+retry:
+	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 5 +
+					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	inode = ext4_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
+		goto out_stop;
+
+	if (l > sizeof (EXT4_I(inode)->i_data)) {
+		inode->i_op = &ext4_symlink_inode_operations;
+		ext4_set_aops(inode);
+		/*
+		 * page_symlink() calls into ext4_prepare/commit_write.
+		 * We have a transaction open.  All is sweetness.  It also sets
+		 * i_size in generic_commit_write().
+		 */
+		err = __page_symlink(inode, symname, l,
+				mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+		if (err) {
+			ext4_dec_count(handle, inode);
+			ext4_mark_inode_dirty(handle, inode);
+			iput (inode);
+			goto out_stop;
+		}
+	} else {
+		inode->i_op = &ext4_fast_symlink_inode_operations;
+		memcpy((char*)&EXT4_I(inode)->i_data,symname,l);
+		inode->i_size = l-1;
+	}
+	EXT4_I(inode)->i_disksize = inode->i_size;
+	err = ext4_add_nondir(handle, dentry, inode);
+out_stop:
+	ext4_journal_stop(handle);
+	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
+	return err;
+}
+
+static int ext4_link (struct dentry * old_dentry,
+		struct inode * dir, struct dentry *dentry)
+{
+	handle_t *handle;
+	struct inode *inode = old_dentry->d_inode;
+	int err, retries = 0;
+
+	if (inode->i_nlink >= EXT4_LINK_MAX)
+		return -EMLINK;
+
+retry:
+	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+					EXT4_INDEX_EXTRA_TRANS_BLOCKS);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
+	inode->i_ctime = CURRENT_TIME_SEC;
+	ext4_inc_count(handle, inode);
+	atomic_inc(&inode->i_count);
+
+	err = ext4_add_nondir(handle, dentry, inode);
+	ext4_journal_stop(handle);
+	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
+	return err;
+}
+
+#define PARENT_INO(buffer) \
+	((struct ext4_dir_entry_2 *) ((char *) buffer + \
+	le16_to_cpu(((struct ext4_dir_entry_2 *) buffer)->rec_len)))->inode
+
+/*
+ * Anybody can rename anything with this: the permission checks are left to the
+ * higher-level routines.
+ */
+static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+			   struct inode * new_dir,struct dentry *new_dentry)
+{
+	handle_t *handle;
+	struct inode * old_inode, * new_inode;
+	struct buffer_head * old_bh, * new_bh, * dir_bh;
+	struct ext4_dir_entry_2 * old_de, * new_de;
+	int retval;
+
+	old_bh = new_bh = dir_bh = NULL;
+
+	/* Initialize quotas before so that eventual writes go
+	 * in separate transaction */
+	if (new_dentry->d_inode)
+		DQUOT_INIT(new_dentry->d_inode);
+	handle = ext4_journal_start(old_dir, 2 *
+					EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
+					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+		handle->h_sync = 1;
+
+	old_bh = ext4_find_entry (old_dentry, &old_de);
+	/*
+	 *  Check for inode number is _not_ due to possible IO errors.
+	 *  We might rmdir the source, keep it as pwd of some process
+	 *  and merrily kill the link to whatever was created under the
+	 *  same name. Goodbye sticky bit ;-<
+	 */
+	old_inode = old_dentry->d_inode;
+	retval = -ENOENT;
+	if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
+		goto end_rename;
+
+	new_inode = new_dentry->d_inode;
+	new_bh = ext4_find_entry (new_dentry, &new_de);
+	if (new_bh) {
+		if (!new_inode) {
+			brelse (new_bh);
+			new_bh = NULL;
+		}
+	}
+	if (S_ISDIR(old_inode->i_mode)) {
+		if (new_inode) {
+			retval = -ENOTEMPTY;
+			if (!empty_dir (new_inode))
+				goto end_rename;
+		}
+		retval = -EIO;
+		dir_bh = ext4_bread (handle, old_inode, 0, 0, &retval);
+		if (!dir_bh)
+			goto end_rename;
+		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
+			goto end_rename;
+		retval = -EMLINK;
+		if (!new_inode && new_dir!=old_dir &&
+				new_dir->i_nlink >= EXT4_LINK_MAX)
+			goto end_rename;
+	}
+	if (!new_bh) {
+		retval = ext4_add_entry (handle, new_dentry, old_inode);
+		if (retval)
+			goto end_rename;
+	} else {
+		BUFFER_TRACE(new_bh, "get write access");
+		ext4_journal_get_write_access(handle, new_bh);
+		new_de->inode = cpu_to_le32(old_inode->i_ino);
+		if (EXT4_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
+					      EXT4_FEATURE_INCOMPAT_FILETYPE))
+			new_de->file_type = old_de->file_type;
+		new_dir->i_version++;
+		BUFFER_TRACE(new_bh, "call ext4_journal_dirty_metadata");
+		ext4_journal_dirty_metadata(handle, new_bh);
+		brelse(new_bh);
+		new_bh = NULL;
+	}
+
+	/*
+	 * Like most other Unix systems, set the ctime for inodes on a
+	 * rename.
+	 */
+	old_inode->i_ctime = CURRENT_TIME_SEC;
+	ext4_mark_inode_dirty(handle, old_inode);
+
+	/*
+	 * ok, that's it
+	 */
+	if (le32_to_cpu(old_de->inode) != old_inode->i_ino ||
+	    old_de->name_len != old_dentry->d_name.len ||
+	    strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) ||
+	    (retval = ext4_delete_entry(handle, old_dir,
+					old_de, old_bh)) == -ENOENT) {
+		/* old_de could have moved from under us during htree split, so
+		 * make sure that we are deleting the right entry.  We might
+		 * also be pointing to a stale entry in the unused part of
+		 * old_bh so just checking inum and the name isn't enough. */
+		struct buffer_head *old_bh2;
+		struct ext4_dir_entry_2 *old_de2;
+
+		old_bh2 = ext4_find_entry(old_dentry, &old_de2);
+		if (old_bh2) {
+			retval = ext4_delete_entry(handle, old_dir,
+						   old_de2, old_bh2);
+			brelse(old_bh2);
+		}
+	}
+	if (retval) {
+		ext4_warning(old_dir->i_sb, "ext4_rename",
+				"Deleting old file (%lu), %d, error=%d",
+				old_dir->i_ino, old_dir->i_nlink, retval);
+	}
+
+	if (new_inode) {
+		drop_nlink(new_inode);
+		new_inode->i_ctime = CURRENT_TIME_SEC;
+	}
+	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+	ext4_update_dx_flag(old_dir);
+	if (dir_bh) {
+		BUFFER_TRACE(dir_bh, "get_write_access");
+		ext4_journal_get_write_access(handle, dir_bh);
+		PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
+		BUFFER_TRACE(dir_bh, "call ext4_journal_dirty_metadata");
+		ext4_journal_dirty_metadata(handle, dir_bh);
+		drop_nlink(old_dir);
+		if (new_inode) {
+			drop_nlink(new_inode);
+		} else {
+			inc_nlink(new_dir);
+			ext4_update_dx_flag(new_dir);
+			ext4_mark_inode_dirty(handle, new_dir);
+		}
+	}
+	ext4_mark_inode_dirty(handle, old_dir);
+	if (new_inode) {
+		ext4_mark_inode_dirty(handle, new_inode);
+		if (!new_inode->i_nlink)
+			ext4_orphan_add(handle, new_inode);
+	}
+	retval = 0;
+
+end_rename:
+	brelse (dir_bh);
+	brelse (old_bh);
+	brelse (new_bh);
+	ext4_journal_stop(handle);
+	return retval;
+}
+
+/*
+ * directories can handle most operations...
+ */
+struct inode_operations ext4_dir_inode_operations = {
+	.create		= ext4_create,
+	.lookup		= ext4_lookup,
+	.link		= ext4_link,
+	.unlink		= ext4_unlink,
+	.symlink	= ext4_symlink,
+	.mkdir		= ext4_mkdir,
+	.rmdir		= ext4_rmdir,
+	.mknod		= ext4_mknod,
+	.rename		= ext4_rename,
+	.setattr	= ext4_setattr,
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= ext4_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+	.permission	= ext4_permission,
+};
+
+struct inode_operations ext4_special_inode_operations = {
+	.setattr	= ext4_setattr,
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= ext4_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+	.permission	= ext4_permission,
+};
diff --git a/fs/ext4/namei.h b/fs/ext4/namei.h
new file mode 100644
index 0000000..5e4dfff
--- /dev/null
+++ b/fs/ext4/namei.h
@@ -0,0 +1,8 @@
+/*  linux/fs/ext4/namei.h
+ *
+ * Copyright (C) 2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+*/
+
+extern struct dentry *ext4_get_parent(struct dentry *child);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
new file mode 100644
index 0000000..1e95780
--- /dev/null
+++ b/fs/ext4/resize.c
@@ -0,0 +1,1045 @@
+/*
+ *  linux/fs/ext4/resize.c
+ *
+ * Support for resizing an ext4 filesystem while it is mounted.
+ *
+ * Copyright (C) 2001, 2002 Andreas Dilger <adilger@clusterfs.com>
+ *
+ * This could probably be made into a module, because it is not often in use.
+ */
+
+
+#define EXT4FS_DEBUG
+
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/ext4_jbd2.h>
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+
+#define outside(b, first, last)	((b) < (first) || (b) >= (last))
+#define inside(b, first, last)	((b) >= (first) && (b) < (last))
+
+static int verify_group_input(struct super_block *sb,
+			      struct ext4_new_group_data *input)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_super_block *es = sbi->s_es;
+	ext4_fsblk_t start = ext4_blocks_count(es);
+	ext4_fsblk_t end = start + input->blocks_count;
+	unsigned group = input->group;
+	ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
+	unsigned overhead = ext4_bg_has_super(sb, group) ?
+		(1 + ext4_bg_num_gdb(sb, group) +
+		 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
+	ext4_fsblk_t metaend = start + overhead;
+	struct buffer_head *bh = NULL;
+	ext4_grpblk_t free_blocks_count, offset;
+	int err = -EINVAL;
+
+	input->free_blocks_count = free_blocks_count =
+		input->blocks_count - 2 - overhead - sbi->s_itb_per_group;
+
+	if (test_opt(sb, DEBUG))
+		printk(KERN_DEBUG "EXT4-fs: adding %s group %u: %u blocks "
+		       "(%d free, %u reserved)\n",
+		       ext4_bg_has_super(sb, input->group) ? "normal" :
+		       "no-super", input->group, input->blocks_count,
+		       free_blocks_count, input->reserved_blocks);
+
+	ext4_get_group_no_and_offset(sb, start, NULL, &offset);
+	if (group != sbi->s_groups_count)
+		ext4_warning(sb, __FUNCTION__,
+			     "Cannot add at group %u (only %lu groups)",
+			     input->group, sbi->s_groups_count);
+	else if (offset != 0)
+			ext4_warning(sb, __FUNCTION__, "Last group not full");
+	else if (input->reserved_blocks > input->blocks_count / 5)
+		ext4_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)",
+			     input->reserved_blocks);
+	else if (free_blocks_count < 0)
+		ext4_warning(sb, __FUNCTION__, "Bad blocks count %u",
+			     input->blocks_count);
+	else if (!(bh = sb_bread(sb, end - 1)))
+		ext4_warning(sb, __FUNCTION__,
+			     "Cannot read last block (%llu)",
+			     end - 1);
+	else if (outside(input->block_bitmap, start, end))
+		ext4_warning(sb, __FUNCTION__,
+			     "Block bitmap not in group (block %llu)",
+			     input->block_bitmap);
+	else if (outside(input->inode_bitmap, start, end))
+		ext4_warning(sb, __FUNCTION__,
+			     "Inode bitmap not in group (block %llu)",
+			     input->inode_bitmap);
+	else if (outside(input->inode_table, start, end) ||
+	         outside(itend - 1, start, end))
+		ext4_warning(sb, __FUNCTION__,
+			     "Inode table not in group (blocks %llu-%llu)",
+			     input->inode_table, itend - 1);
+	else if (input->inode_bitmap == input->block_bitmap)
+		ext4_warning(sb, __FUNCTION__,
+			     "Block bitmap same as inode bitmap (%llu)",
+			     input->block_bitmap);
+	else if (inside(input->block_bitmap, input->inode_table, itend))
+		ext4_warning(sb, __FUNCTION__,
+			     "Block bitmap (%llu) in inode table (%llu-%llu)",
+			     input->block_bitmap, input->inode_table, itend-1);
+	else if (inside(input->inode_bitmap, input->inode_table, itend))
+		ext4_warning(sb, __FUNCTION__,
+			     "Inode bitmap (%llu) in inode table (%llu-%llu)",
+			     input->inode_bitmap, input->inode_table, itend-1);
+	else if (inside(input->block_bitmap, start, metaend))
+		ext4_warning(sb, __FUNCTION__,
+			     "Block bitmap (%llu) in GDT table"
+			     " (%llu-%llu)",
+			     input->block_bitmap, start, metaend - 1);
+	else if (inside(input->inode_bitmap, start, metaend))
+		ext4_warning(sb, __FUNCTION__,
+			     "Inode bitmap (%llu) in GDT table"
+			     " (%llu-%llu)",
+			     input->inode_bitmap, start, metaend - 1);
+	else if (inside(input->inode_table, start, metaend) ||
+	         inside(itend - 1, start, metaend))
+		ext4_warning(sb, __FUNCTION__,
+			     "Inode table (%llu-%llu) overlaps"
+			     "GDT table (%llu-%llu)",
+			     input->inode_table, itend - 1, start, metaend - 1);
+	else
+		err = 0;
+	brelse(bh);
+
+	return err;
+}
+
+static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
+				  ext4_fsblk_t blk)
+{
+	struct buffer_head *bh;
+	int err;
+
+	bh = sb_getblk(sb, blk);
+	if (!bh)
+		return ERR_PTR(-EIO);
+	if ((err = ext4_journal_get_write_access(handle, bh))) {
+		brelse(bh);
+		bh = ERR_PTR(err);
+	} else {
+		lock_buffer(bh);
+		memset(bh->b_data, 0, sb->s_blocksize);
+		set_buffer_uptodate(bh);
+		unlock_buffer(bh);
+	}
+
+	return bh;
+}
+
+/*
+ * To avoid calling the atomic setbit hundreds or thousands of times, we only
+ * need to use it within a single byte (to ensure we get endianness right).
+ * We can use memset for the rest of the bitmap as there are no other users.
+ */
+static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+{
+	int i;
+
+	if (start_bit >= end_bit)
+		return;
+
+	ext4_debug("mark end bits +%d through +%d used\n", start_bit, end_bit);
+	for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
+		ext4_set_bit(i, bitmap);
+	if (i < end_bit)
+		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
+}
+
+/*
+ * Set up the block and inode bitmaps, and the inode table for the new group.
+ * This doesn't need to be part of the main transaction, since we are only
+ * changing blocks outside the actual filesystem.  We still do journaling to
+ * ensure the recovery is correct in case of a failure just after resize.
+ * If any part of this fails, we simply abort the resize.
+ */
+static int setup_new_group_blocks(struct super_block *sb,
+				  struct ext4_new_group_data *input)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	ext4_fsblk_t start = ext4_group_first_block_no(sb, input->group);
+	int reserved_gdb = ext4_bg_has_super(sb, input->group) ?
+		le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0;
+	unsigned long gdblocks = ext4_bg_num_gdb(sb, input->group);
+	struct buffer_head *bh;
+	handle_t *handle;
+	ext4_fsblk_t block;
+	ext4_grpblk_t bit;
+	int i;
+	int err = 0, err2;
+
+	handle = ext4_journal_start_sb(sb, reserved_gdb + gdblocks +
+				       2 + sbi->s_itb_per_group);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	lock_super(sb);
+	if (input->group != sbi->s_groups_count) {
+		err = -EBUSY;
+		goto exit_journal;
+	}
+
+	if (IS_ERR(bh = bclean(handle, sb, input->block_bitmap))) {
+		err = PTR_ERR(bh);
+		goto exit_journal;
+	}
+
+	if (ext4_bg_has_super(sb, input->group)) {
+		ext4_debug("mark backup superblock %#04lx (+0)\n", start);
+		ext4_set_bit(0, bh->b_data);
+	}
+
+	/* Copy all of the GDT blocks into the backup in this group */
+	for (i = 0, bit = 1, block = start + 1;
+	     i < gdblocks; i++, block++, bit++) {
+		struct buffer_head *gdb;
+
+		ext4_debug("update backup group %#04lx (+%d)\n", block, bit);
+
+		gdb = sb_getblk(sb, block);
+		if (!gdb) {
+			err = -EIO;
+			goto exit_bh;
+		}
+		if ((err = ext4_journal_get_write_access(handle, gdb))) {
+			brelse(gdb);
+			goto exit_bh;
+		}
+		lock_buffer(bh);
+		memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
+		set_buffer_uptodate(gdb);
+		unlock_buffer(bh);
+		ext4_journal_dirty_metadata(handle, gdb);
+		ext4_set_bit(bit, bh->b_data);
+		brelse(gdb);
+	}
+
+	/* Zero out all of the reserved backup group descriptor table blocks */
+	for (i = 0, bit = gdblocks + 1, block = start + bit;
+	     i < reserved_gdb; i++, block++, bit++) {
+		struct buffer_head *gdb;
+
+		ext4_debug("clear reserved block %#04lx (+%d)\n", block, bit);
+
+		if (IS_ERR(gdb = bclean(handle, sb, block))) {
+			err = PTR_ERR(bh);
+			goto exit_bh;
+		}
+		ext4_journal_dirty_metadata(handle, gdb);
+		ext4_set_bit(bit, bh->b_data);
+		brelse(gdb);
+	}
+	ext4_debug("mark block bitmap %#04x (+%ld)\n", input->block_bitmap,
+		   input->block_bitmap - start);
+	ext4_set_bit(input->block_bitmap - start, bh->b_data);
+	ext4_debug("mark inode bitmap %#04x (+%ld)\n", input->inode_bitmap,
+		   input->inode_bitmap - start);
+	ext4_set_bit(input->inode_bitmap - start, bh->b_data);
+
+	/* Zero out all of the inode table blocks */
+	for (i = 0, block = input->inode_table, bit = block - start;
+	     i < sbi->s_itb_per_group; i++, bit++, block++) {
+		struct buffer_head *it;
+
+		ext4_debug("clear inode block %#04lx (+%d)\n", block, bit);
+		if (IS_ERR(it = bclean(handle, sb, block))) {
+			err = PTR_ERR(it);
+			goto exit_bh;
+		}
+		ext4_journal_dirty_metadata(handle, it);
+		brelse(it);
+		ext4_set_bit(bit, bh->b_data);
+	}
+	mark_bitmap_end(input->blocks_count, EXT4_BLOCKS_PER_GROUP(sb),
+			bh->b_data);
+	ext4_journal_dirty_metadata(handle, bh);
+	brelse(bh);
+
+	/* Mark unused entries in inode bitmap used */
+	ext4_debug("clear inode bitmap %#04x (+%ld)\n",
+		   input->inode_bitmap, input->inode_bitmap - start);
+	if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) {
+		err = PTR_ERR(bh);
+		goto exit_journal;
+	}
+
+	mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), EXT4_BLOCKS_PER_GROUP(sb),
+			bh->b_data);
+	ext4_journal_dirty_metadata(handle, bh);
+exit_bh:
+	brelse(bh);
+
+exit_journal:
+	unlock_super(sb);
+	if ((err2 = ext4_journal_stop(handle)) && !err)
+		err = err2;
+
+	return err;
+}
+
+
+/*
+ * Iterate through the groups which hold BACKUP superblock/GDT copies in an
+ * ext4 filesystem.  The counters should be initialized to 1, 5, and 7 before
+ * calling this for the first time.  In a sparse filesystem it will be the
+ * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
+ * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
+ */
+static unsigned ext4_list_backups(struct super_block *sb, unsigned *three,
+				  unsigned *five, unsigned *seven)
+{
+	unsigned *min = three;
+	int mult = 3;
+	unsigned ret;
+
+	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
+					EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+		ret = *min;
+		*min += 1;
+		return ret;
+	}
+
+	if (*five < *min) {
+		min = five;
+		mult = 5;
+	}
+	if (*seven < *min) {
+		min = seven;
+		mult = 7;
+	}
+
+	ret = *min;
+	*min *= mult;
+
+	return ret;
+}
+
+/*
+ * Check that all of the backup GDT blocks are held in the primary GDT block.
+ * It is assumed that they are stored in group order.  Returns the number of
+ * groups in current filesystem that have BACKUPS, or -ve error code.
+ */
+static int verify_reserved_gdb(struct super_block *sb,
+			       struct buffer_head *primary)
+{
+	const ext4_fsblk_t blk = primary->b_blocknr;
+	const unsigned long end = EXT4_SB(sb)->s_groups_count;
+	unsigned three = 1;
+	unsigned five = 5;
+	unsigned seven = 7;
+	unsigned grp;
+	__le32 *p = (__le32 *)primary->b_data;
+	int gdbackups = 0;
+
+	while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) {
+		if (le32_to_cpu(*p++) !=
+		    grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
+			ext4_warning(sb, __FUNCTION__,
+				     "reserved GDT %llu"
+				     " missing grp %d (%llu)",
+				     blk, grp,
+				     grp *
+				     (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
+				     blk);
+			return -EINVAL;
+		}
+		if (++gdbackups > EXT4_ADDR_PER_BLOCK(sb))
+			return -EFBIG;
+	}
+
+	return gdbackups;
+}
+
+/*
+ * Called when we need to bring a reserved group descriptor table block into
+ * use from the resize inode.  The primary copy of the new GDT block currently
+ * is an indirect block (under the double indirect block in the resize inode).
+ * The new backup GDT blocks will be stored as leaf blocks in this indirect
+ * block, in group order.  Even though we know all the block numbers we need,
+ * we check to ensure that the resize inode has actually reserved these blocks.
+ *
+ * Don't need to update the block bitmaps because the blocks are still in use.
+ *
+ * We get all of the error cases out of the way, so that we are sure to not
+ * fail once we start modifying the data on disk, because JBD has no rollback.
+ */
+static int add_new_gdb(handle_t *handle, struct inode *inode,
+		       struct ext4_new_group_data *input,
+		       struct buffer_head **primary)
+{
+	struct super_block *sb = inode->i_sb;
+	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+	unsigned long gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb);
+	ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
+	struct buffer_head **o_group_desc, **n_group_desc;
+	struct buffer_head *dind;
+	int gdbackups;
+	struct ext4_iloc iloc;
+	__le32 *data;
+	int err;
+
+	if (test_opt(sb, DEBUG))
+		printk(KERN_DEBUG
+		       "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
+		       gdb_num);
+
+	/*
+	 * If we are not using the primary superblock/GDT copy don't resize,
+	 * because the user tools have no way of handling this.  Probably a
+	 * bad time to do it anyways.
+	 */
+	if (EXT4_SB(sb)->s_sbh->b_blocknr !=
+	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
+		ext4_warning(sb, __FUNCTION__,
+			"won't resize using backup superblock at %llu",
+			(unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
+		return -EPERM;
+	}
+
+	*primary = sb_bread(sb, gdblock);
+	if (!*primary)
+		return -EIO;
+
+	if ((gdbackups = verify_reserved_gdb(sb, *primary)) < 0) {
+		err = gdbackups;
+		goto exit_bh;
+	}
+
+	data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK;
+	dind = sb_bread(sb, le32_to_cpu(*data));
+	if (!dind) {
+		err = -EIO;
+		goto exit_bh;
+	}
+
+	data = (__le32 *)dind->b_data;
+	if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) {
+		ext4_warning(sb, __FUNCTION__,
+			     "new group %u GDT block %llu not reserved",
+			     input->group, gdblock);
+		err = -EINVAL;
+		goto exit_dind;
+	}
+
+	if ((err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh)))
+		goto exit_dind;
+
+	if ((err = ext4_journal_get_write_access(handle, *primary)))
+		goto exit_sbh;
+
+	if ((err = ext4_journal_get_write_access(handle, dind)))
+		goto exit_primary;
+
+	/* ext4_reserve_inode_write() gets a reference on the iloc */
+	if ((err = ext4_reserve_inode_write(handle, inode, &iloc)))
+		goto exit_dindj;
+
+	n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
+			GFP_KERNEL);
+	if (!n_group_desc) {
+		err = -ENOMEM;
+		ext4_warning (sb, __FUNCTION__,
+			      "not enough memory for %lu groups", gdb_num + 1);
+		goto exit_inode;
+	}
+
+	/*
+	 * Finally, we have all of the possible failures behind us...
+	 *
+	 * Remove new GDT block from inode double-indirect block and clear out
+	 * the new GDT block for use (which also "frees" the backup GDT blocks
+	 * from the reserved inode).  We don't need to change the bitmaps for
+	 * these blocks, because they are marked as in-use from being in the
+	 * reserved inode, and will become GDT blocks (primary and backup).
+	 */
+	data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0;
+	ext4_journal_dirty_metadata(handle, dind);
+	brelse(dind);
+	inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
+	ext4_mark_iloc_dirty(handle, inode, &iloc);
+	memset((*primary)->b_data, 0, sb->s_blocksize);
+	ext4_journal_dirty_metadata(handle, *primary);
+
+	o_group_desc = EXT4_SB(sb)->s_group_desc;
+	memcpy(n_group_desc, o_group_desc,
+	       EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
+	n_group_desc[gdb_num] = *primary;
+	EXT4_SB(sb)->s_group_desc = n_group_desc;
+	EXT4_SB(sb)->s_gdb_count++;
+	kfree(o_group_desc);
+
+	es->s_reserved_gdt_blocks =
+		cpu_to_le16(le16_to_cpu(es->s_reserved_gdt_blocks) - 1);
+	ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
+
+	return 0;
+
+exit_inode:
+	//ext4_journal_release_buffer(handle, iloc.bh);
+	brelse(iloc.bh);
+exit_dindj:
+	//ext4_journal_release_buffer(handle, dind);
+exit_primary:
+	//ext4_journal_release_buffer(handle, *primary);
+exit_sbh:
+	//ext4_journal_release_buffer(handle, *primary);
+exit_dind:
+	brelse(dind);
+exit_bh:
+	brelse(*primary);
+
+	ext4_debug("leaving with error %d\n", err);
+	return err;
+}
+
+/*
+ * Called when we are adding a new group which has a backup copy of each of
+ * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks.
+ * We need to add these reserved backup GDT blocks to the resize inode, so
+ * that they are kept for future resizing and not allocated to files.
+ *
+ * Each reserved backup GDT block will go into a different indirect block.
+ * The indirect blocks are actually the primary reserved GDT blocks,
+ * so we know in advance what their block numbers are.  We only get the
+ * double-indirect block to verify it is pointing to the primary reserved
+ * GDT blocks so we don't overwrite a data block by accident.  The reserved
+ * backup GDT blocks are stored in their reserved primary GDT block.
+ */
+static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+			      struct ext4_new_group_data *input)
+{
+	struct super_block *sb = inode->i_sb;
+	int reserved_gdb =le16_to_cpu(EXT4_SB(sb)->s_es->s_reserved_gdt_blocks);
+	struct buffer_head **primary;
+	struct buffer_head *dind;
+	struct ext4_iloc iloc;
+	ext4_fsblk_t blk;
+	__le32 *data, *end;
+	int gdbackups = 0;
+	int res, i;
+	int err;
+
+	primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL);
+	if (!primary)
+		return -ENOMEM;
+
+	data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK;
+	dind = sb_bread(sb, le32_to_cpu(*data));
+	if (!dind) {
+		err = -EIO;
+		goto exit_free;
+	}
+
+	blk = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + EXT4_SB(sb)->s_gdb_count;
+	data = (__le32 *)dind->b_data + EXT4_SB(sb)->s_gdb_count;
+	end = (__le32 *)dind->b_data + EXT4_ADDR_PER_BLOCK(sb);
+
+	/* Get each reserved primary GDT block and verify it holds backups */
+	for (res = 0; res < reserved_gdb; res++, blk++) {
+		if (le32_to_cpu(*data) != blk) {
+			ext4_warning(sb, __FUNCTION__,
+				     "reserved block %llu"
+				     " not at offset %ld",
+				     blk,
+				     (long)(data - (__le32 *)dind->b_data));
+			err = -EINVAL;
+			goto exit_bh;
+		}
+		primary[res] = sb_bread(sb, blk);
+		if (!primary[res]) {
+			err = -EIO;
+			goto exit_bh;
+		}
+		if ((gdbackups = verify_reserved_gdb(sb, primary[res])) < 0) {
+			brelse(primary[res]);
+			err = gdbackups;
+			goto exit_bh;
+		}
+		if (++data >= end)
+			data = (__le32 *)dind->b_data;
+	}
+
+	for (i = 0; i < reserved_gdb; i++) {
+		if ((err = ext4_journal_get_write_access(handle, primary[i]))) {
+			/*
+			int j;
+			for (j = 0; j < i; j++)
+				ext4_journal_release_buffer(handle, primary[j]);
+			 */
+			goto exit_bh;
+		}
+	}
+
+	if ((err = ext4_reserve_inode_write(handle, inode, &iloc)))
+		goto exit_bh;
+
+	/*
+	 * Finally we can add each of the reserved backup GDT blocks from
+	 * the new group to its reserved primary GDT block.
+	 */
+	blk = input->group * EXT4_BLOCKS_PER_GROUP(sb);
+	for (i = 0; i < reserved_gdb; i++) {
+		int err2;
+		data = (__le32 *)primary[i]->b_data;
+		/* printk("reserving backup %lu[%u] = %lu\n",
+		       primary[i]->b_blocknr, gdbackups,
+		       blk + primary[i]->b_blocknr); */
+		data[gdbackups] = cpu_to_le32(blk + primary[i]->b_blocknr);
+		err2 = ext4_journal_dirty_metadata(handle, primary[i]);
+		if (!err)
+			err = err2;
+	}
+	inode->i_blocks += reserved_gdb * sb->s_blocksize >> 9;
+	ext4_mark_iloc_dirty(handle, inode, &iloc);
+
+exit_bh:
+	while (--res >= 0)
+		brelse(primary[res]);
+	brelse(dind);
+
+exit_free:
+	kfree(primary);
+
+	return err;
+}
+
+/*
+ * Update the backup copies of the ext4 metadata.  These don't need to be part
+ * of the main resize transaction, because e2fsck will re-write them if there
+ * is a problem (basically only OOM will cause a problem).  However, we
+ * _should_ update the backups if possible, in case the primary gets trashed
+ * for some reason and we need to run e2fsck from a backup superblock.  The
+ * important part is that the new block and inode counts are in the backup
+ * superblocks, and the location of the new group metadata in the GDT backups.
+ *
+ * We do not need lock_super() for this, because these blocks are not
+ * otherwise touched by the filesystem code when it is mounted.  We don't
+ * need to worry about last changing from sbi->s_groups_count, because the
+ * worst that can happen is that we do not copy the full number of backups
+ * at this time.  The resize which changed s_groups_count will backup again.
+ */
+static void update_backups(struct super_block *sb,
+			   int blk_off, char *data, int size)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	const unsigned long last = sbi->s_groups_count;
+	const int bpg = EXT4_BLOCKS_PER_GROUP(sb);
+	unsigned three = 1;
+	unsigned five = 5;
+	unsigned seven = 7;
+	unsigned group;
+	int rest = sb->s_blocksize - size;
+	handle_t *handle;
+	int err = 0, err2;
+
+	handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);
+	if (IS_ERR(handle)) {
+		group = 1;
+		err = PTR_ERR(handle);
+		goto exit_err;
+	}
+
+	while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) {
+		struct buffer_head *bh;
+
+		/* Out of journal space, and can't get more - abort - so sad */
+		if (handle->h_buffer_credits == 0 &&
+		    ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA) &&
+		    (err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA)))
+			break;
+
+		bh = sb_getblk(sb, group * bpg + blk_off);
+		if (!bh) {
+			err = -EIO;
+			break;
+		}
+		ext4_debug("update metadata backup %#04lx\n",
+			  (unsigned long)bh->b_blocknr);
+		if ((err = ext4_journal_get_write_access(handle, bh)))
+			break;
+		lock_buffer(bh);
+		memcpy(bh->b_data, data, size);
+		if (rest)
+			memset(bh->b_data + size, 0, rest);
+		set_buffer_uptodate(bh);
+		unlock_buffer(bh);
+		ext4_journal_dirty_metadata(handle, bh);
+		brelse(bh);
+	}
+	if ((err2 = ext4_journal_stop(handle)) && !err)
+		err = err2;
+
+	/*
+	 * Ugh! Need to have e2fsck write the backup copies.  It is too
+	 * late to revert the resize, we shouldn't fail just because of
+	 * the backup copies (they are only needed in case of corruption).
+	 *
+	 * However, if we got here we have a journal problem too, so we
+	 * can't really start a transaction to mark the superblock.
+	 * Chicken out and just set the flag on the hope it will be written
+	 * to disk, and if not - we will simply wait until next fsck.
+	 */
+exit_err:
+	if (err) {
+		ext4_warning(sb, __FUNCTION__,
+			     "can't update backup for group %d (err %d), "
+			     "forcing fsck on next reboot", group, err);
+		sbi->s_mount_state &= ~EXT4_VALID_FS;
+		sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
+		mark_buffer_dirty(sbi->s_sbh);
+	}
+}
+
+/* Add group descriptor data to an existing or new group descriptor block.
+ * Ensure we handle all possible error conditions _before_ we start modifying
+ * the filesystem, because we cannot abort the transaction and not have it
+ * write the data to disk.
+ *
+ * If we are on a GDT block boundary, we need to get the reserved GDT block.
+ * Otherwise, we may need to add backup GDT blocks for a sparse group.
+ *
+ * We only need to hold the superblock lock while we are actually adding
+ * in the new group's counts to the superblock.  Prior to that we have
+ * not really "added" the group at all.  We re-check that we are still
+ * adding in the last group in case things have changed since verifying.
+ */
+int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_super_block *es = sbi->s_es;
+	int reserved_gdb = ext4_bg_has_super(sb, input->group) ?
+		le16_to_cpu(es->s_reserved_gdt_blocks) : 0;
+	struct buffer_head *primary = NULL;
+	struct ext4_group_desc *gdp;
+	struct inode *inode = NULL;
+	handle_t *handle;
+	int gdb_off, gdb_num;
+	int err, err2;
+
+	gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb);
+	gdb_off = input->group % EXT4_DESC_PER_BLOCK(sb);
+
+	if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb,
+					EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+		ext4_warning(sb, __FUNCTION__,
+			     "Can't resize non-sparse filesystem further");
+		return -EPERM;
+	}
+
+	if (ext4_blocks_count(es) + input->blocks_count <
+	    ext4_blocks_count(es)) {
+		ext4_warning(sb, __FUNCTION__, "blocks_count overflow\n");
+		return -EINVAL;
+	}
+
+	if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) <
+	    le32_to_cpu(es->s_inodes_count)) {
+		ext4_warning(sb, __FUNCTION__, "inodes_count overflow\n");
+		return -EINVAL;
+	}
+
+	if (reserved_gdb || gdb_off == 0) {
+		if (!EXT4_HAS_COMPAT_FEATURE(sb,
+					     EXT4_FEATURE_COMPAT_RESIZE_INODE)){
+			ext4_warning(sb, __FUNCTION__,
+				     "No reserved GDT blocks, can't resize");
+			return -EPERM;
+		}
+		inode = iget(sb, EXT4_RESIZE_INO);
+		if (!inode || is_bad_inode(inode)) {
+			ext4_warning(sb, __FUNCTION__,
+				     "Error opening resize inode");
+			iput(inode);
+			return -ENOENT;
+		}
+	}
+
+	if ((err = verify_group_input(sb, input)))
+		goto exit_put;
+
+	if ((err = setup_new_group_blocks(sb, input)))
+		goto exit_put;
+
+	/*
+	 * We will always be modifying at least the superblock and a GDT
+	 * block.  If we are adding a group past the last current GDT block,
+	 * we will also modify the inode and the dindirect block.  If we
+	 * are adding a group with superblock/GDT backups  we will also
+	 * modify each of the reserved GDT dindirect blocks.
+	 */
+	handle = ext4_journal_start_sb(sb,
+				       ext4_bg_has_super(sb, input->group) ?
+				       3 + reserved_gdb : 4);
+	if (IS_ERR(handle)) {
+		err = PTR_ERR(handle);
+		goto exit_put;
+	}
+
+	lock_super(sb);
+	if (input->group != sbi->s_groups_count) {
+		ext4_warning(sb, __FUNCTION__,
+			     "multiple resizers run on filesystem!");
+		err = -EBUSY;
+		goto exit_journal;
+	}
+
+	if ((err = ext4_journal_get_write_access(handle, sbi->s_sbh)))
+		goto exit_journal;
+
+	/*
+	 * We will only either add reserved group blocks to a backup group
+	 * or remove reserved blocks for the first group in a new group block.
+	 * Doing both would be mean more complex code, and sane people don't
+	 * use non-sparse filesystems anymore.  This is already checked above.
+	 */
+	if (gdb_off) {
+		primary = sbi->s_group_desc[gdb_num];
+		if ((err = ext4_journal_get_write_access(handle, primary)))
+			goto exit_journal;
+
+		if (reserved_gdb && ext4_bg_num_gdb(sb, input->group) &&
+		    (err = reserve_backup_gdb(handle, inode, input)))
+			goto exit_journal;
+	} else if ((err = add_new_gdb(handle, inode, input, &primary)))
+		goto exit_journal;
+
+	/*
+	 * OK, now we've set up the new group.  Time to make it active.
+	 *
+	 * Current kernels don't lock all allocations via lock_super(),
+	 * so we have to be safe wrt. concurrent accesses the group
+	 * data.  So we need to be careful to set all of the relevant
+	 * group descriptor data etc. *before* we enable the group.
+	 *
+	 * The key field here is sbi->s_groups_count: as long as
+	 * that retains its old value, nobody is going to access the new
+	 * group.
+	 *
+	 * So first we update all the descriptor metadata for the new
+	 * group; then we update the total disk blocks count; then we
+	 * update the groups count to enable the group; then finally we
+	 * update the free space counts so that the system can start
+	 * using the new disk blocks.
+	 */
+
+	/* Update group descriptor block for new group */
+	gdp = (struct ext4_group_desc *)primary->b_data + gdb_off;
+
+	ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */
+	ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */
+	ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */
+	gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count);
+	gdp->bg_free_inodes_count = cpu_to_le16(EXT4_INODES_PER_GROUP(sb));
+
+	/*
+	 * Make the new blocks and inodes valid next.  We do this before
+	 * increasing the group count so that once the group is enabled,
+	 * all of its blocks and inodes are already valid.
+	 *
+	 * We always allocate group-by-group, then block-by-block or
+	 * inode-by-inode within a group, so enabling these
+	 * blocks/inodes before the group is live won't actually let us
+	 * allocate the new space yet.
+	 */
+	ext4_blocks_count_set(es, ext4_blocks_count(es) +
+		input->blocks_count);
+	es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
+		EXT4_INODES_PER_GROUP(sb));
+
+	/*
+	 * We need to protect s_groups_count against other CPUs seeing
+	 * inconsistent state in the superblock.
+	 *
+	 * The precise rules we use are:
+	 *
+	 * * Writers of s_groups_count *must* hold lock_super
+	 * AND
+	 * * Writers must perform a smp_wmb() after updating all dependent
+	 *   data and before modifying the groups count
+	 *
+	 * * Readers must hold lock_super() over the access
+	 * OR
+	 * * Readers must perform an smp_rmb() after reading the groups count
+	 *   and before reading any dependent data.
+	 *
+	 * NB. These rules can be relaxed when checking the group count
+	 * while freeing data, as we can only allocate from a block
+	 * group after serialising against the group count, and we can
+	 * only then free after serialising in turn against that
+	 * allocation.
+	 */
+	smp_wmb();
+
+	/* Update the global fs size fields */
+	sbi->s_groups_count++;
+
+	ext4_journal_dirty_metadata(handle, primary);
+
+	/* Update the reserved block counts only once the new group is
+	 * active. */
+	ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +
+		input->reserved_blocks);
+
+	/* Update the free space counts */
+	percpu_counter_mod(&sbi->s_freeblocks_counter,
+			   input->free_blocks_count);
+	percpu_counter_mod(&sbi->s_freeinodes_counter,
+			   EXT4_INODES_PER_GROUP(sb));
+
+	ext4_journal_dirty_metadata(handle, sbi->s_sbh);
+	sb->s_dirt = 1;
+
+exit_journal:
+	unlock_super(sb);
+	if ((err2 = ext4_journal_stop(handle)) && !err)
+		err = err2;
+	if (!err) {
+		update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
+			       sizeof(struct ext4_super_block));
+		update_backups(sb, primary->b_blocknr, primary->b_data,
+			       primary->b_size);
+	}
+exit_put:
+	iput(inode);
+	return err;
+} /* ext4_group_add */
+
+/* Extend the filesystem to the new number of blocks specified.  This entry
+ * point is only used to extend the current filesystem to the end of the last
+ * existing group.  It can be accessed via ioctl, or by "remount,resize=<size>"
+ * for emergencies (because it has no dependencies on reserved blocks).
+ *
+ * If we _really_ wanted, we could use default values to call ext4_group_add()
+ * allow the "remount" trick to work for arbitrary resizing, assuming enough
+ * GDT blocks are reserved to grow to the desired size.
+ */
+int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+		      ext4_fsblk_t n_blocks_count)
+{
+	ext4_fsblk_t o_blocks_count;
+	unsigned long o_groups_count;
+	ext4_grpblk_t last;
+	ext4_grpblk_t add;
+	struct buffer_head * bh;
+	handle_t *handle;
+	int err;
+	unsigned long freed_blocks;
+
+	/* We don't need to worry about locking wrt other resizers just
+	 * yet: we're going to revalidate es->s_blocks_count after
+	 * taking lock_super() below. */
+	o_blocks_count = ext4_blocks_count(es);
+	o_groups_count = EXT4_SB(sb)->s_groups_count;
+
+	if (test_opt(sb, DEBUG))
+		printk(KERN_DEBUG "EXT4-fs: extending last group from %llu uto %llu blocks\n",
+		       o_blocks_count, n_blocks_count);
+
+	if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+		return 0;
+
+	if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+		printk(KERN_ERR "EXT4-fs: filesystem on %s:"
+			" too large to resize to %llu blocks safely\n",
+			sb->s_id, n_blocks_count);
+		if (sizeof(sector_t) < 8)
+			ext4_warning(sb, __FUNCTION__,
+			"CONFIG_LBD not enabled\n");
+		return -EINVAL;
+	}
+
+	if (n_blocks_count < o_blocks_count) {
+		ext4_warning(sb, __FUNCTION__,
+			     "can't shrink FS - resize aborted");
+		return -EBUSY;
+	}
+
+	/* Handle the remaining blocks in the last group only. */
+	ext4_get_group_no_and_offset(sb, o_blocks_count, NULL, &last);
+
+	if (last == 0) {
+		ext4_warning(sb, __FUNCTION__,
+			     "need to use ext2online to resize further");
+		return -EPERM;
+	}
+
+	add = EXT4_BLOCKS_PER_GROUP(sb) - last;
+
+	if (o_blocks_count + add < o_blocks_count) {
+		ext4_warning(sb, __FUNCTION__, "blocks_count overflow");
+		return -EINVAL;
+	}
+
+	if (o_blocks_count + add > n_blocks_count)
+		add = n_blocks_count - o_blocks_count;
+
+	if (o_blocks_count + add < n_blocks_count)
+		ext4_warning(sb, __FUNCTION__,
+			     "will only finish group (%llu"
+			     " blocks, %u new)",
+			     o_blocks_count + add, add);
+
+	/* See if the device is actually as big as what was requested */
+	bh = sb_bread(sb, o_blocks_count + add -1);
+	if (!bh) {
+		ext4_warning(sb, __FUNCTION__,
+			     "can't read last block, resize aborted");
+		return -ENOSPC;
+	}
+	brelse(bh);
+
+	/* We will update the superblock, one block bitmap, and
+	 * one group descriptor via ext4_free_blocks().
+	 */
+	handle = ext4_journal_start_sb(sb, 3);
+	if (IS_ERR(handle)) {
+		err = PTR_ERR(handle);
+		ext4_warning(sb, __FUNCTION__, "error %d on journal start",err);
+		goto exit_put;
+	}
+
+	lock_super(sb);
+	if (o_blocks_count != ext4_blocks_count(es)) {
+		ext4_warning(sb, __FUNCTION__,
+			     "multiple resizers run on filesystem!");
+		unlock_super(sb);
+		err = -EBUSY;
+		goto exit_put;
+	}
+
+	if ((err = ext4_journal_get_write_access(handle,
+						 EXT4_SB(sb)->s_sbh))) {
+		ext4_warning(sb, __FUNCTION__,
+			     "error %d on journal write access", err);
+		unlock_super(sb);
+		ext4_journal_stop(handle);
+		goto exit_put;
+	}
+	ext4_blocks_count_set(es, o_blocks_count + add);
+	ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
+	sb->s_dirt = 1;
+	unlock_super(sb);
+	ext4_debug("freeing blocks %lu through %llu\n", o_blocks_count,
+		   o_blocks_count + add);
+	ext4_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
+	ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
+		   o_blocks_count + add);
+	if ((err = ext4_journal_stop(handle)))
+		goto exit_put;
+	if (test_opt(sb, DEBUG))
+		printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n",
+		       ext4_blocks_count(es));
+	update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, (char *)es,
+		       sizeof(struct ext4_super_block));
+exit_put:
+	return err;
+} /* ext4_group_extend */
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
new file mode 100644
index 0000000..b4b022a
--- /dev/null
+++ b/fs/ext4/super.c
@@ -0,0 +1,2829 @@
+/*
+ *  linux/fs/ext4/super.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/inode.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/parser.h>
+#include <linux/smp_lock.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/random.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/quotaops.h>
+#include <linux/seq_file.h>
+
+#include <asm/uaccess.h>
+
+#include "xattr.h"
+#include "acl.h"
+#include "namei.h"
+
+static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+			     unsigned long journal_devnum);
+static int ext4_create_journal(struct super_block *, struct ext4_super_block *,
+			       unsigned int);
+static void ext4_commit_super (struct super_block * sb,
+			       struct ext4_super_block * es,
+			       int sync);
+static void ext4_mark_recovery_complete(struct super_block * sb,
+					struct ext4_super_block * es);
+static void ext4_clear_journal_err(struct super_block * sb,
+				   struct ext4_super_block * es);
+static int ext4_sync_fs(struct super_block *sb, int wait);
+static const char *ext4_decode_error(struct super_block * sb, int errno,
+				     char nbuf[16]);
+static int ext4_remount (struct super_block * sb, int * flags, char * data);
+static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf);
+static void ext4_unlockfs(struct super_block *sb);
+static void ext4_write_super (struct super_block * sb);
+static void ext4_write_super_lockfs(struct super_block *sb);
+
+
+ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+			       struct ext4_group_desc *bg)
+{
+	return le32_to_cpu(bg->bg_block_bitmap) |
+		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+		 (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
+}
+
+ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
+			       struct ext4_group_desc *bg)
+{
+	return le32_to_cpu(bg->bg_inode_bitmap) |
+		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+		 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
+}
+
+ext4_fsblk_t ext4_inode_table(struct super_block *sb,
+			      struct ext4_group_desc *bg)
+{
+	return le32_to_cpu(bg->bg_inode_table) |
+		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+		 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
+}
+
+void ext4_block_bitmap_set(struct super_block *sb,
+			   struct ext4_group_desc *bg, ext4_fsblk_t blk)
+{
+	bg->bg_block_bitmap = cpu_to_le32((u32)blk);
+	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+		bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
+}
+
+void ext4_inode_bitmap_set(struct super_block *sb,
+			   struct ext4_group_desc *bg, ext4_fsblk_t blk)
+{
+	bg->bg_inode_bitmap  = cpu_to_le32((u32)blk);
+	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+		bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
+}
+
+void ext4_inode_table_set(struct super_block *sb,
+			  struct ext4_group_desc *bg, ext4_fsblk_t blk)
+{
+	bg->bg_inode_table = cpu_to_le32((u32)blk);
+	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+		bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
+}
+
+/*
+ * Wrappers for jbd2_journal_start/end.
+ *
+ * The only special thing we need to do here is to make sure that all
+ * journal_end calls result in the superblock being marked dirty, so
+ * that sync() will call the filesystem's write_super callback if
+ * appropriate.
+ */
+handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+{
+	journal_t *journal;
+
+	if (sb->s_flags & MS_RDONLY)
+		return ERR_PTR(-EROFS);
+
+	/* Special case here: if the journal has aborted behind our
+	 * backs (eg. EIO in the commit thread), then we still need to
+	 * take the FS itself readonly cleanly. */
+	journal = EXT4_SB(sb)->s_journal;
+	if (is_journal_aborted(journal)) {
+		ext4_abort(sb, __FUNCTION__,
+			   "Detected aborted journal");
+		return ERR_PTR(-EROFS);
+	}
+
+	return jbd2_journal_start(journal, nblocks);
+}
+
+/*
+ * The only special thing we need to do here is to make sure that all
+ * jbd2_journal_stop calls result in the superblock being marked dirty, so
+ * that sync() will call the filesystem's write_super callback if
+ * appropriate.
+ */
+int __ext4_journal_stop(const char *where, handle_t *handle)
+{
+	struct super_block *sb;
+	int err;
+	int rc;
+
+	sb = handle->h_transaction->t_journal->j_private;
+	err = handle->h_err;
+	rc = jbd2_journal_stop(handle);
+
+	if (!err)
+		err = rc;
+	if (err)
+		__ext4_std_error(sb, where, err);
+	return err;
+}
+
+void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+		struct buffer_head *bh, handle_t *handle, int err)
+{
+	char nbuf[16];
+	const char *errstr = ext4_decode_error(NULL, err, nbuf);
+
+	if (bh)
+		BUFFER_TRACE(bh, "abort");
+
+	if (!handle->h_err)
+		handle->h_err = err;
+
+	if (is_handle_aborted(handle))
+		return;
+
+	printk(KERN_ERR "%s: aborting transaction: %s in %s\n",
+	       caller, errstr, err_fn);
+
+	jbd2_journal_abort_handle(handle);
+}
+
+/* Deal with the reporting of failure conditions on a filesystem such as
+ * inconsistencies detected or read IO failures.
+ *
+ * On ext2, we can store the error state of the filesystem in the
+ * superblock.  That is not possible on ext4, because we may have other
+ * write ordering constraints on the superblock which prevent us from
+ * writing it out straight away; and given that the journal is about to
+ * be aborted, we can't rely on the current, or future, transactions to
+ * write out the superblock safely.
+ *
+ * We'll just use the jbd2_journal_abort() error code to record an error in
+ * the journal instead.  On recovery, the journal will compain about
+ * that error until we've noted it down and cleared it.
+ */
+
+static void ext4_handle_error(struct super_block *sb)
+{
+	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
+	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+	es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+
+	if (sb->s_flags & MS_RDONLY)
+		return;
+
+	if (!test_opt (sb, ERRORS_CONT)) {
+		journal_t *journal = EXT4_SB(sb)->s_journal;
+
+		EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
+		if (journal)
+			jbd2_journal_abort(journal, -EIO);
+	}
+	if (test_opt (sb, ERRORS_RO)) {
+		printk (KERN_CRIT "Remounting filesystem read-only\n");
+		sb->s_flags |= MS_RDONLY;
+	}
+	ext4_commit_super(sb, es, 1);
+	if (test_opt(sb, ERRORS_PANIC))
+		panic("EXT4-fs (device %s): panic forced after error\n",
+			sb->s_id);
+}
+
+void ext4_error (struct super_block * sb, const char * function,
+		 const char * fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
+
+	ext4_handle_error(sb);
+}
+
+static const char *ext4_decode_error(struct super_block * sb, int errno,
+				     char nbuf[16])
+{
+	char *errstr = NULL;
+
+	switch (errno) {
+	case -EIO:
+		errstr = "IO failure";
+		break;
+	case -ENOMEM:
+		errstr = "Out of memory";
+		break;
+	case -EROFS:
+		if (!sb || EXT4_SB(sb)->s_journal->j_flags & JBD2_ABORT)
+			errstr = "Journal has aborted";
+		else
+			errstr = "Readonly filesystem";
+		break;
+	default:
+		/* If the caller passed in an extra buffer for unknown
+		 * errors, textualise them now.  Else we just return
+		 * NULL. */
+		if (nbuf) {
+			/* Check for truncated error codes... */
+			if (snprintf(nbuf, 16, "error %d", -errno) >= 0)
+				errstr = nbuf;
+		}
+		break;
+	}
+
+	return errstr;
+}
+
+/* __ext4_std_error decodes expected errors from journaling functions
+ * automatically and invokes the appropriate error response.  */
+
+void __ext4_std_error (struct super_block * sb, const char * function,
+		       int errno)
+{
+	char nbuf[16];
+	const char *errstr;
+
+	/* Special case: if the error is EROFS, and we're not already
+	 * inside a transaction, then there's really no point in logging
+	 * an error. */
+	if (errno == -EROFS && journal_current_handle() == NULL &&
+	    (sb->s_flags & MS_RDONLY))
+		return;
+
+	errstr = ext4_decode_error(sb, errno, nbuf);
+	printk (KERN_CRIT "EXT4-fs error (device %s) in %s: %s\n",
+		sb->s_id, function, errstr);
+
+	ext4_handle_error(sb);
+}
+
+/*
+ * ext4_abort is a much stronger failure handler than ext4_error.  The
+ * abort function may be used to deal with unrecoverable failures such
+ * as journal IO errors or ENOMEM at a critical moment in log management.
+ *
+ * We unconditionally force the filesystem into an ABORT|READONLY state,
+ * unless the error response on the fs has been set to panic in which
+ * case we take the easy way out and panic immediately.
+ */
+
+void ext4_abort (struct super_block * sb, const char * function,
+		 const char * fmt, ...)
+{
+	va_list args;
+
+	printk (KERN_CRIT "ext4_abort called.\n");
+
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
+
+	if (test_opt(sb, ERRORS_PANIC))
+		panic("EXT4-fs panic from previous error\n");
+
+	if (sb->s_flags & MS_RDONLY)
+		return;
+
+	printk(KERN_CRIT "Remounting filesystem read-only\n");
+	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+	sb->s_flags |= MS_RDONLY;
+	EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
+	jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+}
+
+void ext4_warning (struct super_block * sb, const char * function,
+		   const char * fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	printk(KERN_WARNING "EXT4-fs warning (device %s): %s: ",
+	       sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
+}
+
+void ext4_update_dynamic_rev(struct super_block *sb)
+{
+	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
+	if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)
+		return;
+
+	ext4_warning(sb, __FUNCTION__,
+		     "updating to rev %d because of new feature flag, "
+		     "running e2fsck is recommended",
+		     EXT4_DYNAMIC_REV);
+
+	es->s_first_ino = cpu_to_le32(EXT4_GOOD_OLD_FIRST_INO);
+	es->s_inode_size = cpu_to_le16(EXT4_GOOD_OLD_INODE_SIZE);
+	es->s_rev_level = cpu_to_le32(EXT4_DYNAMIC_REV);
+	/* leave es->s_feature_*compat flags alone */
+	/* es->s_uuid will be set by e2fsck if empty */
+
+	/*
+	 * The rest of the superblock fields should be zero, and if not it
+	 * means they are likely already in use, so leave them alone.  We
+	 * can leave it up to e2fsck to clean up any inconsistencies there.
+	 */
+}
+
+/*
+ * Open the external journal device
+ */
+static struct block_device *ext4_blkdev_get(dev_t dev)
+{
+	struct block_device *bdev;
+	char b[BDEVNAME_SIZE];
+
+	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+	if (IS_ERR(bdev))
+		goto fail;
+	return bdev;
+
+fail:
+	printk(KERN_ERR "EXT4: failed to open journal device %s: %ld\n",
+			__bdevname(dev, b), PTR_ERR(bdev));
+	return NULL;
+}
+
+/*
+ * Release the journal device
+ */
+static int ext4_blkdev_put(struct block_device *bdev)
+{
+	bd_release(bdev);
+	return blkdev_put(bdev);
+}
+
+static int ext4_blkdev_remove(struct ext4_sb_info *sbi)
+{
+	struct block_device *bdev;
+	int ret = -ENODEV;
+
+	bdev = sbi->journal_bdev;
+	if (bdev) {
+		ret = ext4_blkdev_put(bdev);
+		sbi->journal_bdev = NULL;
+	}
+	return ret;
+}
+
+static inline struct inode *orphan_list_entry(struct list_head *l)
+{
+	return &list_entry(l, struct ext4_inode_info, i_orphan)->vfs_inode;
+}
+
+static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi)
+{
+	struct list_head *l;
+
+	printk(KERN_ERR "sb orphan head is %d\n",
+	       le32_to_cpu(sbi->s_es->s_last_orphan));
+
+	printk(KERN_ERR "sb_info orphan list:\n");
+	list_for_each(l, &sbi->s_orphan) {
+		struct inode *inode = orphan_list_entry(l);
+		printk(KERN_ERR "  "
+		       "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
+		       inode->i_sb->s_id, inode->i_ino, inode,
+		       inode->i_mode, inode->i_nlink,
+		       NEXT_ORPHAN(inode));
+	}
+}
+
+static void ext4_put_super (struct super_block * sb)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_super_block *es = sbi->s_es;
+	int i;
+
+	ext4_ext_release(sb);
+	ext4_xattr_put_super(sb);
+	jbd2_journal_destroy(sbi->s_journal);
+	if (!(sb->s_flags & MS_RDONLY)) {
+		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+		es->s_state = cpu_to_le16(sbi->s_mount_state);
+		BUFFER_TRACE(sbi->s_sbh, "marking dirty");
+		mark_buffer_dirty(sbi->s_sbh);
+		ext4_commit_super(sb, es, 1);
+	}
+
+	for (i = 0; i < sbi->s_gdb_count; i++)
+		brelse(sbi->s_group_desc[i]);
+	kfree(sbi->s_group_desc);
+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+	percpu_counter_destroy(&sbi->s_dirs_counter);
+	brelse(sbi->s_sbh);
+#ifdef CONFIG_QUOTA
+	for (i = 0; i < MAXQUOTAS; i++)
+		kfree(sbi->s_qf_names[i]);
+#endif
+
+	/* Debugging code just in case the in-memory inode orphan list
+	 * isn't empty.  The on-disk one can be non-empty if we've
+	 * detected an error and taken the fs readonly, but the
+	 * in-memory list had better be clean by this point. */
+	if (!list_empty(&sbi->s_orphan))
+		dump_orphan_list(sb, sbi);
+	J_ASSERT(list_empty(&sbi->s_orphan));
+
+	invalidate_bdev(sb->s_bdev, 0);
+	if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
+		/*
+		 * Invalidate the journal device's buffers.  We don't want them
+		 * floating about in memory - the physical journal device may
+		 * hotswapped, and it breaks the `ro-after' testing code.
+		 */
+		sync_blockdev(sbi->journal_bdev);
+		invalidate_bdev(sbi->journal_bdev, 0);
+		ext4_blkdev_remove(sbi);
+	}
+	sb->s_fs_info = NULL;
+	kfree(sbi);
+	return;
+}
+
+static kmem_cache_t *ext4_inode_cachep;
+
+/*
+ * Called inside transaction, so use GFP_NOFS
+ */
+static struct inode *ext4_alloc_inode(struct super_block *sb)
+{
+	struct ext4_inode_info *ei;
+
+	ei = kmem_cache_alloc(ext4_inode_cachep, SLAB_NOFS);
+	if (!ei)
+		return NULL;
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+	ei->i_acl = EXT4_ACL_NOT_CACHED;
+	ei->i_default_acl = EXT4_ACL_NOT_CACHED;
+#endif
+	ei->i_block_alloc_info = NULL;
+	ei->vfs_inode.i_version = 1;
+	memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
+	return &ei->vfs_inode;
+}
+
+static void ext4_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		INIT_LIST_HEAD(&ei->i_orphan);
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+		init_rwsem(&ei->xattr_sem);
+#endif
+		mutex_init(&ei->truncate_mutex);
+		inode_init_once(&ei->vfs_inode);
+	}
+}
+
+static int init_inodecache(void)
+{
+	ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
+					     sizeof(struct ext4_inode_info),
+					     0, (SLAB_RECLAIM_ACCOUNT|
+						SLAB_MEM_SPREAD),
+					     init_once, NULL);
+	if (ext4_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	kmem_cache_destroy(ext4_inode_cachep);
+}
+
+static void ext4_clear_inode(struct inode *inode)
+{
+	struct ext4_block_alloc_info *rsv = EXT4_I(inode)->i_block_alloc_info;
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+	if (EXT4_I(inode)->i_acl &&
+			EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) {
+		posix_acl_release(EXT4_I(inode)->i_acl);
+		EXT4_I(inode)->i_acl = EXT4_ACL_NOT_CACHED;
+	}
+	if (EXT4_I(inode)->i_default_acl &&
+			EXT4_I(inode)->i_default_acl != EXT4_ACL_NOT_CACHED) {
+		posix_acl_release(EXT4_I(inode)->i_default_acl);
+		EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED;
+	}
+#endif
+	ext4_discard_reservation(inode);
+	EXT4_I(inode)->i_block_alloc_info = NULL;
+	if (unlikely(rsv))
+		kfree(rsv);
+}
+
+static inline void ext4_show_quota_options(struct seq_file *seq, struct super_block *sb)
+{
+#if defined(CONFIG_QUOTA)
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+	if (sbi->s_jquota_fmt)
+		seq_printf(seq, ",jqfmt=%s",
+		(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
+
+	if (sbi->s_qf_names[USRQUOTA])
+		seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+
+	if (sbi->s_qf_names[GRPQUOTA])
+		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
+
+	if (sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA)
+		seq_puts(seq, ",usrquota");
+
+	if (sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA)
+		seq_puts(seq, ",grpquota");
+#endif
+}
+
+static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+	struct super_block *sb = vfs->mnt_sb;
+
+	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+		seq_puts(seq, ",data=journal");
+	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+		seq_puts(seq, ",data=ordered");
+	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+		seq_puts(seq, ",data=writeback");
+
+	ext4_show_quota_options(seq, sb);
+
+	return 0;
+}
+
+
+static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
+		return ERR_PTR(-ESTALE);
+	if (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
+		return ERR_PTR(-ESTALE);
+
+	/* iget isn't really right if the inode is currently unallocated!!
+	 *
+	 * ext4_read_inode will return a bad_inode if the inode had been
+	 * deleted, so we should be safe.
+	 *
+	 * Currently we don't know the generation for parent directory, so
+	 * a generation of 0 means "accept any"
+	 */
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+	/* now to find a dentry.
+	 * If possible, get a well-connected one
+	 */
+	result = d_alloc_anon(inode);
+	if (!result) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
+	}
+	return result;
+}
+
+#ifdef CONFIG_QUOTA
+#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
+#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
+
+static int ext4_dquot_initialize(struct inode *inode, int type);
+static int ext4_dquot_drop(struct inode *inode);
+static int ext4_write_dquot(struct dquot *dquot);
+static int ext4_acquire_dquot(struct dquot *dquot);
+static int ext4_release_dquot(struct dquot *dquot);
+static int ext4_mark_dquot_dirty(struct dquot *dquot);
+static int ext4_write_info(struct super_block *sb, int type);
+static int ext4_quota_on(struct super_block *sb, int type, int format_id, char *path);
+static int ext4_quota_on_mount(struct super_block *sb, int type);
+static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
+			       size_t len, loff_t off);
+static ssize_t ext4_quota_write(struct super_block *sb, int type,
+				const char *data, size_t len, loff_t off);
+
+static struct dquot_operations ext4_quota_operations = {
+	.initialize	= ext4_dquot_initialize,
+	.drop		= ext4_dquot_drop,
+	.alloc_space	= dquot_alloc_space,
+	.alloc_inode	= dquot_alloc_inode,
+	.free_space	= dquot_free_space,
+	.free_inode	= dquot_free_inode,
+	.transfer	= dquot_transfer,
+	.write_dquot	= ext4_write_dquot,
+	.acquire_dquot	= ext4_acquire_dquot,
+	.release_dquot	= ext4_release_dquot,
+	.mark_dirty	= ext4_mark_dquot_dirty,
+	.write_info	= ext4_write_info
+};
+
+static struct quotactl_ops ext4_qctl_operations = {
+	.quota_on	= ext4_quota_on,
+	.quota_off	= vfs_quota_off,
+	.quota_sync	= vfs_quota_sync,
+	.get_info	= vfs_get_dqinfo,
+	.set_info	= vfs_set_dqinfo,
+	.get_dqblk	= vfs_get_dqblk,
+	.set_dqblk	= vfs_set_dqblk
+};
+#endif
+
+static struct super_operations ext4_sops = {
+	.alloc_inode	= ext4_alloc_inode,
+	.destroy_inode	= ext4_destroy_inode,
+	.read_inode	= ext4_read_inode,
+	.write_inode	= ext4_write_inode,
+	.dirty_inode	= ext4_dirty_inode,
+	.delete_inode	= ext4_delete_inode,
+	.put_super	= ext4_put_super,
+	.write_super	= ext4_write_super,
+	.sync_fs	= ext4_sync_fs,
+	.write_super_lockfs = ext4_write_super_lockfs,
+	.unlockfs	= ext4_unlockfs,
+	.statfs		= ext4_statfs,
+	.remount_fs	= ext4_remount,
+	.clear_inode	= ext4_clear_inode,
+	.show_options	= ext4_show_options,
+#ifdef CONFIG_QUOTA
+	.quota_read	= ext4_quota_read,
+	.quota_write	= ext4_quota_write,
+#endif
+};
+
+static struct export_operations ext4_export_ops = {
+	.get_parent = ext4_get_parent,
+	.get_dentry = ext4_get_dentry,
+};
+
+enum {
+	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
+	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
+	Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
+	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
+	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
+	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+	Opt_grpquota, Opt_extents,
+};
+
+static match_table_t tokens = {
+	{Opt_bsd_df, "bsddf"},
+	{Opt_minix_df, "minixdf"},
+	{Opt_grpid, "grpid"},
+	{Opt_grpid, "bsdgroups"},
+	{Opt_nogrpid, "nogrpid"},
+	{Opt_nogrpid, "sysvgroups"},
+	{Opt_resgid, "resgid=%u"},
+	{Opt_resuid, "resuid=%u"},
+	{Opt_sb, "sb=%u"},
+	{Opt_err_cont, "errors=continue"},
+	{Opt_err_panic, "errors=panic"},
+	{Opt_err_ro, "errors=remount-ro"},
+	{Opt_nouid32, "nouid32"},
+	{Opt_nocheck, "nocheck"},
+	{Opt_nocheck, "check=none"},
+	{Opt_debug, "debug"},
+	{Opt_oldalloc, "oldalloc"},
+	{Opt_orlov, "orlov"},
+	{Opt_user_xattr, "user_xattr"},
+	{Opt_nouser_xattr, "nouser_xattr"},
+	{Opt_acl, "acl"},
+	{Opt_noacl, "noacl"},
+	{Opt_reservation, "reservation"},
+	{Opt_noreservation, "noreservation"},
+	{Opt_noload, "noload"},
+	{Opt_nobh, "nobh"},
+	{Opt_bh, "bh"},
+	{Opt_commit, "commit=%u"},
+	{Opt_journal_update, "journal=update"},
+	{Opt_journal_inum, "journal=%u"},
+	{Opt_journal_dev, "journal_dev=%u"},
+	{Opt_abort, "abort"},
+	{Opt_data_journal, "data=journal"},
+	{Opt_data_ordered, "data=ordered"},
+	{Opt_data_writeback, "data=writeback"},
+	{Opt_offusrjquota, "usrjquota="},
+	{Opt_usrjquota, "usrjquota=%s"},
+	{Opt_offgrpjquota, "grpjquota="},
+	{Opt_grpjquota, "grpjquota=%s"},
+	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
+	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
+	{Opt_grpquota, "grpquota"},
+	{Opt_noquota, "noquota"},
+	{Opt_quota, "quota"},
+	{Opt_usrquota, "usrquota"},
+	{Opt_barrier, "barrier=%u"},
+	{Opt_extents, "extents"},
+	{Opt_err, NULL},
+	{Opt_resize, "resize"},
+};
+
+static ext4_fsblk_t get_sb_block(void **data)
+{
+	ext4_fsblk_t	sb_block;
+	char		*options = (char *) *data;
+
+	if (!options || strncmp(options, "sb=", 3) != 0)
+		return 1;	/* Default location */
+	options += 3;
+	/*todo: use simple_strtoll with >32bit ext4 */
+	sb_block = simple_strtoul(options, &options, 0);
+	if (*options && *options != ',') {
+		printk("EXT4-fs: Invalid sb specification: %s\n",
+		       (char *) *data);
+		return 1;
+	}
+	if (*options == ',')
+		options++;
+	*data = (void *) options;
+	return sb_block;
+}
+
+static int parse_options (char *options, struct super_block *sb,
+			  unsigned int *inum, unsigned long *journal_devnum,
+			  ext4_fsblk_t *n_blocks_count, int is_remount)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	char * p;
+	substring_t args[MAX_OPT_ARGS];
+	int data_opt = 0;
+	int option;
+#ifdef CONFIG_QUOTA
+	int qtype;
+	char *qname;
+#endif
+
+	if (!options)
+		return 1;
+
+	while ((p = strsep (&options, ",")) != NULL) {
+		int token;
+		if (!*p)
+			continue;
+
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_bsd_df:
+			clear_opt (sbi->s_mount_opt, MINIX_DF);
+			break;
+		case Opt_minix_df:
+			set_opt (sbi->s_mount_opt, MINIX_DF);
+			break;
+		case Opt_grpid:
+			set_opt (sbi->s_mount_opt, GRPID);
+			break;
+		case Opt_nogrpid:
+			clear_opt (sbi->s_mount_opt, GRPID);
+			break;
+		case Opt_resuid:
+			if (match_int(&args[0], &option))
+				return 0;
+			sbi->s_resuid = option;
+			break;
+		case Opt_resgid:
+			if (match_int(&args[0], &option))
+				return 0;
+			sbi->s_resgid = option;
+			break;
+		case Opt_sb:
+			/* handled by get_sb_block() instead of here */
+			/* *sb_block = match_int(&args[0]); */
+			break;
+		case Opt_err_panic:
+			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+			clear_opt (sbi->s_mount_opt, ERRORS_RO);
+			set_opt (sbi->s_mount_opt, ERRORS_PANIC);
+			break;
+		case Opt_err_ro:
+			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+			set_opt (sbi->s_mount_opt, ERRORS_RO);
+			break;
+		case Opt_err_cont:
+			clear_opt (sbi->s_mount_opt, ERRORS_RO);
+			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+			set_opt (sbi->s_mount_opt, ERRORS_CONT);
+			break;
+		case Opt_nouid32:
+			set_opt (sbi->s_mount_opt, NO_UID32);
+			break;
+		case Opt_nocheck:
+			clear_opt (sbi->s_mount_opt, CHECK);
+			break;
+		case Opt_debug:
+			set_opt (sbi->s_mount_opt, DEBUG);
+			break;
+		case Opt_oldalloc:
+			set_opt (sbi->s_mount_opt, OLDALLOC);
+			break;
+		case Opt_orlov:
+			clear_opt (sbi->s_mount_opt, OLDALLOC);
+			break;
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+		case Opt_user_xattr:
+			set_opt (sbi->s_mount_opt, XATTR_USER);
+			break;
+		case Opt_nouser_xattr:
+			clear_opt (sbi->s_mount_opt, XATTR_USER);
+			break;
+#else
+		case Opt_user_xattr:
+		case Opt_nouser_xattr:
+			printk("EXT4 (no)user_xattr options not supported\n");
+			break;
+#endif
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+		case Opt_acl:
+			set_opt(sbi->s_mount_opt, POSIX_ACL);
+			break;
+		case Opt_noacl:
+			clear_opt(sbi->s_mount_opt, POSIX_ACL);
+			break;
+#else
+		case Opt_acl:
+		case Opt_noacl:
+			printk("EXT4 (no)acl options not supported\n");
+			break;
+#endif
+		case Opt_reservation:
+			set_opt(sbi->s_mount_opt, RESERVATION);
+			break;
+		case Opt_noreservation:
+			clear_opt(sbi->s_mount_opt, RESERVATION);
+			break;
+		case Opt_journal_update:
+			/* @@@ FIXME */
+			/* Eventually we will want to be able to create
+			   a journal file here.  For now, only allow the
+			   user to specify an existing inode to be the
+			   journal file. */
+			if (is_remount) {
+				printk(KERN_ERR "EXT4-fs: cannot specify "
+				       "journal on remount\n");
+				return 0;
+			}
+			set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
+			break;
+		case Opt_journal_inum:
+			if (is_remount) {
+				printk(KERN_ERR "EXT4-fs: cannot specify "
+				       "journal on remount\n");
+				return 0;
+			}
+			if (match_int(&args[0], &option))
+				return 0;
+			*inum = option;
+			break;
+		case Opt_journal_dev:
+			if (is_remount) {
+				printk(KERN_ERR "EXT4-fs: cannot specify "
+				       "journal on remount\n");
+				return 0;
+			}
+			if (match_int(&args[0], &option))
+				return 0;
+			*journal_devnum = option;
+			break;
+		case Opt_noload:
+			set_opt (sbi->s_mount_opt, NOLOAD);
+			break;
+		case Opt_commit:
+			if (match_int(&args[0], &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			if (option == 0)
+				option = JBD_DEFAULT_MAX_COMMIT_AGE;
+			sbi->s_commit_interval = HZ * option;
+			break;
+		case Opt_data_journal:
+			data_opt = EXT4_MOUNT_JOURNAL_DATA;
+			goto datacheck;
+		case Opt_data_ordered:
+			data_opt = EXT4_MOUNT_ORDERED_DATA;
+			goto datacheck;
+		case Opt_data_writeback:
+			data_opt = EXT4_MOUNT_WRITEBACK_DATA;
+		datacheck:
+			if (is_remount) {
+				if ((sbi->s_mount_opt & EXT4_MOUNT_DATA_FLAGS)
+						!= data_opt) {
+					printk(KERN_ERR
+						"EXT4-fs: cannot change data "
+						"mode on remount\n");
+					return 0;
+				}
+			} else {
+				sbi->s_mount_opt &= ~EXT4_MOUNT_DATA_FLAGS;
+				sbi->s_mount_opt |= data_opt;
+			}
+			break;
+#ifdef CONFIG_QUOTA
+		case Opt_usrjquota:
+			qtype = USRQUOTA;
+			goto set_qf_name;
+		case Opt_grpjquota:
+			qtype = GRPQUOTA;
+set_qf_name:
+			if (sb_any_quota_enabled(sb)) {
+				printk(KERN_ERR
+					"EXT4-fs: Cannot change journalled "
+					"quota options when quota turned on.\n");
+				return 0;
+			}
+			qname = match_strdup(&args[0]);
+			if (!qname) {
+				printk(KERN_ERR
+					"EXT4-fs: not enough memory for "
+					"storing quotafile name.\n");
+				return 0;
+			}
+			if (sbi->s_qf_names[qtype] &&
+			    strcmp(sbi->s_qf_names[qtype], qname)) {
+				printk(KERN_ERR
+					"EXT4-fs: %s quota file already "
+					"specified.\n", QTYPE2NAME(qtype));
+				kfree(qname);
+				return 0;
+			}
+			sbi->s_qf_names[qtype] = qname;
+			if (strchr(sbi->s_qf_names[qtype], '/')) {
+				printk(KERN_ERR
+					"EXT4-fs: quotafile must be on "
+					"filesystem root.\n");
+				kfree(sbi->s_qf_names[qtype]);
+				sbi->s_qf_names[qtype] = NULL;
+				return 0;
+			}
+			set_opt(sbi->s_mount_opt, QUOTA);
+			break;
+		case Opt_offusrjquota:
+			qtype = USRQUOTA;
+			goto clear_qf_name;
+		case Opt_offgrpjquota:
+			qtype = GRPQUOTA;
+clear_qf_name:
+			if (sb_any_quota_enabled(sb)) {
+				printk(KERN_ERR "EXT4-fs: Cannot change "
+					"journalled quota options when "
+					"quota turned on.\n");
+				return 0;
+			}
+			/*
+			 * The space will be released later when all options
+			 * are confirmed to be correct
+			 */
+			sbi->s_qf_names[qtype] = NULL;
+			break;
+		case Opt_jqfmt_vfsold:
+			sbi->s_jquota_fmt = QFMT_VFS_OLD;
+			break;
+		case Opt_jqfmt_vfsv0:
+			sbi->s_jquota_fmt = QFMT_VFS_V0;
+			break;
+		case Opt_quota:
+		case Opt_usrquota:
+			set_opt(sbi->s_mount_opt, QUOTA);
+			set_opt(sbi->s_mount_opt, USRQUOTA);
+			break;
+		case Opt_grpquota:
+			set_opt(sbi->s_mount_opt, QUOTA);
+			set_opt(sbi->s_mount_opt, GRPQUOTA);
+			break;
+		case Opt_noquota:
+			if (sb_any_quota_enabled(sb)) {
+				printk(KERN_ERR "EXT4-fs: Cannot change quota "
+					"options when quota turned on.\n");
+				return 0;
+			}
+			clear_opt(sbi->s_mount_opt, QUOTA);
+			clear_opt(sbi->s_mount_opt, USRQUOTA);
+			clear_opt(sbi->s_mount_opt, GRPQUOTA);
+			break;
+#else
+		case Opt_quota:
+		case Opt_usrquota:
+		case Opt_grpquota:
+		case Opt_usrjquota:
+		case Opt_grpjquota:
+		case Opt_offusrjquota:
+		case Opt_offgrpjquota:
+		case Opt_jqfmt_vfsold:
+		case Opt_jqfmt_vfsv0:
+			printk(KERN_ERR
+				"EXT4-fs: journalled quota options not "
+				"supported.\n");
+			break;
+		case Opt_noquota:
+			break;
+#endif
+		case Opt_abort:
+			set_opt(sbi->s_mount_opt, ABORT);
+			break;
+		case Opt_barrier:
+			if (match_int(&args[0], &option))
+				return 0;
+			if (option)
+				set_opt(sbi->s_mount_opt, BARRIER);
+			else
+				clear_opt(sbi->s_mount_opt, BARRIER);
+			break;
+		case Opt_ignore:
+			break;
+		case Opt_resize:
+			if (!is_remount) {
+				printk("EXT4-fs: resize option only available "
+					"for remount\n");
+				return 0;
+			}
+			if (match_int(&args[0], &option) != 0)
+				return 0;
+			*n_blocks_count = option;
+			break;
+		case Opt_nobh:
+			set_opt(sbi->s_mount_opt, NOBH);
+			break;
+		case Opt_bh:
+			clear_opt(sbi->s_mount_opt, NOBH);
+			break;
+		case Opt_extents:
+			set_opt (sbi->s_mount_opt, EXTENTS);
+			break;
+		default:
+			printk (KERN_ERR
+				"EXT4-fs: Unrecognized mount option \"%s\" "
+				"or missing value\n", p);
+			return 0;
+		}
+	}
+#ifdef CONFIG_QUOTA
+	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+		if ((sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA) &&
+		     sbi->s_qf_names[USRQUOTA])
+			clear_opt(sbi->s_mount_opt, USRQUOTA);
+
+		if ((sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA) &&
+		     sbi->s_qf_names[GRPQUOTA])
+			clear_opt(sbi->s_mount_opt, GRPQUOTA);
+
+		if ((sbi->s_qf_names[USRQUOTA] &&
+				(sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA)) ||
+		    (sbi->s_qf_names[GRPQUOTA] &&
+				(sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA))) {
+			printk(KERN_ERR "EXT4-fs: old and new quota "
+					"format mixing.\n");
+			return 0;
+		}
+
+		if (!sbi->s_jquota_fmt) {
+			printk(KERN_ERR "EXT4-fs: journalled quota format "
+					"not specified.\n");
+			return 0;
+		}
+	} else {
+		if (sbi->s_jquota_fmt) {
+			printk(KERN_ERR "EXT4-fs: journalled quota format "
+					"specified with no journalling "
+					"enabled.\n");
+			return 0;
+		}
+	}
+#endif
+	return 1;
+}
+
+static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+			    int read_only)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	int res = 0;
+
+	if (le32_to_cpu(es->s_rev_level) > EXT4_MAX_SUPP_REV) {
+		printk (KERN_ERR "EXT4-fs warning: revision level too high, "
+			"forcing read-only mode\n");
+		res = MS_RDONLY;
+	}
+	if (read_only)
+		return res;
+	if (!(sbi->s_mount_state & EXT4_VALID_FS))
+		printk (KERN_WARNING "EXT4-fs warning: mounting unchecked fs, "
+			"running e2fsck is recommended\n");
+	else if ((sbi->s_mount_state & EXT4_ERROR_FS))
+		printk (KERN_WARNING
+			"EXT4-fs warning: mounting fs with errors, "
+			"running e2fsck is recommended\n");
+	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
+		 le16_to_cpu(es->s_mnt_count) >=
+		 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
+		printk (KERN_WARNING
+			"EXT4-fs warning: maximal mount count reached, "
+			"running e2fsck is recommended\n");
+	else if (le32_to_cpu(es->s_checkinterval) &&
+		(le32_to_cpu(es->s_lastcheck) +
+			le32_to_cpu(es->s_checkinterval) <= get_seconds()))
+		printk (KERN_WARNING
+			"EXT4-fs warning: checktime reached, "
+			"running e2fsck is recommended\n");
+#if 0
+		/* @@@ We _will_ want to clear the valid bit if we find
+		 * inconsistencies, to force a fsck at reboot.  But for
+		 * a plain journaled filesystem we can keep it set as
+		 * valid forever! :)
+		 */
+	es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT4_VALID_FS);
+#endif
+	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
+		es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
+	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
+	es->s_mtime = cpu_to_le32(get_seconds());
+	ext4_update_dynamic_rev(sb);
+	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+
+	ext4_commit_super(sb, es, 1);
+	if (test_opt(sb, DEBUG))
+		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%lu, "
+				"bpg=%lu, ipg=%lu, mo=%04lx]\n",
+			sb->s_blocksize,
+			sbi->s_groups_count,
+			EXT4_BLOCKS_PER_GROUP(sb),
+			EXT4_INODES_PER_GROUP(sb),
+			sbi->s_mount_opt);
+
+	printk(KERN_INFO "EXT4 FS on %s, ", sb->s_id);
+	if (EXT4_SB(sb)->s_journal->j_inode == NULL) {
+		char b[BDEVNAME_SIZE];
+
+		printk("external journal on %s\n",
+			bdevname(EXT4_SB(sb)->s_journal->j_dev, b));
+	} else {
+		printk("internal journal\n");
+	}
+	return res;
+}
+
+/* Called at mount-time, super-block is locked */
+static int ext4_check_descriptors (struct super_block * sb)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+	ext4_fsblk_t last_block;
+	ext4_fsblk_t block_bitmap;
+	ext4_fsblk_t inode_bitmap;
+	ext4_fsblk_t inode_table;
+	struct ext4_group_desc * gdp = NULL;
+	int desc_block = 0;
+	int i;
+
+	ext4_debug ("Checking group descriptors");
+
+	for (i = 0; i < sbi->s_groups_count; i++)
+	{
+		if (i == sbi->s_groups_count - 1)
+			last_block = ext4_blocks_count(sbi->s_es) - 1;
+		else
+			last_block = first_block +
+				(EXT4_BLOCKS_PER_GROUP(sb) - 1);
+
+		if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
+			gdp = (struct ext4_group_desc *)
+					sbi->s_group_desc[desc_block++]->b_data;
+		block_bitmap = ext4_block_bitmap(sb, gdp);
+		if (block_bitmap < first_block || block_bitmap > last_block)
+		{
+			ext4_error (sb, "ext4_check_descriptors",
+				    "Block bitmap for group %d"
+				    " not in group (block %llu)!",
+				    i, block_bitmap);
+			return 0;
+		}
+		inode_bitmap = ext4_inode_bitmap(sb, gdp);
+		if (inode_bitmap < first_block || inode_bitmap > last_block)
+		{
+			ext4_error (sb, "ext4_check_descriptors",
+				    "Inode bitmap for group %d"
+				    " not in group (block %llu)!",
+				    i, inode_bitmap);
+			return 0;
+		}
+		inode_table = ext4_inode_table(sb, gdp);
+		if (inode_table < first_block ||
+		    inode_table + sbi->s_itb_per_group > last_block)
+		{
+			ext4_error (sb, "ext4_check_descriptors",
+				    "Inode table for group %d"
+				    " not in group (block %llu)!",
+				    i, inode_table);
+			return 0;
+		}
+		first_block += EXT4_BLOCKS_PER_GROUP(sb);
+		gdp = (struct ext4_group_desc *)
+			((__u8 *)gdp + EXT4_DESC_SIZE(sb));
+	}
+
+	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
+	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext4_count_free_inodes(sb));
+	return 1;
+}
+
+
+/* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at
+ * the superblock) which were deleted from all directories, but held open by
+ * a process at the time of a crash.  We walk the list and try to delete these
+ * inodes at recovery time (only with a read-write filesystem).
+ *
+ * In order to keep the orphan inode chain consistent during traversal (in
+ * case of crash during recovery), we link each inode into the superblock
+ * orphan list_head and handle it the same way as an inode deletion during
+ * normal operation (which journals the operations for us).
+ *
+ * We only do an iget() and an iput() on each inode, which is very safe if we
+ * accidentally point at an in-use or already deleted inode.  The worst that
+ * can happen in this case is that we get a "bit already cleared" message from
+ * ext4_free_inode().  The only reason we would point at a wrong inode is if
+ * e2fsck was run on this filesystem, and it must have already done the orphan
+ * inode cleanup for us, so we can safely abort without any further action.
+ */
+static void ext4_orphan_cleanup (struct super_block * sb,
+				 struct ext4_super_block * es)
+{
+	unsigned int s_flags = sb->s_flags;
+	int nr_orphans = 0, nr_truncates = 0;
+#ifdef CONFIG_QUOTA
+	int i;
+#endif
+	if (!es->s_last_orphan) {
+		jbd_debug(4, "no orphan inodes to clean up\n");
+		return;
+	}
+
+	if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
+		if (es->s_last_orphan)
+			jbd_debug(1, "Errors on filesystem, "
+				  "clearing orphan list.\n");
+		es->s_last_orphan = 0;
+		jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
+		return;
+	}
+
+	if (s_flags & MS_RDONLY) {
+		printk(KERN_INFO "EXT4-fs: %s: orphan cleanup on readonly fs\n",
+		       sb->s_id);
+		sb->s_flags &= ~MS_RDONLY;
+	}
+#ifdef CONFIG_QUOTA
+	/* Needed for iput() to work correctly and not trash data */
+	sb->s_flags |= MS_ACTIVE;
+	/* Turn on quotas so that they are updated correctly */
+	for (i = 0; i < MAXQUOTAS; i++) {
+		if (EXT4_SB(sb)->s_qf_names[i]) {
+			int ret = ext4_quota_on_mount(sb, i);
+			if (ret < 0)
+				printk(KERN_ERR
+					"EXT4-fs: Cannot turn on journalled "
+					"quota: error %d\n", ret);
+		}
+	}
+#endif
+
+	while (es->s_last_orphan) {
+		struct inode *inode;
+
+		if (!(inode =
+		      ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {
+			es->s_last_orphan = 0;
+			break;
+		}
+
+		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
+		DQUOT_INIT(inode);
+		if (inode->i_nlink) {
+			printk(KERN_DEBUG
+				"%s: truncating inode %lu to %Ld bytes\n",
+				__FUNCTION__, inode->i_ino, inode->i_size);
+			jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
+				  inode->i_ino, inode->i_size);
+			ext4_truncate(inode);
+			nr_truncates++;
+		} else {
+			printk(KERN_DEBUG
+				"%s: deleting unreferenced inode %lu\n",
+				__FUNCTION__, inode->i_ino);
+			jbd_debug(2, "deleting unreferenced inode %lu\n",
+				  inode->i_ino);
+			nr_orphans++;
+		}
+		iput(inode);  /* The delete magic happens here! */
+	}
+
+#define PLURAL(x) (x), ((x)==1) ? "" : "s"
+
+	if (nr_orphans)
+		printk(KERN_INFO "EXT4-fs: %s: %d orphan inode%s deleted\n",
+		       sb->s_id, PLURAL(nr_orphans));
+	if (nr_truncates)
+		printk(KERN_INFO "EXT4-fs: %s: %d truncate%s cleaned up\n",
+		       sb->s_id, PLURAL(nr_truncates));
+#ifdef CONFIG_QUOTA
+	/* Turn quotas off */
+	for (i = 0; i < MAXQUOTAS; i++) {
+		if (sb_dqopt(sb)->files[i])
+			vfs_quota_off(sb, i);
+	}
+#endif
+	sb->s_flags = s_flags; /* Restore MS_RDONLY status */
+}
+
+#define log2(n) ffz(~(n))
+
+/*
+ * Maximal file size.  There is a direct, and {,double-,triple-}indirect
+ * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
+ * We need to be 1 filesystem block less than the 2^32 sector limit.
+ */
+static loff_t ext4_max_size(int bits)
+{
+	loff_t res = EXT4_NDIR_BLOCKS;
+	/* This constant is calculated to be the largest file size for a
+	 * dense, 4k-blocksize file such that the total number of
+	 * sectors in the file, including data and all indirect blocks,
+	 * does not exceed 2^32. */
+	const loff_t upper_limit = 0x1ff7fffd000LL;
+
+	res += 1LL << (bits-2);
+	res += 1LL << (2*(bits-2));
+	res += 1LL << (3*(bits-2));
+	res <<= bits;
+	if (res > upper_limit)
+		res = upper_limit;
+	return res;
+}
+
+static ext4_fsblk_t descriptor_loc(struct super_block *sb,
+				ext4_fsblk_t logical_sb_block, int nr)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	unsigned long bg, first_meta_bg;
+	int has_super = 0;
+
+	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
+
+	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
+	    nr < first_meta_bg)
+		return logical_sb_block + nr + 1;
+	bg = sbi->s_desc_per_block * nr;
+	if (ext4_bg_has_super(sb, bg))
+		has_super = 1;
+	return (has_super + ext4_group_first_block_no(sb, bg));
+}
+
+
+static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+{
+	struct buffer_head * bh;
+	struct ext4_super_block *es = NULL;
+	struct ext4_sb_info *sbi;
+	ext4_fsblk_t block;
+	ext4_fsblk_t sb_block = get_sb_block(&data);
+	ext4_fsblk_t logical_sb_block;
+	unsigned long offset = 0;
+	unsigned int journal_inum = 0;
+	unsigned long journal_devnum = 0;
+	unsigned long def_mount_opts;
+	struct inode *root;
+	int blocksize;
+	int hblock;
+	int db_count;
+	int i;
+	int needs_recovery;
+	__le32 features;
+	__u64 blocks_count;
+
+	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+	if (!sbi)
+		return -ENOMEM;
+	sb->s_fs_info = sbi;
+	sbi->s_mount_opt = 0;
+	sbi->s_resuid = EXT4_DEF_RESUID;
+	sbi->s_resgid = EXT4_DEF_RESGID;
+
+	unlock_kernel();
+
+	blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
+	if (!blocksize) {
+		printk(KERN_ERR "EXT4-fs: unable to set blocksize\n");
+		goto out_fail;
+	}
+
+	/*
+	 * The ext4 superblock will not be buffer aligned for other than 1kB
+	 * block sizes.  We need to calculate the offset from buffer start.
+	 */
+	if (blocksize != EXT4_MIN_BLOCK_SIZE) {
+		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
+		offset = do_div(logical_sb_block, blocksize);
+	} else {
+		logical_sb_block = sb_block;
+	}
+
+	if (!(bh = sb_bread(sb, logical_sb_block))) {
+		printk (KERN_ERR "EXT4-fs: unable to read superblock\n");
+		goto out_fail;
+	}
+	/*
+	 * Note: s_es must be initialized as soon as possible because
+	 *       some ext4 macro-instructions depend on its value
+	 */
+	es = (struct ext4_super_block *) (((char *)bh->b_data) + offset);
+	sbi->s_es = es;
+	sb->s_magic = le16_to_cpu(es->s_magic);
+	if (sb->s_magic != EXT4_SUPER_MAGIC)
+		goto cantfind_ext4;
+
+	/* Set defaults before we parse the mount options */
+	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+	if (def_mount_opts & EXT4_DEFM_DEBUG)
+		set_opt(sbi->s_mount_opt, DEBUG);
+	if (def_mount_opts & EXT4_DEFM_BSDGROUPS)
+		set_opt(sbi->s_mount_opt, GRPID);
+	if (def_mount_opts & EXT4_DEFM_UID16)
+		set_opt(sbi->s_mount_opt, NO_UID32);
+	if (def_mount_opts & EXT4_DEFM_XATTR_USER)
+		set_opt(sbi->s_mount_opt, XATTR_USER);
+	if (def_mount_opts & EXT4_DEFM_ACL)
+		set_opt(sbi->s_mount_opt, POSIX_ACL);
+	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
+		sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
+	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
+		sbi->s_mount_opt |= EXT4_MOUNT_ORDERED_DATA;
+	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)
+		sbi->s_mount_opt |= EXT4_MOUNT_WRITEBACK_DATA;
+
+	if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
+		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_RO)
+		set_opt(sbi->s_mount_opt, ERRORS_RO);
+	else
+		set_opt(sbi->s_mount_opt, ERRORS_CONT);
+
+	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
+	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
+
+	set_opt(sbi->s_mount_opt, RESERVATION);
+
+	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
+			    NULL, 0))
+		goto failed_mount;
+
+	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+		((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+
+	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV &&
+	    (EXT4_HAS_COMPAT_FEATURE(sb, ~0U) ||
+	     EXT4_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
+	     EXT4_HAS_INCOMPAT_FEATURE(sb, ~0U)))
+		printk(KERN_WARNING
+		       "EXT4-fs warning: feature flags set on rev 0 fs, "
+		       "running e2fsck is recommended\n");
+	/*
+	 * Check feature flags regardless of the revision level, since we
+	 * previously didn't change the revision level when setting the flags,
+	 * so there is a chance incompat flags are set on a rev 0 filesystem.
+	 */
+	features = EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP);
+	if (features) {
+		printk(KERN_ERR "EXT4-fs: %s: couldn't mount because of "
+		       "unsupported optional features (%x).\n",
+		       sb->s_id, le32_to_cpu(features));
+		goto failed_mount;
+	}
+	features = EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP);
+	if (!(sb->s_flags & MS_RDONLY) && features) {
+		printk(KERN_ERR "EXT4-fs: %s: couldn't mount RDWR because of "
+		       "unsupported optional features (%x).\n",
+		       sb->s_id, le32_to_cpu(features));
+		goto failed_mount;
+	}
+	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
+
+	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
+	    blocksize > EXT4_MAX_BLOCK_SIZE) {
+		printk(KERN_ERR
+		       "EXT4-fs: Unsupported filesystem blocksize %d on %s.\n",
+		       blocksize, sb->s_id);
+		goto failed_mount;
+	}
+
+	hblock = bdev_hardsect_size(sb->s_bdev);
+	if (sb->s_blocksize != blocksize) {
+		/*
+		 * Make sure the blocksize for the filesystem is larger
+		 * than the hardware sectorsize for the machine.
+		 */
+		if (blocksize < hblock) {
+			printk(KERN_ERR "EXT4-fs: blocksize %d too small for "
+			       "device blocksize %d.\n", blocksize, hblock);
+			goto failed_mount;
+		}
+
+		brelse (bh);
+		sb_set_blocksize(sb, blocksize);
+		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
+		offset = do_div(logical_sb_block, blocksize);
+		bh = sb_bread(sb, logical_sb_block);
+		if (!bh) {
+			printk(KERN_ERR
+			       "EXT4-fs: Can't read superblock on 2nd try.\n");
+			goto failed_mount;
+		}
+		es = (struct ext4_super_block *)(((char *)bh->b_data) + offset);
+		sbi->s_es = es;
+		if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {
+			printk (KERN_ERR
+				"EXT4-fs: Magic mismatch, very weird !\n");
+			goto failed_mount;
+		}
+	}
+
+	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits);
+
+	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
+		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
+		sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
+	} else {
+		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
+		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
+		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
+		    (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
+		    (sbi->s_inode_size > blocksize)) {
+			printk (KERN_ERR
+				"EXT4-fs: unsupported inode size: %d\n",
+				sbi->s_inode_size);
+			goto failed_mount;
+		}
+	}
+	sbi->s_frag_size = EXT4_MIN_FRAG_SIZE <<
+				   le32_to_cpu(es->s_log_frag_size);
+	if (blocksize != sbi->s_frag_size) {
+		printk(KERN_ERR
+		       "EXT4-fs: fragsize %lu != blocksize %u (unsupported)\n",
+		       sbi->s_frag_size, blocksize);
+		goto failed_mount;
+	}
+	sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
+		if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
+		    sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
+		    sbi->s_desc_size & (sbi->s_desc_size - 1)) {
+			printk(KERN_ERR
+			       "EXT4-fs: unsupported descriptor size %lu\n",
+			       sbi->s_desc_size);
+			goto failed_mount;
+		}
+	} else
+		sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
+	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
+	sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
+	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+	if (EXT4_INODE_SIZE(sb) == 0)
+		goto cantfind_ext4;
+	sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
+	if (sbi->s_inodes_per_block == 0)
+		goto cantfind_ext4;
+	sbi->s_itb_per_group = sbi->s_inodes_per_group /
+					sbi->s_inodes_per_block;
+	sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
+	sbi->s_sbh = bh;
+	sbi->s_mount_state = le16_to_cpu(es->s_state);
+	sbi->s_addr_per_block_bits = log2(EXT4_ADDR_PER_BLOCK(sb));
+	sbi->s_desc_per_block_bits = log2(EXT4_DESC_PER_BLOCK(sb));
+	for (i=0; i < 4; i++)
+		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+	sbi->s_def_hash_version = es->s_def_hash_version;
+
+	if (sbi->s_blocks_per_group > blocksize * 8) {
+		printk (KERN_ERR
+			"EXT4-fs: #blocks per group too big: %lu\n",
+			sbi->s_blocks_per_group);
+		goto failed_mount;
+	}
+	if (sbi->s_frags_per_group > blocksize * 8) {
+		printk (KERN_ERR
+			"EXT4-fs: #fragments per group too big: %lu\n",
+			sbi->s_frags_per_group);
+		goto failed_mount;
+	}
+	if (sbi->s_inodes_per_group > blocksize * 8) {
+		printk (KERN_ERR
+			"EXT4-fs: #inodes per group too big: %lu\n",
+			sbi->s_inodes_per_group);
+		goto failed_mount;
+	}
+
+	if (ext4_blocks_count(es) >
+		    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+		printk(KERN_ERR "EXT4-fs: filesystem on %s:"
+			" too large to mount safely\n", sb->s_id);
+		if (sizeof(sector_t) < 8)
+			printk(KERN_WARNING "EXT4-fs: CONFIG_LBD not "
+					"enabled\n");
+		goto failed_mount;
+	}
+
+	if (EXT4_BLOCKS_PER_GROUP(sb) == 0)
+		goto cantfind_ext4;
+	blocks_count = (ext4_blocks_count(es) -
+			le32_to_cpu(es->s_first_data_block) +
+			EXT4_BLOCKS_PER_GROUP(sb) - 1);
+	do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb));
+	sbi->s_groups_count = blocks_count;
+	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+		   EXT4_DESC_PER_BLOCK(sb);
+	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
+				    GFP_KERNEL);
+	if (sbi->s_group_desc == NULL) {
+		printk (KERN_ERR "EXT4-fs: not enough memory\n");
+		goto failed_mount;
+	}
+
+	bgl_lock_init(&sbi->s_blockgroup_lock);
+
+	for (i = 0; i < db_count; i++) {
+		block = descriptor_loc(sb, logical_sb_block, i);
+		sbi->s_group_desc[i] = sb_bread(sb, block);
+		if (!sbi->s_group_desc[i]) {
+			printk (KERN_ERR "EXT4-fs: "
+				"can't read group descriptor %d\n", i);
+			db_count = i;
+			goto failed_mount2;
+		}
+	}
+	if (!ext4_check_descriptors (sb)) {
+		printk(KERN_ERR "EXT4-fs: group descriptors corrupted!\n");
+		goto failed_mount2;
+	}
+	sbi->s_gdb_count = db_count;
+	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+	spin_lock_init(&sbi->s_next_gen_lock);
+
+	percpu_counter_init(&sbi->s_freeblocks_counter,
+		ext4_count_free_blocks(sb));
+	percpu_counter_init(&sbi->s_freeinodes_counter,
+		ext4_count_free_inodes(sb));
+	percpu_counter_init(&sbi->s_dirs_counter,
+		ext4_count_dirs(sb));
+
+	/* per fileystem reservation list head & lock */
+	spin_lock_init(&sbi->s_rsv_window_lock);
+	sbi->s_rsv_window_root = RB_ROOT;
+	/* Add a single, static dummy reservation to the start of the
+	 * reservation window list --- it gives us a placeholder for
+	 * append-at-start-of-list which makes the allocation logic
+	 * _much_ simpler. */
+	sbi->s_rsv_window_head.rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+	sbi->s_rsv_window_head.rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+	sbi->s_rsv_window_head.rsv_alloc_hit = 0;
+	sbi->s_rsv_window_head.rsv_goal_size = 0;
+	ext4_rsv_window_add(sb, &sbi->s_rsv_window_head);
+
+	/*
+	 * set up enough so that it can read an inode
+	 */
+	sb->s_op = &ext4_sops;
+	sb->s_export_op = &ext4_export_ops;
+	sb->s_xattr = ext4_xattr_handlers;
+#ifdef CONFIG_QUOTA
+	sb->s_qcop = &ext4_qctl_operations;
+	sb->dq_op = &ext4_quota_operations;
+#endif
+	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
+
+	sb->s_root = NULL;
+
+	needs_recovery = (es->s_last_orphan != 0 ||
+			  EXT4_HAS_INCOMPAT_FEATURE(sb,
+				    EXT4_FEATURE_INCOMPAT_RECOVER));
+
+	/*
+	 * The first inode we look at is the journal inode.  Don't try
+	 * root first: it may be modified in the journal!
+	 */
+	if (!test_opt(sb, NOLOAD) &&
+	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) {
+		if (ext4_load_journal(sb, es, journal_devnum))
+			goto failed_mount3;
+	} else if (journal_inum) {
+		if (ext4_create_journal(sb, es, journal_inum))
+			goto failed_mount3;
+	} else {
+		if (!silent)
+			printk (KERN_ERR
+				"ext4: No journal on filesystem on %s\n",
+				sb->s_id);
+		goto failed_mount3;
+	}
+
+	/* We have now updated the journal if required, so we can
+	 * validate the data journaling mode. */
+	switch (test_opt(sb, DATA_FLAGS)) {
+	case 0:
+		/* No mode set, assume a default based on the journal
+		 * capabilities: ORDERED_DATA if the journal can
+		 * cope, else JOURNAL_DATA
+		 */
+		if (jbd2_journal_check_available_features
+		    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE))
+			set_opt(sbi->s_mount_opt, ORDERED_DATA);
+		else
+			set_opt(sbi->s_mount_opt, JOURNAL_DATA);
+		break;
+
+	case EXT4_MOUNT_ORDERED_DATA:
+	case EXT4_MOUNT_WRITEBACK_DATA:
+		if (!jbd2_journal_check_available_features
+		    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
+			printk(KERN_ERR "EXT4-fs: Journal does not support "
+			       "requested data journaling mode\n");
+			goto failed_mount4;
+		}
+	default:
+		break;
+	}
+
+	if (test_opt(sb, NOBH)) {
+		if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) {
+			printk(KERN_WARNING "EXT4-fs: Ignoring nobh option - "
+				"its supported only with writeback mode\n");
+			clear_opt(sbi->s_mount_opt, NOBH);
+		}
+	}
+	/*
+	 * The jbd2_journal_load will have done any necessary log recovery,
+	 * so we can safely mount the rest of the filesystem now.
+	 */
+
+	root = iget(sb, EXT4_ROOT_INO);
+	sb->s_root = d_alloc_root(root);
+	if (!sb->s_root) {
+		printk(KERN_ERR "EXT4-fs: get root inode failed\n");
+		iput(root);
+		goto failed_mount4;
+	}
+	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
+		dput(sb->s_root);
+		sb->s_root = NULL;
+		printk(KERN_ERR "EXT4-fs: corrupt root inode, run e2fsck\n");
+		goto failed_mount4;
+	}
+
+	ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY);
+	/*
+	 * akpm: core read_super() calls in here with the superblock locked.
+	 * That deadlocks, because orphan cleanup needs to lock the superblock
+	 * in numerous places.  Here we just pop the lock - it's relatively
+	 * harmless, because we are now ready to accept write_super() requests,
+	 * and aviro says that's the only reason for hanging onto the
+	 * superblock lock.
+	 */
+	EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
+	ext4_orphan_cleanup(sb, es);
+	EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
+	if (needs_recovery)
+		printk (KERN_INFO "EXT4-fs: recovery complete.\n");
+	ext4_mark_recovery_complete(sb, es);
+	printk (KERN_INFO "EXT4-fs: mounted filesystem with %s data mode.\n",
+		test_opt(sb,DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ? "journal":
+		test_opt(sb,DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA ? "ordered":
+		"writeback");
+
+	ext4_ext_init(sb);
+
+	lock_kernel();
+	return 0;
+
+cantfind_ext4:
+	if (!silent)
+		printk(KERN_ERR "VFS: Can't find ext4 filesystem on dev %s.\n",
+		       sb->s_id);
+	goto failed_mount;
+
+failed_mount4:
+	jbd2_journal_destroy(sbi->s_journal);
+failed_mount3:
+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+	percpu_counter_destroy(&sbi->s_dirs_counter);
+failed_mount2:
+	for (i = 0; i < db_count; i++)
+		brelse(sbi->s_group_desc[i]);
+	kfree(sbi->s_group_desc);
+failed_mount:
+#ifdef CONFIG_QUOTA
+	for (i = 0; i < MAXQUOTAS; i++)
+		kfree(sbi->s_qf_names[i]);
+#endif
+	ext4_blkdev_remove(sbi);
+	brelse(bh);
+out_fail:
+	sb->s_fs_info = NULL;
+	kfree(sbi);
+	lock_kernel();
+	return -EINVAL;
+}
+
+/*
+ * Setup any per-fs journal parameters now.  We'll do this both on
+ * initial mount, once the journal has been initialised but before we've
+ * done any recovery; and again on any subsequent remount.
+ */
+static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+	if (sbi->s_commit_interval)
+		journal->j_commit_interval = sbi->s_commit_interval;
+	/* We could also set up an ext4-specific default for the commit
+	 * interval here, but for now we'll just fall back to the jbd
+	 * default. */
+
+	spin_lock(&journal->j_state_lock);
+	if (test_opt(sb, BARRIER))
+		journal->j_flags |= JBD2_BARRIER;
+	else
+		journal->j_flags &= ~JBD2_BARRIER;
+	spin_unlock(&journal->j_state_lock);
+}
+
+static journal_t *ext4_get_journal(struct super_block *sb,
+				   unsigned int journal_inum)
+{
+	struct inode *journal_inode;
+	journal_t *journal;
+
+	/* First, test for the existence of a valid inode on disk.  Bad
+	 * things happen if we iget() an unused inode, as the subsequent
+	 * iput() will try to delete it. */
+
+	journal_inode = iget(sb, journal_inum);
+	if (!journal_inode) {
+		printk(KERN_ERR "EXT4-fs: no journal found.\n");
+		return NULL;
+	}
+	if (!journal_inode->i_nlink) {
+		make_bad_inode(journal_inode);
+		iput(journal_inode);
+		printk(KERN_ERR "EXT4-fs: journal inode is deleted.\n");
+		return NULL;
+	}
+
+	jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
+		  journal_inode, journal_inode->i_size);
+	if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) {
+		printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
+		iput(journal_inode);
+		return NULL;
+	}
+
+	journal = jbd2_journal_init_inode(journal_inode);
+	if (!journal) {
+		printk(KERN_ERR "EXT4-fs: Could not load journal inode\n");
+		iput(journal_inode);
+		return NULL;
+	}
+	journal->j_private = sb;
+	ext4_init_journal_params(sb, journal);
+	return journal;
+}
+
+static journal_t *ext4_get_dev_journal(struct super_block *sb,
+				       dev_t j_dev)
+{
+	struct buffer_head * bh;
+	journal_t *journal;
+	ext4_fsblk_t start;
+	ext4_fsblk_t len;
+	int hblock, blocksize;
+	ext4_fsblk_t sb_block;
+	unsigned long offset;
+	struct ext4_super_block * es;
+	struct block_device *bdev;
+
+	bdev = ext4_blkdev_get(j_dev);
+	if (bdev == NULL)
+		return NULL;
+
+	if (bd_claim(bdev, sb)) {
+		printk(KERN_ERR
+		        "EXT4: failed to claim external journal device.\n");
+		blkdev_put(bdev);
+		return NULL;
+	}
+
+	blocksize = sb->s_blocksize;
+	hblock = bdev_hardsect_size(bdev);
+	if (blocksize < hblock) {
+		printk(KERN_ERR
+			"EXT4-fs: blocksize too small for journal device.\n");
+		goto out_bdev;
+	}
+
+	sb_block = EXT4_MIN_BLOCK_SIZE / blocksize;
+	offset = EXT4_MIN_BLOCK_SIZE % blocksize;
+	set_blocksize(bdev, blocksize);
+	if (!(bh = __bread(bdev, sb_block, blocksize))) {
+		printk(KERN_ERR "EXT4-fs: couldn't read superblock of "
+		       "external journal\n");
+		goto out_bdev;
+	}
+
+	es = (struct ext4_super_block *) (((char *)bh->b_data) + offset);
+	if ((le16_to_cpu(es->s_magic) != EXT4_SUPER_MAGIC) ||
+	    !(le32_to_cpu(es->s_feature_incompat) &
+	      EXT4_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+		printk(KERN_ERR "EXT4-fs: external journal has "
+					"bad superblock\n");
+		brelse(bh);
+		goto out_bdev;
+	}
+
+	if (memcmp(EXT4_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
+		printk(KERN_ERR "EXT4-fs: journal UUID does not match\n");
+		brelse(bh);
+		goto out_bdev;
+	}
+
+	len = ext4_blocks_count(es);
+	start = sb_block + 1;
+	brelse(bh);	/* we're done with the superblock */
+
+	journal = jbd2_journal_init_dev(bdev, sb->s_bdev,
+					start, len, blocksize);
+	if (!journal) {
+		printk(KERN_ERR "EXT4-fs: failed to create device journal\n");
+		goto out_bdev;
+	}
+	journal->j_private = sb;
+	ll_rw_block(READ, 1, &journal->j_sb_buffer);
+	wait_on_buffer(journal->j_sb_buffer);
+	if (!buffer_uptodate(journal->j_sb_buffer)) {
+		printk(KERN_ERR "EXT4-fs: I/O error on journal device\n");
+		goto out_journal;
+	}
+	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
+		printk(KERN_ERR "EXT4-fs: External journal has more than one "
+					"user (unsupported) - %d\n",
+			be32_to_cpu(journal->j_superblock->s_nr_users));
+		goto out_journal;
+	}
+	EXT4_SB(sb)->journal_bdev = bdev;
+	ext4_init_journal_params(sb, journal);
+	return journal;
+out_journal:
+	jbd2_journal_destroy(journal);
+out_bdev:
+	ext4_blkdev_put(bdev);
+	return NULL;
+}
+
+static int ext4_load_journal(struct super_block *sb,
+			     struct ext4_super_block *es,
+			     unsigned long journal_devnum)
+{
+	journal_t *journal;
+	unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
+	dev_t journal_dev;
+	int err = 0;
+	int really_read_only;
+
+	if (journal_devnum &&
+	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+		printk(KERN_INFO "EXT4-fs: external journal device major/minor "
+			"numbers have changed\n");
+		journal_dev = new_decode_dev(journal_devnum);
+	} else
+		journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
+
+	really_read_only = bdev_read_only(sb->s_bdev);
+
+	/*
+	 * Are we loading a blank journal or performing recovery after a
+	 * crash?  For recovery, we need to check in advance whether we
+	 * can get read-write access to the device.
+	 */
+
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
+		if (sb->s_flags & MS_RDONLY) {
+			printk(KERN_INFO "EXT4-fs: INFO: recovery "
+					"required on readonly filesystem.\n");
+			if (really_read_only) {
+				printk(KERN_ERR "EXT4-fs: write access "
+					"unavailable, cannot proceed.\n");
+				return -EROFS;
+			}
+			printk (KERN_INFO "EXT4-fs: write access will "
+					"be enabled during recovery.\n");
+		}
+	}
+
+	if (journal_inum && journal_dev) {
+		printk(KERN_ERR "EXT4-fs: filesystem has both journal "
+		       "and inode journals!\n");
+		return -EINVAL;
+	}
+
+	if (journal_inum) {
+		if (!(journal = ext4_get_journal(sb, journal_inum)))
+			return -EINVAL;
+	} else {
+		if (!(journal = ext4_get_dev_journal(sb, journal_dev)))
+			return -EINVAL;
+	}
+
+	if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
+		err = jbd2_journal_update_format(journal);
+		if (err)  {
+			printk(KERN_ERR "EXT4-fs: error updating journal.\n");
+			jbd2_journal_destroy(journal);
+			return err;
+		}
+	}
+
+	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER))
+		err = jbd2_journal_wipe(journal, !really_read_only);
+	if (!err)
+		err = jbd2_journal_load(journal);
+
+	if (err) {
+		printk(KERN_ERR "EXT4-fs: error loading journal.\n");
+		jbd2_journal_destroy(journal);
+		return err;
+	}
+
+	EXT4_SB(sb)->s_journal = journal;
+	ext4_clear_journal_err(sb, es);
+
+	if (journal_devnum &&
+	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+		es->s_journal_dev = cpu_to_le32(journal_devnum);
+		sb->s_dirt = 1;
+
+		/* Make sure we flush the recovery flag to disk. */
+		ext4_commit_super(sb, es, 1);
+	}
+
+	return 0;
+}
+
+static int ext4_create_journal(struct super_block * sb,
+			       struct ext4_super_block * es,
+			       unsigned int journal_inum)
+{
+	journal_t *journal;
+
+	if (sb->s_flags & MS_RDONLY) {
+		printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to "
+				"create journal.\n");
+		return -EROFS;
+	}
+
+	if (!(journal = ext4_get_journal(sb, journal_inum)))
+		return -EINVAL;
+
+	printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n",
+	       journal_inum);
+
+	if (jbd2_journal_create(journal)) {
+		printk(KERN_ERR "EXT4-fs: error creating journal.\n");
+		jbd2_journal_destroy(journal);
+		return -EIO;
+	}
+
+	EXT4_SB(sb)->s_journal = journal;
+
+	ext4_update_dynamic_rev(sb);
+	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+	EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL);
+
+	es->s_journal_inum = cpu_to_le32(journal_inum);
+	sb->s_dirt = 1;
+
+	/* Make sure we flush the recovery flag to disk. */
+	ext4_commit_super(sb, es, 1);
+
+	return 0;
+}
+
+static void ext4_commit_super (struct super_block * sb,
+			       struct ext4_super_block * es,
+			       int sync)
+{
+	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+
+	if (!sbh)
+		return;
+	es->s_wtime = cpu_to_le32(get_seconds());
+	ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb));
+	es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
+	BUFFER_TRACE(sbh, "marking dirty");
+	mark_buffer_dirty(sbh);
+	if (sync)
+		sync_dirty_buffer(sbh);
+}
+
+
+/*
+ * Have we just finished recovery?  If so, and if we are mounting (or
+ * remounting) the filesystem readonly, then we will end up with a
+ * consistent fs on disk.  Record that fact.
+ */
+static void ext4_mark_recovery_complete(struct super_block * sb,
+					struct ext4_super_block * es)
+{
+	journal_t *journal = EXT4_SB(sb)->s_journal;
+
+	jbd2_journal_lock_updates(journal);
+	jbd2_journal_flush(journal);
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
+	    sb->s_flags & MS_RDONLY) {
+		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+		sb->s_dirt = 0;
+		ext4_commit_super(sb, es, 1);
+	}
+	jbd2_journal_unlock_updates(journal);
+}
+
+/*
+ * If we are mounting (or read-write remounting) a filesystem whose journal
+ * has recorded an error from a previous lifetime, move that error to the
+ * main filesystem now.
+ */
+static void ext4_clear_journal_err(struct super_block * sb,
+				   struct ext4_super_block * es)
+{
+	journal_t *journal;
+	int j_errno;
+	const char *errstr;
+
+	journal = EXT4_SB(sb)->s_journal;
+
+	/*
+	 * Now check for any error status which may have been recorded in the
+	 * journal by a prior ext4_error() or ext4_abort()
+	 */
+
+	j_errno = jbd2_journal_errno(journal);
+	if (j_errno) {
+		char nbuf[16];
+
+		errstr = ext4_decode_error(sb, j_errno, nbuf);
+		ext4_warning(sb, __FUNCTION__, "Filesystem error recorded "
+			     "from previous mount: %s", errstr);
+		ext4_warning(sb, __FUNCTION__, "Marking fs in need of "
+			     "filesystem check.");
+
+		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+		ext4_commit_super (sb, es, 1);
+
+		jbd2_journal_clear_err(journal);
+	}
+}
+
+/*
+ * Force the running and committing transactions to commit,
+ * and wait on the commit.
+ */
+int ext4_force_commit(struct super_block *sb)
+{
+	journal_t *journal;
+	int ret;
+
+	if (sb->s_flags & MS_RDONLY)
+		return 0;
+
+	journal = EXT4_SB(sb)->s_journal;
+	sb->s_dirt = 0;
+	ret = ext4_journal_force_commit(journal);
+	return ret;
+}
+
+/*
+ * Ext4 always journals updates to the superblock itself, so we don't
+ * have to propagate any other updates to the superblock on disk at this
+ * point.  Just start an async writeback to get the buffers on their way
+ * to the disk.
+ *
+ * This implicitly triggers the writebehind on sync().
+ */
+
+static void ext4_write_super (struct super_block * sb)
+{
+	if (mutex_trylock(&sb->s_lock) != 0)
+		BUG();
+	sb->s_dirt = 0;
+}
+
+static int ext4_sync_fs(struct super_block *sb, int wait)
+{
+	tid_t target;
+
+	sb->s_dirt = 0;
+	if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+		if (wait)
+			jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
+	}
+	return 0;
+}
+
+/*
+ * LVM calls this function before a (read-only) snapshot is created.  This
+ * gives us a chance to flush the journal completely and mark the fs clean.
+ */
+static void ext4_write_super_lockfs(struct super_block *sb)
+{
+	sb->s_dirt = 0;
+
+	if (!(sb->s_flags & MS_RDONLY)) {
+		journal_t *journal = EXT4_SB(sb)->s_journal;
+
+		/* Now we set up the journal barrier. */
+		jbd2_journal_lock_updates(journal);
+		jbd2_journal_flush(journal);
+
+		/* Journal blocked and flushed, clear needs_recovery flag. */
+		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+		ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+	}
+}
+
+/*
+ * Called by LVM after the snapshot is done.  We need to reset the RECOVER
+ * flag here, even though the filesystem is not technically dirty yet.
+ */
+static void ext4_unlockfs(struct super_block *sb)
+{
+	if (!(sb->s_flags & MS_RDONLY)) {
+		lock_super(sb);
+		/* Reser the needs_recovery flag before the fs is unlocked. */
+		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+		ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+		unlock_super(sb);
+		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+	}
+}
+
+static int ext4_remount (struct super_block * sb, int * flags, char * data)
+{
+	struct ext4_super_block * es;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	ext4_fsblk_t n_blocks_count = 0;
+	unsigned long old_sb_flags;
+	struct ext4_mount_options old_opts;
+	int err;
+#ifdef CONFIG_QUOTA
+	int i;
+#endif
+
+	/* Store the original options */
+	old_sb_flags = sb->s_flags;
+	old_opts.s_mount_opt = sbi->s_mount_opt;
+	old_opts.s_resuid = sbi->s_resuid;
+	old_opts.s_resgid = sbi->s_resgid;
+	old_opts.s_commit_interval = sbi->s_commit_interval;
+#ifdef CONFIG_QUOTA
+	old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
+	for (i = 0; i < MAXQUOTAS; i++)
+		old_opts.s_qf_names[i] = sbi->s_qf_names[i];
+#endif
+
+	/*
+	 * Allow the "check" option to be passed as a remount option.
+	 */
+	if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
+		err = -EINVAL;
+		goto restore_opts;
+	}
+
+	if (sbi->s_mount_opt & EXT4_MOUNT_ABORT)
+		ext4_abort(sb, __FUNCTION__, "Abort forced by user");
+
+	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+		((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+
+	es = sbi->s_es;
+
+	ext4_init_journal_params(sb, sbi->s_journal);
+
+	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
+		n_blocks_count > ext4_blocks_count(es)) {
+		if (sbi->s_mount_opt & EXT4_MOUNT_ABORT) {
+			err = -EROFS;
+			goto restore_opts;
+		}
+
+		if (*flags & MS_RDONLY) {
+			/*
+			 * First of all, the unconditional stuff we have to do
+			 * to disable replay of the journal when we next remount
+			 */
+			sb->s_flags |= MS_RDONLY;
+
+			/*
+			 * OK, test if we are remounting a valid rw partition
+			 * readonly, and if so set the rdonly flag and then
+			 * mark the partition as valid again.
+			 */
+			if (!(es->s_state & cpu_to_le16(EXT4_VALID_FS)) &&
+			    (sbi->s_mount_state & EXT4_VALID_FS))
+				es->s_state = cpu_to_le16(sbi->s_mount_state);
+
+			ext4_mark_recovery_complete(sb, es);
+		} else {
+			__le32 ret;
+			if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
+					~EXT4_FEATURE_RO_COMPAT_SUPP))) {
+				printk(KERN_WARNING "EXT4-fs: %s: couldn't "
+				       "remount RDWR because of unsupported "
+				       "optional features (%x).\n",
+				       sb->s_id, le32_to_cpu(ret));
+				err = -EROFS;
+				goto restore_opts;
+			}
+			/*
+			 * Mounting a RDONLY partition read-write, so reread
+			 * and store the current valid flag.  (It may have
+			 * been changed by e2fsck since we originally mounted
+			 * the partition.)
+			 */
+			ext4_clear_journal_err(sb, es);
+			sbi->s_mount_state = le16_to_cpu(es->s_state);
+			if ((err = ext4_group_extend(sb, es, n_blocks_count)))
+				goto restore_opts;
+			if (!ext4_setup_super (sb, es, 0))
+				sb->s_flags &= ~MS_RDONLY;
+		}
+	}
+#ifdef CONFIG_QUOTA
+	/* Release old quota file names */
+	for (i = 0; i < MAXQUOTAS; i++)
+		if (old_opts.s_qf_names[i] &&
+		    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
+			kfree(old_opts.s_qf_names[i]);
+#endif
+	return 0;
+restore_opts:
+	sb->s_flags = old_sb_flags;
+	sbi->s_mount_opt = old_opts.s_mount_opt;
+	sbi->s_resuid = old_opts.s_resuid;
+	sbi->s_resgid = old_opts.s_resgid;
+	sbi->s_commit_interval = old_opts.s_commit_interval;
+#ifdef CONFIG_QUOTA
+	sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
+	for (i = 0; i < MAXQUOTAS; i++) {
+		if (sbi->s_qf_names[i] &&
+		    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
+			kfree(sbi->s_qf_names[i]);
+		sbi->s_qf_names[i] = old_opts.s_qf_names[i];
+	}
+#endif
+	return err;
+}
+
+static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_super_block *es = sbi->s_es;
+	ext4_fsblk_t overhead;
+	int i;
+
+	if (test_opt (sb, MINIX_DF))
+		overhead = 0;
+	else {
+		unsigned long ngroups;
+		ngroups = EXT4_SB(sb)->s_groups_count;
+		smp_rmb();
+
+		/*
+		 * Compute the overhead (FS structures)
+		 */
+
+		/*
+		 * All of the blocks before first_data_block are
+		 * overhead
+		 */
+		overhead = le32_to_cpu(es->s_first_data_block);
+
+		/*
+		 * Add the overhead attributed to the superblock and
+		 * block group descriptors.  If the sparse superblocks
+		 * feature is turned on, then not all groups have this.
+		 */
+		for (i = 0; i < ngroups; i++) {
+			overhead += ext4_bg_has_super(sb, i) +
+				ext4_bg_num_gdb(sb, i);
+			cond_resched();
+		}
+
+		/*
+		 * Every block group has an inode bitmap, a block
+		 * bitmap, and an inode table.
+		 */
+		overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group));
+	}
+
+	buf->f_type = EXT4_SUPER_MAGIC;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = ext4_blocks_count(es) - overhead;
+	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
+	if (buf->f_bfree < ext4_r_blocks_count(es))
+		buf->f_bavail = 0;
+	buf->f_files = le32_to_cpu(es->s_inodes_count);
+	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+	buf->f_namelen = EXT4_NAME_LEN;
+	return 0;
+}
+
+/* Helper function for writing quotas on sync - we need to start transaction before quota file
+ * is locked for write. Otherwise the are possible deadlocks:
+ * Process 1                         Process 2
+ * ext4_create()                     quota_sync()
+ *   jbd2_journal_start()                   write_dquot()
+ *   DQUOT_INIT()                        down(dqio_mutex)
+ *     down(dqio_mutex)                    jbd2_journal_start()
+ *
+ */
+
+#ifdef CONFIG_QUOTA
+
+static inline struct inode *dquot_to_inode(struct dquot *dquot)
+{
+	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
+}
+
+static int ext4_dquot_initialize(struct inode *inode, int type)
+{
+	handle_t *handle;
+	int ret, err;
+
+	/* We may create quota structure so we need to reserve enough blocks */
+	handle = ext4_journal_start(inode, 2*EXT4_QUOTA_INIT_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ret = dquot_initialize(inode, type);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+}
+
+static int ext4_dquot_drop(struct inode *inode)
+{
+	handle_t *handle;
+	int ret, err;
+
+	/* We may delete quota structure so we need to reserve enough blocks */
+	handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ret = dquot_drop(inode);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+}
+
+static int ext4_write_dquot(struct dquot *dquot)
+{
+	int ret, err;
+	handle_t *handle;
+	struct inode *inode;
+
+	inode = dquot_to_inode(dquot);
+	handle = ext4_journal_start(inode,
+					EXT4_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ret = dquot_commit(dquot);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+}
+
+static int ext4_acquire_dquot(struct dquot *dquot)
+{
+	int ret, err;
+	handle_t *handle;
+
+	handle = ext4_journal_start(dquot_to_inode(dquot),
+					EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ret = dquot_acquire(dquot);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+}
+
+static int ext4_release_dquot(struct dquot *dquot)
+{
+	int ret, err;
+	handle_t *handle;
+
+	handle = ext4_journal_start(dquot_to_inode(dquot),
+					EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ret = dquot_release(dquot);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+}
+
+static int ext4_mark_dquot_dirty(struct dquot *dquot)
+{
+	/* Are we journalling quotas? */
+	if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
+	    EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
+		dquot_mark_dquot_dirty(dquot);
+		return ext4_write_dquot(dquot);
+	} else {
+		return dquot_mark_dquot_dirty(dquot);
+	}
+}
+
+static int ext4_write_info(struct super_block *sb, int type)
+{
+	int ret, err;
+	handle_t *handle;
+
+	/* Data block + inode block */
+	handle = ext4_journal_start(sb->s_root->d_inode, 2);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ret = dquot_commit_info(sb, type);
+	err = ext4_journal_stop(handle);
+	if (!ret)
+		ret = err;
+	return ret;
+}
+
+/*
+ * Turn on quotas during mount time - we need to find
+ * the quota file and such...
+ */
+static int ext4_quota_on_mount(struct super_block *sb, int type)
+{
+	return vfs_quota_on_mount(sb, EXT4_SB(sb)->s_qf_names[type],
+			EXT4_SB(sb)->s_jquota_fmt, type);
+}
+
+/*
+ * Standard function to be called on quota_on
+ */
+static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+			 char *path)
+{
+	int err;
+	struct nameidata nd;
+
+	if (!test_opt(sb, QUOTA))
+		return -EINVAL;
+	/* Not journalling quota? */
+	if (!EXT4_SB(sb)->s_qf_names[USRQUOTA] &&
+	    !EXT4_SB(sb)->s_qf_names[GRPQUOTA])
+		return vfs_quota_on(sb, type, format_id, path);
+	err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (err)
+		return err;
+	/* Quotafile not on the same filesystem? */
+	if (nd.mnt->mnt_sb != sb) {
+		path_release(&nd);
+		return -EXDEV;
+	}
+	/* Quotafile not of fs root? */
+	if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
+		printk(KERN_WARNING
+			"EXT4-fs: Quota file not on filesystem root. "
+			"Journalled quota will not work.\n");
+	path_release(&nd);
+	return vfs_quota_on(sb, type, format_id, path);
+}
+
+/* Read data from quotafile - avoid pagecache and such because we cannot afford
+ * acquiring the locks... As quota files are never truncated and quota code
+ * itself serializes the operations (and noone else should touch the files)
+ * we don't have to be afraid of races */
+static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
+			       size_t len, loff_t off)
+{
+	struct inode *inode = sb_dqopt(sb)->files[type];
+	sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+	int err = 0;
+	int offset = off & (sb->s_blocksize - 1);
+	int tocopy;
+	size_t toread;
+	struct buffer_head *bh;
+	loff_t i_size = i_size_read(inode);
+
+	if (off > i_size)
+		return 0;
+	if (off+len > i_size)
+		len = i_size-off;
+	toread = len;
+	while (toread > 0) {
+		tocopy = sb->s_blocksize - offset < toread ?
+				sb->s_blocksize - offset : toread;
+		bh = ext4_bread(NULL, inode, blk, 0, &err);
+		if (err)
+			return err;
+		if (!bh)	/* A hole? */
+			memset(data, 0, tocopy);
+		else
+			memcpy(data, bh->b_data+offset, tocopy);
+		brelse(bh);
+		offset = 0;
+		toread -= tocopy;
+		data += tocopy;
+		blk++;
+	}
+	return len;
+}
+
+/* Write to quotafile (we know the transaction is already started and has
+ * enough credits) */
+static ssize_t ext4_quota_write(struct super_block *sb, int type,
+				const char *data, size_t len, loff_t off)
+{
+	struct inode *inode = sb_dqopt(sb)->files[type];
+	sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+	int err = 0;
+	int offset = off & (sb->s_blocksize - 1);
+	int tocopy;
+	int journal_quota = EXT4_SB(sb)->s_qf_names[type] != NULL;
+	size_t towrite = len;
+	struct buffer_head *bh;
+	handle_t *handle = journal_current_handle();
+
+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
+	while (towrite > 0) {
+		tocopy = sb->s_blocksize - offset < towrite ?
+				sb->s_blocksize - offset : towrite;
+		bh = ext4_bread(handle, inode, blk, 1, &err);
+		if (!bh)
+			goto out;
+		if (journal_quota) {
+			err = ext4_journal_get_write_access(handle, bh);
+			if (err) {
+				brelse(bh);
+				goto out;
+			}
+		}
+		lock_buffer(bh);
+		memcpy(bh->b_data+offset, data, tocopy);
+		flush_dcache_page(bh->b_page);
+		unlock_buffer(bh);
+		if (journal_quota)
+			err = ext4_journal_dirty_metadata(handle, bh);
+		else {
+			/* Always do at least ordered writes for quotas */
+			err = ext4_journal_dirty_data(handle, bh);
+			mark_buffer_dirty(bh);
+		}
+		brelse(bh);
+		if (err)
+			goto out;
+		offset = 0;
+		towrite -= tocopy;
+		data += tocopy;
+		blk++;
+	}
+out:
+	if (len == towrite)
+		return err;
+	if (inode->i_size < off+len-towrite) {
+		i_size_write(inode, off+len-towrite);
+		EXT4_I(inode)->i_disksize = inode->i_size;
+	}
+	inode->i_version++;
+	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	ext4_mark_inode_dirty(handle, inode);
+	mutex_unlock(&inode->i_mutex);
+	return len - towrite;
+}
+
+#endif
+
+static int ext4_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
+}
+
+static struct file_system_type ext4dev_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "ext4dev",
+	.get_sb		= ext4_get_sb,
+	.kill_sb	= kill_block_super,
+	.fs_flags	= FS_REQUIRES_DEV,
+};
+
+static int __init init_ext4_fs(void)
+{
+	int err = init_ext4_xattr();
+	if (err)
+		return err;
+	err = init_inodecache();
+	if (err)
+		goto out1;
+	err = register_filesystem(&ext4dev_fs_type);
+	if (err)
+		goto out;
+	return 0;
+out:
+	destroy_inodecache();
+out1:
+	exit_ext4_xattr();
+	return err;
+}
+
+static void __exit exit_ext4_fs(void)
+{
+	unregister_filesystem(&ext4dev_fs_type);
+	destroy_inodecache();
+	exit_ext4_xattr();
+}
+
+MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+MODULE_DESCRIPTION("Fourth Extended Filesystem with extents");
+MODULE_LICENSE("GPL");
+module_init(init_ext4_fs)
+module_exit(exit_ext4_fs)
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
new file mode 100644
index 0000000..fcf5272
--- /dev/null
+++ b/fs/ext4/symlink.c
@@ -0,0 +1,54 @@
+/*
+ *  linux/fs/ext4/symlink.c
+ *
+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/symlink.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  ext4 symlink handling code
+ */
+
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/namei.h>
+#include "xattr.h"
+
+static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct ext4_inode_info *ei = EXT4_I(dentry->d_inode);
+	nd_set_link(nd, (char*)ei->i_data);
+	return NULL;
+}
+
+struct inode_operations ext4_symlink_inode_operations = {
+	.readlink	= generic_readlink,
+	.follow_link	= page_follow_link_light,
+	.put_link	= page_put_link,
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= ext4_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+};
+
+struct inode_operations ext4_fast_symlink_inode_operations = {
+	.readlink	= generic_readlink,
+	.follow_link	= ext4_follow_link,
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= ext4_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+};
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
new file mode 100644
index 0000000..63233cd
--- /dev/null
+++ b/fs/ext4/xattr.c
@@ -0,0 +1,1317 @@
+/*
+ * linux/fs/ext4/xattr.c
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
+ *
+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
+ * Ext4 code with a lot of help from Eric Jarman <ejarman@acm.org>.
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko <luka.renko@hermes.si>.
+ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
+ *  Red Hat Inc.
+ * ea-in-inode support by Alex Tomas <alex@clusterfs.com> aka bzzz
+ *  and Andreas Gruenbacher <agruen@suse.de>.
+ */
+
+/*
+ * Extended attributes are stored directly in inodes (on file systems with
+ * inodes bigger than 128 bytes) and on additional disk blocks. The i_file_acl
+ * field contains the block number if an inode uses an additional block. All
+ * attributes must fit in the inode and one additional block. Blocks that
+ * contain the identical set of attributes may be shared among several inodes.
+ * Identical blocks are detected by keeping a cache of blocks that have
+ * recently been accessed.
+ *
+ * The attributes in inodes and on blocks have a different header; the entries
+ * are stored in the same format:
+ *
+ *   +------------------+
+ *   | header           |
+ *   | entry 1          | |
+ *   | entry 2          | | growing downwards
+ *   | entry 3          | v
+ *   | four null bytes  |
+ *   | . . .            |
+ *   | value 1          | ^
+ *   | value 3          | | growing upwards
+ *   | value 2          | |
+ *   +------------------+
+ *
+ * The header is followed by multiple entry descriptors. In disk blocks, the
+ * entry descriptors are kept sorted. In inodes, they are unsorted. The
+ * attribute values are aligned to the end of the block in no specific order.
+ *
+ * Locking strategy
+ * ----------------
+ * EXT4_I(inode)->i_file_acl is protected by EXT4_I(inode)->xattr_sem.
+ * EA blocks are only changed if they are exclusive to an inode, so
+ * holding xattr_sem also means that nothing but the EA block's reference
+ * count can change. Multiple writers to the same block are synchronized
+ * by the buffer lock.
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/mbcache.h>
+#include <linux/quotaops.h>
+#include <linux/rwsem.h>
+#include "xattr.h"
+#include "acl.h"
+
+#define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data))
+#define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr))
+#define BFIRST(bh) ENTRY(BHDR(bh)+1)
+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
+
+#define IHDR(inode, raw_inode) \
+	((struct ext4_xattr_ibody_header *) \
+		((void *)raw_inode + \
+		 EXT4_GOOD_OLD_INODE_SIZE + \
+		 EXT4_I(inode)->i_extra_isize))
+#define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
+
+#ifdef EXT4_XATTR_DEBUG
+# define ea_idebug(inode, f...) do { \
+		printk(KERN_DEBUG "inode %s:%lu: ", \
+			inode->i_sb->s_id, inode->i_ino); \
+		printk(f); \
+		printk("\n"); \
+	} while (0)
+# define ea_bdebug(bh, f...) do { \
+		char b[BDEVNAME_SIZE]; \
+		printk(KERN_DEBUG "block %s:%lu: ", \
+			bdevname(bh->b_bdev, b), \
+			(unsigned long) bh->b_blocknr); \
+		printk(f); \
+		printk("\n"); \
+	} while (0)
+#else
+# define ea_idebug(f...)
+# define ea_bdebug(f...)
+#endif
+
+static void ext4_xattr_cache_insert(struct buffer_head *);
+static struct buffer_head *ext4_xattr_cache_find(struct inode *,
+						 struct ext4_xattr_header *,
+						 struct mb_cache_entry **);
+static void ext4_xattr_rehash(struct ext4_xattr_header *,
+			      struct ext4_xattr_entry *);
+
+static struct mb_cache *ext4_xattr_cache;
+
+static struct xattr_handler *ext4_xattr_handler_map[] = {
+	[EXT4_XATTR_INDEX_USER]		     = &ext4_xattr_user_handler,
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+	[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext4_xattr_acl_access_handler,
+	[EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext4_xattr_acl_default_handler,
+#endif
+	[EXT4_XATTR_INDEX_TRUSTED]	     = &ext4_xattr_trusted_handler,
+#ifdef CONFIG_EXT4DEV_FS_SECURITY
+	[EXT4_XATTR_INDEX_SECURITY]	     = &ext4_xattr_security_handler,
+#endif
+};
+
+struct xattr_handler *ext4_xattr_handlers[] = {
+	&ext4_xattr_user_handler,
+	&ext4_xattr_trusted_handler,
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+	&ext4_xattr_acl_access_handler,
+	&ext4_xattr_acl_default_handler,
+#endif
+#ifdef CONFIG_EXT4DEV_FS_SECURITY
+	&ext4_xattr_security_handler,
+#endif
+	NULL
+};
+
+static inline struct xattr_handler *
+ext4_xattr_handler(int name_index)
+{
+	struct xattr_handler *handler = NULL;
+
+	if (name_index > 0 && name_index < ARRAY_SIZE(ext4_xattr_handler_map))
+		handler = ext4_xattr_handler_map[name_index];
+	return handler;
+}
+
+/*
+ * Inode operation listxattr()
+ *
+ * dentry->d_inode->i_mutex: don't care
+ */
+ssize_t
+ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	return ext4_xattr_list(dentry->d_inode, buffer, size);
+}
+
+static int
+ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end)
+{
+	while (!IS_LAST_ENTRY(entry)) {
+		struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry);
+		if ((void *)next >= end)
+			return -EIO;
+		entry = next;
+	}
+	return 0;
+}
+
+static inline int
+ext4_xattr_check_block(struct buffer_head *bh)
+{
+	int error;
+
+	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+	    BHDR(bh)->h_blocks != cpu_to_le32(1))
+		return -EIO;
+	error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size);
+	return error;
+}
+
+static inline int
+ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
+{
+	size_t value_size = le32_to_cpu(entry->e_value_size);
+
+	if (entry->e_value_block != 0 || value_size > size ||
+	    le16_to_cpu(entry->e_value_offs) + value_size > size)
+		return -EIO;
+	return 0;
+}
+
+static int
+ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
+		      const char *name, size_t size, int sorted)
+{
+	struct ext4_xattr_entry *entry;
+	size_t name_len;
+	int cmp = 1;
+
+	if (name == NULL)
+		return -EINVAL;
+	name_len = strlen(name);
+	entry = *pentry;
+	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
+		cmp = name_index - entry->e_name_index;
+		if (!cmp)
+			cmp = name_len - entry->e_name_len;
+		if (!cmp)
+			cmp = memcmp(name, entry->e_name, name_len);
+		if (cmp <= 0 && (sorted || cmp == 0))
+			break;
+	}
+	*pentry = entry;
+	if (!cmp && ext4_xattr_check_entry(entry, size))
+			return -EIO;
+	return cmp ? -ENODATA : 0;
+}
+
+static int
+ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+		     void *buffer, size_t buffer_size)
+{
+	struct buffer_head *bh = NULL;
+	struct ext4_xattr_entry *entry;
+	size_t size;
+	int error;
+
+	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
+		  name_index, name, buffer, (long)buffer_size);
+
+	error = -ENODATA;
+	if (!EXT4_I(inode)->i_file_acl)
+		goto cleanup;
+	ea_idebug(inode, "reading block %u", EXT4_I(inode)->i_file_acl);
+	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+	if (!bh)
+		goto cleanup;
+	ea_bdebug(bh, "b_count=%d, refcount=%d",
+		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+	if (ext4_xattr_check_block(bh)) {
+bad_block:	ext4_error(inode->i_sb, __FUNCTION__,
+			   "inode %lu: bad block %llu", inode->i_ino,
+			   EXT4_I(inode)->i_file_acl);
+		error = -EIO;
+		goto cleanup;
+	}
+	ext4_xattr_cache_insert(bh);
+	entry = BFIRST(bh);
+	error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
+	if (error == -EIO)
+		goto bad_block;
+	if (error)
+		goto cleanup;
+	size = le32_to_cpu(entry->e_value_size);
+	if (buffer) {
+		error = -ERANGE;
+		if (size > buffer_size)
+			goto cleanup;
+		memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
+		       size);
+	}
+	error = size;
+
+cleanup:
+	brelse(bh);
+	return error;
+}
+
+static int
+ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+		     void *buffer, size_t buffer_size)
+{
+	struct ext4_xattr_ibody_header *header;
+	struct ext4_xattr_entry *entry;
+	struct ext4_inode *raw_inode;
+	struct ext4_iloc iloc;
+	size_t size;
+	void *end;
+	int error;
+
+	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
+		return -ENODATA;
+	error = ext4_get_inode_loc(inode, &iloc);
+	if (error)
+		return error;
+	raw_inode = ext4_raw_inode(&iloc);
+	header = IHDR(inode, raw_inode);
+	entry = IFIRST(header);
+	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+	error = ext4_xattr_check_names(entry, end);
+	if (error)
+		goto cleanup;
+	error = ext4_xattr_find_entry(&entry, name_index, name,
+				      end - (void *)entry, 0);
+	if (error)
+		goto cleanup;
+	size = le32_to_cpu(entry->e_value_size);
+	if (buffer) {
+		error = -ERANGE;
+		if (size > buffer_size)
+			goto cleanup;
+		memcpy(buffer, (void *)IFIRST(header) +
+		       le16_to_cpu(entry->e_value_offs), size);
+	}
+	error = size;
+
+cleanup:
+	brelse(iloc.bh);
+	return error;
+}
+
+/*
+ * ext4_xattr_get()
+ *
+ * Copy an extended attribute into the buffer
+ * provided, or compute the buffer size required.
+ * Buffer is NULL to compute the size of the buffer required.
+ *
+ * Returns a negative error number on failure, or the number of bytes
+ * used / required on success.
+ */
+int
+ext4_xattr_get(struct inode *inode, int name_index, const char *name,
+	       void *buffer, size_t buffer_size)
+{
+	int error;
+
+	down_read(&EXT4_I(inode)->xattr_sem);
+	error = ext4_xattr_ibody_get(inode, name_index, name, buffer,
+				     buffer_size);
+	if (error == -ENODATA)
+		error = ext4_xattr_block_get(inode, name_index, name, buffer,
+					     buffer_size);
+	up_read(&EXT4_I(inode)->xattr_sem);
+	return error;
+}
+
+static int
+ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
+			char *buffer, size_t buffer_size)
+{
+	size_t rest = buffer_size;
+
+	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
+		struct xattr_handler *handler =
+			ext4_xattr_handler(entry->e_name_index);
+
+		if (handler) {
+			size_t size = handler->list(inode, buffer, rest,
+						    entry->e_name,
+						    entry->e_name_len);
+			if (buffer) {
+				if (size > rest)
+					return -ERANGE;
+				buffer += size;
+			}
+			rest -= size;
+		}
+	}
+	return buffer_size - rest;
+}
+
+static int
+ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+{
+	struct buffer_head *bh = NULL;
+	int error;
+
+	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
+		  buffer, (long)buffer_size);
+
+	error = 0;
+	if (!EXT4_I(inode)->i_file_acl)
+		goto cleanup;
+	ea_idebug(inode, "reading block %u", EXT4_I(inode)->i_file_acl);
+	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+	error = -EIO;
+	if (!bh)
+		goto cleanup;
+	ea_bdebug(bh, "b_count=%d, refcount=%d",
+		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+	if (ext4_xattr_check_block(bh)) {
+		ext4_error(inode->i_sb, __FUNCTION__,
+			   "inode %lu: bad block %llu", inode->i_ino,
+			   EXT4_I(inode)->i_file_acl);
+		error = -EIO;
+		goto cleanup;
+	}
+	ext4_xattr_cache_insert(bh);
+	error = ext4_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
+
+cleanup:
+	brelse(bh);
+
+	return error;
+}
+
+static int
+ext4_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
+{
+	struct ext4_xattr_ibody_header *header;
+	struct ext4_inode *raw_inode;
+	struct ext4_iloc iloc;
+	void *end;
+	int error;
+
+	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
+		return 0;
+	error = ext4_get_inode_loc(inode, &iloc);
+	if (error)
+		return error;
+	raw_inode = ext4_raw_inode(&iloc);
+	header = IHDR(inode, raw_inode);
+	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+	error = ext4_xattr_check_names(IFIRST(header), end);
+	if (error)
+		goto cleanup;
+	error = ext4_xattr_list_entries(inode, IFIRST(header),
+					buffer, buffer_size);
+
+cleanup:
+	brelse(iloc.bh);
+	return error;
+}
+
+/*
+ * ext4_xattr_list()
+ *
+ * Copy a list of attribute names into the buffer
+ * provided, or compute the buffer size required.
+ * Buffer is NULL to compute the size of the buffer required.
+ *
+ * Returns a negative error number on failure, or the number of bytes
+ * used / required on success.
+ */
+int
+ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+{
+	int i_error, b_error;
+
+	down_read(&EXT4_I(inode)->xattr_sem);
+	i_error = ext4_xattr_ibody_list(inode, buffer, buffer_size);
+	if (i_error < 0) {
+		b_error = 0;
+	} else {
+		if (buffer) {
+			buffer += i_error;
+			buffer_size -= i_error;
+		}
+		b_error = ext4_xattr_block_list(inode, buffer, buffer_size);
+		if (b_error < 0)
+			i_error = 0;
+	}
+	up_read(&EXT4_I(inode)->xattr_sem);
+	return i_error + b_error;
+}
+
+/*
+ * If the EXT4_FEATURE_COMPAT_EXT_ATTR feature of this file system is
+ * not set, set it.
+ */
+static void ext4_xattr_update_super_block(handle_t *handle,
+					  struct super_block *sb)
+{
+	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR))
+		return;
+
+	lock_super(sb);
+	if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
+		EXT4_SB(sb)->s_es->s_feature_compat |=
+			cpu_to_le32(EXT4_FEATURE_COMPAT_EXT_ATTR);
+		sb->s_dirt = 1;
+		ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
+	}
+	unlock_super(sb);
+}
+
+/*
+ * Release the xattr block BH: If the reference count is > 1, decrement
+ * it; otherwise free the block.
+ */
+static void
+ext4_xattr_release_block(handle_t *handle, struct inode *inode,
+			 struct buffer_head *bh)
+{
+	struct mb_cache_entry *ce = NULL;
+
+	ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr);
+	if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
+		ea_bdebug(bh, "refcount now=0; freeing");
+		if (ce)
+			mb_cache_entry_free(ce);
+		ext4_free_blocks(handle, inode, bh->b_blocknr, 1);
+		get_bh(bh);
+		ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
+	} else {
+		if (ext4_journal_get_write_access(handle, bh) == 0) {
+			lock_buffer(bh);
+			BHDR(bh)->h_refcount = cpu_to_le32(
+				le32_to_cpu(BHDR(bh)->h_refcount) - 1);
+			ext4_journal_dirty_metadata(handle, bh);
+			if (IS_SYNC(inode))
+				handle->h_sync = 1;
+			DQUOT_FREE_BLOCK(inode, 1);
+			unlock_buffer(bh);
+			ea_bdebug(bh, "refcount now=%d; releasing",
+				  le32_to_cpu(BHDR(bh)->h_refcount));
+		}
+		if (ce)
+			mb_cache_entry_release(ce);
+	}
+}
+
+struct ext4_xattr_info {
+	int name_index;
+	const char *name;
+	const void *value;
+	size_t value_len;
+};
+
+struct ext4_xattr_search {
+	struct ext4_xattr_entry *first;
+	void *base;
+	void *end;
+	struct ext4_xattr_entry *here;
+	int not_found;
+};
+
+static int
+ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
+{
+	struct ext4_xattr_entry *last;
+	size_t free, min_offs = s->end - s->base, name_len = strlen(i->name);
+
+	/* Compute min_offs and last. */
+	last = s->first;
+	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
+		if (!last->e_value_block && last->e_value_size) {
+			size_t offs = le16_to_cpu(last->e_value_offs);
+			if (offs < min_offs)
+				min_offs = offs;
+		}
+	}
+	free = min_offs - ((void *)last - s->base) - sizeof(__u32);
+	if (!s->not_found) {
+		if (!s->here->e_value_block && s->here->e_value_size) {
+			size_t size = le32_to_cpu(s->here->e_value_size);
+			free += EXT4_XATTR_SIZE(size);
+		}
+		free += EXT4_XATTR_LEN(name_len);
+	}
+	if (i->value) {
+		if (free < EXT4_XATTR_SIZE(i->value_len) ||
+		    free < EXT4_XATTR_LEN(name_len) +
+			   EXT4_XATTR_SIZE(i->value_len))
+			return -ENOSPC;
+	}
+
+	if (i->value && s->not_found) {
+		/* Insert the new name. */
+		size_t size = EXT4_XATTR_LEN(name_len);
+		size_t rest = (void *)last - (void *)s->here + sizeof(__u32);
+		memmove((void *)s->here + size, s->here, rest);
+		memset(s->here, 0, size);
+		s->here->e_name_index = i->name_index;
+		s->here->e_name_len = name_len;
+		memcpy(s->here->e_name, i->name, name_len);
+	} else {
+		if (!s->here->e_value_block && s->here->e_value_size) {
+			void *first_val = s->base + min_offs;
+			size_t offs = le16_to_cpu(s->here->e_value_offs);
+			void *val = s->base + offs;
+			size_t size = EXT4_XATTR_SIZE(
+				le32_to_cpu(s->here->e_value_size));
+
+			if (i->value && size == EXT4_XATTR_SIZE(i->value_len)) {
+				/* The old and the new value have the same
+				   size. Just replace. */
+				s->here->e_value_size =
+					cpu_to_le32(i->value_len);
+				memset(val + size - EXT4_XATTR_PAD, 0,
+				       EXT4_XATTR_PAD); /* Clear pad bytes. */
+				memcpy(val, i->value, i->value_len);
+				return 0;
+			}
+
+			/* Remove the old value. */
+			memmove(first_val + size, first_val, val - first_val);
+			memset(first_val, 0, size);
+			s->here->e_value_size = 0;
+			s->here->e_value_offs = 0;
+			min_offs += size;
+
+			/* Adjust all value offsets. */
+			last = s->first;
+			while (!IS_LAST_ENTRY(last)) {
+				size_t o = le16_to_cpu(last->e_value_offs);
+				if (!last->e_value_block &&
+				    last->e_value_size && o < offs)
+					last->e_value_offs =
+						cpu_to_le16(o + size);
+				last = EXT4_XATTR_NEXT(last);
+			}
+		}
+		if (!i->value) {
+			/* Remove the old name. */
+			size_t size = EXT4_XATTR_LEN(name_len);
+			last = ENTRY((void *)last - size);
+			memmove(s->here, (void *)s->here + size,
+				(void *)last - (void *)s->here + sizeof(__u32));
+			memset(last, 0, size);
+		}
+	}
+
+	if (i->value) {
+		/* Insert the new value. */
+		s->here->e_value_size = cpu_to_le32(i->value_len);
+		if (i->value_len) {
+			size_t size = EXT4_XATTR_SIZE(i->value_len);
+			void *val = s->base + min_offs - size;
+			s->here->e_value_offs = cpu_to_le16(min_offs - size);
+			memset(val + size - EXT4_XATTR_PAD, 0,
+			       EXT4_XATTR_PAD); /* Clear the pad bytes. */
+			memcpy(val, i->value, i->value_len);
+		}
+	}
+	return 0;
+}
+
+struct ext4_xattr_block_find {
+	struct ext4_xattr_search s;
+	struct buffer_head *bh;
+};
+
+static int
+ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+		      struct ext4_xattr_block_find *bs)
+{
+	struct super_block *sb = inode->i_sb;
+	int error;
+
+	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
+		  i->name_index, i->name, i->value, (long)i->value_len);
+
+	if (EXT4_I(inode)->i_file_acl) {
+		/* The inode already has an extended attribute block. */
+		bs->bh = sb_bread(sb, EXT4_I(inode)->i_file_acl);
+		error = -EIO;
+		if (!bs->bh)
+			goto cleanup;
+		ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
+			atomic_read(&(bs->bh->b_count)),
+			le32_to_cpu(BHDR(bs->bh)->h_refcount));
+		if (ext4_xattr_check_block(bs->bh)) {
+			ext4_error(sb, __FUNCTION__,
+				"inode %lu: bad block %llu", inode->i_ino,
+				EXT4_I(inode)->i_file_acl);
+			error = -EIO;
+			goto cleanup;
+		}
+		/* Find the named attribute. */
+		bs->s.base = BHDR(bs->bh);
+		bs->s.first = BFIRST(bs->bh);
+		bs->s.end = bs->bh->b_data + bs->bh->b_size;
+		bs->s.here = bs->s.first;
+		error = ext4_xattr_find_entry(&bs->s.here, i->name_index,
+					      i->name, bs->bh->b_size, 1);
+		if (error && error != -ENODATA)
+			goto cleanup;
+		bs->s.not_found = error;
+	}
+	error = 0;
+
+cleanup:
+	return error;
+}
+
+static int
+ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+		     struct ext4_xattr_info *i,
+		     struct ext4_xattr_block_find *bs)
+{
+	struct super_block *sb = inode->i_sb;
+	struct buffer_head *new_bh = NULL;
+	struct ext4_xattr_search *s = &bs->s;
+	struct mb_cache_entry *ce = NULL;
+	int error;
+
+#define header(x) ((struct ext4_xattr_header *)(x))
+
+	if (i->value && i->value_len > sb->s_blocksize)
+		return -ENOSPC;
+	if (s->base) {
+		ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev,
+					bs->bh->b_blocknr);
+		if (header(s->base)->h_refcount == cpu_to_le32(1)) {
+			if (ce) {
+				mb_cache_entry_free(ce);
+				ce = NULL;
+			}
+			ea_bdebug(bs->bh, "modifying in-place");
+			error = ext4_journal_get_write_access(handle, bs->bh);
+			if (error)
+				goto cleanup;
+			lock_buffer(bs->bh);
+			error = ext4_xattr_set_entry(i, s);
+			if (!error) {
+				if (!IS_LAST_ENTRY(s->first))
+					ext4_xattr_rehash(header(s->base),
+							  s->here);
+				ext4_xattr_cache_insert(bs->bh);
+			}
+			unlock_buffer(bs->bh);
+			if (error == -EIO)
+				goto bad_block;
+			if (!error)
+				error = ext4_journal_dirty_metadata(handle,
+								    bs->bh);
+			if (error)
+				goto cleanup;
+			goto inserted;
+		} else {
+			int offset = (char *)s->here - bs->bh->b_data;
+
+			if (ce) {
+				mb_cache_entry_release(ce);
+				ce = NULL;
+			}
+			ea_bdebug(bs->bh, "cloning");
+			s->base = kmalloc(bs->bh->b_size, GFP_KERNEL);
+			error = -ENOMEM;
+			if (s->base == NULL)
+				goto cleanup;
+			memcpy(s->base, BHDR(bs->bh), bs->bh->b_size);
+			s->first = ENTRY(header(s->base)+1);
+			header(s->base)->h_refcount = cpu_to_le32(1);
+			s->here = ENTRY(s->base + offset);
+			s->end = s->base + bs->bh->b_size;
+		}
+	} else {
+		/* Allocate a buffer where we construct the new block. */
+		s->base = kmalloc(sb->s_blocksize, GFP_KERNEL);
+		/* assert(header == s->base) */
+		error = -ENOMEM;
+		if (s->base == NULL)
+			goto cleanup;
+		memset(s->base, 0, sb->s_blocksize);
+		header(s->base)->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
+		header(s->base)->h_blocks = cpu_to_le32(1);
+		header(s->base)->h_refcount = cpu_to_le32(1);
+		s->first = ENTRY(header(s->base)+1);
+		s->here = ENTRY(header(s->base)+1);
+		s->end = s->base + sb->s_blocksize;
+	}
+
+	error = ext4_xattr_set_entry(i, s);
+	if (error == -EIO)
+		goto bad_block;
+	if (error)
+		goto cleanup;
+	if (!IS_LAST_ENTRY(s->first))
+		ext4_xattr_rehash(header(s->base), s->here);
+
+inserted:
+	if (!IS_LAST_ENTRY(s->first)) {
+		new_bh = ext4_xattr_cache_find(inode, header(s->base), &ce);
+		if (new_bh) {
+			/* We found an identical block in the cache. */
+			if (new_bh == bs->bh)
+				ea_bdebug(new_bh, "keeping");
+			else {
+				/* The old block is released after updating
+				   the inode. */
+				error = -EDQUOT;
+				if (DQUOT_ALLOC_BLOCK(inode, 1))
+					goto cleanup;
+				error = ext4_journal_get_write_access(handle,
+								      new_bh);
+				if (error)
+					goto cleanup_dquot;
+				lock_buffer(new_bh);
+				BHDR(new_bh)->h_refcount = cpu_to_le32(1 +
+					le32_to_cpu(BHDR(new_bh)->h_refcount));
+				ea_bdebug(new_bh, "reusing; refcount now=%d",
+					le32_to_cpu(BHDR(new_bh)->h_refcount));
+				unlock_buffer(new_bh);
+				error = ext4_journal_dirty_metadata(handle,
+								    new_bh);
+				if (error)
+					goto cleanup_dquot;
+			}
+			mb_cache_entry_release(ce);
+			ce = NULL;
+		} else if (bs->bh && s->base == bs->bh->b_data) {
+			/* We were modifying this block in-place. */
+			ea_bdebug(bs->bh, "keeping this block");
+			new_bh = bs->bh;
+			get_bh(new_bh);
+		} else {
+			/* We need to allocate a new block */
+			ext4_fsblk_t goal = le32_to_cpu(
+					EXT4_SB(sb)->s_es->s_first_data_block) +
+				(ext4_fsblk_t)EXT4_I(inode)->i_block_group *
+				EXT4_BLOCKS_PER_GROUP(sb);
+			ext4_fsblk_t block = ext4_new_block(handle, inode,
+							goal, &error);
+			if (error)
+				goto cleanup;
+			ea_idebug(inode, "creating block %d", block);
+
+			new_bh = sb_getblk(sb, block);
+			if (!new_bh) {
+getblk_failed:
+				ext4_free_blocks(handle, inode, block, 1);
+				error = -EIO;
+				goto cleanup;
+			}
+			lock_buffer(new_bh);
+			error = ext4_journal_get_create_access(handle, new_bh);
+			if (error) {
+				unlock_buffer(new_bh);
+				goto getblk_failed;
+			}
+			memcpy(new_bh->b_data, s->base, new_bh->b_size);
+			set_buffer_uptodate(new_bh);
+			unlock_buffer(new_bh);
+			ext4_xattr_cache_insert(new_bh);
+			error = ext4_journal_dirty_metadata(handle, new_bh);
+			if (error)
+				goto cleanup;
+		}
+	}
+
+	/* Update the inode. */
+	EXT4_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
+
+	/* Drop the previous xattr block. */
+	if (bs->bh && bs->bh != new_bh)
+		ext4_xattr_release_block(handle, inode, bs->bh);
+	error = 0;
+
+cleanup:
+	if (ce)
+		mb_cache_entry_release(ce);
+	brelse(new_bh);
+	if (!(bs->bh && s->base == bs->bh->b_data))
+		kfree(s->base);
+
+	return error;
+
+cleanup_dquot:
+	DQUOT_FREE_BLOCK(inode, 1);
+	goto cleanup;
+
+bad_block:
+	ext4_error(inode->i_sb, __FUNCTION__,
+		   "inode %lu: bad block %llu", inode->i_ino,
+		   EXT4_I(inode)->i_file_acl);
+	goto cleanup;
+
+#undef header
+}
+
+struct ext4_xattr_ibody_find {
+	struct ext4_xattr_search s;
+	struct ext4_iloc iloc;
+};
+
+static int
+ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+		      struct ext4_xattr_ibody_find *is)
+{
+	struct ext4_xattr_ibody_header *header;
+	struct ext4_inode *raw_inode;
+	int error;
+
+	if (EXT4_I(inode)->i_extra_isize == 0)
+		return 0;
+	raw_inode = ext4_raw_inode(&is->iloc);
+	header = IHDR(inode, raw_inode);
+	is->s.base = is->s.first = IFIRST(header);
+	is->s.here = is->s.first;
+	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
+		error = ext4_xattr_check_names(IFIRST(header), is->s.end);
+		if (error)
+			return error;
+		/* Find the named attribute. */
+		error = ext4_xattr_find_entry(&is->s.here, i->name_index,
+					      i->name, is->s.end -
+					      (void *)is->s.base, 0);
+		if (error && error != -ENODATA)
+			return error;
+		is->s.not_found = error;
+	}
+	return 0;
+}
+
+static int
+ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
+		     struct ext4_xattr_info *i,
+		     struct ext4_xattr_ibody_find *is)
+{
+	struct ext4_xattr_ibody_header *header;
+	struct ext4_xattr_search *s = &is->s;
+	int error;
+
+	if (EXT4_I(inode)->i_extra_isize == 0)
+		return -ENOSPC;
+	error = ext4_xattr_set_entry(i, s);
+	if (error)
+		return error;
+	header = IHDR(inode, ext4_raw_inode(&is->iloc));
+	if (!IS_LAST_ENTRY(s->first)) {
+		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
+		EXT4_I(inode)->i_state |= EXT4_STATE_XATTR;
+	} else {
+		header->h_magic = cpu_to_le32(0);
+		EXT4_I(inode)->i_state &= ~EXT4_STATE_XATTR;
+	}
+	return 0;
+}
+
+/*
+ * ext4_xattr_set_handle()
+ *
+ * Create, replace or remove an extended attribute for this inode. Buffer
+ * is NULL to remove an existing extended attribute, and non-NULL to
+ * either replace an existing extended attribute, or create a new extended
+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
+ * specify that an extended attribute must exist and must not exist
+ * previous to the call, respectively.
+ *
+ * Returns 0, or a negative error number on failure.
+ */
+int
+ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+		      const char *name, const void *value, size_t value_len,
+		      int flags)
+{
+	struct ext4_xattr_info i = {
+		.name_index = name_index,
+		.name = name,
+		.value = value,
+		.value_len = value_len,
+
+	};
+	struct ext4_xattr_ibody_find is = {
+		.s = { .not_found = -ENODATA, },
+	};
+	struct ext4_xattr_block_find bs = {
+		.s = { .not_found = -ENODATA, },
+	};
+	int error;
+
+	if (!name)
+		return -EINVAL;
+	if (strlen(name) > 255)
+		return -ERANGE;
+	down_write(&EXT4_I(inode)->xattr_sem);
+	error = ext4_get_inode_loc(inode, &is.iloc);
+	if (error)
+		goto cleanup;
+
+	if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) {
+		struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
+		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
+		EXT4_I(inode)->i_state &= ~EXT4_STATE_NEW;
+	}
+
+	error = ext4_xattr_ibody_find(inode, &i, &is);
+	if (error)
+		goto cleanup;
+	if (is.s.not_found)
+		error = ext4_xattr_block_find(inode, &i, &bs);
+	if (error)
+		goto cleanup;
+	if (is.s.not_found && bs.s.not_found) {
+		error = -ENODATA;
+		if (flags & XATTR_REPLACE)
+			goto cleanup;
+		error = 0;
+		if (!value)
+			goto cleanup;
+	} else {
+		error = -EEXIST;
+		if (flags & XATTR_CREATE)
+			goto cleanup;
+	}
+	error = ext4_journal_get_write_access(handle, is.iloc.bh);
+	if (error)
+		goto cleanup;
+	if (!value) {
+		if (!is.s.not_found)
+			error = ext4_xattr_ibody_set(handle, inode, &i, &is);
+		else if (!bs.s.not_found)
+			error = ext4_xattr_block_set(handle, inode, &i, &bs);
+	} else {
+		error = ext4_xattr_ibody_set(handle, inode, &i, &is);
+		if (!error && !bs.s.not_found) {
+			i.value = NULL;
+			error = ext4_xattr_block_set(handle, inode, &i, &bs);
+		} else if (error == -ENOSPC) {
+			error = ext4_xattr_block_set(handle, inode, &i, &bs);
+			if (error)
+				goto cleanup;
+			if (!is.s.not_found) {
+				i.value = NULL;
+				error = ext4_xattr_ibody_set(handle, inode, &i,
+							     &is);
+			}
+		}
+	}
+	if (!error) {
+		ext4_xattr_update_super_block(handle, inode->i_sb);
+		inode->i_ctime = CURRENT_TIME_SEC;
+		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
+		/*
+		 * The bh is consumed by ext4_mark_iloc_dirty, even with
+		 * error != 0.
+		 */
+		is.iloc.bh = NULL;
+		if (IS_SYNC(inode))
+			handle->h_sync = 1;
+	}
+
+cleanup:
+	brelse(is.iloc.bh);
+	brelse(bs.bh);
+	up_write(&EXT4_I(inode)->xattr_sem);
+	return error;
+}
+
+/*
+ * ext4_xattr_set()
+ *
+ * Like ext4_xattr_set_handle, but start from an inode. This extended
+ * attribute modification is a filesystem transaction by itself.
+ *
+ * Returns 0, or a negative error number on failure.
+ */
+int
+ext4_xattr_set(struct inode *inode, int name_index, const char *name,
+	       const void *value, size_t value_len, int flags)
+{
+	handle_t *handle;
+	int error, retries = 0;
+
+retry:
+	handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle)) {
+		error = PTR_ERR(handle);
+	} else {
+		int error2;
+
+		error = ext4_xattr_set_handle(handle, inode, name_index, name,
+					      value, value_len, flags);
+		error2 = ext4_journal_stop(handle);
+		if (error == -ENOSPC &&
+		    ext4_should_retry_alloc(inode->i_sb, &retries))
+			goto retry;
+		if (error == 0)
+			error = error2;
+	}
+
+	return error;
+}
+
+/*
+ * ext4_xattr_delete_inode()
+ *
+ * Free extended attribute resources associated with this inode. This
+ * is called immediately before an inode is freed. We have exclusive
+ * access to the inode.
+ */
+void
+ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
+{
+	struct buffer_head *bh = NULL;
+
+	if (!EXT4_I(inode)->i_file_acl)
+		goto cleanup;
+	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+	if (!bh) {
+		ext4_error(inode->i_sb, __FUNCTION__,
+			"inode %lu: block %llu read error", inode->i_ino,
+			EXT4_I(inode)->i_file_acl);
+		goto cleanup;
+	}
+	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+	    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
+		ext4_error(inode->i_sb, __FUNCTION__,
+			"inode %lu: bad block %llu", inode->i_ino,
+			EXT4_I(inode)->i_file_acl);
+		goto cleanup;
+	}
+	ext4_xattr_release_block(handle, inode, bh);
+	EXT4_I(inode)->i_file_acl = 0;
+
+cleanup:
+	brelse(bh);
+}
+
+/*
+ * ext4_xattr_put_super()
+ *
+ * This is called when a file system is unmounted.
+ */
+void
+ext4_xattr_put_super(struct super_block *sb)
+{
+	mb_cache_shrink(sb->s_bdev);
+}
+
+/*
+ * ext4_xattr_cache_insert()
+ *
+ * Create a new entry in the extended attribute cache, and insert
+ * it unless such an entry is already in the cache.
+ *
+ * Returns 0, or a negative error number on failure.
+ */
+static void
+ext4_xattr_cache_insert(struct buffer_head *bh)
+{
+	__u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
+	struct mb_cache_entry *ce;
+	int error;
+
+	ce = mb_cache_entry_alloc(ext4_xattr_cache);
+	if (!ce) {
+		ea_bdebug(bh, "out of memory");
+		return;
+	}
+	error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash);
+	if (error) {
+		mb_cache_entry_free(ce);
+		if (error == -EBUSY) {
+			ea_bdebug(bh, "already in cache");
+			error = 0;
+		}
+	} else {
+		ea_bdebug(bh, "inserting [%x]", (int)hash);
+		mb_cache_entry_release(ce);
+	}
+}
+
+/*
+ * ext4_xattr_cmp()
+ *
+ * Compare two extended attribute blocks for equality.
+ *
+ * Returns 0 if the blocks are equal, 1 if they differ, and
+ * a negative error number on errors.
+ */
+static int
+ext4_xattr_cmp(struct ext4_xattr_header *header1,
+	       struct ext4_xattr_header *header2)
+{
+	struct ext4_xattr_entry *entry1, *entry2;
+
+	entry1 = ENTRY(header1+1);
+	entry2 = ENTRY(header2+1);
+	while (!IS_LAST_ENTRY(entry1)) {
+		if (IS_LAST_ENTRY(entry2))
+			return 1;
+		if (entry1->e_hash != entry2->e_hash ||
+		    entry1->e_name_index != entry2->e_name_index ||
+		    entry1->e_name_len != entry2->e_name_len ||
+		    entry1->e_value_size != entry2->e_value_size ||
+		    memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
+			return 1;
+		if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
+			return -EIO;
+		if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
+			   (char *)header2 + le16_to_cpu(entry2->e_value_offs),
+			   le32_to_cpu(entry1->e_value_size)))
+			return 1;
+
+		entry1 = EXT4_XATTR_NEXT(entry1);
+		entry2 = EXT4_XATTR_NEXT(entry2);
+	}
+	if (!IS_LAST_ENTRY(entry2))
+		return 1;
+	return 0;
+}
+
+/*
+ * ext4_xattr_cache_find()
+ *
+ * Find an identical extended attribute block.
+ *
+ * Returns a pointer to the block found, or NULL if such a block was
+ * not found or an error occurred.
+ */
+static struct buffer_head *
+ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header,
+		      struct mb_cache_entry **pce)
+{
+	__u32 hash = le32_to_cpu(header->h_hash);
+	struct mb_cache_entry *ce;
+
+	if (!header->h_hash)
+		return NULL;  /* never share */
+	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
+again:
+	ce = mb_cache_entry_find_first(ext4_xattr_cache, 0,
+				       inode->i_sb->s_bdev, hash);
+	while (ce) {
+		struct buffer_head *bh;
+
+		if (IS_ERR(ce)) {
+			if (PTR_ERR(ce) == -EAGAIN)
+				goto again;
+			break;
+		}
+		bh = sb_bread(inode->i_sb, ce->e_block);
+		if (!bh) {
+			ext4_error(inode->i_sb, __FUNCTION__,
+				"inode %lu: block %lu read error",
+				inode->i_ino, (unsigned long) ce->e_block);
+		} else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
+				EXT4_XATTR_REFCOUNT_MAX) {
+			ea_idebug(inode, "block %lu refcount %d>=%d",
+				  (unsigned long) ce->e_block,
+				  le32_to_cpu(BHDR(bh)->h_refcount),
+					  EXT4_XATTR_REFCOUNT_MAX);
+		} else if (ext4_xattr_cmp(header, BHDR(bh)) == 0) {
+			*pce = ce;
+			return bh;
+		}
+		brelse(bh);
+		ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
+	}
+	return NULL;
+}
+
+#define NAME_HASH_SHIFT 5
+#define VALUE_HASH_SHIFT 16
+
+/*
+ * ext4_xattr_hash_entry()
+ *
+ * Compute the hash of an extended attribute.
+ */
+static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header,
+					 struct ext4_xattr_entry *entry)
+{
+	__u32 hash = 0;
+	char *name = entry->e_name;
+	int n;
+
+	for (n=0; n < entry->e_name_len; n++) {
+		hash = (hash << NAME_HASH_SHIFT) ^
+		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
+		       *name++;
+	}
+
+	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
+		__le32 *value = (__le32 *)((char *)header +
+			le16_to_cpu(entry->e_value_offs));
+		for (n = (le32_to_cpu(entry->e_value_size) +
+		     EXT4_XATTR_ROUND) >> EXT4_XATTR_PAD_BITS; n; n--) {
+			hash = (hash << VALUE_HASH_SHIFT) ^
+			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
+			       le32_to_cpu(*value++);
+		}
+	}
+	entry->e_hash = cpu_to_le32(hash);
+}
+
+#undef NAME_HASH_SHIFT
+#undef VALUE_HASH_SHIFT
+
+#define BLOCK_HASH_SHIFT 16
+
+/*
+ * ext4_xattr_rehash()
+ *
+ * Re-compute the extended attribute hash value after an entry has changed.
+ */
+static void ext4_xattr_rehash(struct ext4_xattr_header *header,
+			      struct ext4_xattr_entry *entry)
+{
+	struct ext4_xattr_entry *here;
+	__u32 hash = 0;
+
+	ext4_xattr_hash_entry(header, entry);
+	here = ENTRY(header+1);
+	while (!IS_LAST_ENTRY(here)) {
+		if (!here->e_hash) {
+			/* Block is not shared if an entry's hash value == 0 */
+			hash = 0;
+			break;
+		}
+		hash = (hash << BLOCK_HASH_SHIFT) ^
+		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
+		       le32_to_cpu(here->e_hash);
+		here = EXT4_XATTR_NEXT(here);
+	}
+	header->h_hash = cpu_to_le32(hash);
+}
+
+#undef BLOCK_HASH_SHIFT
+
+int __init
+init_ext4_xattr(void)
+{
+	ext4_xattr_cache = mb_cache_create("ext4_xattr", NULL,
+		sizeof(struct mb_cache_entry) +
+		sizeof(((struct mb_cache_entry *) 0)->e_indexes[0]), 1, 6);
+	if (!ext4_xattr_cache)
+		return -ENOMEM;
+	return 0;
+}
+
+void
+exit_ext4_xattr(void)
+{
+	if (ext4_xattr_cache)
+		mb_cache_destroy(ext4_xattr_cache);
+	ext4_xattr_cache = NULL;
+}
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
new file mode 100644
index 0000000..79432b3
--- /dev/null
+++ b/fs/ext4/xattr.h
@@ -0,0 +1,145 @@
+/*
+  File: fs/ext4/xattr.h
+
+  On-disk format of extended attributes for the ext4 filesystem.
+
+  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
+*/
+
+#include <linux/xattr.h>
+
+/* Magic value in attribute blocks */
+#define EXT4_XATTR_MAGIC		0xEA020000
+
+/* Maximum number of references to one attribute block */
+#define EXT4_XATTR_REFCOUNT_MAX		1024
+
+/* Name indexes */
+#define EXT4_XATTR_INDEX_USER			1
+#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS	2
+#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define EXT4_XATTR_INDEX_TRUSTED		4
+#define	EXT4_XATTR_INDEX_LUSTRE			5
+#define EXT4_XATTR_INDEX_SECURITY	        6
+
+struct ext4_xattr_header {
+	__le32	h_magic;	/* magic number for identification */
+	__le32	h_refcount;	/* reference count */
+	__le32	h_blocks;	/* number of disk blocks used */
+	__le32	h_hash;		/* hash value of all attributes */
+	__u32	h_reserved[4];	/* zero right now */
+};
+
+struct ext4_xattr_ibody_header {
+	__le32	h_magic;	/* magic number for identification */
+};
+
+struct ext4_xattr_entry {
+	__u8	e_name_len;	/* length of name */
+	__u8	e_name_index;	/* attribute name index */
+	__le16	e_value_offs;	/* offset in disk block of value */
+	__le32	e_value_block;	/* disk block attribute is stored on (n/i) */
+	__le32	e_value_size;	/* size of attribute value */
+	__le32	e_hash;		/* hash value of name and value */
+	char	e_name[0];	/* attribute name */
+};
+
+#define EXT4_XATTR_PAD_BITS		2
+#define EXT4_XATTR_PAD		(1<<EXT4_XATTR_PAD_BITS)
+#define EXT4_XATTR_ROUND		(EXT4_XATTR_PAD-1)
+#define EXT4_XATTR_LEN(name_len) \
+	(((name_len) + EXT4_XATTR_ROUND + \
+	sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
+#define EXT4_XATTR_NEXT(entry) \
+	( (struct ext4_xattr_entry *)( \
+	  (char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)) )
+#define EXT4_XATTR_SIZE(size) \
+	(((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)
+
+# ifdef CONFIG_EXT4DEV_FS_XATTR
+
+extern struct xattr_handler ext4_xattr_user_handler;
+extern struct xattr_handler ext4_xattr_trusted_handler;
+extern struct xattr_handler ext4_xattr_acl_access_handler;
+extern struct xattr_handler ext4_xattr_acl_default_handler;
+extern struct xattr_handler ext4_xattr_security_handler;
+
+extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
+
+extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
+extern int ext4_xattr_list(struct inode *, char *, size_t);
+extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
+extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
+
+extern void ext4_xattr_delete_inode(handle_t *, struct inode *);
+extern void ext4_xattr_put_super(struct super_block *);
+
+extern int init_ext4_xattr(void);
+extern void exit_ext4_xattr(void);
+
+extern struct xattr_handler *ext4_xattr_handlers[];
+
+# else  /* CONFIG_EXT4DEV_FS_XATTR */
+
+static inline int
+ext4_xattr_get(struct inode *inode, int name_index, const char *name,
+	       void *buffer, size_t size, int flags)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int
+ext4_xattr_list(struct inode *inode, void *buffer, size_t size)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int
+ext4_xattr_set(struct inode *inode, int name_index, const char *name,
+	       const void *value, size_t size, int flags)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int
+ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+	       const char *name, const void *value, size_t size, int flags)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void
+ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
+{
+}
+
+static inline void
+ext4_xattr_put_super(struct super_block *sb)
+{
+}
+
+static inline int
+init_ext4_xattr(void)
+{
+	return 0;
+}
+
+static inline void
+exit_ext4_xattr(void)
+{
+}
+
+#define ext4_xattr_handlers	NULL
+
+# endif  /* CONFIG_EXT4DEV_FS_XATTR */
+
+#ifdef CONFIG_EXT4DEV_FS_SECURITY
+extern int ext4_init_security(handle_t *handle, struct inode *inode,
+				struct inode *dir);
+#else
+static inline int ext4_init_security(handle_t *handle, struct inode *inode,
+				struct inode *dir)
+{
+	return 0;
+}
+#endif
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
new file mode 100644
index 0000000..b6a6861
--- /dev/null
+++ b/fs/ext4/xattr_security.c
@@ -0,0 +1,77 @@
+/*
+ * linux/fs/ext4/xattr_security.c
+ * Handler for storing security labels as extended attributes.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/ext4_fs.h>
+#include <linux/security.h>
+#include "xattr.h"
+
+static size_t
+ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
+			 const char *name, size_t name_len)
+{
+	const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+	const size_t total_len = prefix_len + name_len + 1;
+
+
+	if (list && total_len <= list_size) {
+		memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return total_len;
+}
+
+static int
+ext4_xattr_security_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY, name,
+			      buffer, size);
+}
+
+static int
+ext4_xattr_security_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY, name,
+			      value, size, flags);
+}
+
+int
+ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
+{
+	int err;
+	size_t len;
+	void *value;
+	char *name;
+
+	err = security_inode_init_security(inode, dir, &name, &value, &len);
+	if (err) {
+		if (err == -EOPNOTSUPP)
+			return 0;
+		return err;
+	}
+	err = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_SECURITY,
+				    name, value, len, 0);
+	kfree(name);
+	kfree(value);
+	return err;
+}
+
+struct xattr_handler ext4_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.list	= ext4_xattr_security_list,
+	.get	= ext4_xattr_security_get,
+	.set	= ext4_xattr_security_set,
+};
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
new file mode 100644
index 0000000..b76f2db
--- /dev/null
+++ b/fs/ext4/xattr_trusted.c
@@ -0,0 +1,62 @@
+/*
+ * linux/fs/ext4/xattr_trusted.c
+ * Handler for trusted extended attributes.
+ *
+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/ext4_fs.h>
+#include "xattr.h"
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+
+static size_t
+ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
+			const char *name, size_t name_len)
+{
+	const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+	const size_t total_len = prefix_len + name_len + 1;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return 0;
+
+	if (list && total_len <= list_size) {
+		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return total_len;
+}
+
+static int
+ext4_xattr_trusted_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED, name,
+			      buffer, size);
+}
+
+static int
+ext4_xattr_trusted_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED, name,
+			      value, size, flags);
+}
+
+struct xattr_handler ext4_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.list	= ext4_xattr_trusted_list,
+	.get	= ext4_xattr_trusted_get,
+	.set	= ext4_xattr_trusted_set,
+};
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
new file mode 100644
index 0000000..c53cded
--- /dev/null
+++ b/fs/ext4/xattr_user.c
@@ -0,0 +1,64 @@
+/*
+ * linux/fs/ext4/xattr_user.c
+ * Handler for extended user attributes.
+ *
+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/ext4_fs.h>
+#include "xattr.h"
+
+#define XATTR_USER_PREFIX "user."
+
+static size_t
+ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
+		     const char *name, size_t name_len)
+{
+	const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
+	const size_t total_len = prefix_len + name_len + 1;
+
+	if (!test_opt(inode->i_sb, XATTR_USER))
+		return 0;
+
+	if (list && total_len <= list_size) {
+		memcpy(list, XATTR_USER_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return total_len;
+}
+
+static int
+ext4_xattr_user_get(struct inode *inode, const char *name,
+		    void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!test_opt(inode->i_sb, XATTR_USER))
+		return -EOPNOTSUPP;
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER, name, buffer, size);
+}
+
+static int
+ext4_xattr_user_set(struct inode *inode, const char *name,
+		    const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!test_opt(inode->i_sb, XATTR_USER))
+		return -EOPNOTSUPP;
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER, name,
+			      value, size, flags);
+}
+
+struct xattr_handler ext4_xattr_user_handler = {
+	.prefix	= XATTR_USER_PREFIX,
+	.list	= ext4_xattr_user_list,
+	.get	= ext4_xattr_user_get,
+	.set	= ext4_xattr_user_set,
+};
diff --git a/fs/fat/file.c b/fs/fat/file.c
index f4b8f8b..8337451 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/backing-dev.h>
 #include <linux/blkdev.h>
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
@@ -118,7 +119,7 @@
 	if ((filp->f_mode & FMODE_WRITE) &&
 	     MSDOS_SB(inode->i_sb)->options.flush) {
 		fat_flush_inodes(inode->i_sb, inode, NULL);
-		blk_congestion_wait(WRITE, HZ/10);
+		congestion_wait(WRITE, HZ/10);
 	}
 	return 0;
 }
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 0457380..78945b5 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -384,7 +384,7 @@
 				      le16_to_cpu(de->cdate)) + secs;
 		inode->i_ctime.tv_nsec = csecs * 10000000;
 		inode->i_atime.tv_sec =
-			date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate));
+			date_dos2unix(0, le16_to_cpu(de->adate));
 		inode->i_atime.tv_nsec = 0;
 	} else
 		inode->i_ctime = inode->i_atime = inode->i_mtime;
@@ -1472,7 +1472,7 @@
 		ret = writeback_inode(i1);
 	if (!ret && i2)
 		ret = writeback_inode(i2);
-	if (!ret && sb) {
+	if (!ret) {
 		struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
 		ret = filemap_flush(mapping);
 	}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8605155..cfc8f81 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -138,6 +138,7 @@
 		struct fuse_entry_out outarg;
 		struct fuse_conn *fc;
 		struct fuse_req *req;
+		struct dentry *parent;
 
 		/* Doesn't hurt to "reset" the validity timeout */
 		fuse_invalidate_entry_cache(entry);
@@ -151,8 +152,10 @@
 		if (IS_ERR(req))
 			return 0;
 
-		fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
+		parent = dget_parent(entry);
+		fuse_lookup_init(req, parent->d_inode, entry, &outarg);
 		request_send(fc, req);
+		dput(parent);
 		err = req->out.h.error;
 		/* Zero nodeid is same as -ENOENT */
 		if (!err && !outarg.nodeid)
@@ -163,7 +166,9 @@
 				fuse_send_forget(fc, req, outarg.nodeid, 1);
 				return 0;
 			}
+			spin_lock(&fc->lock);
 			fi->nlookup ++;
+			spin_unlock(&fc->lock);
 		}
 		fuse_put_request(fc, req);
 		if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
@@ -175,22 +180,6 @@
 	return 1;
 }
 
-/*
- * Check if there's already a hashed alias of this directory inode.
- * If yes, then lookup and mkdir must not create a new alias.
- */
-static int dir_alias(struct inode *inode)
-{
-	if (S_ISDIR(inode->i_mode)) {
-		struct dentry *alias = d_find_alias(inode);
-		if (alias) {
-			dput(alias);
-			return 1;
-		}
-	}
-	return 0;
-}
-
 static int invalid_nodeid(u64 nodeid)
 {
 	return !nodeid || nodeid == FUSE_ROOT_ID;
@@ -206,6 +195,24 @@
 		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
 }
 
+/*
+ * Add a directory inode to a dentry, ensuring that no other dentry
+ * refers to this inode.  Called with fc->inst_mutex.
+ */
+static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
+{
+	struct dentry *alias = d_find_alias(inode);
+	if (alias) {
+		/* This tries to shrink the subtree below alias */
+		fuse_invalidate_entry(alias);
+		dput(alias);
+		if (!list_empty(&inode->i_dentry))
+			return -EBUSY;
+	}
+	d_add(entry, inode);
+	return 0;
+}
+
 static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
 				  struct nameidata *nd)
 {
@@ -241,11 +248,17 @@
 	if (err && err != -ENOENT)
 		return ERR_PTR(err);
 
-	if (inode && dir_alias(inode)) {
-		iput(inode);
-		return ERR_PTR(-EIO);
-	}
-	d_add(entry, inode);
+	if (inode && S_ISDIR(inode->i_mode)) {
+		mutex_lock(&fc->inst_mutex);
+		err = fuse_d_add_directory(entry, inode);
+		mutex_unlock(&fc->inst_mutex);
+		if (err) {
+			iput(inode);
+			return ERR_PTR(err);
+		}
+	} else
+		d_add(entry, inode);
+
 	entry->d_op = &fuse_dentry_operations;
 	if (!err)
 		fuse_change_timeout(entry, &outarg);
@@ -401,12 +414,22 @@
 	}
 	fuse_put_request(fc, req);
 
-	if (dir_alias(inode)) {
-		iput(inode);
-		return -EIO;
-	}
+	if (S_ISDIR(inode->i_mode)) {
+		struct dentry *alias;
+		mutex_lock(&fc->inst_mutex);
+		alias = d_find_alias(inode);
+		if (alias) {
+			/* New directory must have moved since mkdir */
+			mutex_unlock(&fc->inst_mutex);
+			dput(alias);
+			iput(inode);
+			return -EBUSY;
+		}
+		d_instantiate(entry, inode);
+		mutex_unlock(&fc->inst_mutex);
+	} else
+		d_instantiate(entry, inode);
 
-	d_instantiate(entry, inode);
 	fuse_change_timeout(entry, &outarg);
 	fuse_invalidate_attr(dir);
 	return 0;
@@ -935,14 +958,30 @@
 	}
 }
 
+static void fuse_vmtruncate(struct inode *inode, loff_t offset)
+{
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	int need_trunc;
+
+	spin_lock(&fc->lock);
+	need_trunc = inode->i_size > offset;
+	i_size_write(inode, offset);
+	spin_unlock(&fc->lock);
+
+	if (need_trunc) {
+		struct address_space *mapping = inode->i_mapping;
+		unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+		truncate_inode_pages(mapping, offset);
+	}
+}
+
 /*
  * Set attributes, and at the same time refresh them.
  *
  * Truncation is slightly complicated, because the 'truncate' request
  * may fail, in which case we don't want to touch the mapping.
- * vmtruncate() doesn't allow for this case.  So do the rlimit
- * checking by hand and call vmtruncate() only after the file has
- * actually been truncated.
+ * vmtruncate() doesn't allow for this case, so do the rlimit checking
+ * and the actual truncation by hand.
  */
 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 {
@@ -993,12 +1032,8 @@
 			make_bad_inode(inode);
 			err = -EIO;
 		} else {
-			if (is_truncate) {
-				loff_t origsize = i_size_read(inode);
-				i_size_write(inode, outarg.attr.size);
-				if (origsize > outarg.attr.size)
-					vmtruncate(inode, outarg.attr.size);
-			}
+			if (is_truncate)
+				fuse_vmtruncate(inode, outarg.attr.size);
 			fuse_change_attributes(inode, &outarg.attr);
 			fi->i_time = time_to_jiffies(outarg.attr_valid,
 						     outarg.attr_valid_nsec);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 1836268..2bb5ace 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -481,8 +481,10 @@
 		err = -EIO;
 	if (!err) {
 		pos += count;
-		if (pos > i_size_read(inode))
+		spin_lock(&fc->lock);
+		if (pos > inode->i_size)
 			i_size_write(inode, pos);
+		spin_unlock(&fc->lock);
 
 		if (offset == 0 && to == PAGE_CACHE_SIZE) {
 			clear_page_dirty(page);
@@ -586,8 +588,12 @@
 	}
 	fuse_put_request(fc, req);
 	if (res > 0) {
-		if (write && pos > i_size_read(inode))
-			i_size_write(inode, pos);
+		if (write) {
+			spin_lock(&fc->lock);
+			if (pos > inode->i_size)
+				i_size_write(inode, pos);
+			spin_unlock(&fc->lock);
+		}
 		*ppos = pos;
 	}
 	fuse_invalidate_attr(inode);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 69c7750..91edb89 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -239,6 +239,9 @@
 	/** Lock protecting accessess to  members of this structure */
 	spinlock_t lock;
 
+	/** Mutex protecting against directory alias creation */
+	struct mutex inst_mutex;
+
 	/** Refcount */
 	atomic_t count;
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 7d0a9ae..fc42035 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -109,6 +109,7 @@
 
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
 {
+	struct fuse_conn *fc = get_fuse_conn(inode);
 	if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
 		invalidate_inode_pages(inode->i_mapping);
 
@@ -117,7 +118,9 @@
 	inode->i_nlink   = attr->nlink;
 	inode->i_uid     = attr->uid;
 	inode->i_gid     = attr->gid;
+	spin_lock(&fc->lock);
 	i_size_write(inode, attr->size);
+	spin_unlock(&fc->lock);
 	inode->i_blocks  = attr->blocks;
 	inode->i_atime.tv_sec   = attr->atime;
 	inode->i_atime.tv_nsec  = attr->atimensec;
@@ -130,7 +133,7 @@
 static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
 {
 	inode->i_mode = attr->mode & S_IFMT;
-	i_size_write(inode, attr->size);
+	inode->i_size = attr->size;
 	if (S_ISREG(inode->i_mode)) {
 		fuse_init_common(inode);
 		fuse_init_file_inode(inode);
@@ -169,7 +172,6 @@
 	struct inode *inode;
 	struct fuse_inode *fi;
 	struct fuse_conn *fc = get_fuse_conn_super(sb);
-	int retried = 0;
 
  retry:
 	inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
@@ -183,16 +185,16 @@
 		fuse_init_inode(inode, attr);
 		unlock_new_inode(inode);
 	} else if ((inode->i_mode ^ attr->mode) & S_IFMT) {
-		BUG_ON(retried);
 		/* Inode has changed type, any I/O on the old should fail */
 		make_bad_inode(inode);
 		iput(inode);
-		retried = 1;
 		goto retry;
 	}
 
 	fi = get_fuse_inode(inode);
+	spin_lock(&fc->lock);
 	fi->nlookup ++;
+	spin_unlock(&fc->lock);
 	fuse_change_attributes(inode, attr);
 	return inode;
 }
@@ -377,6 +379,7 @@
 	fc = kzalloc(sizeof(*fc), GFP_KERNEL);
 	if (fc) {
 		spin_lock_init(&fc->lock);
+		mutex_init(&fc->inst_mutex);
 		atomic_set(&fc->count, 1);
 		init_waitqueue_head(&fc->waitq);
 		init_waitqueue_head(&fc->blocked_waitq);
@@ -396,8 +399,10 @@
 
 void fuse_conn_put(struct fuse_conn *fc)
 {
-	if (atomic_dec_and_test(&fc->count))
+	if (atomic_dec_and_test(&fc->count)) {
+		mutex_destroy(&fc->inst_mutex);
 		kfree(fc);
+	}
 }
 
 struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index cc57f2e..06e9a8c 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -434,8 +434,7 @@
  */
 
 static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
-			       struct buffer_head *bh_map, struct metapath *mp,
-			       unsigned int maxlen)
+			       struct buffer_head *bh_map, struct metapath *mp)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -448,6 +447,7 @@
 	int new = 0;
 	u64 dblock = 0;
 	int boundary;
+	unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
 
 	BUG_ON(maxlen == 0);
 
@@ -541,13 +541,13 @@
 }
 
 int gfs2_block_map(struct inode *inode, u64 lblock, int create,
-		   struct buffer_head *bh, unsigned int maxlen)
+		   struct buffer_head *bh)
 {
 	struct metapath mp;
 	int ret;
 
 	bmap_lock(inode, create);
-	ret = gfs2_block_pointers(inode, lblock, create, bh, &mp, maxlen);
+	ret = gfs2_block_pointers(inode, lblock, create, bh, &mp);
 	bmap_unlock(inode, create);
 	return ret;
 }
@@ -555,7 +555,7 @@
 int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
 {
 	struct metapath mp;
-	struct buffer_head bh = { .b_state = 0, .b_blocknr = 0, .b_size = 0 };
+	struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
 	int ret;
 	int create = *new;
 
@@ -563,8 +563,9 @@
 	BUG_ON(!dblock);
 	BUG_ON(!new);
 
+	bh.b_size = 1 << (inode->i_blkbits + 5);
 	bmap_lock(inode, create);
-	ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, 32);
+	ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp);
 	bmap_unlock(inode, create);
 	*extlen = bh.b_size >> inode->i_blkbits;
 	*dblock = bh.b_blocknr;
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index 0fd379b..ac2fd04 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -15,7 +15,7 @@
 struct page;
 
 int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
-int gfs2_block_map(struct inode *inode, u64 lblock, int create, struct buffer_head *bh, unsigned int maxlen);
+int gfs2_block_map(struct inode *inode, u64 lblock, int create, struct buffer_head *bh);
 int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
 
 int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 459498c..e24af28b1 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -184,7 +184,7 @@
 	while (copied < size) {
 		unsigned int amount;
 		struct buffer_head *bh;
-		int new;
+		int new = 0;
 
 		amount = size - copied;
 		if (amount > sdp->sd_sb.sb_bsize - o)
@@ -212,8 +212,6 @@
 		gfs2_trans_add_bh(ip->i_gl, bh, 1);
 		memcpy(bh->b_data + o, buf, amount);
 		brelse(bh);
-		if (error)
-			goto fail;
 
 		buf += amount;
 		copied += amount;
@@ -317,8 +315,7 @@
 			if (!ra)
 				extlen = 1;
 			bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
-		}
-		if (!bh) {
+		} else {
 			error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, &bh);
 			if (error)
 				goto fail;
@@ -332,7 +329,6 @@
 		extlen--;
 		memcpy(buf, bh->b_data + o, amount);
 		brelse(bh);
-		bh = NULL;
 		buf += amount;
 		copied += amount;
 		lblock++;
@@ -815,7 +811,7 @@
 	leaf = (struct gfs2_leaf *)bh->b_data;
 	leaf->lf_depth = cpu_to_be16(depth);
 	leaf->lf_entries = 0;
-	leaf->lf_dirent_format = cpu_to_be16(GFS2_FORMAT_DE);
+	leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
 	leaf->lf_next = 0;
 	memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved));
 	dent = (struct gfs2_dirent *)(leaf+1);
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 1f94dd3..cdd1694 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -45,7 +45,7 @@
 	strncpy(buf, table_name, 256);
 	buf[255] = '\0';
 
-	p = strstr(buf, ":");
+	p = strchr(buf, ':');
 	if (!p) {
 		log_info("invalid table_name \"%s\"", table_name);
 		kfree(ls);
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 554fe5b..0cace3d 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -312,10 +312,12 @@
 
 static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
 {
+	struct inode *inode = sdp->sd_jdesc->jd_inode;
 	int error;
-	struct buffer_head bh_map;
+	struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
 
-	error = gfs2_block_map(sdp->sd_jdesc->jd_inode, lbn, 0, &bh_map, 1);
+	bh_map.b_size = 1 << inode->i_blkbits;
+	error = gfs2_block_map(inode, lbn, 0, &bh_map);
 	if (error || !bh_map.b_blocknr)
 		printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, bh_map.b_blocknr, lbn);
 	gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr);
@@ -569,16 +571,15 @@
 	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle)
 		log_write_header(sdp, 0, PULL);
 	lops_after_commit(sdp, ai);
+
+	gfs2_log_lock(sdp);
 	sdp->sd_log_head = sdp->sd_log_flush_head;
-
 	sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
-
 	sdp->sd_log_blks_reserved = 0;
 	sdp->sd_log_commited_buf = 0;
 	sdp->sd_log_num_hdrs = 0;
 	sdp->sd_log_commited_revoke = 0;
 
-	gfs2_log_lock(sdp);
 	if (!list_empty(&ai->ai_ail1_list)) {
 		list_add(&ai->ai_list, &sdp->sd_ail1_list);
 		ai = NULL;
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 881e337..ab6d111 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -492,7 +492,7 @@
 	ptr = kaddr + bh_offset(bh);
 	if (*ptr == cpu_to_be32(GFS2_MAGIC))
 		rv = 1;
-	kunmap_atomic(page, KM_USER0);
+	kunmap_atomic(kaddr, KM_USER0);
 
 	return rv;
 }
@@ -626,7 +626,7 @@
 				memcpy(bh->b_data,
 				       kaddr + bh_offset(bd2->bd_bh),
 				       sdp->sd_sb.sb_bsize);
-				kunmap_atomic(page, KM_USER0);
+				kunmap_atomic(kaddr, KM_USER0);
 				*(__be32 *)bh->b_data = 0;
 			} else {
 				bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 4fb743f..8d5963c 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -65,7 +65,7 @@
 int gfs2_get_block(struct inode *inode, sector_t lblock,
 	           struct buffer_head *bh_result, int create)
 {
-	return gfs2_block_map(inode, lblock, create, bh_result, 32);
+	return gfs2_block_map(inode, lblock, create, bh_result);
 }
 
 /**
@@ -83,7 +83,7 @@
 {
 	int error;
 
-	error = gfs2_block_map(inode, lblock, 0, bh_result, 1);
+	error = gfs2_block_map(inode, lblock, 0, bh_result);
 	if (error)
 		return error;
 	if (bh_result->b_blocknr == 0)
@@ -94,7 +94,7 @@
 static int gfs2_get_block_direct(struct inode *inode, sector_t lblock,
 				 struct buffer_head *bh_result, int create)
 {
-	return gfs2_block_map(inode, lblock, 0, bh_result, 32);
+	return gfs2_block_map(inode, lblock, 0, bh_result);
 }
 
 /**
@@ -162,7 +162,7 @@
 
 	kaddr = kmap_atomic(page, KM_USER0);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
-	kunmap_atomic(page, KM_USER0);
+	kunmap_atomic(kaddr, KM_USER0);
 
 	SetPageUptodate(page);
 
@@ -195,7 +195,7 @@
 	memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode),
 	       ip->i_di.di_size);
 	memset(kaddr + ip->i_di.di_size, 0, PAGE_CACHE_SIZE - ip->i_di.di_size);
-	kunmap_atomic(page, KM_USER0);
+	kunmap_atomic(kaddr, KM_USER0);
 
 	brelse(dibh);
 
@@ -370,19 +370,22 @@
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + from;
 	loff_t end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 	struct gfs2_alloc *al;
+	unsigned int write_len = to - from;
+
 
 	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|GL_AOP, &ip->i_gh);
 	error = gfs2_glock_nq_m_atime(1, &ip->i_gh);
 	if (error)
 		goto out_uninit;
 
-	gfs2_write_calc_reserv(ip, to - from, &data_blocks, &ind_blocks);
+	gfs2_write_calc_reserv(ip, write_len, &data_blocks, &ind_blocks);
 
-	error = gfs2_write_alloc_required(ip, pos, from - to, &alloc_required);
+	error = gfs2_write_alloc_required(ip, pos, write_len, &alloc_required);
 	if (error)
 		goto out_unlock;
 
 
+	ip->i_alloc.al_requested = 0;
 	if (alloc_required) {
 		al = gfs2_alloc_get(ip);
 
@@ -482,7 +485,7 @@
 		kaddr = kmap_atomic(page, KM_USER0);
 		memcpy(dibh->b_data + sizeof(struct gfs2_dinode) + from,
 		       kaddr + from, to - from);
-		kunmap_atomic(page, KM_USER0);
+		kunmap_atomic(kaddr, KM_USER0);
 
 		SetPageUptodate(page);
 
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 178b339..882873a 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -794,8 +794,8 @@
 		fs_err(sdp, "can't get root dentry\n");
 		error = -ENOMEM;
 		iput(inode);
-	}
-	new->s_root->d_op = &gfs2_dops;
+	} else
+		new->s_root->d_op = &gfs2_dops;
 
 	return error;
 }
@@ -854,7 +854,6 @@
 	int error = 0;
 	struct super_block *sb = NULL, *new;
 	struct gfs2_sbd *sdp;
-	char *gfs2mnt = NULL;
 
 	sb = get_gfs2_sb(dev_name);
 	if (!sb) {
@@ -892,8 +891,6 @@
 	atomic_inc(&sdp->sd_gfs2mnt->mnt_count);
 	return simple_set_mnt(mnt, new);
 error:
-	if (gfs2mnt)
-		kfree(gfs2mnt);
 	return error;
 }
 
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c69b94a..a3deae7 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -251,7 +251,7 @@
 	unsigned int block, offset;
 	struct buffer_head *bh;
 	int error;
-	struct buffer_head bh_map;
+	struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
 
 	mutex_lock(&sdp->sd_quota_mutex);
 
@@ -263,7 +263,8 @@
 	block = qd->qd_slot / sdp->sd_qc_per_block;
 	offset = qd->qd_slot % sdp->sd_qc_per_block;;
 
-	error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map, 1);
+	bh_map.b_size = 1 << ip->i_inode.i_blkbits;
+	error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map);
 	if (error)
 		goto fail;
 	error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 0a8a4b8..62cd223 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -372,11 +372,12 @@
 	u32 hash;
 	struct buffer_head *bh;
 	int error;
-	struct buffer_head bh_map;
+	struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
 
 	lblock = head->lh_blkno;
 	gfs2_replay_incr_blk(sdp, &lblock);
-	error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map, 1);
+	bh_map.b_size = 1 << ip->i_inode.i_blkbits;
+	error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map);
 	if (error)
 		return error;
 	if (!bh_map.b_blocknr) {
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 9eedfd1..b01e0cf 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -32,7 +32,7 @@
 struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
 static inline void gfs2_alloc_put(struct gfs2_inode *ip)
 {
-	return; /* Se we can see where ip->i_alloc is used */
+	return; /* So we can see where ip->i_alloc is used */
 }
 
 int gfs2_inplace_reserve_i(struct gfs2_inode *ip,
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index bcf6ee3..7faef85 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -60,14 +60,14 @@
 	if (hpfs_sb(i->i_sb)->sb_eas) {
 		if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) {
 			if (ea_size == 2) {
-				i->i_uid = le16_to_cpu(*(u16*)ea);
+				i->i_uid = le16_to_cpu(*(__le16*)ea);
 				hpfs_inode->i_ea_uid = 1;
 			}
 			kfree(ea);
 		}
 		if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) {
 			if (ea_size == 2) {
-				i->i_gid = le16_to_cpu(*(u16*)ea);
+				i->i_gid = le16_to_cpu(*(__le16*)ea);
 				hpfs_inode->i_ea_gid = 1;
 			}
 			kfree(ea);
@@ -87,7 +87,7 @@
 			int rdev = 0;
 			umode_t mode = hpfs_sb(sb)->sb_mode;
 			if (ea_size == 2) {
-				mode = le16_to_cpu(*(u16*)ea);
+				mode = le16_to_cpu(*(__le16*)ea);
 				hpfs_inode->i_ea_mode = 1;
 			}
 			kfree(ea);
@@ -95,7 +95,7 @@
 			if (S_ISBLK(mode) || S_ISCHR(mode)) {
 				if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) {
 					if (ea_size == 4)
-						rdev = le32_to_cpu(*(u32*)ea);
+						rdev = le32_to_cpu(*(__le32*)ea);
 					kfree(ea);
 				}
 			}
@@ -148,7 +148,7 @@
 		   we'd better not overwrite them
 		hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino);
 	} else*/ if (hpfs_sb(i->i_sb)->sb_eas >= 2) {
-		u32 ea;
+		__le32 ea;
 		if ((i->i_uid != hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) {
 			ea = cpu_to_le32(i->i_uid);
 			hpfs_set_ea(i, fnode, "UID", (char*)&ea, 2);
@@ -165,6 +165,7 @@
 			  && i->i_mode != ((hpfs_sb(i->i_sb)->sb_mode & ~(S_ISDIR(i->i_mode) ? 0222 : 0333))
 			  | (S_ISDIR(i->i_mode) ? S_IFDIR : S_IFREG))) || hpfs_inode->i_ea_mode) {
 				ea = cpu_to_le32(i->i_mode);
+				/* sick, but legal */
 				hpfs_set_ea(i, fnode, "MODE", (char *)&ea, 2);
 				hpfs_inode->i_ea_mode = 1;
 			}
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index dcb6d2e..642675f 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -572,7 +572,7 @@
 };
 
 static int hppfs_filldir(void *d, const char *name, int size,
-			 loff_t offset, ino_t inode, unsigned int type)
+			 loff_t offset, u64 inode, unsigned int type)
 {
 	struct hppfs_dirent *dirent = d;
 
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 5e03b2f..4ee3f00 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -293,7 +293,7 @@
 		if (h_vm_pgoff >= h_pgoff)
 			v_offset = 0;
 
-		unmap_hugepage_range(vma,
+		__unmap_hugepage_range(vma,
 				vma->vm_start + v_offset, vma->vm_end);
 	}
 }
diff --git a/fs/inode.c b/fs/inode.c
index bf6bec4..26cdb11 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -162,7 +162,7 @@
 				bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
 			mapping->backing_dev_info = bdi;
 		}
-		inode->i_private = 0;
+		inode->i_private = NULL;
 		inode->i_mapping = mapping;
 	}
 	return inode;
@@ -1306,6 +1306,42 @@
 	wake_up_bit(&inode->i_state, __I_LOCK);
 }
 
+/*
+ * We rarely want to lock two inodes that do not have a parent/child
+ * relationship (such as directory, child inode) simultaneously. The
+ * vast majority of file systems should be able to get along fine
+ * without this. Do not use these functions except as a last resort.
+ */
+void inode_double_lock(struct inode *inode1, struct inode *inode2)
+{
+	if (inode1 == NULL || inode2 == NULL || inode1 == inode2) {
+		if (inode1)
+			mutex_lock(&inode1->i_mutex);
+		else if (inode2)
+			mutex_lock(&inode2->i_mutex);
+		return;
+	}
+
+	if (inode1 < inode2) {
+		mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
+		mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
+	} else {
+		mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT);
+		mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD);
+	}
+}
+EXPORT_SYMBOL(inode_double_lock);
+
+void inode_double_unlock(struct inode *inode1, struct inode *inode2)
+{
+	if (inode1)
+		mutex_unlock(&inode1->i_mutex);
+
+	if (inode2 && inode2 != inode1)
+		mutex_unlock(&inode2->i_mutex);
+}
+EXPORT_SYMBOL(inode_double_unlock);
+
 static __initdata unsigned long ihash_entries;
 static int __init set_ihash_entries(char *str)
 {
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 6dc6721..89e8da1 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -150,11 +150,6 @@
 	unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
 	unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
 
-	if (!ioprio_valid(aprio))
-		return bprio;
-	if (!ioprio_valid(bprio))
-		return aprio;
-
 	if (aclass == IOPRIO_CLASS_NONE)
 		aclass = IOPRIO_CLASS_BE;
 	if (bclass == IOPRIO_CLASS_NONE)
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index 81a90e1..fb8fe7a 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -14,9 +14,9 @@
  * Convert Unicode 16 to UTF-8 or ASCII.
  */
 static int
-uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls)
+uni16_to_x8(unsigned char *ascii, __be16 *uni, int len, struct nls_table *nls)
 {
-	wchar_t *ip, ch;
+	__be16 *ip, ch;
 	unsigned char *op;
 
 	ip = uni;
@@ -24,8 +24,8 @@
 
 	while ((ch = get_unaligned(ip)) && len) {
 		int llen;
-		ch = be16_to_cpu(ch);
-		if ((llen = nls->uni2char(ch, op, NLS_MAX_CHARSET_SIZE)) > 0)
+		llen = nls->uni2char(be16_to_cpu(ch), op, NLS_MAX_CHARSET_SIZE);
+		if (llen > 0)
 			op += llen;
 		else
 			*op++ = '?';
@@ -82,7 +82,7 @@
 		len = wcsntombs_be(outname, de->name,
 				   de->name_len[0] >> 1, PAGE_SIZE);
 	} else {
-		len = uni16_to_x8(outname, (u16 *) de->name,
+		len = uni16_to_x8(outname, (__be16 *) de->name,
 				  de->name_len[0] >> 1, nls);
 	}
 	if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) {
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index c518dd8..b85c686 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -725,6 +725,7 @@
 			__FUNCTION__);
 		kfree(journal);
 		journal = NULL;
+		goto out;
 	}
 	journal->j_dev = bdev;
 	journal->j_fs_dev = fs_dev;
@@ -735,7 +736,7 @@
 	J_ASSERT(bh != NULL);
 	journal->j_sb_buffer = bh;
 	journal->j_superblock = (journal_superblock_t *)bh->b_data;
-
+out:
 	return journal;
 }
 
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index e1b3c8a..d5c6304 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1314,13 +1314,14 @@
 	int old_handle_count, err;
 	pid_t pid;
 
-	J_ASSERT(transaction->t_updates > 0);
 	J_ASSERT(journal_current_handle() == handle);
 
 	if (is_handle_aborted(handle))
 		err = -EIO;
-	else
+	else {
+		J_ASSERT(transaction->t_updates > 0);
 		err = 0;
+	}
 
 	if (--handle->h_ref > 0) {
 		jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
diff --git a/fs/jbd2/Makefile b/fs/jbd2/Makefile
new file mode 100644
index 0000000..802a341
--- /dev/null
+++ b/fs/jbd2/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux journaling routines.
+#
+
+obj-$(CONFIG_JBD2) += jbd2.o
+
+jbd2-objs := transaction.o commit.o recovery.o checkpoint.o revoke.o journal.o
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
new file mode 100644
index 0000000..68039fa
--- /dev/null
+++ b/fs/jbd2/checkpoint.c
@@ -0,0 +1,697 @@
+/*
+ * linux/fs/checkpoint.c
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
+ *
+ * Copyright 1999 Red Hat Software --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Checkpoint routines for the generic filesystem journaling code.
+ * Part of the ext2fs journaling system.
+ *
+ * Checkpointing is the process of ensuring that a section of the log is
+ * committed fully to disk, so that that portion of the log can be
+ * reused.
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+/*
+ * Unlink a buffer from a transaction checkpoint list.
+ *
+ * Called with j_list_lock held.
+ */
+static inline void __buffer_unlink_first(struct journal_head *jh)
+{
+	transaction_t *transaction = jh->b_cp_transaction;
+
+	jh->b_cpnext->b_cpprev = jh->b_cpprev;
+	jh->b_cpprev->b_cpnext = jh->b_cpnext;
+	if (transaction->t_checkpoint_list == jh) {
+		transaction->t_checkpoint_list = jh->b_cpnext;
+		if (transaction->t_checkpoint_list == jh)
+			transaction->t_checkpoint_list = NULL;
+	}
+}
+
+/*
+ * Unlink a buffer from a transaction checkpoint(io) list.
+ *
+ * Called with j_list_lock held.
+ */
+static inline void __buffer_unlink(struct journal_head *jh)
+{
+	transaction_t *transaction = jh->b_cp_transaction;
+
+	__buffer_unlink_first(jh);
+	if (transaction->t_checkpoint_io_list == jh) {
+		transaction->t_checkpoint_io_list = jh->b_cpnext;
+		if (transaction->t_checkpoint_io_list == jh)
+			transaction->t_checkpoint_io_list = NULL;
+	}
+}
+
+/*
+ * Move a buffer from the checkpoint list to the checkpoint io list
+ *
+ * Called with j_list_lock held
+ */
+static inline void __buffer_relink_io(struct journal_head *jh)
+{
+	transaction_t *transaction = jh->b_cp_transaction;
+
+	__buffer_unlink_first(jh);
+
+	if (!transaction->t_checkpoint_io_list) {
+		jh->b_cpnext = jh->b_cpprev = jh;
+	} else {
+		jh->b_cpnext = transaction->t_checkpoint_io_list;
+		jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
+		jh->b_cpprev->b_cpnext = jh;
+		jh->b_cpnext->b_cpprev = jh;
+	}
+	transaction->t_checkpoint_io_list = jh;
+}
+
+/*
+ * Try to release a checkpointed buffer from its transaction.
+ * Returns 1 if we released it and 2 if we also released the
+ * whole transaction.
+ *
+ * Requires j_list_lock
+ * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
+ */
+static int __try_to_free_cp_buf(struct journal_head *jh)
+{
+	int ret = 0;
+	struct buffer_head *bh = jh2bh(jh);
+
+	if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) {
+		JBUFFER_TRACE(jh, "remove from checkpoint list");
+		ret = __jbd2_journal_remove_checkpoint(jh) + 1;
+		jbd_unlock_bh_state(bh);
+		jbd2_journal_remove_journal_head(bh);
+		BUFFER_TRACE(bh, "release");
+		__brelse(bh);
+	} else {
+		jbd_unlock_bh_state(bh);
+	}
+	return ret;
+}
+
+/*
+ * __jbd2_log_wait_for_space: wait until there is space in the journal.
+ *
+ * Called under j-state_lock *only*.  It will be unlocked if we have to wait
+ * for a checkpoint to free up some space in the log.
+ */
+void __jbd2_log_wait_for_space(journal_t *journal)
+{
+	int nblocks;
+	assert_spin_locked(&journal->j_state_lock);
+
+	nblocks = jbd_space_needed(journal);
+	while (__jbd2_log_space_left(journal) < nblocks) {
+		if (journal->j_flags & JBD2_ABORT)
+			return;
+		spin_unlock(&journal->j_state_lock);
+		mutex_lock(&journal->j_checkpoint_mutex);
+
+		/*
+		 * Test again, another process may have checkpointed while we
+		 * were waiting for the checkpoint lock
+		 */
+		spin_lock(&journal->j_state_lock);
+		nblocks = jbd_space_needed(journal);
+		if (__jbd2_log_space_left(journal) < nblocks) {
+			spin_unlock(&journal->j_state_lock);
+			jbd2_log_do_checkpoint(journal);
+			spin_lock(&journal->j_state_lock);
+		}
+		mutex_unlock(&journal->j_checkpoint_mutex);
+	}
+}
+
+/*
+ * We were unable to perform jbd_trylock_bh_state() inside j_list_lock.
+ * The caller must restart a list walk.  Wait for someone else to run
+ * jbd_unlock_bh_state().
+ */
+static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
+	__releases(journal->j_list_lock)
+{
+	get_bh(bh);
+	spin_unlock(&journal->j_list_lock);
+	jbd_lock_bh_state(bh);
+	jbd_unlock_bh_state(bh);
+	put_bh(bh);
+}
+
+/*
+ * Clean up transaction's list of buffers submitted for io.
+ * We wait for any pending IO to complete and remove any clean
+ * buffers. Note that we take the buffers in the opposite ordering
+ * from the one in which they were submitted for IO.
+ *
+ * Called with j_list_lock held.
+ */
+static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
+{
+	struct journal_head *jh;
+	struct buffer_head *bh;
+	tid_t this_tid;
+	int released = 0;
+
+	this_tid = transaction->t_tid;
+restart:
+	/* Did somebody clean up the transaction in the meanwhile? */
+	if (journal->j_checkpoint_transactions != transaction ||
+			transaction->t_tid != this_tid)
+		return;
+	while (!released && transaction->t_checkpoint_io_list) {
+		jh = transaction->t_checkpoint_io_list;
+		bh = jh2bh(jh);
+		if (!jbd_trylock_bh_state(bh)) {
+			jbd_sync_bh(journal, bh);
+			spin_lock(&journal->j_list_lock);
+			goto restart;
+		}
+		if (buffer_locked(bh)) {
+			atomic_inc(&bh->b_count);
+			spin_unlock(&journal->j_list_lock);
+			jbd_unlock_bh_state(bh);
+			wait_on_buffer(bh);
+			/* the journal_head may have gone by now */
+			BUFFER_TRACE(bh, "brelse");
+			__brelse(bh);
+			spin_lock(&journal->j_list_lock);
+			goto restart;
+		}
+		/*
+		 * Now in whatever state the buffer currently is, we know that
+		 * it has been written out and so we can drop it from the list
+		 */
+		released = __jbd2_journal_remove_checkpoint(jh);
+		jbd_unlock_bh_state(bh);
+		jbd2_journal_remove_journal_head(bh);
+		__brelse(bh);
+	}
+}
+
+#define NR_BATCH	64
+
+static void
+__flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
+{
+	int i;
+
+	ll_rw_block(SWRITE, *batch_count, bhs);
+	for (i = 0; i < *batch_count; i++) {
+		struct buffer_head *bh = bhs[i];
+		clear_buffer_jwrite(bh);
+		BUFFER_TRACE(bh, "brelse");
+		__brelse(bh);
+	}
+	*batch_count = 0;
+}
+
+/*
+ * Try to flush one buffer from the checkpoint list to disk.
+ *
+ * Return 1 if something happened which requires us to abort the current
+ * scan of the checkpoint list.
+ *
+ * Called with j_list_lock held and drops it if 1 is returned
+ * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
+ */
+static int __process_buffer(journal_t *journal, struct journal_head *jh,
+			struct buffer_head **bhs, int *batch_count)
+{
+	struct buffer_head *bh = jh2bh(jh);
+	int ret = 0;
+
+	if (buffer_locked(bh)) {
+		atomic_inc(&bh->b_count);
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		wait_on_buffer(bh);
+		/* the journal_head may have gone by now */
+		BUFFER_TRACE(bh, "brelse");
+		__brelse(bh);
+		ret = 1;
+	} else if (jh->b_transaction != NULL) {
+		transaction_t *t = jh->b_transaction;
+		tid_t tid = t->t_tid;
+
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		jbd2_log_start_commit(journal, tid);
+		jbd2_log_wait_commit(journal, tid);
+		ret = 1;
+	} else if (!buffer_dirty(bh)) {
+		J_ASSERT_JH(jh, !buffer_jbddirty(bh));
+		BUFFER_TRACE(bh, "remove from checkpoint");
+		__jbd2_journal_remove_checkpoint(jh);
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		jbd2_journal_remove_journal_head(bh);
+		__brelse(bh);
+		ret = 1;
+	} else {
+		/*
+		 * Important: we are about to write the buffer, and
+		 * possibly block, while still holding the journal lock.
+		 * We cannot afford to let the transaction logic start
+		 * messing around with this buffer before we write it to
+		 * disk, as that would break recoverability.
+		 */
+		BUFFER_TRACE(bh, "queue");
+		get_bh(bh);
+		J_ASSERT_BH(bh, !buffer_jwrite(bh));
+		set_buffer_jwrite(bh);
+		bhs[*batch_count] = bh;
+		__buffer_relink_io(jh);
+		jbd_unlock_bh_state(bh);
+		(*batch_count)++;
+		if (*batch_count == NR_BATCH) {
+			spin_unlock(&journal->j_list_lock);
+			__flush_batch(journal, bhs, batch_count);
+			ret = 1;
+		}
+	}
+	return ret;
+}
+
+/*
+ * Perform an actual checkpoint. We take the first transaction on the
+ * list of transactions to be checkpointed and send all its buffers
+ * to disk. We submit larger chunks of data at once.
+ *
+ * The journal should be locked before calling this function.
+ */
+int jbd2_log_do_checkpoint(journal_t *journal)
+{
+	transaction_t *transaction;
+	tid_t this_tid;
+	int result;
+
+	jbd_debug(1, "Start checkpoint\n");
+
+	/*
+	 * First thing: if there are any transactions in the log which
+	 * don't need checkpointing, just eliminate them from the
+	 * journal straight away.
+	 */
+	result = jbd2_cleanup_journal_tail(journal);
+	jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
+	if (result <= 0)
+		return result;
+
+	/*
+	 * OK, we need to start writing disk blocks.  Take one transaction
+	 * and write it.
+	 */
+	spin_lock(&journal->j_list_lock);
+	if (!journal->j_checkpoint_transactions)
+		goto out;
+	transaction = journal->j_checkpoint_transactions;
+	this_tid = transaction->t_tid;
+restart:
+	/*
+	 * If someone cleaned up this transaction while we slept, we're
+	 * done (maybe it's a new transaction, but it fell at the same
+	 * address).
+	 */
+	if (journal->j_checkpoint_transactions == transaction &&
+			transaction->t_tid == this_tid) {
+		int batch_count = 0;
+		struct buffer_head *bhs[NR_BATCH];
+		struct journal_head *jh;
+		int retry = 0;
+
+		while (!retry && transaction->t_checkpoint_list) {
+			struct buffer_head *bh;
+
+			jh = transaction->t_checkpoint_list;
+			bh = jh2bh(jh);
+			if (!jbd_trylock_bh_state(bh)) {
+				jbd_sync_bh(journal, bh);
+				retry = 1;
+				break;
+			}
+			retry = __process_buffer(journal, jh, bhs,&batch_count);
+			if (!retry && lock_need_resched(&journal->j_list_lock)){
+				spin_unlock(&journal->j_list_lock);
+				retry = 1;
+				break;
+			}
+		}
+
+		if (batch_count) {
+			if (!retry) {
+				spin_unlock(&journal->j_list_lock);
+				retry = 1;
+			}
+			__flush_batch(journal, bhs, &batch_count);
+		}
+
+		if (retry) {
+			spin_lock(&journal->j_list_lock);
+			goto restart;
+		}
+		/*
+		 * Now we have cleaned up the first transaction's checkpoint
+		 * list. Let's clean up the second one
+		 */
+		__wait_cp_io(journal, transaction);
+	}
+out:
+	spin_unlock(&journal->j_list_lock);
+	result = jbd2_cleanup_journal_tail(journal);
+	if (result < 0)
+		return result;
+	return 0;
+}
+
+/*
+ * Check the list of checkpoint transactions for the journal to see if
+ * we have already got rid of any since the last update of the log tail
+ * in the journal superblock.  If so, we can instantly roll the
+ * superblock forward to remove those transactions from the log.
+ *
+ * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
+ *
+ * Called with the journal lock held.
+ *
+ * This is the only part of the journaling code which really needs to be
+ * aware of transaction aborts.  Checkpointing involves writing to the
+ * main filesystem area rather than to the journal, so it can proceed
+ * even in abort state, but we must not update the journal superblock if
+ * we have an abort error outstanding.
+ */
+
+int jbd2_cleanup_journal_tail(journal_t *journal)
+{
+	transaction_t * transaction;
+	tid_t		first_tid;
+	unsigned long	blocknr, freed;
+
+	/* OK, work out the oldest transaction remaining in the log, and
+	 * the log block it starts at.
+	 *
+	 * If the log is now empty, we need to work out which is the
+	 * next transaction ID we will write, and where it will
+	 * start. */
+
+	spin_lock(&journal->j_state_lock);
+	spin_lock(&journal->j_list_lock);
+	transaction = journal->j_checkpoint_transactions;
+	if (transaction) {
+		first_tid = transaction->t_tid;
+		blocknr = transaction->t_log_start;
+	} else if ((transaction = journal->j_committing_transaction) != NULL) {
+		first_tid = transaction->t_tid;
+		blocknr = transaction->t_log_start;
+	} else if ((transaction = journal->j_running_transaction) != NULL) {
+		first_tid = transaction->t_tid;
+		blocknr = journal->j_head;
+	} else {
+		first_tid = journal->j_transaction_sequence;
+		blocknr = journal->j_head;
+	}
+	spin_unlock(&journal->j_list_lock);
+	J_ASSERT(blocknr != 0);
+
+	/* If the oldest pinned transaction is at the tail of the log
+           already then there's not much we can do right now. */
+	if (journal->j_tail_sequence == first_tid) {
+		spin_unlock(&journal->j_state_lock);
+		return 1;
+	}
+
+	/* OK, update the superblock to recover the freed space.
+	 * Physical blocks come first: have we wrapped beyond the end of
+	 * the log?  */
+	freed = blocknr - journal->j_tail;
+	if (blocknr < journal->j_tail)
+		freed = freed + journal->j_last - journal->j_first;
+
+	jbd_debug(1,
+		  "Cleaning journal tail from %d to %d (offset %lu), "
+		  "freeing %lu\n",
+		  journal->j_tail_sequence, first_tid, blocknr, freed);
+
+	journal->j_free += freed;
+	journal->j_tail_sequence = first_tid;
+	journal->j_tail = blocknr;
+	spin_unlock(&journal->j_state_lock);
+	if (!(journal->j_flags & JBD2_ABORT))
+		jbd2_journal_update_superblock(journal, 1);
+	return 0;
+}
+
+
+/* Checkpoint list management */
+
+/*
+ * journal_clean_one_cp_list
+ *
+ * Find all the written-back checkpoint buffers in the given list and release them.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ * Returns number of bufers reaped (for debug)
+ */
+
+static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
+{
+	struct journal_head *last_jh;
+	struct journal_head *next_jh = jh;
+	int ret, freed = 0;
+
+	*released = 0;
+	if (!jh)
+		return 0;
+
+	last_jh = jh->b_cpprev;
+	do {
+		jh = next_jh;
+		next_jh = jh->b_cpnext;
+		/* Use trylock because of the ranking */
+		if (jbd_trylock_bh_state(jh2bh(jh))) {
+			ret = __try_to_free_cp_buf(jh);
+			if (ret) {
+				freed++;
+				if (ret == 2) {
+					*released = 1;
+					return freed;
+				}
+			}
+		}
+		/*
+		 * This function only frees up some memory
+		 * if possible so we dont have an obligation
+		 * to finish processing. Bail out if preemption
+		 * requested:
+		 */
+		if (need_resched())
+			return freed;
+	} while (jh != last_jh);
+
+	return freed;
+}
+
+/*
+ * journal_clean_checkpoint_list
+ *
+ * Find all the written-back checkpoint buffers in the journal and release them.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ * Returns number of buffers reaped (for debug)
+ */
+
+int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
+{
+	transaction_t *transaction, *last_transaction, *next_transaction;
+	int ret = 0;
+	int released;
+
+	transaction = journal->j_checkpoint_transactions;
+	if (!transaction)
+		goto out;
+
+	last_transaction = transaction->t_cpprev;
+	next_transaction = transaction;
+	do {
+		transaction = next_transaction;
+		next_transaction = transaction->t_cpnext;
+		ret += journal_clean_one_cp_list(transaction->
+				t_checkpoint_list, &released);
+		/*
+		 * This function only frees up some memory if possible so we
+		 * dont have an obligation to finish processing. Bail out if
+		 * preemption requested:
+		 */
+		if (need_resched())
+			goto out;
+		if (released)
+			continue;
+		/*
+		 * It is essential that we are as careful as in the case of
+		 * t_checkpoint_list with removing the buffer from the list as
+		 * we can possibly see not yet submitted buffers on io_list
+		 */
+		ret += journal_clean_one_cp_list(transaction->
+				t_checkpoint_io_list, &released);
+		if (need_resched())
+			goto out;
+	} while (transaction != last_transaction);
+out:
+	return ret;
+}
+
+/*
+ * journal_remove_checkpoint: called after a buffer has been committed
+ * to disk (either by being write-back flushed to disk, or being
+ * committed to the log).
+ *
+ * We cannot safely clean a transaction out of the log until all of the
+ * buffer updates committed in that transaction have safely been stored
+ * elsewhere on disk.  To achieve this, all of the buffers in a
+ * transaction need to be maintained on the transaction's checkpoint
+ * lists until they have been rewritten, at which point this function is
+ * called to remove the buffer from the existing transaction's
+ * checkpoint lists.
+ *
+ * The function returns 1 if it frees the transaction, 0 otherwise.
+ *
+ * This function is called with the journal locked.
+ * This function is called with j_list_lock held.
+ * This function is called with jbd_lock_bh_state(jh2bh(jh))
+ */
+
+int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
+{
+	transaction_t *transaction;
+	journal_t *journal;
+	int ret = 0;
+
+	JBUFFER_TRACE(jh, "entry");
+
+	if ((transaction = jh->b_cp_transaction) == NULL) {
+		JBUFFER_TRACE(jh, "not on transaction");
+		goto out;
+	}
+	journal = transaction->t_journal;
+
+	__buffer_unlink(jh);
+	jh->b_cp_transaction = NULL;
+
+	if (transaction->t_checkpoint_list != NULL ||
+	    transaction->t_checkpoint_io_list != NULL)
+		goto out;
+	JBUFFER_TRACE(jh, "transaction has no more buffers");
+
+	/*
+	 * There is one special case to worry about: if we have just pulled the
+	 * buffer off a committing transaction's forget list, then even if the
+	 * checkpoint list is empty, the transaction obviously cannot be
+	 * dropped!
+	 *
+	 * The locking here around j_committing_transaction is a bit sleazy.
+	 * See the comment at the end of jbd2_journal_commit_transaction().
+	 */
+	if (transaction == journal->j_committing_transaction) {
+		JBUFFER_TRACE(jh, "belongs to committing transaction");
+		goto out;
+	}
+
+	/* OK, that was the last buffer for the transaction: we can now
+	   safely remove this transaction from the log */
+
+	__jbd2_journal_drop_transaction(journal, transaction);
+
+	/* Just in case anybody was waiting for more transactions to be
+           checkpointed... */
+	wake_up(&journal->j_wait_logspace);
+	ret = 1;
+out:
+	JBUFFER_TRACE(jh, "exit");
+	return ret;
+}
+
+/*
+ * journal_insert_checkpoint: put a committed buffer onto a checkpoint
+ * list so that we know when it is safe to clean the transaction out of
+ * the log.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ */
+void __jbd2_journal_insert_checkpoint(struct journal_head *jh,
+			       transaction_t *transaction)
+{
+	JBUFFER_TRACE(jh, "entry");
+	J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh)));
+	J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
+
+	jh->b_cp_transaction = transaction;
+
+	if (!transaction->t_checkpoint_list) {
+		jh->b_cpnext = jh->b_cpprev = jh;
+	} else {
+		jh->b_cpnext = transaction->t_checkpoint_list;
+		jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
+		jh->b_cpprev->b_cpnext = jh;
+		jh->b_cpnext->b_cpprev = jh;
+	}
+	transaction->t_checkpoint_list = jh;
+}
+
+/*
+ * We've finished with this transaction structure: adios...
+ *
+ * The transaction must have no links except for the checkpoint by this
+ * point.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ */
+
+void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transaction)
+{
+	assert_spin_locked(&journal->j_list_lock);
+	if (transaction->t_cpnext) {
+		transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
+		transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
+		if (journal->j_checkpoint_transactions == transaction)
+			journal->j_checkpoint_transactions =
+				transaction->t_cpnext;
+		if (journal->j_checkpoint_transactions == transaction)
+			journal->j_checkpoint_transactions = NULL;
+	}
+
+	J_ASSERT(transaction->t_state == T_FINISHED);
+	J_ASSERT(transaction->t_buffers == NULL);
+	J_ASSERT(transaction->t_sync_datalist == NULL);
+	J_ASSERT(transaction->t_forget == NULL);
+	J_ASSERT(transaction->t_iobuf_list == NULL);
+	J_ASSERT(transaction->t_shadow_list == NULL);
+	J_ASSERT(transaction->t_log_list == NULL);
+	J_ASSERT(transaction->t_checkpoint_list == NULL);
+	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
+	J_ASSERT(transaction->t_updates == 0);
+	J_ASSERT(journal->j_committing_transaction != transaction);
+	J_ASSERT(journal->j_running_transaction != transaction);
+
+	jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
+	kfree(transaction);
+}
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
new file mode 100644
index 0000000..70b2ae1
--- /dev/null
+++ b/fs/jbd2/commit.c
@@ -0,0 +1,920 @@
+/*
+ * linux/fs/jbd2/commit.c
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
+ *
+ * Copyright 1998 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Journal commit routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+
+/*
+ * Default IO end handler for temporary BJ_IO buffer_heads.
+ */
+static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
+{
+	BUFFER_TRACE(bh, "");
+	if (uptodate)
+		set_buffer_uptodate(bh);
+	else
+		clear_buffer_uptodate(bh);
+	unlock_buffer(bh);
+}
+
+/*
+ * When an ext3-ordered file is truncated, it is possible that many pages are
+ * not sucessfully freed, because they are attached to a committing transaction.
+ * After the transaction commits, these pages are left on the LRU, with no
+ * ->mapping, and with attached buffers.  These pages are trivially reclaimable
+ * by the VM, but their apparent absence upsets the VM accounting, and it makes
+ * the numbers in /proc/meminfo look odd.
+ *
+ * So here, we have a buffer which has just come off the forget list.  Look to
+ * see if we can strip all buffers from the backing page.
+ *
+ * Called under lock_journal(), and possibly under journal_datalist_lock.  The
+ * caller provided us with a ref against the buffer, and we drop that here.
+ */
+static void release_buffer_page(struct buffer_head *bh)
+{
+	struct page *page;
+
+	if (buffer_dirty(bh))
+		goto nope;
+	if (atomic_read(&bh->b_count) != 1)
+		goto nope;
+	page = bh->b_page;
+	if (!page)
+		goto nope;
+	if (page->mapping)
+		goto nope;
+
+	/* OK, it's a truncated page */
+	if (TestSetPageLocked(page))
+		goto nope;
+
+	page_cache_get(page);
+	__brelse(bh);
+	try_to_free_buffers(page);
+	unlock_page(page);
+	page_cache_release(page);
+	return;
+
+nope:
+	__brelse(bh);
+}
+
+/*
+ * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is
+ * held.  For ranking reasons we must trylock.  If we lose, schedule away and
+ * return 0.  j_list_lock is dropped in this case.
+ */
+static int inverted_lock(journal_t *journal, struct buffer_head *bh)
+{
+	if (!jbd_trylock_bh_state(bh)) {
+		spin_unlock(&journal->j_list_lock);
+		schedule();
+		return 0;
+	}
+	return 1;
+}
+
+/* Done it all: now write the commit record.  We should have
+ * cleaned up our previous buffers by now, so if we are in abort
+ * mode we can now just skip the rest of the journal write
+ * entirely.
+ *
+ * Returns 1 if the journal needs to be aborted or 0 on success
+ */
+static int journal_write_commit_record(journal_t *journal,
+					transaction_t *commit_transaction)
+{
+	struct journal_head *descriptor;
+	struct buffer_head *bh;
+	int i, ret;
+	int barrier_done = 0;
+
+	if (is_journal_aborted(journal))
+		return 0;
+
+	descriptor = jbd2_journal_get_descriptor_buffer(journal);
+	if (!descriptor)
+		return 1;
+
+	bh = jh2bh(descriptor);
+
+	/* AKPM: buglet - add `i' to tmp! */
+	for (i = 0; i < bh->b_size; i += 512) {
+		journal_header_t *tmp = (journal_header_t*)bh->b_data;
+		tmp->h_magic = cpu_to_be32(JBD2_MAGIC_NUMBER);
+		tmp->h_blocktype = cpu_to_be32(JBD2_COMMIT_BLOCK);
+		tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
+	}
+
+	JBUFFER_TRACE(descriptor, "write commit block");
+	set_buffer_dirty(bh);
+	if (journal->j_flags & JBD2_BARRIER) {
+		set_buffer_ordered(bh);
+		barrier_done = 1;
+	}
+	ret = sync_dirty_buffer(bh);
+	/* is it possible for another commit to fail at roughly
+	 * the same time as this one?  If so, we don't want to
+	 * trust the barrier flag in the super, but instead want
+	 * to remember if we sent a barrier request
+	 */
+	if (ret == -EOPNOTSUPP && barrier_done) {
+		char b[BDEVNAME_SIZE];
+
+		printk(KERN_WARNING
+			"JBD: barrier-based sync failed on %s - "
+			"disabling barriers\n",
+			bdevname(journal->j_dev, b));
+		spin_lock(&journal->j_state_lock);
+		journal->j_flags &= ~JBD2_BARRIER;
+		spin_unlock(&journal->j_state_lock);
+
+		/* And try again, without the barrier */
+		clear_buffer_ordered(bh);
+		set_buffer_uptodate(bh);
+		set_buffer_dirty(bh);
+		ret = sync_dirty_buffer(bh);
+	}
+	put_bh(bh);		/* One for getblk() */
+	jbd2_journal_put_journal_head(descriptor);
+
+	return (ret == -EIO);
+}
+
+static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
+{
+	int i;
+
+	for (i = 0; i < bufs; i++) {
+		wbuf[i]->b_end_io = end_buffer_write_sync;
+		/* We use-up our safety reference in submit_bh() */
+		submit_bh(WRITE, wbuf[i]);
+	}
+}
+
+/*
+ *  Submit all the data buffers to disk
+ */
+static void journal_submit_data_buffers(journal_t *journal,
+				transaction_t *commit_transaction)
+{
+	struct journal_head *jh;
+	struct buffer_head *bh;
+	int locked;
+	int bufs = 0;
+	struct buffer_head **wbuf = journal->j_wbuf;
+
+	/*
+	 * Whenever we unlock the journal and sleep, things can get added
+	 * onto ->t_sync_datalist, so we have to keep looping back to
+	 * write_out_data until we *know* that the list is empty.
+	 *
+	 * Cleanup any flushed data buffers from the data list.  Even in
+	 * abort mode, we want to flush this out as soon as possible.
+	 */
+write_out_data:
+	cond_resched();
+	spin_lock(&journal->j_list_lock);
+
+	while (commit_transaction->t_sync_datalist) {
+		jh = commit_transaction->t_sync_datalist;
+		bh = jh2bh(jh);
+		locked = 0;
+
+		/* Get reference just to make sure buffer does not disappear
+		 * when we are forced to drop various locks */
+		get_bh(bh);
+		/* If the buffer is dirty, we need to submit IO and hence
+		 * we need the buffer lock. We try to lock the buffer without
+		 * blocking. If we fail, we need to drop j_list_lock and do
+		 * blocking lock_buffer().
+		 */
+		if (buffer_dirty(bh)) {
+			if (test_set_buffer_locked(bh)) {
+				BUFFER_TRACE(bh, "needs blocking lock");
+				spin_unlock(&journal->j_list_lock);
+				/* Write out all data to prevent deadlocks */
+				journal_do_submit_data(wbuf, bufs);
+				bufs = 0;
+				lock_buffer(bh);
+				spin_lock(&journal->j_list_lock);
+			}
+			locked = 1;
+		}
+		/* We have to get bh_state lock. Again out of order, sigh. */
+		if (!inverted_lock(journal, bh)) {
+			jbd_lock_bh_state(bh);
+			spin_lock(&journal->j_list_lock);
+		}
+		/* Someone already cleaned up the buffer? */
+		if (!buffer_jbd(bh)
+			|| jh->b_transaction != commit_transaction
+			|| jh->b_jlist != BJ_SyncData) {
+			jbd_unlock_bh_state(bh);
+			if (locked)
+				unlock_buffer(bh);
+			BUFFER_TRACE(bh, "already cleaned up");
+			put_bh(bh);
+			continue;
+		}
+		if (locked && test_clear_buffer_dirty(bh)) {
+			BUFFER_TRACE(bh, "needs writeout, adding to array");
+			wbuf[bufs++] = bh;
+			__jbd2_journal_file_buffer(jh, commit_transaction,
+						BJ_Locked);
+			jbd_unlock_bh_state(bh);
+			if (bufs == journal->j_wbufsize) {
+				spin_unlock(&journal->j_list_lock);
+				journal_do_submit_data(wbuf, bufs);
+				bufs = 0;
+				goto write_out_data;
+			}
+		}
+		else {
+			BUFFER_TRACE(bh, "writeout complete: unfile");
+			__jbd2_journal_unfile_buffer(jh);
+			jbd_unlock_bh_state(bh);
+			if (locked)
+				unlock_buffer(bh);
+			jbd2_journal_remove_journal_head(bh);
+			/* Once for our safety reference, once for
+			 * jbd2_journal_remove_journal_head() */
+			put_bh(bh);
+			put_bh(bh);
+		}
+
+		if (lock_need_resched(&journal->j_list_lock)) {
+			spin_unlock(&journal->j_list_lock);
+			goto write_out_data;
+		}
+	}
+	spin_unlock(&journal->j_list_lock);
+	journal_do_submit_data(wbuf, bufs);
+}
+
+static inline void write_tag_block(int tag_bytes, journal_block_tag_t *tag,
+				   unsigned long long block)
+{
+	tag->t_blocknr = cpu_to_be32(block & (u32)~0);
+	if (tag_bytes > JBD_TAG_SIZE32)
+		tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1);
+}
+
+/*
+ * jbd2_journal_commit_transaction
+ *
+ * The primary function for committing a transaction to the log.  This
+ * function is called by the journal thread to begin a complete commit.
+ */
+void jbd2_journal_commit_transaction(journal_t *journal)
+{
+	transaction_t *commit_transaction;
+	struct journal_head *jh, *new_jh, *descriptor;
+	struct buffer_head **wbuf = journal->j_wbuf;
+	int bufs;
+	int flags;
+	int err;
+	unsigned long long blocknr;
+	char *tagp = NULL;
+	journal_header_t *header;
+	journal_block_tag_t *tag = NULL;
+	int space_left = 0;
+	int first_tag = 0;
+	int tag_flag;
+	int i;
+	int tag_bytes = journal_tag_bytes(journal);
+
+	/*
+	 * First job: lock down the current transaction and wait for
+	 * all outstanding updates to complete.
+	 */
+
+#ifdef COMMIT_STATS
+	spin_lock(&journal->j_list_lock);
+	summarise_journal_usage(journal);
+	spin_unlock(&journal->j_list_lock);
+#endif
+
+	/* Do we need to erase the effects of a prior jbd2_journal_flush? */
+	if (journal->j_flags & JBD2_FLUSHED) {
+		jbd_debug(3, "super block updated\n");
+		jbd2_journal_update_superblock(journal, 1);
+	} else {
+		jbd_debug(3, "superblock not updated\n");
+	}
+
+	J_ASSERT(journal->j_running_transaction != NULL);
+	J_ASSERT(journal->j_committing_transaction == NULL);
+
+	commit_transaction = journal->j_running_transaction;
+	J_ASSERT(commit_transaction->t_state == T_RUNNING);
+
+	jbd_debug(1, "JBD: starting commit of transaction %d\n",
+			commit_transaction->t_tid);
+
+	spin_lock(&journal->j_state_lock);
+	commit_transaction->t_state = T_LOCKED;
+
+	spin_lock(&commit_transaction->t_handle_lock);
+	while (commit_transaction->t_updates) {
+		DEFINE_WAIT(wait);
+
+		prepare_to_wait(&journal->j_wait_updates, &wait,
+					TASK_UNINTERRUPTIBLE);
+		if (commit_transaction->t_updates) {
+			spin_unlock(&commit_transaction->t_handle_lock);
+			spin_unlock(&journal->j_state_lock);
+			schedule();
+			spin_lock(&journal->j_state_lock);
+			spin_lock(&commit_transaction->t_handle_lock);
+		}
+		finish_wait(&journal->j_wait_updates, &wait);
+	}
+	spin_unlock(&commit_transaction->t_handle_lock);
+
+	J_ASSERT (commit_transaction->t_outstanding_credits <=
+			journal->j_max_transaction_buffers);
+
+	/*
+	 * First thing we are allowed to do is to discard any remaining
+	 * BJ_Reserved buffers.  Note, it is _not_ permissible to assume
+	 * that there are no such buffers: if a large filesystem
+	 * operation like a truncate needs to split itself over multiple
+	 * transactions, then it may try to do a jbd2_journal_restart() while
+	 * there are still BJ_Reserved buffers outstanding.  These must
+	 * be released cleanly from the current transaction.
+	 *
+	 * In this case, the filesystem must still reserve write access
+	 * again before modifying the buffer in the new transaction, but
+	 * we do not require it to remember exactly which old buffers it
+	 * has reserved.  This is consistent with the existing behaviour
+	 * that multiple jbd2_journal_get_write_access() calls to the same
+	 * buffer are perfectly permissable.
+	 */
+	while (commit_transaction->t_reserved_list) {
+		jh = commit_transaction->t_reserved_list;
+		JBUFFER_TRACE(jh, "reserved, unused: refile");
+		/*
+		 * A jbd2_journal_get_undo_access()+jbd2_journal_release_buffer() may
+		 * leave undo-committed data.
+		 */
+		if (jh->b_committed_data) {
+			struct buffer_head *bh = jh2bh(jh);
+
+			jbd_lock_bh_state(bh);
+			jbd2_slab_free(jh->b_committed_data, bh->b_size);
+			jh->b_committed_data = NULL;
+			jbd_unlock_bh_state(bh);
+		}
+		jbd2_journal_refile_buffer(journal, jh);
+	}
+
+	/*
+	 * Now try to drop any written-back buffers from the journal's
+	 * checkpoint lists.  We do this *before* commit because it potentially
+	 * frees some memory
+	 */
+	spin_lock(&journal->j_list_lock);
+	__jbd2_journal_clean_checkpoint_list(journal);
+	spin_unlock(&journal->j_list_lock);
+
+	jbd_debug (3, "JBD: commit phase 1\n");
+
+	/*
+	 * Switch to a new revoke table.
+	 */
+	jbd2_journal_switch_revoke_table(journal);
+
+	commit_transaction->t_state = T_FLUSH;
+	journal->j_committing_transaction = commit_transaction;
+	journal->j_running_transaction = NULL;
+	commit_transaction->t_log_start = journal->j_head;
+	wake_up(&journal->j_wait_transaction_locked);
+	spin_unlock(&journal->j_state_lock);
+
+	jbd_debug (3, "JBD: commit phase 2\n");
+
+	/*
+	 * First, drop modified flag: all accesses to the buffers
+	 * will be tracked for a new trasaction only -bzzz
+	 */
+	spin_lock(&journal->j_list_lock);
+	if (commit_transaction->t_buffers) {
+		new_jh = jh = commit_transaction->t_buffers->b_tnext;
+		do {
+			J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
+					new_jh->b_modified == 0);
+			new_jh->b_modified = 0;
+			new_jh = new_jh->b_tnext;
+		} while (new_jh != jh);
+	}
+	spin_unlock(&journal->j_list_lock);
+
+	/*
+	 * Now start flushing things to disk, in the order they appear
+	 * on the transaction lists.  Data blocks go first.
+	 */
+	err = 0;
+	journal_submit_data_buffers(journal, commit_transaction);
+
+	/*
+	 * Wait for all previously submitted IO to complete.
+	 */
+	spin_lock(&journal->j_list_lock);
+	while (commit_transaction->t_locked_list) {
+		struct buffer_head *bh;
+
+		jh = commit_transaction->t_locked_list->b_tprev;
+		bh = jh2bh(jh);
+		get_bh(bh);
+		if (buffer_locked(bh)) {
+			spin_unlock(&journal->j_list_lock);
+			wait_on_buffer(bh);
+			if (unlikely(!buffer_uptodate(bh)))
+				err = -EIO;
+			spin_lock(&journal->j_list_lock);
+		}
+		if (!inverted_lock(journal, bh)) {
+			put_bh(bh);
+			spin_lock(&journal->j_list_lock);
+			continue;
+		}
+		if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) {
+			__jbd2_journal_unfile_buffer(jh);
+			jbd_unlock_bh_state(bh);
+			jbd2_journal_remove_journal_head(bh);
+			put_bh(bh);
+		} else {
+			jbd_unlock_bh_state(bh);
+		}
+		put_bh(bh);
+		cond_resched_lock(&journal->j_list_lock);
+	}
+	spin_unlock(&journal->j_list_lock);
+
+	if (err)
+		__jbd2_journal_abort_hard(journal);
+
+	jbd2_journal_write_revoke_records(journal, commit_transaction);
+
+	jbd_debug(3, "JBD: commit phase 2\n");
+
+	/*
+	 * If we found any dirty or locked buffers, then we should have
+	 * looped back up to the write_out_data label.  If there weren't
+	 * any then journal_clean_data_list should have wiped the list
+	 * clean by now, so check that it is in fact empty.
+	 */
+	J_ASSERT (commit_transaction->t_sync_datalist == NULL);
+
+	jbd_debug (3, "JBD: commit phase 3\n");
+
+	/*
+	 * Way to go: we have now written out all of the data for a
+	 * transaction!  Now comes the tricky part: we need to write out
+	 * metadata.  Loop over the transaction's entire buffer list:
+	 */
+	commit_transaction->t_state = T_COMMIT;
+
+	descriptor = NULL;
+	bufs = 0;
+	while (commit_transaction->t_buffers) {
+
+		/* Find the next buffer to be journaled... */
+
+		jh = commit_transaction->t_buffers;
+
+		/* If we're in abort mode, we just un-journal the buffer and
+		   release it for background writing. */
+
+		if (is_journal_aborted(journal)) {
+			JBUFFER_TRACE(jh, "journal is aborting: refile");
+			jbd2_journal_refile_buffer(journal, jh);
+			/* If that was the last one, we need to clean up
+			 * any descriptor buffers which may have been
+			 * already allocated, even if we are now
+			 * aborting. */
+			if (!commit_transaction->t_buffers)
+				goto start_journal_io;
+			continue;
+		}
+
+		/* Make sure we have a descriptor block in which to
+		   record the metadata buffer. */
+
+		if (!descriptor) {
+			struct buffer_head *bh;
+
+			J_ASSERT (bufs == 0);
+
+			jbd_debug(4, "JBD: get descriptor\n");
+
+			descriptor = jbd2_journal_get_descriptor_buffer(journal);
+			if (!descriptor) {
+				__jbd2_journal_abort_hard(journal);
+				continue;
+			}
+
+			bh = jh2bh(descriptor);
+			jbd_debug(4, "JBD: got buffer %llu (%p)\n",
+				(unsigned long long)bh->b_blocknr, bh->b_data);
+			header = (journal_header_t *)&bh->b_data[0];
+			header->h_magic     = cpu_to_be32(JBD2_MAGIC_NUMBER);
+			header->h_blocktype = cpu_to_be32(JBD2_DESCRIPTOR_BLOCK);
+			header->h_sequence  = cpu_to_be32(commit_transaction->t_tid);
+
+			tagp = &bh->b_data[sizeof(journal_header_t)];
+			space_left = bh->b_size - sizeof(journal_header_t);
+			first_tag = 1;
+			set_buffer_jwrite(bh);
+			set_buffer_dirty(bh);
+			wbuf[bufs++] = bh;
+
+			/* Record it so that we can wait for IO
+                           completion later */
+			BUFFER_TRACE(bh, "ph3: file as descriptor");
+			jbd2_journal_file_buffer(descriptor, commit_transaction,
+					BJ_LogCtl);
+		}
+
+		/* Where is the buffer to be written? */
+
+		err = jbd2_journal_next_log_block(journal, &blocknr);
+		/* If the block mapping failed, just abandon the buffer
+		   and repeat this loop: we'll fall into the
+		   refile-on-abort condition above. */
+		if (err) {
+			__jbd2_journal_abort_hard(journal);
+			continue;
+		}
+
+		/*
+		 * start_this_handle() uses t_outstanding_credits to determine
+		 * the free space in the log, but this counter is changed
+		 * by jbd2_journal_next_log_block() also.
+		 */
+		commit_transaction->t_outstanding_credits--;
+
+		/* Bump b_count to prevent truncate from stumbling over
+                   the shadowed buffer!  @@@ This can go if we ever get
+                   rid of the BJ_IO/BJ_Shadow pairing of buffers. */
+		atomic_inc(&jh2bh(jh)->b_count);
+
+		/* Make a temporary IO buffer with which to write it out
+                   (this will requeue both the metadata buffer and the
+                   temporary IO buffer). new_bh goes on BJ_IO*/
+
+		set_bit(BH_JWrite, &jh2bh(jh)->b_state);
+		/*
+		 * akpm: jbd2_journal_write_metadata_buffer() sets
+		 * new_bh->b_transaction to commit_transaction.
+		 * We need to clean this up before we release new_bh
+		 * (which is of type BJ_IO)
+		 */
+		JBUFFER_TRACE(jh, "ph3: write metadata");
+		flags = jbd2_journal_write_metadata_buffer(commit_transaction,
+						      jh, &new_jh, blocknr);
+		set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
+		wbuf[bufs++] = jh2bh(new_jh);
+
+		/* Record the new block's tag in the current descriptor
+                   buffer */
+
+		tag_flag = 0;
+		if (flags & 1)
+			tag_flag |= JBD2_FLAG_ESCAPE;
+		if (!first_tag)
+			tag_flag |= JBD2_FLAG_SAME_UUID;
+
+		tag = (journal_block_tag_t *) tagp;
+		write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr);
+		tag->t_flags = cpu_to_be32(tag_flag);
+		tagp += tag_bytes;
+		space_left -= tag_bytes;
+
+		if (first_tag) {
+			memcpy (tagp, journal->j_uuid, 16);
+			tagp += 16;
+			space_left -= 16;
+			first_tag = 0;
+		}
+
+		/* If there's no more to do, or if the descriptor is full,
+		   let the IO rip! */
+
+		if (bufs == journal->j_wbufsize ||
+		    commit_transaction->t_buffers == NULL ||
+		    space_left < tag_bytes + 16) {
+
+			jbd_debug(4, "JBD: Submit %d IOs\n", bufs);
+
+			/* Write an end-of-descriptor marker before
+                           submitting the IOs.  "tag" still points to
+                           the last tag we set up. */
+
+			tag->t_flags |= cpu_to_be32(JBD2_FLAG_LAST_TAG);
+
+start_journal_io:
+			for (i = 0; i < bufs; i++) {
+				struct buffer_head *bh = wbuf[i];
+				lock_buffer(bh);
+				clear_buffer_dirty(bh);
+				set_buffer_uptodate(bh);
+				bh->b_end_io = journal_end_buffer_io_sync;
+				submit_bh(WRITE, bh);
+			}
+			cond_resched();
+
+			/* Force a new descriptor to be generated next
+                           time round the loop. */
+			descriptor = NULL;
+			bufs = 0;
+		}
+	}
+
+	/* Lo and behold: we have just managed to send a transaction to
+           the log.  Before we can commit it, wait for the IO so far to
+           complete.  Control buffers being written are on the
+           transaction's t_log_list queue, and metadata buffers are on
+           the t_iobuf_list queue.
+
+	   Wait for the buffers in reverse order.  That way we are
+	   less likely to be woken up until all IOs have completed, and
+	   so we incur less scheduling load.
+	*/
+
+	jbd_debug(3, "JBD: commit phase 4\n");
+
+	/*
+	 * akpm: these are BJ_IO, and j_list_lock is not needed.
+	 * See __journal_try_to_free_buffer.
+	 */
+wait_for_iobuf:
+	while (commit_transaction->t_iobuf_list != NULL) {
+		struct buffer_head *bh;
+
+		jh = commit_transaction->t_iobuf_list->b_tprev;
+		bh = jh2bh(jh);
+		if (buffer_locked(bh)) {
+			wait_on_buffer(bh);
+			goto wait_for_iobuf;
+		}
+		if (cond_resched())
+			goto wait_for_iobuf;
+
+		if (unlikely(!buffer_uptodate(bh)))
+			err = -EIO;
+
+		clear_buffer_jwrite(bh);
+
+		JBUFFER_TRACE(jh, "ph4: unfile after journal write");
+		jbd2_journal_unfile_buffer(journal, jh);
+
+		/*
+		 * ->t_iobuf_list should contain only dummy buffer_heads
+		 * which were created by jbd2_journal_write_metadata_buffer().
+		 */
+		BUFFER_TRACE(bh, "dumping temporary bh");
+		jbd2_journal_put_journal_head(jh);
+		__brelse(bh);
+		J_ASSERT_BH(bh, atomic_read(&bh->b_count) == 0);
+		free_buffer_head(bh);
+
+		/* We also have to unlock and free the corresponding
+                   shadowed buffer */
+		jh = commit_transaction->t_shadow_list->b_tprev;
+		bh = jh2bh(jh);
+		clear_bit(BH_JWrite, &bh->b_state);
+		J_ASSERT_BH(bh, buffer_jbddirty(bh));
+
+		/* The metadata is now released for reuse, but we need
+                   to remember it against this transaction so that when
+                   we finally commit, we can do any checkpointing
+                   required. */
+		JBUFFER_TRACE(jh, "file as BJ_Forget");
+		jbd2_journal_file_buffer(jh, commit_transaction, BJ_Forget);
+		/* Wake up any transactions which were waiting for this
+		   IO to complete */
+		wake_up_bit(&bh->b_state, BH_Unshadow);
+		JBUFFER_TRACE(jh, "brelse shadowed buffer");
+		__brelse(bh);
+	}
+
+	J_ASSERT (commit_transaction->t_shadow_list == NULL);
+
+	jbd_debug(3, "JBD: commit phase 5\n");
+
+	/* Here we wait for the revoke record and descriptor record buffers */
+ wait_for_ctlbuf:
+	while (commit_transaction->t_log_list != NULL) {
+		struct buffer_head *bh;
+
+		jh = commit_transaction->t_log_list->b_tprev;
+		bh = jh2bh(jh);
+		if (buffer_locked(bh)) {
+			wait_on_buffer(bh);
+			goto wait_for_ctlbuf;
+		}
+		if (cond_resched())
+			goto wait_for_ctlbuf;
+
+		if (unlikely(!buffer_uptodate(bh)))
+			err = -EIO;
+
+		BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile");
+		clear_buffer_jwrite(bh);
+		jbd2_journal_unfile_buffer(journal, jh);
+		jbd2_journal_put_journal_head(jh);
+		__brelse(bh);		/* One for getblk */
+		/* AKPM: bforget here */
+	}
+
+	jbd_debug(3, "JBD: commit phase 6\n");
+
+	if (journal_write_commit_record(journal, commit_transaction))
+		err = -EIO;
+
+	if (err)
+		__jbd2_journal_abort_hard(journal);
+
+	/* End of a transaction!  Finally, we can do checkpoint
+           processing: any buffers committed as a result of this
+           transaction can be removed from any checkpoint list it was on
+           before. */
+
+	jbd_debug(3, "JBD: commit phase 7\n");
+
+	J_ASSERT(commit_transaction->t_sync_datalist == NULL);
+	J_ASSERT(commit_transaction->t_buffers == NULL);
+	J_ASSERT(commit_transaction->t_checkpoint_list == NULL);
+	J_ASSERT(commit_transaction->t_iobuf_list == NULL);
+	J_ASSERT(commit_transaction->t_shadow_list == NULL);
+	J_ASSERT(commit_transaction->t_log_list == NULL);
+
+restart_loop:
+	/*
+	 * As there are other places (journal_unmap_buffer()) adding buffers
+	 * to this list we have to be careful and hold the j_list_lock.
+	 */
+	spin_lock(&journal->j_list_lock);
+	while (commit_transaction->t_forget) {
+		transaction_t *cp_transaction;
+		struct buffer_head *bh;
+
+		jh = commit_transaction->t_forget;
+		spin_unlock(&journal->j_list_lock);
+		bh = jh2bh(jh);
+		jbd_lock_bh_state(bh);
+		J_ASSERT_JH(jh,	jh->b_transaction == commit_transaction ||
+			jh->b_transaction == journal->j_running_transaction);
+
+		/*
+		 * If there is undo-protected committed data against
+		 * this buffer, then we can remove it now.  If it is a
+		 * buffer needing such protection, the old frozen_data
+		 * field now points to a committed version of the
+		 * buffer, so rotate that field to the new committed
+		 * data.
+		 *
+		 * Otherwise, we can just throw away the frozen data now.
+		 */
+		if (jh->b_committed_data) {
+			jbd2_slab_free(jh->b_committed_data, bh->b_size);
+			jh->b_committed_data = NULL;
+			if (jh->b_frozen_data) {
+				jh->b_committed_data = jh->b_frozen_data;
+				jh->b_frozen_data = NULL;
+			}
+		} else if (jh->b_frozen_data) {
+			jbd2_slab_free(jh->b_frozen_data, bh->b_size);
+			jh->b_frozen_data = NULL;
+		}
+
+		spin_lock(&journal->j_list_lock);
+		cp_transaction = jh->b_cp_transaction;
+		if (cp_transaction) {
+			JBUFFER_TRACE(jh, "remove from old cp transaction");
+			__jbd2_journal_remove_checkpoint(jh);
+		}
+
+		/* Only re-checkpoint the buffer_head if it is marked
+		 * dirty.  If the buffer was added to the BJ_Forget list
+		 * by jbd2_journal_forget, it may no longer be dirty and
+		 * there's no point in keeping a checkpoint record for
+		 * it. */
+
+		/* A buffer which has been freed while still being
+		 * journaled by a previous transaction may end up still
+		 * being dirty here, but we want to avoid writing back
+		 * that buffer in the future now that the last use has
+		 * been committed.  That's not only a performance gain,
+		 * it also stops aliasing problems if the buffer is left
+		 * behind for writeback and gets reallocated for another
+		 * use in a different page. */
+		if (buffer_freed(bh)) {
+			clear_buffer_freed(bh);
+			clear_buffer_jbddirty(bh);
+		}
+
+		if (buffer_jbddirty(bh)) {
+			JBUFFER_TRACE(jh, "add to new checkpointing trans");
+			__jbd2_journal_insert_checkpoint(jh, commit_transaction);
+			JBUFFER_TRACE(jh, "refile for checkpoint writeback");
+			__jbd2_journal_refile_buffer(jh);
+			jbd_unlock_bh_state(bh);
+		} else {
+			J_ASSERT_BH(bh, !buffer_dirty(bh));
+			/* The buffer on BJ_Forget list and not jbddirty means
+			 * it has been freed by this transaction and hence it
+			 * could not have been reallocated until this
+			 * transaction has committed. *BUT* it could be
+			 * reallocated once we have written all the data to
+			 * disk and before we process the buffer on BJ_Forget
+			 * list. */
+			JBUFFER_TRACE(jh, "refile or unfile freed buffer");
+			__jbd2_journal_refile_buffer(jh);
+			if (!jh->b_transaction) {
+				jbd_unlock_bh_state(bh);
+				 /* needs a brelse */
+				jbd2_journal_remove_journal_head(bh);
+				release_buffer_page(bh);
+			} else
+				jbd_unlock_bh_state(bh);
+		}
+		cond_resched_lock(&journal->j_list_lock);
+	}
+	spin_unlock(&journal->j_list_lock);
+	/*
+	 * This is a bit sleazy.  We borrow j_list_lock to protect
+	 * journal->j_committing_transaction in __jbd2_journal_remove_checkpoint.
+	 * Really, __jbd2_journal_remove_checkpoint should be using j_state_lock but
+	 * it's a bit hassle to hold that across __jbd2_journal_remove_checkpoint
+	 */
+	spin_lock(&journal->j_state_lock);
+	spin_lock(&journal->j_list_lock);
+	/*
+	 * Now recheck if some buffers did not get attached to the transaction
+	 * while the lock was dropped...
+	 */
+	if (commit_transaction->t_forget) {
+		spin_unlock(&journal->j_list_lock);
+		spin_unlock(&journal->j_state_lock);
+		goto restart_loop;
+	}
+
+	/* Done with this transaction! */
+
+	jbd_debug(3, "JBD: commit phase 8\n");
+
+	J_ASSERT(commit_transaction->t_state == T_COMMIT);
+
+	commit_transaction->t_state = T_FINISHED;
+	J_ASSERT(commit_transaction == journal->j_committing_transaction);
+	journal->j_commit_sequence = commit_transaction->t_tid;
+	journal->j_committing_transaction = NULL;
+	spin_unlock(&journal->j_state_lock);
+
+	if (commit_transaction->t_checkpoint_list == NULL) {
+		__jbd2_journal_drop_transaction(journal, commit_transaction);
+	} else {
+		if (journal->j_checkpoint_transactions == NULL) {
+			journal->j_checkpoint_transactions = commit_transaction;
+			commit_transaction->t_cpnext = commit_transaction;
+			commit_transaction->t_cpprev = commit_transaction;
+		} else {
+			commit_transaction->t_cpnext =
+				journal->j_checkpoint_transactions;
+			commit_transaction->t_cpprev =
+				commit_transaction->t_cpnext->t_cpprev;
+			commit_transaction->t_cpnext->t_cpprev =
+				commit_transaction;
+			commit_transaction->t_cpprev->t_cpnext =
+				commit_transaction;
+		}
+	}
+	spin_unlock(&journal->j_list_lock);
+
+	jbd_debug(1, "JBD: commit %d complete, head %d\n",
+		  journal->j_commit_sequence, journal->j_tail_sequence);
+
+	wake_up(&journal->j_wait_done_commit);
+}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
new file mode 100644
index 0000000..c60f378
--- /dev/null
+++ b/fs/jbd2/journal.c
@@ -0,0 +1,2084 @@
+/*
+ * linux/fs/jbd2/journal.c
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
+ *
+ * Copyright 1998 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Generic filesystem journal-writing code; part of the ext2fs
+ * journaling system.
+ *
+ * This file manages journals: areas of disk reserved for logging
+ * transactional updates.  This includes the kernel journaling thread
+ * which is responsible for scheduling updates to the log.
+ *
+ * We do not actually manage the physical storage of the journal in this
+ * file: that is left to a per-journal policy function, which allows us
+ * to store the journal within a filesystem-specified area for ext2
+ * journaling (ext2 can use a reserved inode for storing the log).
+ */
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/suspend.h>
+#include <linux/pagemap.h>
+#include <linux/kthread.h>
+#include <linux/poison.h>
+#include <linux/proc_fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+
+EXPORT_SYMBOL(jbd2_journal_start);
+EXPORT_SYMBOL(jbd2_journal_restart);
+EXPORT_SYMBOL(jbd2_journal_extend);
+EXPORT_SYMBOL(jbd2_journal_stop);
+EXPORT_SYMBOL(jbd2_journal_lock_updates);
+EXPORT_SYMBOL(jbd2_journal_unlock_updates);
+EXPORT_SYMBOL(jbd2_journal_get_write_access);
+EXPORT_SYMBOL(jbd2_journal_get_create_access);
+EXPORT_SYMBOL(jbd2_journal_get_undo_access);
+EXPORT_SYMBOL(jbd2_journal_dirty_data);
+EXPORT_SYMBOL(jbd2_journal_dirty_metadata);
+EXPORT_SYMBOL(jbd2_journal_release_buffer);
+EXPORT_SYMBOL(jbd2_journal_forget);
+#if 0
+EXPORT_SYMBOL(journal_sync_buffer);
+#endif
+EXPORT_SYMBOL(jbd2_journal_flush);
+EXPORT_SYMBOL(jbd2_journal_revoke);
+
+EXPORT_SYMBOL(jbd2_journal_init_dev);
+EXPORT_SYMBOL(jbd2_journal_init_inode);
+EXPORT_SYMBOL(jbd2_journal_update_format);
+EXPORT_SYMBOL(jbd2_journal_check_used_features);
+EXPORT_SYMBOL(jbd2_journal_check_available_features);
+EXPORT_SYMBOL(jbd2_journal_set_features);
+EXPORT_SYMBOL(jbd2_journal_create);
+EXPORT_SYMBOL(jbd2_journal_load);
+EXPORT_SYMBOL(jbd2_journal_destroy);
+EXPORT_SYMBOL(jbd2_journal_update_superblock);
+EXPORT_SYMBOL(jbd2_journal_abort);
+EXPORT_SYMBOL(jbd2_journal_errno);
+EXPORT_SYMBOL(jbd2_journal_ack_err);
+EXPORT_SYMBOL(jbd2_journal_clear_err);
+EXPORT_SYMBOL(jbd2_log_wait_commit);
+EXPORT_SYMBOL(jbd2_journal_start_commit);
+EXPORT_SYMBOL(jbd2_journal_force_commit_nested);
+EXPORT_SYMBOL(jbd2_journal_wipe);
+EXPORT_SYMBOL(jbd2_journal_blocks_per_page);
+EXPORT_SYMBOL(jbd2_journal_invalidatepage);
+EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers);
+EXPORT_SYMBOL(jbd2_journal_force_commit);
+
+static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+static void __journal_abort_soft (journal_t *journal, int errno);
+static int jbd2_journal_create_jbd_slab(size_t slab_size);
+
+/*
+ * Helper function used to manage commit timeouts
+ */
+
+static void commit_timeout(unsigned long __data)
+{
+	struct task_struct * p = (struct task_struct *) __data;
+
+	wake_up_process(p);
+}
+
+/*
+ * kjournald2: The main thread function used to manage a logging device
+ * journal.
+ *
+ * This kernel thread is responsible for two things:
+ *
+ * 1) COMMIT:  Every so often we need to commit the current state of the
+ *    filesystem to disk.  The journal thread is responsible for writing
+ *    all of the metadata buffers to disk.
+ *
+ * 2) CHECKPOINT: We cannot reuse a used section of the log file until all
+ *    of the data in that part of the log has been rewritten elsewhere on
+ *    the disk.  Flushing these old buffers to reclaim space in the log is
+ *    known as checkpointing, and this thread is responsible for that job.
+ */
+
+static int kjournald2(void *arg)
+{
+	journal_t *journal = arg;
+	transaction_t *transaction;
+
+	/*
+	 * Set up an interval timer which can be used to trigger a commit wakeup
+	 * after the commit interval expires
+	 */
+	setup_timer(&journal->j_commit_timer, commit_timeout,
+			(unsigned long)current);
+
+	/* Record that the journal thread is running */
+	journal->j_task = current;
+	wake_up(&journal->j_wait_done_commit);
+
+	printk(KERN_INFO "kjournald2 starting.  Commit interval %ld seconds\n",
+			journal->j_commit_interval / HZ);
+
+	/*
+	 * And now, wait forever for commit wakeup events.
+	 */
+	spin_lock(&journal->j_state_lock);
+
+loop:
+	if (journal->j_flags & JBD2_UNMOUNT)
+		goto end_loop;
+
+	jbd_debug(1, "commit_sequence=%d, commit_request=%d\n",
+		journal->j_commit_sequence, journal->j_commit_request);
+
+	if (journal->j_commit_sequence != journal->j_commit_request) {
+		jbd_debug(1, "OK, requests differ\n");
+		spin_unlock(&journal->j_state_lock);
+		del_timer_sync(&journal->j_commit_timer);
+		jbd2_journal_commit_transaction(journal);
+		spin_lock(&journal->j_state_lock);
+		goto loop;
+	}
+
+	wake_up(&journal->j_wait_done_commit);
+	if (freezing(current)) {
+		/*
+		 * The simpler the better. Flushing journal isn't a
+		 * good idea, because that depends on threads that may
+		 * be already stopped.
+		 */
+		jbd_debug(1, "Now suspending kjournald2\n");
+		spin_unlock(&journal->j_state_lock);
+		refrigerator();
+		spin_lock(&journal->j_state_lock);
+	} else {
+		/*
+		 * We assume on resume that commits are already there,
+		 * so we don't sleep
+		 */
+		DEFINE_WAIT(wait);
+		int should_sleep = 1;
+
+		prepare_to_wait(&journal->j_wait_commit, &wait,
+				TASK_INTERRUPTIBLE);
+		if (journal->j_commit_sequence != journal->j_commit_request)
+			should_sleep = 0;
+		transaction = journal->j_running_transaction;
+		if (transaction && time_after_eq(jiffies,
+						transaction->t_expires))
+			should_sleep = 0;
+		if (journal->j_flags & JBD2_UNMOUNT)
+			should_sleep = 0;
+		if (should_sleep) {
+			spin_unlock(&journal->j_state_lock);
+			schedule();
+			spin_lock(&journal->j_state_lock);
+		}
+		finish_wait(&journal->j_wait_commit, &wait);
+	}
+
+	jbd_debug(1, "kjournald2 wakes\n");
+
+	/*
+	 * Were we woken up by a commit wakeup event?
+	 */
+	transaction = journal->j_running_transaction;
+	if (transaction && time_after_eq(jiffies, transaction->t_expires)) {
+		journal->j_commit_request = transaction->t_tid;
+		jbd_debug(1, "woke because of timeout\n");
+	}
+	goto loop;
+
+end_loop:
+	spin_unlock(&journal->j_state_lock);
+	del_timer_sync(&journal->j_commit_timer);
+	journal->j_task = NULL;
+	wake_up(&journal->j_wait_done_commit);
+	jbd_debug(1, "Journal thread exiting.\n");
+	return 0;
+}
+
+static void jbd2_journal_start_thread(journal_t *journal)
+{
+	kthread_run(kjournald2, journal, "kjournald2");
+	wait_event(journal->j_wait_done_commit, journal->j_task != 0);
+}
+
+static void journal_kill_thread(journal_t *journal)
+{
+	spin_lock(&journal->j_state_lock);
+	journal->j_flags |= JBD2_UNMOUNT;
+
+	while (journal->j_task) {
+		wake_up(&journal->j_wait_commit);
+		spin_unlock(&journal->j_state_lock);
+		wait_event(journal->j_wait_done_commit, journal->j_task == 0);
+		spin_lock(&journal->j_state_lock);
+	}
+	spin_unlock(&journal->j_state_lock);
+}
+
+/*
+ * jbd2_journal_write_metadata_buffer: write a metadata buffer to the journal.
+ *
+ * Writes a metadata buffer to a given disk block.  The actual IO is not
+ * performed but a new buffer_head is constructed which labels the data
+ * to be written with the correct destination disk block.
+ *
+ * Any magic-number escaping which needs to be done will cause a
+ * copy-out here.  If the buffer happens to start with the
+ * JBD2_MAGIC_NUMBER, then we can't write it to the log directly: the
+ * magic number is only written to the log for descripter blocks.  In
+ * this case, we copy the data and replace the first word with 0, and we
+ * return a result code which indicates that this buffer needs to be
+ * marked as an escaped buffer in the corresponding log descriptor
+ * block.  The missing word can then be restored when the block is read
+ * during recovery.
+ *
+ * If the source buffer has already been modified by a new transaction
+ * since we took the last commit snapshot, we use the frozen copy of
+ * that data for IO.  If we end up using the existing buffer_head's data
+ * for the write, then we *have* to lock the buffer to prevent anyone
+ * else from using and possibly modifying it while the IO is in
+ * progress.
+ *
+ * The function returns a pointer to the buffer_heads to be used for IO.
+ *
+ * We assume that the journal has already been locked in this function.
+ *
+ * Return value:
+ *  <0: Error
+ * >=0: Finished OK
+ *
+ * On success:
+ * Bit 0 set == escape performed on the data
+ * Bit 1 set == buffer copy-out performed (kfree the data after IO)
+ */
+
+int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
+				  struct journal_head  *jh_in,
+				  struct journal_head **jh_out,
+				  unsigned long long blocknr)
+{
+	int need_copy_out = 0;
+	int done_copy_out = 0;
+	int do_escape = 0;
+	char *mapped_data;
+	struct buffer_head *new_bh;
+	struct journal_head *new_jh;
+	struct page *new_page;
+	unsigned int new_offset;
+	struct buffer_head *bh_in = jh2bh(jh_in);
+
+	/*
+	 * The buffer really shouldn't be locked: only the current committing
+	 * transaction is allowed to write it, so nobody else is allowed
+	 * to do any IO.
+	 *
+	 * akpm: except if we're journalling data, and write() output is
+	 * also part of a shared mapping, and another thread has
+	 * decided to launch a writepage() against this buffer.
+	 */
+	J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
+
+	new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
+
+	/*
+	 * If a new transaction has already done a buffer copy-out, then
+	 * we use that version of the data for the commit.
+	 */
+	jbd_lock_bh_state(bh_in);
+repeat:
+	if (jh_in->b_frozen_data) {
+		done_copy_out = 1;
+		new_page = virt_to_page(jh_in->b_frozen_data);
+		new_offset = offset_in_page(jh_in->b_frozen_data);
+	} else {
+		new_page = jh2bh(jh_in)->b_page;
+		new_offset = offset_in_page(jh2bh(jh_in)->b_data);
+	}
+
+	mapped_data = kmap_atomic(new_page, KM_USER0);
+	/*
+	 * Check for escaping
+	 */
+	if (*((__be32 *)(mapped_data + new_offset)) ==
+				cpu_to_be32(JBD2_MAGIC_NUMBER)) {
+		need_copy_out = 1;
+		do_escape = 1;
+	}
+	kunmap_atomic(mapped_data, KM_USER0);
+
+	/*
+	 * Do we need to do a data copy?
+	 */
+	if (need_copy_out && !done_copy_out) {
+		char *tmp;
+
+		jbd_unlock_bh_state(bh_in);
+		tmp = jbd2_slab_alloc(bh_in->b_size, GFP_NOFS);
+		jbd_lock_bh_state(bh_in);
+		if (jh_in->b_frozen_data) {
+			jbd2_slab_free(tmp, bh_in->b_size);
+			goto repeat;
+		}
+
+		jh_in->b_frozen_data = tmp;
+		mapped_data = kmap_atomic(new_page, KM_USER0);
+		memcpy(tmp, mapped_data + new_offset, jh2bh(jh_in)->b_size);
+		kunmap_atomic(mapped_data, KM_USER0);
+
+		new_page = virt_to_page(tmp);
+		new_offset = offset_in_page(tmp);
+		done_copy_out = 1;
+	}
+
+	/*
+	 * Did we need to do an escaping?  Now we've done all the
+	 * copying, we can finally do so.
+	 */
+	if (do_escape) {
+		mapped_data = kmap_atomic(new_page, KM_USER0);
+		*((unsigned int *)(mapped_data + new_offset)) = 0;
+		kunmap_atomic(mapped_data, KM_USER0);
+	}
+
+	/* keep subsequent assertions sane */
+	new_bh->b_state = 0;
+	init_buffer(new_bh, NULL, NULL);
+	atomic_set(&new_bh->b_count, 1);
+	jbd_unlock_bh_state(bh_in);
+
+	new_jh = jbd2_journal_add_journal_head(new_bh);	/* This sleeps */
+
+	set_bh_page(new_bh, new_page, new_offset);
+	new_jh->b_transaction = NULL;
+	new_bh->b_size = jh2bh(jh_in)->b_size;
+	new_bh->b_bdev = transaction->t_journal->j_dev;
+	new_bh->b_blocknr = blocknr;
+	set_buffer_mapped(new_bh);
+	set_buffer_dirty(new_bh);
+
+	*jh_out = new_jh;
+
+	/*
+	 * The to-be-written buffer needs to get moved to the io queue,
+	 * and the original buffer whose contents we are shadowing or
+	 * copying is moved to the transaction's shadow queue.
+	 */
+	JBUFFER_TRACE(jh_in, "file as BJ_Shadow");
+	jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow);
+	JBUFFER_TRACE(new_jh, "file as BJ_IO");
+	jbd2_journal_file_buffer(new_jh, transaction, BJ_IO);
+
+	return do_escape | (done_copy_out << 1);
+}
+
+/*
+ * Allocation code for the journal file.  Manage the space left in the
+ * journal, so that we can begin checkpointing when appropriate.
+ */
+
+/*
+ * __jbd2_log_space_left: Return the number of free blocks left in the journal.
+ *
+ * Called with the journal already locked.
+ *
+ * Called under j_state_lock
+ */
+
+int __jbd2_log_space_left(journal_t *journal)
+{
+	int left = journal->j_free;
+
+	assert_spin_locked(&journal->j_state_lock);
+
+	/*
+	 * Be pessimistic here about the number of those free blocks which
+	 * might be required for log descriptor control blocks.
+	 */
+
+#define MIN_LOG_RESERVED_BLOCKS 32 /* Allow for rounding errors */
+
+	left -= MIN_LOG_RESERVED_BLOCKS;
+
+	if (left <= 0)
+		return 0;
+	left -= (left >> 3);
+	return left;
+}
+
+/*
+ * Called under j_state_lock.  Returns true if a transaction was started.
+ */
+int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+{
+	/*
+	 * Are we already doing a recent enough commit?
+	 */
+	if (!tid_geq(journal->j_commit_request, target)) {
+		/*
+		 * We want a new commit: OK, mark the request and wakup the
+		 * commit thread.  We do _not_ do the commit ourselves.
+		 */
+
+		journal->j_commit_request = target;
+		jbd_debug(1, "JBD: requesting commit %d/%d\n",
+			  journal->j_commit_request,
+			  journal->j_commit_sequence);
+		wake_up(&journal->j_wait_commit);
+		return 1;
+	}
+	return 0;
+}
+
+int jbd2_log_start_commit(journal_t *journal, tid_t tid)
+{
+	int ret;
+
+	spin_lock(&journal->j_state_lock);
+	ret = __jbd2_log_start_commit(journal, tid);
+	spin_unlock(&journal->j_state_lock);
+	return ret;
+}
+
+/*
+ * Force and wait upon a commit if the calling process is not within
+ * transaction.  This is used for forcing out undo-protected data which contains
+ * bitmaps, when the fs is running out of space.
+ *
+ * We can only force the running transaction if we don't have an active handle;
+ * otherwise, we will deadlock.
+ *
+ * Returns true if a transaction was started.
+ */
+int jbd2_journal_force_commit_nested(journal_t *journal)
+{
+	transaction_t *transaction = NULL;
+	tid_t tid;
+
+	spin_lock(&journal->j_state_lock);
+	if (journal->j_running_transaction && !current->journal_info) {
+		transaction = journal->j_running_transaction;
+		__jbd2_log_start_commit(journal, transaction->t_tid);
+	} else if (journal->j_committing_transaction)
+		transaction = journal->j_committing_transaction;
+
+	if (!transaction) {
+		spin_unlock(&journal->j_state_lock);
+		return 0;	/* Nothing to retry */
+	}
+
+	tid = transaction->t_tid;
+	spin_unlock(&journal->j_state_lock);
+	jbd2_log_wait_commit(journal, tid);
+	return 1;
+}
+
+/*
+ * Start a commit of the current running transaction (if any).  Returns true
+ * if a transaction was started, and fills its tid in at *ptid
+ */
+int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
+{
+	int ret = 0;
+
+	spin_lock(&journal->j_state_lock);
+	if (journal->j_running_transaction) {
+		tid_t tid = journal->j_running_transaction->t_tid;
+
+		ret = __jbd2_log_start_commit(journal, tid);
+		if (ret && ptid)
+			*ptid = tid;
+	} else if (journal->j_committing_transaction && ptid) {
+		/*
+		 * If ext3_write_super() recently started a commit, then we
+		 * have to wait for completion of that transaction
+		 */
+		*ptid = journal->j_committing_transaction->t_tid;
+		ret = 1;
+	}
+	spin_unlock(&journal->j_state_lock);
+	return ret;
+}
+
+/*
+ * Wait for a specified commit to complete.
+ * The caller may not hold the journal lock.
+ */
+int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
+{
+	int err = 0;
+
+#ifdef CONFIG_JBD_DEBUG
+	spin_lock(&journal->j_state_lock);
+	if (!tid_geq(journal->j_commit_request, tid)) {
+		printk(KERN_EMERG
+		       "%s: error: j_commit_request=%d, tid=%d\n",
+		       __FUNCTION__, journal->j_commit_request, tid);
+	}
+	spin_unlock(&journal->j_state_lock);
+#endif
+	spin_lock(&journal->j_state_lock);
+	while (tid_gt(tid, journal->j_commit_sequence)) {
+		jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n",
+				  tid, journal->j_commit_sequence);
+		wake_up(&journal->j_wait_commit);
+		spin_unlock(&journal->j_state_lock);
+		wait_event(journal->j_wait_done_commit,
+				!tid_gt(tid, journal->j_commit_sequence));
+		spin_lock(&journal->j_state_lock);
+	}
+	spin_unlock(&journal->j_state_lock);
+
+	if (unlikely(is_journal_aborted(journal))) {
+		printk(KERN_EMERG "journal commit I/O error\n");
+		err = -EIO;
+	}
+	return err;
+}
+
+/*
+ * Log buffer allocation routines:
+ */
+
+int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp)
+{
+	unsigned long blocknr;
+
+	spin_lock(&journal->j_state_lock);
+	J_ASSERT(journal->j_free > 1);
+
+	blocknr = journal->j_head;
+	journal->j_head++;
+	journal->j_free--;
+	if (journal->j_head == journal->j_last)
+		journal->j_head = journal->j_first;
+	spin_unlock(&journal->j_state_lock);
+	return jbd2_journal_bmap(journal, blocknr, retp);
+}
+
+/*
+ * Conversion of logical to physical block numbers for the journal
+ *
+ * On external journals the journal blocks are identity-mapped, so
+ * this is a no-op.  If needed, we can use j_blk_offset - everything is
+ * ready.
+ */
+int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
+		 unsigned long long *retp)
+{
+	int err = 0;
+	unsigned long long ret;
+
+	if (journal->j_inode) {
+		ret = bmap(journal->j_inode, blocknr);
+		if (ret)
+			*retp = ret;
+		else {
+			char b[BDEVNAME_SIZE];
+
+			printk(KERN_ALERT "%s: journal block not found "
+					"at offset %lu on %s\n",
+				__FUNCTION__,
+				blocknr,
+				bdevname(journal->j_dev, b));
+			err = -EIO;
+			__journal_abort_soft(journal, err);
+		}
+	} else {
+		*retp = blocknr; /* +journal->j_blk_offset */
+	}
+	return err;
+}
+
+/*
+ * We play buffer_head aliasing tricks to write data/metadata blocks to
+ * the journal without copying their contents, but for journal
+ * descriptor blocks we do need to generate bona fide buffers.
+ *
+ * After the caller of jbd2_journal_get_descriptor_buffer() has finished modifying
+ * the buffer's contents they really should run flush_dcache_page(bh->b_page).
+ * But we don't bother doing that, so there will be coherency problems with
+ * mmaps of blockdevs which hold live JBD-controlled filesystems.
+ */
+struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal)
+{
+	struct buffer_head *bh;
+	unsigned long long blocknr;
+	int err;
+
+	err = jbd2_journal_next_log_block(journal, &blocknr);
+
+	if (err)
+		return NULL;
+
+	bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+	lock_buffer(bh);
+	memset(bh->b_data, 0, journal->j_blocksize);
+	set_buffer_uptodate(bh);
+	unlock_buffer(bh);
+	BUFFER_TRACE(bh, "return this buffer");
+	return jbd2_journal_add_journal_head(bh);
+}
+
+/*
+ * Management for journal control blocks: functions to create and
+ * destroy journal_t structures, and to initialise and read existing
+ * journal blocks from disk.  */
+
+/* First: create and setup a journal_t object in memory.  We initialise
+ * very few fields yet: that has to wait until we have created the
+ * journal structures from from scratch, or loaded them from disk. */
+
+static journal_t * journal_init_common (void)
+{
+	journal_t *journal;
+	int err;
+
+	journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL);
+	if (!journal)
+		goto fail;
+	memset(journal, 0, sizeof(*journal));
+
+	init_waitqueue_head(&journal->j_wait_transaction_locked);
+	init_waitqueue_head(&journal->j_wait_logspace);
+	init_waitqueue_head(&journal->j_wait_done_commit);
+	init_waitqueue_head(&journal->j_wait_checkpoint);
+	init_waitqueue_head(&journal->j_wait_commit);
+	init_waitqueue_head(&journal->j_wait_updates);
+	mutex_init(&journal->j_barrier);
+	mutex_init(&journal->j_checkpoint_mutex);
+	spin_lock_init(&journal->j_revoke_lock);
+	spin_lock_init(&journal->j_list_lock);
+	spin_lock_init(&journal->j_state_lock);
+
+	journal->j_commit_interval = (HZ * JBD_DEFAULT_MAX_COMMIT_AGE);
+
+	/* The journal is marked for error until we succeed with recovery! */
+	journal->j_flags = JBD2_ABORT;
+
+	/* Set up a default-sized revoke table for the new mount. */
+	err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);
+	if (err) {
+		kfree(journal);
+		goto fail;
+	}
+	return journal;
+fail:
+	return NULL;
+}
+
+/* jbd2_journal_init_dev and jbd2_journal_init_inode:
+ *
+ * Create a journal structure assigned some fixed set of disk blocks to
+ * the journal.  We don't actually touch those disk blocks yet, but we
+ * need to set up all of the mapping information to tell the journaling
+ * system where the journal blocks are.
+ *
+ */
+
+/**
+ *  journal_t * jbd2_journal_init_dev() - creates an initialises a journal structure
+ *  @bdev: Block device on which to create the journal
+ *  @fs_dev: Device which hold journalled filesystem for this journal.
+ *  @start: Block nr Start of journal.
+ *  @len:  Length of the journal in blocks.
+ *  @blocksize: blocksize of journalling device
+ *  @returns: a newly created journal_t *
+ *
+ *  jbd2_journal_init_dev creates a journal which maps a fixed contiguous
+ *  range of blocks on an arbitrary block device.
+ *
+ */
+journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+			struct block_device *fs_dev,
+			unsigned long long start, int len, int blocksize)
+{
+	journal_t *journal = journal_init_common();
+	struct buffer_head *bh;
+	int n;
+
+	if (!journal)
+		return NULL;
+
+	/* journal descriptor can store up to n blocks -bzzz */
+	journal->j_blocksize = blocksize;
+	n = journal->j_blocksize / sizeof(journal_block_tag_t);
+	journal->j_wbufsize = n;
+	journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+	if (!journal->j_wbuf) {
+		printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+			__FUNCTION__);
+		kfree(journal);
+		journal = NULL;
+		goto out;
+	}
+	journal->j_dev = bdev;
+	journal->j_fs_dev = fs_dev;
+	journal->j_blk_offset = start;
+	journal->j_maxlen = len;
+
+	bh = __getblk(journal->j_dev, start, journal->j_blocksize);
+	J_ASSERT(bh != NULL);
+	journal->j_sb_buffer = bh;
+	journal->j_superblock = (journal_superblock_t *)bh->b_data;
+out:
+	return journal;
+}
+
+/**
+ *  journal_t * jbd2_journal_init_inode () - creates a journal which maps to a inode.
+ *  @inode: An inode to create the journal in
+ *
+ * jbd2_journal_init_inode creates a journal which maps an on-disk inode as
+ * the journal.  The inode must exist already, must support bmap() and
+ * must have all data blocks preallocated.
+ */
+journal_t * jbd2_journal_init_inode (struct inode *inode)
+{
+	struct buffer_head *bh;
+	journal_t *journal = journal_init_common();
+	int err;
+	int n;
+	unsigned long long blocknr;
+
+	if (!journal)
+		return NULL;
+
+	journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev;
+	journal->j_inode = inode;
+	jbd_debug(1,
+		  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
+		  journal, inode->i_sb->s_id, inode->i_ino,
+		  (long long) inode->i_size,
+		  inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
+
+	journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
+	journal->j_blocksize = inode->i_sb->s_blocksize;
+
+	/* journal descriptor can store up to n blocks -bzzz */
+	n = journal->j_blocksize / sizeof(journal_block_tag_t);
+	journal->j_wbufsize = n;
+	journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+	if (!journal->j_wbuf) {
+		printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+			__FUNCTION__);
+		kfree(journal);
+		return NULL;
+	}
+
+	err = jbd2_journal_bmap(journal, 0, &blocknr);
+	/* If that failed, give up */
+	if (err) {
+		printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
+		       __FUNCTION__);
+		kfree(journal);
+		return NULL;
+	}
+
+	bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+	J_ASSERT(bh != NULL);
+	journal->j_sb_buffer = bh;
+	journal->j_superblock = (journal_superblock_t *)bh->b_data;
+
+	return journal;
+}
+
+/*
+ * If the journal init or create aborts, we need to mark the journal
+ * superblock as being NULL to prevent the journal destroy from writing
+ * back a bogus superblock.
+ */
+static void journal_fail_superblock (journal_t *journal)
+{
+	struct buffer_head *bh = journal->j_sb_buffer;
+	brelse(bh);
+	journal->j_sb_buffer = NULL;
+}
+
+/*
+ * Given a journal_t structure, initialise the various fields for
+ * startup of a new journaling session.  We use this both when creating
+ * a journal, and after recovering an old journal to reset it for
+ * subsequent use.
+ */
+
+static int journal_reset(journal_t *journal)
+{
+	journal_superblock_t *sb = journal->j_superblock;
+	unsigned long long first, last;
+
+	first = be32_to_cpu(sb->s_first);
+	last = be32_to_cpu(sb->s_maxlen);
+
+	journal->j_first = first;
+	journal->j_last = last;
+
+	journal->j_head = first;
+	journal->j_tail = first;
+	journal->j_free = last - first;
+
+	journal->j_tail_sequence = journal->j_transaction_sequence;
+	journal->j_commit_sequence = journal->j_transaction_sequence - 1;
+	journal->j_commit_request = journal->j_commit_sequence;
+
+	journal->j_max_transaction_buffers = journal->j_maxlen / 4;
+
+	/* Add the dynamic fields and write it to disk. */
+	jbd2_journal_update_superblock(journal, 1);
+	jbd2_journal_start_thread(journal);
+	return 0;
+}
+
+/**
+ * int jbd2_journal_create() - Initialise the new journal file
+ * @journal: Journal to create. This structure must have been initialised
+ *
+ * Given a journal_t structure which tells us which disk blocks we can
+ * use, create a new journal superblock and initialise all of the
+ * journal fields from scratch.
+ **/
+int jbd2_journal_create(journal_t *journal)
+{
+	unsigned long long blocknr;
+	struct buffer_head *bh;
+	journal_superblock_t *sb;
+	int i, err;
+
+	if (journal->j_maxlen < JBD2_MIN_JOURNAL_BLOCKS) {
+		printk (KERN_ERR "Journal length (%d blocks) too short.\n",
+			journal->j_maxlen);
+		journal_fail_superblock(journal);
+		return -EINVAL;
+	}
+
+	if (journal->j_inode == NULL) {
+		/*
+		 * We don't know what block to start at!
+		 */
+		printk(KERN_EMERG
+		       "%s: creation of journal on external device!\n",
+		       __FUNCTION__);
+		BUG();
+	}
+
+	/* Zero out the entire journal on disk.  We cannot afford to
+	   have any blocks on disk beginning with JBD2_MAGIC_NUMBER. */
+	jbd_debug(1, "JBD: Zeroing out journal blocks...\n");
+	for (i = 0; i < journal->j_maxlen; i++) {
+		err = jbd2_journal_bmap(journal, i, &blocknr);
+		if (err)
+			return err;
+		bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+		lock_buffer(bh);
+		memset (bh->b_data, 0, journal->j_blocksize);
+		BUFFER_TRACE(bh, "marking dirty");
+		mark_buffer_dirty(bh);
+		BUFFER_TRACE(bh, "marking uptodate");
+		set_buffer_uptodate(bh);
+		unlock_buffer(bh);
+		__brelse(bh);
+	}
+
+	sync_blockdev(journal->j_dev);
+	jbd_debug(1, "JBD: journal cleared.\n");
+
+	/* OK, fill in the initial static fields in the new superblock */
+	sb = journal->j_superblock;
+
+	sb->s_header.h_magic	 = cpu_to_be32(JBD2_MAGIC_NUMBER);
+	sb->s_header.h_blocktype = cpu_to_be32(JBD2_SUPERBLOCK_V2);
+
+	sb->s_blocksize	= cpu_to_be32(journal->j_blocksize);
+	sb->s_maxlen	= cpu_to_be32(journal->j_maxlen);
+	sb->s_first	= cpu_to_be32(1);
+
+	journal->j_transaction_sequence = 1;
+
+	journal->j_flags &= ~JBD2_ABORT;
+	journal->j_format_version = 2;
+
+	return journal_reset(journal);
+}
+
+/**
+ * void jbd2_journal_update_superblock() - Update journal sb on disk.
+ * @journal: The journal to update.
+ * @wait: Set to '0' if you don't want to wait for IO completion.
+ *
+ * Update a journal's dynamic superblock fields and write it to disk,
+ * optionally waiting for the IO to complete.
+ */
+void jbd2_journal_update_superblock(journal_t *journal, int wait)
+{
+	journal_superblock_t *sb = journal->j_superblock;
+	struct buffer_head *bh = journal->j_sb_buffer;
+
+	/*
+	 * As a special case, if the on-disk copy is already marked as needing
+	 * no recovery (s_start == 0) and there are no outstanding transactions
+	 * in the filesystem, then we can safely defer the superblock update
+	 * until the next commit by setting JBD2_FLUSHED.  This avoids
+	 * attempting a write to a potential-readonly device.
+	 */
+	if (sb->s_start == 0 && journal->j_tail_sequence ==
+				journal->j_transaction_sequence) {
+		jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
+			"(start %ld, seq %d, errno %d)\n",
+			journal->j_tail, journal->j_tail_sequence,
+			journal->j_errno);
+		goto out;
+	}
+
+	spin_lock(&journal->j_state_lock);
+	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
+		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
+
+	sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
+	sb->s_start    = cpu_to_be32(journal->j_tail);
+	sb->s_errno    = cpu_to_be32(journal->j_errno);
+	spin_unlock(&journal->j_state_lock);
+
+	BUFFER_TRACE(bh, "marking dirty");
+	mark_buffer_dirty(bh);
+	if (wait)
+		sync_dirty_buffer(bh);
+	else
+		ll_rw_block(SWRITE, 1, &bh);
+
+out:
+	/* If we have just flushed the log (by marking s_start==0), then
+	 * any future commit will have to be careful to update the
+	 * superblock again to re-record the true start of the log. */
+
+	spin_lock(&journal->j_state_lock);
+	if (sb->s_start)
+		journal->j_flags &= ~JBD2_FLUSHED;
+	else
+		journal->j_flags |= JBD2_FLUSHED;
+	spin_unlock(&journal->j_state_lock);
+}
+
+/*
+ * Read the superblock for a given journal, performing initial
+ * validation of the format.
+ */
+
+static int journal_get_superblock(journal_t *journal)
+{
+	struct buffer_head *bh;
+	journal_superblock_t *sb;
+	int err = -EIO;
+
+	bh = journal->j_sb_buffer;
+
+	J_ASSERT(bh != NULL);
+	if (!buffer_uptodate(bh)) {
+		ll_rw_block(READ, 1, &bh);
+		wait_on_buffer(bh);
+		if (!buffer_uptodate(bh)) {
+			printk (KERN_ERR
+				"JBD: IO error reading journal superblock\n");
+			goto out;
+		}
+	}
+
+	sb = journal->j_superblock;
+
+	err = -EINVAL;
+
+	if (sb->s_header.h_magic != cpu_to_be32(JBD2_MAGIC_NUMBER) ||
+	    sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) {
+		printk(KERN_WARNING "JBD: no valid journal superblock found\n");
+		goto out;
+	}
+
+	switch(be32_to_cpu(sb->s_header.h_blocktype)) {
+	case JBD2_SUPERBLOCK_V1:
+		journal->j_format_version = 1;
+		break;
+	case JBD2_SUPERBLOCK_V2:
+		journal->j_format_version = 2;
+		break;
+	default:
+		printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");
+		goto out;
+	}
+
+	if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)
+		journal->j_maxlen = be32_to_cpu(sb->s_maxlen);
+	else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {
+		printk (KERN_WARNING "JBD: journal file too short\n");
+		goto out;
+	}
+
+	return 0;
+
+out:
+	journal_fail_superblock(journal);
+	return err;
+}
+
+/*
+ * Load the on-disk journal superblock and read the key fields into the
+ * journal_t.
+ */
+
+static int load_superblock(journal_t *journal)
+{
+	int err;
+	journal_superblock_t *sb;
+
+	err = journal_get_superblock(journal);
+	if (err)
+		return err;
+
+	sb = journal->j_superblock;
+
+	journal->j_tail_sequence = be32_to_cpu(sb->s_sequence);
+	journal->j_tail = be32_to_cpu(sb->s_start);
+	journal->j_first = be32_to_cpu(sb->s_first);
+	journal->j_last = be32_to_cpu(sb->s_maxlen);
+	journal->j_errno = be32_to_cpu(sb->s_errno);
+
+	return 0;
+}
+
+
+/**
+ * int jbd2_journal_load() - Read journal from disk.
+ * @journal: Journal to act on.
+ *
+ * Given a journal_t structure which tells us which disk blocks contain
+ * a journal, read the journal from disk to initialise the in-memory
+ * structures.
+ */
+int jbd2_journal_load(journal_t *journal)
+{
+	int err;
+	journal_superblock_t *sb;
+
+	err = load_superblock(journal);
+	if (err)
+		return err;
+
+	sb = journal->j_superblock;
+	/* If this is a V2 superblock, then we have to check the
+	 * features flags on it. */
+
+	if (journal->j_format_version >= 2) {
+		if ((sb->s_feature_ro_compat &
+		     ~cpu_to_be32(JBD2_KNOWN_ROCOMPAT_FEATURES)) ||
+		    (sb->s_feature_incompat &
+		     ~cpu_to_be32(JBD2_KNOWN_INCOMPAT_FEATURES))) {
+			printk (KERN_WARNING
+				"JBD: Unrecognised features on journal\n");
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Create a slab for this blocksize
+	 */
+	err = jbd2_journal_create_jbd_slab(be32_to_cpu(sb->s_blocksize));
+	if (err)
+		return err;
+
+	/* Let the recovery code check whether it needs to recover any
+	 * data from the journal. */
+	if (jbd2_journal_recover(journal))
+		goto recovery_error;
+
+	/* OK, we've finished with the dynamic journal bits:
+	 * reinitialise the dynamic contents of the superblock in memory
+	 * and reset them on disk. */
+	if (journal_reset(journal))
+		goto recovery_error;
+
+	journal->j_flags &= ~JBD2_ABORT;
+	journal->j_flags |= JBD2_LOADED;
+	return 0;
+
+recovery_error:
+	printk (KERN_WARNING "JBD: recovery failed\n");
+	return -EIO;
+}
+
+/**
+ * void jbd2_journal_destroy() - Release a journal_t structure.
+ * @journal: Journal to act on.
+ *
+ * Release a journal_t structure once it is no longer in use by the
+ * journaled object.
+ */
+void jbd2_journal_destroy(journal_t *journal)
+{
+	/* Wait for the commit thread to wake up and die. */
+	journal_kill_thread(journal);
+
+	/* Force a final log commit */
+	if (journal->j_running_transaction)
+		jbd2_journal_commit_transaction(journal);
+
+	/* Force any old transactions to disk */
+
+	/* Totally anal locking here... */
+	spin_lock(&journal->j_list_lock);
+	while (journal->j_checkpoint_transactions != NULL) {
+		spin_unlock(&journal->j_list_lock);
+		jbd2_log_do_checkpoint(journal);
+		spin_lock(&journal->j_list_lock);
+	}
+
+	J_ASSERT(journal->j_running_transaction == NULL);
+	J_ASSERT(journal->j_committing_transaction == NULL);
+	J_ASSERT(journal->j_checkpoint_transactions == NULL);
+	spin_unlock(&journal->j_list_lock);
+
+	/* We can now mark the journal as empty. */
+	journal->j_tail = 0;
+	journal->j_tail_sequence = ++journal->j_transaction_sequence;
+	if (journal->j_sb_buffer) {
+		jbd2_journal_update_superblock(journal, 1);
+		brelse(journal->j_sb_buffer);
+	}
+
+	if (journal->j_inode)
+		iput(journal->j_inode);
+	if (journal->j_revoke)
+		jbd2_journal_destroy_revoke(journal);
+	kfree(journal->j_wbuf);
+	kfree(journal);
+}
+
+
+/**
+ *int jbd2_journal_check_used_features () - Check if features specified are used.
+ * @journal: Journal to check.
+ * @compat: bitmask of compatible features
+ * @ro: bitmask of features that force read-only mount
+ * @incompat: bitmask of incompatible features
+ *
+ * Check whether the journal uses all of a given set of
+ * features.  Return true (non-zero) if it does.
+ **/
+
+int jbd2_journal_check_used_features (journal_t *journal, unsigned long compat,
+				 unsigned long ro, unsigned long incompat)
+{
+	journal_superblock_t *sb;
+
+	if (!compat && !ro && !incompat)
+		return 1;
+	if (journal->j_format_version == 1)
+		return 0;
+
+	sb = journal->j_superblock;
+
+	if (((be32_to_cpu(sb->s_feature_compat) & compat) == compat) &&
+	    ((be32_to_cpu(sb->s_feature_ro_compat) & ro) == ro) &&
+	    ((be32_to_cpu(sb->s_feature_incompat) & incompat) == incompat))
+		return 1;
+
+	return 0;
+}
+
+/**
+ * int jbd2_journal_check_available_features() - Check feature set in journalling layer
+ * @journal: Journal to check.
+ * @compat: bitmask of compatible features
+ * @ro: bitmask of features that force read-only mount
+ * @incompat: bitmask of incompatible features
+ *
+ * Check whether the journaling code supports the use of
+ * all of a given set of features on this journal.  Return true
+ * (non-zero) if it can. */
+
+int jbd2_journal_check_available_features (journal_t *journal, unsigned long compat,
+				      unsigned long ro, unsigned long incompat)
+{
+	journal_superblock_t *sb;
+
+	if (!compat && !ro && !incompat)
+		return 1;
+
+	sb = journal->j_superblock;
+
+	/* We can support any known requested features iff the
+	 * superblock is in version 2.  Otherwise we fail to support any
+	 * extended sb features. */
+
+	if (journal->j_format_version != 2)
+		return 0;
+
+	if ((compat   & JBD2_KNOWN_COMPAT_FEATURES) == compat &&
+	    (ro       & JBD2_KNOWN_ROCOMPAT_FEATURES) == ro &&
+	    (incompat & JBD2_KNOWN_INCOMPAT_FEATURES) == incompat)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * int jbd2_journal_set_features () - Mark a given journal feature in the superblock
+ * @journal: Journal to act on.
+ * @compat: bitmask of compatible features
+ * @ro: bitmask of features that force read-only mount
+ * @incompat: bitmask of incompatible features
+ *
+ * Mark a given journal feature as present on the
+ * superblock.  Returns true if the requested features could be set.
+ *
+ */
+
+int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
+			  unsigned long ro, unsigned long incompat)
+{
+	journal_superblock_t *sb;
+
+	if (jbd2_journal_check_used_features(journal, compat, ro, incompat))
+		return 1;
+
+	if (!jbd2_journal_check_available_features(journal, compat, ro, incompat))
+		return 0;
+
+	jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",
+		  compat, ro, incompat);
+
+	sb = journal->j_superblock;
+
+	sb->s_feature_compat    |= cpu_to_be32(compat);
+	sb->s_feature_ro_compat |= cpu_to_be32(ro);
+	sb->s_feature_incompat  |= cpu_to_be32(incompat);
+
+	return 1;
+}
+
+
+/**
+ * int jbd2_journal_update_format () - Update on-disk journal structure.
+ * @journal: Journal to act on.
+ *
+ * Given an initialised but unloaded journal struct, poke about in the
+ * on-disk structure to update it to the most recent supported version.
+ */
+int jbd2_journal_update_format (journal_t *journal)
+{
+	journal_superblock_t *sb;
+	int err;
+
+	err = journal_get_superblock(journal);
+	if (err)
+		return err;
+
+	sb = journal->j_superblock;
+
+	switch (be32_to_cpu(sb->s_header.h_blocktype)) {
+	case JBD2_SUPERBLOCK_V2:
+		return 0;
+	case JBD2_SUPERBLOCK_V1:
+		return journal_convert_superblock_v1(journal, sb);
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int journal_convert_superblock_v1(journal_t *journal,
+					 journal_superblock_t *sb)
+{
+	int offset, blocksize;
+	struct buffer_head *bh;
+
+	printk(KERN_WARNING
+		"JBD: Converting superblock from version 1 to 2.\n");
+
+	/* Pre-initialise new fields to zero */
+	offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb);
+	blocksize = be32_to_cpu(sb->s_blocksize);
+	memset(&sb->s_feature_compat, 0, blocksize-offset);
+
+	sb->s_nr_users = cpu_to_be32(1);
+	sb->s_header.h_blocktype = cpu_to_be32(JBD2_SUPERBLOCK_V2);
+	journal->j_format_version = 2;
+
+	bh = journal->j_sb_buffer;
+	BUFFER_TRACE(bh, "marking dirty");
+	mark_buffer_dirty(bh);
+	sync_dirty_buffer(bh);
+	return 0;
+}
+
+
+/**
+ * int jbd2_journal_flush () - Flush journal
+ * @journal: Journal to act on.
+ *
+ * Flush all data for a given journal to disk and empty the journal.
+ * Filesystems can use this when remounting readonly to ensure that
+ * recovery does not need to happen on remount.
+ */
+
+int jbd2_journal_flush(journal_t *journal)
+{
+	int err = 0;
+	transaction_t *transaction = NULL;
+	unsigned long old_tail;
+
+	spin_lock(&journal->j_state_lock);
+
+	/* Force everything buffered to the log... */
+	if (journal->j_running_transaction) {
+		transaction = journal->j_running_transaction;
+		__jbd2_log_start_commit(journal, transaction->t_tid);
+	} else if (journal->j_committing_transaction)
+		transaction = journal->j_committing_transaction;
+
+	/* Wait for the log commit to complete... */
+	if (transaction) {
+		tid_t tid = transaction->t_tid;
+
+		spin_unlock(&journal->j_state_lock);
+		jbd2_log_wait_commit(journal, tid);
+	} else {
+		spin_unlock(&journal->j_state_lock);
+	}
+
+	/* ...and flush everything in the log out to disk. */
+	spin_lock(&journal->j_list_lock);
+	while (!err && journal->j_checkpoint_transactions != NULL) {
+		spin_unlock(&journal->j_list_lock);
+		err = jbd2_log_do_checkpoint(journal);
+		spin_lock(&journal->j_list_lock);
+	}
+	spin_unlock(&journal->j_list_lock);
+	jbd2_cleanup_journal_tail(journal);
+
+	/* Finally, mark the journal as really needing no recovery.
+	 * This sets s_start==0 in the underlying superblock, which is
+	 * the magic code for a fully-recovered superblock.  Any future
+	 * commits of data to the journal will restore the current
+	 * s_start value. */
+	spin_lock(&journal->j_state_lock);
+	old_tail = journal->j_tail;
+	journal->j_tail = 0;
+	spin_unlock(&journal->j_state_lock);
+	jbd2_journal_update_superblock(journal, 1);
+	spin_lock(&journal->j_state_lock);
+	journal->j_tail = old_tail;
+
+	J_ASSERT(!journal->j_running_transaction);
+	J_ASSERT(!journal->j_committing_transaction);
+	J_ASSERT(!journal->j_checkpoint_transactions);
+	J_ASSERT(journal->j_head == journal->j_tail);
+	J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
+	spin_unlock(&journal->j_state_lock);
+	return err;
+}
+
+/**
+ * int jbd2_journal_wipe() - Wipe journal contents
+ * @journal: Journal to act on.
+ * @write: flag (see below)
+ *
+ * Wipe out all of the contents of a journal, safely.  This will produce
+ * a warning if the journal contains any valid recovery information.
+ * Must be called between journal_init_*() and jbd2_journal_load().
+ *
+ * If 'write' is non-zero, then we wipe out the journal on disk; otherwise
+ * we merely suppress recovery.
+ */
+
+int jbd2_journal_wipe(journal_t *journal, int write)
+{
+	journal_superblock_t *sb;
+	int err = 0;
+
+	J_ASSERT (!(journal->j_flags & JBD2_LOADED));
+
+	err = load_superblock(journal);
+	if (err)
+		return err;
+
+	sb = journal->j_superblock;
+
+	if (!journal->j_tail)
+		goto no_recovery;
+
+	printk (KERN_WARNING "JBD: %s recovery information on journal\n",
+		write ? "Clearing" : "Ignoring");
+
+	err = jbd2_journal_skip_recovery(journal);
+	if (write)
+		jbd2_journal_update_superblock(journal, 1);
+
+ no_recovery:
+	return err;
+}
+
+/*
+ * journal_dev_name: format a character string to describe on what
+ * device this journal is present.
+ */
+
+static const char *journal_dev_name(journal_t *journal, char *buffer)
+{
+	struct block_device *bdev;
+
+	if (journal->j_inode)
+		bdev = journal->j_inode->i_sb->s_bdev;
+	else
+		bdev = journal->j_dev;
+
+	return bdevname(bdev, buffer);
+}
+
+/*
+ * Journal abort has very specific semantics, which we describe
+ * for journal abort.
+ *
+ * Two internal function, which provide abort to te jbd layer
+ * itself are here.
+ */
+
+/*
+ * Quick version for internal journal use (doesn't lock the journal).
+ * Aborts hard --- we mark the abort as occurred, but do _nothing_ else,
+ * and don't attempt to make any other journal updates.
+ */
+void __jbd2_journal_abort_hard(journal_t *journal)
+{
+	transaction_t *transaction;
+	char b[BDEVNAME_SIZE];
+
+	if (journal->j_flags & JBD2_ABORT)
+		return;
+
+	printk(KERN_ERR "Aborting journal on device %s.\n",
+		journal_dev_name(journal, b));
+
+	spin_lock(&journal->j_state_lock);
+	journal->j_flags |= JBD2_ABORT;
+	transaction = journal->j_running_transaction;
+	if (transaction)
+		__jbd2_log_start_commit(journal, transaction->t_tid);
+	spin_unlock(&journal->j_state_lock);
+}
+
+/* Soft abort: record the abort error status in the journal superblock,
+ * but don't do any other IO. */
+static void __journal_abort_soft (journal_t *journal, int errno)
+{
+	if (journal->j_flags & JBD2_ABORT)
+		return;
+
+	if (!journal->j_errno)
+		journal->j_errno = errno;
+
+	__jbd2_journal_abort_hard(journal);
+
+	if (errno)
+		jbd2_journal_update_superblock(journal, 1);
+}
+
+/**
+ * void jbd2_journal_abort () - Shutdown the journal immediately.
+ * @journal: the journal to shutdown.
+ * @errno:   an error number to record in the journal indicating
+ *           the reason for the shutdown.
+ *
+ * Perform a complete, immediate shutdown of the ENTIRE
+ * journal (not of a single transaction).  This operation cannot be
+ * undone without closing and reopening the journal.
+ *
+ * The jbd2_journal_abort function is intended to support higher level error
+ * recovery mechanisms such as the ext2/ext3 remount-readonly error
+ * mode.
+ *
+ * Journal abort has very specific semantics.  Any existing dirty,
+ * unjournaled buffers in the main filesystem will still be written to
+ * disk by bdflush, but the journaling mechanism will be suspended
+ * immediately and no further transaction commits will be honoured.
+ *
+ * Any dirty, journaled buffers will be written back to disk without
+ * hitting the journal.  Atomicity cannot be guaranteed on an aborted
+ * filesystem, but we _do_ attempt to leave as much data as possible
+ * behind for fsck to use for cleanup.
+ *
+ * Any attempt to get a new transaction handle on a journal which is in
+ * ABORT state will just result in an -EROFS error return.  A
+ * jbd2_journal_stop on an existing handle will return -EIO if we have
+ * entered abort state during the update.
+ *
+ * Recursive transactions are not disturbed by journal abort until the
+ * final jbd2_journal_stop, which will receive the -EIO error.
+ *
+ * Finally, the jbd2_journal_abort call allows the caller to supply an errno
+ * which will be recorded (if possible) in the journal superblock.  This
+ * allows a client to record failure conditions in the middle of a
+ * transaction without having to complete the transaction to record the
+ * failure to disk.  ext3_error, for example, now uses this
+ * functionality.
+ *
+ * Errors which originate from within the journaling layer will NOT
+ * supply an errno; a null errno implies that absolutely no further
+ * writes are done to the journal (unless there are any already in
+ * progress).
+ *
+ */
+
+void jbd2_journal_abort(journal_t *journal, int errno)
+{
+	__journal_abort_soft(journal, errno);
+}
+
+/**
+ * int jbd2_journal_errno () - returns the journal's error state.
+ * @journal: journal to examine.
+ *
+ * This is the errno numbet set with jbd2_journal_abort(), the last
+ * time the journal was mounted - if the journal was stopped
+ * without calling abort this will be 0.
+ *
+ * If the journal has been aborted on this mount time -EROFS will
+ * be returned.
+ */
+int jbd2_journal_errno(journal_t *journal)
+{
+	int err;
+
+	spin_lock(&journal->j_state_lock);
+	if (journal->j_flags & JBD2_ABORT)
+		err = -EROFS;
+	else
+		err = journal->j_errno;
+	spin_unlock(&journal->j_state_lock);
+	return err;
+}
+
+/**
+ * int jbd2_journal_clear_err () - clears the journal's error state
+ * @journal: journal to act on.
+ *
+ * An error must be cleared or Acked to take a FS out of readonly
+ * mode.
+ */
+int jbd2_journal_clear_err(journal_t *journal)
+{
+	int err = 0;
+
+	spin_lock(&journal->j_state_lock);
+	if (journal->j_flags & JBD2_ABORT)
+		err = -EROFS;
+	else
+		journal->j_errno = 0;
+	spin_unlock(&journal->j_state_lock);
+	return err;
+}
+
+/**
+ * void jbd2_journal_ack_err() - Ack journal err.
+ * @journal: journal to act on.
+ *
+ * An error must be cleared or Acked to take a FS out of readonly
+ * mode.
+ */
+void jbd2_journal_ack_err(journal_t *journal)
+{
+	spin_lock(&journal->j_state_lock);
+	if (journal->j_errno)
+		journal->j_flags |= JBD2_ACK_ERR;
+	spin_unlock(&journal->j_state_lock);
+}
+
+int jbd2_journal_blocks_per_page(struct inode *inode)
+{
+	return 1 << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+}
+
+/*
+ * helper functions to deal with 32 or 64bit block numbers.
+ */
+size_t journal_tag_bytes(journal_t *journal)
+{
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
+		return JBD_TAG_SIZE64;
+	else
+		return JBD_TAG_SIZE32;
+}
+
+/*
+ * Simple support for retrying memory allocations.  Introduced to help to
+ * debug different VM deadlock avoidance strategies.
+ */
+void * __jbd2_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
+{
+	return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0));
+}
+
+/*
+ * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed
+ * and allocate frozen and commit buffers from these slabs.
+ *
+ * Reason for doing this is to avoid, SLAB_DEBUG - since it could
+ * cause bh to cross page boundary.
+ */
+
+#define JBD_MAX_SLABS 5
+#define JBD_SLAB_INDEX(size)  (size >> 11)
+
+static kmem_cache_t *jbd_slab[JBD_MAX_SLABS];
+static const char *jbd_slab_names[JBD_MAX_SLABS] = {
+	"jbd2_1k", "jbd2_2k", "jbd2_4k", NULL, "jbd2_8k"
+};
+
+static void jbd2_journal_destroy_jbd_slabs(void)
+{
+	int i;
+
+	for (i = 0; i < JBD_MAX_SLABS; i++) {
+		if (jbd_slab[i])
+			kmem_cache_destroy(jbd_slab[i]);
+		jbd_slab[i] = NULL;
+	}
+}
+
+static int jbd2_journal_create_jbd_slab(size_t slab_size)
+{
+	int i = JBD_SLAB_INDEX(slab_size);
+
+	BUG_ON(i >= JBD_MAX_SLABS);
+
+	/*
+	 * Check if we already have a slab created for this size
+	 */
+	if (jbd_slab[i])
+		return 0;
+
+	/*
+	 * Create a slab and force alignment to be same as slabsize -
+	 * this will make sure that allocations won't cross the page
+	 * boundary.
+	 */
+	jbd_slab[i] = kmem_cache_create(jbd_slab_names[i],
+				slab_size, slab_size, 0, NULL, NULL);
+	if (!jbd_slab[i]) {
+		printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void * jbd2_slab_alloc(size_t size, gfp_t flags)
+{
+	int idx;
+
+	idx = JBD_SLAB_INDEX(size);
+	BUG_ON(jbd_slab[idx] == NULL);
+	return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
+}
+
+void jbd2_slab_free(void *ptr,  size_t size)
+{
+	int idx;
+
+	idx = JBD_SLAB_INDEX(size);
+	BUG_ON(jbd_slab[idx] == NULL);
+	kmem_cache_free(jbd_slab[idx], ptr);
+}
+
+/*
+ * Journal_head storage management
+ */
+static kmem_cache_t *jbd2_journal_head_cache;
+#ifdef CONFIG_JBD_DEBUG
+static atomic_t nr_journal_heads = ATOMIC_INIT(0);
+#endif
+
+static int journal_init_jbd2_journal_head_cache(void)
+{
+	int retval;
+
+	J_ASSERT(jbd2_journal_head_cache == 0);
+	jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head",
+				sizeof(struct journal_head),
+				0,		/* offset */
+				0,		/* flags */
+				NULL,		/* ctor */
+				NULL);		/* dtor */
+	retval = 0;
+	if (jbd2_journal_head_cache == 0) {
+		retval = -ENOMEM;
+		printk(KERN_EMERG "JBD: no memory for journal_head cache\n");
+	}
+	return retval;
+}
+
+static void jbd2_journal_destroy_jbd2_journal_head_cache(void)
+{
+	J_ASSERT(jbd2_journal_head_cache != NULL);
+	kmem_cache_destroy(jbd2_journal_head_cache);
+	jbd2_journal_head_cache = NULL;
+}
+
+/*
+ * journal_head splicing and dicing
+ */
+static struct journal_head *journal_alloc_journal_head(void)
+{
+	struct journal_head *ret;
+	static unsigned long last_warning;
+
+#ifdef CONFIG_JBD_DEBUG
+	atomic_inc(&nr_journal_heads);
+#endif
+	ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS);
+	if (ret == 0) {
+		jbd_debug(1, "out of memory for journal_head\n");
+		if (time_after(jiffies, last_warning + 5*HZ)) {
+			printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
+			       __FUNCTION__);
+			last_warning = jiffies;
+		}
+		while (ret == 0) {
+			yield();
+			ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS);
+		}
+	}
+	return ret;
+}
+
+static void journal_free_journal_head(struct journal_head *jh)
+{
+#ifdef CONFIG_JBD_DEBUG
+	atomic_dec(&nr_journal_heads);
+	memset(jh, JBD_POISON_FREE, sizeof(*jh));
+#endif
+	kmem_cache_free(jbd2_journal_head_cache, jh);
+}
+
+/*
+ * A journal_head is attached to a buffer_head whenever JBD has an
+ * interest in the buffer.
+ *
+ * Whenever a buffer has an attached journal_head, its ->b_state:BH_JBD bit
+ * is set.  This bit is tested in core kernel code where we need to take
+ * JBD-specific actions.  Testing the zeroness of ->b_private is not reliable
+ * there.
+ *
+ * When a buffer has its BH_JBD bit set, its ->b_count is elevated by one.
+ *
+ * When a buffer has its BH_JBD bit set it is immune from being released by
+ * core kernel code, mainly via ->b_count.
+ *
+ * A journal_head may be detached from its buffer_head when the journal_head's
+ * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL.
+ * Various places in JBD call jbd2_journal_remove_journal_head() to indicate that the
+ * journal_head can be dropped if needed.
+ *
+ * Various places in the kernel want to attach a journal_head to a buffer_head
+ * _before_ attaching the journal_head to a transaction.  To protect the
+ * journal_head in this situation, jbd2_journal_add_journal_head elevates the
+ * journal_head's b_jcount refcount by one.  The caller must call
+ * jbd2_journal_put_journal_head() to undo this.
+ *
+ * So the typical usage would be:
+ *
+ *	(Attach a journal_head if needed.  Increments b_jcount)
+ *	struct journal_head *jh = jbd2_journal_add_journal_head(bh);
+ *	...
+ *	jh->b_transaction = xxx;
+ *	jbd2_journal_put_journal_head(jh);
+ *
+ * Now, the journal_head's b_jcount is zero, but it is safe from being released
+ * because it has a non-zero b_transaction.
+ */
+
+/*
+ * Give a buffer_head a journal_head.
+ *
+ * Doesn't need the journal lock.
+ * May sleep.
+ */
+struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh)
+{
+	struct journal_head *jh;
+	struct journal_head *new_jh = NULL;
+
+repeat:
+	if (!buffer_jbd(bh)) {
+		new_jh = journal_alloc_journal_head();
+		memset(new_jh, 0, sizeof(*new_jh));
+	}
+
+	jbd_lock_bh_journal_head(bh);
+	if (buffer_jbd(bh)) {
+		jh = bh2jh(bh);
+	} else {
+		J_ASSERT_BH(bh,
+			(atomic_read(&bh->b_count) > 0) ||
+			(bh->b_page && bh->b_page->mapping));
+
+		if (!new_jh) {
+			jbd_unlock_bh_journal_head(bh);
+			goto repeat;
+		}
+
+		jh = new_jh;
+		new_jh = NULL;		/* We consumed it */
+		set_buffer_jbd(bh);
+		bh->b_private = jh;
+		jh->b_bh = bh;
+		get_bh(bh);
+		BUFFER_TRACE(bh, "added journal_head");
+	}
+	jh->b_jcount++;
+	jbd_unlock_bh_journal_head(bh);
+	if (new_jh)
+		journal_free_journal_head(new_jh);
+	return bh->b_private;
+}
+
+/*
+ * Grab a ref against this buffer_head's journal_head.  If it ended up not
+ * having a journal_head, return NULL
+ */
+struct journal_head *jbd2_journal_grab_journal_head(struct buffer_head *bh)
+{
+	struct journal_head *jh = NULL;
+
+	jbd_lock_bh_journal_head(bh);
+	if (buffer_jbd(bh)) {
+		jh = bh2jh(bh);
+		jh->b_jcount++;
+	}
+	jbd_unlock_bh_journal_head(bh);
+	return jh;
+}
+
+static void __journal_remove_journal_head(struct buffer_head *bh)
+{
+	struct journal_head *jh = bh2jh(bh);
+
+	J_ASSERT_JH(jh, jh->b_jcount >= 0);
+
+	get_bh(bh);
+	if (jh->b_jcount == 0) {
+		if (jh->b_transaction == NULL &&
+				jh->b_next_transaction == NULL &&
+				jh->b_cp_transaction == NULL) {
+			J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
+			J_ASSERT_BH(bh, buffer_jbd(bh));
+			J_ASSERT_BH(bh, jh2bh(jh) == bh);
+			BUFFER_TRACE(bh, "remove journal_head");
+			if (jh->b_frozen_data) {
+				printk(KERN_WARNING "%s: freeing "
+						"b_frozen_data\n",
+						__FUNCTION__);
+				jbd2_slab_free(jh->b_frozen_data, bh->b_size);
+			}
+			if (jh->b_committed_data) {
+				printk(KERN_WARNING "%s: freeing "
+						"b_committed_data\n",
+						__FUNCTION__);
+				jbd2_slab_free(jh->b_committed_data, bh->b_size);
+			}
+			bh->b_private = NULL;
+			jh->b_bh = NULL;	/* debug, really */
+			clear_buffer_jbd(bh);
+			__brelse(bh);
+			journal_free_journal_head(jh);
+		} else {
+			BUFFER_TRACE(bh, "journal_head was locked");
+		}
+	}
+}
+
+/*
+ * jbd2_journal_remove_journal_head(): if the buffer isn't attached to a transaction
+ * and has a zero b_jcount then remove and release its journal_head.   If we did
+ * see that the buffer is not used by any transaction we also "logically"
+ * decrement ->b_count.
+ *
+ * We in fact take an additional increment on ->b_count as a convenience,
+ * because the caller usually wants to do additional things with the bh
+ * after calling here.
+ * The caller of jbd2_journal_remove_journal_head() *must* run __brelse(bh) at some
+ * time.  Once the caller has run __brelse(), the buffer is eligible for
+ * reaping by try_to_free_buffers().
+ */
+void jbd2_journal_remove_journal_head(struct buffer_head *bh)
+{
+	jbd_lock_bh_journal_head(bh);
+	__journal_remove_journal_head(bh);
+	jbd_unlock_bh_journal_head(bh);
+}
+
+/*
+ * Drop a reference on the passed journal_head.  If it fell to zero then try to
+ * release the journal_head from the buffer_head.
+ */
+void jbd2_journal_put_journal_head(struct journal_head *jh)
+{
+	struct buffer_head *bh = jh2bh(jh);
+
+	jbd_lock_bh_journal_head(bh);
+	J_ASSERT_JH(jh, jh->b_jcount > 0);
+	--jh->b_jcount;
+	if (!jh->b_jcount && !jh->b_transaction) {
+		__journal_remove_journal_head(bh);
+		__brelse(bh);
+	}
+	jbd_unlock_bh_journal_head(bh);
+}
+
+/*
+ * /proc tunables
+ */
+#if defined(CONFIG_JBD_DEBUG)
+int jbd2_journal_enable_debug;
+EXPORT_SYMBOL(jbd2_journal_enable_debug);
+#endif
+
+#if defined(CONFIG_JBD_DEBUG) && defined(CONFIG_PROC_FS)
+
+static struct proc_dir_entry *proc_jbd_debug;
+
+static int read_jbd_debug(char *page, char **start, off_t off,
+			  int count, int *eof, void *data)
+{
+	int ret;
+
+	ret = sprintf(page + off, "%d\n", jbd2_journal_enable_debug);
+	*eof = 1;
+	return ret;
+}
+
+static int write_jbd_debug(struct file *file, const char __user *buffer,
+			   unsigned long count, void *data)
+{
+	char buf[32];
+
+	if (count > ARRAY_SIZE(buf) - 1)
+		count = ARRAY_SIZE(buf) - 1;
+	if (copy_from_user(buf, buffer, count))
+		return -EFAULT;
+	buf[ARRAY_SIZE(buf) - 1] = '\0';
+	jbd2_journal_enable_debug = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+
+#define JBD_PROC_NAME "sys/fs/jbd2-debug"
+
+static void __init create_jbd_proc_entry(void)
+{
+	proc_jbd_debug = create_proc_entry(JBD_PROC_NAME, 0644, NULL);
+	if (proc_jbd_debug) {
+		/* Why is this so hard? */
+		proc_jbd_debug->read_proc = read_jbd_debug;
+		proc_jbd_debug->write_proc = write_jbd_debug;
+	}
+}
+
+static void __exit jbd2_remove_jbd_proc_entry(void)
+{
+	if (proc_jbd_debug)
+		remove_proc_entry(JBD_PROC_NAME, NULL);
+}
+
+#else
+
+#define create_jbd_proc_entry() do {} while (0)
+#define jbd2_remove_jbd_proc_entry() do {} while (0)
+
+#endif
+
+kmem_cache_t *jbd2_handle_cache;
+
+static int __init journal_init_handle_cache(void)
+{
+	jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle",
+				sizeof(handle_t),
+				0,		/* offset */
+				0,		/* flags */
+				NULL,		/* ctor */
+				NULL);		/* dtor */
+	if (jbd2_handle_cache == NULL) {
+		printk(KERN_EMERG "JBD: failed to create handle cache\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void jbd2_journal_destroy_handle_cache(void)
+{
+	if (jbd2_handle_cache)
+		kmem_cache_destroy(jbd2_handle_cache);
+}
+
+/*
+ * Module startup and shutdown
+ */
+
+static int __init journal_init_caches(void)
+{
+	int ret;
+
+	ret = jbd2_journal_init_revoke_caches();
+	if (ret == 0)
+		ret = journal_init_jbd2_journal_head_cache();
+	if (ret == 0)
+		ret = journal_init_handle_cache();
+	return ret;
+}
+
+static void jbd2_journal_destroy_caches(void)
+{
+	jbd2_journal_destroy_revoke_caches();
+	jbd2_journal_destroy_jbd2_journal_head_cache();
+	jbd2_journal_destroy_handle_cache();
+	jbd2_journal_destroy_jbd_slabs();
+}
+
+static int __init journal_init(void)
+{
+	int ret;
+
+	BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024);
+
+	ret = journal_init_caches();
+	if (ret != 0)
+		jbd2_journal_destroy_caches();
+	create_jbd_proc_entry();
+	return ret;
+}
+
+static void __exit journal_exit(void)
+{
+#ifdef CONFIG_JBD_DEBUG
+	int n = atomic_read(&nr_journal_heads);
+	if (n)
+		printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n);
+#endif
+	jbd2_remove_jbd_proc_entry();
+	jbd2_journal_destroy_caches();
+}
+
+MODULE_LICENSE("GPL");
+module_init(journal_init);
+module_exit(journal_exit);
+
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
new file mode 100644
index 0000000..9f10aca
--- /dev/null
+++ b/fs/jbd2/recovery.c
@@ -0,0 +1,609 @@
+/*
+ * linux/fs/recovery.c
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
+ *
+ * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Journal recovery routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ */
+
+#ifndef __KERNEL__
+#include "jfs_user.h"
+#else
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#endif
+
+/*
+ * Maintain information about the progress of the recovery job, so that
+ * the different passes can carry information between them.
+ */
+struct recovery_info
+{
+	tid_t		start_transaction;
+	tid_t		end_transaction;
+
+	int		nr_replays;
+	int		nr_revokes;
+	int		nr_revoke_hits;
+};
+
+enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
+static int do_one_pass(journal_t *journal,
+				struct recovery_info *info, enum passtype pass);
+static int scan_revoke_records(journal_t *, struct buffer_head *,
+				tid_t, struct recovery_info *);
+
+#ifdef __KERNEL__
+
+/* Release readahead buffers after use */
+static void journal_brelse_array(struct buffer_head *b[], int n)
+{
+	while (--n >= 0)
+		brelse (b[n]);
+}
+
+
+/*
+ * When reading from the journal, we are going through the block device
+ * layer directly and so there is no readahead being done for us.  We
+ * need to implement any readahead ourselves if we want it to happen at
+ * all.  Recovery is basically one long sequential read, so make sure we
+ * do the IO in reasonably large chunks.
+ *
+ * This is not so critical that we need to be enormously clever about
+ * the readahead size, though.  128K is a purely arbitrary, good-enough
+ * fixed value.
+ */
+
+#define MAXBUF 8
+static int do_readahead(journal_t *journal, unsigned int start)
+{
+	int err;
+	unsigned int max, nbufs, next;
+	unsigned long long blocknr;
+	struct buffer_head *bh;
+
+	struct buffer_head * bufs[MAXBUF];
+
+	/* Do up to 128K of readahead */
+	max = start + (128 * 1024 / journal->j_blocksize);
+	if (max > journal->j_maxlen)
+		max = journal->j_maxlen;
+
+	/* Do the readahead itself.  We'll submit MAXBUF buffer_heads at
+	 * a time to the block device IO layer. */
+
+	nbufs = 0;
+
+	for (next = start; next < max; next++) {
+		err = jbd2_journal_bmap(journal, next, &blocknr);
+
+		if (err) {
+			printk (KERN_ERR "JBD: bad block at offset %u\n",
+				next);
+			goto failed;
+		}
+
+		bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+		if (!bh) {
+			err = -ENOMEM;
+			goto failed;
+		}
+
+		if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
+			bufs[nbufs++] = bh;
+			if (nbufs == MAXBUF) {
+				ll_rw_block(READ, nbufs, bufs);
+				journal_brelse_array(bufs, nbufs);
+				nbufs = 0;
+			}
+		} else
+			brelse(bh);
+	}
+
+	if (nbufs)
+		ll_rw_block(READ, nbufs, bufs);
+	err = 0;
+
+failed:
+	if (nbufs)
+		journal_brelse_array(bufs, nbufs);
+	return err;
+}
+
+#endif /* __KERNEL__ */
+
+
+/*
+ * Read a block from the journal
+ */
+
+static int jread(struct buffer_head **bhp, journal_t *journal,
+		 unsigned int offset)
+{
+	int err;
+	unsigned long long blocknr;
+	struct buffer_head *bh;
+
+	*bhp = NULL;
+
+	if (offset >= journal->j_maxlen) {
+		printk(KERN_ERR "JBD: corrupted journal superblock\n");
+		return -EIO;
+	}
+
+	err = jbd2_journal_bmap(journal, offset, &blocknr);
+
+	if (err) {
+		printk (KERN_ERR "JBD: bad block at offset %u\n",
+			offset);
+		return err;
+	}
+
+	bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+	if (!bh)
+		return -ENOMEM;
+
+	if (!buffer_uptodate(bh)) {
+		/* If this is a brand new buffer, start readahead.
+                   Otherwise, we assume we are already reading it.  */
+		if (!buffer_req(bh))
+			do_readahead(journal, offset);
+		wait_on_buffer(bh);
+	}
+
+	if (!buffer_uptodate(bh)) {
+		printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
+			offset);
+		brelse(bh);
+		return -EIO;
+	}
+
+	*bhp = bh;
+	return 0;
+}
+
+
+/*
+ * Count the number of in-use tags in a journal descriptor block.
+ */
+
+static int count_tags(journal_t *journal, struct buffer_head *bh)
+{
+	char *			tagp;
+	journal_block_tag_t *	tag;
+	int			nr = 0, size = journal->j_blocksize;
+	int			tag_bytes = journal_tag_bytes(journal);
+
+	tagp = &bh->b_data[sizeof(journal_header_t)];
+
+	while ((tagp - bh->b_data + tag_bytes) <= size) {
+		tag = (journal_block_tag_t *) tagp;
+
+		nr++;
+		tagp += tag_bytes;
+		if (!(tag->t_flags & cpu_to_be32(JBD2_FLAG_SAME_UUID)))
+			tagp += 16;
+
+		if (tag->t_flags & cpu_to_be32(JBD2_FLAG_LAST_TAG))
+			break;
+	}
+
+	return nr;
+}
+
+
+/* Make sure we wrap around the log correctly! */
+#define wrap(journal, var)						\
+do {									\
+	if (var >= (journal)->j_last)					\
+		var -= ((journal)->j_last - (journal)->j_first);	\
+} while (0)
+
+/**
+ * jbd2_journal_recover - recovers a on-disk journal
+ * @journal: the journal to recover
+ *
+ * The primary function for recovering the log contents when mounting a
+ * journaled device.
+ *
+ * Recovery is done in three passes.  In the first pass, we look for the
+ * end of the log.  In the second, we assemble the list of revoke
+ * blocks.  In the third and final pass, we replay any un-revoked blocks
+ * in the log.
+ */
+int jbd2_journal_recover(journal_t *journal)
+{
+	int			err;
+	journal_superblock_t *	sb;
+
+	struct recovery_info	info;
+
+	memset(&info, 0, sizeof(info));
+	sb = journal->j_superblock;
+
+	/*
+	 * The journal superblock's s_start field (the current log head)
+	 * is always zero if, and only if, the journal was cleanly
+	 * unmounted.
+	 */
+
+	if (!sb->s_start) {
+		jbd_debug(1, "No recovery required, last transaction %d\n",
+			  be32_to_cpu(sb->s_sequence));
+		journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
+		return 0;
+	}
+
+	err = do_one_pass(journal, &info, PASS_SCAN);
+	if (!err)
+		err = do_one_pass(journal, &info, PASS_REVOKE);
+	if (!err)
+		err = do_one_pass(journal, &info, PASS_REPLAY);
+
+	jbd_debug(0, "JBD: recovery, exit status %d, "
+		  "recovered transactions %u to %u\n",
+		  err, info.start_transaction, info.end_transaction);
+	jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
+		  info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
+
+	/* Restart the log at the next transaction ID, thus invalidating
+	 * any existing commit records in the log. */
+	journal->j_transaction_sequence = ++info.end_transaction;
+
+	jbd2_journal_clear_revoke(journal);
+	sync_blockdev(journal->j_fs_dev);
+	return err;
+}
+
+/**
+ * jbd2_journal_skip_recovery - Start journal and wipe exiting records
+ * @journal: journal to startup
+ *
+ * Locate any valid recovery information from the journal and set up the
+ * journal structures in memory to ignore it (presumably because the
+ * caller has evidence that it is out of date).
+ * This function does'nt appear to be exorted..
+ *
+ * We perform one pass over the journal to allow us to tell the user how
+ * much recovery information is being erased, and to let us initialise
+ * the journal transaction sequence numbers to the next unused ID.
+ */
+int jbd2_journal_skip_recovery(journal_t *journal)
+{
+	int			err;
+	journal_superblock_t *	sb;
+
+	struct recovery_info	info;
+
+	memset (&info, 0, sizeof(info));
+	sb = journal->j_superblock;
+
+	err = do_one_pass(journal, &info, PASS_SCAN);
+
+	if (err) {
+		printk(KERN_ERR "JBD: error %d scanning journal\n", err);
+		++journal->j_transaction_sequence;
+	} else {
+#ifdef CONFIG_JBD_DEBUG
+		int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
+#endif
+		jbd_debug(0,
+			  "JBD: ignoring %d transaction%s from the journal.\n",
+			  dropped, (dropped == 1) ? "" : "s");
+		journal->j_transaction_sequence = ++info.end_transaction;
+	}
+
+	journal->j_tail = 0;
+	return err;
+}
+
+static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag)
+{
+	unsigned long long block = be32_to_cpu(tag->t_blocknr);
+	if (tag_bytes > JBD_TAG_SIZE32)
+		block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32;
+	return block;
+}
+
+static int do_one_pass(journal_t *journal,
+			struct recovery_info *info, enum passtype pass)
+{
+	unsigned int		first_commit_ID, next_commit_ID;
+	unsigned long		next_log_block;
+	int			err, success = 0;
+	journal_superblock_t *	sb;
+	journal_header_t *	tmp;
+	struct buffer_head *	bh;
+	unsigned int		sequence;
+	int			blocktype;
+	int			tag_bytes = journal_tag_bytes(journal);
+
+	/* Precompute the maximum metadata descriptors in a descriptor block */
+	int			MAX_BLOCKS_PER_DESC;
+	MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
+			       / tag_bytes);
+
+	/*
+	 * First thing is to establish what we expect to find in the log
+	 * (in terms of transaction IDs), and where (in terms of log
+	 * block offsets): query the superblock.
+	 */
+
+	sb = journal->j_superblock;
+	next_commit_ID = be32_to_cpu(sb->s_sequence);
+	next_log_block = be32_to_cpu(sb->s_start);
+
+	first_commit_ID = next_commit_ID;
+	if (pass == PASS_SCAN)
+		info->start_transaction = first_commit_ID;
+
+	jbd_debug(1, "Starting recovery pass %d\n", pass);
+
+	/*
+	 * Now we walk through the log, transaction by transaction,
+	 * making sure that each transaction has a commit block in the
+	 * expected place.  Each complete transaction gets replayed back
+	 * into the main filesystem.
+	 */
+
+	while (1) {
+		int			flags;
+		char *			tagp;
+		journal_block_tag_t *	tag;
+		struct buffer_head *	obh;
+		struct buffer_head *	nbh;
+
+		cond_resched();		/* We're under lock_kernel() */
+
+		/* If we already know where to stop the log traversal,
+		 * check right now that we haven't gone past the end of
+		 * the log. */
+
+		if (pass != PASS_SCAN)
+			if (tid_geq(next_commit_ID, info->end_transaction))
+				break;
+
+		jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
+			  next_commit_ID, next_log_block, journal->j_last);
+
+		/* Skip over each chunk of the transaction looking
+		 * either the next descriptor block or the final commit
+		 * record. */
+
+		jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
+		err = jread(&bh, journal, next_log_block);
+		if (err)
+			goto failed;
+
+		next_log_block++;
+		wrap(journal, next_log_block);
+
+		/* What kind of buffer is it?
+		 *
+		 * If it is a descriptor block, check that it has the
+		 * expected sequence number.  Otherwise, we're all done
+		 * here. */
+
+		tmp = (journal_header_t *)bh->b_data;
+
+		if (tmp->h_magic != cpu_to_be32(JBD2_MAGIC_NUMBER)) {
+			brelse(bh);
+			break;
+		}
+
+		blocktype = be32_to_cpu(tmp->h_blocktype);
+		sequence = be32_to_cpu(tmp->h_sequence);
+		jbd_debug(3, "Found magic %d, sequence %d\n",
+			  blocktype, sequence);
+
+		if (sequence != next_commit_ID) {
+			brelse(bh);
+			break;
+		}
+
+		/* OK, we have a valid descriptor block which matches
+		 * all of the sequence number checks.  What are we going
+		 * to do with it?  That depends on the pass... */
+
+		switch(blocktype) {
+		case JBD2_DESCRIPTOR_BLOCK:
+			/* If it is a valid descriptor block, replay it
+			 * in pass REPLAY; otherwise, just skip over the
+			 * blocks it describes. */
+			if (pass != PASS_REPLAY) {
+				next_log_block += count_tags(journal, bh);
+				wrap(journal, next_log_block);
+				brelse(bh);
+				continue;
+			}
+
+			/* A descriptor block: we can now write all of
+			 * the data blocks.  Yay, useful work is finally
+			 * getting done here! */
+
+			tagp = &bh->b_data[sizeof(journal_header_t)];
+			while ((tagp - bh->b_data + tag_bytes)
+			       <= journal->j_blocksize) {
+				unsigned long io_block;
+
+				tag = (journal_block_tag_t *) tagp;
+				flags = be32_to_cpu(tag->t_flags);
+
+				io_block = next_log_block++;
+				wrap(journal, next_log_block);
+				err = jread(&obh, journal, io_block);
+				if (err) {
+					/* Recover what we can, but
+					 * report failure at the end. */
+					success = err;
+					printk (KERN_ERR
+						"JBD: IO error %d recovering "
+						"block %ld in log\n",
+						err, io_block);
+				} else {
+					unsigned long long blocknr;
+
+					J_ASSERT(obh != NULL);
+					blocknr = read_tag_block(tag_bytes,
+								 tag);
+
+					/* If the block has been
+					 * revoked, then we're all done
+					 * here. */
+					if (jbd2_journal_test_revoke
+					    (journal, blocknr,
+					     next_commit_ID)) {
+						brelse(obh);
+						++info->nr_revoke_hits;
+						goto skip_write;
+					}
+
+					/* Find a buffer for the new
+					 * data being restored */
+					nbh = __getblk(journal->j_fs_dev,
+							blocknr,
+							journal->j_blocksize);
+					if (nbh == NULL) {
+						printk(KERN_ERR
+						       "JBD: Out of memory "
+						       "during recovery.\n");
+						err = -ENOMEM;
+						brelse(bh);
+						brelse(obh);
+						goto failed;
+					}
+
+					lock_buffer(nbh);
+					memcpy(nbh->b_data, obh->b_data,
+							journal->j_blocksize);
+					if (flags & JBD2_FLAG_ESCAPE) {
+						*((__be32 *)bh->b_data) =
+						cpu_to_be32(JBD2_MAGIC_NUMBER);
+					}
+
+					BUFFER_TRACE(nbh, "marking dirty");
+					set_buffer_uptodate(nbh);
+					mark_buffer_dirty(nbh);
+					BUFFER_TRACE(nbh, "marking uptodate");
+					++info->nr_replays;
+					/* ll_rw_block(WRITE, 1, &nbh); */
+					unlock_buffer(nbh);
+					brelse(obh);
+					brelse(nbh);
+				}
+
+			skip_write:
+				tagp += tag_bytes;
+				if (!(flags & JBD2_FLAG_SAME_UUID))
+					tagp += 16;
+
+				if (flags & JBD2_FLAG_LAST_TAG)
+					break;
+			}
+
+			brelse(bh);
+			continue;
+
+		case JBD2_COMMIT_BLOCK:
+			/* Found an expected commit block: not much to
+			 * do other than move on to the next sequence
+			 * number. */
+			brelse(bh);
+			next_commit_ID++;
+			continue;
+
+		case JBD2_REVOKE_BLOCK:
+			/* If we aren't in the REVOKE pass, then we can
+			 * just skip over this block. */
+			if (pass != PASS_REVOKE) {
+				brelse(bh);
+				continue;
+			}
+
+			err = scan_revoke_records(journal, bh,
+						  next_commit_ID, info);
+			brelse(bh);
+			if (err)
+				goto failed;
+			continue;
+
+		default:
+			jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
+				  blocktype);
+			brelse(bh);
+			goto done;
+		}
+	}
+
+ done:
+	/*
+	 * We broke out of the log scan loop: either we came to the
+	 * known end of the log or we found an unexpected block in the
+	 * log.  If the latter happened, then we know that the "current"
+	 * transaction marks the end of the valid log.
+	 */
+
+	if (pass == PASS_SCAN)
+		info->end_transaction = next_commit_ID;
+	else {
+		/* It's really bad news if different passes end up at
+		 * different places (but possible due to IO errors). */
+		if (info->end_transaction != next_commit_ID) {
+			printk (KERN_ERR "JBD: recovery pass %d ended at "
+				"transaction %u, expected %u\n",
+				pass, next_commit_ID, info->end_transaction);
+			if (!success)
+				success = -EIO;
+		}
+	}
+
+	return success;
+
+ failed:
+	return err;
+}
+
+
+/* Scan a revoke record, marking all blocks mentioned as revoked. */
+
+static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
+			       tid_t sequence, struct recovery_info *info)
+{
+	jbd2_journal_revoke_header_t *header;
+	int offset, max;
+	int record_len = 4;
+
+	header = (jbd2_journal_revoke_header_t *) bh->b_data;
+	offset = sizeof(jbd2_journal_revoke_header_t);
+	max = be32_to_cpu(header->r_count);
+
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
+		record_len = 8;
+
+	while (offset + record_len <= max) {
+		unsigned long long blocknr;
+		int err;
+
+		if (record_len == 4)
+			blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset)));
+		else
+			blocknr = be64_to_cpu(* ((__be64 *) (bh->b_data+offset)));
+		offset += record_len;
+		err = jbd2_journal_set_revoke(journal, blocknr, sequence);
+		if (err)
+			return err;
+		++info->nr_revokes;
+	}
+	return 0;
+}
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
new file mode 100644
index 0000000..380d199
--- /dev/null
+++ b/fs/jbd2/revoke.c
@@ -0,0 +1,712 @@
+/*
+ * linux/fs/revoke.c
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
+ *
+ * Copyright 2000 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Journal revoke routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ *
+ * Revoke is the mechanism used to prevent old log records for deleted
+ * metadata from being replayed on top of newer data using the same
+ * blocks.  The revoke mechanism is used in two separate places:
+ *
+ * + Commit: during commit we write the entire list of the current
+ *   transaction's revoked blocks to the journal
+ *
+ * + Recovery: during recovery we record the transaction ID of all
+ *   revoked blocks.  If there are multiple revoke records in the log
+ *   for a single block, only the last one counts, and if there is a log
+ *   entry for a block beyond the last revoke, then that log entry still
+ *   gets replayed.
+ *
+ * We can get interactions between revokes and new log data within a
+ * single transaction:
+ *
+ * Block is revoked and then journaled:
+ *   The desired end result is the journaling of the new block, so we
+ *   cancel the revoke before the transaction commits.
+ *
+ * Block is journaled and then revoked:
+ *   The revoke must take precedence over the write of the block, so we
+ *   need either to cancel the journal entry or to write the revoke
+ *   later in the log than the log block.  In this case, we choose the
+ *   latter: journaling a block cancels any revoke record for that block
+ *   in the current transaction, so any revoke for that block in the
+ *   transaction must have happened after the block was journaled and so
+ *   the revoke must take precedence.
+ *
+ * Block is revoked and then written as data:
+ *   The data write is allowed to succeed, but the revoke is _not_
+ *   cancelled.  We still need to prevent old log records from
+ *   overwriting the new data.  We don't even need to clear the revoke
+ *   bit here.
+ *
+ * Revoke information on buffers is a tri-state value:
+ *
+ * RevokeValid clear:	no cached revoke status, need to look it up
+ * RevokeValid set, Revoked clear:
+ *			buffer has not been revoked, and cancel_revoke
+ *			need do nothing.
+ * RevokeValid set, Revoked set:
+ *			buffer has been revoked.
+ */
+
+#ifndef __KERNEL__
+#include "jfs_user.h"
+#else
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#endif
+
+static kmem_cache_t *jbd2_revoke_record_cache;
+static kmem_cache_t *jbd2_revoke_table_cache;
+
+/* Each revoke record represents one single revoked block.  During
+   journal replay, this involves recording the transaction ID of the
+   last transaction to revoke this block. */
+
+struct jbd2_revoke_record_s
+{
+	struct list_head  hash;
+	tid_t		  sequence;	/* Used for recovery only */
+	unsigned long long	  blocknr;
+};
+
+
+/* The revoke table is just a simple hash table of revoke records. */
+struct jbd2_revoke_table_s
+{
+	/* It is conceivable that we might want a larger hash table
+	 * for recovery.  Must be a power of two. */
+	int		  hash_size;
+	int		  hash_shift;
+	struct list_head *hash_table;
+};
+
+
+#ifdef __KERNEL__
+static void write_one_revoke_record(journal_t *, transaction_t *,
+				    struct journal_head **, int *,
+				    struct jbd2_revoke_record_s *);
+static void flush_descriptor(journal_t *, struct journal_head *, int);
+#endif
+
+/* Utility functions to maintain the revoke table */
+
+/* Borrowed from buffer.c: this is a tried and tested block hash function */
+static inline int hash(journal_t *journal, unsigned long long block)
+{
+	struct jbd2_revoke_table_s *table = journal->j_revoke;
+	int hash_shift = table->hash_shift;
+	int hash = (int)block ^ (int)((block >> 31) >> 1);
+
+	return ((hash << (hash_shift - 6)) ^
+		(hash >> 13) ^
+		(hash << (hash_shift - 12))) & (table->hash_size - 1);
+}
+
+static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,
+			      tid_t seq)
+{
+	struct list_head *hash_list;
+	struct jbd2_revoke_record_s *record;
+
+repeat:
+	record = kmem_cache_alloc(jbd2_revoke_record_cache, GFP_NOFS);
+	if (!record)
+		goto oom;
+
+	record->sequence = seq;
+	record->blocknr = blocknr;
+	hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+	spin_lock(&journal->j_revoke_lock);
+	list_add(&record->hash, hash_list);
+	spin_unlock(&journal->j_revoke_lock);
+	return 0;
+
+oom:
+	if (!journal_oom_retry)
+		return -ENOMEM;
+	jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__);
+	yield();
+	goto repeat;
+}
+
+/* Find a revoke record in the journal's hash table. */
+
+static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal,
+						      unsigned long long blocknr)
+{
+	struct list_head *hash_list;
+	struct jbd2_revoke_record_s *record;
+
+	hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+
+	spin_lock(&journal->j_revoke_lock);
+	record = (struct jbd2_revoke_record_s *) hash_list->next;
+	while (&(record->hash) != hash_list) {
+		if (record->blocknr == blocknr) {
+			spin_unlock(&journal->j_revoke_lock);
+			return record;
+		}
+		record = (struct jbd2_revoke_record_s *) record->hash.next;
+	}
+	spin_unlock(&journal->j_revoke_lock);
+	return NULL;
+}
+
+int __init jbd2_journal_init_revoke_caches(void)
+{
+	jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record",
+					   sizeof(struct jbd2_revoke_record_s),
+					   0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (jbd2_revoke_record_cache == 0)
+		return -ENOMEM;
+
+	jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table",
+					   sizeof(struct jbd2_revoke_table_s),
+					   0, 0, NULL, NULL);
+	if (jbd2_revoke_table_cache == 0) {
+		kmem_cache_destroy(jbd2_revoke_record_cache);
+		jbd2_revoke_record_cache = NULL;
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void jbd2_journal_destroy_revoke_caches(void)
+{
+	kmem_cache_destroy(jbd2_revoke_record_cache);
+	jbd2_revoke_record_cache = NULL;
+	kmem_cache_destroy(jbd2_revoke_table_cache);
+	jbd2_revoke_table_cache = NULL;
+}
+
+/* Initialise the revoke table for a given journal to a given size. */
+
+int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
+{
+	int shift, tmp;
+
+	J_ASSERT (journal->j_revoke_table[0] == NULL);
+
+	shift = 0;
+	tmp = hash_size;
+	while((tmp >>= 1UL) != 0UL)
+		shift++;
+
+	journal->j_revoke_table[0] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
+	if (!journal->j_revoke_table[0])
+		return -ENOMEM;
+	journal->j_revoke = journal->j_revoke_table[0];
+
+	/* Check that the hash_size is a power of two */
+	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+
+	journal->j_revoke->hash_size = hash_size;
+
+	journal->j_revoke->hash_shift = shift;
+
+	journal->j_revoke->hash_table =
+		kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+	if (!journal->j_revoke->hash_table) {
+		kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
+		journal->j_revoke = NULL;
+		return -ENOMEM;
+	}
+
+	for (tmp = 0; tmp < hash_size; tmp++)
+		INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+
+	journal->j_revoke_table[1] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
+	if (!journal->j_revoke_table[1]) {
+		kfree(journal->j_revoke_table[0]->hash_table);
+		kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
+		return -ENOMEM;
+	}
+
+	journal->j_revoke = journal->j_revoke_table[1];
+
+	/* Check that the hash_size is a power of two */
+	J_ASSERT ((hash_size & (hash_size-1)) == 0);
+
+	journal->j_revoke->hash_size = hash_size;
+
+	journal->j_revoke->hash_shift = shift;
+
+	journal->j_revoke->hash_table =
+		kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+	if (!journal->j_revoke->hash_table) {
+		kfree(journal->j_revoke_table[0]->hash_table);
+		kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
+		kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[1]);
+		journal->j_revoke = NULL;
+		return -ENOMEM;
+	}
+
+	for (tmp = 0; tmp < hash_size; tmp++)
+		INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+
+	spin_lock_init(&journal->j_revoke_lock);
+
+	return 0;
+}
+
+/* Destoy a journal's revoke table.  The table must already be empty! */
+
+void jbd2_journal_destroy_revoke(journal_t *journal)
+{
+	struct jbd2_revoke_table_s *table;
+	struct list_head *hash_list;
+	int i;
+
+	table = journal->j_revoke_table[0];
+	if (!table)
+		return;
+
+	for (i=0; i<table->hash_size; i++) {
+		hash_list = &table->hash_table[i];
+		J_ASSERT (list_empty(hash_list));
+	}
+
+	kfree(table->hash_table);
+	kmem_cache_free(jbd2_revoke_table_cache, table);
+	journal->j_revoke = NULL;
+
+	table = journal->j_revoke_table[1];
+	if (!table)
+		return;
+
+	for (i=0; i<table->hash_size; i++) {
+		hash_list = &table->hash_table[i];
+		J_ASSERT (list_empty(hash_list));
+	}
+
+	kfree(table->hash_table);
+	kmem_cache_free(jbd2_revoke_table_cache, table);
+	journal->j_revoke = NULL;
+}
+
+
+#ifdef __KERNEL__
+
+/*
+ * jbd2_journal_revoke: revoke a given buffer_head from the journal.  This
+ * prevents the block from being replayed during recovery if we take a
+ * crash after this current transaction commits.  Any subsequent
+ * metadata writes of the buffer in this transaction cancel the
+ * revoke.
+ *
+ * Note that this call may block --- it is up to the caller to make
+ * sure that there are no further calls to journal_write_metadata
+ * before the revoke is complete.  In ext3, this implies calling the
+ * revoke before clearing the block bitmap when we are deleting
+ * metadata.
+ *
+ * Revoke performs a jbd2_journal_forget on any buffer_head passed in as a
+ * parameter, but does _not_ forget the buffer_head if the bh was only
+ * found implicitly.
+ *
+ * bh_in may not be a journalled buffer - it may have come off
+ * the hash tables without an attached journal_head.
+ *
+ * If bh_in is non-zero, jbd2_journal_revoke() will decrement its b_count
+ * by one.
+ */
+
+int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr,
+		   struct buffer_head *bh_in)
+{
+	struct buffer_head *bh = NULL;
+	journal_t *journal;
+	struct block_device *bdev;
+	int err;
+
+	might_sleep();
+	if (bh_in)
+		BUFFER_TRACE(bh_in, "enter");
+
+	journal = handle->h_transaction->t_journal;
+	if (!jbd2_journal_set_features(journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)){
+		J_ASSERT (!"Cannot set revoke feature!");
+		return -EINVAL;
+	}
+
+	bdev = journal->j_fs_dev;
+	bh = bh_in;
+
+	if (!bh) {
+		bh = __find_get_block(bdev, blocknr, journal->j_blocksize);
+		if (bh)
+			BUFFER_TRACE(bh, "found on hash");
+	}
+#ifdef JBD_EXPENSIVE_CHECKING
+	else {
+		struct buffer_head *bh2;
+
+		/* If there is a different buffer_head lying around in
+		 * memory anywhere... */
+		bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize);
+		if (bh2) {
+			/* ... and it has RevokeValid status... */
+			if (bh2 != bh && buffer_revokevalid(bh2))
+				/* ...then it better be revoked too,
+				 * since it's illegal to create a revoke
+				 * record against a buffer_head which is
+				 * not marked revoked --- that would
+				 * risk missing a subsequent revoke
+				 * cancel. */
+				J_ASSERT_BH(bh2, buffer_revoked(bh2));
+			put_bh(bh2);
+		}
+	}
+#endif
+
+	/* We really ought not ever to revoke twice in a row without
+           first having the revoke cancelled: it's illegal to free a
+           block twice without allocating it in between! */
+	if (bh) {
+		if (!J_EXPECT_BH(bh, !buffer_revoked(bh),
+				 "inconsistent data on disk")) {
+			if (!bh_in)
+				brelse(bh);
+			return -EIO;
+		}
+		set_buffer_revoked(bh);
+		set_buffer_revokevalid(bh);
+		if (bh_in) {
+			BUFFER_TRACE(bh_in, "call jbd2_journal_forget");
+			jbd2_journal_forget(handle, bh_in);
+		} else {
+			BUFFER_TRACE(bh, "call brelse");
+			__brelse(bh);
+		}
+	}
+
+	jbd_debug(2, "insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in);
+	err = insert_revoke_hash(journal, blocknr,
+				handle->h_transaction->t_tid);
+	BUFFER_TRACE(bh_in, "exit");
+	return err;
+}
+
+/*
+ * Cancel an outstanding revoke.  For use only internally by the
+ * journaling code (called from jbd2_journal_get_write_access).
+ *
+ * We trust buffer_revoked() on the buffer if the buffer is already
+ * being journaled: if there is no revoke pending on the buffer, then we
+ * don't do anything here.
+ *
+ * This would break if it were possible for a buffer to be revoked and
+ * discarded, and then reallocated within the same transaction.  In such
+ * a case we would have lost the revoked bit, but when we arrived here
+ * the second time we would still have a pending revoke to cancel.  So,
+ * do not trust the Revoked bit on buffers unless RevokeValid is also
+ * set.
+ *
+ * The caller must have the journal locked.
+ */
+int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
+{
+	struct jbd2_revoke_record_s *record;
+	journal_t *journal = handle->h_transaction->t_journal;
+	int need_cancel;
+	int did_revoke = 0;	/* akpm: debug */
+	struct buffer_head *bh = jh2bh(jh);
+
+	jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
+
+	/* Is the existing Revoke bit valid?  If so, we trust it, and
+	 * only perform the full cancel if the revoke bit is set.  If
+	 * not, we can't trust the revoke bit, and we need to do the
+	 * full search for a revoke record. */
+	if (test_set_buffer_revokevalid(bh)) {
+		need_cancel = test_clear_buffer_revoked(bh);
+	} else {
+		need_cancel = 1;
+		clear_buffer_revoked(bh);
+	}
+
+	if (need_cancel) {
+		record = find_revoke_record(journal, bh->b_blocknr);
+		if (record) {
+			jbd_debug(4, "cancelled existing revoke on "
+				  "blocknr %llu\n", (unsigned long long)bh->b_blocknr);
+			spin_lock(&journal->j_revoke_lock);
+			list_del(&record->hash);
+			spin_unlock(&journal->j_revoke_lock);
+			kmem_cache_free(jbd2_revoke_record_cache, record);
+			did_revoke = 1;
+		}
+	}
+
+#ifdef JBD_EXPENSIVE_CHECKING
+	/* There better not be one left behind by now! */
+	record = find_revoke_record(journal, bh->b_blocknr);
+	J_ASSERT_JH(jh, record == NULL);
+#endif
+
+	/* Finally, have we just cleared revoke on an unhashed
+	 * buffer_head?  If so, we'd better make sure we clear the
+	 * revoked status on any hashed alias too, otherwise the revoke
+	 * state machine will get very upset later on. */
+	if (need_cancel) {
+		struct buffer_head *bh2;
+		bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size);
+		if (bh2) {
+			if (bh2 != bh)
+				clear_buffer_revoked(bh2);
+			__brelse(bh2);
+		}
+	}
+	return did_revoke;
+}
+
+/* journal_switch_revoke table select j_revoke for next transaction
+ * we do not want to suspend any processing until all revokes are
+ * written -bzzz
+ */
+void jbd2_journal_switch_revoke_table(journal_t *journal)
+{
+	int i;
+
+	if (journal->j_revoke == journal->j_revoke_table[0])
+		journal->j_revoke = journal->j_revoke_table[1];
+	else
+		journal->j_revoke = journal->j_revoke_table[0];
+
+	for (i = 0; i < journal->j_revoke->hash_size; i++)
+		INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]);
+}
+
+/*
+ * Write revoke records to the journal for all entries in the current
+ * revoke hash, deleting the entries as we go.
+ *
+ * Called with the journal lock held.
+ */
+
+void jbd2_journal_write_revoke_records(journal_t *journal,
+				  transaction_t *transaction)
+{
+	struct journal_head *descriptor;
+	struct jbd2_revoke_record_s *record;
+	struct jbd2_revoke_table_s *revoke;
+	struct list_head *hash_list;
+	int i, offset, count;
+
+	descriptor = NULL;
+	offset = 0;
+	count = 0;
+
+	/* select revoke table for committing transaction */
+	revoke = journal->j_revoke == journal->j_revoke_table[0] ?
+		journal->j_revoke_table[1] : journal->j_revoke_table[0];
+
+	for (i = 0; i < revoke->hash_size; i++) {
+		hash_list = &revoke->hash_table[i];
+
+		while (!list_empty(hash_list)) {
+			record = (struct jbd2_revoke_record_s *)
+				hash_list->next;
+			write_one_revoke_record(journal, transaction,
+						&descriptor, &offset,
+						record);
+			count++;
+			list_del(&record->hash);
+			kmem_cache_free(jbd2_revoke_record_cache, record);
+		}
+	}
+	if (descriptor)
+		flush_descriptor(journal, descriptor, offset);
+	jbd_debug(1, "Wrote %d revoke records\n", count);
+}
+
+/*
+ * Write out one revoke record.  We need to create a new descriptor
+ * block if the old one is full or if we have not already created one.
+ */
+
+static void write_one_revoke_record(journal_t *journal,
+				    transaction_t *transaction,
+				    struct journal_head **descriptorp,
+				    int *offsetp,
+				    struct jbd2_revoke_record_s *record)
+{
+	struct journal_head *descriptor;
+	int offset;
+	journal_header_t *header;
+
+	/* If we are already aborting, this all becomes a noop.  We
+           still need to go round the loop in
+           jbd2_journal_write_revoke_records in order to free all of the
+           revoke records: only the IO to the journal is omitted. */
+	if (is_journal_aborted(journal))
+		return;
+
+	descriptor = *descriptorp;
+	offset = *offsetp;
+
+	/* Make sure we have a descriptor with space left for the record */
+	if (descriptor) {
+		if (offset == journal->j_blocksize) {
+			flush_descriptor(journal, descriptor, offset);
+			descriptor = NULL;
+		}
+	}
+
+	if (!descriptor) {
+		descriptor = jbd2_journal_get_descriptor_buffer(journal);
+		if (!descriptor)
+			return;
+		header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
+		header->h_magic     = cpu_to_be32(JBD2_MAGIC_NUMBER);
+		header->h_blocktype = cpu_to_be32(JBD2_REVOKE_BLOCK);
+		header->h_sequence  = cpu_to_be32(transaction->t_tid);
+
+		/* Record it so that we can wait for IO completion later */
+		JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
+		jbd2_journal_file_buffer(descriptor, transaction, BJ_LogCtl);
+
+		offset = sizeof(jbd2_journal_revoke_header_t);
+		*descriptorp = descriptor;
+	}
+
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) {
+		* ((__be64 *)(&jh2bh(descriptor)->b_data[offset])) =
+			cpu_to_be64(record->blocknr);
+		offset += 8;
+
+	} else {
+		* ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) =
+			cpu_to_be32(record->blocknr);
+		offset += 4;
+	}
+
+	*offsetp = offset;
+}
+
+/*
+ * Flush a revoke descriptor out to the journal.  If we are aborting,
+ * this is a noop; otherwise we are generating a buffer which needs to
+ * be waited for during commit, so it has to go onto the appropriate
+ * journal buffer list.
+ */
+
+static void flush_descriptor(journal_t *journal,
+			     struct journal_head *descriptor,
+			     int offset)
+{
+	jbd2_journal_revoke_header_t *header;
+	struct buffer_head *bh = jh2bh(descriptor);
+
+	if (is_journal_aborted(journal)) {
+		put_bh(bh);
+		return;
+	}
+
+	header = (jbd2_journal_revoke_header_t *) jh2bh(descriptor)->b_data;
+	header->r_count = cpu_to_be32(offset);
+	set_buffer_jwrite(bh);
+	BUFFER_TRACE(bh, "write");
+	set_buffer_dirty(bh);
+	ll_rw_block(SWRITE, 1, &bh);
+}
+#endif
+
+/*
+ * Revoke support for recovery.
+ *
+ * Recovery needs to be able to:
+ *
+ *  record all revoke records, including the tid of the latest instance
+ *  of each revoke in the journal
+ *
+ *  check whether a given block in a given transaction should be replayed
+ *  (ie. has not been revoked by a revoke record in that or a subsequent
+ *  transaction)
+ *
+ *  empty the revoke table after recovery.
+ */
+
+/*
+ * First, setting revoke records.  We create a new revoke record for
+ * every block ever revoked in the log as we scan it for recovery, and
+ * we update the existing records if we find multiple revokes for a
+ * single block.
+ */
+
+int jbd2_journal_set_revoke(journal_t *journal,
+		       unsigned long long blocknr,
+		       tid_t sequence)
+{
+	struct jbd2_revoke_record_s *record;
+
+	record = find_revoke_record(journal, blocknr);
+	if (record) {
+		/* If we have multiple occurrences, only record the
+		 * latest sequence number in the hashed record */
+		if (tid_gt(sequence, record->sequence))
+			record->sequence = sequence;
+		return 0;
+	}
+	return insert_revoke_hash(journal, blocknr, sequence);
+}
+
+/*
+ * Test revoke records.  For a given block referenced in the log, has
+ * that block been revoked?  A revoke record with a given transaction
+ * sequence number revokes all blocks in that transaction and earlier
+ * ones, but later transactions still need replayed.
+ */
+
+int jbd2_journal_test_revoke(journal_t *journal,
+			unsigned long long blocknr,
+			tid_t sequence)
+{
+	struct jbd2_revoke_record_s *record;
+
+	record = find_revoke_record(journal, blocknr);
+	if (!record)
+		return 0;
+	if (tid_gt(sequence, record->sequence))
+		return 0;
+	return 1;
+}
+
+/*
+ * Finally, once recovery is over, we need to clear the revoke table so
+ * that it can be reused by the running filesystem.
+ */
+
+void jbd2_journal_clear_revoke(journal_t *journal)
+{
+	int i;
+	struct list_head *hash_list;
+	struct jbd2_revoke_record_s *record;
+	struct jbd2_revoke_table_s *revoke;
+
+	revoke = journal->j_revoke;
+
+	for (i = 0; i < revoke->hash_size; i++) {
+		hash_list = &revoke->hash_table[i];
+		while (!list_empty(hash_list)) {
+			record = (struct jbd2_revoke_record_s*) hash_list->next;
+			list_del(&record->hash);
+			kmem_cache_free(jbd2_revoke_record_cache, record);
+		}
+	}
+}
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
new file mode 100644
index 0000000..b6cf2be
--- /dev/null
+++ b/fs/jbd2/transaction.c
@@ -0,0 +1,2081 @@
+/*
+ * linux/fs/transaction.c
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
+ *
+ * Copyright 1998 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Generic filesystem transaction handling code; part of the ext2fs
+ * journaling system.
+ *
+ * This file manages transactions (compound commits managed by the
+ * journaling code) and handles (individual atomic operations by the
+ * filesystem).
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+
+/*
+ * jbd2_get_transaction: obtain a new transaction_t object.
+ *
+ * Simply allocate and initialise a new transaction.  Create it in
+ * RUNNING state and add it to the current journal (which should not
+ * have an existing running transaction: we only make a new transaction
+ * once we have started to commit the old one).
+ *
+ * Preconditions:
+ *	The journal MUST be locked.  We don't perform atomic mallocs on the
+ *	new transaction	and we can't block without protecting against other
+ *	processes trying to touch the journal while it is in transition.
+ *
+ * Called under j_state_lock
+ */
+
+static transaction_t *
+jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+{
+	transaction->t_journal = journal;
+	transaction->t_state = T_RUNNING;
+	transaction->t_tid = journal->j_transaction_sequence++;
+	transaction->t_expires = jiffies + journal->j_commit_interval;
+	spin_lock_init(&transaction->t_handle_lock);
+
+	/* Set up the commit timer for the new transaction. */
+	journal->j_commit_timer.expires = transaction->t_expires;
+	add_timer(&journal->j_commit_timer);
+
+	J_ASSERT(journal->j_running_transaction == NULL);
+	journal->j_running_transaction = transaction;
+
+	return transaction;
+}
+
+/*
+ * Handle management.
+ *
+ * A handle_t is an object which represents a single atomic update to a
+ * filesystem, and which tracks all of the modifications which form part
+ * of that one update.
+ */
+
+/*
+ * start_this_handle: Given a handle, deal with any locking or stalling
+ * needed to make sure that there is enough journal space for the handle
+ * to begin.  Attach the handle to a transaction and set up the
+ * transaction's buffer credits.
+ */
+
+static int start_this_handle(journal_t *journal, handle_t *handle)
+{
+	transaction_t *transaction;
+	int needed;
+	int nblocks = handle->h_buffer_credits;
+	transaction_t *new_transaction = NULL;
+	int ret = 0;
+
+	if (nblocks > journal->j_max_transaction_buffers) {
+		printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
+		       current->comm, nblocks,
+		       journal->j_max_transaction_buffers);
+		ret = -ENOSPC;
+		goto out;
+	}
+
+alloc_transaction:
+	if (!journal->j_running_transaction) {
+		new_transaction = jbd_kmalloc(sizeof(*new_transaction),
+						GFP_NOFS);
+		if (!new_transaction) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		memset(new_transaction, 0, sizeof(*new_transaction));
+	}
+
+	jbd_debug(3, "New handle %p going live.\n", handle);
+
+repeat:
+
+	/*
+	 * We need to hold j_state_lock until t_updates has been incremented,
+	 * for proper journal barrier handling
+	 */
+	spin_lock(&journal->j_state_lock);
+repeat_locked:
+	if (is_journal_aborted(journal) ||
+	    (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) {
+		spin_unlock(&journal->j_state_lock);
+		ret = -EROFS;
+		goto out;
+	}
+
+	/* Wait on the journal's transaction barrier if necessary */
+	if (journal->j_barrier_count) {
+		spin_unlock(&journal->j_state_lock);
+		wait_event(journal->j_wait_transaction_locked,
+				journal->j_barrier_count == 0);
+		goto repeat;
+	}
+
+	if (!journal->j_running_transaction) {
+		if (!new_transaction) {
+			spin_unlock(&journal->j_state_lock);
+			goto alloc_transaction;
+		}
+		jbd2_get_transaction(journal, new_transaction);
+		new_transaction = NULL;
+	}
+
+	transaction = journal->j_running_transaction;
+
+	/*
+	 * If the current transaction is locked down for commit, wait for the
+	 * lock to be released.
+	 */
+	if (transaction->t_state == T_LOCKED) {
+		DEFINE_WAIT(wait);
+
+		prepare_to_wait(&journal->j_wait_transaction_locked,
+					&wait, TASK_UNINTERRUPTIBLE);
+		spin_unlock(&journal->j_state_lock);
+		schedule();
+		finish_wait(&journal->j_wait_transaction_locked, &wait);
+		goto repeat;
+	}
+
+	/*
+	 * If there is not enough space left in the log to write all potential
+	 * buffers requested by this operation, we need to stall pending a log
+	 * checkpoint to free some more log space.
+	 */
+	spin_lock(&transaction->t_handle_lock);
+	needed = transaction->t_outstanding_credits + nblocks;
+
+	if (needed > journal->j_max_transaction_buffers) {
+		/*
+		 * If the current transaction is already too large, then start
+		 * to commit it: we can then go back and attach this handle to
+		 * a new transaction.
+		 */
+		DEFINE_WAIT(wait);
+
+		jbd_debug(2, "Handle %p starting new commit...\n", handle);
+		spin_unlock(&transaction->t_handle_lock);
+		prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
+				TASK_UNINTERRUPTIBLE);
+		__jbd2_log_start_commit(journal, transaction->t_tid);
+		spin_unlock(&journal->j_state_lock);
+		schedule();
+		finish_wait(&journal->j_wait_transaction_locked, &wait);
+		goto repeat;
+	}
+
+	/*
+	 * The commit code assumes that it can get enough log space
+	 * without forcing a checkpoint.  This is *critical* for
+	 * correctness: a checkpoint of a buffer which is also
+	 * associated with a committing transaction creates a deadlock,
+	 * so commit simply cannot force through checkpoints.
+	 *
+	 * We must therefore ensure the necessary space in the journal
+	 * *before* starting to dirty potentially checkpointed buffers
+	 * in the new transaction.
+	 *
+	 * The worst part is, any transaction currently committing can
+	 * reduce the free space arbitrarily.  Be careful to account for
+	 * those buffers when checkpointing.
+	 */
+
+	/*
+	 * @@@ AKPM: This seems rather over-defensive.  We're giving commit
+	 * a _lot_ of headroom: 1/4 of the journal plus the size of
+	 * the committing transaction.  Really, we only need to give it
+	 * committing_transaction->t_outstanding_credits plus "enough" for
+	 * the log control blocks.
+	 * Also, this test is inconsitent with the matching one in
+	 * jbd2_journal_extend().
+	 */
+	if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) {
+		jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
+		spin_unlock(&transaction->t_handle_lock);
+		__jbd2_log_wait_for_space(journal);
+		goto repeat_locked;
+	}
+
+	/* OK, account for the buffers that this operation expects to
+	 * use and add the handle to the running transaction. */
+
+	handle->h_transaction = transaction;
+	transaction->t_outstanding_credits += nblocks;
+	transaction->t_updates++;
+	transaction->t_handle_count++;
+	jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
+		  handle, nblocks, transaction->t_outstanding_credits,
+		  __jbd2_log_space_left(journal));
+	spin_unlock(&transaction->t_handle_lock);
+	spin_unlock(&journal->j_state_lock);
+out:
+	if (unlikely(new_transaction))		/* It's usually NULL */
+		kfree(new_transaction);
+	return ret;
+}
+
+/* Allocate a new handle.  This should probably be in a slab... */
+static handle_t *new_handle(int nblocks)
+{
+	handle_t *handle = jbd_alloc_handle(GFP_NOFS);
+	if (!handle)
+		return NULL;
+	memset(handle, 0, sizeof(*handle));
+	handle->h_buffer_credits = nblocks;
+	handle->h_ref = 1;
+
+	return handle;
+}
+
+/**
+ * handle_t *jbd2_journal_start() - Obtain a new handle.
+ * @journal: Journal to start transaction on.
+ * @nblocks: number of block buffer we might modify
+ *
+ * We make sure that the transaction can guarantee at least nblocks of
+ * modified buffers in the log.  We block until the log can guarantee
+ * that much space.
+ *
+ * This function is visible to journal users (like ext3fs), so is not
+ * called with the journal already locked.
+ *
+ * Return a pointer to a newly allocated handle, or NULL on failure
+ */
+handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
+{
+	handle_t *handle = journal_current_handle();
+	int err;
+
+	if (!journal)
+		return ERR_PTR(-EROFS);
+
+	if (handle) {
+		J_ASSERT(handle->h_transaction->t_journal == journal);
+		handle->h_ref++;
+		return handle;
+	}
+
+	handle = new_handle(nblocks);
+	if (!handle)
+		return ERR_PTR(-ENOMEM);
+
+	current->journal_info = handle;
+
+	err = start_this_handle(journal, handle);
+	if (err < 0) {
+		jbd_free_handle(handle);
+		current->journal_info = NULL;
+		handle = ERR_PTR(err);
+	}
+	return handle;
+}
+
+/**
+ * int jbd2_journal_extend() - extend buffer credits.
+ * @handle:  handle to 'extend'
+ * @nblocks: nr blocks to try to extend by.
+ *
+ * Some transactions, such as large extends and truncates, can be done
+ * atomically all at once or in several stages.  The operation requests
+ * a credit for a number of buffer modications in advance, but can
+ * extend its credit if it needs more.
+ *
+ * jbd2_journal_extend tries to give the running handle more buffer credits.
+ * It does not guarantee that allocation - this is a best-effort only.
+ * The calling process MUST be able to deal cleanly with a failure to
+ * extend here.
+ *
+ * Return 0 on success, non-zero on failure.
+ *
+ * return code < 0 implies an error
+ * return code > 0 implies normal transaction-full status.
+ */
+int jbd2_journal_extend(handle_t *handle, int nblocks)
+{
+	transaction_t *transaction = handle->h_transaction;
+	journal_t *journal = transaction->t_journal;
+	int result;
+	int wanted;
+
+	result = -EIO;
+	if (is_handle_aborted(handle))
+		goto out;
+
+	result = 1;
+
+	spin_lock(&journal->j_state_lock);
+
+	/* Don't extend a locked-down transaction! */
+	if (handle->h_transaction->t_state != T_RUNNING) {
+		jbd_debug(3, "denied handle %p %d blocks: "
+			  "transaction not running\n", handle, nblocks);
+		goto error_out;
+	}
+
+	spin_lock(&transaction->t_handle_lock);
+	wanted = transaction->t_outstanding_credits + nblocks;
+
+	if (wanted > journal->j_max_transaction_buffers) {
+		jbd_debug(3, "denied handle %p %d blocks: "
+			  "transaction too large\n", handle, nblocks);
+		goto unlock;
+	}
+
+	if (wanted > __jbd2_log_space_left(journal)) {
+		jbd_debug(3, "denied handle %p %d blocks: "
+			  "insufficient log space\n", handle, nblocks);
+		goto unlock;
+	}
+
+	handle->h_buffer_credits += nblocks;
+	transaction->t_outstanding_credits += nblocks;
+	result = 0;
+
+	jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
+unlock:
+	spin_unlock(&transaction->t_handle_lock);
+error_out:
+	spin_unlock(&journal->j_state_lock);
+out:
+	return result;
+}
+
+
+/**
+ * int jbd2_journal_restart() - restart a handle .
+ * @handle:  handle to restart
+ * @nblocks: nr credits requested
+ *
+ * Restart a handle for a multi-transaction filesystem
+ * operation.
+ *
+ * If the jbd2_journal_extend() call above fails to grant new buffer credits
+ * to a running handle, a call to jbd2_journal_restart will commit the
+ * handle's transaction so far and reattach the handle to a new
+ * transaction capabable of guaranteeing the requested number of
+ * credits.
+ */
+
+int jbd2_journal_restart(handle_t *handle, int nblocks)
+{
+	transaction_t *transaction = handle->h_transaction;
+	journal_t *journal = transaction->t_journal;
+	int ret;
+
+	/* If we've had an abort of any type, don't even think about
+	 * actually doing the restart! */
+	if (is_handle_aborted(handle))
+		return 0;
+
+	/*
+	 * First unlink the handle from its current transaction, and start the
+	 * commit on that.
+	 */
+	J_ASSERT(transaction->t_updates > 0);
+	J_ASSERT(journal_current_handle() == handle);
+
+	spin_lock(&journal->j_state_lock);
+	spin_lock(&transaction->t_handle_lock);
+	transaction->t_outstanding_credits -= handle->h_buffer_credits;
+	transaction->t_updates--;
+
+	if (!transaction->t_updates)
+		wake_up(&journal->j_wait_updates);
+	spin_unlock(&transaction->t_handle_lock);
+
+	jbd_debug(2, "restarting handle %p\n", handle);
+	__jbd2_log_start_commit(journal, transaction->t_tid);
+	spin_unlock(&journal->j_state_lock);
+
+	handle->h_buffer_credits = nblocks;
+	ret = start_this_handle(journal, handle);
+	return ret;
+}
+
+
+/**
+ * void jbd2_journal_lock_updates () - establish a transaction barrier.
+ * @journal:  Journal to establish a barrier on.
+ *
+ * This locks out any further updates from being started, and blocks
+ * until all existing updates have completed, returning only once the
+ * journal is in a quiescent state with no updates running.
+ *
+ * The journal lock should not be held on entry.
+ */
+void jbd2_journal_lock_updates(journal_t *journal)
+{
+	DEFINE_WAIT(wait);
+
+	spin_lock(&journal->j_state_lock);
+	++journal->j_barrier_count;
+
+	/* Wait until there are no running updates */
+	while (1) {
+		transaction_t *transaction = journal->j_running_transaction;
+
+		if (!transaction)
+			break;
+
+		spin_lock(&transaction->t_handle_lock);
+		if (!transaction->t_updates) {
+			spin_unlock(&transaction->t_handle_lock);
+			break;
+		}
+		prepare_to_wait(&journal->j_wait_updates, &wait,
+				TASK_UNINTERRUPTIBLE);
+		spin_unlock(&transaction->t_handle_lock);
+		spin_unlock(&journal->j_state_lock);
+		schedule();
+		finish_wait(&journal->j_wait_updates, &wait);
+		spin_lock(&journal->j_state_lock);
+	}
+	spin_unlock(&journal->j_state_lock);
+
+	/*
+	 * We have now established a barrier against other normal updates, but
+	 * we also need to barrier against other jbd2_journal_lock_updates() calls
+	 * to make sure that we serialise special journal-locked operations
+	 * too.
+	 */
+	mutex_lock(&journal->j_barrier);
+}
+
+/**
+ * void jbd2_journal_unlock_updates (journal_t* journal) - release barrier
+ * @journal:  Journal to release the barrier on.
+ *
+ * Release a transaction barrier obtained with jbd2_journal_lock_updates().
+ *
+ * Should be called without the journal lock held.
+ */
+void jbd2_journal_unlock_updates (journal_t *journal)
+{
+	J_ASSERT(journal->j_barrier_count != 0);
+
+	mutex_unlock(&journal->j_barrier);
+	spin_lock(&journal->j_state_lock);
+	--journal->j_barrier_count;
+	spin_unlock(&journal->j_state_lock);
+	wake_up(&journal->j_wait_transaction_locked);
+}
+
+/*
+ * Report any unexpected dirty buffers which turn up.  Normally those
+ * indicate an error, but they can occur if the user is running (say)
+ * tune2fs to modify the live filesystem, so we need the option of
+ * continuing as gracefully as possible.  #
+ *
+ * The caller should already hold the journal lock and
+ * j_list_lock spinlock: most callers will need those anyway
+ * in order to probe the buffer's journaling state safely.
+ */
+static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
+{
+	int jlist;
+
+	/* If this buffer is one which might reasonably be dirty
+	 * --- ie. data, or not part of this journal --- then
+	 * we're OK to leave it alone, but otherwise we need to
+	 * move the dirty bit to the journal's own internal
+	 * JBDDirty bit. */
+	jlist = jh->b_jlist;
+
+	if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
+	    jlist == BJ_Shadow || jlist == BJ_Forget) {
+		struct buffer_head *bh = jh2bh(jh);
+
+		if (test_clear_buffer_dirty(bh))
+			set_buffer_jbddirty(bh);
+	}
+}
+
+/*
+ * If the buffer is already part of the current transaction, then there
+ * is nothing we need to do.  If it is already part of a prior
+ * transaction which we are still committing to disk, then we need to
+ * make sure that we do not overwrite the old copy: we do copy-out to
+ * preserve the copy going to disk.  We also account the buffer against
+ * the handle's metadata buffer credits (unless the buffer is already
+ * part of the transaction, that is).
+ *
+ */
+static int
+do_get_write_access(handle_t *handle, struct journal_head *jh,
+			int force_copy)
+{
+	struct buffer_head *bh;
+	transaction_t *transaction;
+	journal_t *journal;
+	int error;
+	char *frozen_buffer = NULL;
+	int need_copy = 0;
+
+	if (is_handle_aborted(handle))
+		return -EROFS;
+
+	transaction = handle->h_transaction;
+	journal = transaction->t_journal;
+
+	jbd_debug(5, "buffer_head %p, force_copy %d\n", jh, force_copy);
+
+	JBUFFER_TRACE(jh, "entry");
+repeat:
+	bh = jh2bh(jh);
+
+	/* @@@ Need to check for errors here at some point. */
+
+	lock_buffer(bh);
+	jbd_lock_bh_state(bh);
+
+	/* We now hold the buffer lock so it is safe to query the buffer
+	 * state.  Is the buffer dirty?
+	 *
+	 * If so, there are two possibilities.  The buffer may be
+	 * non-journaled, and undergoing a quite legitimate writeback.
+	 * Otherwise, it is journaled, and we don't expect dirty buffers
+	 * in that state (the buffers should be marked JBD_Dirty
+	 * instead.)  So either the IO is being done under our own
+	 * control and this is a bug, or it's a third party IO such as
+	 * dump(8) (which may leave the buffer scheduled for read ---
+	 * ie. locked but not dirty) or tune2fs (which may actually have
+	 * the buffer dirtied, ugh.)  */
+
+	if (buffer_dirty(bh)) {
+		/*
+		 * First question: is this buffer already part of the current
+		 * transaction or the existing committing transaction?
+		 */
+		if (jh->b_transaction) {
+			J_ASSERT_JH(jh,
+				jh->b_transaction == transaction ||
+				jh->b_transaction ==
+					journal->j_committing_transaction);
+			if (jh->b_next_transaction)
+				J_ASSERT_JH(jh, jh->b_next_transaction ==
+							transaction);
+		}
+		/*
+		 * In any case we need to clean the dirty flag and we must
+		 * do it under the buffer lock to be sure we don't race
+		 * with running write-out.
+		 */
+		JBUFFER_TRACE(jh, "Unexpected dirty buffer");
+		jbd_unexpected_dirty_buffer(jh);
+	}
+
+	unlock_buffer(bh);
+
+	error = -EROFS;
+	if (is_handle_aborted(handle)) {
+		jbd_unlock_bh_state(bh);
+		goto out;
+	}
+	error = 0;
+
+	/*
+	 * The buffer is already part of this transaction if b_transaction or
+	 * b_next_transaction points to it
+	 */
+	if (jh->b_transaction == transaction ||
+	    jh->b_next_transaction == transaction)
+		goto done;
+
+	/*
+	 * If there is already a copy-out version of this buffer, then we don't
+	 * need to make another one
+	 */
+	if (jh->b_frozen_data) {
+		JBUFFER_TRACE(jh, "has frozen data");
+		J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+		jh->b_next_transaction = transaction;
+		goto done;
+	}
+
+	/* Is there data here we need to preserve? */
+
+	if (jh->b_transaction && jh->b_transaction != transaction) {
+		JBUFFER_TRACE(jh, "owned by older transaction");
+		J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+		J_ASSERT_JH(jh, jh->b_transaction ==
+					journal->j_committing_transaction);
+
+		/* There is one case we have to be very careful about.
+		 * If the committing transaction is currently writing
+		 * this buffer out to disk and has NOT made a copy-out,
+		 * then we cannot modify the buffer contents at all
+		 * right now.  The essence of copy-out is that it is the
+		 * extra copy, not the primary copy, which gets
+		 * journaled.  If the primary copy is already going to
+		 * disk then we cannot do copy-out here. */
+
+		if (jh->b_jlist == BJ_Shadow) {
+			DEFINE_WAIT_BIT(wait, &bh->b_state, BH_Unshadow);
+			wait_queue_head_t *wqh;
+
+			wqh = bit_waitqueue(&bh->b_state, BH_Unshadow);
+
+			JBUFFER_TRACE(jh, "on shadow: sleep");
+			jbd_unlock_bh_state(bh);
+			/* commit wakes up all shadow buffers after IO */
+			for ( ; ; ) {
+				prepare_to_wait(wqh, &wait.wait,
+						TASK_UNINTERRUPTIBLE);
+				if (jh->b_jlist != BJ_Shadow)
+					break;
+				schedule();
+			}
+			finish_wait(wqh, &wait.wait);
+			goto repeat;
+		}
+
+		/* Only do the copy if the currently-owning transaction
+		 * still needs it.  If it is on the Forget list, the
+		 * committing transaction is past that stage.  The
+		 * buffer had better remain locked during the kmalloc,
+		 * but that should be true --- we hold the journal lock
+		 * still and the buffer is already on the BUF_JOURNAL
+		 * list so won't be flushed.
+		 *
+		 * Subtle point, though: if this is a get_undo_access,
+		 * then we will be relying on the frozen_data to contain
+		 * the new value of the committed_data record after the
+		 * transaction, so we HAVE to force the frozen_data copy
+		 * in that case. */
+
+		if (jh->b_jlist != BJ_Forget || force_copy) {
+			JBUFFER_TRACE(jh, "generate frozen data");
+			if (!frozen_buffer) {
+				JBUFFER_TRACE(jh, "allocate memory for buffer");
+				jbd_unlock_bh_state(bh);
+				frozen_buffer =
+					jbd2_slab_alloc(jh2bh(jh)->b_size,
+							 GFP_NOFS);
+				if (!frozen_buffer) {
+					printk(KERN_EMERG
+					       "%s: OOM for frozen_buffer\n",
+					       __FUNCTION__);
+					JBUFFER_TRACE(jh, "oom!");
+					error = -ENOMEM;
+					jbd_lock_bh_state(bh);
+					goto done;
+				}
+				goto repeat;
+			}
+			jh->b_frozen_data = frozen_buffer;
+			frozen_buffer = NULL;
+			need_copy = 1;
+		}
+		jh->b_next_transaction = transaction;
+	}
+
+
+	/*
+	 * Finally, if the buffer is not journaled right now, we need to make
+	 * sure it doesn't get written to disk before the caller actually
+	 * commits the new data
+	 */
+	if (!jh->b_transaction) {
+		JBUFFER_TRACE(jh, "no transaction");
+		J_ASSERT_JH(jh, !jh->b_next_transaction);
+		jh->b_transaction = transaction;
+		JBUFFER_TRACE(jh, "file as BJ_Reserved");
+		spin_lock(&journal->j_list_lock);
+		__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
+		spin_unlock(&journal->j_list_lock);
+	}
+
+done:
+	if (need_copy) {
+		struct page *page;
+		int offset;
+		char *source;
+
+		J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)),
+			    "Possible IO failure.\n");
+		page = jh2bh(jh)->b_page;
+		offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK;
+		source = kmap_atomic(page, KM_USER0);
+		memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
+		kunmap_atomic(source, KM_USER0);
+	}
+	jbd_unlock_bh_state(bh);
+
+	/*
+	 * If we are about to journal a buffer, then any revoke pending on it is
+	 * no longer valid
+	 */
+	jbd2_journal_cancel_revoke(handle, jh);
+
+out:
+	if (unlikely(frozen_buffer))	/* It's usually NULL */
+		jbd2_slab_free(frozen_buffer, bh->b_size);
+
+	JBUFFER_TRACE(jh, "exit");
+	return error;
+}
+
+/**
+ * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update.
+ * @handle: transaction to add buffer modifications to
+ * @bh:     bh to be used for metadata writes
+ * @credits: variable that will receive credits for the buffer
+ *
+ * Returns an error code or 0 on success.
+ *
+ * In full data journalling mode the buffer may be of type BJ_AsyncData,
+ * because we're write()ing a buffer which is also part of a shared mapping.
+ */
+
+int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
+{
+	struct journal_head *jh = jbd2_journal_add_journal_head(bh);
+	int rc;
+
+	/* We do not want to get caught playing with fields which the
+	 * log thread also manipulates.  Make sure that the buffer
+	 * completes any outstanding IO before proceeding. */
+	rc = do_get_write_access(handle, jh, 0);
+	jbd2_journal_put_journal_head(jh);
+	return rc;
+}
+
+
+/*
+ * When the user wants to journal a newly created buffer_head
+ * (ie. getblk() returned a new buffer and we are going to populate it
+ * manually rather than reading off disk), then we need to keep the
+ * buffer_head locked until it has been completely filled with new
+ * data.  In this case, we should be able to make the assertion that
+ * the bh is not already part of an existing transaction.
+ *
+ * The buffer should already be locked by the caller by this point.
+ * There is no lock ranking violation: it was a newly created,
+ * unlocked buffer beforehand. */
+
+/**
+ * int jbd2_journal_get_create_access () - notify intent to use newly created bh
+ * @handle: transaction to new buffer to
+ * @bh: new buffer.
+ *
+ * Call this if you create a new bh.
+ */
+int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+{
+	transaction_t *transaction = handle->h_transaction;
+	journal_t *journal = transaction->t_journal;
+	struct journal_head *jh = jbd2_journal_add_journal_head(bh);
+	int err;
+
+	jbd_debug(5, "journal_head %p\n", jh);
+	err = -EROFS;
+	if (is_handle_aborted(handle))
+		goto out;
+	err = 0;
+
+	JBUFFER_TRACE(jh, "entry");
+	/*
+	 * The buffer may already belong to this transaction due to pre-zeroing
+	 * in the filesystem's new_block code.  It may also be on the previous,
+	 * committing transaction's lists, but it HAS to be in Forget state in
+	 * that case: the transaction must have deleted the buffer for it to be
+	 * reused here.
+	 */
+	jbd_lock_bh_state(bh);
+	spin_lock(&journal->j_list_lock);
+	J_ASSERT_JH(jh, (jh->b_transaction == transaction ||
+		jh->b_transaction == NULL ||
+		(jh->b_transaction == journal->j_committing_transaction &&
+			  jh->b_jlist == BJ_Forget)));
+
+	J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+	J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
+
+	if (jh->b_transaction == NULL) {
+		jh->b_transaction = transaction;
+		JBUFFER_TRACE(jh, "file as BJ_Reserved");
+		__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
+	} else if (jh->b_transaction == journal->j_committing_transaction) {
+		JBUFFER_TRACE(jh, "set next transaction");
+		jh->b_next_transaction = transaction;
+	}
+	spin_unlock(&journal->j_list_lock);
+	jbd_unlock_bh_state(bh);
+
+	/*
+	 * akpm: I added this.  ext3_alloc_branch can pick up new indirect
+	 * blocks which contain freed but then revoked metadata.  We need
+	 * to cancel the revoke in case we end up freeing it yet again
+	 * and the reallocating as data - this would cause a second revoke,
+	 * which hits an assertion error.
+	 */
+	JBUFFER_TRACE(jh, "cancelling revoke");
+	jbd2_journal_cancel_revoke(handle, jh);
+	jbd2_journal_put_journal_head(jh);
+out:
+	return err;
+}
+
+/**
+ * int jbd2_journal_get_undo_access() -  Notify intent to modify metadata with
+ *     non-rewindable consequences
+ * @handle: transaction
+ * @bh: buffer to undo
+ * @credits: store the number of taken credits here (if not NULL)
+ *
+ * Sometimes there is a need to distinguish between metadata which has
+ * been committed to disk and that which has not.  The ext3fs code uses
+ * this for freeing and allocating space, we have to make sure that we
+ * do not reuse freed space until the deallocation has been committed,
+ * since if we overwrote that space we would make the delete
+ * un-rewindable in case of a crash.
+ *
+ * To deal with that, jbd2_journal_get_undo_access requests write access to a
+ * buffer for parts of non-rewindable operations such as delete
+ * operations on the bitmaps.  The journaling code must keep a copy of
+ * the buffer's contents prior to the undo_access call until such time
+ * as we know that the buffer has definitely been committed to disk.
+ *
+ * We never need to know which transaction the committed data is part
+ * of, buffers touched here are guaranteed to be dirtied later and so
+ * will be committed to a new transaction in due course, at which point
+ * we can discard the old committed data pointer.
+ *
+ * Returns error number or 0 on success.
+ */
+int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
+{
+	int err;
+	struct journal_head *jh = jbd2_journal_add_journal_head(bh);
+	char *committed_data = NULL;
+
+	JBUFFER_TRACE(jh, "entry");
+
+	/*
+	 * Do this first --- it can drop the journal lock, so we want to
+	 * make sure that obtaining the committed_data is done
+	 * atomically wrt. completion of any outstanding commits.
+	 */
+	err = do_get_write_access(handle, jh, 1);
+	if (err)
+		goto out;
+
+repeat:
+	if (!jh->b_committed_data) {
+		committed_data = jbd2_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS);
+		if (!committed_data) {
+			printk(KERN_EMERG "%s: No memory for committed data\n",
+				__FUNCTION__);
+			err = -ENOMEM;
+			goto out;
+		}
+	}
+
+	jbd_lock_bh_state(bh);
+	if (!jh->b_committed_data) {
+		/* Copy out the current buffer contents into the
+		 * preserved, committed copy. */
+		JBUFFER_TRACE(jh, "generate b_committed data");
+		if (!committed_data) {
+			jbd_unlock_bh_state(bh);
+			goto repeat;
+		}
+
+		jh->b_committed_data = committed_data;
+		committed_data = NULL;
+		memcpy(jh->b_committed_data, bh->b_data, bh->b_size);
+	}
+	jbd_unlock_bh_state(bh);
+out:
+	jbd2_journal_put_journal_head(jh);
+	if (unlikely(committed_data))
+		jbd2_slab_free(committed_data, bh->b_size);
+	return err;
+}
+
+/**
+ * int jbd2_journal_dirty_data() -  mark a buffer as containing dirty data which
+ *                             needs to be flushed before we can commit the
+ *                             current transaction.
+ * @handle: transaction
+ * @bh: bufferhead to mark
+ *
+ * The buffer is placed on the transaction's data list and is marked as
+ * belonging to the transaction.
+ *
+ * Returns error number or 0 on success.
+ *
+ * jbd2_journal_dirty_data() can be called via page_launder->ext3_writepage
+ * by kswapd.
+ */
+int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
+{
+	journal_t *journal = handle->h_transaction->t_journal;
+	int need_brelse = 0;
+	struct journal_head *jh;
+
+	if (is_handle_aborted(handle))
+		return 0;
+
+	jh = jbd2_journal_add_journal_head(bh);
+	JBUFFER_TRACE(jh, "entry");
+
+	/*
+	 * The buffer could *already* be dirty.  Writeout can start
+	 * at any time.
+	 */
+	jbd_debug(4, "jh: %p, tid:%d\n", jh, handle->h_transaction->t_tid);
+
+	/*
+	 * What if the buffer is already part of a running transaction?
+	 *
+	 * There are two cases:
+	 * 1) It is part of the current running transaction.  Refile it,
+	 *    just in case we have allocated it as metadata, deallocated
+	 *    it, then reallocated it as data.
+	 * 2) It is part of the previous, still-committing transaction.
+	 *    If all we want to do is to guarantee that the buffer will be
+	 *    written to disk before this new transaction commits, then
+	 *    being sure that the *previous* transaction has this same
+	 *    property is sufficient for us!  Just leave it on its old
+	 *    transaction.
+	 *
+	 * In case (2), the buffer must not already exist as metadata
+	 * --- that would violate write ordering (a transaction is free
+	 * to write its data at any point, even before the previous
+	 * committing transaction has committed).  The caller must
+	 * never, ever allow this to happen: there's nothing we can do
+	 * about it in this layer.
+	 */
+	jbd_lock_bh_state(bh);
+	spin_lock(&journal->j_list_lock);
+	if (jh->b_transaction) {
+		JBUFFER_TRACE(jh, "has transaction");
+		if (jh->b_transaction != handle->h_transaction) {
+			JBUFFER_TRACE(jh, "belongs to older transaction");
+			J_ASSERT_JH(jh, jh->b_transaction ==
+					journal->j_committing_transaction);
+
+			/* @@@ IS THIS TRUE  ? */
+			/*
+			 * Not any more.  Scenario: someone does a write()
+			 * in data=journal mode.  The buffer's transaction has
+			 * moved into commit.  Then someone does another
+			 * write() to the file.  We do the frozen data copyout
+			 * and set b_next_transaction to point to j_running_t.
+			 * And while we're in that state, someone does a
+			 * writepage() in an attempt to pageout the same area
+			 * of the file via a shared mapping.  At present that
+			 * calls jbd2_journal_dirty_data(), and we get right here.
+			 * It may be too late to journal the data.  Simply
+			 * falling through to the next test will suffice: the
+			 * data will be dirty and wil be checkpointed.  The
+			 * ordering comments in the next comment block still
+			 * apply.
+			 */
+			//J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+
+			/*
+			 * If we're journalling data, and this buffer was
+			 * subject to a write(), it could be metadata, forget
+			 * or shadow against the committing transaction.  Now,
+			 * someone has dirtied the same darn page via a mapping
+			 * and it is being writepage()'d.
+			 * We *could* just steal the page from commit, with some
+			 * fancy locking there.  Instead, we just skip it -
+			 * don't tie the page's buffers to the new transaction
+			 * at all.
+			 * Implication: if we crash before the writepage() data
+			 * is written into the filesystem, recovery will replay
+			 * the write() data.
+			 */
+			if (jh->b_jlist != BJ_None &&
+					jh->b_jlist != BJ_SyncData &&
+					jh->b_jlist != BJ_Locked) {
+				JBUFFER_TRACE(jh, "Not stealing");
+				goto no_journal;
+			}
+
+			/*
+			 * This buffer may be undergoing writeout in commit.  We
+			 * can't return from here and let the caller dirty it
+			 * again because that can cause the write-out loop in
+			 * commit to never terminate.
+			 */
+			if (buffer_dirty(bh)) {
+				get_bh(bh);
+				spin_unlock(&journal->j_list_lock);
+				jbd_unlock_bh_state(bh);
+				need_brelse = 1;
+				sync_dirty_buffer(bh);
+				jbd_lock_bh_state(bh);
+				spin_lock(&journal->j_list_lock);
+				/* The buffer may become locked again at any
+				   time if it is redirtied */
+			}
+
+			/* journal_clean_data_list() may have got there first */
+			if (jh->b_transaction != NULL) {
+				JBUFFER_TRACE(jh, "unfile from commit");
+				__jbd2_journal_temp_unlink_buffer(jh);
+				/* It still points to the committing
+				 * transaction; move it to this one so
+				 * that the refile assert checks are
+				 * happy. */
+				jh->b_transaction = handle->h_transaction;
+			}
+			/* The buffer will be refiled below */
+
+		}
+		/*
+		 * Special case --- the buffer might actually have been
+		 * allocated and then immediately deallocated in the previous,
+		 * committing transaction, so might still be left on that
+		 * transaction's metadata lists.
+		 */
+		if (jh->b_jlist != BJ_SyncData && jh->b_jlist != BJ_Locked) {
+			JBUFFER_TRACE(jh, "not on correct data list: unfile");
+			J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow);
+			__jbd2_journal_temp_unlink_buffer(jh);
+			jh->b_transaction = handle->h_transaction;
+			JBUFFER_TRACE(jh, "file as data");
+			__jbd2_journal_file_buffer(jh, handle->h_transaction,
+						BJ_SyncData);
+		}
+	} else {
+		JBUFFER_TRACE(jh, "not on a transaction");
+		__jbd2_journal_file_buffer(jh, handle->h_transaction, BJ_SyncData);
+	}
+no_journal:
+	spin_unlock(&journal->j_list_lock);
+	jbd_unlock_bh_state(bh);
+	if (need_brelse) {
+		BUFFER_TRACE(bh, "brelse");
+		__brelse(bh);
+	}
+	JBUFFER_TRACE(jh, "exit");
+	jbd2_journal_put_journal_head(jh);
+	return 0;
+}
+
+/**
+ * int jbd2_journal_dirty_metadata() -  mark a buffer as containing dirty metadata
+ * @handle: transaction to add buffer to.
+ * @bh: buffer to mark
+ *
+ * mark dirty metadata which needs to be journaled as part of the current
+ * transaction.
+ *
+ * The buffer is placed on the transaction's metadata list and is marked
+ * as belonging to the transaction.
+ *
+ * Returns error number or 0 on success.
+ *
+ * Special care needs to be taken if the buffer already belongs to the
+ * current committing transaction (in which case we should have frozen
+ * data present for that commit).  In that case, we don't relink the
+ * buffer: that only gets done when the old transaction finally
+ * completes its commit.
+ */
+int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+{
+	transaction_t *transaction = handle->h_transaction;
+	journal_t *journal = transaction->t_journal;
+	struct journal_head *jh = bh2jh(bh);
+
+	jbd_debug(5, "journal_head %p\n", jh);
+	JBUFFER_TRACE(jh, "entry");
+	if (is_handle_aborted(handle))
+		goto out;
+
+	jbd_lock_bh_state(bh);
+
+	if (jh->b_modified == 0) {
+		/*
+		 * This buffer's got modified and becoming part
+		 * of the transaction. This needs to be done
+		 * once a transaction -bzzz
+		 */
+		jh->b_modified = 1;
+		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+		handle->h_buffer_credits--;
+	}
+
+	/*
+	 * fastpath, to avoid expensive locking.  If this buffer is already
+	 * on the running transaction's metadata list there is nothing to do.
+	 * Nobody can take it off again because there is a handle open.
+	 * I _think_ we're OK here with SMP barriers - a mistaken decision will
+	 * result in this test being false, so we go in and take the locks.
+	 */
+	if (jh->b_transaction == transaction && jh->b_jlist == BJ_Metadata) {
+		JBUFFER_TRACE(jh, "fastpath");
+		J_ASSERT_JH(jh, jh->b_transaction ==
+					journal->j_running_transaction);
+		goto out_unlock_bh;
+	}
+
+	set_buffer_jbddirty(bh);
+
+	/*
+	 * Metadata already on the current transaction list doesn't
+	 * need to be filed.  Metadata on another transaction's list must
+	 * be committing, and will be refiled once the commit completes:
+	 * leave it alone for now.
+	 */
+	if (jh->b_transaction != transaction) {
+		JBUFFER_TRACE(jh, "already on other transaction");
+		J_ASSERT_JH(jh, jh->b_transaction ==
+					journal->j_committing_transaction);
+		J_ASSERT_JH(jh, jh->b_next_transaction == transaction);
+		/* And this case is illegal: we can't reuse another
+		 * transaction's data buffer, ever. */
+		goto out_unlock_bh;
+	}
+
+	/* That test should have eliminated the following case: */
+	J_ASSERT_JH(jh, jh->b_frozen_data == 0);
+
+	JBUFFER_TRACE(jh, "file as BJ_Metadata");
+	spin_lock(&journal->j_list_lock);
+	__jbd2_journal_file_buffer(jh, handle->h_transaction, BJ_Metadata);
+	spin_unlock(&journal->j_list_lock);
+out_unlock_bh:
+	jbd_unlock_bh_state(bh);
+out:
+	JBUFFER_TRACE(jh, "exit");
+	return 0;
+}
+
+/*
+ * jbd2_journal_release_buffer: undo a get_write_access without any buffer
+ * updates, if the update decided in the end that it didn't need access.
+ *
+ */
+void
+jbd2_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
+{
+	BUFFER_TRACE(bh, "entry");
+}
+
+/**
+ * void jbd2_journal_forget() - bforget() for potentially-journaled buffers.
+ * @handle: transaction handle
+ * @bh:     bh to 'forget'
+ *
+ * We can only do the bforget if there are no commits pending against the
+ * buffer.  If the buffer is dirty in the current running transaction we
+ * can safely unlink it.
+ *
+ * bh may not be a journalled buffer at all - it may be a non-JBD
+ * buffer which came off the hashtable.  Check for this.
+ *
+ * Decrements bh->b_count by one.
+ *
+ * Allow this call even if the handle has aborted --- it may be part of
+ * the caller's cleanup after an abort.
+ */
+int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+{
+	transaction_t *transaction = handle->h_transaction;
+	journal_t *journal = transaction->t_journal;
+	struct journal_head *jh;
+	int drop_reserve = 0;
+	int err = 0;
+
+	BUFFER_TRACE(bh, "entry");
+
+	jbd_lock_bh_state(bh);
+	spin_lock(&journal->j_list_lock);
+
+	if (!buffer_jbd(bh))
+		goto not_jbd;
+	jh = bh2jh(bh);
+
+	/* Critical error: attempting to delete a bitmap buffer, maybe?
+	 * Don't do any jbd operations, and return an error. */
+	if (!J_EXPECT_JH(jh, !jh->b_committed_data,
+			 "inconsistent data on disk")) {
+		err = -EIO;
+		goto not_jbd;
+	}
+
+	/*
+	 * The buffer's going from the transaction, we must drop
+	 * all references -bzzz
+	 */
+	jh->b_modified = 0;
+
+	if (jh->b_transaction == handle->h_transaction) {
+		J_ASSERT_JH(jh, !jh->b_frozen_data);
+
+		/* If we are forgetting a buffer which is already part
+		 * of this transaction, then we can just drop it from
+		 * the transaction immediately. */
+		clear_buffer_dirty(bh);
+		clear_buffer_jbddirty(bh);
+
+		JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
+
+		drop_reserve = 1;
+
+		/*
+		 * We are no longer going to journal this buffer.
+		 * However, the commit of this transaction is still
+		 * important to the buffer: the delete that we are now
+		 * processing might obsolete an old log entry, so by
+		 * committing, we can satisfy the buffer's checkpoint.
+		 *
+		 * So, if we have a checkpoint on the buffer, we should
+		 * now refile the buffer on our BJ_Forget list so that
+		 * we know to remove the checkpoint after we commit.
+		 */
+
+		if (jh->b_cp_transaction) {
+			__jbd2_journal_temp_unlink_buffer(jh);
+			__jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
+		} else {
+			__jbd2_journal_unfile_buffer(jh);
+			jbd2_journal_remove_journal_head(bh);
+			__brelse(bh);
+			if (!buffer_jbd(bh)) {
+				spin_unlock(&journal->j_list_lock);
+				jbd_unlock_bh_state(bh);
+				__bforget(bh);
+				goto drop;
+			}
+		}
+	} else if (jh->b_transaction) {
+		J_ASSERT_JH(jh, (jh->b_transaction ==
+				 journal->j_committing_transaction));
+		/* However, if the buffer is still owned by a prior
+		 * (committing) transaction, we can't drop it yet... */
+		JBUFFER_TRACE(jh, "belongs to older transaction");
+		/* ... but we CAN drop it from the new transaction if we
+		 * have also modified it since the original commit. */
+
+		if (jh->b_next_transaction) {
+			J_ASSERT(jh->b_next_transaction == transaction);
+			jh->b_next_transaction = NULL;
+			drop_reserve = 1;
+		}
+	}
+
+not_jbd:
+	spin_unlock(&journal->j_list_lock);
+	jbd_unlock_bh_state(bh);
+	__brelse(bh);
+drop:
+	if (drop_reserve) {
+		/* no need to reserve log space for this block -bzzz */
+		handle->h_buffer_credits++;
+	}
+	return err;
+}
+
+/**
+ * int jbd2_journal_stop() - complete a transaction
+ * @handle: tranaction to complete.
+ *
+ * All done for a particular handle.
+ *
+ * There is not much action needed here.  We just return any remaining
+ * buffer credits to the transaction and remove the handle.  The only
+ * complication is that we need to start a commit operation if the
+ * filesystem is marked for synchronous update.
+ *
+ * jbd2_journal_stop itself will not usually return an error, but it may
+ * do so in unusual circumstances.  In particular, expect it to
+ * return -EIO if a jbd2_journal_abort has been executed since the
+ * transaction began.
+ */
+int jbd2_journal_stop(handle_t *handle)
+{
+	transaction_t *transaction = handle->h_transaction;
+	journal_t *journal = transaction->t_journal;
+	int old_handle_count, err;
+	pid_t pid;
+
+	J_ASSERT(journal_current_handle() == handle);
+
+	if (is_handle_aborted(handle))
+		err = -EIO;
+	else {
+		J_ASSERT(transaction->t_updates > 0);
+		err = 0;
+	}
+
+	if (--handle->h_ref > 0) {
+		jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
+			  handle->h_ref);
+		return err;
+	}
+
+	jbd_debug(4, "Handle %p going down\n", handle);
+
+	/*
+	 * Implement synchronous transaction batching.  If the handle
+	 * was synchronous, don't force a commit immediately.  Let's
+	 * yield and let another thread piggyback onto this transaction.
+	 * Keep doing that while new threads continue to arrive.
+	 * It doesn't cost much - we're about to run a commit and sleep
+	 * on IO anyway.  Speeds up many-threaded, many-dir operations
+	 * by 30x or more...
+	 *
+	 * But don't do this if this process was the most recent one to
+	 * perform a synchronous write.  We do this to detect the case where a
+	 * single process is doing a stream of sync writes.  No point in waiting
+	 * for joiners in that case.
+	 */
+	pid = current->pid;
+	if (handle->h_sync && journal->j_last_sync_writer != pid) {
+		journal->j_last_sync_writer = pid;
+		do {
+			old_handle_count = transaction->t_handle_count;
+			schedule_timeout_uninterruptible(1);
+		} while (old_handle_count != transaction->t_handle_count);
+	}
+
+	current->journal_info = NULL;
+	spin_lock(&journal->j_state_lock);
+	spin_lock(&transaction->t_handle_lock);
+	transaction->t_outstanding_credits -= handle->h_buffer_credits;
+	transaction->t_updates--;
+	if (!transaction->t_updates) {
+		wake_up(&journal->j_wait_updates);
+		if (journal->j_barrier_count)
+			wake_up(&journal->j_wait_transaction_locked);
+	}
+
+	/*
+	 * If the handle is marked SYNC, we need to set another commit
+	 * going!  We also want to force a commit if the current
+	 * transaction is occupying too much of the log, or if the
+	 * transaction is too old now.
+	 */
+	if (handle->h_sync ||
+			transaction->t_outstanding_credits >
+				journal->j_max_transaction_buffers ||
+			time_after_eq(jiffies, transaction->t_expires)) {
+		/* Do this even for aborted journals: an abort still
+		 * completes the commit thread, it just doesn't write
+		 * anything to disk. */
+		tid_t tid = transaction->t_tid;
+
+		spin_unlock(&transaction->t_handle_lock);
+		jbd_debug(2, "transaction too old, requesting commit for "
+					"handle %p\n", handle);
+		/* This is non-blocking */
+		__jbd2_log_start_commit(journal, transaction->t_tid);
+		spin_unlock(&journal->j_state_lock);
+
+		/*
+		 * Special case: JBD2_SYNC synchronous updates require us
+		 * to wait for the commit to complete.
+		 */
+		if (handle->h_sync && !(current->flags & PF_MEMALLOC))
+			err = jbd2_log_wait_commit(journal, tid);
+	} else {
+		spin_unlock(&transaction->t_handle_lock);
+		spin_unlock(&journal->j_state_lock);
+	}
+
+	jbd_free_handle(handle);
+	return err;
+}
+
+/**int jbd2_journal_force_commit() - force any uncommitted transactions
+ * @journal: journal to force
+ *
+ * For synchronous operations: force any uncommitted transactions
+ * to disk.  May seem kludgy, but it reuses all the handle batching
+ * code in a very simple manner.
+ */
+int jbd2_journal_force_commit(journal_t *journal)
+{
+	handle_t *handle;
+	int ret;
+
+	handle = jbd2_journal_start(journal, 1);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+	} else {
+		handle->h_sync = 1;
+		ret = jbd2_journal_stop(handle);
+	}
+	return ret;
+}
+
+/*
+ *
+ * List management code snippets: various functions for manipulating the
+ * transaction buffer lists.
+ *
+ */
+
+/*
+ * Append a buffer to a transaction list, given the transaction's list head
+ * pointer.
+ *
+ * j_list_lock is held.
+ *
+ * jbd_lock_bh_state(jh2bh(jh)) is held.
+ */
+
+static inline void
+__blist_add_buffer(struct journal_head **list, struct journal_head *jh)
+{
+	if (!*list) {
+		jh->b_tnext = jh->b_tprev = jh;
+		*list = jh;
+	} else {
+		/* Insert at the tail of the list to preserve order */
+		struct journal_head *first = *list, *last = first->b_tprev;
+		jh->b_tprev = last;
+		jh->b_tnext = first;
+		last->b_tnext = first->b_tprev = jh;
+	}
+}
+
+/*
+ * Remove a buffer from a transaction list, given the transaction's list
+ * head pointer.
+ *
+ * Called with j_list_lock held, and the journal may not be locked.
+ *
+ * jbd_lock_bh_state(jh2bh(jh)) is held.
+ */
+
+static inline void
+__blist_del_buffer(struct journal_head **list, struct journal_head *jh)
+{
+	if (*list == jh) {
+		*list = jh->b_tnext;
+		if (*list == jh)
+			*list = NULL;
+	}
+	jh->b_tprev->b_tnext = jh->b_tnext;
+	jh->b_tnext->b_tprev = jh->b_tprev;
+}
+
+/*
+ * Remove a buffer from the appropriate transaction list.
+ *
+ * Note that this function can *change* the value of
+ * bh->b_transaction->t_sync_datalist, t_buffers, t_forget,
+ * t_iobuf_list, t_shadow_list, t_log_list or t_reserved_list.  If the caller
+ * is holding onto a copy of one of thee pointers, it could go bad.
+ * Generally the caller needs to re-read the pointer from the transaction_t.
+ *
+ * Called under j_list_lock.  The journal may not be locked.
+ */
+void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh)
+{
+	struct journal_head **list = NULL;
+	transaction_t *transaction;
+	struct buffer_head *bh = jh2bh(jh);
+
+	J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
+	transaction = jh->b_transaction;
+	if (transaction)
+		assert_spin_locked(&transaction->t_journal->j_list_lock);
+
+	J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
+	if (jh->b_jlist != BJ_None)
+		J_ASSERT_JH(jh, transaction != 0);
+
+	switch (jh->b_jlist) {
+	case BJ_None:
+		return;
+	case BJ_SyncData:
+		list = &transaction->t_sync_datalist;
+		break;
+	case BJ_Metadata:
+		transaction->t_nr_buffers--;
+		J_ASSERT_JH(jh, transaction->t_nr_buffers >= 0);
+		list = &transaction->t_buffers;
+		break;
+	case BJ_Forget:
+		list = &transaction->t_forget;
+		break;
+	case BJ_IO:
+		list = &transaction->t_iobuf_list;
+		break;
+	case BJ_Shadow:
+		list = &transaction->t_shadow_list;
+		break;
+	case BJ_LogCtl:
+		list = &transaction->t_log_list;
+		break;
+	case BJ_Reserved:
+		list = &transaction->t_reserved_list;
+		break;
+	case BJ_Locked:
+		list = &transaction->t_locked_list;
+		break;
+	}
+
+	__blist_del_buffer(list, jh);
+	jh->b_jlist = BJ_None;
+	if (test_clear_buffer_jbddirty(bh))
+		mark_buffer_dirty(bh);	/* Expose it to the VM */
+}
+
+void __jbd2_journal_unfile_buffer(struct journal_head *jh)
+{
+	__jbd2_journal_temp_unlink_buffer(jh);
+	jh->b_transaction = NULL;
+}
+
+void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
+{
+	jbd_lock_bh_state(jh2bh(jh));
+	spin_lock(&journal->j_list_lock);
+	__jbd2_journal_unfile_buffer(jh);
+	spin_unlock(&journal->j_list_lock);
+	jbd_unlock_bh_state(jh2bh(jh));
+}
+
+/*
+ * Called from jbd2_journal_try_to_free_buffers().
+ *
+ * Called under jbd_lock_bh_state(bh)
+ */
+static void
+__journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
+{
+	struct journal_head *jh;
+
+	jh = bh2jh(bh);
+
+	if (buffer_locked(bh) || buffer_dirty(bh))
+		goto out;
+
+	if (jh->b_next_transaction != 0)
+		goto out;
+
+	spin_lock(&journal->j_list_lock);
+	if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) {
+		if (jh->b_jlist == BJ_SyncData || jh->b_jlist == BJ_Locked) {
+			/* A written-back ordered data buffer */
+			JBUFFER_TRACE(jh, "release data");
+			__jbd2_journal_unfile_buffer(jh);
+			jbd2_journal_remove_journal_head(bh);
+			__brelse(bh);
+		}
+	} else if (jh->b_cp_transaction != 0 && jh->b_transaction == 0) {
+		/* written-back checkpointed metadata buffer */
+		if (jh->b_jlist == BJ_None) {
+			JBUFFER_TRACE(jh, "remove from checkpoint list");
+			__jbd2_journal_remove_checkpoint(jh);
+			jbd2_journal_remove_journal_head(bh);
+			__brelse(bh);
+		}
+	}
+	spin_unlock(&journal->j_list_lock);
+out:
+	return;
+}
+
+
+/**
+ * int jbd2_journal_try_to_free_buffers() - try to free page buffers.
+ * @journal: journal for operation
+ * @page: to try and free
+ * @unused_gfp_mask: unused
+ *
+ *
+ * For all the buffers on this page,
+ * if they are fully written out ordered data, move them onto BUF_CLEAN
+ * so try_to_free_buffers() can reap them.
+ *
+ * This function returns non-zero if we wish try_to_free_buffers()
+ * to be called. We do this if the page is releasable by try_to_free_buffers().
+ * We also do it if the page has locked or dirty buffers and the caller wants
+ * us to perform sync or async writeout.
+ *
+ * This complicates JBD locking somewhat.  We aren't protected by the
+ * BKL here.  We wish to remove the buffer from its committing or
+ * running transaction's ->t_datalist via __jbd2_journal_unfile_buffer.
+ *
+ * This may *change* the value of transaction_t->t_datalist, so anyone
+ * who looks at t_datalist needs to lock against this function.
+ *
+ * Even worse, someone may be doing a jbd2_journal_dirty_data on this
+ * buffer.  So we need to lock against that.  jbd2_journal_dirty_data()
+ * will come out of the lock with the buffer dirty, which makes it
+ * ineligible for release here.
+ *
+ * Who else is affected by this?  hmm...  Really the only contender
+ * is do_get_write_access() - it could be looking at the buffer while
+ * journal_try_to_free_buffer() is changing its state.  But that
+ * cannot happen because we never reallocate freed data as metadata
+ * while the data is part of a transaction.  Yes?
+ */
+int jbd2_journal_try_to_free_buffers(journal_t *journal,
+				struct page *page, gfp_t unused_gfp_mask)
+{
+	struct buffer_head *head;
+	struct buffer_head *bh;
+	int ret = 0;
+
+	J_ASSERT(PageLocked(page));
+
+	head = page_buffers(page);
+	bh = head;
+	do {
+		struct journal_head *jh;
+
+		/*
+		 * We take our own ref against the journal_head here to avoid
+		 * having to add tons of locking around each instance of
+		 * jbd2_journal_remove_journal_head() and jbd2_journal_put_journal_head().
+		 */
+		jh = jbd2_journal_grab_journal_head(bh);
+		if (!jh)
+			continue;
+
+		jbd_lock_bh_state(bh);
+		__journal_try_to_free_buffer(journal, bh);
+		jbd2_journal_put_journal_head(jh);
+		jbd_unlock_bh_state(bh);
+		if (buffer_jbd(bh))
+			goto busy;
+	} while ((bh = bh->b_this_page) != head);
+	ret = try_to_free_buffers(page);
+busy:
+	return ret;
+}
+
+/*
+ * This buffer is no longer needed.  If it is on an older transaction's
+ * checkpoint list we need to record it on this transaction's forget list
+ * to pin this buffer (and hence its checkpointing transaction) down until
+ * this transaction commits.  If the buffer isn't on a checkpoint list, we
+ * release it.
+ * Returns non-zero if JBD no longer has an interest in the buffer.
+ *
+ * Called under j_list_lock.
+ *
+ * Called under jbd_lock_bh_state(bh).
+ */
+static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
+{
+	int may_free = 1;
+	struct buffer_head *bh = jh2bh(jh);
+
+	__jbd2_journal_unfile_buffer(jh);
+
+	if (jh->b_cp_transaction) {
+		JBUFFER_TRACE(jh, "on running+cp transaction");
+		__jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
+		clear_buffer_jbddirty(bh);
+		may_free = 0;
+	} else {
+		JBUFFER_TRACE(jh, "on running transaction");
+		jbd2_journal_remove_journal_head(bh);
+		__brelse(bh);
+	}
+	return may_free;
+}
+
+/*
+ * jbd2_journal_invalidatepage
+ *
+ * This code is tricky.  It has a number of cases to deal with.
+ *
+ * There are two invariants which this code relies on:
+ *
+ * i_size must be updated on disk before we start calling invalidatepage on the
+ * data.
+ *
+ *  This is done in ext3 by defining an ext3_setattr method which
+ *  updates i_size before truncate gets going.  By maintaining this
+ *  invariant, we can be sure that it is safe to throw away any buffers
+ *  attached to the current transaction: once the transaction commits,
+ *  we know that the data will not be needed.
+ *
+ *  Note however that we can *not* throw away data belonging to the
+ *  previous, committing transaction!
+ *
+ * Any disk blocks which *are* part of the previous, committing
+ * transaction (and which therefore cannot be discarded immediately) are
+ * not going to be reused in the new running transaction
+ *
+ *  The bitmap committed_data images guarantee this: any block which is
+ *  allocated in one transaction and removed in the next will be marked
+ *  as in-use in the committed_data bitmap, so cannot be reused until
+ *  the next transaction to delete the block commits.  This means that
+ *  leaving committing buffers dirty is quite safe: the disk blocks
+ *  cannot be reallocated to a different file and so buffer aliasing is
+ *  not possible.
+ *
+ *
+ * The above applies mainly to ordered data mode.  In writeback mode we
+ * don't make guarantees about the order in which data hits disk --- in
+ * particular we don't guarantee that new dirty data is flushed before
+ * transaction commit --- so it is always safe just to discard data
+ * immediately in that mode.  --sct
+ */
+
+/*
+ * The journal_unmap_buffer helper function returns zero if the buffer
+ * concerned remains pinned as an anonymous buffer belonging to an older
+ * transaction.
+ *
+ * We're outside-transaction here.  Either or both of j_running_transaction
+ * and j_committing_transaction may be NULL.
+ */
+static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+{
+	transaction_t *transaction;
+	struct journal_head *jh;
+	int may_free = 1;
+	int ret;
+
+	BUFFER_TRACE(bh, "entry");
+
+	/*
+	 * It is safe to proceed here without the j_list_lock because the
+	 * buffers cannot be stolen by try_to_free_buffers as long as we are
+	 * holding the page lock. --sct
+	 */
+
+	if (!buffer_jbd(bh))
+		goto zap_buffer_unlocked;
+
+	spin_lock(&journal->j_state_lock);
+	jbd_lock_bh_state(bh);
+	spin_lock(&journal->j_list_lock);
+
+	jh = jbd2_journal_grab_journal_head(bh);
+	if (!jh)
+		goto zap_buffer_no_jh;
+
+	transaction = jh->b_transaction;
+	if (transaction == NULL) {
+		/* First case: not on any transaction.  If it
+		 * has no checkpoint link, then we can zap it:
+		 * it's a writeback-mode buffer so we don't care
+		 * if it hits disk safely. */
+		if (!jh->b_cp_transaction) {
+			JBUFFER_TRACE(jh, "not on any transaction: zap");
+			goto zap_buffer;
+		}
+
+		if (!buffer_dirty(bh)) {
+			/* bdflush has written it.  We can drop it now */
+			goto zap_buffer;
+		}
+
+		/* OK, it must be in the journal but still not
+		 * written fully to disk: it's metadata or
+		 * journaled data... */
+
+		if (journal->j_running_transaction) {
+			/* ... and once the current transaction has
+			 * committed, the buffer won't be needed any
+			 * longer. */
+			JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
+			ret = __dispose_buffer(jh,
+					journal->j_running_transaction);
+			jbd2_journal_put_journal_head(jh);
+			spin_unlock(&journal->j_list_lock);
+			jbd_unlock_bh_state(bh);
+			spin_unlock(&journal->j_state_lock);
+			return ret;
+		} else {
+			/* There is no currently-running transaction. So the
+			 * orphan record which we wrote for this file must have
+			 * passed into commit.  We must attach this buffer to
+			 * the committing transaction, if it exists. */
+			if (journal->j_committing_transaction) {
+				JBUFFER_TRACE(jh, "give to committing trans");
+				ret = __dispose_buffer(jh,
+					journal->j_committing_transaction);
+				jbd2_journal_put_journal_head(jh);
+				spin_unlock(&journal->j_list_lock);
+				jbd_unlock_bh_state(bh);
+				spin_unlock(&journal->j_state_lock);
+				return ret;
+			} else {
+				/* The orphan record's transaction has
+				 * committed.  We can cleanse this buffer */
+				clear_buffer_jbddirty(bh);
+				goto zap_buffer;
+			}
+		}
+	} else if (transaction == journal->j_committing_transaction) {
+		if (jh->b_jlist == BJ_Locked) {
+			/*
+			 * The buffer is on the committing transaction's locked
+			 * list.  We have the buffer locked, so I/O has
+			 * completed.  So we can nail the buffer now.
+			 */
+			may_free = __dispose_buffer(jh, transaction);
+			goto zap_buffer;
+		}
+		/*
+		 * If it is committing, we simply cannot touch it.  We
+		 * can remove it's next_transaction pointer from the
+		 * running transaction if that is set, but nothing
+		 * else. */
+		JBUFFER_TRACE(jh, "on committing transaction");
+		set_buffer_freed(bh);
+		if (jh->b_next_transaction) {
+			J_ASSERT(jh->b_next_transaction ==
+					journal->j_running_transaction);
+			jh->b_next_transaction = NULL;
+		}
+		jbd2_journal_put_journal_head(jh);
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		spin_unlock(&journal->j_state_lock);
+		return 0;
+	} else {
+		/* Good, the buffer belongs to the running transaction.
+		 * We are writing our own transaction's data, not any
+		 * previous one's, so it is safe to throw it away
+		 * (remember that we expect the filesystem to have set
+		 * i_size already for this truncate so recovery will not
+		 * expose the disk blocks we are discarding here.) */
+		J_ASSERT_JH(jh, transaction == journal->j_running_transaction);
+		may_free = __dispose_buffer(jh, transaction);
+	}
+
+zap_buffer:
+	jbd2_journal_put_journal_head(jh);
+zap_buffer_no_jh:
+	spin_unlock(&journal->j_list_lock);
+	jbd_unlock_bh_state(bh);
+	spin_unlock(&journal->j_state_lock);
+zap_buffer_unlocked:
+	clear_buffer_dirty(bh);
+	J_ASSERT_BH(bh, !buffer_jbddirty(bh));
+	clear_buffer_mapped(bh);
+	clear_buffer_req(bh);
+	clear_buffer_new(bh);
+	bh->b_bdev = NULL;
+	return may_free;
+}
+
+/**
+ * void jbd2_journal_invalidatepage()
+ * @journal: journal to use for flush...
+ * @page:    page to flush
+ * @offset:  length of page to invalidate.
+ *
+ * Reap page buffers containing data after offset in page.
+ *
+ */
+void jbd2_journal_invalidatepage(journal_t *journal,
+		      struct page *page,
+		      unsigned long offset)
+{
+	struct buffer_head *head, *bh, *next;
+	unsigned int curr_off = 0;
+	int may_free = 1;
+
+	if (!PageLocked(page))
+		BUG();
+	if (!page_has_buffers(page))
+		return;
+
+	/* We will potentially be playing with lists other than just the
+	 * data lists (especially for journaled data mode), so be
+	 * cautious in our locking. */
+
+	head = bh = page_buffers(page);
+	do {
+		unsigned int next_off = curr_off + bh->b_size;
+		next = bh->b_this_page;
+
+		if (offset <= curr_off) {
+			/* This block is wholly outside the truncation point */
+			lock_buffer(bh);
+			may_free &= journal_unmap_buffer(journal, bh);
+			unlock_buffer(bh);
+		}
+		curr_off = next_off;
+		bh = next;
+
+	} while (bh != head);
+
+	if (!offset) {
+		if (may_free && try_to_free_buffers(page))
+			J_ASSERT(!page_has_buffers(page));
+	}
+}
+
+/*
+ * File a buffer on the given transaction list.
+ */
+void __jbd2_journal_file_buffer(struct journal_head *jh,
+			transaction_t *transaction, int jlist)
+{
+	struct journal_head **list = NULL;
+	int was_dirty = 0;
+	struct buffer_head *bh = jh2bh(jh);
+
+	J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
+	assert_spin_locked(&transaction->t_journal->j_list_lock);
+
+	J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
+	J_ASSERT_JH(jh, jh->b_transaction == transaction ||
+				jh->b_transaction == 0);
+
+	if (jh->b_transaction && jh->b_jlist == jlist)
+		return;
+
+	/* The following list of buffer states needs to be consistent
+	 * with __jbd_unexpected_dirty_buffer()'s handling of dirty
+	 * state. */
+
+	if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
+	    jlist == BJ_Shadow || jlist == BJ_Forget) {
+		if (test_clear_buffer_dirty(bh) ||
+		    test_clear_buffer_jbddirty(bh))
+			was_dirty = 1;
+	}
+
+	if (jh->b_transaction)
+		__jbd2_journal_temp_unlink_buffer(jh);
+	jh->b_transaction = transaction;
+
+	switch (jlist) {
+	case BJ_None:
+		J_ASSERT_JH(jh, !jh->b_committed_data);
+		J_ASSERT_JH(jh, !jh->b_frozen_data);
+		return;
+	case BJ_SyncData:
+		list = &transaction->t_sync_datalist;
+		break;
+	case BJ_Metadata:
+		transaction->t_nr_buffers++;
+		list = &transaction->t_buffers;
+		break;
+	case BJ_Forget:
+		list = &transaction->t_forget;
+		break;
+	case BJ_IO:
+		list = &transaction->t_iobuf_list;
+		break;
+	case BJ_Shadow:
+		list = &transaction->t_shadow_list;
+		break;
+	case BJ_LogCtl:
+		list = &transaction->t_log_list;
+		break;
+	case BJ_Reserved:
+		list = &transaction->t_reserved_list;
+		break;
+	case BJ_Locked:
+		list =  &transaction->t_locked_list;
+		break;
+	}
+
+	__blist_add_buffer(list, jh);
+	jh->b_jlist = jlist;
+
+	if (was_dirty)
+		set_buffer_jbddirty(bh);
+}
+
+void jbd2_journal_file_buffer(struct journal_head *jh,
+				transaction_t *transaction, int jlist)
+{
+	jbd_lock_bh_state(jh2bh(jh));
+	spin_lock(&transaction->t_journal->j_list_lock);
+	__jbd2_journal_file_buffer(jh, transaction, jlist);
+	spin_unlock(&transaction->t_journal->j_list_lock);
+	jbd_unlock_bh_state(jh2bh(jh));
+}
+
+/*
+ * Remove a buffer from its current buffer list in preparation for
+ * dropping it from its current transaction entirely.  If the buffer has
+ * already started to be used by a subsequent transaction, refile the
+ * buffer on that transaction's metadata list.
+ *
+ * Called under journal->j_list_lock
+ *
+ * Called under jbd_lock_bh_state(jh2bh(jh))
+ */
+void __jbd2_journal_refile_buffer(struct journal_head *jh)
+{
+	int was_dirty;
+	struct buffer_head *bh = jh2bh(jh);
+
+	J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
+	if (jh->b_transaction)
+		assert_spin_locked(&jh->b_transaction->t_journal->j_list_lock);
+
+	/* If the buffer is now unused, just drop it. */
+	if (jh->b_next_transaction == NULL) {
+		__jbd2_journal_unfile_buffer(jh);
+		return;
+	}
+
+	/*
+	 * It has been modified by a later transaction: add it to the new
+	 * transaction's metadata list.
+	 */
+
+	was_dirty = test_clear_buffer_jbddirty(bh);
+	__jbd2_journal_temp_unlink_buffer(jh);
+	jh->b_transaction = jh->b_next_transaction;
+	jh->b_next_transaction = NULL;
+	__jbd2_journal_file_buffer(jh, jh->b_transaction,
+				was_dirty ? BJ_Metadata : BJ_Reserved);
+	J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
+
+	if (was_dirty)
+		set_buffer_jbddirty(bh);
+}
+
+/*
+ * For the unlocked version of this call, also make sure that any
+ * hanging journal_head is cleaned up if necessary.
+ *
+ * __jbd2_journal_refile_buffer is usually called as part of a single locked
+ * operation on a buffer_head, in which the caller is probably going to
+ * be hooking the journal_head onto other lists.  In that case it is up
+ * to the caller to remove the journal_head if necessary.  For the
+ * unlocked jbd2_journal_refile_buffer call, the caller isn't going to be
+ * doing anything else to the buffer so we need to do the cleanup
+ * ourselves to avoid a jh leak.
+ *
+ * *** The journal_head may be freed by this call! ***
+ */
+void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh)
+{
+	struct buffer_head *bh = jh2bh(jh);
+
+	jbd_lock_bh_state(bh);
+	spin_lock(&journal->j_list_lock);
+
+	__jbd2_journal_refile_buffer(jh);
+	jbd_unlock_bh_state(bh);
+	jbd2_journal_remove_journal_head(bh);
+
+	spin_unlock(&journal->j_list_lock);
+	__brelse(bh);
+}
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 6de3745..bc4b810 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -334,10 +334,10 @@
 	   which means just 'no padding', without the alignment
 	   thing. But GCC doesn't have that -- we have to just
 	   hope the structs are the right sizes, instead. */
-	BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
-	BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
-	BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
-	BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
+	BUILD_BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
+	BUILD_BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
+	BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
+	BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
 
 	printk(KERN_INFO "JFFS2 version 2.2."
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 489a3d6..ee9b473 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -318,7 +318,7 @@
 	struct inomap *imap;
 	int block_offset;
 	int inodes_left;
-	uint pageno;
+	unsigned long pageno;
 	int rel_inode;
 
 	jfs_info("diRead: ino = %ld", ip->i_ino);
@@ -606,7 +606,7 @@
 	int block_offset;
 	int inodes_left;
 	struct metapage *mp;
-	uint pageno;
+	unsigned long pageno;
 	int rel_inode;
 	int dioffset;
 	struct inode *ipimap;
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index e8c7765..b85a0ad 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -100,12 +100,12 @@
 /*
  * The server lockd has called us back to tell us the lock was granted
  */
-u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
+__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
 {
 	const struct file_lock *fl = &lock->fl;
 	const struct nfs_fh *fh = &lock->fh;
 	struct nlm_wait	*block;
-	u32 res = nlm_lck_denied;
+	__be32 res = nlm_lck_denied;
 
 	/*
 	 * Look up blocked request based on arguments. 
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index e0179f8..eb243ed 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -148,8 +148,8 @@
  * XDR functions for NSM.
  */
 
-static u32 *
-xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
+static __be32 *
+xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
 {
 	char	buffer[20], *name;
 
@@ -176,7 +176,7 @@
 }
 
 static int
-xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
+xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
 {
 	p = xdr_encode_common(rqstp, p, argp);
 	if (IS_ERR(p))
@@ -192,7 +192,7 @@
 }
 
 static int
-xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
+xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
 {
 	p = xdr_encode_common(rqstp, p, argp);
 	if (IS_ERR(p))
@@ -202,7 +202,7 @@
 }
 
 static int
-xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
+xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
 {
 	resp->status = ntohl(*p++);
 	resp->state = ntohl(*p++);
@@ -212,7 +212,7 @@
 }
 
 static int
-xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
+xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
 {
 	resp->state = ntohl(*p++);
 	return 0;
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index fa370f6..0ce5c81 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -24,14 +24,14 @@
 /*
  * Obtain client and file from arguments
  */
-static u32
+static __be32
 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 			struct nlm_host **hostp, struct nlm_file **filp)
 {
 	struct nlm_host		*host = NULL;
 	struct nlm_file		*file = NULL;
 	struct nlm_lock		*lock = &argp->lock;
-	u32			error = 0;
+	__be32			error = 0;
 
 	/* nfsd callbacks must have been installed for this procedure */
 	if (!nlmsvc_ops)
@@ -68,7 +68,7 @@
 /*
  * NULL: Test for presence of service
  */
-static int
+static __be32
 nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	dprintk("lockd: NULL          called\n");
@@ -78,7 +78,7 @@
 /*
  * TEST: Check for conflicting lock
  */
-static int
+static __be32
 nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
 				         struct nlm_res  *resp)
 {
@@ -96,7 +96,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now check for conflicting locks */
 	resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
@@ -107,7 +107,7 @@
 	return rpc_success;
 }
 
-static int
+static __be32
 nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 				         struct nlm_res  *resp)
 {
@@ -126,7 +126,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 #if 0
 	/* If supplied state doesn't match current state, we assume it's
@@ -150,7 +150,7 @@
 	return rpc_success;
 }
 
-static int
+static __be32
 nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
 				           struct nlm_res  *resp)
 {
@@ -169,7 +169,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Try to cancel request. */
 	resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
@@ -183,7 +183,7 @@
 /*
  * UNLOCK: release a lock
  */
-static int
+static __be32
 nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
 				           struct nlm_res  *resp)
 {
@@ -202,7 +202,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now try to remove the lock */
 	resp->status = nlmsvc_unlock(file, &argp->lock);
@@ -217,7 +217,7 @@
  * GRANTED: A server calls us to tell that a process' lock request
  * was granted
  */
-static int
+static __be32
 nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
 				            struct nlm_res  *resp)
 {
@@ -253,12 +253,12 @@
  * because we send the callback before the reply proper. I hope this
  * doesn't break any clients.
  */
-static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
-		int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
+static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
+		__be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
 {
 	struct nlm_host	*host;
 	struct nlm_rqst	*call;
-	int stat;
+	__be32 stat;
 
 	host = nlmsvc_lookup_host(rqstp,
 				  argp->lock.caller,
@@ -282,35 +282,35 @@
 	return rpc_success;
 }
 
-static int nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 					     void	     *resp)
 {
 	dprintk("lockd: TEST_MSG      called\n");
 	return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test);
 }
 
-static int nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 					     void	     *resp)
 {
 	dprintk("lockd: LOCK_MSG      called\n");
 	return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock);
 }
 
-static int nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 					       void	       *resp)
 {
 	dprintk("lockd: CANCEL_MSG    called\n");
 	return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel);
 }
 
-static int nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                                void            *resp)
 {
 	dprintk("lockd: UNLOCK_MSG    called\n");
 	return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock);
 }
 
-static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                                 void            *resp)
 {
 	dprintk("lockd: GRANTED_MSG   called\n");
@@ -320,7 +320,7 @@
 /*
  * SHARE: create a DOS share or alter existing share.
  */
-static int
+static __be32
 nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
 				          struct nlm_res  *resp)
 {
@@ -339,7 +339,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now try to create the share */
 	resp->status = nlmsvc_share_file(host, file, argp);
@@ -353,7 +353,7 @@
 /*
  * UNSHARE: Release a DOS share.
  */
-static int
+static __be32
 nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
 				            struct nlm_res  *resp)
 {
@@ -372,7 +372,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now try to lock the file */
 	resp->status = nlmsvc_unshare_file(host, file, argp);
@@ -386,7 +386,7 @@
 /*
  * NM_LOCK: Create an unmonitored lock
  */
-static int
+static __be32
 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 				            struct nlm_res  *resp)
 {
@@ -399,7 +399,7 @@
 /*
  * FREE_ALL: Release all locks and shares held by client
  */
-static int
+static __be32
 nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
 					     void            *resp)
 {
@@ -417,7 +417,7 @@
 /*
  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
  */
-static int
+static __be32
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
@@ -446,7 +446,7 @@
 /*
  * client sent a GRANTED_RES, let's remove the associated block
  */
-static int
+static __be32
 nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res  *argp,
                                                 void            *resp)
 {
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 814c606..7e219b9 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -334,13 +334,13 @@
  * Attempt to establish a lock, and if it can't be granted, block it
  * if required.
  */
-u32
+__be32
 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 			struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
 {
 	struct nlm_block	*block, *newblock = NULL;
 	int			error;
-	u32			ret;
+	__be32			ret;
 
 	dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
 				file->f_file->f_dentry->d_inode->i_sb->s_id,
@@ -415,7 +415,7 @@
 /*
  * Test for presence of a conflicting lock.
  */
-u32
+__be32
 nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
 				       struct nlm_lock *conflock)
 {
@@ -448,7 +448,7 @@
  * afterwards. In this case the block will still be there, and hence
  * must be removed.
  */
-u32
+__be32
 nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
 {
 	int	error;
@@ -476,7 +476,7 @@
  * be in progress.
  * The calling procedure must check whether the file can be closed.
  */
-u32
+__be32
 nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
 {
 	struct nlm_block	*block;
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 75b2c81..32e99a6 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -22,8 +22,8 @@
 #define NLMDBG_FACILITY		NLMDBG_CLIENT
 
 #ifdef CONFIG_LOCKD_V4
-static u32
-cast_to_nlm(u32 status, u32 vers)
+static __be32
+cast_to_nlm(__be32 status, u32 vers)
 {
 	/* Note: status is assumed to be in network byte order !!! */
 	if (vers != 4){
@@ -52,14 +52,14 @@
 /*
  * Obtain client and file from arguments
  */
-static u32
+static __be32
 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 			struct nlm_host **hostp, struct nlm_file **filp)
 {
 	struct nlm_host		*host = NULL;
 	struct nlm_file		*file = NULL;
 	struct nlm_lock		*lock = &argp->lock;
-	u32			error;
+	__be32			error = 0;
 
 	/* nfsd callbacks must have been installed for this procedure */
 	if (!nlmsvc_ops)
@@ -88,13 +88,15 @@
 no_locks:
 	if (host)
 		nlm_release_host(host);
+	if (error)
+		return error;
 	return nlm_lck_denied_nolocks;
 }
 
 /*
  * NULL: Test for presence of service
  */
-static int
+static __be32
 nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	dprintk("lockd: NULL          called\n");
@@ -104,7 +106,7 @@
 /*
  * TEST: Check for conflicting lock
  */
-static int
+static __be32
 nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
 				         struct nlm_res  *resp)
 {
@@ -122,7 +124,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now check for conflicting locks */
 	resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock));
@@ -134,7 +136,7 @@
 	return rpc_success;
 }
 
-static int
+static __be32
 nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 				         struct nlm_res  *resp)
 {
@@ -153,7 +155,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 #if 0
 	/* If supplied state doesn't match current state, we assume it's
@@ -177,7 +179,7 @@
 	return rpc_success;
 }
 
-static int
+static __be32
 nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
 				           struct nlm_res  *resp)
 {
@@ -196,7 +198,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Try to cancel request. */
 	resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock));
@@ -210,7 +212,7 @@
 /*
  * UNLOCK: release a lock
  */
-static int
+static __be32
 nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
 				           struct nlm_res  *resp)
 {
@@ -229,7 +231,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now try to remove the lock */
 	resp->status = cast_status(nlmsvc_unlock(file, &argp->lock));
@@ -244,7 +246,7 @@
  * GRANTED: A server calls us to tell that a process' lock request
  * was granted
  */
-static int
+static __be32
 nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
 				            struct nlm_res  *resp)
 {
@@ -280,12 +282,12 @@
  * because we send the callback before the reply proper. I hope this
  * doesn't break any clients.
  */
-static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
-		int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
+static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
+		__be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
 {
 	struct nlm_host	*host;
 	struct nlm_rqst	*call;
-	int stat;
+	__be32 stat;
 
 	host = nlmsvc_lookup_host(rqstp,
 				  argp->lock.caller,
@@ -309,28 +311,28 @@
 	return rpc_success;
 }
 
-static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 					     void	     *resp)
 {
 	dprintk("lockd: TEST_MSG      called\n");
 	return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test);
 }
 
-static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 					     void	     *resp)
 {
 	dprintk("lockd: LOCK_MSG      called\n");
 	return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock);
 }
 
-static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 					       void	       *resp)
 {
 	dprintk("lockd: CANCEL_MSG    called\n");
 	return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel);
 }
 
-static int
+static __be32
 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                                void            *resp)
 {
@@ -338,7 +340,7 @@
 	return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock);
 }
 
-static int
+static __be32
 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                                 void            *resp)
 {
@@ -349,7 +351,7 @@
 /*
  * SHARE: create a DOS share or alter existing share.
  */
-static int
+static __be32
 nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
 				          struct nlm_res  *resp)
 {
@@ -368,7 +370,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now try to create the share */
 	resp->status = cast_status(nlmsvc_share_file(host, file, argp));
@@ -382,7 +384,7 @@
 /*
  * UNSHARE: Release a DOS share.
  */
-static int
+static __be32
 nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
 				            struct nlm_res  *resp)
 {
@@ -401,7 +403,7 @@
 
 	/* Obtain client and file */
 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-		return rpc_success;
+		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 	/* Now try to unshare the file */
 	resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
@@ -415,7 +417,7 @@
 /*
  * NM_LOCK: Create an unmonitored lock
  */
-static int
+static __be32
 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 				            struct nlm_res  *resp)
 {
@@ -428,7 +430,7 @@
 /*
  * FREE_ALL: Release all locks and shares held by client
  */
-static int
+static __be32
 nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
 					     void            *resp)
 {
@@ -446,7 +448,7 @@
 /*
  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
  */
-static int
+static __be32
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
@@ -475,7 +477,7 @@
 /*
  * client sent a GRANTED_RES, let's remove the associated block
  */
-static int
+static __be32
 nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res  *argp,
                                                 void            *resp)
 {
diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
index b9926ce..6220dc2 100644
--- a/fs/lockd/svcshare.c
+++ b/fs/lockd/svcshare.c
@@ -23,7 +23,7 @@
 	    && !memcmp(share->s_owner.data, oh->data, oh->len);
 }
 
-u32
+__be32
 nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
 			struct nlm_args *argp)
 {
@@ -64,7 +64,7 @@
 /*
  * Delete a share.
  */
-u32
+__be32
 nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
 			struct nlm_args *argp)
 {
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 514f5f2..e83024e 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -78,14 +78,14 @@
  * This is not quite right, but for now, we assume the client performs
  * the proper R/W checking.
  */
-u32
+__be32
 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
 					struct nfs_fh *f)
 {
 	struct hlist_node *pos;
 	struct nlm_file	*file;
 	unsigned int	hash;
-	u32		nfserr;
+	__be32		nfserr;
 
 	nlm_debug_print_fh("nlm_file_lookup", f);
 
@@ -135,12 +135,6 @@
 
 out_free:
 	kfree(file);
-#ifdef CONFIG_LOCKD_V4
-	if (nfserr == 1)
-		nfserr = nlm4_stale_fh;
-	else
-#endif
-	nfserr = nlm_lck_denied;
 	goto out_unlock;
 }
 
@@ -324,7 +318,16 @@
 static int
 nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy)
 {
-	return host->h_server;
+	if (host->h_server) {
+		/* we are destroying locks even though the client
+		 * hasn't asked us too, so don't unmonitor the
+		 * client
+		 */
+		if (host->h_nsmhandle)
+			host->h_nsmhandle->sm_sticky = 1;
+		return 1;
+	} else
+		return 0;
 }
 
 /*
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 61c46fa..b7c9492 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -43,7 +43,7 @@
 /*
  * XDR functions for basic NLM types
  */
-static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c)
+static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c)
 {
 	unsigned int	len;
 
@@ -69,8 +69,8 @@
 	return p;
 }
 
-static inline u32 *
-nlm_encode_cookie(u32 *p, struct nlm_cookie *c)
+static inline __be32 *
+nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
 {
 	*p++ = htonl(c->len);
 	memcpy(p, c->data, c->len);
@@ -78,8 +78,8 @@
 	return p;
 }
 
-static u32 *
-nlm_decode_fh(u32 *p, struct nfs_fh *f)
+static __be32 *
+nlm_decode_fh(__be32 *p, struct nfs_fh *f)
 {
 	unsigned int	len;
 
@@ -95,8 +95,8 @@
 	return p + XDR_QUADLEN(NFS2_FHSIZE);
 }
 
-static inline u32 *
-nlm_encode_fh(u32 *p, struct nfs_fh *f)
+static inline __be32 *
+nlm_encode_fh(__be32 *p, struct nfs_fh *f)
 {
 	*p++ = htonl(NFS2_FHSIZE);
 	memcpy(p, f->data, NFS2_FHSIZE);
@@ -106,20 +106,20 @@
 /*
  * Encode and decode owner handle
  */
-static inline u32 *
-nlm_decode_oh(u32 *p, struct xdr_netobj *oh)
+static inline __be32 *
+nlm_decode_oh(__be32 *p, struct xdr_netobj *oh)
 {
 	return xdr_decode_netobj(p, oh);
 }
 
-static inline u32 *
-nlm_encode_oh(u32 *p, struct xdr_netobj *oh)
+static inline __be32 *
+nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
 {
 	return xdr_encode_netobj(p, oh);
 }
 
-static u32 *
-nlm_decode_lock(u32 *p, struct nlm_lock *lock)
+static __be32 *
+nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
 {
 	struct file_lock	*fl = &lock->fl;
 	s32			start, len, end;
@@ -153,8 +153,8 @@
 /*
  * Encode a lock as part of an NLM call
  */
-static u32 *
-nlm_encode_lock(u32 *p, struct nlm_lock *lock)
+static __be32 *
+nlm_encode_lock(__be32 *p, struct nlm_lock *lock)
 {
 	struct file_lock	*fl = &lock->fl;
 	__s32			start, len;
@@ -184,8 +184,8 @@
 /*
  * Encode result of a TEST/TEST_MSG call
  */
-static u32 *
-nlm_encode_testres(u32 *p, struct nlm_res *resp)
+static __be32 *
+nlm_encode_testres(__be32 *p, struct nlm_res *resp)
 {
 	s32		start, len;
 
@@ -221,7 +221,7 @@
  * First, the server side XDR functions
  */
 int
-nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	u32	exclusive;
 
@@ -238,7 +238,7 @@
 }
 
 int
-nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_encode_testres(p, resp)))
 		return 0;
@@ -246,7 +246,7 @@
 }
 
 int
-nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	u32	exclusive;
 
@@ -266,7 +266,7 @@
 }
 
 int
-nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	u32	exclusive;
 
@@ -282,7 +282,7 @@
 }
 
 int
-nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	if (!(p = nlm_decode_cookie(p, &argp->cookie))
 	 || !(p = nlm_decode_lock(p, &argp->lock)))
@@ -292,7 +292,7 @@
 }
 
 int
-nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -313,7 +313,7 @@
 }
 
 int
-nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return 0;
@@ -323,7 +323,7 @@
 }
 
 int
-nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return 0;
@@ -332,7 +332,7 @@
 }
 
 int
-nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp)
+nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -344,7 +344,7 @@
 }
 
 int
-nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
+nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
 {
 	if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
 		return 0;
@@ -357,7 +357,7 @@
 }
 
 int
-nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 		return 0;
@@ -366,13 +366,13 @@
 }
 
 int
-nlmsvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_argsize_check(rqstp, p);
 }
 
 int
-nlmsvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_ressize_check(rqstp, p);
 }
@@ -389,7 +389,7 @@
 #endif
 
 static int
-nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlmclt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -403,7 +403,7 @@
 }
 
 static int
-nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlmclt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 		return -EIO;
@@ -438,7 +438,7 @@
 
 
 static int
-nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlmclt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -455,7 +455,7 @@
 }
 
 static int
-nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlmclt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -470,7 +470,7 @@
 }
 
 static int
-nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlmclt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -483,7 +483,7 @@
 }
 
 static int
-nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlmclt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return -EIO;
@@ -493,7 +493,7 @@
 }
 
 static int
-nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlmclt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_encode_testres(p, resp)))
 		return -EIO;
@@ -502,7 +502,7 @@
 }
 
 static int
-nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 		return -EIO;
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 36eb175..f4c0b2b 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -44,8 +44,8 @@
 /*
  * XDR functions for basic NLM types
  */
-static u32 *
-nlm4_decode_cookie(u32 *p, struct nlm_cookie *c)
+static __be32 *
+nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
 {
 	unsigned int	len;
 
@@ -71,8 +71,8 @@
 	return p;
 }
 
-static u32 *
-nlm4_encode_cookie(u32 *p, struct nlm_cookie *c)
+static __be32 *
+nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
 {
 	*p++ = htonl(c->len);
 	memcpy(p, c->data, c->len);
@@ -80,8 +80,8 @@
 	return p;
 }
 
-static u32 *
-nlm4_decode_fh(u32 *p, struct nfs_fh *f)
+static __be32 *
+nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
 {
 	memset(f->data, 0, sizeof(f->data));
 	f->size = ntohl(*p++);
@@ -95,8 +95,8 @@
 	return p + XDR_QUADLEN(f->size);
 }
 
-static u32 *
-nlm4_encode_fh(u32 *p, struct nfs_fh *f)
+static __be32 *
+nlm4_encode_fh(__be32 *p, struct nfs_fh *f)
 {
 	*p++ = htonl(f->size);
 	if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */
@@ -107,20 +107,20 @@
 /*
  * Encode and decode owner handle
  */
-static u32 *
-nlm4_decode_oh(u32 *p, struct xdr_netobj *oh)
+static __be32 *
+nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
 {
 	return xdr_decode_netobj(p, oh);
 }
 
-static u32 *
-nlm4_encode_oh(u32 *p, struct xdr_netobj *oh)
+static __be32 *
+nlm4_encode_oh(__be32 *p, struct xdr_netobj *oh)
 {
 	return xdr_encode_netobj(p, oh);
 }
 
-static u32 *
-nlm4_decode_lock(u32 *p, struct nlm_lock *lock)
+static __be32 *
+nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
 {
 	struct file_lock	*fl = &lock->fl;
 	__s64			len, start, end;
@@ -153,8 +153,8 @@
 /*
  * Encode a lock as part of an NLM call
  */
-static u32 *
-nlm4_encode_lock(u32 *p, struct nlm_lock *lock)
+static __be32 *
+nlm4_encode_lock(__be32 *p, struct nlm_lock *lock)
 {
 	struct file_lock	*fl = &lock->fl;
 	__s64			start, len;
@@ -185,8 +185,8 @@
 /*
  * Encode result of a TEST/TEST_MSG call
  */
-static u32 *
-nlm4_encode_testres(u32 *p, struct nlm_res *resp)
+static __be32 *
+nlm4_encode_testres(__be32 *p, struct nlm_res *resp)
 {
 	s64		start, len;
 
@@ -227,7 +227,7 @@
  * First, the server side XDR functions
  */
 int
-nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	u32	exclusive;
 
@@ -244,7 +244,7 @@
 }
 
 int
-nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_encode_testres(p, resp)))
 		return 0;
@@ -252,7 +252,7 @@
 }
 
 int
-nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	u32	exclusive;
 
@@ -272,7 +272,7 @@
 }
 
 int
-nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	u32	exclusive;
 
@@ -288,7 +288,7 @@
 }
 
 int
-nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	if (!(p = nlm4_decode_cookie(p, &argp->cookie))
 	 || !(p = nlm4_decode_lock(p, &argp->lock)))
@@ -298,7 +298,7 @@
 }
 
 int
-nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
+nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -319,7 +319,7 @@
 }
 
 int
-nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 		return 0;
@@ -329,7 +329,7 @@
 }
 
 int
-nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 		return 0;
@@ -338,7 +338,7 @@
 }
 
 int
-nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp)
+nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -350,7 +350,7 @@
 }
 
 int
-nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
+nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
 {
 	if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
 		return 0;
@@ -363,7 +363,7 @@
 }
 
 int
-nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
+nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 		return 0;
@@ -372,13 +372,13 @@
 }
 
 int
-nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_argsize_check(rqstp, p);
 }
 
 int
-nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_ressize_check(rqstp, p);
 }
@@ -388,14 +388,14 @@
  */
 #ifdef NLMCLNT_SUPPORT_SHARES
 static int
-nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr)
+nlm4clt_decode_void(struct rpc_rqst *req, __be32 *p, void *ptr)
 {
 	return 0;
 }
 #endif
 
 static int
-nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlm4clt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -409,7 +409,7 @@
 }
 
 static int
-nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 		return -EIO;
@@ -444,7 +444,7 @@
 
 
 static int
-nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlm4clt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -461,7 +461,7 @@
 }
 
 static int
-nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlm4clt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -476,7 +476,7 @@
 }
 
 static int
-nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
+nlm4clt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
 {
 	struct nlm_lock	*lock = &argp->lock;
 
@@ -489,7 +489,7 @@
 }
 
 static int
-nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlm4clt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 		return -EIO;
@@ -499,7 +499,7 @@
 }
 
 static int
-nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlm4clt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_encode_testres(p, resp)))
 		return -EIO;
@@ -508,7 +508,7 @@
 }
 
 static int
-nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
+nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 {
 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 		return -EIO;
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index c11a4b9..1e36bae 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -149,12 +149,8 @@
 		return -ENOMEM;
 	s->s_fs_info = sbi;
 
-	/* N.B. These should be compile-time tests.
-	   Unfortunately that is impossible. */
-	if (32 != sizeof (struct minix_inode))
-		panic("bad V1 i-node size");
-	if (64 != sizeof(struct minix2_inode))
-		panic("bad V2 i-node size");
+	BUILD_BUG_ON(32 != sizeof (struct minix_inode));
+	BUILD_BUG_ON(64 != sizeof(struct minix2_inode));
 
 	if (!sb_set_blocksize(s, BLOCK_SIZE))
 		goto out_bad_hblock;
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index a89ac84..589d1ea 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -726,7 +726,7 @@
 				struct compat_ncp_privatedata_ioctl user32;
 				user32.len = user.len;
 				user32.data = (unsigned long) user.data;
-				if (copy_to_user(&user32, argp, sizeof(user32)))
+				if (copy_to_user(argp, &user32, sizeof(user32)))
 					return -EFAULT;
 			} else
 #endif
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 5676163d..db3d791 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -31,10 +31,10 @@
 };
 
 struct cb_compound_hdr_res {
-	uint32_t *status;
+	__be32 *status;
 	int taglen;
 	const char *tag;
-	uint32_t *nops;
+	__be32 *nops;
 };
 
 struct cb_getattrargs {
@@ -44,7 +44,7 @@
 };
 
 struct cb_getattrres {
-	uint32_t status;
+	__be32 status;
 	uint32_t bitmap[2];
 	uint64_t size;
 	uint64_t change_attr;
@@ -59,8 +59,8 @@
 	uint32_t truncate;
 };
 
-extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
-extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
+extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
+extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
 
 #ifdef CONFIG_NFS_V4
 extern int nfs_callback_up(void);
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 97cf8f7..72e55d8 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -14,7 +14,7 @@
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
  
-unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res)
+__be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res)
 {
 	struct nfs_client *clp;
 	struct nfs_delegation *delegation;
@@ -55,11 +55,11 @@
 	return res->status;
 }
 
-unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
+__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
 {
 	struct nfs_client *clp;
 	struct inode *inode;
-	unsigned res;
+	__be32 res;
 	
 	res = htonl(NFS4ERR_BADHANDLE);
 	clp = nfs_find_client(args->addr, 4);
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 29f9321..f8ea1f5 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -22,9 +22,9 @@
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
 
-typedef unsigned (*callback_process_op_t)(void *, void *);
-typedef unsigned (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
-typedef unsigned (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
+typedef __be32 (*callback_process_op_t)(void *, void *);
+typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
+typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
 
 
 struct callback_op {
@@ -36,24 +36,24 @@
 
 static struct callback_op callback_ops[];
 
-static int nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp)
+static __be32 nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	return htonl(NFS4_OK);
 }
 
-static int nfs4_decode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy)
+static int nfs4_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_argsize_check(rqstp, p);
 }
 
-static int nfs4_encode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy)
+static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_ressize_check(rqstp, p);
 }
 
-static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes)
+static __be32 *read_buf(struct xdr_stream *xdr, int nbytes)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = xdr_inline_decode(xdr, nbytes);
 	if (unlikely(p == NULL))
@@ -61,9 +61,9 @@
 	return p;
 }
 
-static unsigned decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str)
+static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = read_buf(xdr, 4);
 	if (unlikely(p == NULL))
@@ -81,9 +81,9 @@
 	return 0;
 }
 
-static unsigned decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
+static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = read_buf(xdr, 4);
 	if (unlikely(p == NULL))
@@ -99,9 +99,9 @@
 	return 0;
 }
 
-static unsigned decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
+static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
 {
-	uint32_t *p;
+	__be32 *p;
 	unsigned int attrlen;
 
 	p = read_buf(xdr, 4);
@@ -118,9 +118,9 @@
 	return 0;
 }
 
-static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = read_buf(xdr, 16);
 	if (unlikely(p == NULL))
@@ -129,11 +129,11 @@
 	return 0;
 }
 
-static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
+static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
 {
-	uint32_t *p;
+	__be32 *p;
 	unsigned int minor_version;
-	unsigned status;
+	__be32 status;
 
 	status = decode_string(xdr, &hdr->taglen, &hdr->tag);
 	if (unlikely(status != 0))
@@ -159,9 +159,9 @@
 	return 0;
 }
 
-static unsigned decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
+static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
 {
-	uint32_t *p;
+	__be32 *p;
 	p = read_buf(xdr, 4);
 	if (unlikely(p == NULL))
 		return htonl(NFS4ERR_RESOURCE);
@@ -169,9 +169,9 @@
 	return 0;
 }
 
-static unsigned decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args)
+static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args)
 {
-	unsigned status;
+	__be32 status;
 
 	status = decode_fh(xdr, &args->fh);
 	if (unlikely(status != 0))
@@ -183,10 +183,10 @@
 	return status;
 }
 
-static unsigned decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args)
+static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args)
 {
-	uint32_t *p;
-	unsigned status;
+	__be32 *p;
+	__be32 status;
 
 	args->addr = &rqstp->rq_addr;
 	status = decode_stateid(xdr, &args->stateid);
@@ -204,9 +204,9 @@
 	return status;
 }
 
-static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
+static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = xdr_reserve_space(xdr, 4 + len);
 	if (unlikely(p == NULL))
@@ -217,10 +217,10 @@
 
 #define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE)
 #define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY)
-static unsigned encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep)
+static __be32 encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, __be32 **savep)
 {
-	uint32_t bm[2];
-	uint32_t *p;
+	__be32 bm[2];
+	__be32 *p;
 
 	bm[0] = htonl(bitmap[0] & CB_SUPPORTED_ATTR0);
 	bm[1] = htonl(bitmap[1] & CB_SUPPORTED_ATTR1);
@@ -247,9 +247,9 @@
 	return 0;
 }
 
-static unsigned encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change)
+static __be32 encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	if (!(bitmap[0] & FATTR4_WORD0_CHANGE))
 		return 0;
@@ -260,9 +260,9 @@
 	return 0;
 }
 
-static unsigned encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size)
+static __be32 encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	if (!(bitmap[0] & FATTR4_WORD0_SIZE))
 		return 0;
@@ -273,9 +273,9 @@
 	return 0;
 }
 
-static unsigned encode_attr_time(struct xdr_stream *xdr, const struct timespec *time)
+static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec *time)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = xdr_reserve_space(xdr, 12);
 	if (unlikely(p == 0))
@@ -285,23 +285,23 @@
 	return 0;
 }
 
-static unsigned encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
+static __be32 encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
 {
 	if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA))
 		return 0;
 	return encode_attr_time(xdr,time);
 }
 
-static unsigned encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
+static __be32 encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
 {
 	if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY))
 		return 0;
 	return encode_attr_time(xdr,time);
 }
 
-static unsigned encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr)
+static __be32 encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr)
 {
-	unsigned status;
+	__be32 status;
 
 	hdr->status = xdr_reserve_space(xdr, 4);
 	if (unlikely(hdr->status == NULL))
@@ -315,9 +315,9 @@
 	return 0;
 }
 
-static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res)
+static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res)
 {
-	uint32_t *p;
+	__be32 *p;
 	
 	p = xdr_reserve_space(xdr, 8);
 	if (unlikely(p == NULL))
@@ -327,10 +327,10 @@
 	return 0;
 }
 
-static unsigned encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res)
+static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res)
 {
-	uint32_t *savep = NULL;
-	unsigned status = res->status;
+	__be32 *savep = NULL;
+	__be32 status = res->status;
 	
 	if (unlikely(status != 0))
 		goto out;
@@ -353,15 +353,15 @@
 	return status;
 }
 
-static unsigned process_op(struct svc_rqst *rqstp,
+static __be32 process_op(struct svc_rqst *rqstp,
 		struct xdr_stream *xdr_in, void *argp,
 		struct xdr_stream *xdr_out, void *resp)
 {
 	struct callback_op *op = &callback_ops[0];
 	unsigned int op_nr = OP_CB_ILLEGAL;
-	unsigned int status = 0;
+	__be32 status = 0;
 	long maxlen;
-	unsigned res;
+	__be32 res;
 
 	dprintk("%s: start\n", __FUNCTION__);
 	status = decode_op_hdr(xdr_in, &op_nr);
@@ -399,20 +399,20 @@
 /*
  * Decode, process and encode a COMPOUND
  */
-static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp)
+static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	struct cb_compound_hdr_arg hdr_arg;
 	struct cb_compound_hdr_res hdr_res;
 	struct xdr_stream xdr_in, xdr_out;
-	uint32_t *p;
-	unsigned int status;
+	__be32 *p;
+	__be32 status;
 	unsigned int nops = 1;
 
 	dprintk("%s: start\n", __FUNCTION__);
 
 	xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
 
-	p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
+	p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
 	xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
 
 	decode_compound_hdr_arg(&xdr_in, &hdr_arg);
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 6e4e48c..5fea638 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -232,11 +232,15 @@
  * Find a client by address
  * - caller must hold nfs_client_lock
  */
-static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
+static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion, int match_port)
 {
 	struct nfs_client *clp;
 
 	list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+		/* Don't match clients that failed to initialise properly */
+		if (clp->cl_cons_state < 0)
+			continue;
+
 		/* Different NFS versions cannot share the same nfs_client */
 		if (clp->cl_nfsversion != nfsversion)
 			continue;
@@ -245,7 +249,7 @@
 			   sizeof(clp->cl_addr.sin_addr)) != 0)
 			continue;
 
-		if (clp->cl_addr.sin_port == addr->sin_port)
+		if (!match_port || clp->cl_addr.sin_port == addr->sin_port)
 			goto found;
 	}
 
@@ -265,11 +269,12 @@
 	struct nfs_client *clp;
 
 	spin_lock(&nfs_client_lock);
-	clp = __nfs_find_client(addr, nfsversion);
+	clp = __nfs_find_client(addr, nfsversion, 0);
 	spin_unlock(&nfs_client_lock);
-
-	BUG_ON(clp && clp->cl_cons_state == 0);
-
+	if (clp != NULL && clp->cl_cons_state != NFS_CS_READY) {
+		nfs_put_client(clp);
+		clp = NULL;
+	}
 	return clp;
 }
 
@@ -292,7 +297,7 @@
 	do {
 		spin_lock(&nfs_client_lock);
 
-		clp = __nfs_find_client(addr, nfsversion);
+		clp = __nfs_find_client(addr, nfsversion, 1);
 		if (clp)
 			goto found_client;
 		if (new)
@@ -322,25 +327,11 @@
 	if (new)
 		nfs_free_client(new);
 
-	if (clp->cl_cons_state == NFS_CS_INITING) {
-		DECLARE_WAITQUEUE(myself, current);
-
-		add_wait_queue(&nfs_client_active_wq, &myself);
-
-		for (;;) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			if (signal_pending(current) ||
-			    clp->cl_cons_state > NFS_CS_READY)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&nfs_client_active_wq, &myself);
-
-		if (signal_pending(current)) {
-			nfs_put_client(clp);
-			return ERR_PTR(-ERESTARTSYS);
-		}
+	error = wait_event_interruptible(nfs_client_active_wq,
+				clp->cl_cons_state != NFS_CS_INITING);
+	if (error < 0) {
+		nfs_put_client(clp);
+		return ERR_PTR(-ERESTARTSYS);
 	}
 
 	if (clp->cl_cons_state < NFS_CS_READY) {
@@ -863,6 +854,7 @@
  */
 static int nfs4_init_client(struct nfs_client *clp,
 		int proto, int timeo, int retrans,
+		const char *ip_addr,
 		rpc_authflavor_t authflavour)
 {
 	int error;
@@ -879,6 +871,7 @@
 	error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour);
 	if (error < 0)
 		goto error;
+	memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
 
 	error = nfs_idmap_new(clp);
 	if (error < 0) {
@@ -902,6 +895,7 @@
  */
 static int nfs4_set_client(struct nfs_server *server,
 		const char *hostname, const struct sockaddr_in *addr,
+		const char *ip_addr,
 		rpc_authflavor_t authflavour,
 		int proto, int timeo, int retrans)
 {
@@ -916,7 +910,7 @@
 		error = PTR_ERR(clp);
 		goto error;
 	}
-	error = nfs4_init_client(clp, proto, timeo, retrans, authflavour);
+	error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour);
 	if (error < 0)
 		goto error_put;
 
@@ -985,7 +979,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	/* Get a client record */
-	error = nfs4_set_client(server, hostname, addr, authflavour,
+	error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour,
 			data->proto, data->timeo, data->retrans);
 	if (error < 0)
 		goto error;
@@ -1055,6 +1049,7 @@
 	/* Get a client representation.
 	 * Note: NFSv4 always uses TCP, */
 	error = nfs4_set_client(server, data->hostname, data->addr,
+			parent_client->cl_ipaddr,
 			data->authflavor,
 			parent_server->client->cl_xprt->prot,
 			parent_client->retrans_timeo,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 481f889..b34cd16 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -142,12 +142,12 @@
 	return res;
 }
 
-typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int);
+typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int);
 typedef struct {
 	struct file	*file;
 	struct page	*page;
 	unsigned long	page_index;
-	u32		*ptr;
+	__be32		*ptr;
 	u64		*dir_cookie;
 	loff_t		current_index;
 	struct nfs_entry *entry;
@@ -203,8 +203,10 @@
 	 * Note: assumes we have exclusive access to this mapping either
 	 *	 through inode->i_mutex or some other mechanism.
 	 */
-	if (page->index == 0)
-		invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1);
+	if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) {
+		/* Should never happen */
+		nfs_zap_mapping(inode, inode->i_mapping);
+	}
 	unlock_page(page);
 	return 0;
  error:
@@ -218,7 +220,7 @@
 static inline
 int dir_decode(nfs_readdir_descriptor_t *desc)
 {
-	u32	*p = desc->ptr;
+	__be32	*p = desc->ptr;
 	p = desc->decode(p, desc->entry, desc->plus);
 	if (IS_ERR(p))
 		return PTR_ERR(p);
@@ -933,8 +935,17 @@
 
 no_entry:
 	res = d_materialise_unique(dentry, inode);
-	if (res != NULL)
+	if (res != NULL) {
+		struct dentry *parent;
+		if (IS_ERR(res))
+			goto out_unlock;
+		/* Was a directory renamed! */
+		parent = dget_parent(res);
+		if (!IS_ROOT(parent))
+			nfs_mark_for_revalidate(parent->d_inode);
+		dput(parent);
 		dentry = res;
+	}
 	nfs_renew_times(dentry);
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 out_unlock:
@@ -1130,6 +1141,8 @@
 	alias = d_materialise_unique(dentry, inode);
 	if (alias != NULL) {
 		dput(dentry);
+		if (IS_ERR(alias))
+			return NULL;
 		dentry = alias;
 	}
 
@@ -1517,8 +1530,8 @@
 	pagevec_init(&lru_pvec, 0);
 	if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0,
 							GFP_KERNEL)) {
-		if (!pagevec_add(&lru_pvec, page))
-			__pagevec_lru_add(&lru_pvec);
+		pagevec_add(&lru_pvec, page);
+		pagevec_lru_add(&lru_pvec);
 		SetPageUptodate(page);
 		unlock_page(page);
 	} else
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 9f7f8b9..bdfabf8 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -497,6 +497,7 @@
 			if (dreq->commit_data != NULL)
 				nfs_commit_free(dreq->commit_data);
 			nfs_direct_free_writedata(dreq);
+			nfs_zap_mapping(inode, inode->i_mapping);
 			nfs_direct_complete(dreq);
 	}
 }
@@ -517,6 +518,7 @@
 {
 	nfs_end_data_update(inode);
 	nfs_direct_free_writedata(dreq);
+	nfs_zap_mapping(inode, inode->i_mapping);
 	nfs_direct_complete(dreq);
 }
 #endif
@@ -532,10 +534,12 @@
 
 	spin_lock(&dreq->lock);
 
-	if (likely(status >= 0))
-		dreq->count += data->res.count;
-	else
-		dreq->error = task->tk_status;
+	if (unlikely(status < 0)) {
+		dreq->error = status;
+		goto out_unlock;
+	}
+
+	dreq->count += data->res.count;
 
 	if (data->res.verf->committed != NFS_FILE_SYNC) {
 		switch (dreq->flags) {
@@ -550,7 +554,7 @@
 				}
 		}
 	}
-
+out_unlock:
 	spin_unlock(&dreq->lock);
 }
 
@@ -828,17 +832,6 @@
 
 	retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos);
 
-	/*
-	 * XXX: nfs_end_data_update() already ensures this file's
-	 *      cached data is subsequently invalidated.  Do we really
-	 *      need to call invalidate_inode_pages2() again here?
-	 *
-	 *      For aio writes, this invalidation will almost certainly
-	 *      occur before the writes complete.  Kind of racey.
-	 */
-	if (mapping->nrpages)
-		invalidate_inode_pages2(mapping);
-
 	if (retval > 0)
 		iocb->ki_pos = pos + retval;
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bc9376c..08cc4c5 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -131,6 +131,15 @@
 	spin_unlock(&inode->i_lock);
 }
 
+void nfs_zap_mapping(struct inode *inode, struct address_space *mapping)
+{
+	if (mapping->nrpages != 0) {
+		spin_lock(&inode->i_lock);
+		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
+		spin_unlock(&inode->i_lock);
+	}
+}
+
 static void nfs_zap_acl_cache(struct inode *inode)
 {
 	void (*clear_acl_cache)(struct inode *);
@@ -574,7 +583,7 @@
 
 	nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
 	lock_kernel();
-	if (!inode || is_bad_inode(inode))
+	if (is_bad_inode(inode))
  		goto out_nowait;
 	if (NFS_STALE(inode))
  		goto out_nowait;
@@ -671,13 +680,20 @@
 	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
 			|| nfs_attribute_timeout(inode))
 		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (ret < 0)
+		goto out;
 
 	if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
-		nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
-		if (S_ISREG(inode->i_mode))
-			nfs_sync_mapping(mapping);
-		invalidate_inode_pages2(mapping);
-
+		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)) {
@@ -687,10 +703,12 @@
 		}
 		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));
 	}
+out:
 	return ret;
 }
 
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index bea0b01..d205466 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -93,15 +93,15 @@
 /* nfs2xdr.c */
 extern int nfs_stat_to_errno(int);
 extern struct rpc_procinfo nfs_procedures[];
-extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
+extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
 
 /* nfs3xdr.c */
 extern struct rpc_procinfo nfs3_procedures[];
-extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
+extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
 
 /* nfs4xdr.c */
 #ifdef CONFIG_NFS_V4
-extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
 #endif
 
 /* nfs4proc.c */
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index d507b02..f75fe72 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -95,7 +95,7 @@
  * XDR encode/decode functions for MOUNT
  */
 static int
-xdr_encode_dirpath(struct rpc_rqst *req, u32 *p, const char *path)
+xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
 {
 	p = xdr_encode_string(p, path);
 
@@ -104,7 +104,7 @@
 }
 
 static int
-xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
+xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
 {
 	struct nfs_fh *fh = res->fh;
 
@@ -116,7 +116,7 @@
 }
 
 static int
-xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
+xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
 {
 	struct nfs_fh *fh = res->fh;
 
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index b49501f..3be4e72 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -66,15 +66,15 @@
 /*
  * Common NFS XDR functions as inlines
  */
-static inline u32 *
-xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
+static inline __be32 *
+xdr_encode_fhandle(__be32 *p, struct nfs_fh *fhandle)
 {
 	memcpy(p, fhandle->data, NFS2_FHSIZE);
 	return p + XDR_QUADLEN(NFS2_FHSIZE);
 }
 
-static inline u32 *
-xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
+static inline __be32 *
+xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle)
 {
 	/* NFSv2 handles have a fixed length */
 	fhandle->size = NFS2_FHSIZE;
@@ -82,8 +82,8 @@
 	return p + XDR_QUADLEN(NFS2_FHSIZE);
 }
 
-static inline u32*
-xdr_encode_time(u32 *p, struct timespec *timep)
+static inline __be32*
+xdr_encode_time(__be32 *p, struct timespec *timep)
 {
 	*p++ = htonl(timep->tv_sec);
 	/* Convert nanoseconds into microseconds */
@@ -91,8 +91,8 @@
 	return p;
 }
 
-static inline u32*
-xdr_encode_current_server_time(u32 *p, struct timespec *timep)
+static inline __be32*
+xdr_encode_current_server_time(__be32 *p, struct timespec *timep)
 {
 	/*
 	 * Passing the invalid value useconds=1000000 is a
@@ -108,8 +108,8 @@
 	return p;
 }
 
-static inline u32*
-xdr_decode_time(u32 *p, struct timespec *timep)
+static inline __be32*
+xdr_decode_time(__be32 *p, struct timespec *timep)
 {
 	timep->tv_sec = ntohl(*p++);
 	/* Convert microseconds into nanoseconds */
@@ -117,8 +117,8 @@
 	return p;
 }
 
-static u32 *
-xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
+static __be32 *
+xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
 {
 	u32 rdev;
 	fattr->type = (enum nfs_ftype) ntohl(*p++);
@@ -146,10 +146,10 @@
 	return p;
 }
 
-static inline u32 *
-xdr_encode_sattr(u32 *p, struct iattr *attr)
+static inline __be32 *
+xdr_encode_sattr(__be32 *p, struct iattr *attr)
 {
-	const u32 not_set = __constant_htonl(0xFFFFFFFF);
+	const __be32 not_set = __constant_htonl(0xFFFFFFFF);
 
 	*p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
 	*p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
@@ -184,7 +184,7 @@
  * GETATTR, READLINK, STATFS
  */
 static int
-nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
+nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
 {
 	p = xdr_encode_fhandle(p, fh);
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
@@ -195,7 +195,7 @@
  * Encode SETATTR arguments
  */
 static int
-nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args)
+nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_sattr(p, args->sattr);
@@ -208,7 +208,7 @@
  * LOOKUP, REMOVE, RMDIR
  */
 static int
-nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args)
+nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_array(p, args->name, args->len);
@@ -222,7 +222,7 @@
  * exactly to the page we want to fetch.
  */
 static int
-nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
+nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
 	struct rpc_auth	*auth = req->rq_task->tk_auth;
 	unsigned int replen;
@@ -246,7 +246,7 @@
  * Decode READ reply
  */
 static int
-nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
+nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
 {
 	struct kvec *iov = req->rq_rcv_buf.head;
 	int	status, count, recvd, hdrlen;
@@ -286,7 +286,7 @@
  * Write arguments. Splice the buffer to be written into the iovec.
  */
 static int
-nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
+nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
 {
 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
 	u32 offset = (u32)args->offset;
@@ -309,7 +309,7 @@
  * CREATE, MKDIR
  */
 static int
-nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args)
+nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_array(p, args->name, args->len);
@@ -322,7 +322,7 @@
  * Encode RENAME arguments
  */
 static int
-nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args)
+nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fromfh);
 	p = xdr_encode_array(p, args->fromname, args->fromlen);
@@ -336,7 +336,7 @@
  * Encode LINK arguments
  */
 static int
-nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
+nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fromfh);
 	p = xdr_encode_fhandle(p, args->tofh);
@@ -349,7 +349,7 @@
  * Encode SYMLINK arguments
  */
 static int
-nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
+nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args)
 {
 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
 	size_t pad;
@@ -378,7 +378,7 @@
  * Encode arguments to readdir call
  */
 static int
-nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
+nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
 {
 	struct rpc_task	*task = req->rq_task;
 	struct rpc_auth	*auth = task->tk_auth;
@@ -404,7 +404,7 @@
  * from nfs_readdir for each entry.
  */
 static int
-nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, void *dummy)
+nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
@@ -412,7 +412,7 @@
 	int hdrlen, recvd;
 	int status, nr;
 	unsigned int len, pglen;
-	u32 *end, *entry, *kaddr;
+	__be32 *end, *entry, *kaddr;
 
 	if ((status = ntohl(*p++)))
 		return -nfs_stat_to_errno(status);
@@ -432,8 +432,8 @@
 	if (pglen > recvd)
 		pglen = recvd;
 	page = rcvbuf->pages;
-	kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
-	end = (u32 *)((char *)p + pglen);
+	kaddr = p = kmap_atomic(*page, KM_USER0);
+	end = (__be32 *)((char *)p + pglen);
 	entry = p;
 	for (nr = 0; *p++; nr++) {
 		if (p + 2 > end)
@@ -468,8 +468,8 @@
 	goto out;
 }
 
-u32 *
-nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
+__be32 *
+nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
 {
 	if (!*p++) {
 		if (!*p)
@@ -496,7 +496,7 @@
  * Decode simple status reply
  */
 static int
-nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy)
+nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
 {
 	int	status;
 
@@ -510,7 +510,7 @@
  * GETATTR, SETATTR, WRITE
  */
 static int
-nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 {
 	int	status;
 
@@ -525,7 +525,7 @@
  * LOOKUP, CREATE, MKDIR
  */
 static int
-nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res)
+nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
 {
 	int	status;
 
@@ -540,7 +540,7 @@
  * Encode READLINK args
  */
 static int
-nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
+nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
 	unsigned int replen;
@@ -558,7 +558,7 @@
  * Decode READLINK reply
  */
 static int
-nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy)
+nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
@@ -601,7 +601,7 @@
  * Decode WRITE reply
  */
 static int
-nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
+nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
 {
 	res->verf->committed = NFS_FILE_SYNC;
 	return nfs_xdr_attrstat(req, p, res->fattr);
@@ -611,7 +611,7 @@
  * Decode STATFS reply
  */
 static int
-nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs2_fsstat *res)
+nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
 {
 	int	status;
 
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 3b234d4..e5f128f 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -668,7 +668,7 @@
 {
 	struct inode		*dir = dentry->d_inode;
 	struct nfs_fattr	dir_attr;
-	u32			*verf = NFS_COOKIEVERF(dir);
+	__be32			*verf = NFS_COOKIEVERF(dir);
 	struct nfs3_readdirargs	arg = {
 		.fh		= NFS_FH(dir),
 		.cookie		= cookie,
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 16556fa..0ace092 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -105,14 +105,14 @@
 /*
  * Common NFS XDR functions as inlines
  */
-static inline u32 *
-xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
+static inline __be32 *
+xdr_encode_fhandle(__be32 *p, struct nfs_fh *fh)
 {
 	return xdr_encode_array(p, fh->data, fh->size);
 }
 
-static inline u32 *
-xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
+static inline __be32 *
+xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
 {
 	if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
 		memcpy(fh->data, p, fh->size);
@@ -124,24 +124,24 @@
 /*
  * Encode/decode time.
  */
-static inline u32 *
-xdr_encode_time3(u32 *p, struct timespec *timep)
+static inline __be32 *
+xdr_encode_time3(__be32 *p, struct timespec *timep)
 {
 	*p++ = htonl(timep->tv_sec);
 	*p++ = htonl(timep->tv_nsec);
 	return p;
 }
 
-static inline u32 *
-xdr_decode_time3(u32 *p, struct timespec *timep)
+static inline __be32 *
+xdr_decode_time3(__be32 *p, struct timespec *timep)
 {
 	timep->tv_sec = ntohl(*p++);
 	timep->tv_nsec = ntohl(*p++);
 	return p;
 }
 
-static u32 *
-xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
+static __be32 *
+xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
 {
 	unsigned int	type, major, minor;
 	int		fmode;
@@ -177,8 +177,8 @@
 	return p;
 }
 
-static inline u32 *
-xdr_encode_sattr(u32 *p, struct iattr *attr)
+static inline __be32 *
+xdr_encode_sattr(__be32 *p, struct iattr *attr)
 {
 	if (attr->ia_valid & ATTR_MODE) {
 		*p++ = xdr_one;
@@ -223,8 +223,8 @@
 	return p;
 }
 
-static inline u32 *
-xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
 {
 	p = xdr_decode_hyper(p, &fattr->pre_size);
 	p = xdr_decode_time3(p, &fattr->pre_mtime);
@@ -233,16 +233,16 @@
 	return p;
 }
 
-static inline u32 *
-xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
 {
 	if (*p++)
 		p = xdr_decode_fattr(p, fattr);
 	return p;
 }
 
-static inline u32 *
-xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
 {
 	if (*p++)
 		return xdr_decode_wcc_attr(p, fattr);
@@ -250,8 +250,8 @@
 }
 
 
-static inline u32 *
-xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
+static inline __be32 *
+xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
 {
 	p = xdr_decode_pre_op_attr(p, fattr);
 	return xdr_decode_post_op_attr(p, fattr);
@@ -265,7 +265,7 @@
  * Encode file handle argument
  */
 static int
-nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
+nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
 {
 	p = xdr_encode_fhandle(p, fh);
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
@@ -276,7 +276,7 @@
  * Encode SETATTR arguments
  */
 static int
-nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
+nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_sattr(p, args->sattr);
@@ -291,7 +291,7 @@
  * Encode directory ops argument
  */
 static int
-nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args)
+nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_array(p, args->name, args->len);
@@ -303,7 +303,7 @@
  * Encode access() argument
  */
 static int
-nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args)
+nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	*p++ = htonl(args->access);
@@ -317,7 +317,7 @@
  * exactly to the page we want to fetch.
  */
 static int
-nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
+nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
 	struct rpc_auth	*auth = req->rq_task->tk_auth;
 	unsigned int replen;
@@ -339,7 +339,7 @@
  * Write arguments. Splice the buffer to be written into the iovec.
  */
 static int
-nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
+nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
 {
 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
 	u32 count = args->count;
@@ -360,7 +360,7 @@
  * Encode CREATE arguments
  */
 static int
-nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args)
+nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_array(p, args->name, args->len);
@@ -380,7 +380,7 @@
  * Encode MKDIR arguments
  */
 static int
-nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
+nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_array(p, args->name, args->len);
@@ -393,7 +393,7 @@
  * Encode SYMLINK arguments
  */
 static int
-nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args)
+nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fromfh);
 	p = xdr_encode_array(p, args->fromname, args->fromlen);
@@ -410,7 +410,7 @@
  * Encode MKNOD arguments
  */
 static int
-nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
+nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_array(p, args->name, args->len);
@@ -429,7 +429,7 @@
  * Encode RENAME arguments
  */
 static int
-nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
+nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fromfh);
 	p = xdr_encode_array(p, args->fromname, args->fromlen);
@@ -443,7 +443,7 @@
  * Encode LINK arguments
  */
 static int
-nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
+nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fromfh);
 	p = xdr_encode_fhandle(p, args->tofh);
@@ -456,7 +456,7 @@
  * Encode arguments to readdir call
  */
 static int
-nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
+nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
 {
 	struct rpc_auth	*auth = req->rq_task->tk_auth;
 	unsigned int replen;
@@ -485,7 +485,7 @@
  * We just check for syntactical correctness.
  */
 static int
-nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
+nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
@@ -493,7 +493,7 @@
 	int hdrlen, recvd;
 	int status, nr;
 	unsigned int len, pglen;
-	u32 *entry, *end, *kaddr;
+	__be32 *entry, *end, *kaddr;
 
 	status = ntohl(*p++);
 	/* Decode post_op_attrs */
@@ -523,8 +523,8 @@
 	if (pglen > recvd)
 		pglen = recvd;
 	page = rcvbuf->pages;
-	kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
-	end = (u32 *)((char *)p + pglen);
+	kaddr = p = kmap_atomic(*page, KM_USER0);
+	end = (__be32 *)((char *)p + pglen);
 	entry = p;
 	for (nr = 0; *p++; nr++) {
 		if (p + 3 > end)
@@ -583,8 +583,8 @@
 	goto out;
 }
 
-u32 *
-nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
+__be32 *
+nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
 {
 	struct nfs_entry old = *entry;
 
@@ -626,7 +626,7 @@
  * Encode COMMIT arguments
  */
 static int
-nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
+nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
 {
 	p = xdr_encode_fhandle(p, args->fh);
 	p = xdr_encode_hyper(p, args->offset);
@@ -640,7 +640,7 @@
  * Encode GETACL arguments
  */
 static int
-nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
+nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
 		    struct nfs3_getaclargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
@@ -664,7 +664,7 @@
  * Encode SETACL arguments
  */
 static int
-nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
+nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
                    struct nfs3_setaclargs *args)
 {
 	struct xdr_buf *buf = &req->rq_snd_buf;
@@ -711,7 +711,7 @@
  * Decode attrstat reply.
  */
 static int
-nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 {
 	int	status;
 
@@ -726,7 +726,7 @@
  * SATTR, REMOVE, RMDIR
  */
 static int
-nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 {
 	int	status;
 
@@ -740,7 +740,7 @@
  * Decode LOOKUP reply
  */
 static int
-nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
+nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
 {
 	int	status;
 
@@ -759,7 +759,7 @@
  * Decode ACCESS reply
  */
 static int
-nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
+nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
 {
 	int	status = ntohl(*p++);
 
@@ -771,7 +771,7 @@
 }
 
 static int
-nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
+nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
 	unsigned int replen;
@@ -789,7 +789,7 @@
  * Decode READLINK reply
  */
 static int
-nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
@@ -837,7 +837,7 @@
  * Decode READ reply
  */
 static int
-nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
+nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
 {
 	struct kvec *iov = req->rq_rcv_buf.head;
 	int	status, count, ocount, recvd, hdrlen;
@@ -888,7 +888,7 @@
  * Decode WRITE response
  */
 static int
-nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
+nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
 {
 	int	status;
 
@@ -910,7 +910,7 @@
  * Decode a CREATE response
  */
 static int
-nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
+nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
 {
 	int	status;
 
@@ -937,7 +937,7 @@
  * Decode RENAME reply
  */
 static int
-nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
+nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
 {
 	int	status;
 
@@ -952,7 +952,7 @@
  * Decode LINK reply
  */
 static int
-nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
+nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
 {
 	int	status;
 
@@ -967,7 +967,7 @@
  * Decode FSSTAT reply
  */
 static int
-nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
+nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
 {
 	int		status;
 
@@ -992,7 +992,7 @@
  * Decode FSINFO reply
  */
 static int
-nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
+nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
 {
 	int		status;
 
@@ -1020,7 +1020,7 @@
  * Decode PATHCONF reply
  */
 static int
-nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
+nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
 {
 	int		status;
 
@@ -1040,7 +1040,7 @@
  * Decode COMMIT reply
  */
 static int
-nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
+nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
 {
 	int		status;
 
@@ -1059,7 +1059,7 @@
  * Decode GETACL reply
  */
 static int
-nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
+nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
 		   struct nfs3_getaclres *res)
 {
 	struct xdr_buf *buf = &req->rq_rcv_buf;
@@ -1091,7 +1091,7 @@
  * Decode setacl reply.
  */
 static int
-nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 {
 	int status = ntohl(*p++);
 
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 61095fe..6f34667 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -212,7 +212,7 @@
 extern const nfs4_stateid zero_stateid;
 
 /* nfs4xdr.c */
-extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
 struct nfs4_mount_data;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 47c7e6e..8118036 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -138,10 +138,10 @@
 	| FATTR4_WORD1_MOUNTED_ON_FILEID
 };
 
-static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
+static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
 		struct nfs4_readdir_arg *readdir)
 {
-	u32 *start, *p;
+	__be32 *start, *p;
 
 	BUG_ON(readdir->count < 80);
 	if (cookie > 2) {
@@ -162,7 +162,7 @@
 	 * when talking to the server, we always send cookie 0
 	 * instead of 1 or 2.
 	 */
-	start = p = (u32 *)kmap_atomic(*readdir->pages, KM_USER0);
+	start = p = kmap_atomic(*readdir->pages, KM_USER0);
 	
 	if (cookie == 0) {
 		*p++ = xdr_one;                                  /* next */
@@ -1314,11 +1314,9 @@
 			case -EROFS:
 				lookup_instantiate_filp(nd, (struct dentry *)state, NULL);
 				return 1;
-			case -ENOENT:
-				if (dentry->d_inode == NULL)
-					return 1;
+			default:
+				goto out_drop;
 		}
-		goto out_drop;
 	}
 	if (state->inode == dentry->d_inode) {
 		nfs4_intent_set_file(nd, dentry, state);
@@ -2917,11 +2915,11 @@
 		.rpc_resp = clp,
 		.rpc_cred = cred,
 	};
-	u32 *p;
+	__be32 *p;
 	int loop = 0;
 	int status;
 
-	p = (u32*)sc_verifier.data;
+	p = (__be32*)sc_verifier.data;
 	*p++ = htonl((u32)clp->cl_boot_time.tv_sec);
 	*p = htonl((u32)clp->cl_boot_time.tv_nsec);
 
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 3dd413f..0cf3fa3 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -471,7 +471,7 @@
 
 static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = xdr_reserve_space(xdr, 4 + len);
 	BUG_ON(p == NULL);
@@ -480,7 +480,7 @@
 
 static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
 	BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
@@ -494,7 +494,7 @@
 
 static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
 	BUG_ON(p == NULL);
@@ -507,8 +507,8 @@
 	char owner_group[IDMAP_NAMESZ];
 	int owner_namelen = 0;
 	int owner_grouplen = 0;
-	uint32_t *p;
-	uint32_t *q;
+	__be32 *p;
+	__be32 *q;
 	int len;
 	uint32_t bmval0 = 0;
 	uint32_t bmval1 = 0;
@@ -630,7 +630,7 @@
 
 static int encode_access(struct xdr_stream *xdr, u32 access)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8);
 	WRITE32(OP_ACCESS);
@@ -641,7 +641,7 @@
 
 static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8+sizeof(arg->stateid->data));
 	WRITE32(OP_CLOSE);
@@ -653,7 +653,7 @@
 
 static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args)
 {
-	uint32_t *p;
+	__be32 *p;
         
         RESERVE_SPACE(16);
         WRITE32(OP_COMMIT);
@@ -665,7 +665,7 @@
 
 static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create)
 {
-	uint32_t *p;
+	__be32 *p;
 	
 	RESERVE_SPACE(8);
 	WRITE32(OP_CREATE);
@@ -697,7 +697,7 @@
 
 static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)
 {
-        uint32_t *p;
+        __be32 *p;
 
         RESERVE_SPACE(12);
         WRITE32(OP_GETATTR);
@@ -708,7 +708,7 @@
 
 static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1)
 {
-        uint32_t *p;
+        __be32 *p;
 
         RESERVE_SPACE(16);
         WRITE32(OP_GETATTR);
@@ -740,7 +740,7 @@
 
 static int encode_getfh(struct xdr_stream *xdr)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(OP_GETFH);
@@ -750,7 +750,7 @@
 
 static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8 + name->len);
 	WRITE32(OP_LINK);
@@ -780,7 +780,7 @@
  */
 static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(32);
 	WRITE32(OP_LOCK);
@@ -809,7 +809,7 @@
 
 static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(40);
 	WRITE32(OP_LOCKT);
@@ -825,7 +825,7 @@
 
 static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(44);
 	WRITE32(OP_LOCKU);
@@ -841,7 +841,7 @@
 static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
 {
 	int len = name->len;
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8 + len);
 	WRITE32(OP_LOOKUP);
@@ -853,7 +853,7 @@
 
 static void encode_share_access(struct xdr_stream *xdr, int open_flags)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8);
 	switch (open_flags & (FMODE_READ|FMODE_WRITE)) {
@@ -874,7 +874,7 @@
 
 static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
  /*
  * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
  * owner 4 = 32
@@ -891,7 +891,7 @@
 
 static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	switch(arg->open_flags & O_EXCL) {
@@ -907,7 +907,7 @@
 
 static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	switch (arg->open_flags & O_CREAT) {
@@ -923,7 +923,7 @@
 
 static inline void encode_delegation_type(struct xdr_stream *xdr, int delegation_type)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	switch (delegation_type) {
@@ -943,7 +943,7 @@
 
 static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(NFS4_OPEN_CLAIM_NULL);
@@ -952,7 +952,7 @@
 
 static inline void encode_claim_previous(struct xdr_stream *xdr, int type)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
@@ -961,7 +961,7 @@
 
 static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4+sizeof(stateid->data));
 	WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
@@ -991,7 +991,7 @@
 
 static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8+sizeof(arg->stateid->data));
 	WRITE32(OP_OPEN_CONFIRM);
@@ -1003,7 +1003,7 @@
 
 static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8+sizeof(arg->stateid->data));
 	WRITE32(OP_OPEN_DOWNGRADE);
@@ -1017,7 +1017,7 @@
 encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
 	int len = fh->size;
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8 + len);
 	WRITE32(OP_PUTFH);
@@ -1029,7 +1029,7 @@
 
 static int encode_putrootfh(struct xdr_stream *xdr)
 {
-        uint32_t *p;
+        __be32 *p;
         
         RESERVE_SPACE(4);
         WRITE32(OP_PUTROOTFH);
@@ -1040,7 +1040,7 @@
 static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
 {
 	nfs4_stateid stateid;
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(16);
 	if (ctx->state != NULL) {
@@ -1052,7 +1052,7 @@
 
 static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(OP_READ);
@@ -1074,7 +1074,7 @@
 		FATTR4_WORD1_MOUNTED_ON_FILEID,
 	};
 	int replen;
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(32+sizeof(nfs4_verifier));
 	WRITE32(OP_READDIR);
@@ -1116,7 +1116,7 @@
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
 	unsigned int replen;
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(OP_READLINK);
@@ -1134,7 +1134,7 @@
 
 static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8 + name->len);
 	WRITE32(OP_REMOVE);
@@ -1146,7 +1146,7 @@
 
 static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(8 + oldname->len);
 	WRITE32(OP_RENAME);
@@ -1162,7 +1162,7 @@
 
 static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(12);
 	WRITE32(OP_RENEW);
@@ -1174,7 +1174,7 @@
 static int
 encode_restorefh(struct xdr_stream *xdr)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(OP_RESTOREFH);
@@ -1185,7 +1185,7 @@
 static int
 encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4+sizeof(zero_stateid.data));
 	WRITE32(OP_SETATTR);
@@ -1204,7 +1204,7 @@
 static int
 encode_savefh(struct xdr_stream *xdr)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(OP_SAVEFH);
@@ -1215,7 +1215,7 @@
 static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server)
 {
 	int status;
-	uint32_t *p;
+	__be32 *p;
 	
         RESERVE_SPACE(4+sizeof(arg->stateid.data));
         WRITE32(OP_SETATTR);
@@ -1229,7 +1229,7 @@
 
 static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data));
 	WRITE32(OP_SETCLIENTID);
@@ -1248,7 +1248,7 @@
 
 static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state)
 {
-        uint32_t *p;
+        __be32 *p;
 
         RESERVE_SPACE(12 + sizeof(client_state->cl_confirm.data));
         WRITE32(OP_SETCLIENTID_CONFIRM);
@@ -1260,7 +1260,7 @@
 
 static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(4);
 	WRITE32(OP_WRITE);
@@ -1279,7 +1279,7 @@
 
 static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	RESERVE_SPACE(20);
 
@@ -1295,7 +1295,7 @@
 /*
  * Encode an ACCESS request
  */
-static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct nfs4_accessargs *args)
+static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1313,7 +1313,7 @@
 /*
  * Encode LOOKUP request
  */
-static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_arg *args)
+static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1337,7 +1337,7 @@
 /*
  * Encode LOOKUP_ROOT request
  */
-static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_root_arg *args)
+static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1358,7 +1358,7 @@
 /*
  * Encode REMOVE request
  */
-static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct nfs4_remove_arg *args)
+static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs4_remove_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1380,7 +1380,7 @@
 /*
  * Encode RENAME request
  */
-static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct nfs4_rename_arg *args)
+static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1410,7 +1410,7 @@
 /*
  * Encode LINK request
  */
-static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs4_link_arg *args)
+static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1440,7 +1440,7 @@
 /*
  * Encode CREATE request
  */
-static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
+static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1470,7 +1470,7 @@
 /*
  * Encode SYMLINK request
  */
-static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
+static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
 {
 	return nfs4_xdr_enc_create(req, p, args);
 }
@@ -1478,7 +1478,7 @@
 /*
  * Encode GETATTR request
  */
-static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, uint32_t *p, const struct nfs4_getattr_arg *args)
+static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1496,7 +1496,7 @@
 /*
  * Encode a CLOSE request
  */
-static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args)
+static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr = {
@@ -1520,7 +1520,7 @@
 /*
  * Encode an OPEN request
  */
-static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
+static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1556,7 +1556,7 @@
 /*
  * Encode an OPEN_CONFIRM request
  */
-static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_open_confirmargs *args)
+static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_open_confirmargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1577,7 +1577,7 @@
 /*
  * Encode an OPEN request with no attributes.
  */
-static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
+static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1601,7 +1601,7 @@
 /*
  * Encode an OPEN_DOWNGRADE request
  */
-static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args)
+static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1625,7 +1625,7 @@
 /*
  * Encode a LOCK request
  */
-static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lock_args *args)
+static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1646,7 +1646,7 @@
 /*
  * Encode a LOCKT request
  */
-static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockt_args *args)
+static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1667,7 +1667,7 @@
 /*
  * Encode a LOCKU request
  */
-static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_locku_args *args)
+static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1688,7 +1688,7 @@
 /*
  * Encode a READLINK request
  */
-static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_readlink *args)
+static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1709,7 +1709,7 @@
 /*
  * Encode a READDIR request
  */
-static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, uint32_t *p, const struct nfs4_readdir_arg *args)
+static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1730,7 +1730,7 @@
 /*
  * Encode a READ request
  */
-static int nfs4_xdr_enc_read(struct rpc_rqst *req, uint32_t *p, struct nfs_readargs *args)
+static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 {
 	struct rpc_auth	*auth = req->rq_task->tk_auth;
 	struct xdr_stream xdr;
@@ -1762,7 +1762,7 @@
 /*
  * Encode an SETATTR request
  */
-static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, uint32_t *p, struct nfs_setattrargs *args)
+static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
 
 {
         struct xdr_stream xdr;
@@ -1788,7 +1788,7 @@
  * Encode a GETACL request
  */
 static int
-nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p,
+nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
 		struct nfs_getaclargs *args)
 {
 	struct xdr_stream xdr;
@@ -1815,7 +1815,7 @@
 /*
  * Encode a WRITE request
  */
-static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
+static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1839,7 +1839,7 @@
 /*
  *  a COMMIT request
  */
-static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
+static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1863,7 +1863,7 @@
 /*
  * FSINFO request
  */
-static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fsinfo_arg *args)
+static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1882,7 +1882,7 @@
 /*
  * a PATHCONF request
  */
-static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args)
+static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1902,7 +1902,7 @@
 /*
  * a STATFS request
  */
-static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args)
+static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1923,7 +1923,7 @@
 /*
  * GETATTR_BITMAP request
  */
-static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const struct nfs_fh *fhandle)
+static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struct nfs_fh *fhandle)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1945,7 +1945,7 @@
 /*
  * a RENEW request
  */
-static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp)
+static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1960,7 +1960,7 @@
 /*
  * a SETCLIENTID request
  */
-static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nfs4_setclientid *sc)
+static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid *sc)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1975,7 +1975,7 @@
 /*
  * a SETCLIENTID_CONFIRM request
  */
-static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp)
+static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -1997,7 +1997,7 @@
 /*
  * DELEGRETURN request
  */
-static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const struct nfs4_delegreturnargs *args)
+static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -2021,7 +2021,7 @@
 /*
  * Encode FS_LOCATIONS request
  */
-static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations_arg *args)
+static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -2086,7 +2086,7 @@
 
 static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	READ_BUF(4);
 	READ32(*len);
@@ -2097,7 +2097,7 @@
 
 static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	READ_BUF(8);
 	READ32(hdr->status);
@@ -2112,7 +2112,7 @@
 
 static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint32_t opnum;
 	int32_t nfserr;
 
@@ -2134,7 +2134,7 @@
 /* Dummy routine */
 static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
 {
-	uint32_t *p;
+	__be32 *p;
 	unsigned int strlen;
 	char *str;
 
@@ -2144,7 +2144,8 @@
 
 static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
 {
-	uint32_t bmlen, *p;
+	uint32_t bmlen;
+	__be32 *p;
 
 	READ_BUF(4);
 	READ32(bmlen);
@@ -2159,9 +2160,9 @@
 	return 0;
 }
 
-static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, uint32_t **savep)
+static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	READ_BUF(4);
 	READ32(*attrlen);
@@ -2182,7 +2183,7 @@
 
 static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*type = 0;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
@@ -2202,7 +2203,7 @@
 
 static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*change = 0;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
@@ -2219,7 +2220,7 @@
 
 static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*size = 0;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
@@ -2235,7 +2236,7 @@
 
 static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*res = 0;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
@@ -2251,7 +2252,7 @@
 
 static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*res = 0;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
@@ -2267,7 +2268,7 @@
 
 static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	fsid->major = 0;
 	fsid->minor = 0;
@@ -2287,7 +2288,7 @@
 
 static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*res = 60;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
@@ -2303,7 +2304,7 @@
 
 static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
@@ -2319,7 +2320,7 @@
 
 static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*fileid = 0;
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
@@ -2335,7 +2336,7 @@
 
 static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*fileid = 0;
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
@@ -2351,7 +2352,7 @@
 
 static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2368,7 +2369,7 @@
 
 static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2385,7 +2386,7 @@
 
 static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2403,7 +2404,7 @@
 static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
 {
 	int n;
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	READ_BUF(4);
@@ -2448,7 +2449,7 @@
 static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
 {
 	int n;
-	uint32_t *p;
+	__be32 *p;
 	int status = -EIO;
 
 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
@@ -2512,7 +2513,7 @@
 
 static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2529,7 +2530,7 @@
 
 static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*maxlink = 1;
@@ -2546,7 +2547,7 @@
 
 static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*maxname = 1024;
@@ -2563,7 +2564,7 @@
 
 static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 1024;
@@ -2584,7 +2585,7 @@
 
 static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 1024;
@@ -2605,7 +2606,7 @@
 
 static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *mode)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*mode = 0;
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
@@ -2622,7 +2623,7 @@
 
 static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*nlink = 1;
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
@@ -2638,7 +2639,8 @@
 
 static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid)
 {
-	uint32_t len, *p;
+	uint32_t len;
+	__be32 *p;
 
 	*uid = -2;
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
@@ -2662,7 +2664,8 @@
 
 static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid)
 {
-	uint32_t len, *p;
+	uint32_t len;
+	__be32 *p;
 
 	*gid = -2;
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
@@ -2686,7 +2689,8 @@
 
 static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
 {
-	uint32_t major = 0, minor = 0, *p;
+	uint32_t major = 0, minor = 0;
+	__be32 *p;
 
 	*rdev = MKDEV(0,0);
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
@@ -2708,7 +2712,7 @@
 
 static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2725,7 +2729,7 @@
 
 static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2742,7 +2746,7 @@
 
 static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status = 0;
 
 	*res = 0;
@@ -2759,7 +2763,7 @@
 
 static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	*used = 0;
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
@@ -2776,7 +2780,7 @@
 
 static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint64_t sec;
 	uint32_t nsec;
 
@@ -2836,7 +2840,7 @@
 	return status;
 }
 
-static int verify_attr_len(struct xdr_stream *xdr, uint32_t *savep, uint32_t attrlen)
+static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen)
 {
 	unsigned int attrwords = XDR_QUADLEN(attrlen);
 	unsigned int nwords = xdr->p - savep;
@@ -2854,7 +2858,7 @@
 
 static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	READ_BUF(20);
 	READ32(cinfo->atomic);
@@ -2865,7 +2869,7 @@
 
 static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint32_t supp, acc;
 	int status;
 
@@ -2882,7 +2886,7 @@
 
 static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_CLOSE);
@@ -2895,7 +2899,7 @@
 
 static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_COMMIT);
@@ -2908,7 +2912,7 @@
 
 static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint32_t bmlen;
 	int status;
 
@@ -2925,7 +2929,7 @@
 
 static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
 {
-	uint32_t *savep;
+	__be32 *savep;
 	uint32_t attrlen, 
 		 bitmap[2] = {0};
 	int status;
@@ -2952,7 +2956,7 @@
 	
 static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
 {
-	uint32_t *savep;
+	__be32 *savep;
 	uint32_t attrlen, 
 		 bitmap[2] = {0};
 	int status;
@@ -2985,7 +2989,7 @@
 
 static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
 {
-	uint32_t *savep;
+	__be32 *savep;
 	uint32_t attrlen, 
 		 bitmap[2] = {0};
 	int status;
@@ -3010,7 +3014,7 @@
 
 static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, const struct nfs_server *server)
 {
-	uint32_t *savep;
+	__be32 *savep;
 	uint32_t attrlen,
 		 bitmap[2] = {0},
 		 type;
@@ -3079,7 +3083,7 @@
 
 static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 {
-	uint32_t *savep;
+	__be32 *savep;
 	uint32_t attrlen, bitmap[2];
 	int status;
 
@@ -3111,7 +3115,7 @@
 
 static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint32_t len;
 	int status;
 
@@ -3147,7 +3151,7 @@
 static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
 {
 	uint64_t offset, length, clientid;
-	uint32_t *p;
+	__be32 *p;
 	uint32_t namelen, type;
 
 	READ_BUF(32);
@@ -3172,7 +3176,7 @@
 
 static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_LOCK);
@@ -3195,7 +3199,7 @@
 
 static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_LOCKU);
@@ -3214,7 +3218,7 @@
 /* This is too sick! */
 static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
 {
-        uint32_t *p;
+        __be32 *p;
 	uint32_t limit_type, nblocks, blocksize;
 
 	READ_BUF(12);
@@ -3233,7 +3237,7 @@
 
 static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
 {
-        uint32_t *p;
+        __be32 *p;
         uint32_t delegation_type;
 
 	READ_BUF(4);
@@ -3259,7 +3263,7 @@
 
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
 {
-        uint32_t *p;
+        __be32 *p;
         uint32_t bmlen;
         int status;
 
@@ -3287,7 +3291,7 @@
 
 static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
 {
-        uint32_t *p;
+        __be32 *p;
 	int status;
 
         status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
@@ -3300,7 +3304,7 @@
 
 static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
@@ -3324,7 +3328,7 @@
 static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
 {
 	struct kvec *iov = req->rq_rcv_buf.head;
-	uint32_t *p;
+	__be32 *p;
 	uint32_t count, eof, recvd, hdrlen;
 	int status;
 
@@ -3354,7 +3358,7 @@
 	struct page	*page = *rcvbuf->pages;
 	struct kvec	*iov = rcvbuf->head;
 	unsigned int	nr, pglen = rcvbuf->page_len;
-	uint32_t	*end, *entry, *p, *kaddr;
+	__be32		*end, *entry, *p, *kaddr;
 	uint32_t	len, attrlen, xlen;
 	int 		hdrlen, recvd, status;
 
@@ -3376,7 +3380,7 @@
 	xdr_read_pages(xdr, pglen);
 
 	BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
-	kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0);
+	kaddr = p = kmap_atomic(page, KM_USER0);
 	end = p + ((pglen + readdir->pgbase) >> 2);
 	entry = p;
 	for (nr = 0; *p++; nr++) {
@@ -3428,7 +3432,7 @@
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
 	int hdrlen, len, recvd;
-	uint32_t *p;
+	__be32 *p;
 	char *kaddr;
 	int status;
 
@@ -3505,7 +3509,7 @@
 static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
 		size_t *acl_len)
 {
-	uint32_t *savep;
+	__be32 *savep;
 	uint32_t attrlen,
 		 bitmap[2] = {0};
 	struct kvec *iov = req->rq_rcv_buf.head;
@@ -3551,7 +3555,7 @@
 
 static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint32_t bmlen;
 	int status;
 
@@ -3567,7 +3571,7 @@
 
 static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
 {
-	uint32_t *p;
+	__be32 *p;
 	uint32_t opnum;
 	int32_t nfserr;
 
@@ -3610,7 +3614,7 @@
 
 static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_WRITE);
@@ -3632,7 +3636,7 @@
 /*
  * Decode OPEN_DOWNGRADE response
  */
-static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res)
+static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -3660,7 +3664,7 @@
 /*
  * Decode ACCESS response
  */
-static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_accessres *res)
+static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3678,7 +3682,7 @@
 /*
  * Decode LOOKUP response
  */
-static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res)
+static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3701,7 +3705,7 @@
 /*
  * Decode LOOKUP_ROOT response
  */
-static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res)
+static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3721,7 +3725,7 @@
 /*
  * Decode REMOVE response
  */
-static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_remove_res *res)
+static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_remove_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3742,7 +3746,7 @@
 /*
  * Decode RENAME response
  */
-static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_rename_res *res)
+static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3772,7 +3776,7 @@
 /*
  * Decode LINK response
  */
-static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res)
+static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3805,7 +3809,7 @@
 /*
  * Decode CREATE response
  */
-static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
+static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3834,7 +3838,7 @@
 /*
  * Decode SYMLINK response
  */
-static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
+static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
 {
 	return nfs4_xdr_dec_create(rqstp, p, res);
 }
@@ -3842,7 +3846,7 @@
 /*
  * Decode GETATTR response
  */
-static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_getattr_res *res)
+static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3865,7 +3869,7 @@
  * Encode an SETACL request
  */
 static int
-nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args)
+nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr = {
@@ -3886,7 +3890,7 @@
  * Decode SETACL response
  */
 static int
-nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res)
+nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3908,7 +3912,7 @@
  * Decode GETACL response
  */
 static int
-nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len)
+nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3930,7 +3934,7 @@
 /*
  * Decode CLOSE response
  */
-static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res)
+static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -3960,7 +3964,7 @@
 /*
  * Decode OPEN response
  */
-static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
+static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -3994,7 +3998,7 @@
 /*
  * Decode OPEN_CONFIRM response
  */
-static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_open_confirmres *res)
+static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, __be32 *p, struct nfs_open_confirmres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -4015,7 +4019,7 @@
 /*
  * Decode OPEN response
  */
-static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
+static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -4039,7 +4043,7 @@
 /*
  * Decode SETATTR response
  */
-static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_setattrres *res)
+static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -4065,7 +4069,7 @@
 /*
  * Decode LOCK response
  */
-static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lock_res *res)
+static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4086,7 +4090,7 @@
 /*
  * Decode LOCKT response
  */
-static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockt_res *res)
+static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4107,7 +4111,7 @@
 /*
  * Decode LOCKU response
  */
-static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_locku_res *res)
+static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4128,7 +4132,7 @@
 /*
  * Decode READLINK response
  */
-static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, uint32_t *p, void *res)
+static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4149,7 +4153,7 @@
 /*
  * Decode READDIR response
  */
-static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_readdir_res *res)
+static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4170,7 +4174,7 @@
 /*
  * Decode Read response
  */
-static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res)
+static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4193,7 +4197,7 @@
 /*
  * Decode WRITE response
  */
-static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *res)
+static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4219,7 +4223,7 @@
 /*
  * Decode COMMIT response
  */
-static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *res)
+static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4243,7 +4247,7 @@
 /*
  * FSINFO request
  */
-static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo)
+static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4263,7 +4267,7 @@
 /*
  * PATHCONF request
  */
-static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, uint32_t *p, struct nfs_pathconf *pathconf)
+static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *pathconf)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4281,7 +4285,7 @@
 /*
  * STATFS request
  */
-static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, uint32_t *p, struct nfs_fsstat *fsstat)
+static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *fsstat)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4299,7 +4303,7 @@
 /*
  * GETATTR_BITMAP request
  */
-static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, uint32_t *p, struct nfs4_server_caps_res *res)
+static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4318,7 +4322,7 @@
 /*
  * Decode RENEW response
  */
-static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
+static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4334,7 +4338,7 @@
 /*
  * a SETCLIENTID request
  */
-static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p,
+static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
 		struct nfs_client *clp)
 {
 	struct xdr_stream xdr;
@@ -4353,7 +4357,7 @@
 /*
  * a SETCLIENTID_CONFIRM request
  */
-static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo)
+static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4375,7 +4379,7 @@
 /*
  * DELEGRETURN request
  */
-static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_delegreturnres *res)
+static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4397,7 +4401,7 @@
 /*
  * FS_LOCATIONS request
  */
-static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res)
+static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -4417,7 +4421,7 @@
 	return status;
 }
 
-uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
+__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
 {
 	uint32_t bitmap[2] = {0};
 	uint32_t len;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 28659a9..28108c8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -834,7 +834,7 @@
 	}
 	/* RFC3530: The default port for NFS is 2049 */
 	if (addr.sin_port == 0)
-		addr.sin_port = NFS_PORT;
+		addr.sin_port = htons(NFS_PORT);
 
 	/* Grab the authentication type */
 	authflavour = RPC_AUTH_UNIX;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index f6675d2..883dd4a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -57,6 +57,8 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
 #include <linux/nfs_page.h>
+#include <linux/backing-dev.h>
+
 #include <asm/uaccess.h>
 #include <linux/smp_lock.h>
 
@@ -395,7 +397,7 @@
 out:
 	clear_bit(BDI_write_congested, &bdi->state);
 	wake_up_all(&nfs_write_congestion);
-	writeback_congestion_end();
+	congestion_end(WRITE);
 	return err;
 }
 
@@ -588,10 +590,10 @@
 
 	while(!list_empty(head)) {
 		req = nfs_list_entry(head->next);
+		dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
 		nfs_list_remove_request(req);
 		nfs_inode_remove_request(req);
-		dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-		nfs_clear_page_writeback(req);
+		nfs_unlock_request(req);
 	}
 }
 
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
index 0c2be8c..c11f537 100644
--- a/fs/nfs_common/nfsacl.c
+++ b/fs/nfs_common/nfsacl.c
@@ -46,7 +46,7 @@
 {
 	struct nfsacl_encode_desc *nfsacl_desc =
 		(struct nfsacl_encode_desc *) desc;
-	u32 *p = (u32 *) elem;
+	__be32 *p = elem;
 
 	struct posix_acl_entry *entry =
 		&nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
@@ -127,7 +127,7 @@
 {
 	struct nfsacl_decode_desc *nfsacl_desc =
 		(struct nfsacl_decode_desc *) desc;
-	u32 *p = (u32 *) elem;
+	__be32 *p = elem;
 	struct posix_acl_entry *entry;
 
 	if (!nfsacl_desc->acl) {
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index e13fa23..f37df46 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1148,12 +1148,12 @@
  * for a given NFSv4 client.   The root is defined to be the
  * export point with fsid==0
  */
-int
+__be32
 exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
 	       struct cache_req *creq)
 {
 	struct svc_export *exp;
-	int rv;
+	__be32 rv;
 	u32 fsidv[2];
 
 	mk_fsid_v1(fsidv, 0);
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 7b889ff..11fdaf7 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -25,7 +25,7 @@
 static u32
 nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 {
-	u32		nfserr;
+	__be32		nfserr;
 	struct svc_fh	fh;
 
 	/* must initialize before using! but maxsize doesn't matter */
@@ -39,18 +39,20 @@
 	fh_put(&fh);
 	rqstp->rq_client = NULL;
 	exp_readunlock();
- 	/* nlm and nfsd don't share error codes.
-	 * we invent: 0 = no error
-	 *            1 = stale file handle
-	 *	      2 = other error
+ 	/* We return nlm error codes as nlm doesn't know
+	 * about nfsd, but nfsd does know about nlm..
 	 */
 	switch (nfserr) {
 	case nfs_ok:
 		return 0;
+	case nfserr_dropit:
+		return nlm_drop_reply;
+#ifdef CONFIG_LOCKD_V4
 	case nfserr_stale:
-		return 1;
+		return nlm4_stale_fh;
+#endif
 	default:
-		return 2;
+		return nlm_lck_denied;
 	}
 }
 
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 9187755..e3eca08 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -21,7 +21,7 @@
 /*
  * NULL call.
  */
-static int
+static __be32
 nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	return nfs_ok;
@@ -30,12 +30,12 @@
 /*
  * Get the Access and/or Default ACL of a file.
  */
-static int nfsacld_proc_getacl(struct svc_rqst * rqstp,
+static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
 		struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
 {
 	svc_fh *fh;
 	struct posix_acl *acl;
-	int nfserr = 0;
+	__be32 nfserr = 0;
 
 	dprintk("nfsd: GETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
 
@@ -97,12 +97,12 @@
 /*
  * Set the Access and/or Default ACL of a file.
  */
-static int nfsacld_proc_setacl(struct svc_rqst * rqstp,
+static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
 		struct nfsd3_setaclargs *argp,
 		struct nfsd_attrstat *resp)
 {
 	svc_fh *fh;
-	int nfserr = 0;
+	__be32 nfserr = 0;
 
 	dprintk("nfsd: SETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
 
@@ -128,7 +128,7 @@
 /*
  * Check file attributes
  */
-static int nfsacld_proc_getattr(struct svc_rqst * rqstp,
+static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp,
 		struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)
 {
 	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
@@ -140,10 +140,10 @@
 /*
  * Check file access
  */
-static int nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
+static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
 		struct nfsd3_accessres *resp)
 {
-	int nfserr;
+	__be32 nfserr;
 
 	dprintk("nfsd: ACCESS(2acl)   %s 0x%x\n",
 			SVCFH_fmt(&argp->fh),
@@ -158,7 +158,7 @@
 /*
  * XDR decode functions
  */
-static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclargs *argp)
 {
 	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
@@ -169,7 +169,7 @@
 }
 
 
-static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_setaclargs *argp)
 {
 	struct kvec *head = rqstp->rq_arg.head;
@@ -194,7 +194,7 @@
 	return (n > 0);
 }
 
-static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd_fhandle *argp)
 {
 	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
@@ -202,7 +202,7 @@
 	return xdr_argsize_check(rqstp, p);
 }
 
-static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_accessargs *argp)
 {
 	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
@@ -217,7 +217,7 @@
  */
 
 /* GETACL */
-static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclres *resp)
 {
 	struct dentry *dentry = resp->fh.fh_dentry;
@@ -259,7 +259,7 @@
 	return 1;
 }
 
-static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd_attrstat *resp)
 {
 	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
@@ -267,7 +267,7 @@
 }
 
 /* ACCESS */
-static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_accessres *resp)
 {
 	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
@@ -278,7 +278,7 @@
 /*
  * XDR release functions
  */
-static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclres *resp)
 {
 	fh_put(&resp->fh);
@@ -287,7 +287,7 @@
 	return 1;
 }
 
-static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
+static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd_fhandle *resp)
 {
 	fh_put(&resp->fh);
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index d4bdc00..fcad289 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -19,7 +19,7 @@
 /*
  * NULL call.
  */
-static int
+static __be32
 nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	return nfs_ok;
@@ -28,12 +28,12 @@
 /*
  * Get the Access and/or Default ACL of a file.
  */
-static int nfsd3_proc_getacl(struct svc_rqst * rqstp,
+static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
 		struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
 {
 	svc_fh *fh;
 	struct posix_acl *acl;
-	int nfserr = 0;
+	__be32 nfserr = 0;
 
 	fh = fh_copy(&resp->fh, &argp->fh);
 	if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
@@ -93,12 +93,12 @@
 /*
  * Set the Access and/or Default ACL of a file.
  */
-static int nfsd3_proc_setacl(struct svc_rqst * rqstp,
+static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
 		struct nfsd3_setaclargs *argp,
 		struct nfsd3_attrstat *resp)
 {
 	svc_fh *fh;
-	int nfserr = 0;
+	__be32 nfserr = 0;
 
 	fh = fh_copy(&resp->fh, &argp->fh);
 	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR);
@@ -122,7 +122,7 @@
 /*
  * XDR decode functions
  */
-static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
+static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclargs *args)
 {
 	if (!(p = nfs3svc_decode_fh(p, &args->fh)))
@@ -133,7 +133,7 @@
 }
 
 
-static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
+static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_setaclargs *args)
 {
 	struct kvec *head = rqstp->rq_arg.head;
@@ -163,7 +163,7 @@
  */
 
 /* GETACL */
-static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
+static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclres *resp)
 {
 	struct dentry *dentry = resp->fh.fh_dentry;
@@ -208,7 +208,7 @@
 }
 
 /* SETACL */
-static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p,
+static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_attrstat *resp)
 {
 	p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
@@ -219,7 +219,7 @@
 /*
  * XDR release functions
  */
-static int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
+static int nfs3svc_release_getacl(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclres *resp)
 {
 	fh_put(&resp->fh);
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index a5ebc7d..64db601 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -43,7 +43,7 @@
 /*
  * NULL call.
  */
-static int
+static __be32
 nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	return nfs_ok;
@@ -52,11 +52,12 @@
 /*
  * Get a file's attributes
  */
-static int
+static __be32
 nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
 					   struct nfsd3_attrstat *resp)
 {
-	int	err, nfserr;
+	int	err;
+	__be32	nfserr;
 
 	dprintk("nfsd: GETATTR(3)  %s\n",
 		SVCFH_fmt(&argp->fh));
@@ -76,11 +77,11 @@
 /*
  * Set a file's attributes
  */
-static int
+static __be32
 nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
 					   struct nfsd3_attrstat  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: SETATTR(3)  %s\n",
 				SVCFH_fmt(&argp->fh));
@@ -94,11 +95,11 @@
 /*
  * Look up a path name component
  */
-static int
+static __be32
 nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
 					  struct nfsd3_diropres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: LOOKUP(3)   %s %.*s\n",
 				SVCFH_fmt(&argp->fh),
@@ -118,11 +119,11 @@
 /*
  * Check file access
  */
-static int
+static __be32
 nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
 					  struct nfsd3_accessres *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: ACCESS(3)   %s 0x%x\n",
 				SVCFH_fmt(&argp->fh),
@@ -137,11 +138,11 @@
 /*
  * Read a symlink.
  */
-static int
+static __be32
 nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp,
 					   struct nfsd3_readlinkres *resp)
 {
-	int nfserr;
+	__be32 nfserr;
 
 	dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
 
@@ -155,11 +156,11 @@
 /*
  * Read a portion of a file.
  */
-static int
+static __be32
 nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
 				        struct nfsd3_readres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 	u32	max_blocksize = svc_max_payload(rqstp);
 
 	dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
@@ -195,11 +196,11 @@
 /*
  * Write data to a file
  */
-static int
+static __be32
 nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
 					 struct nfsd3_writeres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: WRITE(3)    %s %d bytes at %ld%s\n",
 				SVCFH_fmt(&argp->fh),
@@ -223,13 +224,13 @@
  * At least in theory; we'll see how it fares in practice when the
  * first reports about SunOS compatibility problems start to pour in...
  */
-static int
+static __be32
 nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
 					  struct nfsd3_diropres   *resp)
 {
 	svc_fh		*dirfhp, *newfhp = NULL;
 	struct iattr	*attr;
-	u32		nfserr;
+	__be32		nfserr;
 
 	dprintk("nfsd: CREATE(3)   %s %.*s\n",
 				SVCFH_fmt(&argp->fh),
@@ -265,11 +266,11 @@
 /*
  * Make directory. This operation is not idempotent.
  */
-static int
+static __be32
 nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
 					 struct nfsd3_diropres   *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: MKDIR(3)    %s %.*s\n",
 				SVCFH_fmt(&argp->fh),
@@ -285,11 +286,11 @@
 	RETURN_STATUS(nfserr);
 }
 
-static int
+static __be32
 nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
 					   struct nfsd3_diropres    *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: SYMLINK(3)  %s %.*s -> %.*s\n",
 				SVCFH_fmt(&argp->ffh),
@@ -307,11 +308,12 @@
 /*
  * Make socket/fifo/device.
  */
-static int
+static __be32
 nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
 					 struct nfsd3_diropres  *resp)
 {
-	int	nfserr, type;
+	__be32	nfserr;
+	int type;
 	dev_t	rdev = 0;
 
 	dprintk("nfsd: MKNOD(3)    %s %.*s\n",
@@ -343,11 +345,11 @@
 /*
  * Remove file/fifo/socket etc.
  */
-static int
+static __be32
 nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
 					  struct nfsd3_attrstat  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: REMOVE(3)   %s %.*s\n",
 				SVCFH_fmt(&argp->fh),
@@ -363,11 +365,11 @@
 /*
  * Remove a directory
  */
-static int
+static __be32
 nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
 					 struct nfsd3_attrstat  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: RMDIR(3)    %s %.*s\n",
 				SVCFH_fmt(&argp->fh),
@@ -379,11 +381,11 @@
 	RETURN_STATUS(nfserr);
 }
 
-static int
+static __be32
 nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
 					  struct nfsd3_renameres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: RENAME(3)   %s %.*s ->\n",
 				SVCFH_fmt(&argp->ffh),
@@ -401,11 +403,11 @@
 	RETURN_STATUS(nfserr);
 }
 
-static int
+static __be32
 nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
 					struct nfsd3_linkres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: LINK(3)     %s ->\n",
 				SVCFH_fmt(&argp->ffh));
@@ -424,11 +426,12 @@
 /*
  * Read a portion of a directory.
  */
-static int
+static __be32
 nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
 					   struct nfsd3_readdirres  *resp)
 {
-	int		nfserr, count;
+	__be32		nfserr;
+	int		count;
 
 	dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
 				SVCFH_fmt(&argp->fh),
@@ -459,11 +462,12 @@
  * Read a portion of a directory, including file handles and attrs.
  * For now, we choose to ignore the dircount parameter.
  */
-static int
+static __be32
 nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
 					       struct nfsd3_readdirres  *resp)
 {
-	int	nfserr, count = 0;
+	__be32	nfserr;
+	int	count = 0;
 	loff_t	offset;
 	int	i;
 	caddr_t	page_addr = NULL;
@@ -517,11 +521,11 @@
 /*
  * Get file system stats
  */
-static int
+static __be32
 nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
 					   struct nfsd3_fsstatres *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: FSSTAT(3)   %s\n",
 				SVCFH_fmt(&argp->fh));
@@ -534,11 +538,11 @@
 /*
  * Get file system info
  */
-static int
+static __be32
 nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
 					   struct nfsd3_fsinfores *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 	u32	max_blocksize = svc_max_payload(rqstp);
 
 	dprintk("nfsd: FSINFO(3)   %s\n",
@@ -576,11 +580,11 @@
 /*
  * Get pathconf info for the specified file
  */
-static int
+static __be32
 nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle      *argp,
 					     struct nfsd3_pathconfres *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: PATHCONF(3) %s\n",
 				SVCFH_fmt(&argp->fh));
@@ -619,11 +623,11 @@
 /*
  * Commit a file (range) to stable storage.
  */
-static int
+static __be32
 nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
 					   struct nfsd3_commitres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
 				SVCFH_fmt(&argp->fh),
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 247d518..b4baca3 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -42,23 +42,23 @@
 /*
  * XDR functions for basic NFS types
  */
-static inline u32 *
-encode_time3(u32 *p, struct timespec *time)
+static inline __be32 *
+encode_time3(__be32 *p, struct timespec *time)
 {
 	*p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
 	return p;
 }
 
-static inline u32 *
-decode_time3(u32 *p, struct timespec *time)
+static inline __be32 *
+decode_time3(__be32 *p, struct timespec *time)
 {
 	time->tv_sec = ntohl(*p++);
 	time->tv_nsec = ntohl(*p++);
 	return p;
 }
 
-static inline u32 *
-decode_fh(u32 *p, struct svc_fh *fhp)
+static inline __be32 *
+decode_fh(__be32 *p, struct svc_fh *fhp)
 {
 	unsigned int size;
 	fh_init(fhp, NFS3_FHSIZE);
@@ -72,13 +72,13 @@
 }
 
 /* Helper function for NFSv3 ACL code */
-u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp)
+__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
 {
 	return decode_fh(p, fhp);
 }
 
-static inline u32 *
-encode_fh(u32 *p, struct svc_fh *fhp)
+static inline __be32 *
+encode_fh(__be32 *p, struct svc_fh *fhp)
 {
 	unsigned int size = fhp->fh_handle.fh_size;
 	*p++ = htonl(size);
@@ -91,8 +91,8 @@
  * Decode a file name and make sure that the path contains
  * no slashes or null bytes.
  */
-static inline u32 *
-decode_filename(u32 *p, char **namp, int *lenp)
+static inline __be32 *
+decode_filename(__be32 *p, char **namp, int *lenp)
 {
 	char		*name;
 	int		i;
@@ -107,8 +107,8 @@
 	return p;
 }
 
-static inline u32 *
-decode_sattr3(u32 *p, struct iattr *iap)
+static inline __be32 *
+decode_sattr3(__be32 *p, struct iattr *iap)
 {
 	u32	tmp;
 
@@ -153,8 +153,8 @@
 	return p;
 }
 
-static inline u32 *
-encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
+static inline __be32 *
+encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 	      struct kstat *stat)
 {
 	struct dentry	*dentry = fhp->fh_dentry;
@@ -186,8 +186,8 @@
 	return p;
 }
 
-static inline u32 *
-encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+static inline __be32 *
+encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
 	struct inode	*inode = fhp->fh_dentry->d_inode;
 
@@ -224,8 +224,8 @@
  * The inode may be NULL if the call failed because of a stale file
  * handle. In this case, no attributes are returned.
  */
-static u32 *
-encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+static __be32 *
+encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
 	struct dentry *dentry = fhp->fh_dentry;
 	if (dentry && dentry->d_inode != NULL) {
@@ -243,8 +243,8 @@
 }
 
 /* Helper for NFSv3 ACLs */
-u32 *
-nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+__be32 *
+nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
 	return encode_post_op_attr(rqstp, p, fhp);
 }
@@ -252,8 +252,8 @@
 /*
  * Enocde weak cache consistency data
  */
-static u32 *
-encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+static __be32 *
+encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
 	struct dentry	*dentry = fhp->fh_dentry;
 
@@ -278,7 +278,7 @@
  * XDR decode functions
  */
 int
-nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args)
+nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
@@ -286,7 +286,7 @@
 }
 
 int
-nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_sattrargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -303,7 +303,7 @@
 }
 
 int
-nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_diropargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -314,7 +314,7 @@
 }
 
 int
-nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_accessargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
@@ -325,7 +325,7 @@
 }
 
 int
-nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readargs *args)
 {
 	unsigned int len;
@@ -355,7 +355,7 @@
 }
 
 int
-nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_writeargs *args)
 {
 	unsigned int len, v, hdr;
@@ -393,7 +393,7 @@
 }
 
 int
-nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_createargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -417,7 +417,7 @@
 	return xdr_argsize_check(rqstp, p);
 }
 int
-nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_createargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -429,7 +429,7 @@
 }
 
 int
-nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_symlinkargs *args)
 {
 	unsigned int len;
@@ -481,7 +481,7 @@
 }
 
 int
-nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_mknodargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -505,7 +505,7 @@
 }
 
 int
-nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_renameargs *args)
 {
 	if (!(p = decode_fh(p, &args->ffh))
@@ -518,7 +518,7 @@
 }
 
 int
-nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readlinkargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
@@ -530,7 +530,7 @@
 }
 
 int
-nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_linkargs *args)
 {
 	if (!(p = decode_fh(p, &args->ffh))
@@ -542,7 +542,7 @@
 }
 
 int
-nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readdirargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
@@ -562,7 +562,7 @@
 }
 
 int
-nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readdirargs *args)
 {
 	int len, pn;
@@ -590,7 +590,7 @@
 }
 
 int
-nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_commitargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
@@ -609,14 +609,14 @@
  * will work properly.
  */
 int
-nfs3svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_ressize_check(rqstp, p);
 }
 
 /* GETATTR */
 int
-nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_attrstat *resp)
 {
 	if (resp->status == 0)
@@ -626,7 +626,7 @@
 
 /* SETATTR, REMOVE, RMDIR */
 int
-nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_attrstat *resp)
 {
 	p = encode_wcc_data(rqstp, p, &resp->fh);
@@ -635,7 +635,7 @@
 
 /* LOOKUP */
 int
-nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_diropres *resp)
 {
 	if (resp->status == 0) {
@@ -648,7 +648,7 @@
 
 /* ACCESS */
 int
-nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_accessres *resp)
 {
 	p = encode_post_op_attr(rqstp, p, &resp->fh);
@@ -659,7 +659,7 @@
 
 /* READLINK */
 int
-nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readlinkres *resp)
 {
 	p = encode_post_op_attr(rqstp, p, &resp->fh);
@@ -680,7 +680,7 @@
 
 /* READ */
 int
-nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readres *resp)
 {
 	p = encode_post_op_attr(rqstp, p, &resp->fh);
@@ -704,7 +704,7 @@
 
 /* WRITE */
 int
-nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_writeres *resp)
 {
 	p = encode_wcc_data(rqstp, p, &resp->fh);
@@ -719,7 +719,7 @@
 
 /* CREATE, MKDIR, SYMLINK, MKNOD */
 int
-nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_diropres *resp)
 {
 	if (resp->status == 0) {
@@ -733,7 +733,7 @@
 
 /* RENAME */
 int
-nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_renameres *resp)
 {
 	p = encode_wcc_data(rqstp, p, &resp->ffh);
@@ -743,7 +743,7 @@
 
 /* LINK */
 int
-nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_linkres *resp)
 {
 	p = encode_post_op_attr(rqstp, p, &resp->fh);
@@ -753,7 +753,7 @@
 
 /* READDIR */
 int
-nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_readdirres *resp)
 {
 	p = encode_post_op_attr(rqstp, p, &resp->fh);
@@ -776,8 +776,8 @@
 		return xdr_ressize_check(rqstp, p);
 }
 
-static inline u32 *
-encode_entry_baggage(struct nfsd3_readdirres *cd, u32 *p, const char *name,
+static inline __be32 *
+encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
 	     int namlen, ino_t ino)
 {
 	*p++ = xdr_one;				 /* mark entry present */
@@ -790,8 +790,8 @@
 	return p;
 }
 
-static inline u32 *
-encode_entryplus_baggage(struct nfsd3_readdirres *cd, u32 *p,
+static inline __be32 *
+encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p,
 		struct svc_fh *fhp)
 {
 		p = encode_post_op_attr(cd->rqstp, p, fhp);
@@ -853,7 +853,7 @@
 {
 	struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
 		       					common);
-	u32		*p = cd->buffer;
+	__be32		*p = cd->buffer;
 	caddr_t		curr_page_addr = NULL;
 	int		pn;		/* current page number */
 	int		slen;		/* string (name) length */
@@ -919,7 +919,7 @@
 	} else if (cd->rqstp->rq_respages[pn+1] != NULL) {
 		/* temporarily encode entry into next page, then move back to
 		 * current and next page in rq_respages[] */
-		u32 *p1, *tmp;
+		__be32 *p1, *tmp;
 		int len1, len2;
 
 		/* grab next page for temporary storage of entry */
@@ -1009,7 +1009,7 @@
 
 /* FSSTAT */
 int
-nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_fsstatres *resp)
 {
 	struct kstatfs	*s = &resp->stats;
@@ -1031,7 +1031,7 @@
 
 /* FSINFO */
 int
-nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_fsinfores *resp)
 {
 	*p++ = xdr_zero;	/* no post_op_attr */
@@ -1055,7 +1055,7 @@
 
 /* PATHCONF */
 int
-nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_pathconfres *resp)
 {
 	*p++ = xdr_zero;	/* no post_op_attr */
@@ -1074,7 +1074,7 @@
 
 /* COMMIT */
 int
-nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_commitres *resp)
 {
 	p = encode_wcc_data(rqstp, p, &resp->fh);
@@ -1090,7 +1090,7 @@
  * XDR release functions
  */
 int
-nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_attrstat *resp)
 {
 	fh_put(&resp->fh);
@@ -1098,7 +1098,7 @@
 }
 
 int
-nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
+nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd3_fhandle_pair *resp)
 {
 	fh_put(&resp->fh1);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index f6ca9fb..f57655a7 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -85,8 +85,8 @@
 /*
 * Generic encode routines from fs/nfs/nfs4xdr.c
 */
-static inline u32 *
-xdr_writemem(u32 *p, const void *ptr, int nbytes)
+static inline __be32 *
+xdr_writemem(__be32 *p, const void *ptr, int nbytes)
 {
 	int tmp = XDR_QUADLEN(nbytes);
 	if (!tmp)
@@ -205,7 +205,7 @@
 static int
 encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
 {
-	u32 * p;
+	__be32 * p;
 
 	RESERVE_SPACE(16);
 	WRITE32(0);            /* tag length is always 0 */
@@ -218,7 +218,7 @@
 static int
 encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
 {
-	u32 *p;
+	__be32 *p;
 	int len = cb_rec->cbr_fhlen;
 
 	RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
@@ -231,7 +231,7 @@
 }
 
 static int
-nfs4_xdr_enc_cb_null(struct rpc_rqst *req, u32 *p)
+nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p)
 {
 	struct xdr_stream xdrs, *xdr = &xdrs;
 
@@ -241,7 +241,7 @@
 }
 
 static int
-nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p, struct nfs4_cb_recall *args)
+nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, struct nfs4_cb_recall *args)
 {
 	struct xdr_stream xdr;
 	struct nfs4_cb_compound_hdr hdr = {
@@ -257,7 +257,7 @@
 
 static int
 decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){
-        u32 *p;
+        __be32 *p;
 
         READ_BUF(8);
         READ32(hdr->status);
@@ -272,7 +272,7 @@
 static int
 decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
 {
-	u32 *p;
+	__be32 *p;
 	u32 op;
 	int32_t nfserr;
 
@@ -291,13 +291,13 @@
 }
 
 static int
-nfs4_xdr_dec_cb_null(struct rpc_rqst *req, u32 *p)
+nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p)
 {
 	return 0;
 }
 
 static int
-nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p)
+nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p)
 {
 	struct xdr_stream xdr;
 	struct nfs4_cb_compound_hdr hdr;
@@ -421,7 +421,7 @@
 
 	/* Create RPC client */
 	cb->cb_client = rpc_create(&args);
-	if (!cb->cb_client) {
+	if (IS_ERR(cb->cb_client)) {
 		dprintk("NFSD: couldn't create callback client\n");
 		goto out_err;
 	}
@@ -448,10 +448,10 @@
 out_rpciod:
 	atomic_dec(&clp->cl_count);
 	rpciod_down();
-	cb->cb_client = NULL;
 out_clnt:
 	rpc_shutdown_client(cb->cb_client);
 out_err:
+	cb->cb_client = NULL;
 	dprintk("NFSD: warning: no callback path to client %.*s\n",
 		(int)clp->cl_name.len, clp->cl_name.data);
 }
@@ -461,7 +461,7 @@
 {
 	struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
 	struct nfs4_callback *cb = &clp->cl_callback;
-	u32 addr = htonl(cb->cb_addr);
+	__be32 addr = htonl(cb->cb_addr);
 
 	dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status);
 
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 8333db1..0a7bbdc 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -67,32 +67,32 @@
 	*dst = *src;
 }
 
-static int
-do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+static __be32
+do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode)
 {
-	int accmode, status;
+	__be32 status;
 
 	if (open->op_truncate &&
 		!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
 		return nfserr_inval;
 
-	accmode = MAY_NOP;
 	if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
-		accmode = MAY_READ;
-	if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
+		accmode |= MAY_READ;
+	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
 		accmode |= (MAY_WRITE | MAY_TRUNC);
-	accmode |= MAY_OWNER_OVERRIDE;
+	if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
+		accmode |= MAY_WRITE;
 
 	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
 
 	return status;
 }
 
-static int
+static __be32
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
 	struct svc_fh resfh;
-	int status;
+	__be32 status;
 
 	fh_init(&resfh, NFS4_FHSIZE);
 	open->op_truncate = 0;
@@ -124,17 +124,17 @@
 				&resfh.fh_handle.fh_base,
 				resfh.fh_handle.fh_size);
 
-		status = do_open_permission(rqstp, current_fh, open);
+		status = do_open_permission(rqstp, current_fh, open, MAY_NOP);
 	}
 
 	fh_put(&resfh);
 	return status;
 }
 
-static int
+static __be32
 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
-	int status;
+	__be32 status;
 
 	/* Only reclaims from previously confirmed clients are valid */
 	if ((status = nfs4_check_open_reclaim(&open->op_clientid)))
@@ -155,16 +155,16 @@
 	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
 		(open->op_iattr.ia_size == 0);
 
-	status = do_open_permission(rqstp, current_fh, open);
+	status = do_open_permission(rqstp, current_fh, open, MAY_OWNER_OVERRIDE);
 
 	return status;
 }
 
 
-static inline int
+static inline __be32
 nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
 {
-	int status;
+	__be32 status;
 	dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
 		(int)open->op_fname.len, open->op_fname.data,
 		open->op_stateowner);
@@ -177,7 +177,7 @@
 
 	/* check seqid for replay. set nfs4_owner */
 	status = nfsd4_process_open1(open);
-	if (status == NFSERR_REPLAY_ME) {
+	if (status == nfserr_replay_me) {
 		struct nfs4_replay *rp = &open->op_stateowner->so_replay;
 		fh_put(current_fh);
 		current_fh->fh_handle.fh_size = rp->rp_openfh_len;
@@ -188,7 +188,7 @@
 			dprintk("nfsd4_open: replay failed"
 				" restoring previous filehandle\n");
 		else
-			status = NFSERR_REPLAY_ME;
+			status = nfserr_replay_me;
 	}
 	if (status)
 		goto out;
@@ -261,7 +261,7 @@
 /*
  * filehandle-manipulating ops.
  */
-static inline int
+static inline __be32
 nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
 {
 	if (!current_fh->fh_dentry)
@@ -271,7 +271,7 @@
 	return nfs_ok;
 }
 
-static inline int
+static inline __be32
 nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
 {
 	fh_put(current_fh);
@@ -280,10 +280,10 @@
 	return fh_verify(rqstp, current_fh, 0, MAY_NOP);
 }
 
-static inline int
+static inline __be32
 nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
 {
-	int status;
+	__be32 status;
 
 	fh_put(current_fh);
 	status = exp_pseudoroot(rqstp->rq_client, current_fh,
@@ -291,7 +291,7 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
 {
 	if (!save_fh->fh_dentry)
@@ -301,7 +301,7 @@
 	return nfs_ok;
 }
 
-static inline int
+static inline __be32
 nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
 {
 	if (!current_fh->fh_dentry)
@@ -314,7 +314,7 @@
 /*
  * misc nfsv4 ops
  */
-static inline int
+static inline __be32
 nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
 {
 	if (access->ac_req_access & ~NFS3_ACCESS_FULL)
@@ -324,10 +324,10 @@
 	return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
 }
 
-static inline int
+static inline __be32
 nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
 {
-	int status;
+	__be32 status;
 
 	u32 *p = (u32 *)commit->co_verf.data;
 	*p++ = nfssvc_boot.tv_sec;
@@ -339,11 +339,11 @@
 	return status;
 }
 
-static int
+static __be32
 nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
 {
 	struct svc_fh resfh;
-	int status;
+	__be32 status;
 	dev_t rdev;
 
 	fh_init(&resfh, NFS4_FHSIZE);
@@ -423,10 +423,10 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
 {
-	int status;
+	__be32 status;
 
 	status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
 	if (status)
@@ -442,11 +442,11 @@
 	return nfs_ok;
 }
 
-static inline int
+static inline __be32
 nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 	   struct svc_fh *save_fh, struct nfsd4_link *link)
 {
-	int status = nfserr_nofilehandle;
+	__be32 status = nfserr_nofilehandle;
 
 	if (!save_fh->fh_dentry)
 		return status;
@@ -456,11 +456,11 @@
 	return status;
 }
 
-static int
+static __be32
 nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
 {
 	struct svc_fh tmp_fh;
-	int ret;
+	__be32 ret;
 
 	fh_init(&tmp_fh, NFS4_FHSIZE);
 	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
@@ -474,16 +474,16 @@
 	return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
 }
 
-static inline int
+static inline __be32
 nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
 {
 	return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
 }
 
-static inline int
+static inline __be32
 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
 {
-	int status;
+	__be32 status;
 
 	/* no need to check permission - this will be done in nfsd_read() */
 
@@ -508,7 +508,7 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
 {
 	u64 cookie = readdir->rd_cookie;
@@ -531,7 +531,7 @@
 	return nfs_ok;
 }
 
-static inline int
+static inline __be32
 nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
 {
 	readlink->rl_rqstp = rqstp;
@@ -539,10 +539,10 @@
 	return nfs_ok;
 }
 
-static inline int
+static inline __be32
 nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
 {
-	int status;
+	__be32 status;
 
 	if (nfs4_in_grace())
 		return nfserr_grace;
@@ -556,11 +556,11 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 	     struct svc_fh *save_fh, struct nfsd4_rename *rename)
 {
-	int status = nfserr_nofilehandle;
+	__be32 status = nfserr_nofilehandle;
 
 	if (!save_fh->fh_dentry)
 		return status;
@@ -589,10 +589,10 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
 {
-	int status = nfs_ok;
+	__be32 status = nfs_ok;
 
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 		nfs4_lock_state();
@@ -614,13 +614,13 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
 {
 	stateid_t *stateid = &write->wr_stateid;
 	struct file *filp = NULL;
 	u32 *p;
-	int status = nfs_ok;
+	__be32 status = nfs_ok;
 
 	/* no need to check permission - this will be done in nfsd_write() */
 
@@ -661,12 +661,12 @@
  * attributes matched.  VERIFY is implemented by mapping NFSERR_SAME
  * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
  */
-static int
+static __be32
 nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
 {
-	u32 *buf, *p;
+	__be32 *buf, *p;
 	int count;
-	int status;
+	__be32 status;
 
 	status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
 	if (status)
@@ -715,7 +715,7 @@
 /*
  * NULL call.
  */
-static int
+static __be32
 nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	return nfs_ok;
@@ -731,7 +731,7 @@
 /*
  * COMPOUND call.
  */
-static int
+static __be32
 nfsd4_proc_compound(struct svc_rqst *rqstp,
 		    struct nfsd4_compoundargs *args,
 		    struct nfsd4_compoundres *resp)
@@ -741,7 +741,7 @@
 	struct svc_fh	*save_fh = NULL;
 	struct nfs4_stateowner *replay_owner = NULL;
 	int		slack_space;    /* in words, not bytes! */
-	int		status;
+	__be32		status;
 
 	status = nfserr_resource;
 	current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL);
@@ -937,7 +937,7 @@
 		}
 
 encode_op:
-		if (op->status == NFSERR_REPLAY_ME) {
+		if (op->status == nfserr_replay_me) {
 			op->replay = &replay_owner->so_replay;
 			nfsd4_encode_replay(resp, op);
 			status = op->status = op->replay->rp_status;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 1cbd2e4..e9d0770 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -83,13 +83,13 @@
 	*out = '\0';
 }
 
-int
+__be32
 nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
 {
 	struct xdr_netobj cksum;
 	struct hash_desc desc;
 	struct scatterlist sg[1];
-	int status = nfserr_resource;
+	__be32 status = nfserr_resource;
 
 	dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
 			clname->len, clname->data);
@@ -193,7 +193,7 @@
 	struct dentry_list *child;
 
 	if (name && isdotent(name, namlen))
-		return nfs_ok;
+		return 0;
 	dentry = lookup_one_len(name, parent, namlen);
 	if (IS_ERR(dentry))
 		return PTR_ERR(dentry);
@@ -333,14 +333,14 @@
 	int status;
 
 	if (nfs4_has_reclaimed_state(child->d_name.name))
-		return nfs_ok;
+		return 0;
 
 	status = nfsd4_clear_clid_dir(parent, child);
 	if (status)
 		printk("failed to remove client recovery directory %s\n",
 				child->d_name.name);
 	/* Keep trying, success or failure: */
-	return nfs_ok;
+	return 0;
 }
 
 void
@@ -365,10 +365,10 @@
 		printk("nfsd4: illegal name %s in recovery directory\n",
 				child->d_name.name);
 		/* Keep trying; maybe the others are OK: */
-		return nfs_ok;
+		return 0;
 	}
 	nfs4_client_to_reclaim(child->d_name.name);
-	return nfs_ok;
+	return 0;
 }
 
 int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index ebcf226..293b649 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -710,10 +710,10 @@
  *		as described above.
  *
  */
-int
+__be32
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
 {
-	u32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	__be32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -721,7 +721,7 @@
 	nfs4_verifier		clverifier = setclid->se_verf;
 	unsigned int 		strhashval;
 	struct nfs4_client	*conf, *unconf, *new;
-	int 			status;
+	__be32 			status;
 	char                    dname[HEXDIR_LEN];
 	
 	if (!check_name(clname))
@@ -875,14 +875,14 @@
  *
  * NOTE: callback information will be processed here in a future patch
  */
-int
+__be32
 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
 	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
-	int status;
+	__be32 status;
 
 	if (STALE_CLIENTID(clid))
 		return nfserr_stale_clientid;
@@ -1280,13 +1280,13 @@
  * Called to check deny when READ with all zero stateid or
  * WRITE with all zero or all one stateid
  */
-static int
+static __be32
 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
 {
 	struct inode *ino = current_fh->fh_dentry->d_inode;
 	struct nfs4_file *fp;
 	struct nfs4_stateid *stp;
-	int ret;
+	__be32 ret;
 
 	dprintk("NFSD: nfs4_share_conflict\n");
 
@@ -1444,7 +1444,7 @@
 };
 
 
-int
+__be32
 nfsd4_process_open1(struct nfsd4_open *open)
 {
 	clientid_t *clientid = &open->op_clientid;
@@ -1477,7 +1477,7 @@
 	}
 	if (open->op_seqid == sop->so_seqid - 1) {
 		if (sop->so_replay.rp_buflen)
-			return NFSERR_REPLAY_ME;
+			return nfserr_replay_me;
 		/* The original OPEN failed so spectacularly
 		 * that we don't even have replay data saved!
 		 * Therefore, we have no choice but to continue
@@ -1501,7 +1501,7 @@
 	return nfs_ok;
 }
 
-static inline int
+static inline __be32
 nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
 {
 	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
@@ -1522,12 +1522,12 @@
 	return NULL;
 }
 
-static int
+static __be32
 nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
 		struct nfs4_delegation **dp)
 {
 	int flags;
-	int status = nfserr_bad_stateid;
+	__be32 status = nfserr_bad_stateid;
 
 	*dp = find_delegation_file(fp, &open->op_delegate_stateid);
 	if (*dp == NULL)
@@ -1546,11 +1546,11 @@
 	return nfs_ok;
 }
 
-static int
+static __be32
 nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
 {
 	struct nfs4_stateid *local;
-	int status = nfserr_share_denied;
+	__be32 status = nfserr_share_denied;
 	struct nfs4_stateowner *sop = open->op_stateowner;
 
 	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
@@ -1575,7 +1575,7 @@
 	return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
 }
 
-static int
+static __be32
 nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
 		struct nfs4_delegation *dp,
 		struct svc_fh *cur_fh, int flags)
@@ -1590,7 +1590,7 @@
 		get_file(dp->dl_vfs_file);
 		stp->st_vfs_file = dp->dl_vfs_file;
 	} else {
-		int status;
+		__be32 status;
 		status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
 				&stp->st_vfs_file);
 		if (status) {
@@ -1604,7 +1604,7 @@
 	return 0;
 }
 
-static inline int
+static inline __be32
 nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
 		struct nfsd4_open *open)
 {
@@ -1619,22 +1619,22 @@
 	return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
 }
 
-static int
+static __be32
 nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
 {
 	struct file *filp = stp->st_vfs_file;
 	struct inode *inode = filp->f_dentry->d_inode;
 	unsigned int share_access, new_writer;
-	int status;
+	__be32 status;
 
 	set_access(&share_access, stp->st_access_bmap);
 	new_writer = (~share_access) & open->op_share_access
 			& NFS4_SHARE_ACCESS_WRITE;
 
 	if (new_writer) {
-		status = get_write_access(inode);
-		if (status)
-			return nfserrno(status);
+		int err = get_write_access(inode);
+		if (err)
+			return nfserrno(err);
 	}
 	status = nfsd4_truncate(rqstp, cur_fh, open);
 	if (status) {
@@ -1738,14 +1738,14 @@
 /*
  * called with nfs4_lock_state() held.
  */
-int
+__be32
 nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
 	struct nfs4_file *fp = NULL;
 	struct inode *ino = current_fh->fh_dentry->d_inode;
 	struct nfs4_stateid *stp = NULL;
 	struct nfs4_delegation *dp = NULL;
-	int status;
+	__be32 status;
 
 	status = nfserr_inval;
 	if (!access_valid(open->op_share_access)
@@ -1833,11 +1833,11 @@
 static void laundromat_main(void *);
 static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
 
-int 
+__be32
 nfsd4_renew(clientid_t *clid)
 {
 	struct nfs4_client *clp;
-	int status;
+	__be32 status;
 
 	nfs4_lock_state();
 	dprintk("process_renew(%08x/%08x): starting\n", 
@@ -1996,9 +1996,9 @@
 }
 
 static
-int nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
+__be32 nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
 {
-        int status = nfserr_openmode;
+        __be32 status = nfserr_openmode;
 
 	if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap)))
                 goto out;
@@ -2009,7 +2009,7 @@
 	return status;
 }
 
-static inline int
+static inline __be32
 check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
 {
 	/* Trying to call delegreturn with a special stateid? Yuch: */
@@ -2043,14 +2043,14 @@
 /*
 * Checks for stateid operations
 */
-int
+__be32
 nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filpp)
 {
 	struct nfs4_stateid *stp = NULL;
 	struct nfs4_delegation *dp = NULL;
 	stateid_t *stidp;
 	struct inode *ino = current_fh->fh_dentry->d_inode;
-	int status;
+	__be32 status;
 
 	dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
 		stateid->si_boot, stateid->si_stateownerid, 
@@ -2125,7 +2125,7 @@
 /* 
  * Checks for sequence id mutating operations. 
  */
-static int
+static __be32
 nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock)
 {
 	struct nfs4_stateid *stp;
@@ -2169,7 +2169,7 @@
 		clientid_t *lockclid = &lock->v.new.clientid;
 		struct nfs4_client *clp = sop->so_client;
 		int lkflg = 0;
-		int status;
+		__be32 status;
 
 		lkflg = setlkflg(lock->lk_type);
 
@@ -2233,7 +2233,7 @@
 	if (seqid == sop->so_seqid - 1) {
 		dprintk("NFSD: preprocess_seqid_op: retransmission?\n");
 		/* indicate replay to calling function */
-		return NFSERR_REPLAY_ME;
+		return nfserr_replay_me;
 	}
 	printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n",
 			sop->so_seqid, seqid);
@@ -2241,10 +2241,10 @@
 	return nfserr_bad_seqid;
 }
 
-int
+__be32
 nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
 {
-	int status;
+	__be32 status;
 	struct nfs4_stateowner *sop;
 	struct nfs4_stateid *stp;
 
@@ -2310,10 +2310,10 @@
 	}
 }
 
-int
+__be32
 nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
 {
-	int status;
+	__be32 status;
 	struct nfs4_stateid *stp;
 	unsigned int share_access;
 
@@ -2365,10 +2365,10 @@
 /*
  * nfs4_unlock_state() called after encode
  */
-int
+__be32
 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
 {
-	int status;
+	__be32 status;
 	struct nfs4_stateid *stp;
 
 	dprintk("NFSD: nfsd4_close on file %.*s\n", 
@@ -2404,10 +2404,10 @@
 	return status;
 }
 
-int
+__be32
 nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr)
 {
-	int status;
+	__be32 status;
 
 	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
 		goto out;
@@ -2635,7 +2635,7 @@
 /*
  *  LOCK operation 
  */
-int
+__be32
 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
 {
 	struct nfs4_stateowner *open_sop = NULL;
@@ -2644,8 +2644,9 @@
 	struct file *filp;
 	struct file_lock file_lock;
 	struct file_lock conflock;
-	int status = 0;
+	__be32 status = 0;
 	unsigned int strhashval;
+	int err;
 
 	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
 		(long long) lock->lk_offset,
@@ -2758,13 +2759,14 @@
 	 * locks_copy_lock: */
 	conflock.fl_ops = NULL;
 	conflock.fl_lmops = NULL;
-	status = posix_lock_file_conf(filp, &file_lock, &conflock);
+	err = posix_lock_file_conf(filp, &file_lock, &conflock);
 	dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
-	switch (-status) {
+	switch (-err) {
 	case 0: /* success! */
 		update_stateid(&lock_stp->st_stateid);
 		memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, 
 				sizeof(stateid_t));
+		status = 0;
 		break;
 	case (EAGAIN):		/* conflock holds conflicting lock */
 		status = nfserr_denied;
@@ -2775,7 +2777,7 @@
 		status = nfserr_deadlock;
 		break;
 	default:        
-		dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status);
+		dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",err);
 		status = nfserr_resource;
 		break;
 	}
@@ -2793,14 +2795,14 @@
 /*
  * LOCKT operation
  */
-int
+__be32
 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
 {
 	struct inode *inode;
 	struct file file;
 	struct file_lock file_lock;
 	struct file_lock conflock;
-	int status;
+	__be32 status;
 
 	if (nfs4_in_grace())
 		return nfserr_grace;
@@ -2873,13 +2875,14 @@
 	return status;
 }
 
-int
+__be32
 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
 {
 	struct nfs4_stateid *stp;
 	struct file *filp = NULL;
 	struct file_lock file_lock;
-	int status;
+	__be32 status;
+	int err;
 						        
 	dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
 		(long long) locku->lu_offset,
@@ -2917,8 +2920,8 @@
 	/*
 	*  Try to unlock the file in the VFS.
 	*/
-	status = posix_lock_file(filp, &file_lock); 
-	if (status) {
+	err = posix_lock_file(filp, &file_lock);
+	if (err) {
 		dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
 		goto out_nfserr;
 	}
@@ -2937,7 +2940,7 @@
 	return status;
 
 out_nfserr:
-	status = nfserrno(status);
+	status = nfserrno(err);
 	goto out;
 }
 
@@ -2965,7 +2968,7 @@
 	return status;
 }
 
-int
+__be32
 nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
 {
 	clientid_t *clid = &rlockowner->rl_clientid;
@@ -2974,7 +2977,7 @@
 	struct xdr_netobj *owner = &rlockowner->rl_owner;
 	struct list_head matches;
 	int i;
-	int status;
+	__be32 status;
 
 	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
 		clid->cl_boot, clid->cl_id);
@@ -3111,7 +3114,7 @@
 /*
 * Called from OPEN. Look for clientid in reclaim list.
 */
-int
+__be32
 nfs4_check_open_reclaim(clientid_t *clid)
 {
 	return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 41fc241..f3f239d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -68,8 +68,8 @@
 #define NFS4_REFERRAL_FSID_MAJOR	0x8000000ULL
 #define NFS4_REFERRAL_FSID_MINOR	0x8000000ULL
 
-static int
-check_filename(char *str, int len, int err)
+static __be32
+check_filename(char *str, int len, __be32 err)
 {
 	int i;
 
@@ -94,8 +94,8 @@
  * consistent with the style used in NFSv2/v3...
  */
 #define DECODE_HEAD				\
-	u32 *p;					\
-	int status
+	__be32 *p;				\
+	__be32 status
 #define DECODE_TAIL				\
 	status = 0;				\
 out:						\
@@ -144,13 +144,13 @@
 	}					\
 } while (0)
 
-static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
+static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
 {
 	/* We want more bytes than seem to be available.
 	 * Maybe we need a new page, maybe we have just run out
 	 */
 	int avail = (char*)argp->end - (char*)argp->p;
-	u32 *p;
+	__be32 *p;
 	if (avail + argp->pagelen < nbytes)
 		return NULL;
 	if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
@@ -197,7 +197,7 @@
 	return 0;
 }
 
-static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
+static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
 {
 	void *new = NULL;
 	if (p == argp->tmp) {
@@ -217,7 +217,7 @@
 }
 
 
-static int
+static __be32
 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 {
 	u32 bmlen;
@@ -240,13 +240,14 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr,
     struct nfs4_acl **acl)
 {
 	int expected_len, len = 0;
 	u32 dummy32;
 	char *buf;
+	int host_err;
 
 	DECODE_HEAD;
 	iattr->ia_valid = 0;
@@ -280,7 +281,7 @@
 
 		*acl = nfs4_acl_new();
 		if (*acl == NULL) {
-			status = -ENOMEM;
+			host_err = -ENOMEM;
 			goto out_nfserr;
 		}
 		defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
@@ -295,20 +296,20 @@
 			len += XDR_QUADLEN(dummy32) << 2;
 			READMEM(buf, dummy32);
 			ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
-			status = 0;
+			host_err = 0;
 			if (ace.whotype != NFS4_ACL_WHO_NAMED)
 				ace.who = 0;
 			else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
-				status = nfsd_map_name_to_gid(argp->rqstp,
+				host_err = nfsd_map_name_to_gid(argp->rqstp,
 						buf, dummy32, &ace.who);
 			else
-				status = nfsd_map_name_to_uid(argp->rqstp,
+				host_err = nfsd_map_name_to_uid(argp->rqstp,
 						buf, dummy32, &ace.who);
-			if (status)
+			if (host_err)
 				goto out_nfserr;
-			status = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+			host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
 				 ace.access_mask, ace.whotype, ace.who);
-			if (status)
+			if (host_err)
 				goto out_nfserr;
 		}
 	} else
@@ -327,7 +328,7 @@
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
+		if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
 			goto out_nfserr;
 		iattr->ia_valid |= ATTR_UID;
 	}
@@ -338,7 +339,7 @@
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
+		if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
 			goto out_nfserr;
 		iattr->ia_valid |= ATTR_GID;
 	}
@@ -414,11 +415,11 @@
 	DECODE_TAIL;
 
 out_nfserr:
-	status = nfserrno(status);
+	status = nfserrno(host_err);
 	goto out;
 }
 
-static int
+static __be32
 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
 {
 	DECODE_HEAD;
@@ -429,7 +430,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
 {
 	DECODE_HEAD;
@@ -444,7 +445,7 @@
 }
 
 
-static int
+static __be32
 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
 {
 	DECODE_HEAD;
@@ -456,7 +457,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
 {
 	DECODE_HEAD;
@@ -496,7 +497,7 @@
 	DECODE_TAIL;
 }
 
-static inline int
+static inline __be32
 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
 {
 	DECODE_HEAD;
@@ -508,13 +509,13 @@
 	DECODE_TAIL;
 }
 
-static inline int
+static inline __be32
 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
 {
 	return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
 }
 
-static int
+static __be32
 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
 {
 	DECODE_HEAD;
@@ -529,7 +530,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
 {
 	DECODE_HEAD;
@@ -568,7 +569,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
 {
 	DECODE_HEAD;
@@ -587,7 +588,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
 {
 	DECODE_HEAD;
@@ -606,7 +607,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
 {
 	DECODE_HEAD;
@@ -621,7 +622,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 {
 	DECODE_HEAD;
@@ -699,7 +700,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
 {
 	DECODE_HEAD;
@@ -713,7 +714,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
 {
 	DECODE_HEAD;
@@ -729,7 +730,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
 {
 	DECODE_HEAD;
@@ -744,7 +745,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
 {
 	DECODE_HEAD;
@@ -758,7 +759,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
 {
 	DECODE_HEAD;
@@ -774,7 +775,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
 {
 	DECODE_HEAD;
@@ -789,7 +790,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
 {
 	DECODE_HEAD;
@@ -809,7 +810,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
 {
 	DECODE_HEAD;
@@ -820,7 +821,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
 {
 	DECODE_HEAD;
@@ -834,7 +835,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
 {
 	DECODE_HEAD;
@@ -859,7 +860,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
 {
 	DECODE_HEAD;
@@ -872,7 +873,7 @@
 }
 
 /* Also used for NVERIFY */
-static int
+static __be32
 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
 {
 #if 0
@@ -908,7 +909,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 {
 	int avail;
@@ -951,15 +952,15 @@
 			argp->pagelen -= len;
 		}
 	}
-	argp->end = (u32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
-	argp->p = (u32*)  (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
+	argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
+	argp->p = (__be32*)  (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
 	argp->rqstp->rq_vec[v].iov_len = len;
 	write->wr_vlen = v+1;
 
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
 {
 	DECODE_HEAD;
@@ -973,7 +974,7 @@
 	DECODE_TAIL;
 }
 
-static int
+static __be32
 nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 {
 	DECODE_HEAD;
@@ -1179,7 +1180,7 @@
  * task to translate them into Linux-specific versions which are more
  * consistent with the style used in NFSv2/v3...
  */
-#define ENCODE_HEAD              u32 *p
+#define ENCODE_HEAD              __be32 *p
 
 #define WRITE32(n)               *p++ = htonl(n)
 #define WRITE64(n)               do {				\
@@ -1209,8 +1210,8 @@
  * Header routine to setup seqid operation replay cache
  */
 #define ENCODE_SEQID_OP_HEAD					\
-	u32 *p;							\
-	u32 *save;						\
+	__be32 *p;						\
+	__be32 *save;						\
 								\
 	save = resp->p;
 
@@ -1234,11 +1235,11 @@
 /* Encode as an array of strings the string given with components
  * seperated @sep.
  */
-static int nfsd4_encode_components(char sep, char *components,
-				   u32 **pp, int *buflen)
+static __be32 nfsd4_encode_components(char sep, char *components,
+				   __be32 **pp, int *buflen)
 {
-	u32 *p = *pp;
-	u32 *countp = p;
+	__be32 *p = *pp;
+	__be32 *countp = p;
 	int strlen, count=0;
 	char *str, *end;
 
@@ -1271,11 +1272,11 @@
 /*
  * encode a location element of a fs_locations structure
  */
-static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
-				    u32 **pp, int *buflen)
+static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
+				    __be32 **pp, int *buflen)
 {
-	int status;
-	u32 *p = *pp;
+	__be32 status;
+	__be32 *p = *pp;
 
 	status = nfsd4_encode_components(':', location->hosts, &p, buflen);
 	if (status)
@@ -1292,16 +1293,15 @@
  * Returned string is safe to use as long as the caller holds a reference
  * to @exp.
  */
-static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp)
+static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat)
 {
 	struct svc_fh tmp_fh;
 	char *path, *rootpath;
-	int stat;
 
 	fh_init(&tmp_fh, NFS4_FHSIZE);
-	stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
-	if (stat)
-		return ERR_PTR(stat);
+	*stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
+	if (*stat)
+		return NULL;
 	rootpath = tmp_fh.fh_export->ex_path;
 
 	path = exp->ex_path;
@@ -1309,7 +1309,8 @@
 	if (strncmp(path, rootpath, strlen(rootpath))) {
 		printk("nfsd: fs_locations failed;"
 			"%s is not contained in %s\n", path, rootpath);
-		return ERR_PTR(-EOPNOTSUPP);
+		*stat = nfserr_notsupp;
+		return NULL;
 	}
 
 	return path + strlen(rootpath);
@@ -1318,17 +1319,18 @@
 /*
  *  encode a fs_locations structure
  */
-static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
+static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
 				     struct svc_export *exp,
-				     u32 **pp, int *buflen)
+				     __be32 **pp, int *buflen)
 {
-	int status, i;
-	u32 *p = *pp;
+	__be32 status;
+	int i;
+	__be32 *p = *pp;
 	struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
-	char *root = nfsd4_path(rqstp, exp);
+	char *root = nfsd4_path(rqstp, exp, &status);
 
-	if (IS_ERR(root))
-		return PTR_ERR(root);
+	if (status)
+		return status;
 	status = nfsd4_encode_components('/', root, &p, buflen);
 	if (status)
 		return status;
@@ -1352,9 +1354,9 @@
         NF4SOCK, NF4BAD,  NF4LNK, NF4BAD,
 };
 
-static int
+static __be32
 nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
-			u32 **p, int *buflen)
+			__be32 **p, int *buflen)
 {
 	int status;
 
@@ -1374,21 +1376,21 @@
 	return 0;
 }
 
-static inline int
-nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
+static inline __be32
+nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
 {
 	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
 }
 
-static inline int
-nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
+static inline __be32
+nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
 {
 	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
 }
 
-static inline int
+static inline __be32
 nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
-		u32 **p, int *buflen)
+		__be32 **p, int *buflen)
 {
 	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
 }
@@ -1397,7 +1399,7 @@
 			      FATTR4_WORD0_RDATTR_ERROR)
 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
 
-static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
+static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
 {
 	/* As per referral draft:  */
 	if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
@@ -1420,9 +1422,9 @@
  * @countp is the buffer size in _words_; upon successful return this becomes
  * replaced with the number of words written.
  */
-int
+__be32
 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
-		struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval,
+		struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
 		struct svc_rqst *rqstp)
 {
 	u32 bmval0 = bmval[0];
@@ -1431,12 +1433,13 @@
 	struct svc_fh tempfh;
 	struct kstatfs statfs;
 	int buflen = *countp << 2;
-	u32 *attrlenp;
+	__be32 *attrlenp;
 	u32 dummy;
 	u64 dummy64;
 	u32 rdattr_err = 0;
-	u32 *p = buffer;
-	int status;
+	__be32 *p = buffer;
+	__be32 status;
+	int err;
 	int aclsupport = 0;
 	struct nfs4_acl *acl = NULL;
 
@@ -1450,14 +1453,14 @@
 			goto out;
 	}
 
-	status = vfs_getattr(exp->ex_mnt, dentry, &stat);
-	if (status)
+	err = vfs_getattr(exp->ex_mnt, dentry, &stat);
+	if (err)
 		goto out_nfserr;
 	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
 	    (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
 		       FATTR4_WORD1_SPACE_TOTAL))) {
-		status = vfs_statfs(dentry, &statfs);
-		if (status)
+		err = vfs_statfs(dentry, &statfs);
+		if (err)
 			goto out_nfserr;
 	}
 	if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
@@ -1469,15 +1472,15 @@
 	}
 	if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
 			| FATTR4_WORD0_SUPPORTED_ATTRS)) {
-		status = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
-		aclsupport = (status == 0);
+		err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
+		aclsupport = (err == 0);
 		if (bmval0 & FATTR4_WORD0_ACL) {
-			if (status == -EOPNOTSUPP)
+			if (err == -EOPNOTSUPP)
 				bmval0 &= ~FATTR4_WORD0_ACL;
-			else if (status == -EINVAL) {
+			else if (err == -EINVAL) {
 				status = nfserr_attrnotsupp;
 				goto out;
-			} else if (status != 0)
+			} else if (err != 0)
 				goto out_nfserr;
 		}
 	}
@@ -1817,7 +1820,7 @@
 		fh_put(&tempfh);
 	return status;
 out_nfserr:
-	status = nfserrno(status);
+	status = nfserrno(err);
 	goto out;
 out_resource:
 	*countp = 0;
@@ -1828,13 +1831,13 @@
 	goto out;
 }
 
-static int
+static __be32
 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
-		const char *name, int namlen, u32 *p, int *buflen)
+		const char *name, int namlen, __be32 *p, int *buflen)
 {
 	struct svc_export *exp = cd->rd_fhp->fh_export;
 	struct dentry *dentry;
-	int nfserr;
+	__be32 nfserr;
 
 	dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
 	if (IS_ERR(dentry))
@@ -1863,10 +1866,10 @@
 	return nfserr;
 }
 
-static u32 *
-nfsd4_encode_rdattr_error(u32 *p, int buflen, int nfserr)
+static __be32 *
+nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
 {
-	u32 *attrlenp;
+	__be32 *attrlenp;
 
 	if (buflen < 6)
 		return NULL;
@@ -1886,8 +1889,8 @@
 {
 	struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
 	int buflen;
-	u32 *p = cd->buffer;
-	int nfserr = nfserr_toosmall;
+	__be32 *p = cd->buffer;
+	__be32 nfserr = nfserr_toosmall;
 
 	/* In nfsv4, "." and ".." never make it onto the wire.. */
 	if (name && isdotent(name, namlen)) {
@@ -1943,7 +1946,7 @@
 }
 
 static void
-nfsd4_encode_access(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_access *access)
+nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
 {
 	ENCODE_HEAD;
 
@@ -1956,7 +1959,7 @@
 }
 
 static void
-nfsd4_encode_close(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_close *close)
+nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
 {
 	ENCODE_SEQID_OP_HEAD;
 
@@ -1971,7 +1974,7 @@
 
 
 static void
-nfsd4_encode_commit(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_commit *commit)
+nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
 {
 	ENCODE_HEAD;
 
@@ -1983,7 +1986,7 @@
 }
 
 static void
-nfsd4_encode_create(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_create *create)
+nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
 {
 	ENCODE_HEAD;
 
@@ -1997,8 +2000,8 @@
 	}
 }
 
-static int
-nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_getattr *getattr)
+static __be32
+nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
 {
 	struct svc_fh *fhp = getattr->ga_fhp;
 	int buflen;
@@ -2016,7 +2019,7 @@
 }
 
 static void
-nfsd4_encode_getfh(struct nfsd4_compoundres *resp, int nfserr, struct svc_fh *fhp)
+nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh *fhp)
 {
 	unsigned int len;
 	ENCODE_HEAD;
@@ -2056,7 +2059,7 @@
 }
 
 static void
-nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
+nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
 {
 	ENCODE_SEQID_OP_HEAD;
 
@@ -2072,14 +2075,14 @@
 }
 
 static void
-nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lockt *lockt)
+nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
 {
 	if (nfserr == nfserr_denied)
 		nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
 }
 
 static void
-nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku)
+nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
 {
 	ENCODE_SEQID_OP_HEAD;
 
@@ -2095,7 +2098,7 @@
 
 
 static void
-nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link)
+nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
 {
 	ENCODE_HEAD;
 
@@ -2108,7 +2111,7 @@
 
 
 static void
-nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open *open)
+nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
 {
 	ENCODE_SEQID_OP_HEAD;
 
@@ -2173,7 +2176,7 @@
 }
 
 static void
-nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc)
+nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
 {
 	ENCODE_SEQID_OP_HEAD;
 				        
@@ -2188,7 +2191,7 @@
 }
 
 static void
-nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od)
+nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
 {
 	ENCODE_SEQID_OP_HEAD;
 				        
@@ -2202,8 +2205,8 @@
 	ENCODE_SEQID_OP_TAIL(od->od_stateowner);
 }
 
-static int
-nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr,
+static __be32
+nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
 		  struct nfsd4_read *read)
 {
 	u32 eof;
@@ -2267,8 +2270,8 @@
 	return 0;
 }
 
-static int
-nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink)
+static __be32
+nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
 {
 	int maxcount;
 	char *page;
@@ -2315,12 +2318,12 @@
 	return 0;
 }
 
-static int
-nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readdir *readdir)
+static __be32
+nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
 {
 	int maxcount;
 	loff_t offset;
-	u32 *page, *savep, *tailbase;
+	__be32 *page, *savep, *tailbase;
 	ENCODE_HEAD;
 
 	if (nfserr)
@@ -2395,7 +2398,7 @@
 }
 
 static void
-nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_remove *remove)
+nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
 {
 	ENCODE_HEAD;
 
@@ -2407,7 +2410,7 @@
 }
 
 static void
-nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rename *rename)
+nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
 {
 	ENCODE_HEAD;
 
@@ -2424,7 +2427,7 @@
  * regardless of the error status.
  */
 static void
-nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setattr *setattr)
+nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
 {
 	ENCODE_HEAD;
 
@@ -2443,7 +2446,7 @@
 }
 
 static void
-nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setclientid *scd)
+nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
 {
 	ENCODE_HEAD;
 
@@ -2462,7 +2465,7 @@
 }
 
 static void
-nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_write *write)
+nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
 {
 	ENCODE_HEAD;
 
@@ -2478,7 +2481,7 @@
 void
 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
 {
-	u32 *statp;
+	__be32 *statp;
 	ENCODE_HEAD;
 
 	RESERVE_SPACE(8);
@@ -2616,7 +2619,7 @@
  */
 
 int
-nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
         return xdr_ressize_check(rqstp, p);
 }
@@ -2638,9 +2641,9 @@
 }
 
 int
-nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args)
+nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
 {
-	int status;
+	__be32 status;
 
 	args->p = p;
 	args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
@@ -2659,7 +2662,7 @@
 }
 
 int
-nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundres *resp)
+nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp)
 {
 	/*
 	 * All that remains is to write the tag and operation count...
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index fdf7cf3..6100bbe 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -29,7 +29,7 @@
  */
 #define CACHESIZE		1024
 #define HASHSIZE		64
-#define REQHASH(xid)		((((xid) >> 24) ^ (xid)) & (HASHSIZE-1))
+#define REQHASH(xid)		(((((__force __u32)xid) >> 24) ^ ((__force __u32)xid)) & (HASHSIZE-1))
 
 static struct hlist_head *	hash_list;
 static struct list_head 	lru_head;
@@ -127,8 +127,8 @@
 	struct hlist_node	*hn;
 	struct hlist_head 	*rh;
 	struct svc_cacherep	*rp;
-	u32			xid = rqstp->rq_xid,
-				proto =  rqstp->rq_prot,
+	__be32			xid = rqstp->rq_xid;
+	u32			proto =  rqstp->rq_prot,
 				vers = rqstp->rq_vers,
 				proc = rqstp->rq_proc;
 	unsigned long		age;
@@ -258,7 +258,7 @@
  * In this case, nfsd_cache_update is called with statp == NULL.
  */
 void
-nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, u32 *statp)
+nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
 {
 	struct svc_cacherep *rp;
 	struct kvec	*resv = &rqstp->rq_res.head[0], *cachv;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 501d838..727ab3b 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -76,7 +76,7 @@
  * comment in the NFSv3 spec says this is incorrect (implementation notes for
  * the write call).
  */
-static inline int
+static inline __be32
 nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
 {
 	/* Type can be negative when creating hardlinks - not to a dir */
@@ -110,13 +110,13 @@
  * This is only called at the start of an nfsproc call, so fhp points to
  * a svc_fh which is all 0 except for the over-the-wire file handle.
  */
-u32
+__be32
 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 {
 	struct knfsd_fh	*fh = &fhp->fh_handle;
 	struct svc_export *exp = NULL;
 	struct dentry	*dentry;
-	u32		error = 0;
+	__be32		error = 0;
 
 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
@@ -315,7 +315,7 @@
 		fh->ofh_dirino = 0;
 }
 
-int
+__be32
 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
 {
 	/* ref_fh is a reference file handle.
@@ -451,7 +451,7 @@
  * Update file handle information after changing a dentry.
  * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
  */
-int
+__be32
 fh_update(struct svc_fh *fhp)
 {
 	struct dentry *dentry;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 9ee1dab..ec983b7 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -30,22 +30,22 @@
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
 
-static int
+static __be32
 nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
 	return nfs_ok;
 }
 
-static int
-nfsd_return_attrs(int err, struct nfsd_attrstat *resp)
+static __be32
+nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
 {
 	if (err) return err;
 	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
 				    resp->fh.fh_dentry,
 				    &resp->stat));
 }
-static int
-nfsd_return_dirop(int err, struct nfsd_diropres *resp)
+static __be32
+nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
 {
 	if (err) return err;
 	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
@@ -56,11 +56,11 @@
  * Get a file's attributes
  * N.B. After this call resp->fh needs an fh_put
  */
-static int
+static __be32
 nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
 					  struct nfsd_attrstat *resp)
 {
-	int nfserr;
+	__be32 nfserr;
 	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
@@ -72,11 +72,11 @@
  * Set a file's attributes
  * N.B. After this call resp->fh needs an fh_put
  */
-static int
+static __be32
 nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
 					  struct nfsd_attrstat  *resp)
 {
-	int nfserr;
+	__be32 nfserr;
 	dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld\n",
 		SVCFH_fmt(&argp->fh),
 		argp->attrs.ia_valid, (long) argp->attrs.ia_size);
@@ -92,11 +92,11 @@
  * doesn't exist yet.
  * N.B. After this call resp->fh needs an fh_put
  */
-static int
+static __be32
 nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
 					 struct nfsd_diropres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: LOOKUP   %s %.*s\n",
 		SVCFH_fmt(&argp->fh), argp->len, argp->name);
@@ -112,11 +112,11 @@
 /*
  * Read a symlink.
  */
-static int
+static __be32
 nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_readlinkargs *argp,
 					   struct nfsd_readlinkres *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
 
@@ -132,11 +132,11 @@
  * Read a portion of a file.
  * N.B. After this call resp->fh needs an fh_put
  */
-static int
+static __be32
 nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
 				       struct nfsd_readres  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: READ    %s %d bytes at %d\n",
 		SVCFH_fmt(&argp->fh),
@@ -172,11 +172,11 @@
  * Write data to a file
  * N.B. After this call resp->fh needs an fh_put
  */
-static int
+static __be32
 nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
 					struct nfsd_attrstat  *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 	int	stable = 1;
 
 	dprintk("nfsd: WRITE    %s %d bytes at %d\n",
@@ -197,7 +197,7 @@
  * and the actual create() call in compliance with VFS protocols.
  * N.B. After this call _both_ argp->fh and resp->fh need an fh_put
  */
-static int
+static __be32
 nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
 					 struct nfsd_diropres   *resp)
 {
@@ -206,7 +206,8 @@
 	struct iattr	*attr = &argp->attrs;
 	struct inode	*inode;
 	struct dentry	*dchild;
-	int		nfserr, type, mode;
+	int		type, mode;
+	__be32		nfserr;
 	dev_t		rdev = 0, wanted = new_decode_dev(attr->ia_size);
 
 	dprintk("nfsd: CREATE   %s %.*s\n",
@@ -348,11 +349,11 @@
 	return nfsd_return_dirop(nfserr, resp);
 }
 
-static int
+static __be32
 nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
 					 void		       *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: REMOVE   %s %.*s\n", SVCFH_fmt(&argp->fh),
 		argp->len, argp->name);
@@ -363,11 +364,11 @@
 	return nfserr;
 }
 
-static int
+static __be32
 nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
 				  	 void		        *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: RENAME   %s %.*s -> \n",
 		SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
@@ -381,11 +382,11 @@
 	return nfserr;
 }
 
-static int
+static __be32
 nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
 				void			    *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: LINK     %s ->\n",
 		SVCFH_fmt(&argp->ffh));
@@ -401,12 +402,12 @@
 	return nfserr;
 }
 
-static int
+static __be32
 nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
 				          void			  *resp)
 {
 	struct svc_fh	newfh;
-	int		nfserr;
+	__be32		nfserr;
 
 	dprintk("nfsd: SYMLINK  %s %.*s -> %.*s\n",
 		SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
@@ -430,11 +431,11 @@
  * Make directory. This operation is not idempotent.
  * N.B. After this call resp->fh needs an fh_put
  */
-static int
+static __be32
 nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
 					struct nfsd_diropres   *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: MKDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
@@ -454,11 +455,11 @@
 /*
  * Remove a directory
  */
-static int
+static __be32
 nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
 				 	void		      *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: RMDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
@@ -470,11 +471,12 @@
 /*
  * Read a portion of a directory.
  */
-static int
+static __be32
 nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
 					  struct nfsd_readdirres  *resp)
 {
-	int		nfserr, count;
+	int		count;
+	__be32		nfserr;
 	loff_t		offset;
 
 	dprintk("nfsd: READDIR  %s %d bytes at %d\n",
@@ -509,11 +511,11 @@
 /*
  * Get file system info
  */
-static int
+static __be32
 nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle   *argp,
 					  struct nfsd_statfsres *resp)
 {
-	int	nfserr;
+	__be32	nfserr;
 
 	dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
 
@@ -579,11 +581,11 @@
 /*
  * Map errnos to NFS errnos.
  */
-int
+__be32
 nfserrno (int errno)
 {
 	static struct {
-		int	nfserr;
+		__be32	nfserr;
 		int	syserr;
 	} nfs_errtbl[] = {
 		{ nfs_ok, 0 },
@@ -615,11 +617,10 @@
 		{ nfserr_badname, -ESRCH },
 		{ nfserr_io, -ETXTBSY },
 		{ nfserr_notsupp, -EOPNOTSUPP },
-		{ -1, -EIO }
 	};
 	int	i;
 
-	for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
+	for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
 		if (nfs_errtbl[i].syserr == errno)
 			return nfs_errtbl[i].nfserr;
 	}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 6fa6340..0aaccb0 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -217,7 +217,7 @@
 
 	atomic_set(&nfsd_busy, 0);
 	nfsd_serv = svc_create_pooled(&nfsd_program,
-				      NFSD_BUFSIZE - NFSSVC_MAXBLKSIZE + nfsd_max_blksize,
+				      nfsd_max_blksize,
 				      nfsd_last_thread,
 				      nfsd, SIG_NOCLEAN, THIS_MODULE);
 	if (nfsd_serv == NULL)
@@ -491,12 +491,12 @@
 }
 
 int
-nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
+nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
 	struct svc_procedure	*proc;
 	kxdrproc_t		xdr;
-	u32			nfserr;
-	u32			*nfserrp;
+	__be32			nfserr;
+	__be32			*nfserrp;
 
 	dprintk("nfsd_dispatch: vers %d proc %d\n",
 				rqstp->rq_vers, rqstp->rq_proc);
@@ -515,7 +515,7 @@
 
 	/* Decode arguments */
 	xdr = proc->pc_decode;
-	if (xdr && !xdr(rqstp, (u32*)rqstp->rq_arg.head[0].iov_base,
+	if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
 			rqstp->rq_argp)) {
 		dprintk("nfsd: failed to decode arguments!\n");
 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
@@ -528,7 +528,7 @@
 	 */
 	nfserrp = rqstp->rq_res.head[0].iov_base
 		+ rqstp->rq_res.head[0].iov_len;
-	rqstp->rq_res.head[0].iov_len += sizeof(u32);
+	rqstp->rq_res.head[0].iov_len += sizeof(__be32);
 
 	/* Now call the procedure handler, and encode NFS status. */
 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 1135c0d..56ebb14 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -37,8 +37,8 @@
 /*
  * XDR functions for basic NFS types
  */
-static u32 *
-decode_fh(u32 *p, struct svc_fh *fhp)
+static __be32 *
+decode_fh(__be32 *p, struct svc_fh *fhp)
 {
 	fh_init(fhp, NFS_FHSIZE);
 	memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
@@ -50,13 +50,13 @@
 }
 
 /* Helper function for NFSv2 ACL code */
-u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp)
+__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
 {
 	return decode_fh(p, fhp);
 }
 
-static inline u32 *
-encode_fh(u32 *p, struct svc_fh *fhp)
+static inline __be32 *
+encode_fh(__be32 *p, struct svc_fh *fhp)
 {
 	memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
 	return p + (NFS_FHSIZE>> 2);
@@ -66,8 +66,8 @@
  * Decode a file name and make sure that the path contains
  * no slashes or null bytes.
  */
-static inline u32 *
-decode_filename(u32 *p, char **namp, int *lenp)
+static inline __be32 *
+decode_filename(__be32 *p, char **namp, int *lenp)
 {
 	char		*name;
 	int		i;
@@ -82,8 +82,8 @@
 	return p;
 }
 
-static inline u32 *
-decode_pathname(u32 *p, char **namp, int *lenp)
+static inline __be32 *
+decode_pathname(__be32 *p, char **namp, int *lenp)
 {
 	char		*name;
 	int		i;
@@ -98,8 +98,8 @@
 	return p;
 }
 
-static inline u32 *
-decode_sattr(u32 *p, struct iattr *iap)
+static inline __be32 *
+decode_sattr(__be32 *p, struct iattr *iap)
 {
 	u32	tmp, tmp1;
 
@@ -151,8 +151,8 @@
 	return p;
 }
 
-static u32 *
-encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
+static __be32 *
+encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 	     struct kstat *stat)
 {
 	struct dentry	*dentry = fhp->fh_dentry;
@@ -195,7 +195,7 @@
 }
 
 /* Helper function for NFSv2 ACL code */
-u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
 	struct kstat stat;
 	vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat);
@@ -206,13 +206,13 @@
  * XDR decode functions
  */
 int
-nfssvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_argsize_check(rqstp, p);
 }
 
 int
-nfssvc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args)
+nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
@@ -220,7 +220,7 @@
 }
 
 int
-nfssvc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_sattrargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -231,7 +231,7 @@
 }
 
 int
-nfssvc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_diropargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -242,7 +242,7 @@
 }
 
 int
-nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_readargs *args)
 {
 	unsigned int len;
@@ -273,7 +273,7 @@
 }
 
 int
-nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_writeargs *args)
 {
 	unsigned int len;
@@ -303,7 +303,7 @@
 }
 
 int
-nfssvc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_createargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
@@ -315,7 +315,7 @@
 }
 
 int
-nfssvc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_renameargs *args)
 {
 	if (!(p = decode_fh(p, &args->ffh))
@@ -328,7 +328,7 @@
 }
 
 int
-nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinkargs *args)
+nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readlinkargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
@@ -338,7 +338,7 @@
 }
 
 int
-nfssvc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_linkargs *args)
 {
 	if (!(p = decode_fh(p, &args->ffh))
@@ -350,7 +350,7 @@
 }
 
 int
-nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_symlinkargs *args)
 {
 	if (!(p = decode_fh(p, &args->ffh))
@@ -363,7 +363,7 @@
 }
 
 int
-nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
+nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_readdirargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh)))
@@ -382,13 +382,13 @@
  * XDR encode functions
  */
 int
-nfssvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
+nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 {
 	return xdr_ressize_check(rqstp, p);
 }
 
 int
-nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
+nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_attrstat *resp)
 {
 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
@@ -396,7 +396,7 @@
 }
 
 int
-nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
+nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_diropres *resp)
 {
 	p = encode_fh(p, &resp->fh);
@@ -405,7 +405,7 @@
 }
 
 int
-nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
+nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_readlinkres *resp)
 {
 	*p++ = htonl(resp->len);
@@ -421,7 +421,7 @@
 }
 
 int
-nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
+nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_readres *resp)
 {
 	p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
@@ -440,7 +440,7 @@
 }
 
 int
-nfssvc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
+nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_readdirres *resp)
 {
 	xdr_ressize_check(rqstp, p);
@@ -453,7 +453,7 @@
 }
 
 int
-nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
+nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_statfsres *resp)
 {
 	struct kstatfs	*stat = &resp->stats;
@@ -471,7 +471,7 @@
 		    int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
 	struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common);
-	u32	*p = cd->buffer;
+	__be32	*p = cd->buffer;
 	int	buflen, slen;
 
 	/*
@@ -497,7 +497,7 @@
 	*p++ = htonl((u32) ino);		/* file id */
 	p    = xdr_encode_array(p, name, namlen);/* name length & name */
 	cd->offset = p;			/* remember pointer */
-	*p++ = ~(u32) 0;		/* offset of next entry */
+	*p++ = htonl(~0U);		/* offset of next entry */
 
 	cd->buflen = buflen;
 	cd->buffer = p;
@@ -509,7 +509,7 @@
  * XDR release functions
  */
 int
-nfssvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
+nfssvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
 					struct nfsd_fhandle *resp)
 {
 	fh_put(&resp->fh);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 1141bd2..f21e917 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -110,7 +110,7 @@
 	struct dentry *dentry = *dpp;
 	struct vfsmount *mnt = mntget(exp->ex_mnt);
 	struct dentry *mounts = dget(dentry);
-	int err = nfs_ok;
+	int err = 0;
 
 	while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
 
@@ -148,14 +148,15 @@
  *   clients and is explicitly disallowed for NFSv3
  *      NeilBrown <neilb@cse.unsw.edu.au>
  */
-int
+__be32
 nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
 					int len, struct svc_fh *resfh)
 {
 	struct svc_export	*exp;
 	struct dentry		*dparent;
 	struct dentry		*dentry;
-	int			err;
+	__be32			err;
+	int			host_err;
 
 	dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name);
 
@@ -193,7 +194,7 @@
 			exp2 = exp_parent(exp->ex_client, mnt, dentry,
 					  &rqstp->rq_chandle);
 			if (IS_ERR(exp2)) {
-				err = PTR_ERR(exp2);
+				host_err = PTR_ERR(exp2);
 				dput(dentry);
 				mntput(mnt);
 				goto out_nfserr;
@@ -210,14 +211,14 @@
 	} else {
 		fh_lock(fhp);
 		dentry = lookup_one_len(name, dparent, len);
-		err = PTR_ERR(dentry);
+		host_err = PTR_ERR(dentry);
 		if (IS_ERR(dentry))
 			goto out_nfserr;
 		/*
 		 * check if we have crossed a mount point ...
 		 */
 		if (d_mountpoint(dentry)) {
-			if ((err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
+			if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
 				dput(dentry);
 				goto out_nfserr;
 			}
@@ -236,7 +237,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out;
 }
 
@@ -244,7 +245,7 @@
  * Set various file attributes.
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 	     int check_guard, time_t guardtime)
 {
@@ -253,7 +254,8 @@
 	int		accmode = MAY_SATTR;
 	int		ftype = 0;
 	int		imode;
-	int		err;
+	__be32		err;
+	int		host_err;
 	int		size_change = 0;
 
 	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
@@ -319,19 +321,19 @@
 		 * If we are changing the size of the file, then
 		 * we need to break all leases.
 		 */
-		err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
-		if (err == -EWOULDBLOCK)
-			err = -ETIMEDOUT;
-		if (err) /* ENOMEM or EWOULDBLOCK */
+		host_err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
+		if (host_err == -EWOULDBLOCK)
+			host_err = -ETIMEDOUT;
+		if (host_err) /* ENOMEM or EWOULDBLOCK */
 			goto out_nfserr;
 
-		err = get_write_access(inode);
-		if (err)
+		host_err = get_write_access(inode);
+		if (host_err)
 			goto out_nfserr;
 
 		size_change = 1;
-		err = locks_verify_truncate(inode, NULL, iap->ia_size);
-		if (err) {
+		host_err = locks_verify_truncate(inode, NULL, iap->ia_size);
+		if (host_err) {
 			put_write_access(inode);
 			goto out_nfserr;
 		}
@@ -357,8 +359,8 @@
 	err = nfserr_notsync;
 	if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
 		fh_lock(fhp);
-		err = notify_change(dentry, iap);
-		err = nfserrno(err);
+		host_err = notify_change(dentry, iap);
+		err = nfserrno(host_err);
 		fh_unlock(fhp);
 	}
 	if (size_change)
@@ -370,7 +372,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out;
 }
 
@@ -420,11 +422,12 @@
 	return error;
 }
 
-int
+__be32
 nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
     struct nfs4_acl *acl)
 {
-	int error;
+	__be32 error;
+	int host_error;
 	struct dentry *dentry;
 	struct inode *inode;
 	struct posix_acl *pacl = NULL, *dpacl = NULL;
@@ -440,20 +443,20 @@
 	if (S_ISDIR(inode->i_mode))
 		flags = NFS4_ACL_DIR;
 
-	error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
-	if (error == -EINVAL) {
+	host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
+	if (host_error == -EINVAL) {
 		error = nfserr_attrnotsupp;
 		goto out;
-	} else if (error < 0)
+	} else if (host_error < 0)
 		goto out_nfserr;
 
-	error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
-	if (error < 0)
+	host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
+	if (host_error < 0)
 		goto out_nfserr;
 
 	if (S_ISDIR(inode->i_mode)) {
-		error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
-		if (error < 0)
+		host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
+		if (host_error < 0)
 			goto out_nfserr;
 	}
 
@@ -464,7 +467,7 @@
 	posix_acl_release(dpacl);
 	return (error);
 out_nfserr:
-	error = nfserrno(error);
+	error = nfserrno(host_error);
 	goto out;
 }
 
@@ -571,14 +574,14 @@
     {	0,			0				}
 };
 
-int
+__be32
 nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported)
 {
 	struct accessmap	*map;
 	struct svc_export	*export;
 	struct dentry		*dentry;
 	u32			query, result = 0, sresult = 0;
-	unsigned int		error;
+	__be32			error;
 
 	error = fh_verify(rqstp, fhp, 0, MAY_NOP);
 	if (error)
@@ -598,7 +601,7 @@
 	query = *access;
 	for  (; map->access; map++) {
 		if (map->access & query) {
-			unsigned int err2;
+			__be32 err2;
 
 			sresult |= map->access;
 
@@ -637,13 +640,15 @@
  * The access argument indicates the type of open (read/write/lock)
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
 			int access, struct file **filp)
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
-	int		flags = O_RDONLY|O_LARGEFILE, err;
+	int		flags = O_RDONLY|O_LARGEFILE;
+	__be32		err;
+	int		host_err;
 
 	/*
 	 * If we get here, then the client has already done an "open",
@@ -673,10 +678,10 @@
 	 * Check to see if there are any leases on this file.
 	 * This may block while leases are broken.
 	 */
-	err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0));
-	if (err == -EWOULDBLOCK)
-		err = -ETIMEDOUT;
-	if (err) /* NOMEM or WOULDBLOCK */
+	host_err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0));
+	if (host_err == -EWOULDBLOCK)
+		host_err = -ETIMEDOUT;
+	if (host_err) /* NOMEM or WOULDBLOCK */
 		goto out_nfserr;
 
 	if (access & MAY_WRITE) {
@@ -689,10 +694,9 @@
 	}
 	*filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags);
 	if (IS_ERR(*filp))
-		err = PTR_ERR(*filp);
+		host_err = PTR_ERR(*filp);
 out_nfserr:
-	if (err)
-		err = nfserrno(err);
+	err = nfserrno(host_err);
 out:
 	return err;
 }
@@ -830,14 +834,15 @@
 	return size;
 }
 
-static int
+static __be32
 nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
               loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
 {
 	struct inode *inode;
 	struct raparms	*ra;
 	mm_segment_t	oldfs;
-	int		err;
+	__be32		err;
+	int		host_err;
 
 	err = nfserr_perm;
 	inode = file->f_dentry->d_inode;
@@ -855,12 +860,12 @@
 
 	if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
 		rqstp->rq_resused = 1;
-		err = file->f_op->sendfile(file, &offset, *count,
+		host_err = file->f_op->sendfile(file, &offset, *count,
 						 nfsd_read_actor, rqstp);
 	} else {
 		oldfs = get_fs();
 		set_fs(KERNEL_DS);
-		err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
+		host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
 		set_fs(oldfs);
 	}
 
@@ -874,13 +879,13 @@
 		spin_unlock(&rab->pb_lock);
 	}
 
-	if (err >= 0) {
-		nfsdstats.io_read += err;
-		*count = err;
+	if (host_err >= 0) {
+		nfsdstats.io_read += host_err;
+		*count = host_err;
 		err = 0;
 		fsnotify_access(file->f_dentry);
 	} else 
-		err = nfserrno(err);
+		err = nfserrno(host_err);
 out:
 	return err;
 }
@@ -895,7 +900,7 @@
 	mutex_unlock(&dentry->d_inode->i_mutex);
 }
 
-static int
+static __be32
 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 				loff_t offset, struct kvec *vec, int vlen,
 	   			unsigned long cnt, int *stablep)
@@ -904,7 +909,8 @@
 	struct dentry		*dentry;
 	struct inode		*inode;
 	mm_segment_t		oldfs;
-	int			err = 0;
+	__be32			err = 0;
+	int			host_err;
 	int			stable = *stablep;
 
 #ifdef MSNFS
@@ -940,18 +946,18 @@
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
+	host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
 	set_fs(oldfs);
-	if (err >= 0) {
+	if (host_err >= 0) {
 		nfsdstats.io_write += cnt;
 		fsnotify_modify(file->f_dentry);
 	}
 
 	/* clear setuid/setgid flag after write */
-	if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
+	if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
 		kill_suid(dentry);
 
-	if (err >= 0 && stable) {
+	if (host_err >= 0 && stable) {
 		static ino_t	last_ino;
 		static dev_t	last_dev;
 
@@ -977,7 +983,7 @@
 
 			if (inode->i_state & I_DIRTY) {
 				dprintk("nfsd: write sync %d\n", current->pid);
-				err=nfsd_sync(file);
+				host_err=nfsd_sync(file);
 			}
 #if 0
 			wake_up(&inode->i_wait);
@@ -987,11 +993,11 @@
 		last_dev = inode->i_sb->s_dev;
 	}
 
-	dprintk("nfsd: write complete err=%d\n", err);
-	if (err >= 0)
+	dprintk("nfsd: write complete host_err=%d\n", host_err);
+	if (host_err >= 0)
 		err = 0;
 	else 
-		err = nfserrno(err);
+		err = nfserrno(host_err);
 out:
 	return err;
 }
@@ -1001,12 +1007,12 @@
  * on entry. On return, *count contains the number of bytes actually read.
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 		loff_t offset, struct kvec *vec, int vlen,
 		unsigned long *count)
 {
-	int		err;
+	__be32		err;
 
 	if (file) {
 		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
@@ -1030,12 +1036,12 @@
  * The stable flag requests synchronous writes.
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 		loff_t offset, struct kvec *vec, int vlen, unsigned long cnt,
 		int *stablep)
 {
-	int			err = 0;
+	__be32			err = 0;
 
 	if (file) {
 		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
@@ -1067,12 +1073,12 @@
  * Unfortunately we cannot lock the file to make sure we return full WCC
  * data to the client, as locking happens lower down in the filesystem.
  */
-int
+__be32
 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
                loff_t offset, unsigned long count)
 {
 	struct file	*file;
-	int		err;
+	__be32		err;
 
 	if ((u64)count > ~(u64)offset)
 		return nfserr_inval;
@@ -1100,14 +1106,15 @@
  *
  * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
  */
-int
+__be32
 nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
 		char *fname, int flen, struct iattr *iap,
 		int type, dev_t rdev, struct svc_fh *resfhp)
 {
 	struct dentry	*dentry, *dchild = NULL;
 	struct inode	*dirp;
-	int		err;
+	__be32		err;
+	int		host_err;
 
 	err = nfserr_perm;
 	if (!flen)
@@ -1134,7 +1141,7 @@
 		/* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
 		fh_lock_nested(fhp, I_MUTEX_PARENT);
 		dchild = lookup_one_len(fname, dentry, flen);
-		err = PTR_ERR(dchild);
+		host_err = PTR_ERR(dchild);
 		if (IS_ERR(dchild))
 			goto out_nfserr;
 		err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
@@ -1173,22 +1180,22 @@
 	err = nfserr_perm;
 	switch (type) {
 	case S_IFREG:
-		err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+		host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
 		break;
 	case S_IFDIR:
-		err = vfs_mkdir(dirp, dchild, iap->ia_mode);
+		host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
 		break;
 	case S_IFCHR:
 	case S_IFBLK:
 	case S_IFIFO:
 	case S_IFSOCK:
-		err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
+		host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
 		break;
 	default:
 	        printk("nfsd: bad file type %o in nfsd_create\n", type);
-		err = -EINVAL;
+		host_err = -EINVAL;
 	}
-	if (err < 0)
+	if (host_err < 0)
 		goto out_nfserr;
 
 	if (EX_ISSYNC(fhp->fh_export)) {
@@ -1203,7 +1210,7 @@
 	 * directories via NFS.
 	 */
 	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
-		int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+		__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
 		if (err2)
 			err = err2;
 	}
@@ -1218,7 +1225,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out;
 }
 
@@ -1226,7 +1233,7 @@
 /*
  * NFSv3 version of nfsd_create
  */
-int
+__be32
 nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
 		char *fname, int flen, struct iattr *iap,
 		struct svc_fh *resfhp, int createmode, u32 *verifier,
@@ -1234,7 +1241,8 @@
 {
 	struct dentry	*dentry, *dchild = NULL;
 	struct inode	*dirp;
-	int		err;
+	__be32		err;
+	int		host_err;
 	__u32		v_mtime=0, v_atime=0;
 	int		v_mode=0;
 
@@ -1264,7 +1272,7 @@
 	 * Compose the response file handle.
 	 */
 	dchild = lookup_one_len(fname, dentry, flen);
-	err = PTR_ERR(dchild);
+	host_err = PTR_ERR(dchild);
 	if (IS_ERR(dchild))
 		goto out_nfserr;
 
@@ -1320,8 +1328,8 @@
 		goto out;
 	}
 
-	err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
-	if (err < 0)
+	host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+	if (host_err < 0)
 		goto out_nfserr;
 
 	if (EX_ISSYNC(fhp->fh_export)) {
@@ -1350,7 +1358,7 @@
 	 */
  set_attr:
 	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
- 		int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ 		__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
 		if (err2)
 			err = err2;
 	}
@@ -1368,7 +1376,7 @@
  	return err;
  
  out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out;
 }
 #endif /* CONFIG_NFSD_V3 */
@@ -1378,13 +1386,14 @@
  * fits into the buffer. On return, it contains the true length.
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
 	mm_segment_t	oldfs;
-	int		err;
+	__be32		err;
+	int		host_err;
 
 	err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP);
 	if (err)
@@ -1403,18 +1412,18 @@
 	 */
 
 	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = inode->i_op->readlink(dentry, buf, *lenp);
+	host_err = inode->i_op->readlink(dentry, buf, *lenp);
 	set_fs(oldfs);
 
-	if (err < 0)
+	if (host_err < 0)
 		goto out_nfserr;
-	*lenp = err;
+	*lenp = host_err;
 	err = 0;
 out:
 	return err;
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out;
 }
 
@@ -1422,7 +1431,7 @@
  * Create a symlink and look up its inode
  * N.B. After this call _both_ fhp and resfhp need an fh_put
  */
-int
+__be32
 nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
 				char *fname, int flen,
 				char *path,  int plen,
@@ -1430,7 +1439,8 @@
 				struct iattr *iap)
 {
 	struct dentry	*dentry, *dnew;
-	int		err, cerr;
+	__be32		err, cerr;
+	int		host_err;
 	umode_t		mode;
 
 	err = nfserr_noent;
@@ -1446,7 +1456,7 @@
 	fh_lock(fhp);
 	dentry = fhp->fh_dentry;
 	dnew = lookup_one_len(fname, dentry, flen);
-	err = PTR_ERR(dnew);
+	host_err = PTR_ERR(dnew);
 	if (IS_ERR(dnew))
 		goto out_nfserr;
 
@@ -1458,21 +1468,21 @@
 	if (unlikely(path[plen] != 0)) {
 		char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
 		if (path_alloced == NULL)
-			err = -ENOMEM;
+			host_err = -ENOMEM;
 		else {
 			strncpy(path_alloced, path, plen);
 			path_alloced[plen] = 0;
-			err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
+			host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
 			kfree(path_alloced);
 		}
 	} else
-		err = vfs_symlink(dentry->d_inode, dnew, path, mode);
+		host_err = vfs_symlink(dentry->d_inode, dnew, path, mode);
 
-	if (!err)
+	if (!host_err) {
 		if (EX_ISSYNC(fhp->fh_export))
-			err = nfsd_sync_dir(dentry);
-	if (err)
-		err = nfserrno(err);
+			host_err = nfsd_sync_dir(dentry);
+	}
+	err = nfserrno(host_err);
 	fh_unlock(fhp);
 
 	cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
@@ -1482,7 +1492,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out;
 }
 
@@ -1490,13 +1500,14 @@
  * Create a hardlink
  * N.B. After this call _both_ ffhp and tfhp need an fh_put
  */
-int
+__be32
 nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
 				char *name, int len, struct svc_fh *tfhp)
 {
 	struct dentry	*ddir, *dnew, *dold;
 	struct inode	*dirp, *dest;
-	int		err;
+	__be32		err;
+	int		host_err;
 
 	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);
 	if (err)
@@ -1517,24 +1528,25 @@
 	dirp = ddir->d_inode;
 
 	dnew = lookup_one_len(name, ddir, len);
-	err = PTR_ERR(dnew);
+	host_err = PTR_ERR(dnew);
 	if (IS_ERR(dnew))
 		goto out_nfserr;
 
 	dold = tfhp->fh_dentry;
 	dest = dold->d_inode;
 
-	err = vfs_link(dold, dirp, dnew);
-	if (!err) {
+	host_err = vfs_link(dold, dirp, dnew);
+	if (!host_err) {
 		if (EX_ISSYNC(ffhp->fh_export)) {
 			err = nfserrno(nfsd_sync_dir(ddir));
 			write_inode_now(dest, 1);
 		}
+		err = 0;
 	} else {
-		if (err == -EXDEV && rqstp->rq_vers == 2)
+		if (host_err == -EXDEV && rqstp->rq_vers == 2)
 			err = nfserr_acces;
 		else
-			err = nfserrno(err);
+			err = nfserrno(host_err);
 	}
 
 	dput(dnew);
@@ -1544,7 +1556,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 	goto out_unlock;
 }
 
@@ -1552,13 +1564,14 @@
  * Rename a file
  * N.B. After this call _both_ ffhp and tfhp need an fh_put
  */
-int
+__be32
 nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
 			    struct svc_fh *tfhp, char *tname, int tlen)
 {
 	struct dentry	*fdentry, *tdentry, *odentry, *ndentry, *trap;
 	struct inode	*fdir, *tdir;
-	int		err;
+	__be32		err;
+	int		host_err;
 
 	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);
 	if (err)
@@ -1589,22 +1602,22 @@
 	fill_pre_wcc(tfhp);
 
 	odentry = lookup_one_len(fname, fdentry, flen);
-	err = PTR_ERR(odentry);
+	host_err = PTR_ERR(odentry);
 	if (IS_ERR(odentry))
 		goto out_nfserr;
 
-	err = -ENOENT;
+	host_err = -ENOENT;
 	if (!odentry->d_inode)
 		goto out_dput_old;
-	err = -EINVAL;
+	host_err = -EINVAL;
 	if (odentry == trap)
 		goto out_dput_old;
 
 	ndentry = lookup_one_len(tname, tdentry, tlen);
-	err = PTR_ERR(ndentry);
+	host_err = PTR_ERR(ndentry);
 	if (IS_ERR(ndentry))
 		goto out_dput_old;
-	err = -ENOTEMPTY;
+	host_err = -ENOTEMPTY;
 	if (ndentry == trap)
 		goto out_dput_new;
 
@@ -1612,14 +1625,14 @@
 	if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		((atomic_read(&odentry->d_count) > 1)
 		 || (atomic_read(&ndentry->d_count) > 1))) {
-			err = -EPERM;
+			host_err = -EPERM;
 	} else
 #endif
-	err = vfs_rename(fdir, odentry, tdir, ndentry);
-	if (!err && EX_ISSYNC(tfhp->fh_export)) {
-		err = nfsd_sync_dir(tdentry);
-		if (!err)
-			err = nfsd_sync_dir(fdentry);
+	host_err = vfs_rename(fdir, odentry, tdir, ndentry);
+	if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
+		host_err = nfsd_sync_dir(tdentry);
+		if (!host_err)
+			host_err = nfsd_sync_dir(fdentry);
 	}
 
  out_dput_new:
@@ -1627,8 +1640,7 @@
  out_dput_old:
 	dput(odentry);
  out_nfserr:
-	if (err)
-		err = nfserrno(err);
+	err = nfserrno(host_err);
 
 	/* we cannot reply on fh_unlock on the two filehandles,
 	 * as that would do the wrong thing if the two directories
@@ -1647,13 +1659,14 @@
  * Unlink a file or directory
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
 				char *fname, int flen)
 {
 	struct dentry	*dentry, *rdentry;
 	struct inode	*dirp;
-	int		err;
+	__be32		err;
+	int		host_err;
 
 	err = nfserr_acces;
 	if (!flen || isdotent(fname, flen))
@@ -1667,7 +1680,7 @@
 	dirp = dentry->d_inode;
 
 	rdentry = lookup_one_len(fname, dentry, flen);
-	err = PTR_ERR(rdentry);
+	host_err = PTR_ERR(rdentry);
 	if (IS_ERR(rdentry))
 		goto out_nfserr;
 
@@ -1684,22 +1697,23 @@
 #ifdef MSNFS
 		if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 			(atomic_read(&rdentry->d_count) > 1)) {
-			err = -EPERM;
+			host_err = -EPERM;
 		} else
 #endif
-		err = vfs_unlink(dirp, rdentry);
+		host_err = vfs_unlink(dirp, rdentry);
 	} else { /* It's RMDIR */
-		err = vfs_rmdir(dirp, rdentry);
+		host_err = vfs_rmdir(dirp, rdentry);
 	}
 
 	dput(rdentry);
 
-	if (err == 0 &&
-	    EX_ISSYNC(fhp->fh_export))
-			err = nfsd_sync_dir(dentry);
+	if (host_err)
+		goto out_nfserr;
+	if (EX_ISSYNC(fhp->fh_export))
+		host_err = nfsd_sync_dir(dentry);
 
 out_nfserr:
-	err = nfserrno(err);
+	err = nfserrno(host_err);
 out:
 	return err;
 }
@@ -1708,11 +1722,12 @@
  * Read entries from a directory.
  * The  NFSv3/4 verifier we ignore for now.
  */
-int
+__be32
 nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, 
 	     struct readdir_cd *cdp, encode_dent_fn func)
 {
-	int		err;
+	__be32		err;
+	int 		host_err;
 	struct file	*file;
 	loff_t		offset = *offsetp;
 
@@ -1734,10 +1749,10 @@
 
 	do {
 		cdp->err = nfserr_eof; /* will be cleared on successful read */
-		err = vfs_readdir(file, (filldir_t) func, cdp);
-	} while (err >=0 && cdp->err == nfs_ok);
-	if (err)
-		err = nfserrno(err);
+		host_err = vfs_readdir(file, (filldir_t) func, cdp);
+	} while (host_err >=0 && cdp->err == nfs_ok);
+	if (host_err)
+		err = nfserrno(host_err);
 	else
 		err = cdp->err;
 	*offsetp = vfs_llseek(file, 0, 1);
@@ -1754,10 +1769,10 @@
  * Get file system stats
  * N.B. After this call fhp needs an fh_put
  */
-int
+__be32
 nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
 {
-	int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
+	__be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP);
 	if (!err && vfs_statfs(fhp->fh_dentry,stat))
 		err = nfserr_io;
 	return err;
@@ -1766,7 +1781,7 @@
 /*
  * Check for a user's access permissions to this inode.
  */
-int
+__be32
 nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
 {
 	struct inode	*inode = dentry->d_inode;
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index e1fceb8..d11753c 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -152,14 +152,16 @@
 	struct o2nm_node *node, *ret = NULL;
 
 	while (*p) {
+		int cmp;
+
 		parent = *p;
 		node = rb_entry(parent, struct o2nm_node, nd_ip_node);
 
-		if (memcmp(&ip_needle, &node->nd_ipv4_address,
-		           sizeof(ip_needle)) < 0)
+		cmp = memcmp(&ip_needle, &node->nd_ipv4_address,
+				sizeof(ip_needle));
+		if (cmp < 0)
 			p = &(*p)->rb_left;
-		else if (memcmp(&ip_needle, &node->nd_ipv4_address,
-			        sizeof(ip_needle)) > 0)
+		else if (cmp > 0)
 			p = &(*p)->rb_right;
 		else {
 			ret = node;
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index d9ba0a9..1be74c4 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -30,6 +30,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/uio.h>
+#include <linux/sched.h>
 
 #define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
@@ -691,6 +692,12 @@
 		}
 
 		start_off += sb->s_blocksize;
+
+		/*
+		 * Very large extends have the potential to lock up
+		 * the cpu for extended periods of time.
+		 */
+		cond_resched();
 	}
 
 out:
@@ -728,31 +735,36 @@
 	clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) - 
 		OCFS2_I(inode)->ip_clusters;
 
-	if (clusters_to_add) {
-		/* 
-		 * protect the pages that ocfs2_zero_extend is going to
-		 * be pulling into the page cache.. we do this before the
-		 * metadata extend so that we don't get into the situation
-		 * where we've extended the metadata but can't get the data
-		 * lock to zero.
-		 */
-		ret = ocfs2_data_lock(inode, 1);
-		if (ret < 0) {
-			mlog_errno(ret);
-			goto out;
-		}
+	/* 
+	 * protect the pages that ocfs2_zero_extend is going to be
+	 * pulling into the page cache.. we do this before the
+	 * metadata extend so that we don't get into the situation
+	 * where we've extended the metadata but can't get the data
+	 * lock to zero.
+	 */
+	ret = ocfs2_data_lock(inode, 1);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
 
+	if (clusters_to_add) {
 		ret = ocfs2_extend_allocation(inode, clusters_to_add);
 		if (ret < 0) {
 			mlog_errno(ret);
 			goto out_unlock;
 		}
+	}
 
-		ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip);
-		if (ret < 0) {
-			mlog_errno(ret);
-			goto out_unlock;
-		}
+	/*
+	 * Call this even if we don't add any clusters to the tree. We
+	 * still need to zero the area between the old i_size and the
+	 * new i_size.
+	 */
+	ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out_unlock;
 	}
 
 	if (!tail_to_skip) {
@@ -764,8 +776,7 @@
 	}
 
 out_unlock:
-	if (clusters_to_add) /* this is the only case in which we lock */
-		ocfs2_data_unlock(inode, 1);
+	ocfs2_data_unlock(inode, 1);
 
 out:
 	return ret;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 259155f..a57b751 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1085,14 +1085,6 @@
 			BUG();
 	}
 
-	if (atomic_read(&old_dentry->d_count) > 2) {
-		shrink_dcache_parent(old_dentry);
-		if (atomic_read(&old_dentry->d_count) > 2) {
-			status = -EBUSY;
-			goto bail;
-		}
-	}
-
 	/* Assume a directory heirarchy thusly:
 	 * a/b/c
 	 * a/d
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 4c29cd7..76b46eb 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -339,7 +339,7 @@
 
 #if BITS_PER_LONG == 32
 # if defined(CONFIG_LBD)
-	BUG_ON(sizeof(sector_t) != 8);
+	BUILD_BUG_ON(sizeof(sector_t) != 8);
 	pagefactor = PAGE_CACHE_SIZE;
 	bitshift = BITS_PER_LONG;
 # else
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 51c6a74..6fb4b61 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -376,18 +376,48 @@
 	return name;
 }
 
-static void disk_sysfs_symlinks(struct gendisk *disk)
+static int disk_sysfs_symlinks(struct gendisk *disk)
 {
 	struct device *target = get_device(disk->driverfs_dev);
+	int err;
+	char *disk_name = NULL;
+
 	if (target) {
-		char *disk_name = make_block_name(disk);
-		sysfs_create_link(&disk->kobj,&target->kobj,"device");
-		if (disk_name) {
-			sysfs_create_link(&target->kobj,&disk->kobj,disk_name);
-			kfree(disk_name);
+		disk_name = make_block_name(disk);
+		if (!disk_name) {
+			err = -ENOMEM;
+			goto err_out;
 		}
+
+		err = sysfs_create_link(&disk->kobj, &target->kobj, "device");
+		if (err)
+			goto err_out_disk_name;
+
+		err = sysfs_create_link(&target->kobj, &disk->kobj, disk_name);
+		if (err)
+			goto err_out_dev_link;
 	}
-	sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem");
+
+	err = sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj,
+				"subsystem");
+	if (err)
+		goto err_out_disk_name_lnk;
+
+	kfree(disk_name);
+
+	return 0;
+
+err_out_disk_name_lnk:
+	if (target) {
+		sysfs_remove_link(&target->kobj, disk_name);
+err_out_dev_link:
+		sysfs_remove_link(&disk->kobj, "device");
+err_out_disk_name:
+		kfree(disk_name);
+err_out:
+		put_device(target);
+	}
+	return err;
 }
 
 /* Not exported, helper to add_disk(). */
@@ -406,7 +436,11 @@
 		*s = '!';
 	if ((err = kobject_add(&disk->kobj)))
 		return;
-	disk_sysfs_symlinks(disk);
+	err = disk_sysfs_symlinks(disk);
+	if (err) {
+		kobject_del(&disk->kobj);
+		return;
+	}
  	disk_sysfs_add_subdirs(disk);
 
 	/* No minors to use for partitions */
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 4f8df71..8c7af17 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -32,13 +32,11 @@
 #include <asm/unaligned.h>
 
 #define SYS_IND(p)	(get_unaligned(&p->sys_ind))
-#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
-				get_unaligned(&p->nr_sects);	\
+#define NR_SECTS(p)	({ __le32 __a =	get_unaligned(&p->nr_sects);	\
 				le32_to_cpu(__a); \
 			})
 
-#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
-				get_unaligned(&p->start_sect);	\
+#define START_SECT(p)	({ __le32 __a =	get_unaligned(&p->start_sect);	\
 				le32_to_cpu(__a); \
 			})
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 82da55b..8df27401 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -72,6 +72,7 @@
 #include <linux/audit.h>
 #include <linux/poll.h>
 #include <linux/nsproxy.h>
+#include <linux/oom.h>
 #include "internal.h"
 
 /* NOTE:
@@ -86,7 +87,7 @@
 
 
 /* Worst case buffer size needed for holding an integer. */
-#define PROC_NUMBUF 10
+#define PROC_NUMBUF 13
 
 struct pid_entry {
 	int len;
@@ -689,7 +690,8 @@
 	if (copy_from_user(buffer, buf, count))
 		return -EFAULT;
 	oom_adjust = simple_strtol(buffer, &end, 0);
-	if ((oom_adjust < -16 || oom_adjust > 15) && oom_adjust != OOM_DISABLE)
+	if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) &&
+	     oom_adjust != OOM_DISABLE)
 		return -EINVAL;
 	if (*end == '\n')
 		end++;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 8d88e58..93c43b6 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -647,7 +647,7 @@
 
 		if (get_user(c, buf))
 			return -EFAULT;
-		__handle_sysrq(c, NULL, NULL, 0);
+		__handle_sysrq(c, NULL, 0);
 	}
 	return count;
 }
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 1bfae42..e3d466a 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -1304,8 +1304,8 @@
 
 	bh = sb_bread(sb, block);
 	if (bh == NULL)
-		reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%lu) "
-		                 "reading failed", __FUNCTION__, bh->b_blocknr);
+		reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) "
+		                 "reading failed", __FUNCTION__, block);
 	else {
 		if (buffer_locked(bh)) {
 			PROC_INFO_INC(sb, scan_bitmap.wait);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index ad8cbc4..85ce232 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -53,6 +53,7 @@
 #include <linux/workqueue.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
+#include <linux/backing-dev.h>
 
 /* gets a struct reiserfs_journal_list * from a list head */
 #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
@@ -970,7 +971,7 @@
 	DEFINE_WAIT(wait);
 	struct reiserfs_journal *j = SB_JOURNAL(s);
 	if (atomic_read(&j->j_async_throttle))
-		blk_congestion_wait(WRITE, HZ / 10);
+		congestion_wait(WRITE, HZ / 10);
 	return 0;
 }
 
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index c89aa23..9041802 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -430,21 +430,30 @@
 	return journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
 }
 
+static void reiserfs_kill_sb(struct super_block *s)
+{
+	if (REISERFS_SB(s)) {
+		if (REISERFS_SB(s)->xattr_root) {
+			d_invalidate(REISERFS_SB(s)->xattr_root);
+			dput(REISERFS_SB(s)->xattr_root);
+			REISERFS_SB(s)->xattr_root = NULL;
+		}
+
+		if (REISERFS_SB(s)->priv_root) {
+			d_invalidate(REISERFS_SB(s)->priv_root);
+			dput(REISERFS_SB(s)->priv_root);
+			REISERFS_SB(s)->priv_root = NULL;
+		}
+	}
+
+	kill_block_super(s);
+}
+
 static void reiserfs_put_super(struct super_block *s)
 {
 	struct reiserfs_transaction_handle th;
 	th.t_trans_id = 0;
 
-	if (REISERFS_SB(s)->xattr_root) {
-		d_invalidate(REISERFS_SB(s)->xattr_root);
-		dput(REISERFS_SB(s)->xattr_root);
-	}
-
-	if (REISERFS_SB(s)->priv_root) {
-		d_invalidate(REISERFS_SB(s)->priv_root);
-		dput(REISERFS_SB(s)->priv_root);
-	}
-
 	/* change file system state to current state if it was mounted with read-write permissions */
 	if (!(s->s_flags & MS_RDONLY)) {
 		if (!journal_begin(&th, s, 10)) {
@@ -2156,7 +2165,7 @@
 	.owner = THIS_MODULE,
 	.name = "reiserfs",
 	.get_sb = get_super_block,
-	.kill_sb = kill_block_super,
+	.kill_sb = reiserfs_kill_sb,
 	.fs_flags = FS_REQUIRES_DEV,
 };
 
diff --git a/fs/splice.c b/fs/splice.c
index 13e92dd..49fb9f1 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -607,7 +607,7 @@
 			ret = -ENOMEM;
 			page = page_cache_alloc_cold(mapping);
 			if (unlikely(!page))
-				goto out_nomem;
+				goto out_ret;
 
 			/*
 			 * This will also lock the page
@@ -666,7 +666,7 @@
 		if (sd->pos + this_len > isize)
 			vmtruncate(mapping->host, isize);
 
-		goto out;
+		goto out_ret;
 	}
 
 	if (buf->page != page) {
@@ -698,7 +698,7 @@
 out:
 	page_cache_release(page);
 	unlock_page(page);
-out_nomem:
+out_ret:
 	return ret;
 }
 
@@ -707,9 +707,9 @@
  * key here is the 'actor' worker passed in that actually moves the data
  * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
  */
-ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
-			 loff_t *ppos, size_t len, unsigned int flags,
-			 splice_actor *actor)
+static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
+				  struct file *out, loff_t *ppos, size_t len,
+				  unsigned int flags, splice_actor *actor)
 {
 	int ret, do_wakeup, err;
 	struct splice_desc sd;
@@ -722,9 +722,6 @@
 	sd.file = out;
 	sd.pos = *ppos;
 
-	if (pipe->inode)
-		mutex_lock(&pipe->inode->i_mutex);
-
 	for (;;) {
 		if (pipe->nrbufs) {
 			struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
@@ -797,9 +794,6 @@
 		pipe_wait(pipe);
 	}
 
-	if (pipe->inode)
-		mutex_unlock(&pipe->inode->i_mutex);
-
 	if (do_wakeup) {
 		smp_mb();
 		if (waitqueue_active(&pipe->wait))
@@ -810,6 +804,73 @@
 	return ret;
 }
 
+ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
+			 loff_t *ppos, size_t len, unsigned int flags,
+			 splice_actor *actor)
+{
+	ssize_t ret;
+	struct inode *inode = out->f_mapping->host;
+
+	/*
+	 * The actor worker might be calling ->prepare_write and
+	 * ->commit_write. Most of the time, these expect i_mutex to
+	 * be held. Since this may result in an ABBA deadlock with
+	 * pipe->inode, we have to order lock acquiry here.
+	 */
+	inode_double_lock(inode, pipe->inode);
+	ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor);
+	inode_double_unlock(inode, pipe->inode);
+
+	return ret;
+}
+
+/**
+ * generic_file_splice_write_nolock - generic_file_splice_write without mutexes
+ * @pipe:	pipe info
+ * @out:	file to write to
+ * @len:	number of bytes to splice
+ * @flags:	splice modifier flags
+ *
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file. The caller is responsible
+ * for acquiring i_mutex on both inodes.
+ *
+ */
+ssize_t
+generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
+				 loff_t *ppos, size_t len, unsigned int flags)
+{
+	struct address_space *mapping = out->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret;
+	int err;
+
+	err = remove_suid(out->f_dentry);
+	if (unlikely(err))
+		return err;
+
+	ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+	if (ret > 0) {
+		*ppos += ret;
+
+		/*
+		 * If file or inode is SYNC and we actually wrote some data,
+		 * sync it.
+		 */
+		if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+			err = generic_osync_inode(inode, mapping,
+						  OSYNC_METADATA|OSYNC_DATA);
+
+			if (err)
+				ret = err;
+		}
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(generic_file_splice_write_nolock);
+
 /**
  * generic_file_splice_write - splice data from a pipe to a file
  * @pipe:	pipe info
@@ -826,12 +887,21 @@
 			  loff_t *ppos, size_t len, unsigned int flags)
 {
 	struct address_space *mapping = out->f_mapping;
+	struct inode *inode = mapping->host;
 	ssize_t ret;
+	int err;
+
+	err = should_remove_suid(out->f_dentry);
+	if (unlikely(err)) {
+		mutex_lock(&inode->i_mutex);
+		err = __remove_suid(out->f_dentry, err);
+		mutex_unlock(&inode->i_mutex);
+		if (err)
+			return err;
+	}
 
 	ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
 	if (ret > 0) {
-		struct inode *inode = mapping->host;
-
 		*ppos += ret;
 
 		/*
@@ -839,8 +909,6 @@
 		 * sync it.
 		 */
 		if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
-			int err;
-
 			mutex_lock(&inode->i_mutex);
 			err = generic_osync_inode(inode, mapping,
 						  OSYNC_METADATA|OSYNC_DATA);
@@ -1400,13 +1468,7 @@
 	 * grabbing by inode address. Otherwise two different processes
 	 * could deadlock (one doing tee from A -> B, the other from B -> A).
 	 */
-	if (ipipe->inode < opipe->inode) {
-		mutex_lock_nested(&ipipe->inode->i_mutex, I_MUTEX_PARENT);
-		mutex_lock_nested(&opipe->inode->i_mutex, I_MUTEX_CHILD);
-	} else {
-		mutex_lock_nested(&opipe->inode->i_mutex, I_MUTEX_PARENT);
-		mutex_lock_nested(&ipipe->inode->i_mutex, I_MUTEX_CHILD);
-	}
+	inode_double_lock(ipipe->inode, opipe->inode);
 
 	do {
 		if (!opipe->readers) {
@@ -1450,8 +1512,7 @@
 		i++;
 	} while (len);
 
-	mutex_unlock(&ipipe->inode->i_mutex);
-	mutex_unlock(&opipe->inode->i_mutex);
+	inode_double_unlock(ipipe->inode, opipe->inode);
 
 	/*
 	 * If we put data in the output pipe, wakeup any potential readers.
diff --git a/fs/super.c b/fs/super.c
index aec99dd..47e554c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -260,17 +260,17 @@
  *	that need destruction out of superblock, call generic_shutdown_super()
  *	and release aforementioned objects.  Note: dentries and inodes _are_
  *	taken care of and do not need specific handling.
+ *
+ *	Upon calling this function, the filesystem may no longer alter or
+ *	rearrange the set of dentries belonging to this super_block, nor may it
+ *	change the attachments of dentries to inodes.
  */
 void generic_shutdown_super(struct super_block *sb)
 {
-	struct dentry *root = sb->s_root;
 	struct super_operations *sop = sb->s_op;
 
-	if (root) {
-		sb->s_root = NULL;
-		shrink_dcache_parent(root);
-		shrink_dcache_sb(sb);
-		dput(root);
+	if (sb->s_root) {
+		shrink_dcache_for_umount(sb);
 		fsync_super(sb);
 		lock_super(sb);
 		sb->s_flags &= ~MS_ACTIVE;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 146f1de..298303b 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -483,17 +483,12 @@
 		    (victim->d_parent->d_inode == dir->d_inode)) {
 			victim->d_inode->i_mtime = CURRENT_TIME;
 			fsnotify_modify(victim);
-
-			/**
-			 * Drop reference from initial sysfs_get_dentry().
-			 */
-			dput(victim);
 			res = 0;
 		} else
 			d_drop(victim);
 		
 		/**
-		 * Drop the reference acquired from sysfs_get_dentry() above.
+		 * Drop the reference acquired from lookup_one_len() above.
 		 */
 		dput(victim);
 	}
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 350cba5..dc9e7dc 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -358,16 +358,11 @@
 	unsigned long blocknr;
 	int size = 0, i;
 	
-	if (1024 != sizeof (struct xenix_super_block))
-		panic("Xenix FS: bad superblock size");
-	if (512 != sizeof (struct sysv4_super_block))
-		panic("SystemV FS: bad superblock size");
-	if (512 != sizeof (struct sysv2_super_block))
-		panic("SystemV FS: bad superblock size");
-	if (500 != sizeof (struct coh_super_block))
-		panic("Coherent FS: bad superblock size");
-	if (64 != sizeof (struct sysv_inode))
-		panic("sysv fs: bad inode size");
+	BUILD_BUG_ON(1024 != sizeof (struct xenix_super_block));
+	BUILD_BUG_ON(512 != sizeof (struct sysv4_super_block));
+	BUILD_BUG_ON(512 != sizeof (struct sysv2_super_block));
+	BUILD_BUG_ON(500 != sizeof (struct coh_super_block));
+	BUILD_BUG_ON(64 != sizeof (struct sysv_inode));
 
 	sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
 	if (!sbi)
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 1d3b5d2..1aea6a4 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1621,9 +1621,10 @@
 		goto error_out;
 	}
 
-	if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_READ_ONLY)
+	if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_READ_ONLY) {
 		printk("UDF-fs: Partition marked readonly; forcing readonly mount\n");
 		sb->s_flags |= MS_RDONLY;
+	}
 
 	if ( udf_find_fileset(sb, &fileset, &rootdir) )
 	{
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 22f820a..1743757 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -184,14 +184,13 @@
 dev_t
 ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
 {
-	__fs32 fs32;
+	__u32 fs32;
 	dev_t dev;
 
 	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
-		fs32 = ufsi->i_u1.i_data[1];
+		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]);
 	else
-		fs32 = ufsi->i_u1.i_data[0];
-	fs32 = fs32_to_cpu(sb, fs32);
+		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]);
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUNx86:
 	case UFS_ST_SUN:
@@ -212,7 +211,7 @@
 void
 ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
 {
-	__fs32 fs32;
+	__u32 fs32;
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUNx86:
@@ -227,11 +226,10 @@
 		fs32 = old_encode_dev(dev);
 		break;
 	}
-	fs32 = cpu_to_fs32(sb, fs32);
 	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
-		ufsi->i_u1.i_data[1] = fs32;
+		ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32);
 	else
-		ufsi->i_u1.i_data[0] = fs32;
+		ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
 }
 
 /**
diff --git a/fs/xattr.c b/fs/xattr.c
index c32f15b..3956351 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -135,6 +135,26 @@
 }
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
+ssize_t
+vfs_listxattr(struct dentry *d, char *list, size_t size)
+{
+	ssize_t error;
+
+	error = security_inode_listxattr(d);
+	if (error)
+		return error;
+	error = -EOPNOTSUPP;
+	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
+		error = d->d_inode->i_op->listxattr(d, list, size);
+	} else {
+		error = security_inode_listsecurity(d->d_inode, list, size);
+		if (size && error > size)
+			error = -ERANGE;
+	}
+	return error;
+}
+EXPORT_SYMBOL_GPL(vfs_listxattr);
+
 int
 vfs_removexattr(struct dentry *dentry, char *name)
 {
@@ -346,17 +366,7 @@
 			return -ENOMEM;
 	}
 
-	error = security_inode_listxattr(d);
-	if (error)
-		goto out;
-	error = -EOPNOTSUPP;
-	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
-		error = d->d_inode->i_op->listxattr(d, klist, size);
-	} else {
-		error = security_inode_listsecurity(d->d_inode, klist, size);
-		if (size && error > size)
-			error = -ERANGE;
-	}
+	error = vfs_listxattr(d, klist, size);
 	if (error > 0) {
 		if (size && copy_to_user(list, klist, error))
 			error = -EFAULT;
@@ -365,7 +375,6 @@
 		   than XATTR_LIST_MAX bytes. Not possible. */
 		error = -E2BIG;
 	}
-out:
 	kfree(klist);
 	return error;
 }
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index d597375..004baf6 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -21,6 +21,7 @@
 #include <linux/highmem.h>
 #include <linux/swap.h>
 #include <linux/blkdev.h>
+#include <linux/backing-dev.h>
 #include "time.h"
 #include "kmem.h"
 
@@ -53,7 +54,7 @@
 			printk(KERN_ERR "XFS: possible memory allocation "
 					"deadlock in %s (mode:0x%x)\n",
 					__FUNCTION__, lflags);
-		blk_congestion_wait(WRITE, HZ/50);
+		congestion_wait(WRITE, HZ/50);
 	} while (1);
 }
 
@@ -131,7 +132,7 @@
 			printk(KERN_ERR "XFS: possible memory allocation "
 					"deadlock in %s (mode:0x%x)\n",
 					__FUNCTION__, lflags);
-		blk_congestion_wait(WRITE, HZ/50);
+		congestion_wait(WRITE, HZ/50);
 	} while (1);
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 9bbadaf..db5f5a3 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -30,6 +30,7 @@
 #include <linux/hash.h>
 #include <linux/kthread.h>
 #include <linux/migrate.h>
+#include <linux/backing-dev.h>
 #include "xfs_linux.h"
 
 STATIC kmem_zone_t *xfs_buf_zone;
@@ -395,7 +396,7 @@
 
 			XFS_STATS_INC(xb_page_retries);
 			xfsbufd_wakeup(0, gfp_mask);
-			blk_congestion_wait(WRITE, HZ/50);
+			congestion_wait(WRITE, HZ/50);
 			goto retry;
 		}
 
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index a4d0e73..063c4b5 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -708,7 +708,7 @@
  * must be preserved.
  */
 #define ACPI_PM1_STATUS_PRESERVED_BITS          0x0800	/* Bit 11 */
-#define ACPI_PM1_CONTROL_PRESERVED_BITS         0x0201	/* Bit 9, Bit 0 (SCI_EN) */
+#define ACPI_PM1_CONTROL_PRESERVED_BITS         0x0200	/* Bit 9 (whatever) */
 
 /*
  * Register IDs
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index c5472be..e72bfdd 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -13,6 +13,7 @@
 #define ACPI_PDC_SMP_C_SWCOORD		(0x0040)
 #define ACPI_PDC_SMP_T_SWCOORD		(0x0080)
 #define ACPI_PDC_C_C1_FFH		(0x0100)
+#define ACPI_PDC_C_C2C3_FFH		(0x0200)
 
 #define ACPI_PDC_EST_CAPABILITY_SMP	(ACPI_PDC_SMP_C1PT | \
 					 ACPI_PDC_C_C1_HALT | \
@@ -23,8 +24,10 @@
 					 ACPI_PDC_SMP_P_SWCOORD | \
 					 ACPI_PDC_P_FFH)
 
-#define ACPI_PDC_C_CAPABILITY_SMP	(ACPI_PDC_SMP_C2C3 | \
-					 ACPI_PDC_SMP_C1PT | \
-					 ACPI_PDC_C_C1_HALT)
+#define ACPI_PDC_C_CAPABILITY_SMP	(ACPI_PDC_SMP_C2C3  | \
+					 ACPI_PDC_SMP_C1PT  | \
+					 ACPI_PDC_C_C1_HALT | \
+					 ACPI_PDC_C_C1_FFH  | \
+					 ACPI_PDC_C_C2C3_FFH)
 
 #endif				/* __PDC_INTEL_H__ */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 9dd5b75..7798d2a 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -29,6 +29,9 @@
 #define DOMAIN_COORD_TYPE_SW_ANY	0xfd
 #define DOMAIN_COORD_TYPE_HW_ALL	0xfe
 
+#define ACPI_CSTATE_SYSTEMIO	(0)
+#define ACPI_CSTATE_FFH		(1)
+
 /* Power Management */
 
 struct acpi_processor_cx;
@@ -58,6 +61,8 @@
 	u8 valid;
 	u8 type;
 	u32 address;
+	u8 space_id;
+	u8 index;
 	u32 latency;
 	u32 latency_ticks;
 	u32 power;
@@ -206,6 +211,9 @@
 #ifdef ARCH_HAS_POWER_INIT
 void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
 					unsigned int cpu);
+int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+		struct acpi_processor_cx *cx, struct acpi_power_register *reg);
+void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cstate);
 #else
 static inline void acpi_processor_power_init_bm_check(struct
 						      acpi_processor_flags
@@ -214,6 +222,16 @@
 	flags->bm_check = 1;
 	return;
 }
+static inline int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+		struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+{
+	return -1;
+}
+static inline void acpi_processor_ffh_cstate_enter(
+		struct acpi_processor_cx *cstate)
+{
+	return;
+}
 #endif
 
 /* in processor_perflib.c */
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index f5ae98c..5d15af2 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -533,19 +533,6 @@
 #define eth_io_copy_and_sum(skb,src,len,unused) \
   memcpy_fromio((skb)->data,src,len)
 
-static inline int
-check_signature(const volatile void __iomem *io_addr,
-		const unsigned char *signature, int length)
-{
-	do {
-		if (readb(io_addr) != *signature)
-			return 0;
-		io_addr++;
-		signature++;
-	} while (--length);
-	return 1;
-}
-
 /*
  * The Alpha Jensen hardware for some rather strange reason puts
  * the RTC clock at 0x170 instead of 0x70. Probably due to some
diff --git a/include/asm-alpha/irq_regs.h b/include/asm-alpha/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-alpha/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h
index aced22f..a86c083 100644
--- a/include/asm-alpha/machvec.h
+++ b/include/asm-alpha/machvec.h
@@ -15,7 +15,6 @@
 
 struct task_struct;
 struct mm_struct;
-struct pt_regs;
 struct vm_area_struct;
 struct linux_hose_info;
 struct pci_dev;
@@ -79,8 +78,8 @@
 
 	void (*update_irq_hw)(unsigned long, unsigned long, int);
 	void (*ack_irq)(unsigned long);
-	void (*device_interrupt)(unsigned long vector, struct pt_regs *regs);
-	void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs);
+	void (*device_interrupt)(unsigned long vector);
+	void (*machine_check)(u64 vector, u64 la);
 
 	void (*smp_callin)(void);
 	void (*init_arch)(void);
diff --git a/include/asm-arm/arch-clps711x/time.h b/include/asm-arm/arch-clps711x/time.h
index 0e4a390..5edaae1 100644
--- a/include/asm-arm/arch-clps711x/time.h
+++ b/include/asm-arm/arch-clps711x/time.h
@@ -26,8 +26,9 @@
  * IRQ handler for the timer
  */
 static irqreturn_t
-p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+p720t_timer_interrupt(int irq, void *dev_id)
 {
+	struct pt_regs *regs = get_irq_regs();
 	do_leds();
 	do_timer(1);
 #ifndef CONFIG_SMP
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
index 599f03e..5b1066d 100644
--- a/include/asm-arm/arch-imx/imx-dma.h
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -45,8 +45,8 @@
 
 struct imx_dma_channel {
 	const char *name;
-	void (*irq_handler) (int, void *, struct pt_regs *);
-	void (*err_handler) (int, void *, struct pt_regs *, int errcode);
+	void (*irq_handler) (int, void *);
+	void (*err_handler) (int, void *, int errcode);
 	void *data;
 	dmamode_t  dma_mode;
 	struct scatterlist *sg;
@@ -77,8 +77,8 @@
 
 int
 imx_dma_setup_handlers(imx_dmach_t dma_ch,
-		void (*irq_handler) (int, void *, struct pt_regs *),
-		void (*err_handler) (int, void *, struct pt_regs *, int), void *data);
+		void (*irq_handler) (int, void *),
+		void (*err_handler) (int, void *, int), void *data);
 
 void imx_dma_enable(imx_dmach_t dma_ch);
 
diff --git a/include/asm-arm/arch-l7200/time.h b/include/asm-arm/arch-l7200/time.h
index c69cb50..ea22f7f 100644
--- a/include/asm-arm/arch-l7200/time.h
+++ b/include/asm-arm/arch-l7200/time.h
@@ -43,8 +43,9 @@
  * Handler for RTC timer interrupt
  */
 static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer_interrupt(int irq, void *dev_id)
 {
+	struct pt_regs *regs = get_irq_regs();
 	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
diff --git a/include/asm-arm/arch-pnx4008/dma.h b/include/asm-arm/arch-pnx4008/dma.h
index 3aee120..418f152 100644
--- a/include/asm-arm/arch-pnx4008/dma.h
+++ b/include/asm-arm/arch-pnx4008/dma.h
@@ -137,7 +137,7 @@
 extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *);
 
 extern int pnx4008_request_channel(char *, int,
-				   void (*)(int, int, void *, struct pt_regs *),
+				   void (*)(int, int, void *),
 				   void *);
 extern void pnx4008_free_channel(int);
 extern int pnx4008_config_dma(int, int, int);
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index a008150..bed042d 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -56,7 +56,7 @@
 
 int pxa_request_dma (char *name,
 			 pxa_dma_prio prio,
-			 void (*irq_handler)(int, void *, struct pt_regs *),
+			 void (*irq_handler)(int, void *),
 			 void *data);
 
 void pxa_free_dma (int dma_ch);
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
index 88c17dd..a38a28c 100644
--- a/include/asm-arm/arch-pxa/mmc.h
+++ b/include/asm-arm/arch-pxa/mmc.h
@@ -10,7 +10,7 @@
 struct pxamci_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
 	unsigned long detect_delay;		/* delay in jiffies before detecting cards after interrupt */
-	int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *);
+	int (*init)(struct device *, irq_handler_t , void *);
 	int (*get_ro)(struct device *);
 	void (*setpower)(struct device *, unsigned int);
 	void (*exit)(struct device *, void *);
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index f5cc65d..68731e0 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1681,6 +1681,7 @@
 #define SSSR_TINT		(1 << 19)	/* Receiver Time-out Interrupt */
 #define SSSR_PINT		(1 << 18)	/* Peripheral Trailing Byte Interrupt */
 
+#define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
 #define SSPSP_DMYSTOP(x)	(x << 23)	/* Dummy Stop */
 #define SSPSP_SFRMWDTH(x)	(x << 16)	/* Serial Frame Width */
 #define SSPSP_SFRMDLY(x)	(x << 9)	/* Serial Frame Delay */
diff --git a/include/asm-arm/arch-sa1100/jornada720.h b/include/asm-arm/arch-sa1100/jornada720.h
index 1b8e8a3..3f37ca0 100644
--- a/include/asm-arm/arch-sa1100/jornada720.h
+++ b/include/asm-arm/arch-sa1100/jornada720.h
@@ -19,6 +19,20 @@
 #define GPIO_JORNADA720_KEYBOARD_IRQ	IRQ_GPIO0
 #define GPIO_JORNADA720_MOUSE_IRQ		IRQ_GPIO9
 
+/* MCU COMMANDS */
+#define MCU_GetBatteryData  0xc0
+#define MCU_GetScanKeyCode  0x90
+#define MCU_GetTouchSamples 0xa0
+#define MCU_GetContrast     0xD0
+#define MCU_SetContrast     0xD1
+#define MCU_GetBrightness   0xD2
+#define MCU_SetBrightness   0xD3
+#define MCU_ContrastOff     0xD8
+#define MCU_BrightnessOff   0xD9
+#define MCU_PWMOFF          0xDF
+#define MCU_TxDummy         0x11
+#define MCU_ErrorCode       0x00
+
 #ifndef __ASSEMBLY__
 
 void jornada720_mcu_init(void);
diff --git a/include/asm-arm/arch-versatile/hardware.h b/include/asm-arm/arch-versatile/hardware.h
index 41c1bee..edc0659 100644
--- a/include/asm-arm/arch-versatile/hardware.h
+++ b/include/asm-arm/arch-versatile/hardware.h
@@ -28,8 +28,8 @@
 /*
  * PCI space virtual addresses
  */
-#define VERSATILE_PCI_VIRT_BASE		0xe8000000
-#define VERSATILE_PCI_CFG_VIRT_BASE	0xe9000000
+#define VERSATILE_PCI_VIRT_BASE		(void __iomem *)0xe8000000ul
+#define VERSATILE_PCI_CFG_VIRT_BASE	(void __iomem *)0xe9000000ul
 
 #if 0
 #define VERSATILE_PCI_VIRT_MEM_BASE0	0xf4000000
diff --git a/include/asm-arm/hardware/sharpsl_pm.h b/include/asm-arm/hardware/sharpsl_pm.h
index a836e76..2d00db2 100644
--- a/include/asm-arm/hardware/sharpsl_pm.h
+++ b/include/asm-arm/hardware/sharpsl_pm.h
@@ -100,7 +100,7 @@
 
 void sharpsl_battery_kick(void);
 void sharpsl_pm_led(int val);
-irqreturn_t sharpsl_ac_isr(int irq, void *dev_id, struct pt_regs *fp);
-irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp);
-irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp);
+irqreturn_t sharpsl_ac_isr(int irq, void *dev_id);
+irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id);
+irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id);
 
diff --git a/include/asm-arm/hw_irq.h b/include/asm-arm/hw_irq.h
index ea85697..98d594a 100644
--- a/include/asm-arm/hw_irq.h
+++ b/include/asm-arm/hw_irq.h
@@ -12,7 +12,7 @@
 	if (!(action->flags & IRQF_TIMER) && system_timer->dyn_tick) {	\
 		write_seqlock(&xtime_lock);				\
 		if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)	\
-			system_timer->dyn_tick->handler(irq, 0, regs);	\
+			system_timer->dyn_tick->handler(irq, NULL);	\
 		write_sequnlock(&xtime_lock);				\
 	}
 #endif
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 8076a85..ae999fd 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -63,7 +63,7 @@
  */
 extern void __iomem * __ioremap_pfn(unsigned long, unsigned long, size_t, unsigned long);
 extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
-extern void __iounmap(void __iomem *addr);
+extern void __iounmap(volatile void __iomem *addr);
 
 /*
  * Bad read/write accesses...
@@ -193,23 +193,6 @@
 #define eth_io_copy_and_sum(s,c,l,b) \
 				eth_copy_and_sum((s),__mem_pci(c),(l),(b))
 
-static inline int
-check_signature(void __iomem *io_addr, const unsigned char *signature,
-		int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 #elif !defined(readb)
 
 #define readb(c)			(__readwrite_bug("readb"),0)
diff --git a/include/asm-arm/irq_regs.h b/include/asm-arm/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-arm/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h
index 131f337..0e017ec 100644
--- a/include/asm-arm/mach/irq.h
+++ b/include/asm-arm/mach/irq.h
@@ -30,10 +30,9 @@
 /*
  * Obsolete inline function for calling irq descriptor handlers.
  */
-static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc,
-				   struct pt_regs *regs)
+static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)
 {
-	desc->handle_irq(irq, desc, regs);
+	desc->handle_irq(irq, desc);
 }
 
 void set_irq_flags(unsigned int irq, unsigned int flags);
@@ -51,10 +50,10 @@
 #define irqdesc		irq_desc
 #define irqchip		irq_chip
 
-#define do_bad_IRQ(irq,desc,regs)			\
+#define do_bad_IRQ(irq,desc)				\
 do {							\
 	spin_lock(&desc->lock);				\
-	handle_bad_irq(irq, desc, regs);		\
+	handle_bad_irq(irq, desc);			\
 	spin_unlock(&desc->lock);			\
 } while(0)
 
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index 1eb93f5..5dc3570 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -57,7 +57,7 @@
 	int		(*enable)(void);	/* Enables dynamic tick */
 	int		(*disable)(void);	/* Disables dynamic tick */
 	void		(*reprogram)(unsigned long); /* Reprograms the timer */
-	int		(*handler)(int, void *, struct pt_regs *);
+	int		(*handler)(int, void *);
 };
 
 void timer_dyn_reprogram(void);
@@ -66,7 +66,7 @@
 #endif
 
 extern struct sys_timer *system_timer;
-extern void timer_tick(struct pt_regs *);
+extern void timer_tick(void);
 
 /*
  * Kernel time keeping support.
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
index 87aba57..09ad0ca 100644
--- a/include/asm-arm/uaccess.h
+++ b/include/asm-arm/uaccess.h
@@ -110,7 +110,7 @@
 #define get_user(x,p)							\
 	({								\
 		const register typeof(*(p)) __user *__p asm("r0") = (p);\
-		register unsigned int __r2 asm("r2");			\
+		register unsigned long __r2 asm("r2");			\
 		register int __e asm("r0");				\
 		switch (sizeof(*(__p))) {				\
 		case 1:							\
diff --git a/include/asm-avr32/irq_regs.h b/include/asm-avr32/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-avr32/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-frv/dma.h b/include/asm-frv/dma.h
index 18d6bb8..683c47d 100644
--- a/include/asm-frv/dma.h
+++ b/include/asm-frv/dma.h
@@ -24,10 +24,7 @@
 /*
  * FRV DMA controller management
  */
-struct pt_regs;
-
-typedef irqreturn_t (*dma_irq_handler_t)(int dmachan, unsigned long cstr, void *data,
-					 struct pt_regs *regs);
+typedef irqreturn_t (*dma_irq_handler_t)(int dmachan, unsigned long cstr, void *data);
 
 extern void frv_dma_init(void);
 
diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h
index e2247c2..0f390f4 100644
--- a/include/asm-frv/highmem.h
+++ b/include/asm-frv/highmem.h
@@ -82,11 +82,11 @@
 	dampr = paddr | xAMPRx_L | xAMPRx_M | xAMPRx_S | xAMPRx_SS_16Kb | xAMPRx_V;		\
 												\
 	if (type != __KM_CACHE)									\
-		asm volatile("movgs %0,dampr"#ampr :: "r"(dampr));				\
+		asm volatile("movgs %0,dampr"#ampr :: "r"(dampr) : "memory");			\
 	else											\
 		asm volatile("movgs %0,iampr"#ampr"\n"						\
 			     "movgs %0,dampr"#ampr"\n"						\
-			     :: "r"(dampr)							\
+			     :: "r"(dampr) : "memory"						\
 			     );									\
 												\
 	asm("movsg damlr"#ampr",%0" : "=r"(damlr));						\
@@ -104,7 +104,7 @@
 	asm volatile("movgs %0,tplr \n"								  \
 		     "movgs %1,tppr \n"								  \
 		     "tlbpr %0,gr0,#2,#1"							  \
-		     : : "r"(damlr), "r"(dampr));						  \
+		     : : "r"(damlr), "r"(dampr) : "memory");					  \
 												  \
 	/*printk("TLB: SECN sl=%d L=%08lx P=%08lx\n", slot, damlr, dampr);*/			  \
 												  \
@@ -115,7 +115,7 @@
 {
 	unsigned long paddr;
 
-	preempt_disable();
+	inc_preempt_count();
 	paddr = page_to_phys(page);
 
 	switch (type) {
@@ -138,16 +138,16 @@
 	}
 }
 
-#define __kunmap_atomic_primary(type, ampr)			\
-do {								\
-	asm volatile("movgs gr0,dampr"#ampr"\n");		\
-	if (type == __KM_CACHE)					\
-		asm volatile("movgs gr0,iampr"#ampr"\n");	\
+#define __kunmap_atomic_primary(type, ampr)				\
+do {									\
+	asm volatile("movgs gr0,dampr"#ampr"\n" ::: "memory");		\
+	if (type == __KM_CACHE)						\
+		asm volatile("movgs gr0,iampr"#ampr"\n" ::: "memory");	\
 } while(0)
 
-#define __kunmap_atomic_secondary(slot, vaddr)			\
-do {								\
-	asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr));	\
+#define __kunmap_atomic_secondary(slot, vaddr)				\
+do {									\
+	asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory");	\
 } while(0)
 
 static inline void kunmap_atomic(void *kvaddr, enum km_type type)
@@ -170,7 +170,8 @@
 	default:
 		BUG();
 	}
-	preempt_enable();
+	dec_preempt_count();
+	preempt_check_resched();
 }
 
 #endif /* !__ASSEMBLY__ */
diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h
index 7765f55..20e44fe0 100644
--- a/include/asm-frv/io.h
+++ b/include/asm-frv/io.h
@@ -385,27 +385,6 @@
  */
 #define xlate_dev_kmem_ptr(p)	p
 
-/*
- * Check BIOS signature
- */
-static inline int check_signature(volatile void __iomem *io_addr,
-				  const unsigned char *signature, int length)
-{
-	int retval = 0;
-
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-
-	retval = 1;
-out:
-	return retval;
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_IO_H */
diff --git a/include/asm-frv/irq_regs.h b/include/asm-frv/irq_regs.h
new file mode 100644
index 0000000..d22e832
--- /dev/null
+++ b/include/asm-frv/irq_regs.h
@@ -0,0 +1,27 @@
+/* FRV per-CPU frame pointer holder
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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.
+ */
+
+#ifndef _ASM_IRQ_REGS_H
+#define _ASM_IRQ_REGS_H
+
+/*
+ * Per-cpu current frame pointer - the location of the last exception frame on
+ * the stack
+ * - on FRV, GR28 is dedicated to keeping a pointer to the current exception
+ *   frame
+ */
+#define ARCH_HAS_OWN_IRQ_REGS
+
+#ifndef __ASSEMBLY__
+#define get_irq_regs() (__frame)
+#endif
+
+#endif /* _ASM_IRQ_REGS_H */
diff --git a/include/asm-frv/ptrace.h b/include/asm-frv/ptrace.h
index 7ff5251..9a2241b 100644
--- a/include/asm-frv/ptrace.h
+++ b/include/asm-frv/ptrace.h
@@ -12,6 +12,7 @@
 #define _ASM_PTRACE_H
 
 #include <asm/registers.h>
+#include <asm/irq_regs.h>
 
 #define in_syscall(regs) (((regs)->tbr & TBR_TT) == TBR_TT_TRAP0)
 
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
index 5ef93a4..815bb01 100644
--- a/include/asm-generic/bitops/sched.h
+++ b/include/asm-generic/bitops/sched.h
@@ -15,7 +15,7 @@
 #if BITS_PER_LONG == 64
 	if (unlikely(b[0]))
 		return __ffs(b[0]);
-	if (unlikely(b[1]))
+	if (likely(b[1]))
 		return __ffs(b[1]) + 64;
 	return __ffs(b[2]) + 128;
 #elif BITS_PER_LONG == 32
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index a525089..c92ae0f 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -37,18 +37,21 @@
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
-#define WARN_ON(condition) unlikely((condition))
+#define WARN_ON(condition) ({						\
+	typeof(condition) __ret_warn_on = (condition);			\
+	unlikely(__ret_warn_on);					\
+})
 #endif
 #endif
 
-#define WARN_ON_ONCE(condition)	({			\
-	static int __warn_once = 1;			\
-	typeof(condition) __ret_warn_once = (condition);\
-							\
-	if (likely(__warn_once))			\
-		if (WARN_ON(__ret_warn_once)) 		\
-			__warn_once = 0;		\
-	unlikely(__ret_warn_once);			\
+#define WARN_ON_ONCE(condition)	({				\
+	static int __warned;					\
+	typeof(condition) __ret_warn_once = (condition);	\
+								\
+	if (unlikely(__ret_warn_once))				\
+		if (WARN_ON(!__warned)) 			\
+			__warned = 1;				\
+	unlikely(__ret_warn_once);				\
 })
 
 #ifdef CONFIG_SMP
diff --git a/include/asm-generic/irq_regs.h b/include/asm-generic/irq_regs.h
new file mode 100644
index 0000000..5ae1d07
--- /dev/null
+++ b/include/asm-generic/irq_regs.h
@@ -0,0 +1,37 @@
+/* Fallback per-CPU frame pointer holder
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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.
+ */
+
+#ifndef _ASM_GENERIC_IRQ_REGS_H
+#define _ASM_GENERIC_IRQ_REGS_H
+
+#include <linux/percpu.h>
+
+/*
+ * Per-cpu current frame pointer - the location of the last exception frame on
+ * the stack
+ */
+DECLARE_PER_CPU(struct pt_regs *, __irq_regs);
+
+static inline struct pt_regs *get_irq_regs(void)
+{
+	return __get_cpu_var(__irq_regs);
+}
+
+static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
+{
+	struct pt_regs *old_regs, **pp_regs = &__get_cpu_var(__irq_regs);
+
+	old_regs = *pp_regs;
+	*pp_regs = new_regs;
+	return old_regs;
+}
+
+#endif /* _ASM_GENERIC_IRQ_REGS_H */
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 6d45ee5..1963762 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -15,7 +15,7 @@
 
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*({				\
-	extern int simple_indentifier_##var(void);	\
+	extern int simple_identifier_##var(void);	\
 	RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]); }))
 #define __get_cpu_var(var) per_cpu(var, smp_processor_id())
 #define __raw_get_cpu_var(var) per_cpu(var, raw_smp_processor_id())
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 69240b5..9d0d11c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -125,6 +125,10 @@
 		*(__param)						\
 		VMLINUX_SYMBOL(__stop___param) = .;			\
 	}								\
+									\
+	/* Unwind data binary search table */				\
+	EH_FRAME_HDR							\
+									\
 	__end_rodata = .;						\
 	. = ALIGN(4096);
 
@@ -157,6 +161,18 @@
 		*(.kprobes.text)					\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
+#ifdef CONFIG_STACK_UNWIND
+		/* Unwind data binary search table */
+#define EH_FRAME_HDR							\
+        	.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) {	\
+			VMLINUX_SYMBOL(__start_unwind_hdr) = .;		\
+			*(.eh_frame_hdr)				\
+			VMLINUX_SYMBOL(__end_unwind_hdr) = .;		\
+		}
+#else
+#define EH_FRAME_HDR
+#endif
+
 		/* DWARF debug sections.
 		Symbols in the DWARF debugging sections are relative to
 		the beginning of the section so we begin them at 0.  */
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 3a42b7d..b952957 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -98,7 +98,7 @@
 extern void init_bsp_APIC (void);
 extern void setup_local_APIC (void);
 extern void init_apic_mappings (void);
-extern void smp_local_timer_interrupt (struct pt_regs * regs);
+extern void smp_local_timer_interrupt (void);
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
@@ -107,7 +107,7 @@
 
 extern void enable_NMI_through_LVT0 (void * dummy);
 
-void smp_send_timer_broadcast_ipi(struct pt_regs *regs);
+void smp_send_timer_broadcast_ipi(void);
 void switch_APIC_timer_to_ipi(void *cpumask);
 void switch_ipi_to_APIC_timer(void *cpumask);
 #define ARCH_APICTIMER_STOPS_ON_C3	1
diff --git a/include/asm-i386/arch_hooks.h b/include/asm-i386/arch_hooks.h
index 238cf42..a8c1fca 100644
--- a/include/asm-i386/arch_hooks.h
+++ b/include/asm-i386/arch_hooks.h
@@ -14,7 +14,7 @@
 extern void init_ISA_irqs(void);
 extern void apic_intr_init(void);
 extern void smp_intr_init(void);
-extern irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t timer_interrupt(int irq, void *dev_id);
 
 /* these are the defined hooks */
 extern void intr_init_hook(void);
diff --git a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h
index 359ead6..44ef2f5 100644
--- a/include/asm-i386/floppy.h
+++ b/include/asm-i386/floppy.h
@@ -51,7 +51,7 @@
 static int virtual_dma_mode;
 static int doing_pdma;
 
-static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t floppy_hardint(int irq, void *dev_id)
 {
 	register unsigned char st;
 
@@ -63,7 +63,7 @@
 	static int dma_wait=0;
 #endif
 	if (!doing_pdma)
-		return floppy_interrupt(irq, dev_id, regs);
+		return floppy_interrupt(irq, dev_id);
 
 #ifdef TRACE_FLPY_INT
 	if(!calls)
@@ -106,7 +106,7 @@
 		dma_wait=0;
 #endif
 		doing_pdma = 0;
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 #ifdef TRACE_FLPY_INT
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index af5d435..e47be9a 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -108,7 +108,7 @@
 extern int hpet_set_periodic_freq(unsigned long freq);
 extern int hpet_rtc_dropped_irq(void);
 extern int hpet_rtc_timer_init(void);
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif /* CONFIG_HPET_EMULATE_RTC */
 #endif /* CONFIG_HPET_TIMER */
 #endif /* _I386_HPET_H */
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 88f02a0..0bedbdf 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -26,9 +26,6 @@
  * Interrupt entry/exit code at both C and assembly level
  */
 
-extern u8 irq_vector[NR_IRQ_VECTORS];
-#define IO_APIC_VECTOR(irq)	(irq_vector[irq])
-
 extern void (*interrupt[NR_IRQS])(void);
 
 #ifdef CONFIG_SMP
@@ -41,7 +38,7 @@
 fastcall void apic_timer_interrupt(void);
 fastcall void error_interrupt(void);
 fastcall void spurious_interrupt(void);
-fastcall void thermal_interrupt(struct pt_regs *);
+fastcall void thermal_interrupt(void);
 #define platform_legacy_irq(irq)	((irq) < 16)
 #endif
 
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index b3724fe..68df0dc3 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -224,33 +224,6 @@
 
 #define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void __force *)(b),(c),(d))
 
-/**
- *	check_signature		-	find BIOS signatures
- *	@io_addr: mmio address to check 
- *	@signature:  signature block
- *	@length: length of signature
- *
- *	Perform a signature comparison with the mmio address io_addr. This
- *	address should have been obtained by ioremap.
- *	Returns 1 on a match.
- */
- 
-static inline int check_signature(volatile void __iomem * io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 /*
  *	Cache management
  *
diff --git a/include/asm-i386/irq_regs.h b/include/asm-i386/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-i386/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h
index 4182c34..7d606e3 100644
--- a/include/asm-i386/mach-default/do_timer.h
+++ b/include/asm-i386/mach-default/do_timer.h
@@ -14,11 +14,11 @@
  *	timer interrupt as a means of triggering reschedules etc.
  **/
 
-static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+static inline void do_timer_interrupt_hook(void)
 {
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode_vm(regs));
+	update_process_times(user_mode_vm(get_irq_regs()));
 #endif
 /*
  * In the SMP case we use the local APIC timer interrupt to do the
@@ -26,10 +26,10 @@
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #else
 	if (!using_apic_timer)
-		smp_local_timer_interrupt(regs);
+		smp_local_timer_interrupt();
 #endif
 }
 
diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h
index 8db618c..21cd696 100644
--- a/include/asm-i386/mach-visws/do_timer.h
+++ b/include/asm-i386/mach-visws/do_timer.h
@@ -4,14 +4,14 @@
 #include <asm/i8259.h>
 #include "cobalt.h"
 
-static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+static inline void do_timer_interrupt_hook(void)
 {
 	/* Clear the interrupt */
 	co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
 
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode_vm(regs));
+	update_process_times(user_mode_vm(irq_regs));
 #endif
 /*
  * In the SMP case we use the local APIC timer interrupt to do the
@@ -19,10 +19,10 @@
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-	profile_tick(CPU_PROFILING, regs);
+	profile_tick(CPU_PROFILING);
 #else
 	if (!using_apic_timer)
-		smp_local_timer_interrupt(regs);
+		smp_local_timer_interrupt();
 #endif
 }
 
diff --git a/include/asm-i386/mach-voyager/do_timer.h b/include/asm-i386/mach-voyager/do_timer.h
index 099fe9f..04e69c1 100644
--- a/include/asm-i386/mach-voyager/do_timer.h
+++ b/include/asm-i386/mach-voyager/do_timer.h
@@ -1,14 +1,14 @@
 /* defines for inline arch setup functions */
 #include <asm/voyager.h>
 
-static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+static inline void do_timer_interrupt_hook(void)
 {
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode_vm(regs));
+	update_process_times(user_mode_vm(irq_regs));
 #endif
 
-	voyager_timer_interrupt(regs);
+	voyager_timer_interrupt();
 }
 
 static inline int do_timer_overflow(int count)
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 2277127..e0ddca9 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -306,6 +306,8 @@
 		: :"a" (eax), "c" (ecx));
 }
 
+extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+
 /* from system description table in BIOS.  Mostly for MCA use, but
 others may find it useful. */
 extern unsigned int machine_id;
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 6aa1206..bd59c15 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -46,8 +46,6 @@
 
 #define cpu_physical_id(cpu)	x86_cpu_to_apicid[cpu]
 
-extern u8 apicid_2_node[];
-
 #ifdef CONFIG_HOTPLUG_CPU
 extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);
@@ -101,6 +99,9 @@
 #endif
 
 #ifndef __ASSEMBLY__
+
+extern u8 apicid_2_node[];
+
 #ifdef CONFIG_X86_LOCAL_APIC
 static __inline int logical_smp_processor_id(void)
 {
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 54d905e..eef5133 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -404,20 +404,6 @@
  * anything, so this is accurate.
  */
 
-/**
- * __copy_to_user: - Copy a block of data into user space, with less checking.
- * @to:   Destination address, in user space.
- * @from: Source address, in kernel space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only.  This function may sleep.
- *
- * Copy data from kernel space to user space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
 static __always_inline unsigned long __must_check
 __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 {
@@ -439,6 +425,20 @@
 	return __copy_to_user_ll(to, from, n);
 }
 
+/**
+ * __copy_to_user: - Copy a block of data into user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
 static __always_inline unsigned long __must_check
 __copy_to_user(void __user *to, const void *from, unsigned long n)
 {
@@ -446,28 +446,6 @@
        return __copy_to_user_inatomic(to, from, n);
 }
 
-/**
- * __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.
- *
- * Context: User context only.  This function may sleep.
- *
- * Copy data from user space to kernel space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- *
- * If some data could not be copied, this function will pad the copied
- * data to the requested size using zero bytes.
- *
- * An alternate version - __copy_from_user_inatomic() - may be called from
- * atomic context and will fail rather than sleep.  In this case the
- * uncopied bytes will *NOT* be padded with zeros.  See fs/filemap.h
- * for explanation of why this is needed.
- */
 static __always_inline unsigned long
 __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
@@ -493,6 +471,29 @@
 	}
 	return __copy_from_user_ll_nozero(to, from, n);
 }
+
+/**
+ * __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.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ *
+ * An alternate version - __copy_from_user_inatomic() - may be called from
+ * atomic context and will fail rather than sleep.  In this case the
+ * uncopied bytes will *NOT* be padded with zeros.  See fs/filemap.h
+ * for explanation of why this is needed.
+ */
 static __always_inline unsigned long
 __copy_from_user(void *to, const void __user *from, unsigned long n)
 {
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 3ca7ab9..beeeaf6 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -324,10 +324,11 @@
 #define __NR_vmsplice		316
 #define __NR_move_pages		317
 #define __NR_getcpu		318
+#define __NR_epoll_pwait	319
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 319
+#define NR_syscalls 320
 #include <linux/err.h>
 
 /*
diff --git a/include/asm-i386/vic.h b/include/asm-i386/vic.h
index 4abfcfb..53100f3 100644
--- a/include/asm-i386/vic.h
+++ b/include/asm-i386/vic.h
@@ -58,4 +58,4 @@
 
 #define VIC_BOOT_INTERRUPT_MASK		0xfe
 
-extern void smp_vic_timer_interrupt(struct pt_regs *regs);
+extern void smp_vic_timer_interrupt(void);
diff --git a/include/asm-i386/voyager.h b/include/asm-i386/voyager.h
index aaf432d..5b27838 100644
--- a/include/asm-i386/voyager.h
+++ b/include/asm-i386/voyager.h
@@ -118,33 +118,33 @@
 } voyager_module_t;
 
 typedef struct voyager_eeprom_hdr {
-	 __u8  module_id[4] __attribute__((packed)); 
-	 __u8  version_id __attribute__((packed));
-	 __u8  config_id __attribute__((packed)); 
-	 __u16 boundry_id __attribute__((packed));	/* boundary scan id */
-	 __u16 ee_size __attribute__((packed));		/* size of EEPROM */
-	 __u8  assembly[11] __attribute__((packed));	/* assembly # */
-	 __u8  assembly_rev __attribute__((packed));	/* assembly rev */
-	 __u8  tracer[4] __attribute__((packed));	/* tracer number */
-	 __u16 assembly_cksum __attribute__((packed));	/* asm checksum */
-	 __u16 power_consump __attribute__((packed));	/* pwr requirements */
-	 __u16 num_asics __attribute__((packed));	/* number of asics */
-	 __u16 bist_time __attribute__((packed));	/* min. bist time */
-	 __u16 err_log_offset __attribute__((packed));	/* error log offset */
-	 __u16 scan_path_offset __attribute__((packed));/* scan path offset */
-	 __u16 cct_offset __attribute__((packed));
-	 __u16 log_length __attribute__((packed));	/* length of err log */
-	 __u16 xsum_end __attribute__((packed));	/* offset to end of
+	 __u8  module_id[4];
+	 __u8  version_id;
+	 __u8  config_id;
+	 __u16 boundry_id;	/* boundary scan id */
+	 __u16 ee_size;		/* size of EEPROM */
+	 __u8  assembly[11];	/* assembly # */
+	 __u8  assembly_rev;	/* assembly rev */
+	 __u8  tracer[4];	/* tracer number */
+	 __u16 assembly_cksum;	/* asm checksum */
+	 __u16 power_consump;	/* pwr requirements */
+	 __u16 num_asics;	/* number of asics */
+	 __u16 bist_time;	/* min. bist time */
+	 __u16 err_log_offset;	/* error log offset */
+	 __u16 scan_path_offset;/* scan path offset */
+	 __u16 cct_offset;
+	 __u16 log_length;	/* length of err log */
+	 __u16 xsum_end;	/* offset to end of
 							   checksum */
-	 __u8  reserved[4] __attribute__((packed));
-	 __u8  sflag __attribute__((packed));		/* starting sentinal */
-	 __u8  part_number[13] __attribute__((packed));	/* prom part number */
-	 __u8  version[10] __attribute__((packed));	/* version number */
-	 __u8  signature[8] __attribute__((packed));
-	 __u16 eeprom_chksum __attribute__((packed));
-	 __u32  data_stamp_offset __attribute__((packed));
-	 __u8  eflag  __attribute__((packed));		 /* ending sentinal */
-} voyager_eprom_hdr_t;
+	 __u8  reserved[4];
+	 __u8  sflag;		/* starting sentinal */
+	 __u8  part_number[13];	/* prom part number */
+	 __u8  version[10];	/* version number */
+	 __u8  signature[8];
+	 __u16 eeprom_chksum;
+	 __u32  data_stamp_offset;
+	 __u8  eflag ;		 /* ending sentinal */
+} __attribute__((packed)) voyager_eprom_hdr_t;
 
 
 
@@ -155,30 +155,30 @@
  * in the module EPROMs.  We really only care about the IDs and
  * offsets */
 typedef struct voyager_sp_table {
-	__u8 asic_id __attribute__((packed));
-	__u8 bypass_flag __attribute__((packed));
-	__u16 asic_data_offset __attribute__((packed));
-	__u16 config_data_offset __attribute__((packed));
-} voyager_sp_table_t;
+	__u8 asic_id;
+	__u8 bypass_flag;
+	__u16 asic_data_offset;
+	__u16 config_data_offset;
+} __attribute__((packed)) voyager_sp_table_t;
 
 typedef struct voyager_jtag_table {
-	__u8 icode[4] __attribute__((packed));
-	__u8 runbist[4] __attribute__((packed));
-	__u8 intest[4] __attribute__((packed));
-	__u8 samp_preld[4] __attribute__((packed));
-	__u8 ireg_len __attribute__((packed));
-} voyager_jtt_t;
+	__u8 icode[4];
+	__u8 runbist[4];
+	__u8 intest[4];
+	__u8 samp_preld[4];
+	__u8 ireg_len;
+} __attribute__((packed)) voyager_jtt_t;
 
 typedef struct voyager_asic_data_table {
-	__u8 jtag_id[4] __attribute__((packed));
-	__u16 length_bsr __attribute__((packed));
-	__u16 length_bist_reg __attribute__((packed));
-	__u32 bist_clk __attribute__((packed));
-	__u16 subaddr_bits __attribute__((packed));
-	__u16 seed_bits __attribute__((packed));
-	__u16 sig_bits __attribute__((packed));
-	__u16 jtag_offset __attribute__((packed));
-} voyager_at_t;
+	__u8 jtag_id[4];
+	__u16 length_bsr;
+	__u16 length_bist_reg;
+	__u32 bist_clk;
+	__u16 subaddr_bits;
+	__u16 seed_bits;
+	__u16 sig_bits;
+	__u16 jtag_offset;
+} __attribute__((packed)) voyager_at_t;
 
 /* Voyager Interrupt Controller (VIC) registers */
 
@@ -328,52 +328,52 @@
 #define NUMBER_OF_POS_REGS	8
 
 typedef struct {
-	__u8	MC_Slot __attribute__((packed));
-	__u8	POS_Values[NUMBER_OF_POS_REGS] __attribute__((packed));
-} MC_SlotInformation_t;
+	__u8	MC_Slot;
+	__u8	POS_Values[NUMBER_OF_POS_REGS];
+} __attribute__((packed)) MC_SlotInformation_t;
 
 struct QuadDescription {
-	__u8  Type __attribute__((packed));	/* for type 0 (DYADIC or MONADIC) all fields
+	__u8  Type;	/* for type 0 (DYADIC or MONADIC) all fields
                          * will be zero except for slot */
-	__u8 StructureVersion __attribute__((packed));
-	__u32 CPI_BaseAddress __attribute__((packed));
-	__u32  LARC_BankSize __attribute__((packed));	
-	__u32 LocalMemoryStateBits __attribute__((packed));
-	__u8  Slot __attribute__((packed)); /* Processor slots 1 - 4 */
-}; 
+	__u8 StructureVersion;
+	__u32 CPI_BaseAddress;
+	__u32  LARC_BankSize;
+	__u32 LocalMemoryStateBits;
+	__u8  Slot; /* Processor slots 1 - 4 */
+} __attribute__((packed));
 
 struct ProcBoardInfo { 
-	__u8 Type __attribute__((packed));    
-	__u8 StructureVersion __attribute__((packed));
-	__u8 NumberOfBoards __attribute__((packed));
-	struct QuadDescription QuadData[MAX_PROCESSOR_BOARDS] __attribute__((packed));
-};
+	__u8 Type;
+	__u8 StructureVersion;
+	__u8 NumberOfBoards;
+	struct QuadDescription QuadData[MAX_PROCESSOR_BOARDS];
+} __attribute__((packed));
 
 struct CacheDescription {
-	__u8 Level __attribute__((packed));
-	__u32 TotalSize __attribute__((packed));
-	__u16 LineSize __attribute__((packed));
-	__u8  Associativity __attribute__((packed));
-	__u8  CacheType __attribute__((packed));
-	__u8  WriteType __attribute__((packed));
-	__u8  Number_CPUs_SharedBy __attribute__((packed));
-	__u8  Shared_CPUs_Hardware_IDs[MAX_SHARED_CPUS] __attribute__((packed));
+	__u8 Level;
+	__u32 TotalSize;
+	__u16 LineSize;
+	__u8  Associativity;
+	__u8  CacheType;
+	__u8  WriteType;
+	__u8  Number_CPUs_SharedBy;
+	__u8  Shared_CPUs_Hardware_IDs[MAX_SHARED_CPUS];
 
-};
+} __attribute__((packed));
 
 struct CPU_Description {
-	__u8 CPU_HardwareId __attribute__((packed));
-	char *FRU_String __attribute__((packed));
-	__u8 NumberOfCacheLevels __attribute__((packed));
-	struct CacheDescription CacheLevelData[MAX_CACHE_LEVELS] __attribute__((packed));
-};
+	__u8 CPU_HardwareId;
+	char *FRU_String;
+	__u8 NumberOfCacheLevels;
+	struct CacheDescription CacheLevelData[MAX_CACHE_LEVELS];
+} __attribute__((packed));
 
 struct CPU_Info {
-	__u8 Type __attribute__((packed));
-	__u8 StructureVersion __attribute__((packed));
-	__u8 NumberOf_CPUs __attribute__((packed));
-	struct CPU_Description CPU_Data[MAX_CPUS] __attribute__((packed));
-};
+	__u8 Type;
+	__u8 StructureVersion;
+	__u8 NumberOf_CPUs;
+	struct CPU_Description CPU_Data[MAX_CPUS];
+} __attribute__((packed));
 
 
 /*
@@ -505,8 +505,8 @@
 extern void voyager_smp_intr_init(void);
 extern __u8 voyager_extended_cmos_read(__u16 cmos_address);
 extern void voyager_smp_dump(void);
-extern void voyager_timer_interrupt(struct pt_regs *regs);
-extern void smp_local_timer_interrupt(struct pt_regs * regs);
+extern void voyager_timer_interrupt(void);
+extern void smp_local_timer_interrupt(void);
 extern void voyager_power_off(void);
 extern void smp_voyager_power_off(void *dummy);
 extern void voyager_restart(void);
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index 43bfff6..855c30a 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -417,6 +417,8 @@
 # define outl_p		outl
 #endif
 
+# ifdef __KERNEL__
+
 extern void __iomem * ioremap(unsigned long offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 
@@ -430,8 +432,6 @@
 #define dmi_iounmap(x,l) iounmap(x)
 #define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
 
-# ifdef __KERNEL__
-
 /*
  * String version of IO memory access ops:
  */
diff --git a/include/asm-ia64/irq_regs.h b/include/asm-ia64/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-ia64/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index 90cba96..7ffbddf 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -26,7 +26,7 @@
 typedef void ia64_mv_cpu_init_t (void);
 typedef void ia64_mv_irq_init_t (void);
 typedef void ia64_mv_send_ipi_t (int, int, int, int);
-typedef void ia64_mv_timer_interrupt_t (int, void *, struct pt_regs *);
+typedef void ia64_mv_timer_interrupt_t (int, void *);
 typedef void ia64_mv_global_tlb_purge_t (struct mm_struct *, unsigned long, unsigned long, unsigned long);
 typedef void ia64_mv_tlb_migrate_finish_t (struct mm_struct *);
 typedef unsigned int ia64_mv_local_vector_to_irq (u8);
@@ -96,7 +96,7 @@
 }
 
 extern void machvec_setup (char **);
-extern void machvec_timer_interrupt (int, void *, struct pt_regs *);
+extern void machvec_timer_interrupt (int, void *);
 extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int);
 extern void machvec_dma_sync_sg (struct device *, struct scatterlist *, int, int);
 extern void machvec_tlb_migrate_finish (struct mm_struct *);
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 2c8fd92..4283ddc 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -764,7 +764,7 @@
  * (generally 0) MUST be passed.  Reserved parameters are not optional
  * parameters.
  */
-extern struct ia64_pal_retval ia64_pal_call_static (u64, u64, u64, u64, u64);
+extern struct ia64_pal_retval ia64_pal_call_static (u64, u64, u64, u64);
 extern struct ia64_pal_retval ia64_pal_call_stacked (u64, u64, u64, u64);
 extern struct ia64_pal_retval ia64_pal_call_phys_static (u64, u64, u64, u64);
 extern struct ia64_pal_retval ia64_pal_call_phys_stacked (u64, u64, u64, u64);
@@ -774,14 +774,7 @@
 #define PAL_CALL(iprv,a0,a1,a2,a3) do {			\
 	struct ia64_fpreg fr[6];			\
 	ia64_save_scratch_fpregs(fr);			\
-	iprv = ia64_pal_call_static(a0, a1, a2, a3, 0);	\
-	ia64_load_scratch_fpregs(fr);			\
-} while (0)
-
-#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3) do {		\
-	struct ia64_fpreg fr[6];			\
-	ia64_save_scratch_fpregs(fr);			\
-	iprv = ia64_pal_call_static(a0, a1, a2, a3, 1);	\
+	iprv = ia64_pal_call_static(a0, a1, a2, a3);	\
 	ia64_load_scratch_fpregs(fr);			\
 } while (0)
 
diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h
index e3b0c3f..da3eade 100644
--- a/include/asm-ia64/sn/pcibr_provider.h
+++ b/include/asm-ia64/sn/pcibr_provider.h
@@ -135,7 +135,7 @@
 extern void             pcireg_force_intr_set(struct pcibus_info *, int);
 extern u64         pcireg_wrb_flush_get(struct pcibus_info *, int);
 extern void             pcireg_int_ate_set(struct pcibus_info *, int, u64);
-extern u64 *	pcireg_int_ate_addr(struct pcibus_info *, int);
+extern u64 __iomem *	pcireg_int_ate_addr(struct pcibus_info *, int);
 extern void 		pcibr_force_interrupt(struct sn_irq_info *sn_irq_info);
 extern void 		pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info);
 extern int 		pcibr_ate_alloc(struct pcibus_info *, int);
diff --git a/include/asm-ia64/sn/tioca_provider.h b/include/asm-ia64/sn/tioca_provider.h
index 65cdd73..9a820ac 100644
--- a/include/asm-ia64/sn/tioca_provider.h
+++ b/include/asm-ia64/sn/tioca_provider.h
@@ -162,11 +162,11 @@
 tioca_tlbflush(struct tioca_kernel *tioca_kernel)
 {
 	volatile u64 tmp;
-	volatile struct tioca *ca_base;
+	volatile struct tioca __iomem *ca_base;
 	struct tioca_common *tioca_common;
 
 	tioca_common = tioca_kernel->ca_common;
-	ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+	ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
 
 	/*
 	 * Explicit flushes not needed if GART is in cached mode
diff --git a/include/asm-ia64/sn/tioce_provider.h b/include/asm-ia64/sn/tioce_provider.h
index 6d62b13..32c32f3 100644
--- a/include/asm-ia64/sn/tioce_provider.h
+++ b/include/asm-ia64/sn/tioce_provider.h
@@ -53,7 +53,7 @@
 	u64		ct_start;	/* coretalk start address */
 	u64		pci_start;	/* bus start address */
 
-	u64		*ate_hw;	/* hw ptr of first ate in map */
+	u64		__iomem *ate_hw;/* hw ptr of first ate in map */
 	u64		*ate_shadow;	/* shadow ptr of firat ate */
 	u16		ate_count;	/* # ate's in the map */
 };
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index 35e1386..1d45e15 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -669,7 +669,7 @@
 extern struct device *xpc_chan;
 extern int xpc_disengage_request_timelimit;
 extern int xpc_disengage_request_timedout;
-extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
+extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
 extern void xpc_dropped_IPI_check(struct xpc_partition *);
 extern void xpc_activate_partition(struct xpc_partition *);
 extern void xpc_activate_kthreads(struct xpc_channel *, int);
diff --git a/include/asm-m32r/io.h b/include/asm-m32r/io.h
index 70ad1c9..d06933b 100644
--- a/include/asm-m32r/io.h
+++ b/include/asm-m32r/io.h
@@ -166,38 +166,6 @@
 
 #define flush_write_buffers() do { } while (0)  /* M32R_FIXME */
 
-/**
- *	check_signature		-	find BIOS signatures
- *	@io_addr: mmio address to check
- *	@signature:  signature block
- *	@length: length of signature
- *
- *	Perform a signature comparison with the ISA mmio address io_addr.
- *	Returns 1 on a match.
- *
- *	This function is deprecated. New drivers should use ioremap and
- *	check_signature.
- */
-
-static inline int check_signature(void __iomem *io_addr,
-        const unsigned char *signature, int length)
-{
-        int retval = 0;
-#if 0
-printk("check_signature\n");
-        do {
-                if (readb(io_addr) != *signature)
-                        goto out;
-                io_addr++;
-                signature++;
-                length--;
-        } while (length);
-        retval = 1;
-out:
-#endif
-        return retval;
-}
-
 static inline void
 memset_io(volatile void __iomem *addr, unsigned char val, int count)
 {
diff --git a/include/asm-m32r/irq_regs.h b/include/asm-m32r/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-m32r/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-m68k/atari_stdma.h b/include/asm-m68k/atari_stdma.h
index b4eadf8..8e389b7 100644
--- a/include/asm-m68k/atari_stdma.h
+++ b/include/asm-m68k/atari_stdma.h
@@ -8,8 +8,7 @@
 
 /***************************** Prototypes *****************************/
 
-void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		void *data);
+void stdma_lock(irq_handler_t handler, void *data);
 void stdma_release( void );
 int stdma_others_waiting( void );
 int stdma_islocked( void );
diff --git a/include/asm-m68k/dma-mapping.h b/include/asm-m68k/dma-mapping.h
index cebbb03..d90d841 100644
--- a/include/asm-m68k/dma-mapping.h
+++ b/include/asm-m68k/dma-mapping.h
@@ -5,6 +5,7 @@
 
 struct scatterlist;
 
+#ifndef CONFIG_MMU_SUN3
 static inline int dma_supported(struct device *dev, u64 mask)
 {
 	return 1;
@@ -26,7 +27,7 @@
 }
 
 extern void *dma_alloc_coherent(struct device *, size_t,
-				dma_addr_t *, int);
+				dma_addr_t *, gfp_t);
 extern void dma_free_coherent(struct device *, size_t,
 			      void *, dma_addr_t);
 
@@ -88,4 +89,8 @@
 	return 0;
 }
 
+#else
+#include <asm-generic/dma-mapping-broken.h>
+#endif
+
 #endif  /* _M68K_DMA_MAPPING_H */
diff --git a/include/asm-m68k/floppy.h b/include/asm-m68k/floppy.h
index 57f4fdd..45dc908 100644
--- a/include/asm-m68k/floppy.h
+++ b/include/asm-m68k/floppy.h
@@ -17,8 +17,7 @@
 
 #include <linux/vmalloc.h>
 
-asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id,
-				      struct pt_regs *regs);
+asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id);
 
 /* constants... */
 
@@ -184,8 +183,7 @@
 
 /* this is the only truly Q40 specific function */
 
-asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id,
-				      struct pt_regs *regs)
+asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id)
 {
 	register unsigned char st;
 
@@ -198,7 +196,7 @@
 	static int dma_wait=0;
 #endif
 	if(!doing_pdma) {
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 
@@ -246,7 +244,7 @@
 		dma_wait=0;
 #endif
 		doing_pdma = 0;
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 #ifdef TRACE_FLPY_INT
diff --git a/include/asm-m68k/ide.h b/include/asm-m68k/ide.h
index 365f76f..f9ffb2c 100644
--- a/include/asm-m68k/ide.h
+++ b/include/asm-m68k/ide.h
@@ -123,7 +123,7 @@
 }
 
 static __inline__ void
-ide_get_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *), void *data)
+ide_get_lock(irq_handler_t handler, void *data)
 {
 	if (MACH_IS_ATARI) {
 		if (falconide_intr_lock == 0) {
diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h
index 3257f98..4901cb1 100644
--- a/include/asm-m68k/irq.h
+++ b/include/asm-m68k/irq.h
@@ -83,7 +83,7 @@
  * interrupt source (if it supports chaining).
  */
 typedef struct irq_node {
-	int		(*handler)(int, void *, struct pt_regs *);
+	int		(*handler)(int, void *);
 	void		*dev_id;
 	struct irq_node *next;
 	unsigned long	flags;
@@ -93,12 +93,12 @@
 /*
  * This structure has only 4 elements for speed reasons
  */
-typedef struct irq_handler {
-	int		(*handler)(int, void *, struct pt_regs *);
+struct irq_handler {
+	int		(*handler)(int, void *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
-} irq_handler_t;
+};
 
 struct irq_controller {
 	const char *name;
@@ -122,6 +122,7 @@
 				      void (*handler)(unsigned int, struct pt_regs *));
 extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
 
-asmlinkage void m68k_handle_int(unsigned int, struct pt_regs *);
+asmlinkage void m68k_handle_int(unsigned int);
+asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
 
 #endif /* _M68K_IRQ_H_ */
diff --git a/include/asm-m68k/irq_regs.h b/include/asm-m68k/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-m68k/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-m68k/mac_iop.h b/include/asm-m68k/mac_iop.h
index b0d2e34..a2c7e6f 100644
--- a/include/asm-m68k/mac_iop.h
+++ b/include/asm-m68k/mac_iop.h
@@ -143,17 +143,17 @@
 	int	status;			/* status of this message            */
 	__u8	message[IOP_MSG_LEN];	/* the message being sent/received   */
 	__u8	reply[IOP_MSG_LEN];	/* the reply to the message          */
-	void	(*handler)(struct iop_msg *, struct pt_regs *);
+	void	(*handler)(struct iop_msg *);
 					/* function to call when reply recvd */
 };
 
 extern int iop_scc_present,iop_ism_present;
 
 extern int iop_listen(uint, uint,
-			void (*handler)(struct iop_msg *, struct pt_regs *),
+			void (*handler)(struct iop_msg *),
 			const char *);
 extern int iop_send_message(uint, uint, void *, uint, __u8 *,
-			    void (*)(struct iop_msg *, struct pt_regs *));
+			    void (*)(struct iop_msg *));
 extern void iop_complete_message(struct iop_msg *);
 extern void iop_upload_code(uint, __u8 *, uint, __u16);
 extern void iop_download_code(uint, __u8 *, uint, __u16);
diff --git a/include/asm-m68k/machdep.h b/include/asm-m68k/machdep.h
index df898f2..26d2b91 100644
--- a/include/asm-m68k/machdep.h
+++ b/include/asm-m68k/machdep.h
@@ -10,7 +10,7 @@
 struct rtc_pll_info;
 struct buffer_head;
 
-extern void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *));
+extern void (*mach_sched_init) (irq_handler_t handler);
 /* machine dependent irq functions */
 extern void (*mach_init_IRQ) (void);
 extern void (*mach_get_model) (char *model);
diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h
index de1ba6e..3db8a81 100644
--- a/include/asm-m68k/signal.h
+++ b/include/asm-m68k/signal.h
@@ -198,6 +198,7 @@
 	return word ^ 31;
 }
 
+struct pt_regs;
 extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-m68k/string.h b/include/asm-m68k/string.h
index 6c59215..2eb7df1 100644
--- a/include/asm-m68k/string.h
+++ b/include/asm-m68k/string.h
@@ -1,138 +1,114 @@
 #ifndef _M68K_STRING_H_
 #define _M68K_STRING_H_
 
-#include <asm/setup.h>
-#include <asm/page.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
 
-#define __HAVE_ARCH_STRCPY
-static inline char * strcpy(char * dest,const char *src)
+static inline size_t __kernel_strlen(const char *s)
 {
-  char *xdest = dest;
+	const char *sc;
 
-  __asm__ __volatile__
-       ("1:\tmoveb %1@+,%0@+\n\t"
-        "jne 1b"
-	: "=a" (dest), "=a" (src)
-        : "0" (dest), "1" (src) : "memory");
-  return xdest;
+	for (sc = s; *sc++; )
+		;
+	return sc - s - 1;
 }
 
-#define __HAVE_ARCH_STRNCPY
-static inline char * strncpy(char *dest, const char *src, size_t n)
+static inline char *__kernel_strcpy(char *dest, const char *src)
 {
-  char *xdest = dest;
+	char *xdest = dest;
 
-  if (n == 0)
-    return xdest;
+	asm volatile ("\n"
+		"1:	move.b	(%1)+,(%0)+\n"
+		"	jne	1b"
+		: "+a" (dest), "+a" (src)
+		: : "memory");
+	return xdest;
+}
 
-  __asm__ __volatile__
-       ("1:\tmoveb %1@+,%0@+\n\t"
-	"jeq 2f\n\t"
-        "subql #1,%2\n\t"
-        "jne 1b\n\t"
-        "2:"
-        : "=a" (dest), "=a" (src), "=d" (n)
-        : "0" (dest), "1" (src), "2" (n)
-        : "memory");
-  return xdest;
+#ifndef __IN_STRING_C
+
+#define __HAVE_ARCH_STRLEN
+#define strlen(s)	(__builtin_constant_p(s) ?	\
+			 __builtin_strlen(s) :		\
+			 __kernel_strlen(s))
+
+#define __HAVE_ARCH_STRNLEN
+static inline size_t strnlen(const char *s, size_t count)
+{
+	const char *sc = s;
+
+	asm volatile ("\n"
+		"1:     subq.l  #1,%1\n"
+		"       jcs     2f\n"
+		"       tst.b   (%0)+\n"
+		"       jne     1b\n"
+		"       subq.l  #1,%0\n"
+		"2:"
+		: "+a" (sc), "+d" (count));
+	return sc - s;
+}
+
+#define __HAVE_ARCH_STRCPY
+#if __GNUC__ >= 4
+#define strcpy(d, s)	(__builtin_constant_p(s) &&	\
+			 __builtin_strlen(s) <= 32 ?	\
+			 __builtin_strcpy(d, s) :	\
+			 __kernel_strcpy(d, s))
+#else
+#define strcpy(d, s)	__kernel_strcpy(d, s)
+#endif
+
+#define __HAVE_ARCH_STRNCPY
+static inline char *strncpy(char *dest, const char *src, size_t n)
+{
+	char *xdest = dest;
+
+	asm volatile ("\n"
+		"	jra	2f\n"
+		"1:	move.b	(%1),(%0)+\n"
+		"	jeq	2f\n"
+		"	addq.l	#1,%1\n"
+		"2:	subq.l	#1,%2\n"
+		"	jcc	1b\n"
+		: "+a" (dest), "+a" (src), "+d" (n)
+		: : "memory");
+	return xdest;
 }
 
 #define __HAVE_ARCH_STRCAT
-static inline char * strcat(char * dest, const char * src)
-{
-	char *tmp = dest;
-
-	while (*dest)
-		dest++;
-	while ((*dest++ = *src++))
-		;
-
-	return tmp;
-}
-
-#define __HAVE_ARCH_STRNCAT
-static inline char * strncat(char *dest, const char *src, size_t count)
-{
-	char *tmp = dest;
-
-	if (count) {
-		while (*dest)
-			dest++;
-		while ((*dest++ = *src++)) {
-			if (--count == 0) {
-				*dest++='\0';
-				break;
-			}
-		}
-	}
-
-	return tmp;
-}
+#define strcat(d, s)	({			\
+	char *__d = (d);			\
+	strcpy(__d + strlen(__d), (s));		\
+})
 
 #define __HAVE_ARCH_STRCHR
-static inline char * strchr(const char * s, int c)
+static inline char *strchr(const char *s, int c)
 {
-  const char ch = c;
+	char sc, ch = c;
 
-  for(; *s != ch; ++s)
-    if (*s == '\0')
-      return( NULL );
-  return( (char *) s);
+	for (; (sc = *s++) != ch; ) {
+		if (!sc)
+			return NULL;
+	}
+	return (char *)s - 1;
 }
 
-/* strstr !! */
-
-#define __HAVE_ARCH_STRLEN
-static inline size_t strlen(const char * s)
-{
-  const char *sc;
-  for (sc = s; *sc != '\0'; ++sc) ;
-  return(sc - s);
-}
-
-/* strnlen !! */
-
 #define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char * cs,const char * ct)
+static inline int strcmp(const char *cs, const char *ct)
 {
-  char __res;
+	char res;
 
-  __asm__
-       ("1:\tmoveb %0@+,%2\n\t" /* get *cs */
-        "cmpb %1@+,%2\n\t"      /* compare a byte */
-        "jne  2f\n\t"           /* not equal, break out */
-        "tstb %2\n\t"           /* at end of cs? */
-        "jne  1b\n\t"           /* no, keep going */
-        "jra  3f\n\t"		/* strings are equal */
-        "2:\tsubb %1@-,%2\n\t"  /* *cs - *ct */
-        "3:"
-        : "=a" (cs), "=a" (ct), "=d" (__res)
-        : "0" (cs), "1" (ct));
-  return __res;
-}
-
-#define __HAVE_ARCH_STRNCMP
-static inline int strncmp(const char * cs,const char * ct,size_t count)
-{
-  char __res;
-
-  if (!count)
-    return 0;
-  __asm__
-       ("1:\tmovb %0@+,%3\n\t"          /* get *cs */
-        "cmpb   %1@+,%3\n\t"            /* compare a byte */
-        "jne    3f\n\t"                 /* not equal, break out */
-        "tstb   %3\n\t"                 /* at end of cs? */
-        "jeq    4f\n\t"                 /* yes, all done */
-        "subql  #1,%2\n\t"              /* no, adjust count */
-        "jne    1b\n\t"                 /* more to do, keep going */
-        "2:\tmoveq #0,%3\n\t"           /* strings are equal */
-        "jra    4f\n\t"
-        "3:\tsubb %1@-,%3\n\t"          /* *cs - *ct */
-        "4:"
-        : "=a" (cs), "=a" (ct), "=d" (count), "=d" (__res)
-        : "0" (cs), "1" (ct), "2" (count));
-  return __res;
+	asm ("\n"
+		"1:	move.b	(%0)+,%2\n"	/* get *cs */
+		"	cmp.b	(%1)+,%2\n"	/* compare a byte */
+		"	jne	2f\n"		/* not equal, break out */
+		"	tst.b	%2\n"		/* at end of cs? */
+		"	jne	1b\n"		/* no, keep going */
+		"	jra	3f\n"		/* strings are equal */
+		"2:	sub.b	-(%1),%2\n"	/* *cs - *ct */
+		"3:"
+		: "+a" (cs), "+a" (ct), "=d" (res));
+	return res;
 }
 
 #define __HAVE_ARCH_MEMSET
@@ -150,4 +126,6 @@
 extern int memcmp(const void *, const void *, __kernel_size_t);
 #define memcmp(d, s, n) __builtin_memcmp(d, s, n)
 
+#endif
+
 #endif /* _M68K_STRING_H_ */
diff --git a/include/asm-m68k/sun3mmu.h b/include/asm-m68k/sun3mmu.h
index 6c8c17d..d8f17a0 100644
--- a/include/asm-m68k/sun3mmu.h
+++ b/include/asm-m68k/sun3mmu.h
@@ -4,6 +4,7 @@
 #ifndef __SUN3_MMU_H__
 #define __SUN3_MMU_H__
 
+#include <linux/types.h>
 #include <asm/movs.h>
 #include <asm/sun3-head.h>
 
@@ -160,7 +161,7 @@
 	return;
 }
 
-extern void *sun3_ioremap(unsigned long phys, unsigned long size,
+extern void __iomem *sun3_ioremap(unsigned long phys, unsigned long size,
 			  unsigned long type);
 
 extern int sun3_map_test(unsigned long addr, char *val);
diff --git a/include/asm-m68k/sun3xflop.h b/include/asm-m68k/sun3xflop.h
index ca8cc41..32c45f8 100644
--- a/include/asm-m68k/sun3xflop.h
+++ b/include/asm-m68k/sun3xflop.h
@@ -111,8 +111,7 @@
 }
 
 
-asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id,
-					 struct pt_regs * regs)
+asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id)
 {
 	register unsigned char st;
 
@@ -125,7 +124,7 @@
 	static int dma_wait=0;
 #endif
 	if(!doing_pdma) {
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 
@@ -189,7 +188,7 @@
 		dma_wait=0;
 #endif
 
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index 131a0cb..243dd13 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -78,13 +78,13 @@
 #define mb()		barrier()
 #define rmb()		barrier()
 #define wmb()		barrier()
-#define read_barrier_depends()	do { } while(0)
-#define set_mb(var, value)    do { xchg(&var, value); } while (0)
+#define read_barrier_depends()	((void)0)
+#define set_mb(var, value)	({ (var) = (value); wmb(); })
 
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while(0)
+#define smp_read_barrier_depends()	((void)0)
 
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index 88b1f47..e4c9f08 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -76,7 +76,7 @@
 		break;							\
 	case 8:								\
  	    {								\
- 		const void *__pu_ptr = (ptr);				\
+ 		const void __user *__pu_ptr = (ptr);			\
 		asm volatile ("\n"					\
 			"1:	moves.l	%2,(%1)+\n"			\
 			"2:	moves.l	%R2,(%1)\n"			\
@@ -125,7 +125,7 @@
 		"	.previous"				\
 		: "+d" (res), "=&" #reg (__gu_val)		\
 		: "m" (*(ptr)), "i" (err));			\
-	(x) = (typeof(*(ptr)))(long)__gu_val;			\
+	(x) = (typeof(*(ptr)))(unsigned long)__gu_val;		\
 })
 
 #define __get_user(x, ptr)						\
@@ -221,16 +221,16 @@
 
 	switch (n) {
 	case 1:
-		__get_user_asm(res, *(u8 *)to, (u8 *)from, u8, b, d, 1);
+		__get_user_asm(res, *(u8 *)to, (u8 __user *)from, u8, b, d, 1);
 		break;
 	case 2:
-		__get_user_asm(res, *(u16 *)to, (u16 *)from, u16, w, d, 2);
+		__get_user_asm(res, *(u16 *)to, (u16 __user *)from, u16, w, d, 2);
 		break;
 	case 3:
 		__constant_copy_from_user_asm(res, to, from, tmp, 3, w, b,);
 		break;
 	case 4:
-		__get_user_asm(res, *(u32 *)to, (u32 *)from, u32, l, r, 4);
+		__get_user_asm(res, *(u32 *)to, (u32 __user *)from, u32, l, r, 4);
 		break;
 	case 5:
 		__constant_copy_from_user_asm(res, to, from, tmp, 5, l, b,);
@@ -302,16 +302,16 @@
 
 	switch (n) {
 	case 1:
-		__put_user_asm(res, *(u8 *)from, (u8 *)to, b, d, 1);
+		__put_user_asm(res, *(u8 *)from, (u8 __user *)to, b, d, 1);
 		break;
 	case 2:
-		__put_user_asm(res, *(u16 *)from, (u16 *)to, w, d, 2);
+		__put_user_asm(res, *(u16 *)from, (u16 __user *)to, w, d, 2);
 		break;
 	case 3:
 		__constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,);
 		break;
 	case 4:
-		__put_user_asm(res, *(u32 *)from, (u32 *)to, l, r, 4);
+		__put_user_asm(res, *(u32 *)from, (u32 __user *)to, l, r, 4);
 		break;
 	case 5:
 		__constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,);
diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
index 3ab716f..ad43480 100644
--- a/include/asm-m68k/unistd.h
+++ b/include/asm-m68k/unistd.h
@@ -284,10 +284,39 @@
 #define __NR_add_key		279
 #define __NR_request_key	280
 #define __NR_keyctl		281
+#define __NR_ioprio_set		282
+#define __NR_ioprio_get		283
+#define __NR_inotify_init	284
+#define __NR_inotify_add_watch	285
+#define __NR_inotify_rm_watch	286
+#define __NR_migrate_pages	287
+#define __NR_openat		288
+#define __NR_mkdirat		289
+#define __NR_mknodat		290
+#define __NR_fchownat		291
+#define __NR_futimesat		292
+#define __NR_fstatat64		293
+#define __NR_unlinkat		294
+#define __NR_renameat		295
+#define __NR_linkat		296
+#define __NR_symlinkat		297
+#define __NR_readlinkat		298
+#define __NR_fchmodat		299
+#define __NR_faccessat		300
+#define __NR_pselect6		301
+#define __NR_ppoll		302
+#define __NR_unshare		303
+#define __NR_set_robust_list	304
+#define __NR_get_robust_list	305
+#define __NR_splice		306
+#define __NR_sync_file_range	307
+#define __NR_tee		308
+#define __NR_vmsplice		309
+#define __NR_move_pages		310
 
 #ifdef __KERNEL__
 
-#define NR_syscalls		282
+#define NR_syscalls		311
 #include <linux/err.h>
 
 /* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
diff --git a/include/asm-m68k/user.h b/include/asm-m68k/user.h
index e8d5a64..d7c0b10 100644
--- a/include/asm-m68k/user.h
+++ b/include/asm-m68k/user.h
@@ -81,7 +81,7 @@
   unsigned long magic;		/* To uniquely identify a core file */
   char u_comm[32];		/* User command that was responsible */
 };
-#define NBPG PAGE_SIZE
+#define NBPG 4096
 #define UPAGES 1
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
index daafb5d..ebaf031 100644
--- a/include/asm-m68knommu/unistd.h
+++ b/include/asm-m68knommu/unistd.h
@@ -281,14 +281,43 @@
 #define __NR_mq_notify		275
 #define __NR_mq_getsetattr	276
 #define __NR_waitid		277
-#define __NR_sys_setaltroot	278
+#define __NR_vserver		278
 #define __NR_add_key		279
 #define __NR_request_key	280
 #define __NR_keyctl		281
- 
+#define __NR_ioprio_set		282
+#define __NR_ioprio_get		283
+#define __NR_inotify_init	284
+#define __NR_inotify_add_watch	285
+#define __NR_inotify_rm_watch	286
+#define __NR_migrate_pages	287
+#define __NR_openat		288
+#define __NR_mkdirat		289
+#define __NR_mknodat		290
+#define __NR_fchownat		291
+#define __NR_futimesat		292
+#define __NR_fstatat64		293
+#define __NR_unlinkat		294
+#define __NR_renameat		295
+#define __NR_linkat		296
+#define __NR_symlinkat		297
+#define __NR_readlinkat		298
+#define __NR_fchmodat		299
+#define __NR_faccessat		300
+#define __NR_pselect6		301
+#define __NR_ppoll		302
+#define __NR_unshare		303
+#define __NR_set_robust_list	304
+#define __NR_get_robust_list	305
+#define __NR_splice		306
+#define __NR_sync_file_range	307
+#define __NR_tee		308
+#define __NR_vmsplice		309
+#define __NR_move_pages		310
+
 #ifdef __KERNEL__
 
-#define NR_syscalls		282
+#define NR_syscalls		311
 #include <linux/err.h>
 
 /* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index 9ab59e2..e3c9925 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -55,24 +55,13 @@
 #define flush_cache_vmap(start, end)		flush_cache_all()
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
-static inline void copy_to_user_page(struct vm_area_struct *vma,
+extern void copy_to_user_page(struct vm_area_struct *vma,
 	struct page *page, unsigned long vaddr, void *dst, const void *src,
-	unsigned long len)
-{
-	if (cpu_has_dc_aliases)
-		flush_cache_page(vma, vaddr, page_to_pfn(page));
-	memcpy(dst, src, len);
-	__flush_icache_page(vma, page);
-}
+	unsigned long len);
 
-static inline void copy_from_user_page(struct vm_area_struct *vma,
+extern void copy_from_user_page(struct vm_area_struct *vma,
 	struct page *page, unsigned long vaddr, void *dst, const void *src,
-	unsigned long len)
-{
-	if (cpu_has_dc_aliases)
-		flush_cache_page(vma, vaddr, page_to_pfn(page));
-	memcpy(dst, src, len);
-}
+	unsigned long len);
 
 extern void (*flush_cache_sigtramp)(unsigned long addr);
 extern void (*flush_icache_all)(void);
diff --git a/include/asm-mips/dec/ecc.h b/include/asm-mips/dec/ecc.h
index 19495a4..707ffdb 100644
--- a/include/asm-mips/dec/ecc.h
+++ b/include/asm-mips/dec/ecc.h
@@ -49,8 +49,7 @@
 
 extern void dec_ecc_be_init(void);
 extern int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup);
-extern irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id,
-					struct pt_regs *regs);
+extern irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id);
 #endif
 
 #endif /* __ASM_MIPS_DEC_ECC_H */
diff --git a/include/asm-mips/dec/kn01.h b/include/asm-mips/dec/kn01.h
index eb522aa..28fa717 100644
--- a/include/asm-mips/dec/kn01.h
+++ b/include/asm-mips/dec/kn01.h
@@ -84,8 +84,7 @@
 
 extern void dec_kn01_be_init(void);
 extern int dec_kn01_be_handler(struct pt_regs *regs, int is_fixup);
-extern irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id,
-					 struct pt_regs *regs);
+extern irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id);
 #endif
 
 #endif /* __ASM_MIPS_DEC_KN01_H */
diff --git a/include/asm-mips/dec/kn02xa.h b/include/asm-mips/dec/kn02xa.h
index a25f3d7..b56b457 100644
--- a/include/asm-mips/dec/kn02xa.h
+++ b/include/asm-mips/dec/kn02xa.h
@@ -78,8 +78,7 @@
 
 extern void dec_kn02xa_be_init(void);
 extern int dec_kn02xa_be_handler(struct pt_regs *regs, int is_fixup);
-extern irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id,
-					   struct pt_regs *regs);
+extern irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id);
 #endif
 
 #endif /* __ASM_MIPS_DEC_KN02XA_H */
diff --git a/include/asm-mips/fixmap.h b/include/asm-mips/fixmap.h
index 6959bdb..02c8a13 100644
--- a/include/asm-mips/fixmap.h
+++ b/include/asm-mips/fixmap.h
@@ -45,8 +45,16 @@
  * fix-mapped?
  */
 enum fixed_addresses {
+#define FIX_N_COLOURS 8
+	FIX_CMAP_BEGIN,
+#ifdef CONFIG_MIPS_MT_SMTC
+	FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS),
+#else
+	FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS,
+#endif
 #ifdef CONFIG_HIGHMEM
-	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+	/* reserved pte's for temporary kernel mappings */
+	FIX_KMAP_BEGIN = FIX_CMAP_END + 1,
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
 	__end_of_fixed_addresses
@@ -70,9 +78,9 @@
  * at the top of mem..
  */
 #if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX)
-#define FIXADDR_TOP	(0xff000000UL - 0x2000)
+#define FIXADDR_TOP	((unsigned long)(long)(int)(0xff000000 - 0x20000))
 #else
-#define FIXADDR_TOP	(0xffffe000UL)
+#define FIXADDR_TOP	((unsigned long)(long)(int)0xfffe0000)
 #endif
 #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 58c561a..efef843 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -134,9 +134,11 @@
 
 static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
 {
-	if (cpu_has_fpu) {
-		if ((tsk == current) && __is_fpu_owner())
+	if (tsk == current) {
+		preempt_disable();
+		if (is_fpu_owner())
 			_save_fp(current);
+		preempt_enable();
 	}
 
 	return tsk->thread.fpu.fpr;
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index df624e1..bc5f3c5 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -172,7 +172,7 @@
 #define page_to_phys(page)	((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
 extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags);
-extern void __iounmap(volatile void __iomem *addr);
+extern void __iounmap(const volatile void __iomem *addr);
 
 static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
@@ -279,7 +279,7 @@
 #define ioremap_uncached_accelerated(offset, size)			\
 	__ioremap_mode((offset), (size), _CACHE_UNCACHED_ACCELERATED)
 
-static inline void iounmap(volatile void __iomem *addr)
+static inline void iounmap(const volatile void __iomem *addr)
 {
 #define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
 
@@ -562,32 +562,6 @@
 #define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len))
 
 /*
- *     check_signature         -       find BIOS signatures
- *     @io_addr: mmio address to check
- *     @signature:  signature block
- *     @length: length of signature
- *
- *     Perform a signature comparison with the mmio address io_addr. This
- *     address should have been obtained by ioremap.
- *     Returns 1 on a match.
- */
-static inline int check_signature(char __iomem *io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
-/*
  * The caches on some architectures aren't dma-coherent and have need to
  * handle this in software.  There are three types of operations that
  * can be applied to dma buffers.
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index d35c617..0ce2a80 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -24,9 +24,7 @@
 #define irq_canonicalize(irq) (irq)	/* Sane hardware, sane code ... */
 #endif
 
-struct pt_regs;
-
-extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
+extern asmlinkage unsigned int do_IRQ(unsigned int irq);
 
 #ifdef CONFIG_MIPS_MT_SMTC
 /*
@@ -55,18 +53,18 @@
  * Ideally there should be away to get this into kernel/irq/handle.c to
  * avoid the overhead of a call for just a tiny function ...
  */
-#define do_IRQ(irq, regs)						\
+#define do_IRQ(irq)							\
 do {									\
 	irq_enter();							\
 	__DO_IRQ_SMTC_HOOK();						\
-	__do_IRQ((irq), (regs));					\
+	__do_IRQ((irq));						\
 	irq_exit();							\
 } while (0)
 
 #endif
 
 extern void arch_init_irq(void);
-extern void spurious_interrupt(struct pt_regs *regs);
+extern void spurious_interrupt(void);
 
 #ifdef CONFIG_MIPS_MT_SMTC
 struct irqaction;
diff --git a/include/asm-mips/irq_regs.h b/include/asm-mips/irq_regs.h
new file mode 100644
index 0000000..33bd2a0
--- /dev/null
+++ b/include/asm-mips/irq_regs.h
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_IRQ_REGS_H
+#define __ASM_IRQ_REGS_H
+
+#define ARCH_HAS_OWN_IRQ_REGS
+
+#include <linux/thread_info.h>
+
+static inline struct pt_regs *get_irq_regs(void)
+{
+	return current_thread_info()->regs;
+}
+
+#endif /* __ASM_IRQ_REGS_H */
diff --git a/include/asm-mips/jmr3927/irq.h b/include/asm-mips/jmr3927/irq.h
index fe551f3..e3e7ed3 100644
--- a/include/asm-mips/jmr3927/irq.h
+++ b/include/asm-mips/jmr3927/irq.h
@@ -45,10 +45,6 @@
 toshibaboards_setup_irq(int irq, struct irqaction * new);
 
 
-#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
-extern void tx_branch_likely_bug_fixup(struct pt_regs *regs);
-#endif
-
 extern int (*toshibaboards_gen_iack)(void);
 
 #endif /* !__ASSEMBLY__ */
diff --git a/include/asm-mips/mach-au1x00/au1000_dma.h b/include/asm-mips/mach-au1x00/au1000_dma.h
index 810f2fa..9f29520 100644
--- a/include/asm-mips/mach-au1x00/au1000_dma.h
+++ b/include/asm-mips/mach-au1x00/au1000_dma.h
@@ -123,8 +123,7 @@
 extern struct dma_chan au1000_dma_table[];
 extern int request_au1000_dma(int dev_id,
 			      const char *dev_str,
-			      irqreturn_t (*irqhandler)(int, void *,
-						 struct pt_regs *),
+			      irq_handler_t irqhandler,
 			      unsigned long irqflags,
 			      void *irq_dev_id);
 extern void free_au1000_dma(unsigned int dmanr);
diff --git a/include/asm-mips/mach-au1x00/au1000_usbdev.h b/include/asm-mips/mach-au1x00/au1000_usbdev.h
deleted file mode 100644
index 05bc74b..0000000
--- a/include/asm-mips/mach-au1x00/au1000_usbdev.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Au1000 USB Device-Side Driver
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *		stevel@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define USBDEV_REV 0x0110 // BCD
-#define USBDEV_EP0_MAX_PACKET_SIZE 64
-
-typedef enum {
-	ATTACHED = 0,
-	POWERED,
-	DEFAULT,
-	ADDRESS,
-	CONFIGURED
-} usbdev_state_t;
-
-typedef enum {
-	CB_NEW_STATE = 0,
-	CB_PKT_COMPLETE
-} usbdev_cb_type_t;
-
-
-typedef struct usbdev_pkt {
-	int                ep_addr;    // ep addr this packet routed to
-	int                size;       // size of payload in bytes
-	unsigned           status;     // packet status
-	struct usbdev_pkt* next;       // function layer can't touch this
-	u8                 payload[0]; // the payload
-} usbdev_pkt_t;
-
-#define PKT_STATUS_ACK  (1<<0)
-#define PKT_STATUS_NAK  (1<<1)
-#define PKT_STATUS_SU   (1<<2)
-
-extern int usbdev_init(struct usb_device_descriptor* dev_desc,
-		       struct usb_config_descriptor* config_desc,
-		       struct usb_interface_descriptor* if_desc,
-		       struct usb_endpoint_descriptor* ep_desc,
-		       struct usb_string_descriptor* str_desc[],
-		       void (*cb)(usbdev_cb_type_t, unsigned long, void *),
-		       void* cb_data);
-
-extern void usbdev_exit(void);
-
-extern int usbdev_alloc_packet  (int ep_addr, int data_size,
-				 usbdev_pkt_t** pkt);
-extern int usbdev_send_packet   (int ep_addr, usbdev_pkt_t* pkt);
-extern int usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt);
-extern int usbdev_get_byte_count(int ep_addr);
diff --git a/include/asm-mips/marvell.h b/include/asm-mips/marvell.h
index 6bb2125..df94955 100644
--- a/include/asm-mips/marvell.h
+++ b/include/asm-mips/marvell.h
@@ -53,6 +53,6 @@
 	unsigned long   config_vreg;
 };
 
-extern void ll_mv64340_irq(struct pt_regs *regs);
+extern void ll_mv64340_irq(void);
 
 #endif	/* __ASM_MIPS_MARVELL_H */
diff --git a/include/asm-mips/msc01_ic.h b/include/asm-mips/msc01_ic.h
index 64f1720..aa7ad9a 100644
--- a/include/asm-mips/msc01_ic.h
+++ b/include/asm-mips/msc01_ic.h
@@ -145,7 +145,7 @@
 #define MSC01_IRQ_EDGE		1
 
 extern void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq);
-extern void ll_msc_irq(struct pt_regs *regs);
+extern void ll_msc_irq(void);
 
 #endif /* __ASM_MIPS_BOARDS_MSC01_IC_H */
 
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 158a4cd..1fae5dc 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -59,69 +59,43 @@
 		.endm
 
 #ifdef CONFIG_SMP
+#ifdef CONFIG_MIPS_MT_SMTC
+#define PTEBASE_SHIFT	19	/* TCBIND */
+#else
+#define PTEBASE_SHIFT	23	/* CONTEXT */
+#endif
 		.macro	get_saved_sp	/* SMP variation */
-#ifdef CONFIG_32BIT
 #ifdef CONFIG_MIPS_MT_SMTC
-		.set	mips32
-		mfc0	k0, CP0_TCBIND;
-		.set	mips0
-		lui	k1, %hi(kernelsp)
-		srl	k0, k0, 19
-		/* No need to shift down and up to clear bits 0-1 */
+		mfc0	k0, CP0_TCBIND
 #else
-		mfc0	k0, CP0_CONTEXT
-		lui	k1, %hi(kernelsp)
-		srl	k0, k0, 23
+		MFC0	k0, CP0_CONTEXT
 #endif
-		addu	k1, k0
-		LONG_L	k1, %lo(kernelsp)(k1)
-#endif
-#ifdef CONFIG_64BIT
-#ifdef CONFIG_MIPS_MT_SMTC
-		.set	mips64
-		mfc0	k0, CP0_TCBIND;
-		.set	mips0
-		lui	k0, %highest(kernelsp)
-		dsrl	k1, 19
-		/* No need to shift down and up to clear bits 0-2 */
+#if defined(CONFIG_BUILD_ELF64) || (defined(CONFIG_64BIT) && __GNUC__ < 4)
+		lui	k1, %highest(kernelsp)
+		daddiu	k1, %higher(kernelsp)
+		dsll	k1, 16
+		daddiu	k1, %hi(kernelsp)
+		dsll	k1, 16
 #else
-		MFC0	k1, CP0_CONTEXT
-		lui	k0, %highest(kernelsp)
-		dsrl	k1, 23
-		daddiu	k0, %higher(kernelsp)
-		dsll	k0, k0, 16
-		daddiu	k0, %hi(kernelsp)
-		dsll	k0, k0, 16
-#endif /* CONFIG_MIPS_MT_SMTC */
-		daddu	k1, k1, k0
+		lui	k1, %hi(kernelsp)
+#endif
+		LONG_SRL	k0, PTEBASE_SHIFT
+		LONG_ADDU	k1, k0
 		LONG_L	k1, %lo(kernelsp)(k1)
-#endif /* CONFIG_64BIT */
 		.endm
 
 		.macro	set_saved_sp stackp temp temp2
-#ifdef CONFIG_32BIT
 #ifdef CONFIG_MIPS_MT_SMTC
 		mfc0	\temp, CP0_TCBIND
-		srl	\temp, 19
-#else
-		mfc0	\temp, CP0_CONTEXT
-		srl	\temp, 23
-#endif
-#endif
-#ifdef CONFIG_64BIT
-#ifdef CONFIG_MIPS_MT_SMTC
-		mfc0	\temp, CP0_TCBIND
-		dsrl	\temp, 19
 #else
 		MFC0	\temp, CP0_CONTEXT
-		dsrl	\temp, 23
 #endif
-#endif
+		LONG_SRL	\temp, PTEBASE_SHIFT
 		LONG_S	\stackp, kernelsp(\temp)
 		.endm
 #else
 		.macro	get_saved_sp	/* Uniprocessor variation */
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_BUILD_ELF64) || (defined(CONFIG_64BIT) && __GNUC__ < 4)
 		lui	k1, %highest(kernelsp)
 		daddiu	k1, %higher(kernelsp)
 		dsll	k1, k1, 16
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
index fa6d04d..b62ec7c 100644
--- a/include/asm-mips/termbits.h
+++ b/include/asm-mips/termbits.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996, 1999, 2001 Ralf Baechle
+ * Copyright (C) 1995, 96, 99, 2001, 06 Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
@@ -13,14 +13,8 @@
 #include <linux/posix_types.h>
 
 typedef unsigned char cc_t;
-#if (_MIPS_SZLONG == 32)
-typedef unsigned long speed_t;
-typedef unsigned long tcflag_t;
-#endif
-#if (_MIPS_SZLONG == 64)
-typedef __u32 speed_t;
-typedef __u32 tcflag_t;
-#endif
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
 
 /*
  * The ABI says nothing about NCC but seems to use NCCS as
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index ae8ada5..e475c45 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -34,6 +34,7 @@
 						   0-0xFFFFFFFF for kernel-thread
 						*/
 	struct restart_block	restart_block;
+	struct pt_regs		*regs;
 };
 
 /*
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index 2d54373..28512ba 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -67,18 +67,18 @@
 /*
  * high-level timer interrupt routines.
  */
-extern irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t timer_interrupt(int irq, void *dev_id);
 
 /*
  * the corresponding low-level timer interrupt routine.
  */
-extern asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs);
+extern asmlinkage void ll_timer_interrupt(int irq);
 
 /*
  * profiling and process accouting is done separately in local_timer_interrupt
  */
-extern void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
+extern void local_timer_interrupt(int irq, void *dev_id);
+extern asmlinkage void ll_local_timer_interrupt(int irq);
 
 /*
  * board specific routines required by time_init().
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 685c914..30240a4 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -331,16 +331,17 @@
 #define __NR_move_pages			(__NR_Linux + 308)
 #define __NR_set_robust_list		(__NR_Linux + 309)
 #define __NR_get_robust_list		(__NR_Linux + 310)
+#define __NR_kexec_load			(__NR_Linux + 311)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		310
+#define __NR_Linux_syscalls		311
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		310
+#define __NR_O32_Linux_syscalls		311
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -618,16 +619,17 @@
 #define __NR_move_pages			(__NR_Linux + 267)
 #define __NR_set_robust_list		(__NR_Linux + 268)
 #define __NR_get_robust_list		(__NR_Linux + 269)
+#define __NR_kexec_load			(__NR_Linux + 270)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		269
+#define __NR_Linux_syscalls		270
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		269
+#define __NR_64_Linux_syscalls		270
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -909,16 +911,17 @@
 #define __NR_move_pages			(__NR_Linux + 271)
 #define __NR_set_robust_list		(__NR_Linux + 272)
 #define __NR_get_robust_list		(__NR_Linux + 273)
+#define __NR_kexec_load			(__NR_Linux + 274)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		273
+#define __NR_Linux_syscalls		274
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		273
+#define __NR_N32_Linux_syscalls		274
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
index dd3eb3d..88b492f 100644
--- a/include/asm-mips/vr41xx/vr41xx.h
+++ b/include/asm-mips/vr41xx/vr41xx.h
@@ -75,7 +75,7 @@
  * Interrupt Control Unit
  */
 extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign);
-extern int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *));
+extern int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int));
 
 #define PIUINT_COMMAND		0x0040
 #define PIUINT_DATA		0x0020
diff --git a/include/asm-parisc/irq_regs.h b/include/asm-parisc/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-parisc/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h
index c9b2e35..423c2b8 100644
--- a/include/asm-parisc/pdc.h
+++ b/include/asm-parisc/pdc.h
@@ -774,8 +774,6 @@
                  unsigned long inptr, unsigned long outputr,
                  unsigned long glob_cfg);
 
-extern void pdc_init(void);
-
 static inline char * os_id_to_string(u16 os_id) {
 	switch(os_id) {
 	case OS_ID_NONE:	return "No OS";
diff --git a/include/asm-powerpc/i8259.h b/include/asm-powerpc/i8259.h
index c80e113..78489fb 100644
--- a/include/asm-powerpc/i8259.h
+++ b/include/asm-powerpc/i8259.h
@@ -6,10 +6,10 @@
 
 #ifdef CONFIG_PPC_MERGE
 extern void i8259_init(struct device_node *node, unsigned long intack_addr);
-extern unsigned int i8259_irq(struct pt_regs *regs);
+extern unsigned int i8259_irq(void);
 #else
 extern void i8259_init(unsigned long intack_addr, int offset);
-extern int i8259_irq(struct pt_regs *regs);
+extern int i8259_irq(void);
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
index 7ab195a..3493429b 100644
--- a/include/asm-powerpc/ibmebus.h
+++ b/include/asm-powerpc/ibmebus.h
@@ -65,7 +65,7 @@
 
 int ibmebus_request_irq(struct ibmebus_dev *dev,
 			u32 ist, 
-			irqreturn_t (*handler)(int, void*, struct pt_regs *),
+			irq_handler_t handler,
 			unsigned long irq_flags, const char * devname,
 			void *dev_id);
 void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index cbbd8c6..3baff8b 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -404,32 +404,6 @@
 
 #include <asm/eeh.h>
 
-/**
- *	check_signature		-	find BIOS signatures
- *	@io_addr: mmio address to check
- *	@signature:  signature block
- *	@length: length of signature
- *
- *	Perform a signature comparison with the mmio address io_addr. This
- *	address should have been obtained by ioremap.
- *	Returns 1 on a match.
- */
-static inline int check_signature(const volatile void __iomem * io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 /* Nothing to do */
 
 #define dma_cache_inv(_start,_size)		do { } while (0)
diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h
index 1ce09a3..9fbb034 100644
--- a/include/asm-powerpc/ipic.h
+++ b/include/asm-powerpc/ipic.h
@@ -79,12 +79,12 @@
 
 #ifdef CONFIG_PPC_MERGE
 extern void ipic_init(struct device_node *node, unsigned int flags);
-extern unsigned int ipic_get_irq(struct pt_regs *regs);
+extern unsigned int ipic_get_irq(void);
 #else
 extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
 		unsigned int irq_offset,
 		unsigned char *senses, unsigned int senses_count);
-extern int ipic_get_irq(struct pt_regs *regs);
+extern int ipic_get_irq(void);
 #endif
 
 #endif /* __ASM_IPIC_H__ */
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 89ed545..f960f53 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -825,7 +825,7 @@
 
 extern void irq_ctx_init(void);
 extern void call_do_softirq(struct thread_info *tp);
-extern int call_handle_irq(int irq, void *p1, void *p2,
+extern int call_handle_irq(int irq, void *p1,
 			   struct thread_info *tp, void *func);
 #else
 #define irq_ctx_init()
diff --git a/include/asm-powerpc/irq_regs.h b/include/asm-powerpc/irq_regs.h
new file mode 100644
index 0000000..ba94b51
--- /dev/null
+++ b/include/asm-powerpc/irq_regs.h
@@ -0,0 +1,2 @@
+#include <asm-generic/irq_regs.h>
+
diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h
index 4065a4d..6ce2ce1 100644
--- a/include/asm-powerpc/iseries/hv_lp_event.h
+++ b/include/asm-powerpc/iseries/hv_lp_event.h
@@ -50,7 +50,7 @@
 	u64	xCorrelationToken;	/* Unique value for source/type x10-x17 */
 };
 
-typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *);
+typedef void (*LpEventHandler)(struct HvLpEvent *);
 
 /* Register a handler for an event type - returns 0 on success */
 extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType,
diff --git a/include/asm-powerpc/iseries/it_lp_queue.h b/include/asm-powerpc/iseries/it_lp_queue.h
index 3f68147..4282788 100644
--- a/include/asm-powerpc/iseries/it_lp_queue.h
+++ b/include/asm-powerpc/iseries/it_lp_queue.h
@@ -72,7 +72,7 @@
 extern struct hvlpevent_queue hvlpevent_queue;
 
 extern int hvlpevent_is_pending(void);
-extern void process_hvlpevents(struct pt_regs *);
+extern void process_hvlpevents(void);
 extern void setup_hvlpevent_queue(void);
 
 #endif /* _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index c17c137..dac90dc 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -97,7 +97,7 @@
 	void		(*show_percpuinfo)(struct seq_file *m, int i);
 
 	void		(*init_IRQ)(void);
-	unsigned int	(*get_irq)(struct pt_regs *);
+	unsigned int	(*get_irq)(void);
 #ifdef CONFIG_KEXEC
 	void		(*kexec_cpu_down)(int crash_shutdown, int secondary);
 #endif
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index a9f9604..ef0a545 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -409,9 +409,9 @@
 void smp_mpic_message_pass(int target, int msg);
 
 /* Fetch interrupt from a given mpic */
-extern unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
+extern unsigned int mpic_get_one_irq(struct mpic *mpic);
 /* This one gets to the primary mpic */
-extern unsigned int mpic_get_irq(struct pt_regs *regs);
+extern unsigned int mpic_get_irq(void);
 
 /* Set the EPIC clock ratio */
 void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 3a9fcc1..8fb9681 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -503,7 +503,7 @@
 
 /*
  * An mtfsf instruction with the L bit set. On CPUs that support this a
- * full 64bits of FPSCR is restored and on other CPUs it is ignored.
+ * full 64bits of FPSCR is restored and on other CPUs the L bit is ignored.
  *
  * Until binutils gets the new form of mtfsf, hardwire the instruction.
  */
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 068f119..20ea7c7 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -34,8 +34,7 @@
 #ifdef CONFIG_SMP
 
 extern void smp_send_debugger_break(int cpu);
-struct pt_regs;
-extern void smp_message_recv(int, struct pt_regs *);
+extern void smp_message_recv(int);
 
 #ifdef CONFIG_HOTPLUG_CPU
 extern void fixup_irqs(cpumask_t map);
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index b42b53c..e73ea00 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -138,6 +138,7 @@
 	void (* ibox_callback)(struct spu *spu);
 	void (* stop_callback)(struct spu *spu);
 	void (* mfc_callback)(struct spu *spu);
+	void (* dma_callback)(struct spu *spu, int type);
 
 	char irq_c0[8];
 	char irq_c1[8];
@@ -147,6 +148,7 @@
 };
 
 struct spu *spu_alloc(void);
+struct spu *spu_alloc_node(int node);
 void spu_free(struct spu *spu);
 int spu_irq_class_0_bottom(struct spu *spu);
 int spu_irq_class_1_bottom(struct spu *spu);
@@ -168,6 +170,22 @@
 	struct module *owner;
 } spufs_calls;
 
+/* return status from spu_run, same as in libspe */
+#define SPE_EVENT_DMA_ALIGNMENT		0x0008	/*A DMA alignment error */
+#define SPE_EVENT_SPE_ERROR		0x0010	/*An illegal instruction error*/
+#define SPE_EVENT_SPE_DATA_SEGMENT	0x0020	/*A DMA segmentation error    */
+#define SPE_EVENT_SPE_DATA_STORAGE	0x0040	/*A DMA storage error */
+#define SPE_EVENT_INVALID_DMA		0x0800	/* Invalid MFC DMA */
+
+/*
+ * Flags for sys_spu_create.
+ */
+#define SPU_CREATE_EVENTS_ENABLED	0x0001
+#define SPU_CREATE_GANG			0x0002
+
+#define SPU_CREATE_FLAG_ALL		0x0003 /* mask of all valid flags */
+
+
 #ifdef CONFIG_SPU_FS_MODULE
 int register_spu_syscalls(struct spufs_calls *calls);
 void unregister_spu_syscalls(struct spufs_calls *calls);
@@ -183,6 +201,24 @@
 
 
 /*
+ * Notifier blocks:
+ *
+ * oprofile can get notified when a context switch is performed
+ * on an spe. The notifer function that gets called is passed
+ * a pointer to the SPU structure as well as the object-id that
+ * identifies the binary running on that SPU now.
+ *
+ * For a context save, the object-id that is passed is zero,
+ * identifying that the kernel will run from that moment on.
+ *
+ * For a context restore, the object-id is the value written
+ * to object-id spufs file from user space and the notifer
+ * function can assume that spu->ctx is valid.
+ */
+int spu_switch_event_register(struct notifier_block * n);
+int spu_switch_event_unregister(struct notifier_block * n);
+
+/*
  * This defines the Local Store, Problem Area and Privlege Area of an SPU.
  */
 
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 3247bea..7b06b4e 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -690,8 +690,7 @@
 #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
 #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
 
-extern void cpm_install_handler(int vec,
-		void (*handler)(void *, struct pt_regs *regs), void *dev_id);
+extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id);
 extern void cpm_free_handler(int vec);
 
 #endif /* __CPM_8XX__ */
diff --git a/include/asm-ppc/floppy.h b/include/asm-ppc/floppy.h
index d3963ca..ae316e6 100644
--- a/include/asm-ppc/floppy.h
+++ b/include/asm-ppc/floppy.h
@@ -38,14 +38,14 @@
 static int doing_vdma;
 static struct fd_dma_ops *fd_ops;
 
-static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t floppy_hardint(int irq, void *dev_id)
 {
 	unsigned char st;
 	int lcount;
 	char *lptr;
 
 	if (!doing_vdma)
-		return floppy_interrupt(irq, dev_id, regs);
+		return floppy_interrupt(irq, dev_id);
 
 
 	st = 1;
@@ -69,7 +69,7 @@
 		virtual_dma_residue += virtual_dma_count;
 		virtual_dma_count=0;
 		doing_vdma = 0;
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 	return IRQ_HANDLED;
diff --git a/include/asm-ppc/gt64260.h b/include/asm-ppc/gt64260.h
index cd0ef64..9e63b3c 100644
--- a/include/asm-ppc/gt64260.h
+++ b/include/asm-ppc/gt64260.h
@@ -315,7 +315,7 @@
 int gt64260_pci_exclude_device(u8 bus, u8 devfn);
 
 void gt64260_init_irq(void);
-int gt64260_get_irq(struct pt_regs *regs);
+int gt64260_get_irq(void);
 
 void gt64260_mpsc_progress(char *s, unsigned short hex);
 
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index 3d9a9e6..a4c411b 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -439,22 +439,6 @@
 #define iobarrier_r()  eieio()
 #define iobarrier_w()  eieio()
 
-static inline int check_signature(volatile void __iomem * io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 /*
  * Here comes the ppc implementation of the IOMAP 
  * interfaces.
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index da77467..293a444 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -43,7 +43,7 @@
 	/* Optional, may be NULL. */
 	unsigned int	(*irq_canonicalize)(unsigned int irq);
 	void		(*init_IRQ)(void);
-	int		(*get_irq)(struct pt_regs *);
+	int		(*get_irq)(void);
 	
 	/* A general init function, called by ppc_init in init/main.c.
 	   May be NULL. DEPRECATED ! */
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 7e98428..64c8874 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -415,7 +415,7 @@
 #ifndef __ASSEMBLY__
 
 extern void mpc52xx_init_irq(void);
-extern int mpc52xx_get_irq(struct pt_regs *regs);
+extern int mpc52xx_get_irq(void);
 
 extern unsigned long mpc52xx_find_end_of_memory(void);
 extern void mpc52xx_set_bat(void);
diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h
index 663edbe..db3776f 100644
--- a/include/asm-ppc/mv64x60.h
+++ b/include/asm-ppc/mv64x60.h
@@ -336,9 +336,9 @@
 
 
 void gt64260_init_irq(void);
-int gt64260_get_irq(struct pt_regs *regs);
+int gt64260_get_irq(void);
 void mv64360_init_irq(void);
-int mv64360_get_irq(struct pt_regs *regs);
+int mv64360_get_irq(void);
 
 u32 mv64x60_mask(u32 val, u32 num_bits);
 u32 mv64x60_shift_left(u32 val, u32 num_bits);
diff --git a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h
index a4fe962..778d572 100644
--- a/include/asm-ppc/open_pic.h
+++ b/include/asm-ppc/open_pic.h
@@ -48,12 +48,12 @@
 extern void openpic_init_nmi_irq(u_int irq);
 extern void openpic_set_irq_priority(u_int irq, u_int pri);
 extern void openpic_hookup_cascade(u_int irq, char *name,
-				   int (*cascade_fn)(struct pt_regs *));
+				   int (*cascade_fn)(void));
 extern u_int openpic_irq(void);
 extern void openpic_eoi(void);
 extern void openpic_request_IPIs(void);
 extern void do_openpic_setup_cpu(void);
-extern int openpic_get_irq(struct pt_regs *regs);
+extern int openpic_get_irq(void);
 extern void openpic_reset_processor_phys(u_int cpumask);
 extern void openpic_setup_ISU(int isu_num, unsigned long addr);
 extern void openpic_cause_IPI(u_int ipi, cpumask_t cpumask);
@@ -93,6 +93,6 @@
 extern void openpic2_init_nmi_irq(u_int irq);
 extern u_int openpic2_irq(void);
 extern void openpic2_eoi(void);
-extern int openpic2_get_irq(struct pt_regs *regs);
+extern int openpic2_get_irq(void);
 extern void openpic2_setup_ISU(int isu_num, unsigned long addr);
 #endif /* _PPC_KERNEL_OPEN_PIC_H */
diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
index 0b7fa89..e75791e 100644
--- a/include/asm-ppc/smp.h
+++ b/include/asm-ppc/smp.h
@@ -39,7 +39,7 @@
 extern void smp_send_tlb_invalidate(int);
 extern void smp_send_xmon_break(int cpu);
 struct pt_regs;
-extern void smp_message_recv(int, struct pt_regs *);
+extern void smp_message_recv(int);
 
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
index da063cd..81287d8 100644
--- a/include/asm-s390/cio.h
+++ b/include/asm-s390/cio.h
@@ -275,6 +275,12 @@
 	u16 devno;
 };
 
+static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1,
+				      struct ccw_dev_id *dev_id2)
+{
+	return !memcmp(dev_id1, dev_id2, sizeof(struct ccw_dev_id));
+}
+
 extern int diag210(struct diag210 *addr);
 
 extern void wait_cons_dev(void);
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index e84b7ef..c2f6a87 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(struct pt_regs *);
+extern void account_ticks(void);
 
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-s390/irq_regs.h b/include/asm-s390/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-s390/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h
index 495ad99..9ea7f10 100644
--- a/include/asm-s390/percpu.h
+++ b/include/asm-s390/percpu.h
@@ -16,7 +16,7 @@
 #if defined(__s390x__) && defined(MODULE)
 
 #define __reloc_hide(var,offset) (*({			\
-	extern int simple_indentifier_##var(void);	\
+	extern int simple_identifier_##var(void);	\
 	unsigned long *__ptr;				\
 	asm ( "larl %0,per_cpu__"#var"@GOTENT"		\
 	    : "=a" (__ptr) : "X" (per_cpu__##var) );	\
@@ -25,7 +25,7 @@
 #else
 
 #define __reloc_hide(var, offset) (*({				\
-	extern int simple_indentifier_##var(void);		\
+	extern int simple_identifier_##var(void);		\
 	unsigned long __ptr;					\
 	asm ( "" : "=a" (__ptr) : "0" (&per_cpu__##var) );	\
 	(typeof(&per_cpu__##var)) (__ptr + (offset)); }))
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 519f0a5..36bb6da 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -200,18 +200,45 @@
  */
 
 /* Hardware bits in the page table entry */
-#define _PAGE_RO        0x200          /* HW read-only                     */
-#define _PAGE_INVALID   0x400          /* HW invalid                       */
+#define _PAGE_RO	0x200		/* HW read-only bit  */
+#define _PAGE_INVALID	0x400		/* HW invalid bit    */
+#define _PAGE_SWT	0x001		/* SW pte type bit t */
+#define _PAGE_SWX	0x002		/* SW pte type bit x */
 
-/* Mask and six different types of pages. */
-#define _PAGE_TYPE_MASK		0x601
+/* Six different types of pages. */
 #define _PAGE_TYPE_EMPTY	0x400
 #define _PAGE_TYPE_NONE		0x401
-#define _PAGE_TYPE_SWAP		0x600
-#define _PAGE_TYPE_FILE		0x601
+#define _PAGE_TYPE_SWAP		0x403
+#define _PAGE_TYPE_FILE		0x601	/* bit 0x002 is used for offset !! */
 #define _PAGE_TYPE_RO		0x200
 #define _PAGE_TYPE_RW		0x000
 
+/*
+ * PTE type bits are rather complicated. handle_pte_fault uses pte_present,
+ * pte_none and pte_file to find out the pte type WITHOUT holding the page
+ * table lock. ptep_clear_flush on the other hand uses ptep_clear_flush to
+ * invalidate a given pte. ipte sets the hw invalid bit and clears all tlbs
+ * for the page. The page table entry is set to _PAGE_TYPE_EMPTY afterwards.
+ * This change is done while holding the lock, but the intermediate step
+ * of a previously valid pte with the hw invalid bit set can be observed by
+ * handle_pte_fault. That makes it necessary that all valid pte types with
+ * the hw invalid bit set must be distinguishable from the four pte types
+ * empty, none, swap and file.
+ *
+ *			irxt  ipte  irxt
+ * _PAGE_TYPE_EMPTY	1000   ->   1000
+ * _PAGE_TYPE_NONE	1001   ->   1001
+ * _PAGE_TYPE_SWAP	1011   ->   1011
+ * _PAGE_TYPE_FILE	11?1   ->   11?1
+ * _PAGE_TYPE_RO	0100   ->   1100
+ * _PAGE_TYPE_RW	0000   ->   1000
+ *
+ * pte_none is true for bits combinations 1000, 1100
+ * 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.
+ */
+
 #ifndef __s390x__
 
 /* Bits in the segment table entry */
@@ -365,18 +392,21 @@
 
 static inline int pte_none(pte_t pte)
 {
-	return (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_EMPTY;
+	return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
 }
 
 static inline int pte_present(pte_t pte)
 {
-	return !(pte_val(pte) & _PAGE_INVALID) ||
-		(pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_NONE;
+	unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT | _PAGE_SWX;
+	return (pte_val(pte) & mask) == _PAGE_TYPE_NONE ||
+		(!(pte_val(pte) & _PAGE_INVALID) &&
+		 !(pte_val(pte) & _PAGE_SWT));
 }
 
 static inline int pte_file(pte_t pte)
 {
-	return (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_FILE;
+	unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT;
+	return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
 }
 
 #define pte_same(a,b)	(pte_val(a) == pte_val(b))
diff --git a/include/asm-s390/s390_ext.h b/include/asm-s390/s390_ext.h
index e9a2862..df9b101 100644
--- a/include/asm-s390/s390_ext.h
+++ b/include/asm-s390/s390_ext.h
@@ -10,7 +10,7 @@
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
-typedef void (*ext_int_handler_t)(struct pt_regs *regs, __u16 code);
+typedef void (*ext_int_handler_t)(__u16 code);
 
 /*
  * Warning: if you change ext_int_info_t you have to change the
diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h
index fcd6c25..30e5cbe 100644
--- a/include/asm-s390/timer.h
+++ b/include/asm-s390/timer.h
@@ -26,7 +26,7 @@
 	spinlock_t lock;
 	unsigned long magic;
 
-	void (*function)(unsigned long, struct pt_regs*);
+	void (*function)(unsigned long);
 	unsigned long data;
 };
 
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index a19238c..71d3c21 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -249,8 +249,9 @@
 #define __NR_vmsplice		309
 /* Number 310 is reserved for new sys_move_pages */
 #define __NR_getcpu		311
+#define __NR_epoll_pwait	312
 
-#define NR_syscalls 312
+#define NR_syscalls 313
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff --git a/include/asm-sh/cpu-sh4/ubc.h b/include/asm-sh/cpu-sh4/ubc.h
index 3d09431..c86e170 100644
--- a/include/asm-sh/cpu-sh4/ubc.h
+++ b/include/asm-sh/cpu-sh4/ubc.h
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1999 Niibe Yutaka
  * Copyright (C) 2003 Paul Mundt
+ * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
  *
  * 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
@@ -11,6 +12,41 @@
 #ifndef __ASM_CPU_SH4_UBC_H
 #define __ASM_CPU_SH4_UBC_H
 
+#if defined(CONFIG_CPU_SH4A)
+#define UBC_CBR0		0xff200000
+#define UBC_CRR0		0xff200004
+#define UBC_CAR0		0xff200008
+#define UBC_CAMR0		0xff20000c
+#define UBC_CBR1		0xff200020
+#define UBC_CRR1		0xff200024
+#define UBC_CAR1		0xff200028
+#define UBC_CAMR1		0xff20002c
+#define UBC_CDR1		0xff200030
+#define UBC_CDMR1		0xff200034
+#define UBC_CETR1		0xff200038
+#define UBC_CCMFR		0xff200600
+#define UBC_CBCR		0xff200620
+
+/* CBR	*/
+#define UBC_CBR_AIE		(0x01<<30)
+#define UBC_CBR_ID_INST		(0x01<<4)
+#define UBC_CBR_RW_READ		(0x01<<1)
+#define UBC_CBR_CE		(0x01)
+
+#define	UBC_CBR_AIV_MASK	(0x00FF0000)
+#define	UBC_CBR_AIV_SHIFT	(16)
+#define UBC_CBR_AIV_SET(asid)	(((asid)<<UBC_CBR_AIV_SHIFT) & UBC_CBR_AIV_MASK)
+
+#define UBC_CBR_INIT		0x20000000
+
+/* CRR	*/
+#define UBC_CRR_RES		(0x01<<13)
+#define UBC_CRR_PCB		(0x01<<1)
+#define UBC_CRR_BIE		(0x01)
+
+#define UBC_CRR_INIT		0x00002000
+
+#else	/* CONFIG_CPU_SH4 */
 #define UBC_BARA		0xff200000
 #define UBC_BAMRA		0xff200004
 #define UBC_BBRA		0xff200008
@@ -22,6 +58,7 @@
 #define UBC_BDRB		0xff200018
 #define UBC_BDMRB		0xff20001c
 #define UBC_BRCR		0xff200020
+#endif	/* CONFIG_CPU_SH4 */
 
 #endif /* __ASM_CPU_SH4_UBC_H */
 
diff --git a/include/asm-sh/edosk7705/io.h b/include/asm-sh/edosk7705.h
similarity index 100%
rename from include/asm-sh/edosk7705/io.h
rename to include/asm-sh/edosk7705.h
diff --git a/include/asm-sh/hp6xx/hp6xx.h b/include/asm-sh/hp6xx.h
similarity index 100%
rename from include/asm-sh/hp6xx/hp6xx.h
rename to include/asm-sh/hp6xx.h
diff --git a/include/asm-sh/hp6xx/ide.h b/include/asm-sh/hp6xx/ide.h
deleted file mode 100644
index 570395a..0000000
--- a/include/asm-sh/hp6xx/ide.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_SH_HP6XX_IDE_H
-#define __ASM_SH_HP6XX_IDE_H
-
-#define IRQ_CFCARD	93
-#define IRQ_PCMCIA	94
-
-#endif /* __ASM_SH_HP6XX_IDE_H */
-
diff --git a/include/asm-sh/hp6xx/io.h b/include/asm-sh/hp6xx/io.h
deleted file mode 100644
index 2044476..0000000
--- a/include/asm-sh/hp6xx/io.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SH_HP6XX_IO_H
-#define __ASM_SH_HP6XX_IO_H
-
-/*
- * Nothing special here.. just use the generic cchip io routines.
- */
-#include <asm/hd64461.h>
-
-#endif /* __ASM_SH_HP6XX_IO_H */
-
diff --git a/include/asm-sh/hs7751rvoip/hs7751rvoip.h b/include/asm-sh/hs7751rvoip.h
similarity index 100%
rename from include/asm-sh/hs7751rvoip/hs7751rvoip.h
rename to include/asm-sh/hs7751rvoip.h
diff --git a/include/asm-sh/hs7751rvoip/ide.h b/include/asm-sh/hs7751rvoip/ide.h
deleted file mode 100644
index 65ad1d0..0000000
--- a/include/asm-sh/hs7751rvoip/ide.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_SH_HS7751RVOIP_IDE_H
-#define __ASM_SH_HS7751RVOIP_IDE_H
-
-/* Nothing to see here.. */
-#include <asm/hs7751rvoip/hs7751rvoip.h>
-
-#endif /* __ASM_SH_HS7751RVOIP_IDE_H */
-
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index fed2661..80ee1cd 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -1,4 +1,8 @@
 #ifndef __ASM_SH_HW_IRQ_H
 #define __ASM_SH_HW_IRQ_H
 
+#include <asm/atomic.h>
+
+extern atomic_t irq_err_count;
+
 #endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h
index ed12d38..a0e55b0 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -304,22 +304,6 @@
 #define iounmap(addr)					\
 	__iounmap((addr))
 
-static inline int check_signature(char __iomem *io_addr,
-			const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 /*
  * The caches on some architectures aren't dma-coherent and have need to
  * handle this in software.  There are three types of operations that
diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h
index 895c578..19912ae 100644
--- a/include/asm-sh/irq-sh7780.h
+++ b/include/asm-sh/irq-sh7780.h
@@ -6,16 +6,6 @@
  *
  * Copyright (C) 2004 Takashi SHUDO <shudo@hitachi-ul.co.jp>
  */
-
-#ifdef CONFIG_IDE
-# ifndef IRQ_CFCARD
-#  define IRQ_CFCARD	14
-# endif
-# ifndef IRQ_PCMCIA
-#  define IRQ_PCMCIA	15
-# endif
-#endif
-
 #define INTC_BASE	0xffd00000
 #define INTC_ICR0	(INTC_BASE+0x0)
 #define INTC_ICR1	(INTC_BASE+0x1c)
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 0e5f365..7596ab8 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -14,16 +14,6 @@
 #include <asm/machvec.h>
 #include <asm/ptrace.h>		/* for pt_regs */
 
-#if defined(CONFIG_SH_HP6XX) || \
-    defined(CONFIG_SH_RTS7751R2D) || \
-    defined(CONFIG_SH_HS7751RVOIP) || \
-    defined(CONFIG_SH_HS7751RVOIP) || \
-    defined(CONFIG_SH_SH03) || \
-    defined(CONFIG_SH_R7780RP) || \
-    defined(CONFIG_SH_LANDISK)
-#include <asm/mach/ide.h>
-#endif
-
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
 
 #define INTC_DMAC0_MSK	0
@@ -38,15 +28,6 @@
 #define INTC_IPRD	0xffd00010UL
 #endif
 
-#ifdef CONFIG_IDE
-# ifndef IRQ_CFCARD
-#  define IRQ_CFCARD	14
-# endif
-# ifndef IRQ_PCMCIA
-#  define IRQ_PCMCIA	15
-# endif
-#endif
-
 #define TIMER_IRQ	16
 #define TIMER_IPR_ADDR	INTC_IPRA
 #define TIMER_IPR_POS	 3
@@ -697,13 +678,15 @@
 
 #define INTC2_INTPRI_OFFSET	0x00
 
-void make_intc2_irq(unsigned int irq,
-		    unsigned int ipr_offset, unsigned int ipr_shift,
-		    unsigned int msk_offset, unsigned int msk_shift,
-		    unsigned int priority);
-void init_IRQ_intc2(void);
-void intc2_add_clear_irq(int irq, int (*fn)(int));
+struct intc2_data {
+	unsigned short irq;
+	unsigned char ipr_offset, ipr_shift;
+	unsigned char msk_offset, msk_shift;
+	unsigned char priority;
+};
 
+void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs);
+void init_IRQ_intc2(void);
 #endif
 
 extern int shmse_irq_demux(int irq);
diff --git a/include/asm-sh/irq_regs.h b/include/asm-sh/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-sh/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-sh/landisk/ide.h b/include/asm-sh/landisk/ide.h
deleted file mode 100644
index 6490e28..0000000
--- a/include/asm-sh/landisk/ide.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * modifed by kogiidena
- * 2005.03.03
- */
-
-#ifndef __ASM_SH_LANDISK_IDE_H
-#define __ASM_SH_LANDISK_IDE_H
-
-/* Nothing to see here.. */
-#include <asm/landisk/iodata_landisk.h>
-#define IRQ_CFCARD	IRQ_FATA	/* CF Card IRQ */
-#define IRQ_PCMCIA	IRQ_ATA		/* PCMCIA IRQ */
-
-#endif /* __ASM_SH_LANDISK_IDE_H  */
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index 4747738..45bb74e 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -255,6 +255,8 @@
  */
 #define thread_saved_pc(tsk)	(tsk->thread.pc)
 
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+		struct pt_regs *regs);
 extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.pc)
diff --git a/include/asm-sh/r7780rp/r7780rp.h b/include/asm-sh/r7780rp.h
similarity index 96%
rename from include/asm-sh/r7780rp/r7780rp.h
rename to include/asm-sh/r7780rp.h
index f95d9db..c18f648 100644
--- a/include/asm-sh/r7780rp/r7780rp.h
+++ b/include/asm-sh/r7780rp.h
@@ -72,8 +72,6 @@
 
 #define PA_AX88796L     0xa4100400      /* AX88796L Area */
 #define PA_SC1602BSLB   0xa6000000      /* SC1602BSLB Area */
-#define PA_AREA5_IO     0xb4000000      /* Area 5 IO Memory */
-#define PA_AREA6_IO     0xb8000000      /* Area 6 IO Memory */
 #define PA_IDE_OFFSET   0x1f0           /* CF IDE Offset */
 #define AX88796L_IO_BASE        0x1000  /* AX88796L IO Base Address */
 
@@ -83,7 +81,6 @@
 #define IRQ_PCISLOT2    66              /* PCI Slot #2 IRQ */
 #define IRQ_PCISLOT3    67              /* PCI Slot #3 IRQ */
 #define IRQ_PCISLOT4    68              /* PCI Slot #4 IRQ */
-#define IRQ_CFCARD      1               /* CF Card IRQ */
 // #define IRQ_CFINST   0               /* CF Card Insert IRQ */
 #define IRQ_TP          2               /* Touch Panel IRQ */
 #define IRQ_SCI1        3               /* SCI1 IRQ */
@@ -146,8 +143,6 @@
 
 #define PA_AX88796L	0xa5800400	/* AX88796L Area */
 #define PA_SC1602BSLB	0xa6000000	/* SC1602BSLB Area */
-#define PA_AREA5_IO	0xb4000000	/* Area 5 IO Memory */
-#define PA_AREA6_IO	0xb8000000	/* Area 6 IO Memory */
 #define PA_IDE_OFFSET	0x1f0		/* CF IDE Offset */
 #define AX88796L_IO_BASE	0x1000	/* AX88796L IO Base Address */
 
@@ -157,7 +152,6 @@
 #define IRQ_PCISLOT2	1		/* PCI Slot #2 IRQ */
 #define IRQ_PCISLOT3	2		/* PCI Slot #3 IRQ */
 #define IRQ_PCISLOT4	3		/* PCI Slot #4 IRQ */
-#define IRQ_CFCARD	4		/* CF Card IRQ */
 #define IRQ_CFINST	5		/* CF Card Insert IRQ */
 #define IRQ_M66596	6		/* M66596 IRQ */
 #define IRQ_SDCARD	7		/* SD Card IRQ */
diff --git a/include/asm-sh/r7780rp/ide.h b/include/asm-sh/r7780rp/ide.h
deleted file mode 100644
index a1ed78e..0000000
--- a/include/asm-sh/r7780rp/ide.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_SH_R7780RP_IDE_H
-#define __ASM_SH_R7780RP_IDE_H
-
-/* Nothing to see here.. */
-#include <asm/mach/r7780rp.h>
-
-#endif /* __ASM_SH_R7780RP_IDE_H */
-
diff --git a/include/asm-sh/rts7751r2d/rts7751r2d.h b/include/asm-sh/rts7751r2d.h
similarity index 100%
rename from include/asm-sh/rts7751r2d/rts7751r2d.h
rename to include/asm-sh/rts7751r2d.h
diff --git a/include/asm-sh/rts7751r2d/ide.h b/include/asm-sh/rts7751r2d/ide.h
deleted file mode 100644
index 416f96b..0000000
--- a/include/asm-sh/rts7751r2d/ide.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_SH_RTS7751R2D_IDE_H
-#define __ASM_SH_RTS7751R2D_IDE_H
-
-/* Nothing to see here.. */
-#include <asm/rts7751r2d/rts7751r2d.h>
-
-#endif /* __ASM_SH_RTS7751R2D_IDE_H */
-
diff --git a/include/asm-sh/sh03/ide.h b/include/asm-sh/sh03/ide.h
deleted file mode 100644
index 73ee92e..0000000
--- a/include/asm-sh/sh03/ide.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_SH_SH03_IDE_H
-#define __ASM_SH_SH03_IDE_H
-
-#define IRQ_CFCARD	8
-#define IRQ_PCMCIA	8
-
-#endif /* __ASM_SH_SH03_IDE_H */
diff --git a/include/asm-sh/shmin/shmin.h b/include/asm-sh/shmin.h
similarity index 100%
rename from include/asm-sh/shmin/shmin.h
rename to include/asm-sh/shmin.h
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 6c1f8fd..3340126 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -353,6 +353,13 @@
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+extern void *set_exception_table_vec(unsigned int vec, void *handler);
+
+static inline void *set_exception_table_evt(unsigned int evt, void *handler)
+{
+	return set_exception_table_vec(evt >> 5, handler);
+}
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */
diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h
index c7ab280..5df842b 100644
--- a/include/asm-sh/timer.h
+++ b/include/asm-sh/timer.h
@@ -8,8 +8,9 @@
 	int (*init)(void);
 	int (*start)(void);
 	int (*stop)(void);
+#ifndef CONFIG_GENERIC_TIME
 	unsigned long (*get_offset)(void);
-	unsigned long (*get_frequency)(void);
+#endif
 };
 
 struct sys_timer {
@@ -24,21 +25,17 @@
 extern struct sys_timer tmu_timer;
 extern struct sys_timer *sys_timer;
 
+#ifndef CONFIG_GENERIC_TIME
 static inline unsigned long get_timer_offset(void)
 {
 	return sys_timer->ops->get_offset();
 }
-
-static inline unsigned long get_timer_frequency(void)
-{
-	return sys_timer->ops->get_frequency();
-}
+#endif
 
 /* arch/sh/kernel/timers/timer.c */
 struct sys_timer *get_sys_timer(void);
 
 /* arch/sh/kernel/time.c */
-void handle_timer_tick(struct pt_regs *);
+void handle_timer_tick(void);
 
 #endif /* __ASM_SH_TIMER_H */
-
diff --git a/include/asm-sh64/io.h b/include/asm-sh64/io.h
index 252fedb..14d8e7b 100644
--- a/include/asm-sh64/io.h
+++ b/include/asm-sh64/io.h
@@ -178,22 +178,6 @@
 unsigned long onchip_remap(unsigned long addr, unsigned long size, const char* name);
 extern void onchip_unmap(unsigned long vaddr);
 
-static __inline__ int check_signature(volatile void __iomem *io_addr,
-			const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 /*
  * The caches on some architectures aren't dma-coherent and have need to
  * handle this in software.  There are three types of operations that
diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
index 83a3dd1..aaf6ef4 100644
--- a/include/asm-sparc/elf.h
+++ b/include/asm-sparc/elf.h
@@ -8,11 +8,6 @@
 
 #include <asm/ptrace.h>
 
-#ifdef __KERNEL__
-#include <asm/mbus.h>
-#include <asm/uaccess.h>
-#endif
-
 /*
  * Sparc section types
  */
@@ -77,6 +72,23 @@
 #define ELF_NGREG 38
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
+typedef struct {
+	union {
+		unsigned long	pr_regs[32];
+		double		pr_dregs[16];
+	} pr_fr;
+	unsigned long __unused;
+	unsigned long	pr_fsr;
+	unsigned char	pr_qcnt;
+	unsigned char	pr_q_entrysize;
+	unsigned char	pr_en;
+	unsigned int	pr_q[64];
+} elf_fpregset_t;
+
+#ifdef __KERNEL__
+#include <asm/mbus.h>
+#include <asm/uaccess.h>
+
 /* Format is:
  * 	G0 --> G7
  *	O0 --> O7
@@ -99,20 +111,7 @@
 	dest[34] = src->npc;				\
 	dest[35] = src->y;				\
 	dest[36] = dest[37] = 0; /* XXX */		\
-} while(0); /* Janitors: Don't touch this colon. */
-
-typedef struct {
-	union {
-		unsigned long	pr_regs[32];
-		double		pr_dregs[16];
-	} pr_fr;
-	unsigned long __unused;
-	unsigned long	pr_fsr;
-	unsigned char	pr_qcnt;
-	unsigned char	pr_q_entrysize;
-	unsigned char	pr_en;
-	unsigned int	pr_q[64];
-} elf_fpregset_t;
+} while(0); /* Janitors: Don't touch this semicolon. */
 
 #define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs)	\
 	({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; })
@@ -165,8 +164,8 @@
 
 #define ELF_PLATFORM	(NULL)
 
-#ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
-#endif
+
+#endif /* __KERNEL__ */
 
 #endif /* !(__ASMSPARC_ELF_H) */
diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
index c53b332..9073c84 100644
--- a/include/asm-sparc/floppy.h
+++ b/include/asm-sparc/floppy.h
@@ -262,7 +262,7 @@
 }
 
 /* Our low-level entry point in arch/sparc/kernel/entry.S */
-irqreturn_t floppy_hardint(int irq, void *unused, struct pt_regs *regs);
+irqreturn_t floppy_hardint(int irq, void *unused);
 
 static int sun_fd_request_irq(void)
 {
diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h
index 3141ddf..ff520ea 100644
--- a/include/asm-sparc/irq.h
+++ b/include/asm-sparc/irq.h
@@ -76,8 +76,8 @@
 	BTFIXUP_CALL(load_profile_irq)(cpu, limit);
 }
 
-extern void (*sparc_init_timers)(irqreturn_t (*lvl10_irq)(int, void *, struct pt_regs *));
-extern void claim_ticker14(irqreturn_t (*irq_handler)(int, void *, struct pt_regs *),
+extern void (*sparc_init_timers)(irq_handler_t lvl10_irq);
+extern void claim_ticker14(irq_handler_t irq_handler,
 			   int irq,
 			   unsigned int timeout);
 
@@ -91,7 +91,7 @@
 #define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
 #endif
 
-extern int request_fast_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, __const__ char *devname);
+extern int request_fast_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, __const__ char *devname);
 
 /* On the sun4m, just like the timers, we have both per-cpu and master
  * interrupt registers.
diff --git a/include/asm-sparc/irq_regs.h b/include/asm-sparc/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-sparc/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h
index 557d089..de2249b 100644
--- a/include/asm-sparc/spinlock.h
+++ b/include/asm-sparc/spinlock.h
@@ -129,6 +129,7 @@
 	: /* no outputs */
 	: "r" (lp)
 	: "g2", "g4", "memory", "cc");
+	*(volatile __u32 *)&lp->lock = ~0U;
 }
 
 static inline int __raw_write_trylock(raw_rwlock_t *rw)
@@ -144,15 +145,40 @@
 		val = rw->lock & ~0xff;
 		if (val)
 			((volatile u8*)&rw->lock)[3] = 0;
+		else
+			*(volatile u32*)&rw->lock = ~0U;
 	}
 
 	return (val == 0);
 }
 
+static inline int __read_trylock(raw_rwlock_t *rw)
+{
+	register raw_rwlock_t *lp asm("g1");
+	register int res asm("o0");
+	lp = rw;
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___rw_read_try\n\t"
+	" ldstub	[%%g1 + 3], %%g2\n"
+	: "=r" (res)
+	: "r" (lp)
+	: "g2", "g4", "memory", "cc");
+	return res;
+}
+
+#define __raw_read_trylock(lock) \
+({	unsigned long flags; \
+	int res; \
+	local_irq_save(flags); \
+	res = __read_trylock(lock); \
+	local_irq_restore(flags); \
+	res; \
+})
+
 #define __raw_write_unlock(rw)	do { (rw)->lock = 0; } while(0)
 
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
 #define _raw_spin_relax(lock)	cpu_relax()
 #define _raw_read_relax(lock)	cpu_relax()
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index c73935d..36511ca 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -164,7 +164,7 @@
 	return (u32)(unsigned long)uptr;
 }
 
-static __inline__ void __user *compat_alloc_user_space(long len)
+static inline void __user *compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = current_thread_info()->kregs;
 	unsigned long usp = regs->u_regs[UREG_I6];
@@ -174,7 +174,10 @@
 	else
 		usp &= 0xffffffffUL;
 
-	return (void __user *) (usp - len);
+	usp -= len;
+	usp &= ~0x7UL;
+
+	return (void __user *) usp;
 }
 
 struct compat_ipc64_perm {
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index abf1500..dbe033e 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -208,7 +208,7 @@
 	pdma_areasize = pdma_size;
 }
 
-irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
+irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
 {
 	if (likely(doing_pdma)) {
 		void __iomem *stat = (void __iomem *) fdc_status;
@@ -255,7 +255,7 @@
 	}
 
 main_interrupt:
-	return floppy_interrupt(irq, dev_cookie, regs);
+	return floppy_interrupt(irq, dev_cookie);
 }
 
 static int sun_fd_request_irq(void)
@@ -311,7 +311,7 @@
 static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
 static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
 
-extern irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t floppy_interrupt(int irq, void *dev_id);
 
 static unsigned char sun_pci_fd_inb(unsigned long port)
 {
@@ -446,7 +446,7 @@
 
 void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
 {
-	floppy_interrupt(0, NULL, NULL);
+	floppy_interrupt(0, NULL);
 }
 
 /*
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 0056770..30b912d 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -440,21 +440,6 @@
 
 #define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
 
-static inline int check_signature(void __iomem *io_addr,
-				  const unsigned char *signature,
-				  int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature++)
-			goto out;
-		io_addr++;
-	} while (--length);
-	retval = 1;
-out:
-	return retval;
-}
-
 #define mmiowb()
 
 #ifdef __KERNEL__
diff --git a/include/asm-sparc64/irq_regs.h b/include/asm-sparc64/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-sparc64/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-um/archparam-ppc.h b/include/asm-um/archparam-ppc.h
index 172cd6f..4269d8a 100644
--- a/include/asm-um/archparam-ppc.h
+++ b/include/asm-um/archparam-ppc.h
@@ -1,15 +1,6 @@
 #ifndef __UM_ARCHPARAM_PPC_H
 #define __UM_ARCHPARAM_PPC_H
 
-/********* Bits for asm-um/hw_irq.h **********/
-
-struct hw_interrupt_type;
-
-/********* Bits for asm-um/hardirq.h **********/
-
-#define irq_enter(cpu, irq) hardirq_enter(cpu)
-#define irq_exit(cpu, irq) hardirq_exit(cpu)
-
 /********* Bits for asm-um/string.h **********/
 
 #define __HAVE_ARCH_STRRCHR
diff --git a/include/asm-um/irq_regs.h b/include/asm-um/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-um/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index 9e66d32..e81d0f2 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -77,7 +77,7 @@
 extern void init_bsp_APIC (void);
 extern void setup_local_APIC (void);
 extern void init_apic_mappings (void);
-extern void smp_local_timer_interrupt (struct pt_regs * regs);
+extern void smp_local_timer_interrupt (void);
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
diff --git a/include/asm-x86_64/floppy.h b/include/asm-x86_64/floppy.h
index 32ff5d13..6ea13c3 100644
--- a/include/asm-x86_64/floppy.h
+++ b/include/asm-x86_64/floppy.h
@@ -51,7 +51,7 @@
 static int virtual_dma_mode;
 static int doing_pdma;
 
-static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t floppy_hardint(int irq, void *dev_id)
 {
 	register unsigned char st;
 
@@ -63,7 +63,7 @@
 	static int dma_wait=0;
 #endif
 	if (!doing_pdma)
-		return floppy_interrupt(irq, dev_id, regs);
+		return floppy_interrupt(irq, dev_id);
 
 #ifdef TRACE_FLPY_INT
 	if(!calls)
@@ -106,7 +106,7 @@
 		dma_wait=0;
 #endif
 		doing_pdma = 0;
-		floppy_interrupt(irq, dev_id, regs);
+		floppy_interrupt(irq, dev_id);
 		return IRQ_HANDLED;
 	}
 #ifdef TRACE_FLPY_INT
diff --git a/include/asm-x86_64/genapic.h b/include/asm-x86_64/genapic.h
index 81e7146..a0e9a4b 100644
--- a/include/asm-x86_64/genapic.h
+++ b/include/asm-x86_64/genapic.h
@@ -18,6 +18,7 @@
 	u32 int_dest_mode;
 	int (*apic_id_registered)(void);
 	cpumask_t (*target_cpus)(void);
+	cpumask_t (*vector_allocation_domain)(int cpu);
 	void (*init_apic_ldr)(void);
 	/* ipi */
 	void (*send_IPI_mask)(cpumask_t mask, int vector);
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 53d0d9f..792dd52 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -74,10 +74,8 @@
 
 
 #ifndef __ASSEMBLY__
-extern unsigned int irq_vector[NR_IRQ_VECTORS];
 typedef int vector_irq_t[NR_VECTORS];
 DECLARE_PER_CPU(vector_irq_t, vector_irq);
-#define IO_APIC_VECTOR(irq)	(irq_vector[irq])
 
 /*
  * Various low-level irq details needed by irq.c, process.c,
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 70e91fe..6ee9fad 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -254,33 +254,6 @@
 
 #define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void *)(b),(c),(d))
 
-/**
- *	check_signature		-	find BIOS signatures
- *	@io_addr: mmio address to check 
- *	@signature:  signature block
- *	@length: length of signature
- *
- *	Perform a signature comparison with the mmio address io_addr. This
- *	address should have been obtained by ioremap.
- *	Returns 1 on a match.
- */
- 
-static inline int check_signature(void __iomem *io_addr,
-	const unsigned char *signature, int length)
-{
-	int retval = 0;
-	do {
-		if (readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
-}
-
 /* Nothing to do */
 
 #define dma_cache_inv(_start,_size)		do { } while (0)
diff --git a/include/asm-x86_64/irq_regs.h b/include/asm-x86_64/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-x86_64/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-x86_64/mach_apic.h b/include/asm-x86_64/mach_apic.h
index d334224..7b7115a 100644
--- a/include/asm-x86_64/mach_apic.h
+++ b/include/asm-x86_64/mach_apic.h
@@ -17,6 +17,7 @@
 #define INT_DELIVERY_MODE (genapic->int_delivery_mode)
 #define INT_DEST_MODE (genapic->int_dest_mode)
 #define TARGET_CPUS	  (genapic->target_cpus())
+#define vector_allocation_domain	(genapic->vector_allocation_domain)
 #define apic_id_registered (genapic->apic_id_registered)
 #define init_apic_ldr (genapic->init_apic_ldr)
 #define send_IPI_mask (genapic->send_IPI_mask)
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 2857560..5ed0ef3 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -32,13 +32,13 @@
 
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*({				\
-	extern int simple_indentifier_##var(void);	\
+	extern int simple_identifier_##var(void);	\
 	RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)); }))
 #define __get_cpu_var(var) (*({				\
-	extern int simple_indentifier_##var(void);	\
+	extern int simple_identifier_##var(void);	\
 	RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()); }))
 #define __raw_get_cpu_var(var) (*({			\
-	extern int simple_indentifier_##var(void);	\
+	extern int simple_identifier_##var(void);	\
 	RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()); }))
 
 /* A macro to avoid #include hell... */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 6899e77..0555c1c 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -366,6 +366,7 @@
 { 
 	pte_t pte;
 	pte_val(pte) = physpage | pgprot_val(pgprot); 
+	pte_val(pte) &= __supported_pte_mask;
 	return pte; 
 }
  
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index de9c314..cef17e0 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -475,6 +475,8 @@
 		: :"a" (eax), "c" (ecx));
 }
 
+extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+
 #define stack_current() \
 ({								\
 	struct thread_info *ti;					\
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index c28fc2d..e72cfcd 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -66,7 +66,7 @@
 extern void load_gs_index(unsigned gs);
 
 extern void stop_timer_interrupt(void);
-extern void main_timer_handler(struct pt_regs *regs);
+extern void main_timer_handler(void);
 
 extern unsigned long end_pfn_map; 
 
@@ -122,9 +122,11 @@
 extern int reboot_force;
 extern int notsc_setup(char *);
 
+extern int timer_over_8254;
+
 extern int gsi_irq_sharing(int gsi);
 
-extern void smp_local_timer_interrupt(struct pt_regs * regs);
+extern void smp_local_timer_interrupt(void);
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 5114ff1..a1155a2 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -120,6 +120,7 @@
 header-y += nfs2.h
 header-y += nfs4_mount.h
 header-y += nfs_mount.h
+header-y += oom.h
 header-y += param.h
 header-y += pci_ids.h
 header-y += pci_regs.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 88b5dfd..2b0c955 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -494,6 +494,9 @@
 
 extern int ec_read(u8 addr, u8 *val);
 extern int ec_write(u8 addr, u8 val);
+extern int ec_transaction(u8 command,
+                          const u8 *wdata, unsigned wdata_len,
+                          u8 *rdata, unsigned rdata_len);
 
 #endif /*CONFIG_ACPI_EC*/
 
diff --git a/include/linux/adb.h b/include/linux/adb.h
index b7305b1..64d8878 100644
--- a/include/linux/adb.h
+++ b/include/linux/adb.h
@@ -90,10 +90,10 @@
 int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
 		int flags, int nbytes, ...);
 int adb_register(int default_id,int handler_id,struct adb_ids *ids,
-		 void (*handler)(unsigned char *, int, struct pt_regs *, int));
+		 void (*handler)(unsigned char *, int, int));
 int adb_unregister(int index);
 void adb_poll(void);
-void adb_input(unsigned char *, int, struct pt_regs *, int);
+void adb_input(unsigned char *, int, int);
 int adb_reset_bus(void);
 
 int adb_try_handler_change(int address, int new_id);
diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
index 231ba09..2f85049 100644
--- a/include/linux/arcdevice.h
+++ b/include/linux/arcdevice.h
@@ -334,7 +334,7 @@
 #endif
 
 void arcnet_unregister_proto(struct ArcProto *proto);
-irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t arcnet_interrupt(int irq, void *dev_id);
 struct net_device *alloc_arcdev(char *name);
 
 #endif				/* __KERNEL__ */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index f7a1390..7011d625 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -10,6 +10,8 @@
 
 #include <asm/atomic.h>
 
+struct page;
+
 /*
  * Bits in backing_dev_info.state
  */
@@ -88,6 +90,11 @@
 				  (1 << BDI_write_congested));
 }
 
+void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
+void set_bdi_congested(struct backing_dev_info *bdi, int rw);
+long congestion_wait(int rw, long timeout);
+void congestion_end(int rw);
+
 #define bdi_cap_writeback_dirty(bdi) \
 	(!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
 
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index dcc5de7c..64b4641 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -46,7 +46,8 @@
  * bitmap_remap(dst, src, old, new, nbits)	*dst = map(old, new)(src)
  * bitmap_bitremap(oldbit, old, new, nbits)	newbit = map(old, new)(oldbit)
  * bitmap_scnprintf(buf, len, src, nbits)	Print bitmap src to buf
- * bitmap_parse(ubuf, ulen, dst, nbits)		Parse bitmap dst from user buf
+ * bitmap_parse(buf, buflen, dst, nbits)	Parse bitmap dst from kernel buf
+ * bitmap_parse_user(ubuf, ulen, dst, nbits)	Parse bitmap dst from user buf
  * bitmap_scnlistprintf(buf, len, src, nbits)	Print bitmap src as list to buf
  * bitmap_parselist(buf, dst, nbits)		Parse bitmap dst from list
  * bitmap_find_free_region(bitmap, bits, order)	Find and allocate bit region
@@ -106,7 +107,9 @@
 
 extern int bitmap_scnprintf(char *buf, unsigned int len,
 			const unsigned long *src, int nbits);
-extern int bitmap_parse(const char __user *ubuf, unsigned int ulen,
+extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
+			unsigned long *dst, int nbits);
+extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
 			unsigned long *dst, int nbits);
 extern int bitmap_scnlistprintf(char *buf, unsigned int len,
 			const unsigned long *src, int nbits);
@@ -270,6 +273,12 @@
 		__bitmap_shift_left(dst, src, n, nbits);
 }
 
+static inline int bitmap_parse(const char *buf, unsigned int buflen,
+			unsigned long *maskp, int nmaskbits)
+{
+	return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __LINUX_BITMAP_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 26f7856..7bfcde2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -157,6 +157,7 @@
 	REQ_TYPE_ATA_CMD,
 	REQ_TYPE_ATA_TASK,
 	REQ_TYPE_ATA_TASKFILE,
+	REQ_TYPE_ATA_PC,
 };
 
 /*
@@ -650,6 +651,26 @@
 extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
 extern int sg_scsi_ioctl(struct file *, struct request_queue *,
 		struct gendisk *, struct scsi_ioctl_command __user *);
+
+/*
+ * A queue has just exitted congestion.  Note this in the global counter of
+ * congested queues, and wake up anyone who was waiting for requests to be
+ * put back.
+ */
+static inline void blk_clear_queue_congested(request_queue_t *q, int rw)
+{
+	clear_bdi_congested(&q->backing_dev_info, rw);
+}
+
+/*
+ * A queue has just entered congestion.  Flag that in the queue's VM-visible
+ * state flags and increment the global gounter of congested queues.
+ */
+static inline void blk_set_queue_congested(request_queue_t *q, int rw)
+{
+	set_bdi_congested(&q->backing_dev_info, rw);
+}
+
 extern void blk_start_queue(request_queue_t *q);
 extern void blk_stop_queue(request_queue_t *q);
 extern void blk_sync_queue(struct request_queue *q);
@@ -764,10 +785,8 @@
 extern void blk_queue_free_tags(request_queue_t *);
 extern int blk_queue_resize_tags(request_queue_t *, int);
 extern void blk_queue_invalidate_tags(request_queue_t *);
-extern long blk_congestion_wait(int rw, long timeout);
 extern struct blk_queue_tag *blk_init_tags(int);
 extern void blk_free_tags(struct blk_queue_tag *);
-extern void blk_congestion_end(int rw);
 
 static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,
 						int tag)
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 131ffd3..5d9fb0e 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -69,6 +69,8 @@
 	bh_end_io_t *b_end_io;		/* I/O completion */
  	void *b_private;		/* reserved for b_end_io */
 	struct list_head b_assoc_buffers; /* associated with another mapping */
+	struct address_space *b_assoc_map;	/* mapping this buffer is
+						   associated with */
 	atomic_t b_count;		/* users using this buffer_head */
 };
 
diff --git a/include/linux/carta_random32.h b/include/linux/carta_random32.h
new file mode 100644
index 0000000..f6f3bd9
--- /dev/null
+++ b/include/linux/carta_random32.h
@@ -0,0 +1,29 @@
+/*
+ * Fast, simple, yet decent quality random number generator based on
+ * a paper by David G. Carta ("Two Fast Implementations of the
+ * `Minimal Standard' Random Number Generator," Communications of the
+ * ACM, January, 1990).
+ *
+ * Copyright (c) 2002-2006 Hewlett-Packard Development Company, L.P.
+ *	Contributed by Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+#ifndef _LINUX_CARTA_RANDOM32_H_
+#define _LINUX_CARTA_RANDOM32_H_
+
+u64 carta_random32(u64 seed);
+
+#endif /* _LINUX_CARTA_RANDOM32_H_ */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 3c9b0bc..bbbe7b4 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -749,7 +749,7 @@
 #define MRW_MODE_PC			0x03
 
 struct mrw_feature_desc {
-	__u16 feature_code;
+	__be16 feature_code;
 #if defined(__BIG_ENDIAN_BITFIELD)
 	__u8 reserved1		: 2;
 	__u8 feature_version	: 4;
@@ -776,7 +776,7 @@
 
 /* cf. mmc4r02g.pdf 5.3.10 Random Writable Feature (0020h) pg 197 of 635 */
 struct rwrt_feature_desc {
-	__u16 feature_code;
+	__be16 feature_code;
 #if defined(__BIG_ENDIAN_BITFIELD)
 	__u8 reserved1		: 2;
 	__u8 feature_version	: 4;
@@ -803,7 +803,7 @@
 };
 
 typedef struct {
-	__u16 disc_information_length;
+	__be16 disc_information_length;
 #if defined(__BIG_ENDIAN_BITFIELD)
 	__u8 reserved1			: 3;
         __u8 erasable			: 1;
@@ -849,7 +849,7 @@
 } disc_information;
 
 typedef struct {
-	__u16 track_information_length;
+	__be16 track_information_length;
 	__u8 track_lsb;
 	__u8 session_lsb;
 	__u8 reserved1;
@@ -880,12 +880,12 @@
 	__u8 lra_v			: 1;
 	__u8 reserved3			: 6;
 #endif
-	__u32 track_start;
-	__u32 next_writable;
-	__u32 free_blocks;
-	__u32 fixed_packet_size;
-	__u32 track_size;
-	__u32 last_rec_address;
+	__be32 track_start;
+	__be32 next_writable;
+	__be32 free_blocks;
+	__be32 fixed_packet_size;
+	__be32 track_size;
+	__be32 last_rec_address;
 } track_information;
 
 struct feature_header {
@@ -896,12 +896,12 @@
 };
 
 struct mode_page_header {
-	__u16 mode_data_length;
+	__be16 mode_data_length;
 	__u8 medium_type;
 	__u8 reserved1;
 	__u8 reserved2;
 	__u8 reserved3;
-	__u16 desc_length;
+	__be16 desc_length;
 };
 
 #ifdef __KERNEL__
@@ -1106,7 +1106,7 @@
 #endif
 	__u8 session_format;
 	__u8 reserved6;
-	__u32 packet_size;
+	__be32 packet_size;
 	__u16 audio_pause;
 	__u8 mcn[16];
 	__u8 isrc[16];
@@ -1151,7 +1151,7 @@
 } rpc_state_t;
 
 struct event_header {
-	__u16 data_len;
+	__be16 data_len;
 #if defined(__BIG_ENDIAN_BITFIELD)
 	__u8 nea		: 1;
 	__u8 reserved1		: 4;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index ef5cd19..f4ebf96 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -163,7 +163,7 @@
 compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
 			   compat_size_t len);
 asmlinkage long
-compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
+compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
 			   compat_size_t __user *len_ptr);
 
 long compat_sys_semctl(int first, int second, int third, void __user *uptr);
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 4e1663d..c26c3ad 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -61,17 +61,23 @@
  *         Some need translations, these do not.
  */
 COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
-COMPATIBLE_IOCTL(HDIO_SET_DMA)
-COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR)
-COMPATIBLE_IOCTL(HDIO_SET_NOWERR)
-COMPATIBLE_IOCTL(HDIO_SET_32BIT)
-COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
-COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
 COMPATIBLE_IOCTL(HDIO_DRIVE_TASK)
-COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
-COMPATIBLE_IOCTL(HDIO_SET_NICE)
-COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS)
+COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+ULONG_IOCTL(HDIO_SET_MULTCOUNT)
+ULONG_IOCTL(HDIO_SET_UNMASKINTR)
+ULONG_IOCTL(HDIO_SET_KEEPSETTINGS)
+ULONG_IOCTL(HDIO_SET_32BIT)
+ULONG_IOCTL(HDIO_SET_NOWERR)
+ULONG_IOCTL(HDIO_SET_DMA)
+ULONG_IOCTL(HDIO_SET_PIO_MODE)
+ULONG_IOCTL(HDIO_SET_NICE)
+ULONG_IOCTL(HDIO_SET_WCACHE)
+ULONG_IOCTL(HDIO_SET_ACOUSTIC)
+ULONG_IOCTL(HDIO_SET_BUSSTATE)
+ULONG_IOCTL(HDIO_SET_ADDRESS)
 COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
+/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+COMPATIBLE_IOCTL(0x330)
 /* 0x02 -- Floppy ioctls */
 COMPATIBLE_IOCTL(FDMSGON)
 COMPATIBLE_IOCTL(FDMSGOFF)
@@ -125,6 +131,7 @@
 COMPATIBLE_IOCTL(STOP_ARRAY)
 COMPATIBLE_IOCTL(STOP_ARRAY_RO)
 COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
+COMPATIBLE_IOCTL(GET_BITMAP_FILE)
 ULONG_IOCTL(SET_BITMAP_FILE)
 /* DM */
 COMPATIBLE_IOCTL(DM_VERSION_32)
diff --git a/include/linux/config.h b/include/linux/config.h
deleted file mode 100644
index 479ffb0..0000000
--- a/include/linux/config.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _LINUX_CONFIG_H
-#define _LINUX_CONFIG_H
-/* This file is no longer in use and kept only for backward compatibility.
- * autoconf.h is now included via -imacros on the commandline
- */
-#warning Including config.h is deprecated.
-#include <linux/autoconf.h>
-
-#endif
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index b268a3c..d0e8c8b 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -8,8 +8,8 @@
  * See detailed comments in the file linux/bitmap.h describing the
  * data type on which these cpumasks are based.
  *
- * For details of cpumask_scnprintf() and cpumask_parse(),
- * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
+ * For details of cpumask_scnprintf() and cpumask_parse_user(),
+ * see bitmap_scnprintf() and bitmap_parse_user() in lib/bitmap.c.
  * For details of cpulist_scnprintf() and cpulist_parse(), see
  * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  * For details of cpu_remap(), see bitmap_bitremap in lib/bitmap.c
@@ -49,7 +49,7 @@
  * unsigned long *cpus_addr(mask)	Array of unsigned long's in mask
  *
  * int cpumask_scnprintf(buf, len, mask) Format cpumask for printing
- * int cpumask_parse(ubuf, ulen, mask)	Parse ascii string as cpumask
+ * int cpumask_parse_user(ubuf, ulen, mask)	Parse ascii string as cpumask
  * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
  * int cpulist_parse(buf, map)		Parse ascii string as cpulist
  * int cpu_remap(oldbit, old, new)	newbit = map(old, new)(oldbit)
@@ -273,12 +273,12 @@
 	return bitmap_scnprintf(buf, len, srcp->bits, nbits);
 }
 
-#define cpumask_parse(ubuf, ulen, dst) \
-			__cpumask_parse((ubuf), (ulen), &(dst), NR_CPUS)
-static inline int __cpumask_parse(const char __user *buf, int len,
+#define cpumask_parse_user(ubuf, ulen, dst) \
+			__cpumask_parse_user((ubuf), (ulen), &(dst), NR_CPUS)
+static inline int __cpumask_parse_user(const char __user *buf, int len,
 					cpumask_t *dstp, int nbits)
 {
-	return bitmap_parse(buf, len, dstp->bits, nbits);
+	return bitmap_parse_user(buf, len, dstp->bits, nbits);
 }
 
 #define cpulist_scnprintf(buf, len, src) \
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 44605be..63f64a9 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -230,6 +230,7 @@
 extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
 extern void shrink_dcache_sb(struct super_block *);
 extern void shrink_dcache_parent(struct dentry *);
+extern void shrink_dcache_for_umount(struct super_block *);
 extern int d_invalidate(struct dentry *);
 
 /* only used at mount-time */
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index d6f4ec4..53553c9 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -191,7 +191,7 @@
 /* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
 struct dccp_so_feat {
 	__u8 dccpsf_feat;
-	__u8 *dccpsf_val;
+	__u8 __user *dccpsf_val;
 	__u8 dccpsf_len;
 };
 
diff --git a/include/linux/device.h b/include/linux/device.h
index 662e6a1..9d4f6a9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -393,7 +393,7 @@
 extern void device_initialize(struct device * dev);
 extern int __must_check device_add(struct device * dev);
 extern void device_del(struct device * dev);
-extern int __must_check device_for_each_child(struct device *, void *,
+extern int device_for_each_child(struct device *, void *,
 		     int (*fn)(struct device *, void *));
 extern int device_rename(struct device *dev, char *new_name);
 
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 38dc403..904bf3d 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -69,6 +69,7 @@
 	struct dmi_device *from);
 extern void dmi_scan_machine(void);
 extern int dmi_get_year(int field);
+extern int dmi_name_in_vendors(char *str);
 
 #else
 
@@ -77,6 +78,7 @@
 static inline struct dmi_device * dmi_find_device(int type, const char *name,
 	struct dmi_device *from) { return NULL; }
 static inline int dmi_get_year(int year) { return 0; }
+static inline int dmi_name_in_vendors(char *s) { return 0; }
 
 #endif
 
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index b3370ef..2fa9f11 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -70,7 +70,6 @@
 {
 	struct list_head list;
 	struct elevator_ops ops;
-	struct elevator_type *elevator_type;
 	struct elv_fs_entry *elevator_attrs;
 	char elevator_name[ELV_NAME_MAX];
 	struct module *elevator_owner;
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
new file mode 100644
index 0000000..498503e
--- /dev/null
+++ b/include/linux/ext4_fs.h
@@ -0,0 +1,994 @@
+/*
+ *  linux/include/linux/ext4_fs.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/include/linux/minix_fs.h
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT4_FS_H
+#define _LINUX_EXT4_FS_H
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/magic.h>
+
+/*
+ * The second extended filesystem constants/structures
+ */
+
+/*
+ * Define EXT4FS_DEBUG to produce debug messages
+ */
+#undef EXT4FS_DEBUG
+
+/*
+ * Define EXT4_RESERVATION to reserve data blocks for expanding files
+ */
+#define EXT4_DEFAULT_RESERVE_BLOCKS     8
+/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
+#define EXT4_MAX_RESERVE_BLOCKS         1027
+#define EXT4_RESERVE_WINDOW_NOT_ALLOCATED 0
+/*
+ * Always enable hashed directories
+ */
+#define CONFIG_EXT4_INDEX
+
+/*
+ * Debug code
+ */
+#ifdef EXT4FS_DEBUG
+#define ext4_debug(f, a...)						\
+	do {								\
+		printk (KERN_DEBUG "EXT4-fs DEBUG (%s, %d): %s:",	\
+			__FILE__, __LINE__, __FUNCTION__);		\
+		printk (KERN_DEBUG f, ## a);				\
+	} while (0)
+#else
+#define ext4_debug(f, a...)	do {} while (0)
+#endif
+
+/*
+ * Special inodes numbers
+ */
+#define	EXT4_BAD_INO		 1	/* Bad blocks inode */
+#define EXT4_ROOT_INO		 2	/* Root inode */
+#define EXT4_BOOT_LOADER_INO	 5	/* Boot loader inode */
+#define EXT4_UNDEL_DIR_INO	 6	/* Undelete directory inode */
+#define EXT4_RESIZE_INO		 7	/* Reserved group descriptors inode */
+#define EXT4_JOURNAL_INO	 8	/* Journal inode */
+
+/* First non-reserved inode for old ext4 filesystems */
+#define EXT4_GOOD_OLD_FIRST_INO	11
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT4_LINK_MAX		32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT4_MIN_BLOCK_SIZE		1024
+#define	EXT4_MAX_BLOCK_SIZE		4096
+#define EXT4_MIN_BLOCK_LOG_SIZE		  10
+#ifdef __KERNEL__
+# define EXT4_BLOCK_SIZE(s)		((s)->s_blocksize)
+#else
+# define EXT4_BLOCK_SIZE(s)		(EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#endif
+#define	EXT4_ADDR_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / sizeof (__u32))
+#ifdef __KERNEL__
+# define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
+#else
+# define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
+#endif
+#ifdef __KERNEL__
+#define	EXT4_ADDR_PER_BLOCK_BITS(s)	(EXT4_SB(s)->s_addr_per_block_bits)
+#define EXT4_INODE_SIZE(s)		(EXT4_SB(s)->s_inode_size)
+#define EXT4_FIRST_INO(s)		(EXT4_SB(s)->s_first_ino)
+#else
+#define EXT4_INODE_SIZE(s)	(((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \
+				 EXT4_GOOD_OLD_INODE_SIZE : \
+				 (s)->s_inode_size)
+#define EXT4_FIRST_INO(s)	(((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \
+				 EXT4_GOOD_OLD_FIRST_INO : \
+				 (s)->s_first_ino)
+#endif
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT4_MIN_FRAG_SIZE		1024
+#define	EXT4_MAX_FRAG_SIZE		4096
+#define EXT4_MIN_FRAG_LOG_SIZE		  10
+#ifdef __KERNEL__
+# define EXT4_FRAG_SIZE(s)		(EXT4_SB(s)->s_frag_size)
+# define EXT4_FRAGS_PER_BLOCK(s)	(EXT4_SB(s)->s_frags_per_block)
+#else
+# define EXT4_FRAG_SIZE(s)		(EXT4_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT4_FRAGS_PER_BLOCK(s)	(EXT4_BLOCK_SIZE(s) / EXT4_FRAG_SIZE(s))
+#endif
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext4_group_desc
+{
+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__le32	bg_inode_table;		/* Inodes table block */
+	__le16	bg_free_blocks_count;	/* Free blocks count */
+	__le16	bg_free_inodes_count;	/* Free inodes count */
+	__le16	bg_used_dirs_count;	/* Directories count */
+	__u16	bg_flags;
+	__u32	bg_reserved[3];
+	__le32	bg_block_bitmap_hi;	/* Blocks bitmap block MSB */
+	__le32	bg_inode_bitmap_hi;	/* Inodes bitmap block MSB */
+	__le32	bg_inode_table_hi;	/* Inodes table block MSB */
+};
+
+#ifdef __KERNEL__
+#include <linux/ext4_fs_i.h>
+#include <linux/ext4_fs_sb.h>
+#endif
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+#define EXT4_MIN_DESC_SIZE		32
+#define EXT4_MIN_DESC_SIZE_64BIT	64
+#define	EXT4_MAX_DESC_SIZE		EXT4_MIN_BLOCK_SIZE
+#define EXT4_DESC_SIZE(s)		(EXT4_SB(s)->s_desc_size)
+#ifdef __KERNEL__
+# define EXT4_BLOCKS_PER_GROUP(s)	(EXT4_SB(s)->s_blocks_per_group)
+# define EXT4_DESC_PER_BLOCK(s)		(EXT4_SB(s)->s_desc_per_block)
+# define EXT4_INODES_PER_GROUP(s)	(EXT4_SB(s)->s_inodes_per_group)
+# define EXT4_DESC_PER_BLOCK_BITS(s)	(EXT4_SB(s)->s_desc_per_block_bits)
+#else
+# define EXT4_BLOCKS_PER_GROUP(s)	((s)->s_blocks_per_group)
+# define EXT4_DESC_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / EXT4_DESC_SIZE(s))
+# define EXT4_INODES_PER_GROUP(s)	((s)->s_inodes_per_group)
+#endif
+
+/*
+ * Constants relative to the data blocks
+ */
+#define	EXT4_NDIR_BLOCKS		12
+#define	EXT4_IND_BLOCK			EXT4_NDIR_BLOCKS
+#define	EXT4_DIND_BLOCK			(EXT4_IND_BLOCK + 1)
+#define	EXT4_TIND_BLOCK			(EXT4_DIND_BLOCK + 1)
+#define	EXT4_N_BLOCKS			(EXT4_TIND_BLOCK + 1)
+
+/*
+ * Inode flags
+ */
+#define	EXT4_SECRM_FL			0x00000001 /* Secure deletion */
+#define	EXT4_UNRM_FL			0x00000002 /* Undelete */
+#define	EXT4_COMPR_FL			0x00000004 /* Compress file */
+#define EXT4_SYNC_FL			0x00000008 /* Synchronous updates */
+#define EXT4_IMMUTABLE_FL		0x00000010 /* Immutable file */
+#define EXT4_APPEND_FL			0x00000020 /* writes to file may only append */
+#define EXT4_NODUMP_FL			0x00000040 /* do not dump file */
+#define EXT4_NOATIME_FL			0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT4_DIRTY_FL			0x00000100
+#define EXT4_COMPRBLK_FL		0x00000200 /* One or more compressed clusters */
+#define EXT4_NOCOMPR_FL			0x00000400 /* Don't compress */
+#define EXT4_ECOMPR_FL			0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */
+#define EXT4_INDEX_FL			0x00001000 /* hash-indexed directory */
+#define EXT4_IMAGIC_FL			0x00002000 /* AFS directory */
+#define EXT4_JOURNAL_DATA_FL		0x00004000 /* file data should be journaled */
+#define EXT4_NOTAIL_FL			0x00008000 /* file tail should not be merged */
+#define EXT4_DIRSYNC_FL			0x00010000 /* dirsync behaviour (directories only) */
+#define EXT4_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
+#define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
+#define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
+
+#define EXT4_FL_USER_VISIBLE		0x000BDFFF /* User visible flags */
+#define EXT4_FL_USER_MODIFIABLE		0x000380FF /* User modifiable flags */
+
+/*
+ * Inode dynamic state flags
+ */
+#define EXT4_STATE_JDATA		0x00000001 /* journaled data exists */
+#define EXT4_STATE_NEW			0x00000002 /* inode is newly created */
+#define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
+
+/* Used to pass group descriptor data when online resize is done */
+struct ext4_new_group_input {
+	__u32 group;            /* Group number for this data */
+	__u64 block_bitmap;     /* Absolute block number of block bitmap */
+	__u64 inode_bitmap;     /* Absolute block number of inode bitmap */
+	__u64 inode_table;      /* Absolute block number of inode table start */
+	__u32 blocks_count;     /* Total number of blocks in this group */
+	__u16 reserved_blocks;  /* Number of reserved blocks in this group */
+	__u16 unused;
+};
+
+/* The struct ext4_new_group_input in kernel space, with free_blocks_count */
+struct ext4_new_group_data {
+	__u32 group;
+	__u64 block_bitmap;
+	__u64 inode_bitmap;
+	__u64 inode_table;
+	__u32 blocks_count;
+	__u16 reserved_blocks;
+	__u16 unused;
+	__u32 free_blocks_count;
+};
+
+
+/*
+ * ioctl commands
+ */
+#define	EXT4_IOC_GETFLAGS		FS_IOC_GETFLAGS
+#define	EXT4_IOC_SETFLAGS		FS_IOC_SETFLAGS
+#define	EXT4_IOC_GETVERSION		_IOR('f', 3, long)
+#define	EXT4_IOC_SETVERSION		_IOW('f', 4, long)
+#define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
+#define EXT4_IOC_GROUP_ADD		_IOW('f', 8,struct ext4_new_group_input)
+#define	EXT4_IOC_GETVERSION_OLD		FS_IOC_GETVERSION
+#define	EXT4_IOC_SETVERSION_OLD		FS_IOC_SETVERSION
+#ifdef CONFIG_JBD_DEBUG
+#define EXT4_IOC_WAIT_FOR_READONLY	_IOR('f', 99, long)
+#endif
+#define EXT4_IOC_GETRSVSZ		_IOR('f', 5, long)
+#define EXT4_IOC_SETRSVSZ		_IOW('f', 6, long)
+
+/*
+ * ioctl commands in 32 bit emulation
+ */
+#define EXT4_IOC32_GETFLAGS		FS_IOC32_GETFLAGS
+#define EXT4_IOC32_SETFLAGS		FS_IOC32_SETFLAGS
+#define EXT4_IOC32_GETVERSION		_IOR('f', 3, int)
+#define EXT4_IOC32_SETVERSION		_IOW('f', 4, int)
+#define EXT4_IOC32_GETRSVSZ		_IOR('f', 5, int)
+#define EXT4_IOC32_SETRSVSZ		_IOW('f', 6, int)
+#define EXT4_IOC32_GROUP_EXTEND		_IOW('f', 7, unsigned int)
+#ifdef CONFIG_JBD_DEBUG
+#define EXT4_IOC32_WAIT_FOR_READONLY	_IOR('f', 99, int)
+#endif
+#define EXT4_IOC32_GETVERSION_OLD	FS_IOC32_GETVERSION
+#define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
+
+
+/*
+ *  Mount options
+ */
+struct ext4_mount_options {
+	unsigned long s_mount_opt;
+	uid_t s_resuid;
+	gid_t s_resgid;
+	unsigned long s_commit_interval;
+#ifdef CONFIG_QUOTA
+	int s_jquota_fmt;
+	char *s_qf_names[MAXQUOTAS];
+#endif
+};
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext4_inode {
+	__le16	i_mode;		/* File mode */
+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
+	__le32	i_size;		/* Size in bytes */
+	__le32	i_atime;	/* Access time */
+	__le32	i_ctime;	/* Creation time */
+	__le32	i_mtime;	/* Modification time */
+	__le32	i_dtime;	/* Deletion Time */
+	__le16	i_gid;		/* Low 16 bits of Group Id */
+	__le16	i_links_count;	/* Links count */
+	__le32	i_blocks;	/* Blocks count */
+	__le32	i_flags;	/* File flags */
+	union {
+		struct {
+			__u32  l_i_reserved1;
+		} linux1;
+		struct {
+			__u32  h_i_translator;
+		} hurd1;
+		struct {
+			__u32  m_i_reserved1;
+		} masix1;
+	} osd1;				/* OS dependent 1 */
+	__le32	i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
+	__le32	i_generation;	/* File version (for NFS) */
+	__le32	i_file_acl;	/* File ACL */
+	__le32	i_dir_acl;	/* Directory ACL */
+	__le32	i_faddr;	/* Fragment address */
+	union {
+		struct {
+			__u8	l_i_frag;	/* Fragment number */
+			__u8	l_i_fsize;	/* Fragment size */
+			__le16	l_i_file_acl_high;
+			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_gid_high;	/* were reserved2[0] */
+			__u32	l_i_reserved2;
+		} linux2;
+		struct {
+			__u8	h_i_frag;	/* Fragment number */
+			__u8	h_i_fsize;	/* Fragment size */
+			__u16	h_i_mode_high;
+			__u16	h_i_uid_high;
+			__u16	h_i_gid_high;
+			__u32	h_i_author;
+		} hurd2;
+		struct {
+			__u8	m_i_frag;	/* Fragment number */
+			__u8	m_i_fsize;	/* Fragment size */
+			__le16	m_i_file_acl_high;
+			__u32	m_i_reserved2[2];
+		} masix2;
+	} osd2;				/* OS dependent 2 */
+	__le16	i_extra_isize;
+	__le16	i_pad1;
+};
+
+#define i_size_high	i_dir_acl
+
+#if defined(__KERNEL__) || defined(__linux__)
+#define i_reserved1	osd1.linux1.l_i_reserved1
+#define i_frag		osd2.linux2.l_i_frag
+#define i_fsize		osd2.linux2.l_i_fsize
+#define i_file_acl_high	osd2.linux2.l_i_file_acl_high
+#define i_uid_low	i_uid
+#define i_gid_low	i_gid
+#define i_uid_high	osd2.linux2.l_i_uid_high
+#define i_gid_high	osd2.linux2.l_i_gid_high
+#define i_reserved2	osd2.linux2.l_i_reserved2
+
+#elif defined(__GNU__)
+
+#define i_translator	osd1.hurd1.h_i_translator
+#define i_frag		osd2.hurd2.h_i_frag;
+#define i_fsize		osd2.hurd2.h_i_fsize;
+#define i_uid_high	osd2.hurd2.h_i_uid_high
+#define i_gid_high	osd2.hurd2.h_i_gid_high
+#define i_author	osd2.hurd2.h_i_author
+
+#elif defined(__masix__)
+
+#define i_reserved1	osd1.masix1.m_i_reserved1
+#define i_frag		osd2.masix2.m_i_frag
+#define i_fsize		osd2.masix2.m_i_fsize
+#define i_file_acl_high	osd2.masix2.m_i_file_acl_high
+#define i_reserved2	osd2.masix2.m_i_reserved2
+
+#endif /* defined(__KERNEL__) || defined(__linux__) */
+
+/*
+ * File system states
+ */
+#define	EXT4_VALID_FS			0x0001	/* Unmounted cleanly */
+#define	EXT4_ERROR_FS			0x0002	/* Errors detected */
+#define	EXT4_ORPHAN_FS			0x0004	/* Orphans being recovered */
+
+/*
+ * Mount flags
+ */
+#define EXT4_MOUNT_CHECK		0x00001	/* Do mount-time checks */
+#define EXT4_MOUNT_OLDALLOC		0x00002  /* Don't use the new Orlov allocator */
+#define EXT4_MOUNT_GRPID		0x00004	/* Create files with directory's group */
+#define EXT4_MOUNT_DEBUG		0x00008	/* Some debugging messages */
+#define EXT4_MOUNT_ERRORS_CONT		0x00010	/* Continue on errors */
+#define EXT4_MOUNT_ERRORS_RO		0x00020	/* Remount fs ro on errors */
+#define EXT4_MOUNT_ERRORS_PANIC		0x00040	/* Panic on errors */
+#define EXT4_MOUNT_MINIX_DF		0x00080	/* Mimics the Minix statfs */
+#define EXT4_MOUNT_NOLOAD		0x00100	/* Don't use existing journal*/
+#define EXT4_MOUNT_ABORT		0x00200	/* Fatal error detected */
+#define EXT4_MOUNT_DATA_FLAGS		0x00C00	/* Mode for data writes: */
+#define EXT4_MOUNT_JOURNAL_DATA		0x00400	/* Write data to journal */
+#define EXT4_MOUNT_ORDERED_DATA		0x00800	/* Flush data before commit */
+#define EXT4_MOUNT_WRITEBACK_DATA	0x00C00	/* No data ordering */
+#define EXT4_MOUNT_UPDATE_JOURNAL	0x01000	/* Update the journal format */
+#define EXT4_MOUNT_NO_UID32		0x02000  /* Disable 32-bit UIDs */
+#define EXT4_MOUNT_XATTR_USER		0x04000	/* Extended user attributes */
+#define EXT4_MOUNT_POSIX_ACL		0x08000	/* POSIX Access Control Lists */
+#define EXT4_MOUNT_RESERVATION		0x10000	/* Preallocation */
+#define EXT4_MOUNT_BARRIER		0x20000 /* Use block barriers */
+#define EXT4_MOUNT_NOBH			0x40000 /* No bufferheads */
+#define EXT4_MOUNT_QUOTA		0x80000 /* Some quota option set */
+#define EXT4_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
+#define EXT4_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
+#define EXT4_MOUNT_EXTENTS		0x400000 /* Extents support */
+
+/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
+#ifndef _LINUX_EXT2_FS_H
+#define clear_opt(o, opt)		o &= ~EXT4_MOUNT_##opt
+#define set_opt(o, opt)			o |= EXT4_MOUNT_##opt
+#define test_opt(sb, opt)		(EXT4_SB(sb)->s_mount_opt & \
+					 EXT4_MOUNT_##opt)
+#else
+#define EXT2_MOUNT_NOLOAD		EXT4_MOUNT_NOLOAD
+#define EXT2_MOUNT_ABORT		EXT4_MOUNT_ABORT
+#define EXT2_MOUNT_DATA_FLAGS		EXT4_MOUNT_DATA_FLAGS
+#endif
+
+#define ext4_set_bit			ext2_set_bit
+#define ext4_set_bit_atomic		ext2_set_bit_atomic
+#define ext4_clear_bit			ext2_clear_bit
+#define ext4_clear_bit_atomic		ext2_clear_bit_atomic
+#define ext4_test_bit			ext2_test_bit
+#define ext4_find_first_zero_bit	ext2_find_first_zero_bit
+#define ext4_find_next_zero_bit		ext2_find_next_zero_bit
+
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT4_DFL_MAX_MNT_COUNT		20	/* Allow 20 mounts */
+#define EXT4_DFL_CHECKINTERVAL		0	/* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT4_ERRORS_CONTINUE		1	/* Continue execution */
+#define EXT4_ERRORS_RO			2	/* Remount fs read-only */
+#define EXT4_ERRORS_PANIC		3	/* Panic */
+#define EXT4_ERRORS_DEFAULT		EXT4_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext4_super_block {
+/*00*/	__le32	s_inodes_count;		/* Inodes count */
+	__le32	s_blocks_count;		/* Blocks count */
+	__le32	s_r_blocks_count;	/* Reserved blocks count */
+	__le32	s_free_blocks_count;	/* Free blocks count */
+/*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
+	__le32	s_first_data_block;	/* First Data Block */
+	__le32	s_log_block_size;	/* Block size */
+	__le32	s_log_frag_size;	/* Fragment size */
+/*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
+	__le32	s_frags_per_group;	/* # Fragments per group */
+	__le32	s_inodes_per_group;	/* # Inodes per group */
+	__le32	s_mtime;		/* Mount time */
+/*30*/	__le32	s_wtime;		/* Write time */
+	__le16	s_mnt_count;		/* Mount count */
+	__le16	s_max_mnt_count;	/* Maximal mount count */
+	__le16	s_magic;		/* Magic signature */
+	__le16	s_state;		/* File system state */
+	__le16	s_errors;		/* Behaviour when detecting errors */
+	__le16	s_minor_rev_level;	/* minor revision level */
+/*40*/	__le32	s_lastcheck;		/* time of last check */
+	__le32	s_checkinterval;	/* max. time between checks */
+	__le32	s_creator_os;		/* OS */
+	__le32	s_rev_level;		/* Revision level */
+/*50*/	__le16	s_def_resuid;		/* Default uid for reserved blocks */
+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
+	/*
+	 * These fields are for EXT4_DYNAMIC_REV superblocks only.
+	 *
+	 * Note: the difference between the compatible feature set and
+	 * the incompatible feature set is that if there is a bit set
+	 * in the incompatible feature set that the kernel doesn't
+	 * know about, it should refuse to mount the filesystem.
+	 *
+	 * e2fsck's requirements are more strict; if it doesn't know
+	 * about a feature in either the compatible or incompatible
+	 * feature set, it must abort and not try to meddle with
+	 * things it doesn't understand...
+	 */
+	__le32	s_first_ino;		/* First non-reserved inode */
+	__le16  s_inode_size;		/* size of inode structure */
+	__le16	s_block_group_nr;	/* block group # of this superblock */
+	__le32	s_feature_compat;	/* compatible feature set */
+/*60*/	__le32	s_feature_incompat;	/* incompatible feature set */
+	__le32	s_feature_ro_compat;	/* readonly-compatible feature set */
+/*68*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */
+/*78*/	char	s_volume_name[16];	/* volume name */
+/*88*/	char	s_last_mounted[64];	/* directory where last mounted */
+/*C8*/	__le32	s_algorithm_usage_bitmap; /* For compression */
+	/*
+	 * Performance hints.  Directory preallocation should only
+	 * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+	 */
+	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
+	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
+	__le16	s_reserved_gdt_blocks;	/* Per group desc for online growth */
+	/*
+	 * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
+	 */
+/*D0*/	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
+/*E0*/	__le32	s_journal_inum;		/* inode number of journal file */
+	__le32	s_journal_dev;		/* device number of journal file */
+	__le32	s_last_orphan;		/* start of list of inodes to delete */
+	__le32	s_hash_seed[4];		/* HTREE hash seed */
+	__u8	s_def_hash_version;	/* Default hash version to use */
+	__u8	s_reserved_char_pad;
+	__le16  s_desc_size;		/* size of group descriptor */
+/*100*/	__le32	s_default_mount_opts;
+	__le32	s_first_meta_bg;	/* First metablock block group */
+	__le32	s_mkfs_time;		/* When the filesystem was created */
+	__le32	s_jnl_blocks[17];	/* Backup of the journal inode */
+	/* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
+/*150*/	__le32	s_blocks_count_hi;	/* Blocks count */
+	__le32	s_r_blocks_count_hi;	/* Reserved blocks count */
+	__le32	s_free_blocks_count_hi;	/* Free blocks count */
+	__u32	s_reserved[169];	/* Padding to the end of the block */
+};
+
+#ifdef __KERNEL__
+static inline struct ext4_sb_info * EXT4_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
+{
+	return container_of(inode, struct ext4_inode_info, vfs_inode);
+}
+
+static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+{
+	return ino == EXT4_ROOT_INO ||
+		ino == EXT4_JOURNAL_INO ||
+		ino == EXT4_RESIZE_INO ||
+		(ino >= EXT4_FIRST_INO(sb) &&
+		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+}
+#else
+/* Assume that user mode programs are passing in an ext4fs superblock, not
+ * a kernel struct super_block.  This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT4_SB(sb)	(sb)
+#endif
+
+#define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
+
+/*
+ * Codes for operating systems
+ */
+#define EXT4_OS_LINUX		0
+#define EXT4_OS_HURD		1
+#define EXT4_OS_MASIX		2
+#define EXT4_OS_FREEBSD		3
+#define EXT4_OS_LITES		4
+
+/*
+ * Revision levels
+ */
+#define EXT4_GOOD_OLD_REV	0	/* The good old (original) format */
+#define EXT4_DYNAMIC_REV	1	/* V2 format w/ dynamic inode sizes */
+
+#define EXT4_CURRENT_REV	EXT4_GOOD_OLD_REV
+#define EXT4_MAX_SUPP_REV	EXT4_DYNAMIC_REV
+
+#define EXT4_GOOD_OLD_INODE_SIZE 128
+
+/*
+ * Feature set definitions
+ */
+
+#define EXT4_HAS_COMPAT_FEATURE(sb,mask)			\
+	( EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
+#define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask)			\
+	( EXT4_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
+#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask)			\
+	( EXT4_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
+#define EXT4_SET_COMPAT_FEATURE(sb,mask)			\
+	EXT4_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
+#define EXT4_SET_RO_COMPAT_FEATURE(sb,mask)			\
+	EXT4_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
+#define EXT4_SET_INCOMPAT_FEATURE(sb,mask)			\
+	EXT4_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
+#define EXT4_CLEAR_COMPAT_FEATURE(sb,mask)			\
+	EXT4_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
+#define EXT4_CLEAR_RO_COMPAT_FEATURE(sb,mask)			\
+	EXT4_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
+#define EXT4_CLEAR_INCOMPAT_FEATURE(sb,mask)			\
+	EXT4_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
+
+#define EXT4_FEATURE_COMPAT_DIR_PREALLOC	0x0001
+#define EXT4_FEATURE_COMPAT_IMAGIC_INODES	0x0002
+#define EXT4_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+#define EXT4_FEATURE_COMPAT_EXT_ATTR		0x0008
+#define EXT4_FEATURE_COMPAT_RESIZE_INODE	0x0010
+#define EXT4_FEATURE_COMPAT_DIR_INDEX		0x0020
+
+#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
+#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
+#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR	0x0004
+
+#define EXT4_FEATURE_INCOMPAT_COMPRESSION	0x0001
+#define EXT4_FEATURE_INCOMPAT_FILETYPE		0x0002
+#define EXT4_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
+#define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
+#define EXT4_FEATURE_INCOMPAT_META_BG		0x0010
+#define EXT4_FEATURE_INCOMPAT_EXTENTS		0x0040 /* extents support */
+#define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
+
+#define EXT4_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
+#define EXT4_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \
+					 EXT4_FEATURE_INCOMPAT_RECOVER| \
+					 EXT4_FEATURE_INCOMPAT_META_BG| \
+					 EXT4_FEATURE_INCOMPAT_EXTENTS| \
+					 EXT4_FEATURE_INCOMPAT_64BIT)
+#define EXT4_FEATURE_RO_COMPAT_SUPP	(EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+					 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
+					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
+
+/*
+ * Default values for user and/or group using reserved blocks
+ */
+#define	EXT4_DEF_RESUID		0
+#define	EXT4_DEF_RESGID		0
+
+/*
+ * Default mount options
+ */
+#define EXT4_DEFM_DEBUG		0x0001
+#define EXT4_DEFM_BSDGROUPS	0x0002
+#define EXT4_DEFM_XATTR_USER	0x0004
+#define EXT4_DEFM_ACL		0x0008
+#define EXT4_DEFM_UID16		0x0010
+#define EXT4_DEFM_JMODE		0x0060
+#define EXT4_DEFM_JMODE_DATA	0x0020
+#define EXT4_DEFM_JMODE_ORDERED	0x0040
+#define EXT4_DEFM_JMODE_WBACK	0x0060
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT4_NAME_LEN 255
+
+struct ext4_dir_entry {
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__le16	name_len;		/* Name length */
+	char	name[EXT4_NAME_LEN];	/* File name */
+};
+
+/*
+ * The new version of the directory entry.  Since EXT4 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext4_dir_entry_2 {
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__u8	name_len;		/* Name length */
+	__u8	file_type;
+	char	name[EXT4_NAME_LEN];	/* File name */
+};
+
+/*
+ * Ext4 directory file types.  Only the low 3 bits are used.  The
+ * other bits are reserved for now.
+ */
+#define EXT4_FT_UNKNOWN		0
+#define EXT4_FT_REG_FILE	1
+#define EXT4_FT_DIR		2
+#define EXT4_FT_CHRDEV		3
+#define EXT4_FT_BLKDEV		4
+#define EXT4_FT_FIFO		5
+#define EXT4_FT_SOCK		6
+#define EXT4_FT_SYMLINK		7
+
+#define EXT4_FT_MAX		8
+
+/*
+ * EXT4_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT4_DIR_PAD			4
+#define EXT4_DIR_ROUND			(EXT4_DIR_PAD - 1)
+#define EXT4_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT4_DIR_ROUND) & \
+					 ~EXT4_DIR_ROUND)
+/*
+ * Hash Tree Directory indexing
+ * (c) Daniel Phillips, 2001
+ */
+
+#ifdef CONFIG_EXT4_INDEX
+  #define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
+					      EXT4_FEATURE_COMPAT_DIR_INDEX) && \
+		      (EXT4_I(dir)->i_flags & EXT4_INDEX_FL))
+#define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
+#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
+#else
+  #define is_dx(dir) 0
+#define EXT4_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT4_LINK_MAX)
+#define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
+#endif
+
+/* Legal values for the dx_root hash_version field: */
+
+#define DX_HASH_LEGACY		0
+#define DX_HASH_HALF_MD4	1
+#define DX_HASH_TEA		2
+
+#ifdef __KERNEL__
+
+/* hash info structure used by the directory hash */
+struct dx_hash_info
+{
+	u32		hash;
+	u32		minor_hash;
+	int		hash_version;
+	u32		*seed;
+};
+
+#define EXT4_HTREE_EOF	0x7fffffff
+
+/*
+ * Control parameters used by ext4_htree_next_block
+ */
+#define HASH_NB_ALWAYS		1
+
+
+/*
+ * Describe an inode's exact location on disk and in memory
+ */
+struct ext4_iloc
+{
+	struct buffer_head *bh;
+	unsigned long offset;
+	unsigned long block_group;
+};
+
+static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc)
+{
+	return (struct ext4_inode *) (iloc->bh->b_data + iloc->offset);
+}
+
+/*
+ * This structure is stuffed into the struct file's private_data field
+ * for directories.  It is where we put information so that we can do
+ * readdir operations in hash tree order.
+ */
+struct dir_private_info {
+	struct rb_root	root;
+	struct rb_node	*curr_node;
+	struct fname	*extra_fname;
+	loff_t		last_pos;
+	__u32		curr_hash;
+	__u32		curr_minor_hash;
+	__u32		next_hash;
+};
+
+/* calculate the first block number of the group */
+static inline ext4_fsblk_t
+ext4_group_first_block_no(struct super_block *sb, unsigned long group_no)
+{
+	return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
+		le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+}
+
+/*
+ * Special error return code only used by dx_probe() and its callers.
+ */
+#define ERR_BAD_DX_DIR	-75000
+
+void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+			unsigned long *blockgrpp, ext4_grpblk_t *offsetp);
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * Ok, these declarations are also in <linux/kernel.h> but none of the
+ * ext4 source programs needs to include it so they are duplicated here.
+ */
+# define NORET_TYPE    /**/
+# define ATTRIB_NORET  __attribute__((noreturn))
+# define NORET_AND     noreturn,
+
+/* balloc.c */
+extern unsigned int ext4_block_group(struct super_block *sb,
+			ext4_fsblk_t blocknr);
+extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
+			ext4_fsblk_t blocknr);
+extern int ext4_bg_has_super(struct super_block *sb, int group);
+extern unsigned long ext4_bg_num_gdb(struct super_block *sb, int group);
+extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode,
+			ext4_fsblk_t goal, int *errp);
+extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode,
+			ext4_fsblk_t goal, unsigned long *count, int *errp);
+extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
+			ext4_fsblk_t block, unsigned long count);
+extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
+				 ext4_fsblk_t block, unsigned long count,
+				unsigned long *pdquot_freed_blocks);
+extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *);
+extern void ext4_check_blocks_bitmap (struct super_block *);
+extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+						    unsigned int block_group,
+						    struct buffer_head ** bh);
+extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+extern void ext4_init_block_alloc_info(struct inode *);
+extern void ext4_rsv_window_add(struct super_block *sb, struct ext4_reserve_window_node *rsv);
+
+/* dir.c */
+extern int ext4_check_dir_entry(const char *, struct inode *,
+				struct ext4_dir_entry_2 *,
+				struct buffer_head *, unsigned long);
+extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+				    __u32 minor_hash,
+				    struct ext4_dir_entry_2 *dirent);
+extern void ext4_htree_free_dir_info(struct dir_private_info *p);
+
+/* fsync.c */
+extern int ext4_sync_file (struct file *, struct dentry *, int);
+
+/* hash.c */
+extern int ext4fs_dirhash(const char *name, int len, struct
+			  dx_hash_info *hinfo);
+
+/* ialloc.c */
+extern struct inode * ext4_new_inode (handle_t *, struct inode *, int);
+extern void ext4_free_inode (handle_t *, struct inode *);
+extern struct inode * ext4_orphan_get (struct super_block *, unsigned long);
+extern unsigned long ext4_count_free_inodes (struct super_block *);
+extern unsigned long ext4_count_dirs (struct super_block *);
+extern void ext4_check_inodes_bitmap (struct super_block *);
+extern unsigned long ext4_count_free (struct buffer_head *, unsigned);
+
+
+/* inode.c */
+int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+		struct buffer_head *bh, ext4_fsblk_t blocknr);
+struct buffer_head * ext4_getblk (handle_t *, struct inode *, long, int, int *);
+struct buffer_head * ext4_bread (handle_t *, struct inode *, int, int, int *);
+int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+	sector_t iblock, unsigned long maxblocks, struct buffer_head *bh_result,
+	int create, int extend_disksize);
+
+extern void ext4_read_inode (struct inode *);
+extern int  ext4_write_inode (struct inode *, int);
+extern int  ext4_setattr (struct dentry *, struct iattr *);
+extern void ext4_delete_inode (struct inode *);
+extern int  ext4_sync_inode (handle_t *, struct inode *);
+extern void ext4_discard_reservation (struct inode *);
+extern void ext4_dirty_inode(struct inode *);
+extern int ext4_change_inode_journal_flag(struct inode *, int);
+extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+extern void ext4_truncate (struct inode *);
+extern void ext4_set_inode_flags(struct inode *);
+extern void ext4_set_aops(struct inode *inode);
+extern int ext4_writepage_trans_blocks(struct inode *);
+extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
+		struct address_space *mapping, loff_t from);
+
+/* ioctl.c */
+extern int ext4_ioctl (struct inode *, struct file *, unsigned int,
+		       unsigned long);
+extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
+
+/* namei.c */
+extern int ext4_orphan_add(handle_t *, struct inode *);
+extern int ext4_orphan_del(handle_t *, struct inode *);
+extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+				__u32 start_minor_hash, __u32 *next_hash);
+
+/* resize.c */
+extern int ext4_group_add(struct super_block *sb,
+				struct ext4_new_group_data *input);
+extern int ext4_group_extend(struct super_block *sb,
+				struct ext4_super_block *es,
+				ext4_fsblk_t n_blocks_count);
+
+/* super.c */
+extern void ext4_error (struct super_block *, const char *, const char *, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern void __ext4_std_error (struct super_block *, const char *, int);
+extern void ext4_abort (struct super_block *, const char *, const char *, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern void ext4_warning (struct super_block *, const char *, const char *, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern void ext4_update_dynamic_rev (struct super_block *sb);
+extern ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+				      struct ext4_group_desc *bg);
+extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
+				      struct ext4_group_desc *bg);
+extern ext4_fsblk_t ext4_inode_table(struct super_block *sb,
+				     struct ext4_group_desc *bg);
+extern void ext4_block_bitmap_set(struct super_block *sb,
+				  struct ext4_group_desc *bg, ext4_fsblk_t blk);
+extern void ext4_inode_bitmap_set(struct super_block *sb,
+				  struct ext4_group_desc *bg, ext4_fsblk_t blk);
+extern void ext4_inode_table_set(struct super_block *sb,
+				 struct ext4_group_desc *bg, ext4_fsblk_t blk);
+
+static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
+{
+	return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
+		le32_to_cpu(es->s_blocks_count);
+}
+
+static inline ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
+{
+	return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
+		le32_to_cpu(es->s_r_blocks_count);
+}
+
+static inline ext4_fsblk_t ext4_free_blocks_count(struct ext4_super_block *es)
+{
+	return ((ext4_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) |
+		le32_to_cpu(es->s_free_blocks_count);
+}
+
+static inline void ext4_blocks_count_set(struct ext4_super_block *es,
+					 ext4_fsblk_t blk)
+{
+	es->s_blocks_count = cpu_to_le32((u32)blk);
+	es->s_blocks_count_hi = cpu_to_le32(blk >> 32);
+}
+
+static inline void ext4_free_blocks_count_set(struct ext4_super_block *es,
+					      ext4_fsblk_t blk)
+{
+	es->s_free_blocks_count = cpu_to_le32((u32)blk);
+	es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32);
+}
+
+static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
+					   ext4_fsblk_t blk)
+{
+	es->s_r_blocks_count = cpu_to_le32((u32)blk);
+	es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32);
+}
+
+
+
+#define ext4_std_error(sb, errno)				\
+do {								\
+	if ((errno))						\
+		__ext4_std_error((sb), __FUNCTION__, (errno));	\
+} while (0)
+
+/*
+ * Inodes and files operations
+ */
+
+/* dir.c */
+extern const struct file_operations ext4_dir_operations;
+
+/* file.c */
+extern struct inode_operations ext4_file_inode_operations;
+extern const struct file_operations ext4_file_operations;
+
+/* namei.c */
+extern struct inode_operations ext4_dir_inode_operations;
+extern struct inode_operations ext4_special_inode_operations;
+
+/* symlink.c */
+extern struct inode_operations ext4_symlink_inode_operations;
+extern struct inode_operations ext4_fast_symlink_inode_operations;
+
+/* extents.c */
+extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+			ext4_fsblk_t iblock,
+			unsigned long max_blocks, struct buffer_head *bh_result,
+			int create, int extend_disksize);
+extern void ext4_ext_truncate(struct inode *, struct page *);
+extern void ext4_ext_init(struct super_block *);
+extern void ext4_ext_release(struct super_block *);
+static inline int
+ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
+			unsigned long max_blocks, struct buffer_head *bh,
+			int create, int extend_disksize)
+{
+	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+		return ext4_ext_get_blocks(handle, inode, block, max_blocks,
+					bh, create, extend_disksize);
+	return ext4_get_blocks_handle(handle, inode, block, max_blocks, bh,
+					create, extend_disksize);
+}
+
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _LINUX_EXT4_FS_H */
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
new file mode 100644
index 0000000..a41cc24
--- /dev/null
+++ b/include/linux/ext4_fs_extents.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.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.
+ *
+ * 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 Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+ */
+
+#ifndef _LINUX_EXT4_EXTENTS
+#define _LINUX_EXT4_EXTENTS
+
+#include <linux/ext4_fs.h>
+
+/*
+ * With AGRESSIVE_TEST defined, the capacity of index/leaf blocks
+ * becomes very small, so index split, in-depth growing and
+ * other hard changes happen much more often.
+ * This is for debug purposes only.
+ */
+#define AGRESSIVE_TEST_
+
+/*
+ * With EXTENTS_STATS defined, the number of blocks and extents
+ * are collected in the truncate path. They'll be shown at
+ * umount time.
+ */
+#define EXTENTS_STATS__
+
+/*
+ * If CHECK_BINSEARCH is defined, then the results of the binary search
+ * will also be checked by linear search.
+ */
+#define CHECK_BINSEARCH__
+
+/*
+ * If EXT_DEBUG is defined you can use the 'extdebug' mount option
+ * to get lots of info about what's going on.
+ */
+#define EXT_DEBUG__
+#ifdef EXT_DEBUG
+#define ext_debug(a...)		printk(a)
+#else
+#define ext_debug(a...)
+#endif
+
+/*
+ * If EXT_STATS is defined then stats numbers are collected.
+ * These number will be displayed at umount time.
+ */
+#define EXT_STATS_
+
+
+/*
+ * ext4_inode has i_block array (60 bytes total).
+ * The first 12 bytes store ext4_extent_header;
+ * the remainder stores an array of ext4_extent.
+ */
+
+/*
+ * This is the extent on-disk structure.
+ * It's used at the bottom of the tree.
+ */
+struct ext4_extent {
+	__le32	ee_block;	/* first logical block extent covers */
+	__le16	ee_len;		/* number of blocks covered by extent */
+	__le16	ee_start_hi;	/* high 16 bits of physical block */
+	__le32	ee_start;	/* low 32 bits of physical block */
+};
+
+/*
+ * This is index on-disk structure.
+ * It's used at all the levels except the bottom.
+ */
+struct ext4_extent_idx {
+	__le32	ei_block;	/* index covers logical blocks from 'block' */
+	__le32	ei_leaf;	/* pointer to the physical block of the next *
+				 * level. leaf or next index could be there */
+	__le16	ei_leaf_hi;	/* high 16 bits of physical block */
+	__u16	ei_unused;
+};
+
+/*
+ * Each block (leaves and indexes), even inode-stored has header.
+ */
+struct ext4_extent_header {
+	__le16	eh_magic;	/* probably will support different formats */
+	__le16	eh_entries;	/* number of valid entries */
+	__le16	eh_max;		/* capacity of store in entries */
+	__le16	eh_depth;	/* has tree real underlying blocks? */
+	__le32	eh_generation;	/* generation of the tree */
+};
+
+#define EXT4_EXT_MAGIC		cpu_to_le16(0xf30a)
+
+/*
+ * Array of ext4_ext_path contains path to some extent.
+ * Creation/lookup routines use it for traversal/splitting/etc.
+ * Truncate uses it to simulate recursive walking.
+ */
+struct ext4_ext_path {
+	ext4_fsblk_t			p_block;
+	__u16				p_depth;
+	struct ext4_extent		*p_ext;
+	struct ext4_extent_idx		*p_idx;
+	struct ext4_extent_header	*p_hdr;
+	struct buffer_head		*p_bh;
+};
+
+/*
+ * structure for external API
+ */
+
+#define EXT4_EXT_CACHE_NO	0
+#define EXT4_EXT_CACHE_GAP	1
+#define EXT4_EXT_CACHE_EXTENT	2
+
+/*
+ * to be called by ext4_ext_walk_space()
+ * negative retcode - error
+ * positive retcode - signal for ext4_ext_walk_space(), see below
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
+					struct ext4_ext_cache *,
+					void *);
+
+#define EXT_CONTINUE	0
+#define EXT_BREAK	1
+#define EXT_REPEAT	2
+
+
+#define EXT_MAX_BLOCK	0xffffffff
+
+#define EXT_MAX_LEN	((1UL << 15) - 1)
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+	((struct ext4_extent *) (((char *) (__hdr__)) +		\
+				 sizeof(struct ext4_extent_header)))
+#define EXT_FIRST_INDEX(__hdr__) \
+	((struct ext4_extent_idx *) (((char *) (__hdr__)) +	\
+				     sizeof(struct ext4_extent_header)))
+#define EXT_HAS_FREE_INDEX(__path__) \
+        (le16_to_cpu((__path__)->p_hdr->eh_entries) \
+	                             < le16_to_cpu((__path__)->p_hdr->eh_max))
+#define EXT_LAST_EXTENT(__hdr__) \
+	(EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
+#define EXT_LAST_INDEX(__hdr__) \
+	(EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
+#define EXT_MAX_EXTENT(__hdr__) \
+	(EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
+#define EXT_MAX_INDEX(__hdr__) \
+	(EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
+
+static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
+{
+	return (struct ext4_extent_header *) EXT4_I(inode)->i_data;
+}
+
+static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
+{
+	return (struct ext4_extent_header *) bh->b_data;
+}
+
+static inline unsigned short ext_depth(struct inode *inode)
+{
+	return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
+}
+
+static inline void ext4_ext_tree_changed(struct inode *inode)
+{
+	EXT4_I(inode)->i_ext_generation++;
+}
+
+static inline void
+ext4_ext_invalidate_cache(struct inode *inode)
+{
+	EXT4_I(inode)->i_cached_extent.ec_type = EXT4_EXT_CACHE_NO;
+}
+
+extern int ext4_extent_tree_init(handle_t *, struct inode *);
+extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
+extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
+extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
+extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
+
+#endif /* _LINUX_EXT4_EXTENTS */
+
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h
new file mode 100644
index 0000000..bb42379
--- /dev/null
+++ b/include/linux/ext4_fs_i.h
@@ -0,0 +1,158 @@
+/*
+ *  linux/include/linux/ext4_fs_i.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/include/linux/minix_fs_i.h
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT4_FS_I
+#define _LINUX_EXT4_FS_I
+
+#include <linux/rwsem.h>
+#include <linux/rbtree.h>
+#include <linux/seqlock.h>
+#include <linux/mutex.h>
+
+/* data type for block offset of block group */
+typedef int ext4_grpblk_t;
+
+/* data type for filesystem-wide blocks number */
+typedef unsigned long long ext4_fsblk_t;
+
+struct ext4_reserve_window {
+	ext4_fsblk_t	_rsv_start;	/* First byte reserved */
+	ext4_fsblk_t	_rsv_end;	/* Last byte reserved or 0 */
+};
+
+struct ext4_reserve_window_node {
+	struct rb_node		rsv_node;
+	__u32			rsv_goal_size;
+	__u32			rsv_alloc_hit;
+	struct ext4_reserve_window	rsv_window;
+};
+
+struct ext4_block_alloc_info {
+	/* information about reservation window */
+	struct ext4_reserve_window_node	rsv_window_node;
+	/*
+	 * was i_next_alloc_block in ext4_inode_info
+	 * is the logical (file-relative) number of the
+	 * most-recently-allocated block in this file.
+	 * We use this for detecting linearly ascending allocation requests.
+	 */
+	__u32                   last_alloc_logical_block;
+	/*
+	 * Was i_next_alloc_goal in ext4_inode_info
+	 * is the *physical* companion to i_next_alloc_block.
+	 * it the the physical block number of the block which was most-recentl
+	 * allocated to this file.  This give us the goal (target) for the next
+	 * allocation when we detect linearly ascending requests.
+	 */
+	ext4_fsblk_t		last_alloc_physical_block;
+};
+
+#define rsv_start rsv_window._rsv_start
+#define rsv_end rsv_window._rsv_end
+
+/*
+ * storage for cached extent
+ */
+struct ext4_ext_cache {
+	ext4_fsblk_t	ec_start;
+	__u32		ec_block;
+	__u32		ec_len; /* must be 32bit to return holes */
+	__u32		ec_type;
+};
+
+/*
+ * third extended file system inode data in memory
+ */
+struct ext4_inode_info {
+	__le32	i_data[15];	/* unconverted */
+	__u32	i_flags;
+#ifdef EXT4_FRAGMENTS
+	__u32	i_faddr;
+	__u8	i_frag_no;
+	__u8	i_frag_size;
+#endif
+	ext4_fsblk_t	i_file_acl;
+	__u32	i_dir_acl;
+	__u32	i_dtime;
+
+	/*
+	 * i_block_group is the number of the block group which contains
+	 * this file's inode.  Constant across the lifetime of the inode,
+	 * it is ued for making block allocation decisions - we try to
+	 * place a file's data blocks near its inode block, and new inodes
+	 * near to their parent directory's inode.
+	 */
+	__u32	i_block_group;
+	__u32	i_state;		/* Dynamic state flags for ext4 */
+
+	/* block reservation info */
+	struct ext4_block_alloc_info *i_block_alloc_info;
+
+	__u32	i_dir_start_lookup;
+#ifdef CONFIG_EXT4DEV_FS_XATTR
+	/*
+	 * Extended attributes can be read independently of the main file
+	 * data. Taking i_mutex even when reading would cause contention
+	 * between readers of EAs and writers of regular file data, so
+	 * instead we synchronize on xattr_sem when reading or changing
+	 * EAs.
+	 */
+	struct rw_semaphore xattr_sem;
+#endif
+#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+	struct posix_acl	*i_acl;
+	struct posix_acl	*i_default_acl;
+#endif
+
+	struct list_head i_orphan;	/* unlinked but open inodes */
+
+	/*
+	 * i_disksize keeps track of what the inode size is ON DISK, not
+	 * in memory.  During truncate, i_size is set to the new size by
+	 * the VFS prior to calling ext4_truncate(), but the filesystem won't
+	 * set i_disksize to 0 until the truncate is actually under way.
+	 *
+	 * The intent is that i_disksize always represents the blocks which
+	 * are used by this file.  This allows recovery to restart truncate
+	 * on orphans if we crash during truncate.  We actually write i_disksize
+	 * into the on-disk inode when writing inodes out, instead of i_size.
+	 *
+	 * The only time when i_disksize and i_size may be different is when
+	 * a truncate is in progress.  The only things which change i_disksize
+	 * are ext4_get_block (growth) and ext4_truncate (shrinkth).
+	 */
+	loff_t	i_disksize;
+
+	/* on-disk additional length */
+	__u16 i_extra_isize;
+
+	/*
+	 * truncate_mutex is for serialising ext4_truncate() against
+	 * ext4_getblock().  In the 2.4 ext2 design, great chunks of inode's
+	 * data tree are chopped off during truncate. We can't do that in
+	 * ext4 because whenever we perform intermediate commits during
+	 * truncate, the inode and all the metadata blocks *must* be in a
+	 * consistent state which allows truncation of the orphans to restart
+	 * during recovery.  Hence we must fix the get_block-vs-truncate race
+	 * by other means, so we have truncate_mutex.
+	 */
+	struct mutex truncate_mutex;
+	struct inode vfs_inode;
+
+	unsigned long i_ext_generation;
+	struct ext4_ext_cache i_cached_extent;
+};
+
+#endif	/* _LINUX_EXT4_FS_I */
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
new file mode 100644
index 0000000..691a713
--- /dev/null
+++ b/include/linux/ext4_fs_sb.h
@@ -0,0 +1,94 @@
+/*
+ *  linux/include/linux/ext4_fs_sb.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/include/linux/minix_fs_sb.h
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT4_FS_SB
+#define _LINUX_EXT4_FS_SB
+
+#ifdef __KERNEL__
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/blockgroup_lock.h>
+#include <linux/percpu_counter.h>
+#endif
+#include <linux/rbtree.h>
+
+/*
+ * third extended-fs super-block data in memory
+ */
+struct ext4_sb_info {
+	unsigned long s_frag_size;	/* Size of a fragment in bytes */
+	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
+	unsigned long s_frags_per_block;/* Number of fragments per block */
+	unsigned long s_inodes_per_block;/* Number of inodes per block */
+	unsigned long s_frags_per_group;/* Number of fragments in a group */
+	unsigned long s_blocks_per_group;/* Number of blocks in a group */
+	unsigned long s_inodes_per_group;/* Number of inodes in a group */
+	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
+	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
+	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
+	unsigned long s_groups_count;	/* Number of groups in the fs */
+	struct buffer_head * s_sbh;	/* Buffer containing the super block */
+	struct ext4_super_block * s_es;	/* Pointer to the super block in the buffer */
+	struct buffer_head ** s_group_desc;
+	unsigned long  s_mount_opt;
+	uid_t s_resuid;
+	gid_t s_resgid;
+	unsigned short s_mount_state;
+	unsigned short s_pad;
+	int s_addr_per_block_bits;
+	int s_desc_per_block_bits;
+	int s_inode_size;
+	int s_first_ino;
+	spinlock_t s_next_gen_lock;
+	u32 s_next_generation;
+	u32 s_hash_seed[4];
+	int s_def_hash_version;
+	struct percpu_counter s_freeblocks_counter;
+	struct percpu_counter s_freeinodes_counter;
+	struct percpu_counter s_dirs_counter;
+	struct blockgroup_lock s_blockgroup_lock;
+
+	/* root of the per fs reservation window tree */
+	spinlock_t s_rsv_window_lock;
+	struct rb_root s_rsv_window_root;
+	struct ext4_reserve_window_node s_rsv_window_head;
+
+	/* Journaling */
+	struct inode * s_journal_inode;
+	struct journal_s * s_journal;
+	struct list_head s_orphan;
+	unsigned long s_commit_interval;
+	struct block_device *journal_bdev;
+#ifdef CONFIG_JBD_DEBUG
+	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
+	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
+#endif
+#ifdef CONFIG_QUOTA
+	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
+	int s_jquota_fmt;			/* Format of quota to use */
+#endif
+
+#ifdef EXTENTS_STATS
+	/* ext4 extents stats */
+	unsigned long s_ext_min;
+	unsigned long s_ext_max;
+	unsigned long s_depth_max;
+	spinlock_t s_ext_stats_lock;
+	unsigned long s_ext_blocks;
+	unsigned long s_ext_extents;
+#endif
+};
+
+#endif	/* _LINUX_EXT4_FS_SB */
diff --git a/include/linux/ext4_jbd2.h b/include/linux/ext4_jbd2.h
new file mode 100644
index 0000000..72dd631
--- /dev/null
+++ b/include/linux/ext4_jbd2.h
@@ -0,0 +1,273 @@
+/*
+ * linux/include/linux/ext4_jbd2.h
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
+ *
+ * Copyright 1998--1999 Red Hat corp --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Ext4-specific journaling extensions.
+ */
+
+#ifndef _LINUX_EXT4_JBD_H
+#define _LINUX_EXT4_JBD_H
+
+#include <linux/fs.h>
+#include <linux/jbd2.h>
+#include <linux/ext4_fs.h>
+
+#define EXT4_JOURNAL(inode)	(EXT4_SB((inode)->i_sb)->s_journal)
+
+/* Define the number of blocks we need to account to a transaction to
+ * modify one block of data.
+ *
+ * We may have to touch one inode, one bitmap buffer, up to three
+ * indirection blocks, the group and superblock summaries, and the data
+ * block to complete the transaction.
+ *
+ * For extents-enabled fs we may have to allocate and modify up to
+ * 5 levels of tree + root which are stored in the inode. */
+
+#define EXT4_SINGLEDATA_TRANS_BLOCKS(sb)				\
+	(EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)	\
+		|| test_opt(sb, EXTENTS) ? 27U : 8U)
+
+/* Extended attribute operations touch at most two data buffers,
+ * two bitmap buffers, and two group summaries, in addition to the inode
+ * and the superblock, which are already accounted for. */
+
+#define EXT4_XATTR_TRANS_BLOCKS		6U
+
+/* Define the minimum size for a transaction which modifies data.  This
+ * needs to take into account the fact that we may end up modifying two
+ * quota files too (one for the group, one for the user quota).  The
+ * superblock only gets updated once, of course, so don't bother
+ * counting that again for the quota updates. */
+
+#define EXT4_DATA_TRANS_BLOCKS(sb)	(EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \
+					 EXT4_XATTR_TRANS_BLOCKS - 2 + \
+					 2*EXT4_QUOTA_TRANS_BLOCKS(sb))
+
+/* Delete operations potentially hit one directory's namespace plus an
+ * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
+ * generous.  We can grow the delete transaction later if necessary. */
+
+#define EXT4_DELETE_TRANS_BLOCKS(sb)	(2 * EXT4_DATA_TRANS_BLOCKS(sb) + 64)
+
+/* Define an arbitrary limit for the amount of data we will anticipate
+ * writing to any given transaction.  For unbounded transactions such as
+ * write(2) and truncate(2) we can write more than this, but we always
+ * start off at the maximum transaction size and grow the transaction
+ * optimistically as we go. */
+
+#define EXT4_MAX_TRANS_DATA		64U
+
+/* We break up a large truncate or write transaction once the handle's
+ * buffer credits gets this low, we need either to extend the
+ * transaction or to start a new one.  Reserve enough space here for
+ * inode, bitmap, superblock, group and indirection updates for at least
+ * one block, plus two quota updates.  Quota allocations are not
+ * needed. */
+
+#define EXT4_RESERVE_TRANS_BLOCKS	12U
+
+#define EXT4_INDEX_EXTRA_TRANS_BLOCKS	8
+
+#ifdef CONFIG_QUOTA
+/* Amount of blocks needed for quota update - we know that the structure was
+ * allocated so we need to update only inode+data */
+#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
+/* Amount of blocks needed for quota insert/delete - we do some block writes
+ * but inode, sb and group updates are done only once */
+#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
+		(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
+#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
+		(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)
+#else
+#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
+#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
+#define EXT4_QUOTA_DEL_BLOCKS(sb) 0
+#endif
+
+int
+ext4_mark_iloc_dirty(handle_t *handle,
+		     struct inode *inode,
+		     struct ext4_iloc *iloc);
+
+/*
+ * On success, We end up with an outstanding reference count against
+ * iloc->bh.  This _must_ be cleaned up later.
+ */
+
+int ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
+			struct ext4_iloc *iloc);
+
+int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
+
+/*
+ * Wrapper functions with which ext4 calls into JBD.  The intent here is
+ * to allow these to be turned into appropriate stubs so ext4 can control
+ * ext2 filesystems, so ext2+ext4 systems only nee one fs.  This work hasn't
+ * been done yet.
+ */
+
+void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+		struct buffer_head *bh, handle_t *handle, int err);
+
+static inline int
+__ext4_journal_get_undo_access(const char *where, handle_t *handle,
+				struct buffer_head *bh)
+{
+	int err = jbd2_journal_get_undo_access(handle, bh);
+	if (err)
+		ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+	return err;
+}
+
+static inline int
+__ext4_journal_get_write_access(const char *where, handle_t *handle,
+				struct buffer_head *bh)
+{
+	int err = jbd2_journal_get_write_access(handle, bh);
+	if (err)
+		ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+	return err;
+}
+
+static inline void
+ext4_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
+{
+	jbd2_journal_release_buffer(handle, bh);
+}
+
+static inline int
+__ext4_journal_forget(const char *where, handle_t *handle, struct buffer_head *bh)
+{
+	int err = jbd2_journal_forget(handle, bh);
+	if (err)
+		ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+	return err;
+}
+
+static inline int
+__ext4_journal_revoke(const char *where, handle_t *handle,
+		      ext4_fsblk_t blocknr, struct buffer_head *bh)
+{
+	int err = jbd2_journal_revoke(handle, blocknr, bh);
+	if (err)
+		ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+	return err;
+}
+
+static inline int
+__ext4_journal_get_create_access(const char *where,
+				 handle_t *handle, struct buffer_head *bh)
+{
+	int err = jbd2_journal_get_create_access(handle, bh);
+	if (err)
+		ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+	return err;
+}
+
+static inline int
+__ext4_journal_dirty_metadata(const char *where,
+			      handle_t *handle, struct buffer_head *bh)
+{
+	int err = jbd2_journal_dirty_metadata(handle, bh);
+	if (err)
+		ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+	return err;
+}
+
+
+#define ext4_journal_get_undo_access(handle, bh) \
+	__ext4_journal_get_undo_access(__FUNCTION__, (handle), (bh))
+#define ext4_journal_get_write_access(handle, bh) \
+	__ext4_journal_get_write_access(__FUNCTION__, (handle), (bh))
+#define ext4_journal_revoke(handle, blocknr, bh) \
+	__ext4_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
+#define ext4_journal_get_create_access(handle, bh) \
+	__ext4_journal_get_create_access(__FUNCTION__, (handle), (bh))
+#define ext4_journal_dirty_metadata(handle, bh) \
+	__ext4_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
+#define ext4_journal_forget(handle, bh) \
+	__ext4_journal_forget(__FUNCTION__, (handle), (bh))
+
+int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
+
+handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
+int __ext4_journal_stop(const char *where, handle_t *handle);
+
+static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks)
+{
+	return ext4_journal_start_sb(inode->i_sb, nblocks);
+}
+
+#define ext4_journal_stop(handle) \
+	__ext4_journal_stop(__FUNCTION__, (handle))
+
+static inline handle_t *ext4_journal_current_handle(void)
+{
+	return journal_current_handle();
+}
+
+static inline int ext4_journal_extend(handle_t *handle, int nblocks)
+{
+	return jbd2_journal_extend(handle, nblocks);
+}
+
+static inline int ext4_journal_restart(handle_t *handle, int nblocks)
+{
+	return jbd2_journal_restart(handle, nblocks);
+}
+
+static inline int ext4_journal_blocks_per_page(struct inode *inode)
+{
+	return jbd2_journal_blocks_per_page(inode);
+}
+
+static inline int ext4_journal_force_commit(journal_t *journal)
+{
+	return jbd2_journal_force_commit(journal);
+}
+
+/* super.c */
+int ext4_force_commit(struct super_block *sb);
+
+static inline int ext4_should_journal_data(struct inode *inode)
+{
+	if (!S_ISREG(inode->i_mode))
+		return 1;
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+		return 1;
+	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+		return 1;
+	return 0;
+}
+
+static inline int ext4_should_order_data(struct inode *inode)
+{
+	if (!S_ISREG(inode->i_mode))
+		return 0;
+	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+		return 0;
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+		return 1;
+	return 0;
+}
+
+static inline int ext4_should_writeback_data(struct inode *inode)
+{
+	if (!S_ISREG(inode->i_mode))
+		return 0;
+	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+		return 0;
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+		return 1;
+	return 0;
+}
+
+#endif	/* _LINUX_EXT4_JBD_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 34406ed..2fe6e3f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -623,6 +623,9 @@
 	I_MUTEX_QUOTA
 };
 
+extern void inode_double_lock(struct inode *inode1, struct inode *inode2);
+extern void inode_double_unlock(struct inode *inode1, struct inode *inode2);
+
 /*
  * NOTE: in a 32bit arch with a preemptable kernel and
  * an UP compile the i_size_read/write must be atomic
@@ -656,7 +659,11 @@
 #endif
 }
 
-
+/*
+ * NOTE: unlike i_size_read(), i_size_write() does need locking around it
+ * (normally i_mutex), otherwise on 32bit/SMP an update of i_size_seqcount
+ * can be lost, resulting in subsequent i_size_read() calls spinning forever.
+ */
 static inline void i_size_write(struct inode *inode, loff_t i_size)
 {
 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
@@ -1705,6 +1712,8 @@
 extern void clear_inode(struct inode *);
 extern void destroy_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
+extern int __remove_suid(struct dentry *, int);
+extern int should_remove_suid(struct dentry *);
 extern int remove_suid(struct dentry *);
 extern void remove_dquot_ref(struct super_block *, int, struct list_head *);
 
@@ -1751,6 +1760,8 @@
 		struct pipe_inode_info *, size_t, unsigned int);
 extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
 		struct file *, loff_t *, size_t, unsigned int);
+extern ssize_t generic_file_splice_write_nolock(struct pipe_inode_info *,
+		struct file *, loff_t *, size_t, unsigned int);
 extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
 		struct file *out, loff_t *, size_t len, unsigned int flags);
 extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
index 945ba1a..acbdae6 100644
--- a/include/linux/hiddev.h
+++ b/include/linux/hiddev.h
@@ -222,7 +222,7 @@
 int hiddev_connect(struct hid_device *);
 void hiddev_disconnect(struct hid_device *);
 void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
-		      struct hid_usage *usage, __s32 value, struct pt_regs *regs);
+		      struct hid_usage *usage, __s32 value);
 void hiddev_report_event(struct hid_device *hid, struct hid_report *report);
 int __init hiddev_init(void);
 void hiddev_exit(void);
@@ -230,7 +230,7 @@
 static inline int hiddev_connect(struct hid_device *hid) { return -1; }
 static inline void hiddev_disconnect(struct hid_device *hid) { }
 static inline void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
-		      struct hid_usage *usage, __s32 value, struct pt_regs *regs) { }
+		      struct hid_usage *usage, __s32 value) { }
 static inline void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { }
 static inline int hiddev_init(void) { return 0; }
 static inline void hiddev_exit(void) { }
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index c25a38d..5081d27 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -17,6 +17,7 @@
 int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
 int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
 void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
+void __unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
 int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
 int hugetlb_report_meminfo(char *);
 int hugetlb_report_node_meminfo(int, char *);
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 07d8d72..9c20502 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1185,7 +1185,7 @@
 
 extern int ide_spin_wait_hwgroup(ide_drive_t *);
 extern void ide_timer_expiry(unsigned long);
-extern irqreturn_t ide_intr(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t ide_intr(int irq, void *dev_id);
 extern void do_ide_request(request_queue_t *);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index ab27408..35cb385 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -44,7 +44,7 @@
    unsigned char	h_source[ETH_ALEN];	   /* source ether addr	*/
    __be16               h_vlan_proto;              /* Should always be 0x8100 */
    __be16               h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
-   unsigned short	h_vlan_encapsulated_proto; /* packet type ID field (or len) */
+   __be16		h_vlan_encapsulated_proto; /* packet type ID field (or len) */
 };
 
 #include <linux/skbuff.h>
diff --git a/include/linux/input.h b/include/linux/input.h
index 5770105..c38507b 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -953,7 +953,6 @@
 	unsigned int repeat_key;
 	struct timer_list timer;
 
-	struct pt_regs *regs;
 	int state;
 
 	int sync;
@@ -1149,15 +1148,9 @@
 	input_event(dev, EV_SW, code, !!value);
 }
 
-static inline void input_regs(struct input_dev *dev, struct pt_regs *regs)
-{
-	dev->regs = regs;
-}
-
 static inline void input_sync(struct input_dev *dev)
 {
 	input_event(dev, EV_SYN, SYN_REPORT, 0);
-	dev->regs = NULL;
 }
 
 static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 1f97e3d..5b83e7b 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -64,8 +64,10 @@
 #define SA_TRIGGER_RISING	IRQF_TRIGGER_RISING
 #define SA_TRIGGER_MASK		IRQF_TRIGGER_MASK
 
+typedef irqreturn_t (*irq_handler_t)(int, void *);
+
 struct irqaction {
-	irqreturn_t (*handler)(int, void *, struct pt_regs *);
+	irq_handler_t handler;
 	unsigned long flags;
 	cpumask_t mask;
 	const char *name;
@@ -75,9 +77,8 @@
 	struct proc_dir_entry *dir;
 };
 
-extern irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs);
-extern int request_irq(unsigned int,
-		       irqreturn_t (*handler)(int, void *, struct pt_regs *),
+extern irqreturn_t no_action(int cpl, void *dev_id);
+extern int request_irq(unsigned int, irq_handler_t handler,
 		       unsigned long, const char *, void *);
 extern void free_irq(unsigned int, void *);
 
diff --git a/include/linux/io.h b/include/linux/io.h
index aa3f5af..81877ea 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -18,6 +18,7 @@
 #ifndef _LINUX_IO_H
 #define _LINUX_IO_H
 
+#include <linux/types.h>
 #include <asm/io.h>
 #include <asm/page.h>
 
@@ -27,4 +28,31 @@
 int ioremap_page_range(unsigned long addr, unsigned long end,
 		       unsigned long phys_addr, pgprot_t prot);
 
+/**
+ *	check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the mmio address io_addr. This
+ *	address should have been obtained by ioremap.
+ *	Returns 1 on a match.
+ */
+
+static inline int check_signature(const volatile void __iomem *io_addr,
+	const unsigned char *signature, int length)
+{
+	int retval = 0;
+	do {
+		if (readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
 #endif /* _LINUX_IO_H */
diff --git a/include/linux/ioc3.h b/include/linux/ioc3.h
index da7c09e..38b286e9 100644
--- a/include/linux/ioc3.h
+++ b/include/linux/ioc3.h
@@ -63,7 +63,7 @@
 	/* IRQ stuff */
 	unsigned int irq_mask;	/* IOC3 IRQ mask, leave clear for Ethernet */
 	int reset_mask;		/* non-zero if you want the ioc3.c module to reset interrupts */
-	int (*intr) (struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int, struct pt_regs *);
+	int (*intr) (struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
 	/* private submodule data */
 	void *data;		/* assigned by submodule */
 };
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
index de73a32..51e2b9f 100644
--- a/include/linux/ioc4.h
+++ b/include/linux/ioc4.h
@@ -157,7 +157,7 @@
 	unsigned long idd_bar0;
 	struct pci_dev *idd_pdev;
 	const struct pci_device_id *idd_pci_id;
-	struct __iomem ioc4_misc_regs *idd_misc_regs;
+	struct ioc4_misc_regs __iomem *idd_misc_regs;
 	unsigned long count_period;
 	void *idd_serial_data;
 	unsigned int idd_variant;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 6f46360..52fc405 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -21,6 +21,12 @@
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
+#include <asm/irq_regs.h>
+
+struct irq_desc;
+typedef	void fastcall (*irq_flow_handler_t)(unsigned int irq,
+					    struct irq_desc *desc);
+
 
 /*
  * IRQ line status.
@@ -135,13 +141,12 @@
  * @pending_mask:	pending rebalanced interrupts
  * @dir:		/proc/irq/ procfs entry
  * @affinity_entry:	/proc/irq/smp_affinity procfs entry on SMP
+ * @name:		flow handler name for /proc/interrupts output
  *
  * Pad this out to 32 bytes for cache and indexing reasons.
  */
 struct irq_desc {
-	void fastcall		(*handle_irq)(unsigned int irq,
-					      struct irq_desc *desc,
-					      struct pt_regs *regs);
+	irq_flow_handler_t	handle_irq;
 	struct irq_chip		*chip;
 	void			*handler_data;
 	void			*chip_data;
@@ -161,8 +166,9 @@
 	cpumask_t		pending_mask;
 #endif
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *dir;
+	struct proc_dir_entry	*dir;
 #endif
+	const char		*name;
 } ____cacheline_aligned;
 
 extern struct irq_desc irq_desc[NR_IRQS];
@@ -254,43 +260,25 @@
 extern int no_irq_affinity;
 
 /* Handle irq action chains: */
-extern int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
-			    struct irqaction *action);
+extern int handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
 /*
  * Built-in IRQ handlers for various IRQ types,
  * callable via desc->chip->handle_irq()
  */
-extern void fastcall
-handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs);
-extern void fastcall
-handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc,
-			 struct pt_regs *regs);
-extern void fastcall
-handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs);
-extern void fastcall
-handle_simple_irq(unsigned int irq, struct irq_desc *desc,
-		  struct pt_regs *regs);
-extern void fastcall
-handle_percpu_irq(unsigned int irq, struct irq_desc *desc,
-		  struct pt_regs *regs);
-extern void fastcall
-handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs);
-
-/*
- * Get a descriptive string for the highlevel handler, for
- * /proc/interrupts output:
- */
-extern const char *
-handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *,
-					struct pt_regs *));
+extern void fastcall handle_level_irq(unsigned int irq, struct irq_desc *desc);
+extern void fastcall handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc);
+extern void fastcall handle_edge_irq(unsigned int irq, struct irq_desc *desc);
+extern void fastcall handle_simple_irq(unsigned int irq, struct irq_desc *desc);
+extern void fastcall handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
+extern void fastcall handle_bad_irq(unsigned int irq, struct irq_desc *desc);
 
 /*
  * Monolithic do_IRQ implementation.
  * (is an explicit fastcall, because i386 4KSTACKS calls it from assembly)
  */
 #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
+extern fastcall unsigned int __do_IRQ(unsigned int irq);
 #endif
 
 /*
@@ -299,23 +287,23 @@
  * irqchip-style controller then we call the ->handle_irq() handler,
  * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
  */
-static inline void generic_handle_irq(unsigned int irq, struct pt_regs *regs)
+static inline void generic_handle_irq(unsigned int irq)
 {
 	struct irq_desc *desc = irq_desc + irq;
 
 #ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-	desc->handle_irq(irq, desc, regs);
+	desc->handle_irq(irq, desc);
 #else
 	if (likely(desc->handle_irq))
-		desc->handle_irq(irq, desc, regs);
+		desc->handle_irq(irq, desc);
 	else
-		__do_IRQ(irq, regs);
+		__do_IRQ(irq);
 #endif
 }
 
 /* Handling of unhandled and spurious interrupts: */
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
-			   int action_ret, struct pt_regs *regs);
+			   int action_ret);
 
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
@@ -335,24 +323,22 @@
 
 extern void
 set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
-			 void fastcall (*handle)(unsigned int,
-						 struct irq_desc *,
-						 struct pt_regs *));
+			 irq_flow_handler_t handle);
 extern void
-__set_irq_handler(unsigned int irq,
-		  void fastcall (*handle)(unsigned int, struct irq_desc *,
-					  struct pt_regs *),
-		  int is_chained);
+set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
+			      irq_flow_handler_t handle, const char *name);
+
+extern void
+__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+		  const char *name);
 
 /*
  * Set a highlevel flow handler for a given IRQ:
  */
 static inline void
-set_irq_handler(unsigned int irq,
-		void fastcall (*handle)(unsigned int, struct irq_desc *,
-					struct pt_regs *))
+set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
 {
-	__set_irq_handler(irq, handle, 0);
+	__set_irq_handler(irq, handle, 0, NULL);
 }
 
 /*
@@ -362,10 +348,9 @@
  */
 static inline void
 set_irq_chained_handler(unsigned int irq,
-			void fastcall (*handle)(unsigned int, struct irq_desc *,
-						struct pt_regs *))
+			irq_flow_handler_t handle)
 {
-	__set_irq_handler(irq, handle, 1);
+	__set_irq_handler(irq, handle, 1, NULL);
 }
 
 /* Handle dynamic irq creation and destruction */
diff --git a/include/linux/istallion.h b/include/linux/istallion.h
index 1f99662..b55e2a0 100644
--- a/include/linux/istallion.h
+++ b/include/linux/istallion.h
@@ -100,7 +100,7 @@
 	unsigned int	iobase;
 	int		iosize;
 	unsigned long	memaddr;
-	void		*membase;
+	void		__iomem *membase;
 	int		memsize;
 	int		pagesize;
 	int		hostoffset;
@@ -113,7 +113,7 @@
 	void		(*enable)(struct stlibrd *brdp);
 	void		(*reenable)(struct stlibrd *brdp);
 	void		(*disable)(struct stlibrd *brdp);
-	char		*(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
+	void		__iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
 	void		(*intr)(struct stlibrd *brdp);
 	void		(*reset)(struct stlibrd *brdp);
 	stliport_t	*ports[STL_MAXPORTS];
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
new file mode 100644
index 0000000..ddb1287
--- /dev/null
+++ b/include/linux/jbd2.h
@@ -0,0 +1,1107 @@
+/*
+ * linux/include/linux/jbd2.h
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>
+ *
+ * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Definitions for transaction data structures for the buffer cache
+ * filesystem journaling support.
+ */
+
+#ifndef _LINUX_JBD_H
+#define _LINUX_JBD_H
+
+/* Allow this file to be included directly into e2fsprogs */
+#ifndef __KERNEL__
+#include "jfs_compat.h"
+#define JBD2_DEBUG
+#define jfs_debug jbd_debug
+#else
+
+#include <linux/types.h>
+#include <linux/buffer_head.h>
+#include <linux/journal-head.h>
+#include <linux/stddef.h>
+#include <linux/bit_spinlock.h>
+#include <linux/mutex.h>
+#include <linux/timer.h>
+
+#include <asm/semaphore.h>
+#endif
+
+#define journal_oom_retry 1
+
+/*
+ * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds
+ * certain classes of error which can occur due to failed IOs.  Under
+ * normal use we want ext3 to continue after such errors, because
+ * hardware _can_ fail, but for debugging purposes when running tests on
+ * known-good hardware we may want to trap these errors.
+ */
+#undef JBD_PARANOID_IOFAIL
+
+/*
+ * The default maximum commit age, in seconds.
+ */
+#define JBD_DEFAULT_MAX_COMMIT_AGE 5
+
+#ifdef CONFIG_JBD_DEBUG
+/*
+ * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal
+ * consistency checks.  By default we don't do this unless
+ * CONFIG_JBD_DEBUG is on.
+ */
+#define JBD_EXPENSIVE_CHECKING
+extern int jbd2_journal_enable_debug;
+
+#define jbd_debug(n, f, a...)						\
+	do {								\
+		if ((n) <= jbd2_journal_enable_debug) {			\
+			printk (KERN_DEBUG "(%s, %d): %s: ",		\
+				__FILE__, __LINE__, __FUNCTION__);	\
+			printk (f, ## a);				\
+		}							\
+	} while (0)
+#else
+#define jbd_debug(f, a...)	/**/
+#endif
+
+extern void * __jbd2_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
+extern void * jbd2_slab_alloc(size_t size, gfp_t flags);
+extern void jbd2_slab_free(void *ptr, size_t size);
+
+#define jbd_kmalloc(size, flags) \
+	__jbd2_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
+#define jbd_rep_kmalloc(size, flags) \
+	__jbd2_kmalloc(__FUNCTION__, (size), (flags), 1)
+
+#define JBD2_MIN_JOURNAL_BLOCKS 1024
+
+#ifdef __KERNEL__
+
+/**
+ * typedef handle_t - The handle_t type represents a single atomic update being performed by some process.
+ *
+ * All filesystem modifications made by the process go
+ * through this handle.  Recursive operations (such as quota operations)
+ * are gathered into a single update.
+ *
+ * The buffer credits field is used to account for journaled buffers
+ * being modified by the running process.  To ensure that there is
+ * enough log space for all outstanding operations, we need to limit the
+ * number of outstanding buffers possible at any time.  When the
+ * operation completes, any buffer credits not used are credited back to
+ * the transaction, so that at all times we know how many buffers the
+ * outstanding updates on a transaction might possibly touch.
+ *
+ * This is an opaque datatype.
+ **/
+typedef struct handle_s		handle_t;	/* Atomic operation type */
+
+
+/**
+ * typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem.
+ *
+ * journal_t is linked to from the fs superblock structure.
+ *
+ * We use the journal_t to keep track of all outstanding transaction
+ * activity on the filesystem, and to manage the state of the log
+ * writing process.
+ *
+ * This is an opaque datatype.
+ **/
+typedef struct journal_s	journal_t;	/* Journal control structure */
+#endif
+
+/*
+ * Internal structures used by the logging mechanism:
+ */
+
+#define JBD2_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
+
+/*
+ * On-disk structures
+ */
+
+/*
+ * Descriptor block types:
+ */
+
+#define JBD2_DESCRIPTOR_BLOCK	1
+#define JBD2_COMMIT_BLOCK	2
+#define JBD2_SUPERBLOCK_V1	3
+#define JBD2_SUPERBLOCK_V2	4
+#define JBD2_REVOKE_BLOCK	5
+
+/*
+ * Standard header for all descriptor blocks:
+ */
+typedef struct journal_header_s
+{
+	__be32		h_magic;
+	__be32		h_blocktype;
+	__be32		h_sequence;
+} journal_header_t;
+
+
+/*
+ * The block tag: used to describe a single buffer in the journal.
+ * t_blocknr_high is only used if INCOMPAT_64BIT is set, so this
+ * raw struct shouldn't be used for pointer math or sizeof() - use
+ * journal_tag_bytes(journal) instead to compute this.
+ */
+typedef struct journal_block_tag_s
+{
+	__be32		t_blocknr;	/* The on-disk block number */
+	__be32		t_flags;	/* See below */
+	__be32		t_blocknr_high; /* most-significant high 32bits. */
+} journal_block_tag_t;
+
+#define JBD_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high))
+#define JBD_TAG_SIZE64 (sizeof(journal_block_tag_t))
+
+/*
+ * The revoke descriptor: used on disk to describe a series of blocks to
+ * be revoked from the log
+ */
+typedef struct jbd2_journal_revoke_header_s
+{
+	journal_header_t r_header;
+	__be32		 r_count;	/* Count of bytes used in the block */
+} jbd2_journal_revoke_header_t;
+
+
+/* Definitions for the journal tag flags word: */
+#define JBD2_FLAG_ESCAPE		1	/* on-disk block is escaped */
+#define JBD2_FLAG_SAME_UUID	2	/* block has same uuid as previous */
+#define JBD2_FLAG_DELETED	4	/* block deleted by this transaction */
+#define JBD2_FLAG_LAST_TAG	8	/* last tag in this descriptor block */
+
+
+/*
+ * The journal superblock.  All fields are in big-endian byte order.
+ */
+typedef struct journal_superblock_s
+{
+/* 0x0000 */
+	journal_header_t s_header;
+
+/* 0x000C */
+	/* Static information describing the journal */
+	__be32	s_blocksize;		/* journal device blocksize */
+	__be32	s_maxlen;		/* total blocks in journal file */
+	__be32	s_first;		/* first block of log information */
+
+/* 0x0018 */
+	/* Dynamic information describing the current state of the log */
+	__be32	s_sequence;		/* first commit ID expected in log */
+	__be32	s_start;		/* blocknr of start of log */
+
+/* 0x0020 */
+	/* Error value, as set by jbd2_journal_abort(). */
+	__be32	s_errno;
+
+/* 0x0024 */
+	/* Remaining fields are only valid in a version-2 superblock */
+	__be32	s_feature_compat;	/* compatible feature set */
+	__be32	s_feature_incompat;	/* incompatible feature set */
+	__be32	s_feature_ro_compat;	/* readonly-compatible feature set */
+/* 0x0030 */
+	__u8	s_uuid[16];		/* 128-bit uuid for journal */
+
+/* 0x0040 */
+	__be32	s_nr_users;		/* Nr of filesystems sharing log */
+
+	__be32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/
+
+/* 0x0048 */
+	__be32	s_max_transaction;	/* Limit of journal blocks per trans.*/
+	__be32	s_max_trans_data;	/* Limit of data blocks per trans. */
+
+/* 0x0050 */
+	__u32	s_padding[44];
+
+/* 0x0100 */
+	__u8	s_users[16*48];		/* ids of all fs'es sharing the log */
+/* 0x0400 */
+} journal_superblock_t;
+
+#define JBD2_HAS_COMPAT_FEATURE(j,mask)					\
+	((j)->j_format_version >= 2 &&					\
+	 ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask))))
+#define JBD2_HAS_RO_COMPAT_FEATURE(j,mask)				\
+	((j)->j_format_version >= 2 &&					\
+	 ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask))))
+#define JBD2_HAS_INCOMPAT_FEATURE(j,mask)				\
+	((j)->j_format_version >= 2 &&					\
+	 ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
+
+#define JBD2_FEATURE_INCOMPAT_REVOKE	0x00000001
+#define JBD2_FEATURE_INCOMPAT_64BIT	0x00000002
+
+/* Features known to this kernel version: */
+#define JBD2_KNOWN_COMPAT_FEATURES	0
+#define JBD2_KNOWN_ROCOMPAT_FEATURES	0
+#define JBD2_KNOWN_INCOMPAT_FEATURES	(JBD2_FEATURE_INCOMPAT_REVOKE | \
+					 JBD2_FEATURE_INCOMPAT_64BIT)
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/sched.h>
+
+#define JBD_ASSERTIONS
+#ifdef JBD_ASSERTIONS
+#define J_ASSERT(assert)						\
+do {									\
+	if (!(assert)) {						\
+		printk (KERN_EMERG					\
+			"Assertion failure in %s() at %s:%d: \"%s\"\n",	\
+			__FUNCTION__, __FILE__, __LINE__, # assert);	\
+		BUG();							\
+	}								\
+} while (0)
+
+#if defined(CONFIG_BUFFER_DEBUG)
+void buffer_assertion_failure(struct buffer_head *bh);
+#define J_ASSERT_BH(bh, expr)						\
+	do {								\
+		if (!(expr))						\
+			buffer_assertion_failure(bh);			\
+		J_ASSERT(expr);						\
+	} while (0)
+#define J_ASSERT_JH(jh, expr)	J_ASSERT_BH(jh2bh(jh), expr)
+#else
+#define J_ASSERT_BH(bh, expr)	J_ASSERT(expr)
+#define J_ASSERT_JH(jh, expr)	J_ASSERT(expr)
+#endif
+
+#else
+#define J_ASSERT(assert)	do { } while (0)
+#endif		/* JBD_ASSERTIONS */
+
+#if defined(JBD_PARANOID_IOFAIL)
+#define J_EXPECT(expr, why...)		J_ASSERT(expr)
+#define J_EXPECT_BH(bh, expr, why...)	J_ASSERT_BH(bh, expr)
+#define J_EXPECT_JH(jh, expr, why...)	J_ASSERT_JH(jh, expr)
+#else
+#define __journal_expect(expr, why...)					     \
+	({								     \
+		int val = (expr);					     \
+		if (!val) {						     \
+			printk(KERN_ERR					     \
+				"EXT3-fs unexpected failure: %s;\n",# expr); \
+			printk(KERN_ERR why "\n");			     \
+		}							     \
+		val;							     \
+	})
+#define J_EXPECT(expr, why...)		__journal_expect(expr, ## why)
+#define J_EXPECT_BH(bh, expr, why...)	__journal_expect(expr, ## why)
+#define J_EXPECT_JH(jh, expr, why...)	__journal_expect(expr, ## why)
+#endif
+
+enum jbd_state_bits {
+	BH_JBD			/* Has an attached ext3 journal_head */
+	  = BH_PrivateStart,
+	BH_JWrite,		/* Being written to log (@@@ DEBUGGING) */
+	BH_Freed,		/* Has been freed (truncated) */
+	BH_Revoked,		/* Has been revoked from the log */
+	BH_RevokeValid,		/* Revoked flag is valid */
+	BH_JBDDirty,		/* Is dirty but journaled */
+	BH_State,		/* Pins most journal_head state */
+	BH_JournalHead,		/* Pins bh->b_private and jh->b_bh */
+	BH_Unshadow,		/* Dummy bit, for BJ_Shadow wakeup filtering */
+};
+
+BUFFER_FNS(JBD, jbd)
+BUFFER_FNS(JWrite, jwrite)
+BUFFER_FNS(JBDDirty, jbddirty)
+TAS_BUFFER_FNS(JBDDirty, jbddirty)
+BUFFER_FNS(Revoked, revoked)
+TAS_BUFFER_FNS(Revoked, revoked)
+BUFFER_FNS(RevokeValid, revokevalid)
+TAS_BUFFER_FNS(RevokeValid, revokevalid)
+BUFFER_FNS(Freed, freed)
+
+static inline struct buffer_head *jh2bh(struct journal_head *jh)
+{
+	return jh->b_bh;
+}
+
+static inline struct journal_head *bh2jh(struct buffer_head *bh)
+{
+	return bh->b_private;
+}
+
+static inline void jbd_lock_bh_state(struct buffer_head *bh)
+{
+	bit_spin_lock(BH_State, &bh->b_state);
+}
+
+static inline int jbd_trylock_bh_state(struct buffer_head *bh)
+{
+	return bit_spin_trylock(BH_State, &bh->b_state);
+}
+
+static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
+{
+	return bit_spin_is_locked(BH_State, &bh->b_state);
+}
+
+static inline void jbd_unlock_bh_state(struct buffer_head *bh)
+{
+	bit_spin_unlock(BH_State, &bh->b_state);
+}
+
+static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
+{
+	bit_spin_lock(BH_JournalHead, &bh->b_state);
+}
+
+static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
+{
+	bit_spin_unlock(BH_JournalHead, &bh->b_state);
+}
+
+struct jbd2_revoke_table_s;
+
+/**
+ * struct handle_s - The handle_s type is the concrete type associated with
+ *     handle_t.
+ * @h_transaction: Which compound transaction is this update a part of?
+ * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
+ * @h_ref: Reference count on this handle
+ * @h_err: Field for caller's use to track errors through large fs operations
+ * @h_sync: flag for sync-on-close
+ * @h_jdata: flag to force data journaling
+ * @h_aborted: flag indicating fatal error on handle
+ **/
+
+/* Docbook can't yet cope with the bit fields, but will leave the documentation
+ * in so it can be fixed later.
+ */
+
+struct handle_s
+{
+	/* Which compound transaction is this update a part of? */
+	transaction_t		*h_transaction;
+
+	/* Number of remaining buffers we are allowed to dirty: */
+	int			h_buffer_credits;
+
+	/* Reference count on this handle */
+	int			h_ref;
+
+	/* Field for caller's use to track errors through large fs */
+	/* operations */
+	int			h_err;
+
+	/* Flags [no locking] */
+	unsigned int	h_sync:		1;	/* sync-on-close */
+	unsigned int	h_jdata:	1;	/* force data journaling */
+	unsigned int	h_aborted:	1;	/* fatal error on handle */
+};
+
+
+/* The transaction_t type is the guts of the journaling mechanism.  It
+ * tracks a compound transaction through its various states:
+ *
+ * RUNNING:	accepting new updates
+ * LOCKED:	Updates still running but we don't accept new ones
+ * RUNDOWN:	Updates are tidying up but have finished requesting
+ *		new buffers to modify (state not used for now)
+ * FLUSH:       All updates complete, but we are still writing to disk
+ * COMMIT:      All data on disk, writing commit record
+ * FINISHED:	We still have to keep the transaction for checkpointing.
+ *
+ * The transaction keeps track of all of the buffers modified by a
+ * running transaction, and all of the buffers committed but not yet
+ * flushed to home for finished transactions.
+ */
+
+/*
+ * Lock ranking:
+ *
+ *    j_list_lock
+ *      ->jbd_lock_bh_journal_head()	(This is "innermost")
+ *
+ *    j_state_lock
+ *    ->jbd_lock_bh_state()
+ *
+ *    jbd_lock_bh_state()
+ *    ->j_list_lock
+ *
+ *    j_state_lock
+ *    ->t_handle_lock
+ *
+ *    j_state_lock
+ *    ->j_list_lock			(journal_unmap_buffer)
+ *
+ */
+
+struct transaction_s
+{
+	/* Pointer to the journal for this transaction. [no locking] */
+	journal_t		*t_journal;
+
+	/* Sequence number for this transaction [no locking] */
+	tid_t			t_tid;
+
+	/*
+	 * Transaction's current state
+	 * [no locking - only kjournald2 alters this]
+	 * FIXME: needs barriers
+	 * KLUDGE: [use j_state_lock]
+	 */
+	enum {
+		T_RUNNING,
+		T_LOCKED,
+		T_RUNDOWN,
+		T_FLUSH,
+		T_COMMIT,
+		T_FINISHED
+	}			t_state;
+
+	/*
+	 * Where in the log does this transaction's commit start? [no locking]
+	 */
+	unsigned long		t_log_start;
+
+	/* Number of buffers on the t_buffers list [j_list_lock] */
+	int			t_nr_buffers;
+
+	/*
+	 * Doubly-linked circular list of all buffers reserved but not yet
+	 * modified by this transaction [j_list_lock]
+	 */
+	struct journal_head	*t_reserved_list;
+
+	/*
+	 * Doubly-linked circular list of all buffers under writeout during
+	 * commit [j_list_lock]
+	 */
+	struct journal_head	*t_locked_list;
+
+	/*
+	 * Doubly-linked circular list of all metadata buffers owned by this
+	 * transaction [j_list_lock]
+	 */
+	struct journal_head	*t_buffers;
+
+	/*
+	 * Doubly-linked circular list of all data buffers still to be
+	 * flushed before this transaction can be committed [j_list_lock]
+	 */
+	struct journal_head	*t_sync_datalist;
+
+	/*
+	 * Doubly-linked circular list of all forget buffers (superseded
+	 * buffers which we can un-checkpoint once this transaction commits)
+	 * [j_list_lock]
+	 */
+	struct journal_head	*t_forget;
+
+	/*
+	 * Doubly-linked circular list of all buffers still to be flushed before
+	 * this transaction can be checkpointed. [j_list_lock]
+	 */
+	struct journal_head	*t_checkpoint_list;
+
+	/*
+	 * Doubly-linked circular list of all buffers submitted for IO while
+	 * checkpointing. [j_list_lock]
+	 */
+	struct journal_head	*t_checkpoint_io_list;
+
+	/*
+	 * Doubly-linked circular list of temporary buffers currently undergoing
+	 * IO in the log [j_list_lock]
+	 */
+	struct journal_head	*t_iobuf_list;
+
+	/*
+	 * Doubly-linked circular list of metadata buffers being shadowed by log
+	 * IO.  The IO buffers on the iobuf list and the shadow buffers on this
+	 * list match each other one for one at all times. [j_list_lock]
+	 */
+	struct journal_head	*t_shadow_list;
+
+	/*
+	 * Doubly-linked circular list of control buffers being written to the
+	 * log. [j_list_lock]
+	 */
+	struct journal_head	*t_log_list;
+
+	/*
+	 * Protects info related to handles
+	 */
+	spinlock_t		t_handle_lock;
+
+	/*
+	 * Number of outstanding updates running on this transaction
+	 * [t_handle_lock]
+	 */
+	int			t_updates;
+
+	/*
+	 * Number of buffers reserved for use by all handles in this transaction
+	 * handle but not yet modified. [t_handle_lock]
+	 */
+	int			t_outstanding_credits;
+
+	/*
+	 * Forward and backward links for the circular list of all transactions
+	 * awaiting checkpoint. [j_list_lock]
+	 */
+	transaction_t		*t_cpnext, *t_cpprev;
+
+	/*
+	 * When will the transaction expire (become due for commit), in jiffies?
+	 * [no locking]
+	 */
+	unsigned long		t_expires;
+
+	/*
+	 * How many handles used this transaction? [t_handle_lock]
+	 */
+	int t_handle_count;
+
+};
+
+/**
+ * struct journal_s - The journal_s type is the concrete type associated with
+ *     journal_t.
+ * @j_flags:  General journaling state flags
+ * @j_errno:  Is there an outstanding uncleared error on the journal (from a
+ *     prior abort)?
+ * @j_sb_buffer: First part of superblock buffer
+ * @j_superblock: Second part of superblock buffer
+ * @j_format_version: Version of the superblock format
+ * @j_state_lock: Protect the various scalars in the journal
+ * @j_barrier_count:  Number of processes waiting to create a barrier lock
+ * @j_barrier: The barrier lock itself
+ * @j_running_transaction: The current running transaction..
+ * @j_committing_transaction: the transaction we are pushing to disk
+ * @j_checkpoint_transactions: a linked circular list of all transactions
+ *  waiting for checkpointing
+ * @j_wait_transaction_locked: Wait queue for waiting for a locked transaction
+ *  to start committing, or for a barrier lock to be released
+ * @j_wait_logspace: Wait queue for waiting for checkpointing to complete
+ * @j_wait_done_commit: Wait queue for waiting for commit to complete
+ * @j_wait_checkpoint:  Wait queue to trigger checkpointing
+ * @j_wait_commit: Wait queue to trigger commit
+ * @j_wait_updates: Wait queue to wait for updates to complete
+ * @j_checkpoint_mutex: Mutex for locking against concurrent checkpoints
+ * @j_head: Journal head - identifies the first unused block in the journal
+ * @j_tail: Journal tail - identifies the oldest still-used block in the
+ *  journal.
+ * @j_free: Journal free - how many free blocks are there in the journal?
+ * @j_first: The block number of the first usable block
+ * @j_last: The block number one beyond the last usable block
+ * @j_dev: Device where we store the journal
+ * @j_blocksize: blocksize for the location where we store the journal.
+ * @j_blk_offset: starting block offset for into the device where we store the
+ *     journal
+ * @j_fs_dev: Device which holds the client fs.  For internal journal this will
+ *     be equal to j_dev
+ * @j_maxlen: Total maximum capacity of the journal region on disk.
+ * @j_list_lock: Protects the buffer lists and internal buffer state.
+ * @j_inode: Optional inode where we store the journal.  If present, all journal
+ *     block numbers are mapped into this inode via bmap().
+ * @j_tail_sequence:  Sequence number of the oldest transaction in the log
+ * @j_transaction_sequence: Sequence number of the next transaction to grant
+ * @j_commit_sequence: Sequence number of the most recently committed
+ *  transaction
+ * @j_commit_request: Sequence number of the most recent transaction wanting
+ *     commit
+ * @j_uuid: Uuid of client object.
+ * @j_task: Pointer to the current commit thread for this journal
+ * @j_max_transaction_buffers:  Maximum number of metadata buffers to allow in a
+ *     single compound commit transaction
+ * @j_commit_interval: What is the maximum transaction lifetime before we begin
+ *  a commit?
+ * @j_commit_timer:  The timer used to wakeup the commit thread
+ * @j_revoke_lock: Protect the revoke table
+ * @j_revoke: The revoke table - maintains the list of revoked blocks in the
+ *     current transaction.
+ * @j_revoke_table: alternate revoke tables for j_revoke
+ * @j_wbuf: array of buffer_heads for jbd2_journal_commit_transaction
+ * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the
+ *	number that will fit in j_blocksize
+ * @j_last_sync_writer: most recent pid which did a synchronous write
+ * @j_private: An opaque pointer to fs-private information.
+ */
+
+struct journal_s
+{
+	/* General journaling state flags [j_state_lock] */
+	unsigned long		j_flags;
+
+	/*
+	 * Is there an outstanding uncleared error on the journal (from a prior
+	 * abort)? [j_state_lock]
+	 */
+	int			j_errno;
+
+	/* The superblock buffer */
+	struct buffer_head	*j_sb_buffer;
+	journal_superblock_t	*j_superblock;
+
+	/* Version of the superblock format */
+	int			j_format_version;
+
+	/*
+	 * Protect the various scalars in the journal
+	 */
+	spinlock_t		j_state_lock;
+
+	/*
+	 * Number of processes waiting to create a barrier lock [j_state_lock]
+	 */
+	int			j_barrier_count;
+
+	/* The barrier lock itself */
+	struct mutex		j_barrier;
+
+	/*
+	 * Transactions: The current running transaction...
+	 * [j_state_lock] [caller holding open handle]
+	 */
+	transaction_t		*j_running_transaction;
+
+	/*
+	 * the transaction we are pushing to disk
+	 * [j_state_lock] [caller holding open handle]
+	 */
+	transaction_t		*j_committing_transaction;
+
+	/*
+	 * ... and a linked circular list of all transactions waiting for
+	 * checkpointing. [j_list_lock]
+	 */
+	transaction_t		*j_checkpoint_transactions;
+
+	/*
+	 * Wait queue for waiting for a locked transaction to start committing,
+	 * or for a barrier lock to be released
+	 */
+	wait_queue_head_t	j_wait_transaction_locked;
+
+	/* Wait queue for waiting for checkpointing to complete */
+	wait_queue_head_t	j_wait_logspace;
+
+	/* Wait queue for waiting for commit to complete */
+	wait_queue_head_t	j_wait_done_commit;
+
+	/* Wait queue to trigger checkpointing */
+	wait_queue_head_t	j_wait_checkpoint;
+
+	/* Wait queue to trigger commit */
+	wait_queue_head_t	j_wait_commit;
+
+	/* Wait queue to wait for updates to complete */
+	wait_queue_head_t	j_wait_updates;
+
+	/* Semaphore for locking against concurrent checkpoints */
+	struct mutex		j_checkpoint_mutex;
+
+	/*
+	 * Journal head: identifies the first unused block in the journal.
+	 * [j_state_lock]
+	 */
+	unsigned long		j_head;
+
+	/*
+	 * Journal tail: identifies the oldest still-used block in the journal.
+	 * [j_state_lock]
+	 */
+	unsigned long		j_tail;
+
+	/*
+	 * Journal free: how many free blocks are there in the journal?
+	 * [j_state_lock]
+	 */
+	unsigned long		j_free;
+
+	/*
+	 * Journal start and end: the block numbers of the first usable block
+	 * and one beyond the last usable block in the journal. [j_state_lock]
+	 */
+	unsigned long		j_first;
+	unsigned long		j_last;
+
+	/*
+	 * Device, blocksize and starting block offset for the location where we
+	 * store the journal.
+	 */
+	struct block_device	*j_dev;
+	int			j_blocksize;
+	unsigned long long		j_blk_offset;
+
+	/*
+	 * Device which holds the client fs.  For internal journal this will be
+	 * equal to j_dev.
+	 */
+	struct block_device	*j_fs_dev;
+
+	/* Total maximum capacity of the journal region on disk. */
+	unsigned int		j_maxlen;
+
+	/*
+	 * Protects the buffer lists and internal buffer state.
+	 */
+	spinlock_t		j_list_lock;
+
+	/* Optional inode where we store the journal.  If present, all */
+	/* journal block numbers are mapped into this inode via */
+	/* bmap(). */
+	struct inode		*j_inode;
+
+	/*
+	 * Sequence number of the oldest transaction in the log [j_state_lock]
+	 */
+	tid_t			j_tail_sequence;
+
+	/*
+	 * Sequence number of the next transaction to grant [j_state_lock]
+	 */
+	tid_t			j_transaction_sequence;
+
+	/*
+	 * Sequence number of the most recently committed transaction
+	 * [j_state_lock].
+	 */
+	tid_t			j_commit_sequence;
+
+	/*
+	 * Sequence number of the most recent transaction wanting commit
+	 * [j_state_lock]
+	 */
+	tid_t			j_commit_request;
+
+	/*
+	 * Journal uuid: identifies the object (filesystem, LVM volume etc)
+	 * backed by this journal.  This will eventually be replaced by an array
+	 * of uuids, allowing us to index multiple devices within a single
+	 * journal and to perform atomic updates across them.
+	 */
+	__u8			j_uuid[16];
+
+	/* Pointer to the current commit thread for this journal */
+	struct task_struct	*j_task;
+
+	/*
+	 * Maximum number of metadata buffers to allow in a single compound
+	 * commit transaction
+	 */
+	int			j_max_transaction_buffers;
+
+	/*
+	 * What is the maximum transaction lifetime before we begin a commit?
+	 */
+	unsigned long		j_commit_interval;
+
+	/* The timer used to wakeup the commit thread: */
+	struct timer_list	j_commit_timer;
+
+	/*
+	 * The revoke table: maintains the list of revoked blocks in the
+	 * current transaction.  [j_revoke_lock]
+	 */
+	spinlock_t		j_revoke_lock;
+	struct jbd2_revoke_table_s *j_revoke;
+	struct jbd2_revoke_table_s *j_revoke_table[2];
+
+	/*
+	 * array of bhs for jbd2_journal_commit_transaction
+	 */
+	struct buffer_head	**j_wbuf;
+	int			j_wbufsize;
+
+	pid_t			j_last_sync_writer;
+
+	/*
+	 * An opaque pointer to fs-private information.  ext3 puts its
+	 * superblock pointer here
+	 */
+	void *j_private;
+};
+
+/*
+ * Journal flag definitions
+ */
+#define JBD2_UNMOUNT	0x001	/* Journal thread is being destroyed */
+#define JBD2_ABORT	0x002	/* Journaling has been aborted for errors. */
+#define JBD2_ACK_ERR	0x004	/* The errno in the sb has been acked */
+#define JBD2_FLUSHED	0x008	/* The journal superblock has been flushed */
+#define JBD2_LOADED	0x010	/* The journal superblock has been loaded */
+#define JBD2_BARRIER	0x020	/* Use IDE barriers */
+
+/*
+ * Function declarations for the journaling transaction and buffer
+ * management
+ */
+
+/* Filing buffers */
+extern void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
+extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *);
+extern void __jbd2_journal_unfile_buffer(struct journal_head *);
+extern void __jbd2_journal_refile_buffer(struct journal_head *);
+extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *);
+extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int);
+extern void __journal_free_buffer(struct journal_head *bh);
+extern void jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int);
+extern void __journal_clean_data_list(transaction_t *transaction);
+
+/* Log buffer allocation */
+extern struct journal_head * jbd2_journal_get_descriptor_buffer(journal_t *);
+int jbd2_journal_next_log_block(journal_t *, unsigned long long *);
+
+/* Commit management */
+extern void jbd2_journal_commit_transaction(journal_t *);
+
+/* Checkpoint list management */
+int __jbd2_journal_clean_checkpoint_list(journal_t *journal);
+int __jbd2_journal_remove_checkpoint(struct journal_head *);
+void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
+
+/* Buffer IO */
+extern int
+jbd2_journal_write_metadata_buffer(transaction_t	  *transaction,
+			      struct journal_head  *jh_in,
+			      struct journal_head **jh_out,
+			      unsigned long long   blocknr);
+
+/* Transaction locking */
+extern void		__wait_on_journal (journal_t *);
+
+/*
+ * Journal locking.
+ *
+ * We need to lock the journal during transaction state changes so that nobody
+ * ever tries to take a handle on the running transaction while we are in the
+ * middle of moving it to the commit phase.  j_state_lock does this.
+ *
+ * Note that the locking is completely interrupt unsafe.  We never touch
+ * journal structures from interrupts.
+ */
+
+static inline handle_t *journal_current_handle(void)
+{
+	return current->journal_info;
+}
+
+/* The journaling code user interface:
+ *
+ * Create and destroy handles
+ * Register buffer modifications against the current transaction.
+ */
+
+extern handle_t *jbd2_journal_start(journal_t *, int nblocks);
+extern int	 jbd2_journal_restart (handle_t *, int nblocks);
+extern int	 jbd2_journal_extend (handle_t *, int nblocks);
+extern int	 jbd2_journal_get_write_access(handle_t *, struct buffer_head *);
+extern int	 jbd2_journal_get_create_access (handle_t *, struct buffer_head *);
+extern int	 jbd2_journal_get_undo_access(handle_t *, struct buffer_head *);
+extern int	 jbd2_journal_dirty_data (handle_t *, struct buffer_head *);
+extern int	 jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *);
+extern void	 jbd2_journal_release_buffer (handle_t *, struct buffer_head *);
+extern int	 jbd2_journal_forget (handle_t *, struct buffer_head *);
+extern void	 journal_sync_buffer (struct buffer_head *);
+extern void	 jbd2_journal_invalidatepage(journal_t *,
+				struct page *, unsigned long);
+extern int	 jbd2_journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
+extern int	 jbd2_journal_stop(handle_t *);
+extern int	 jbd2_journal_flush (journal_t *);
+extern void	 jbd2_journal_lock_updates (journal_t *);
+extern void	 jbd2_journal_unlock_updates (journal_t *);
+
+extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+				struct block_device *fs_dev,
+				unsigned long long start, int len, int bsize);
+extern journal_t * jbd2_journal_init_inode (struct inode *);
+extern int	   jbd2_journal_update_format (journal_t *);
+extern int	   jbd2_journal_check_used_features
+		   (journal_t *, unsigned long, unsigned long, unsigned long);
+extern int	   jbd2_journal_check_available_features
+		   (journal_t *, unsigned long, unsigned long, unsigned long);
+extern int	   jbd2_journal_set_features
+		   (journal_t *, unsigned long, unsigned long, unsigned long);
+extern int	   jbd2_journal_create     (journal_t *);
+extern int	   jbd2_journal_load       (journal_t *journal);
+extern void	   jbd2_journal_destroy    (journal_t *);
+extern int	   jbd2_journal_recover    (journal_t *journal);
+extern int	   jbd2_journal_wipe       (journal_t *, int);
+extern int	   jbd2_journal_skip_recovery	(journal_t *);
+extern void	   jbd2_journal_update_superblock	(journal_t *, int);
+extern void	   __jbd2_journal_abort_hard	(journal_t *);
+extern void	   jbd2_journal_abort      (journal_t *, int);
+extern int	   jbd2_journal_errno      (journal_t *);
+extern void	   jbd2_journal_ack_err    (journal_t *);
+extern int	   jbd2_journal_clear_err  (journal_t *);
+extern int	   jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *);
+extern int	   jbd2_journal_force_commit(journal_t *);
+
+/*
+ * journal_head management
+ */
+struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh);
+struct journal_head *jbd2_journal_grab_journal_head(struct buffer_head *bh);
+void jbd2_journal_remove_journal_head(struct buffer_head *bh);
+void jbd2_journal_put_journal_head(struct journal_head *jh);
+
+/*
+ * handle management
+ */
+extern kmem_cache_t *jbd2_handle_cache;
+
+static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags)
+{
+	return kmem_cache_alloc(jbd2_handle_cache, gfp_flags);
+}
+
+static inline void jbd_free_handle(handle_t *handle)
+{
+	kmem_cache_free(jbd2_handle_cache, handle);
+}
+
+/* Primary revoke support */
+#define JOURNAL_REVOKE_DEFAULT_HASH 256
+extern int	   jbd2_journal_init_revoke(journal_t *, int);
+extern void	   jbd2_journal_destroy_revoke_caches(void);
+extern int	   jbd2_journal_init_revoke_caches(void);
+
+extern void	   jbd2_journal_destroy_revoke(journal_t *);
+extern int	   jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *);
+extern int	   jbd2_journal_cancel_revoke(handle_t *, struct journal_head *);
+extern void	   jbd2_journal_write_revoke_records(journal_t *, transaction_t *);
+
+/* Recovery revoke support */
+extern int	jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);
+extern int	jbd2_journal_test_revoke(journal_t *, unsigned long long, tid_t);
+extern void	jbd2_journal_clear_revoke(journal_t *);
+extern void	jbd2_journal_switch_revoke_table(journal_t *journal);
+
+/*
+ * The log thread user interface:
+ *
+ * Request space in the current transaction, and force transaction commit
+ * transitions on demand.
+ */
+
+int __jbd2_log_space_left(journal_t *); /* Called with journal locked */
+int jbd2_log_start_commit(journal_t *journal, tid_t tid);
+int __jbd2_log_start_commit(journal_t *journal, tid_t tid);
+int jbd2_journal_start_commit(journal_t *journal, tid_t *tid);
+int jbd2_journal_force_commit_nested(journal_t *journal);
+int jbd2_log_wait_commit(journal_t *journal, tid_t tid);
+int jbd2_log_do_checkpoint(journal_t *journal);
+
+void __jbd2_log_wait_for_space(journal_t *journal);
+extern void	__jbd2_journal_drop_transaction(journal_t *, transaction_t *);
+extern int	jbd2_cleanup_journal_tail(journal_t *);
+
+/* Debugging code only: */
+
+#define jbd_ENOSYS() \
+do {								           \
+	printk (KERN_ERR "JBD unimplemented function %s\n", __FUNCTION__); \
+	current->state = TASK_UNINTERRUPTIBLE;			           \
+	schedule();						           \
+} while (1)
+
+/*
+ * is_journal_abort
+ *
+ * Simple test wrapper function to test the JBD2_ABORT state flag.  This
+ * bit, when set, indicates that we have had a fatal error somewhere,
+ * either inside the journaling layer or indicated to us by the client
+ * (eg. ext3), and that we and should not commit any further
+ * transactions.
+ */
+
+static inline int is_journal_aborted(journal_t *journal)
+{
+	return journal->j_flags & JBD2_ABORT;
+}
+
+static inline int is_handle_aborted(handle_t *handle)
+{
+	if (handle->h_aborted)
+		return 1;
+	return is_journal_aborted(handle->h_transaction->t_journal);
+}
+
+static inline void jbd2_journal_abort_handle(handle_t *handle)
+{
+	handle->h_aborted = 1;
+}
+
+#endif /* __KERNEL__   */
+
+/* Comparison functions for transaction IDs: perform comparisons using
+ * modulo arithmetic so that they work over sequence number wraps. */
+
+static inline int tid_gt(tid_t x, tid_t y)
+{
+	int difference = (x - y);
+	return (difference > 0);
+}
+
+static inline int tid_geq(tid_t x, tid_t y)
+{
+	int difference = (x - y);
+	return (difference >= 0);
+}
+
+extern int jbd2_journal_blocks_per_page(struct inode *inode);
+extern size_t journal_tag_bytes(journal_t *journal);
+
+/*
+ * Return the minimum number of blocks which must be free in the journal
+ * before a new transaction may be started.  Must be called under j_state_lock.
+ */
+static inline int jbd_space_needed(journal_t *journal)
+{
+	int nblocks = journal->j_max_transaction_buffers;
+	if (journal->j_committing_transaction)
+		nblocks += journal->j_committing_transaction->
+					t_outstanding_credits;
+	return nblocks;
+}
+
+/*
+ * Definitions which augment the buffer_head layer
+ */
+
+/* journaling buffer types */
+#define BJ_None		0	/* Not journaled */
+#define BJ_SyncData	1	/* Normal data: flush before commit */
+#define BJ_Metadata	2	/* Normal journaled metadata */
+#define BJ_Forget	3	/* Buffer superseded by this transaction */
+#define BJ_IO		4	/* Buffer is for temporary IO use */
+#define BJ_Shadow	5	/* Buffer contents being shadowed to the log */
+#define BJ_LogCtl	6	/* Buffer contains log descriptors */
+#define BJ_Reserved	7	/* Buffer is reserved for access by journal */
+#define BJ_Locked	8	/* Locked for I/O during commit */
+#define BJ_Types	9
+
+extern int jbd_blocks_per_page(struct inode *inode);
+
+#ifdef __KERNEL__
+
+#define buffer_trace_init(bh)	do {} while (0)
+#define print_buffer_fields(bh)	do {} while (0)
+#define print_buffer_trace(bh)	do {} while (0)
+#define BUFFER_TRACE(bh, info)	do {} while (0)
+#define BUFFER_TRACE2(bh, bh2, info)	do {} while (0)
+#define JBUFFER_TRACE(jh, info)	do {} while (0)
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _LINUX_JBD_H */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d1af1dbe..b03d5a3 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -143,7 +143,7 @@
 	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */
-	ATA_DFLAG_NCQ_OFF	= (1 << 9), /* devied limited to non-NCQ mode */
+	ATA_DFLAG_NCQ_OFF	= (1 << 9), /* device limited to non-NCQ mode */
 	ATA_DFLAG_SUSPENDED	= (1 << 10), /* device suspended */
 	ATA_DFLAG_INIT_MASK	= (1 << 16) - 1,
 
@@ -628,7 +628,7 @@
 	void (*error_handler) (struct ata_port *ap);
 	void (*post_internal_cmd) (struct ata_queued_cmd *qc);
 
-	irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
+	irq_handler_t irq_handler;
 	void (*irq_clear) (struct ata_port *);
 
 	u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
@@ -769,7 +769,7 @@
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern void ata_host_stop (struct ata_host *host);
-extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
 extern void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
 			       unsigned int buflen, int write_data);
 extern void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 81e3a18..aa50d89 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -10,6 +10,11 @@
 #define LINUX_LOCKD_BIND_H
 
 #include <linux/lockd/nlm.h>
+/* need xdr-encoded error codes too, so... */
+#include <linux/lockd/xdr.h>
+#ifdef CONFIG_LOCKD_V4
+#include <linux/lockd/xdr4.h>
+#endif
 
 /* Dummy declarations */
 struct svc_rqst;
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 2909619..862d973 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -154,7 +154,7 @@
 struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl);
 void		  nlmclnt_finish_block(struct nlm_wait *block);
 int		  nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
-u32		  nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
+__be32		  nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
 void		  nlmclnt_recovery(struct nlm_host *);
 int		  nlmclnt_reclaim(struct nlm_host *, struct file_lock *);
 void		  nlmclnt_next_cookie(struct nlm_cookie *);
@@ -184,12 +184,12 @@
 /*
  * Server-side lock handling
  */
-u32		  nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
+__be32		  nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
 					struct nlm_lock *, int, struct nlm_cookie *);
-u32		  nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
-u32		  nlmsvc_testlock(struct nlm_file *, struct nlm_lock *,
+__be32		  nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
+__be32		  nlmsvc_testlock(struct nlm_file *, struct nlm_lock *,
 					struct nlm_lock *);
-u32		  nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
+__be32		  nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
 unsigned long	  nlmsvc_retry_blocked(void);
 void		  nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
 					nlm_host_match_fn_t match);
@@ -198,7 +198,7 @@
 /*
  * File handling for the server personality
  */
-u32		  nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
+__be32		  nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
 					struct nfs_fh *);
 void		  nlm_release_file(struct nlm_file *);
 void		  nlmsvc_mark_resources(void);
diff --git a/include/linux/lockd/share.h b/include/linux/lockd/share.h
index cd7816e..630c5bf 100644
--- a/include/linux/lockd/share.h
+++ b/include/linux/lockd/share.h
@@ -21,9 +21,9 @@
 	u32			s_mode;		/* deny mode */
 };
 
-u32	nlmsvc_share_file(struct nlm_host *, struct nlm_file *,
+__be32	nlmsvc_share_file(struct nlm_host *, struct nlm_file *,
 					       struct nlm_args *);
-u32	nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *,
+__be32	nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *,
 					       struct nlm_args *);
 void	nlmsvc_traverse_shares(struct nlm_host *, struct nlm_file *,
 					       nlm_host_match_fn_t);
diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h
index bb0a0f1..29e7d9f 100644
--- a/include/linux/lockd/xdr.h
+++ b/include/linux/lockd/xdr.h
@@ -13,6 +13,8 @@
 #include <linux/nfs.h>
 #include <linux/sunrpc/xdr.h>
 
+struct svc_rqst;
+
 #define NLM_MAXCOOKIELEN    	32
 #define NLM_MAXSTRLEN		1024
 
@@ -22,6 +24,8 @@
 #define	nlm_lck_blocked		__constant_htonl(NLM_LCK_BLOCKED)
 #define	nlm_lck_denied_grace_period	__constant_htonl(NLM_LCK_DENIED_GRACE_PERIOD)
 
+#define nlm_drop_reply		__constant_htonl(30000)
+
 /* Lock info passed via NLM */
 struct nlm_lock {
 	char *			caller;
@@ -86,19 +90,19 @@
  */
 #define NLMSVC_XDRSIZE		sizeof(struct nlm_args)
 
-int	nlmsvc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlmsvc_encode_testres(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlmsvc_decode_lockargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlmsvc_decode_cancargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlmsvc_decode_unlockargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlmsvc_encode_res(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlmsvc_decode_res(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlmsvc_encode_void(struct svc_rqst *, u32 *, void *);
-int	nlmsvc_decode_void(struct svc_rqst *, u32 *, void *);
-int	nlmsvc_decode_shareargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlmsvc_encode_shareres(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlmsvc_decode_notify(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlmsvc_decode_reboot(struct svc_rqst *, u32 *, struct nlm_reboot *);
+int	nlmsvc_decode_testargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlmsvc_encode_testres(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlmsvc_decode_lockargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlmsvc_decode_cancargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlmsvc_decode_unlockargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlmsvc_encode_res(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlmsvc_decode_res(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlmsvc_encode_void(struct svc_rqst *, __be32 *, void *);
+int	nlmsvc_decode_void(struct svc_rqst *, __be32 *, void *);
+int	nlmsvc_decode_shareargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlmsvc_encode_shareres(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlmsvc_decode_notify(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlmsvc_decode_reboot(struct svc_rqst *, __be32 *, struct nlm_reboot *);
 /*
 int	nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *);
 int	nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h
index 3cc1ae2..dd12b4c 100644
--- a/include/linux/lockd/xdr4.h
+++ b/include/linux/lockd/xdr4.h
@@ -23,19 +23,19 @@
 
 
 
-int	nlm4svc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlm4svc_encode_testres(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlm4svc_decode_lockargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlm4svc_decode_cancargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlm4svc_decode_unlockargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlm4svc_encode_res(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlm4svc_decode_res(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlm4svc_encode_void(struct svc_rqst *, u32 *, void *);
-int	nlm4svc_decode_void(struct svc_rqst *, u32 *, void *);
-int	nlm4svc_decode_shareargs(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlm4svc_encode_shareres(struct svc_rqst *, u32 *, struct nlm_res *);
-int	nlm4svc_decode_notify(struct svc_rqst *, u32 *, struct nlm_args *);
-int	nlm4svc_decode_reboot(struct svc_rqst *, u32 *, struct nlm_reboot *);
+int	nlm4svc_decode_testargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlm4svc_encode_testres(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlm4svc_decode_lockargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlm4svc_decode_cancargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlm4svc_decode_unlockargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlm4svc_encode_res(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlm4svc_decode_res(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlm4svc_encode_void(struct svc_rqst *, __be32 *, void *);
+int	nlm4svc_decode_void(struct svc_rqst *, __be32 *, void *);
+int	nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlm4svc_encode_shareres(struct svc_rqst *, __be32 *, struct nlm_res *);
+int	nlm4svc_decode_notify(struct svc_rqst *, __be32 *, struct nlm_args *);
+int	nlm4svc_decode_reboot(struct svc_rqst *, __be32 *, struct nlm_reboot *);
 /*
 int	nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *);
 int	nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 1314ca0..819f08f 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -202,7 +202,7 @@
  */
 
 extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
-			     struct lock_class_key *key);
+			     struct lock_class_key *key, int subclass);
 
 /*
  * Reinitialize a lock key - for cases where there is special locking or
@@ -211,9 +211,14 @@
  * or they are too narrow (they suffer from a false class-split):
  */
 #define lockdep_set_class(lock, key) \
-		lockdep_init_map(&(lock)->dep_map, #key, key)
+		lockdep_init_map(&(lock)->dep_map, #key, key, 0)
 #define lockdep_set_class_and_name(lock, key, name) \
-		lockdep_init_map(&(lock)->dep_map, name, key)
+		lockdep_init_map(&(lock)->dep_map, name, key, 0)
+#define lockdep_set_class_and_subclass(lock, key, sub) \
+		lockdep_init_map(&(lock)->dep_map, #key, key, sub)
+#define lockdep_set_subclass(lock, sub)	\
+		lockdep_init_map(&(lock)->dep_map, #lock, \
+				 (lock)->dep_map.key, sub)
 
 /*
  * Acquire a lock.
@@ -257,10 +262,14 @@
 # define lock_release(l, n, i)			do { } while (0)
 # define lockdep_init()				do { } while (0)
 # define lockdep_info()				do { } while (0)
-# define lockdep_init_map(lock, name, key)	do { (void)(key); } while (0)
+# define lockdep_init_map(lock, name, key, sub)	do { (void)(key); } while (0)
 # define lockdep_set_class(lock, key)		do { (void)(key); } while (0)
 # define lockdep_set_class_and_name(lock, key, name) \
 		do { (void)(key); } while (0)
+#define lockdep_set_class_and_subclass(lock, key, sub) \
+		do { (void)(key); } while (0)
+#define lockdep_set_subclass(lock, sub)		do { } while (0)
+
 # define INIT_LOCKDEP
 # define lockdep_reset()		do { debug_locks = 1; } while (0)
 # define lockdep_free_key_range(start, size)	do { } while (0)
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 22036dd..156c40f 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -8,6 +8,7 @@
 #define EFS_SUPER_MAGIC		0x414A53
 #define EXT2_SUPER_MAGIC	0xEF53
 #define EXT3_SUPER_MAGIC	0xEF53
+#define EXT4_SUPER_MAGIC	0xEF53
 #define HPFS_SUPER_MAGIC	0xf995e849
 #define ISOFS_SUPER_MAGIC	0x9660
 #define JFFS2_SUPER_MAGIC	0x72b6
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 09f0f57..daabb3a 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -150,7 +150,7 @@
 extern void mpol_fix_fork_child_flag(struct task_struct *p);
 #define set_cpuset_being_rebound(x) (cpuset_being_rebound = (x))
 
-#ifdef CONFIG_CPUSET
+#ifdef CONFIG_CPUSETS
 #define current_cpuset_is_being_rebound() \
 				(cpuset_being_rebound == current->cpuset)
 #else
diff --git a/include/linux/mm.h b/include/linux/mm.h
index b7966ab..d538de9 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -593,6 +593,7 @@
  */
 #define NOPAGE_SIGBUS	(NULL)
 #define NOPAGE_OOM	((struct page *) (-1))
+#define NOPAGE_REFAULT	((struct page *) (-2))	/* Return to userspace, rerun */
 
 /*
  * Error return values for the *_nopfn functions
@@ -1102,12 +1103,7 @@
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
-kernel_map_pages(struct page *page, int numpages, int enable)
-{
-	if (!PageHighMem(page) && !enable)
-		debug_check_no_locks_freed(page_address(page),
-					   numpages * PAGE_SIZE);
-}
+kernel_map_pages(struct page *page, int numpages, int enable) {}
 #endif
 
 extern struct vm_area_struct *get_gate_vma(struct task_struct *tsk);
@@ -1119,9 +1115,6 @@
 #define in_gate_area(task, addr) ({(void)task; in_gate_area_no_task(addr);})
 #endif	/* __HAVE_ARCH_GATE_AREA */
 
-/* /proc/<pid>/oom_adj set to -17 protects from the oom-killer */
-#define OOM_DISABLE -17
-
 int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
 					void __user *, size_t *, loff_t *);
 unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 81c3f77..08dec8d 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -83,6 +83,7 @@
 
   /* Application commands */
 #define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
+#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
 #define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
 #define SD_APP_SEND_SCR          51   /* adtc                    R1  */
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 59855b8..ed0762b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -674,6 +674,12 @@
 #define sparse_index_init(_sec, _nid)  do {} while (0)
 #endif /* CONFIG_SPARSEMEM */
 
+#ifdef CONFIG_NODES_SPAN_OTHER_NODES
+#define early_pfn_in_nid(pfn, nid)	(early_pfn_to_nid(pfn) == (nid))
+#else
+#define early_pfn_in_nid(pfn, nid)	(1)
+#endif
+
 #ifndef early_pfn_valid
 #define early_pfn_valid(pfn)	(1)
 #endif
diff --git a/include/linux/module.h b/include/linux/module.h
index 4b2d809..d1d00ce 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -317,9 +317,6 @@
 	/* Am I unsafe to unload? */
 	int unsafe;
 
-	/* Am I GPL-compatible */
-	int license_gplok;
-
 	unsigned int taints;	/* same bits as kernel:tainted */
 
 #ifdef CONFIG_MODULE_UNLOAD
diff --git a/include/linux/nbd.h b/include/linux/nbd.h
index e712e7d..d6b6dc0 100644
--- a/include/linux/nbd.h
+++ b/include/linux/nbd.h
@@ -15,6 +15,8 @@
 #ifndef LINUX_NBD_H
 #define LINUX_NBD_H
 
+#include <linux/types.h>
+
 #define NBD_SET_SOCK	_IO( 0xab, 0 )
 #define NBD_SET_BLKSIZE	_IO( 0xab, 1 )
 #define NBD_SET_SIZE	_IO( 0xab, 2 )
diff --git a/include/linux/net.h b/include/linux/net.h
index c257f71..15c733b 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -19,6 +19,7 @@
 #define _LINUX_NET_H
 
 #include <linux/wait.h>
+#include <linux/random.h>
 #include <asm/socket.h>
 
 struct poll_table_struct;
@@ -193,9 +194,9 @@
 extern struct socket *sockfd_lookup(int fd, int *err);
 #define		     sockfd_put(sock) fput(sock->file)
 extern int	     net_ratelimit(void);
-extern unsigned long net_random(void);
-extern void	     net_srandom(unsigned long);
-extern void	     net_random_init(void);
+
+#define net_random()		random32()
+#define net_srandom(seed)	srandom32(seed)
 
 extern int   	     kernel_sendmsg(struct socket *sock, struct msghdr *msg,
 				    struct kvec *vec, size_t num, size_t len);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 76ff548..45228c1 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -157,7 +157,7 @@
 	 * This is the cookie verifier used for NFSv3 readdir
 	 * operations
 	 */
-	__u32			cookieverf[2];
+	__be32			cookieverf[2];
 
 	/*
 	 * This is the list of dirty unwritten pages.
@@ -290,6 +290,7 @@
  * linux/fs/nfs/inode.c
  */
 extern int nfs_sync_mapping(struct address_space *mapping);
+extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping);
 extern void nfs_zap_caches(struct inode *);
 extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
 				struct nfs_fattr *);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index dc5397d..768c1ad 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -266,7 +266,7 @@
 
 struct nfs_writeverf {
 	enum nfs3_stable_how	committed;
-	__u32			verifier[2];
+	__be32			verifier[2];
 };
 
 struct nfs_writeres {
@@ -420,7 +420,7 @@
 	unsigned int		len;
 	struct iattr *		sattr;
 	enum nfs3_createmode	createmode;
-	__u32			verifier[2];
+	__be32			verifier[2];
 };
 
 struct nfs3_mkdirargs {
@@ -467,7 +467,7 @@
 struct nfs3_readdirargs {
 	struct nfs_fh *		fh;
 	__u64			cookie;
-	__u32			verf[2];
+	__be32			verf[2];
 	int			plus;
 	unsigned int            count;
 	struct page **		pages;
@@ -503,7 +503,7 @@
 
 struct nfs3_readdirres {
 	struct nfs_fattr *	dir_attr;
-	__u32 *			verf;
+	__be32 *		verf;
 	int			plus;
 };
 
@@ -811,7 +811,7 @@
 	int	(*pathconf) (struct nfs_server *, struct nfs_fh *,
 			     struct nfs_pathconf *);
 	int	(*set_capabilities)(struct nfs_server *, struct nfs_fh *);
-	u32 *	(*decode_dirent)(u32 *, struct nfs_entry *, int plus);
+	__be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus);
 	void	(*read_setup)   (struct nfs_read_data *);
 	int	(*read_done)  (struct rpc_task *, struct nfs_read_data *);
 	void	(*write_setup)  (struct nfs_write_data *, int how);
diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
index c3a3557..007480c 100644
--- a/include/linux/nfsd/cache.h
+++ b/include/linux/nfsd/cache.h
@@ -26,14 +26,14 @@
 				c_type,		/* status, buffer */
 				c_secure : 1;	/* req came from port < 1024 */
 	struct sockaddr_in	c_addr;
-	u32			c_xid;
+	__be32			c_xid;
 	u32			c_prot;
 	u32			c_proc;
 	u32			c_vers;
 	unsigned long		c_timestamp;
 	union {
 		struct kvec	u_vec;
-		u32		u_status;
+		__be32		u_status;
 	}			c_u;
 };
 
@@ -75,7 +75,7 @@
 void	nfsd_cache_init(void);
 void	nfsd_cache_shutdown(void);
 int	nfsd_cache_lookup(struct svc_rqst *, int);
-void	nfsd_cache_update(struct svc_rqst *, int, u32 *);
+void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
 
 #endif /* __KERNEL__ */
 #endif /* NFSCACHE_H */
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 6e78ea9..045e38c 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -117,8 +117,8 @@
 				   struct cache_req *reqp);
 int			exp_rootfh(struct auth_domain *, 
 					char *path, struct knfsd_fh *, int maxsize);
-int			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
-int			nfserrno(int errno);
+__be32			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
+__be32			nfserrno(int errno);
 
 extern struct cache_detail svc_export_cache;
 
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index d0d4aae..eb23114 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -50,7 +50,7 @@
  * Callback function for readdir
  */
 struct readdir_cd {
-	int			err;	/* 0, nfserr, or nfserr_eof */
+	__be32			err;	/* 0, nfserr, or nfserr_eof */
 };
 typedef int		(*encode_dent_fn)(struct readdir_cd *, const char *,
 						int, loff_t, ino_t, unsigned int);
@@ -64,7 +64,7 @@
  * Function prototypes.
  */
 int		nfsd_svc(unsigned short port, int nrservs);
-int		nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp);
+int		nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
 
 /* nfsd/vfs.c */
 int		fh_lock_parent(struct svc_fh *, struct dentry *);
@@ -72,57 +72,57 @@
 void		nfsd_racache_shutdown(void);
 int		nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
 		                struct svc_export **expp);
-int		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
 				const char *, int, struct svc_fh *);
-int		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
 				struct iattr *, int, time_t);
 #ifdef CONFIG_NFSD_V4
-int             nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
                     struct nfs4_acl *);
 int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
 #endif /* CONFIG_NFSD_V4 */
-int		nfsd_create(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
 				int type, dev_t rdev, struct svc_fh *res);
 #ifdef CONFIG_NFSD_V3
-int		nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
-int		nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
+__be32		nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
 				struct svc_fh *res, int createmode,
 				u32 *verifier, int *truncp);
-int		nfsd_commit(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_commit(struct svc_rqst *, struct svc_fh *,
 				loff_t, unsigned long);
 #endif /* CONFIG_NFSD_V3 */
-int		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
+__be32		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
 				int, struct file **);
 void		nfsd_close(struct file *);
-int 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
+__be32 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
 				loff_t, struct kvec *, int, unsigned long *);
-int 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
+__be32 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
 				loff_t, struct kvec *,int, unsigned long, int *);
-int		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
 				char *, int *);
-int		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, char *path, int plen,
 				struct svc_fh *res, struct iattr *);
-int		nfsd_link(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_link(struct svc_rqst *, struct svc_fh *,
 				char *, int, struct svc_fh *);
-int		nfsd_rename(struct svc_rqst *,
+__be32		nfsd_rename(struct svc_rqst *,
 				struct svc_fh *, char *, int,
 				struct svc_fh *, char *, int);
-int		nfsd_remove(struct svc_rqst *,
+__be32		nfsd_remove(struct svc_rqst *,
 				struct svc_fh *, char *, int);
-int		nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
+__be32		nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
 				char *name, int len);
 int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
 				unsigned long size);
-int		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
 			     loff_t *, struct readdir_cd *, encode_dent_fn);
-int		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
+__be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
 				struct kstatfs *);
 
 int		nfsd_notify_change(struct inode *, struct iattr *);
-int		nfsd_permission(struct svc_export *, struct dentry *, int);
+__be32		nfsd_permission(struct svc_export *, struct dentry *, int);
 int		nfsd_sync_dir(struct dentry *dp);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -238,6 +238,7 @@
 #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
 #define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
 #define	nfserr_locked		__constant_htonl(NFSERR_LOCKED)
+#define	nfserr_replay_me	__constant_htonl(NFSERR_REPLAY_ME)
 
 /* error codes for internal use */
 /* if a request fails due to kmalloc failure, it gets dropped.
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index 069257e..f3b51d6 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -157,7 +157,7 @@
 	__u64			fh_post_size;	/* i_size */
 	unsigned long		fh_post_blocks; /* i_blocks */
 	unsigned long		fh_post_blksize;/* i_blksize */
-	__u32			fh_post_rdev[2];/* i_rdev */
+	__be32			fh_post_rdev[2];/* i_rdev */
 	struct timespec		fh_post_atime;	/* i_atime */
 	struct timespec		fh_post_mtime;	/* i_mtime */
 	struct timespec		fh_post_ctime;	/* i_ctime */
@@ -209,9 +209,9 @@
 /*
  * Function prototypes
  */
-u32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
-int	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
-int	fh_update(struct svc_fh *);
+__be32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
+__be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
+__be32	fh_update(struct svc_fh *);
 void	fh_put(struct svc_fh *);
 
 static __inline__ struct svc_fh *
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 8bf23cf..c3673f4 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -125,7 +125,7 @@
 	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	time_t                  cl_time;        /* time of last lease renewal */
-	u32			cl_addr; 	/* client ipaddress */
+	__be32			cl_addr; 	/* client ipaddress */
 	struct svc_cred		cl_cred; 	/* setclientid principal */
 	clientid_t		cl_clientid;	/* generated by server */
 	nfs4_verifier		cl_confirm;	/* generated by server */
@@ -164,7 +164,7 @@
  * is cached. 
  */
 struct nfs4_replay {
-	u32			rp_status;
+	__be32			rp_status;
 	unsigned int		rp_buflen;
 	char			*rp_buf;
 	unsigned		intrp_allocated;
@@ -273,19 +273,19 @@
 	((err) != nfserr_stale_stateid) &&      \
 	((err) != nfserr_bad_stateid))
 
-extern int nfsd4_renew(clientid_t *clid);
-extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 
+extern __be32 nfsd4_renew(clientid_t *clid);
+extern __be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
 		stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
 extern int nfs4_in_grace(void);
-extern int nfs4_check_open_reclaim(clientid_t *clid);
+extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
 extern void put_nfs4_client(struct nfs4_client *clp);
 extern void nfs4_free_stateowner(struct kref *kref);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
-extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
+extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
 extern void nfsd4_init_recdir(char *recdir_name);
 extern int nfsd4_recdir_load(void);
 extern void nfsd4_shutdown_recdir(void);
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index 0e53de8..877192d 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -81,7 +81,7 @@
 	struct svc_fh		fh;
 	__u32			cookie;
 	__u32			count;
-	u32 *			buffer;
+	__be32 *		buffer;
 };
 
 struct nfsd_attrstat {
@@ -108,9 +108,9 @@
 	int			count;
 
 	struct readdir_cd	common;
-	u32 *			buffer;
+	__be32 *		buffer;
 	int			buflen;
-	u32 *			offset;
+	__be32 *		offset;
 };
 
 struct nfsd_statfsres {
@@ -135,43 +135,43 @@
 #define NFS2_SVC_XDRSIZE	sizeof(union nfsd_xdrstore)
 
 
-int nfssvc_decode_void(struct svc_rqst *, u32 *, void *);
-int nfssvc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
-int nfssvc_decode_sattrargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_void(struct svc_rqst *, __be32 *, void *);
+int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
+int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *,
 				struct nfsd_sattrargs *);
-int nfssvc_decode_diropargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *,
 				struct nfsd_diropargs *);
-int nfssvc_decode_readargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_readargs(struct svc_rqst *, __be32 *,
 				struct nfsd_readargs *);
-int nfssvc_decode_writeargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_writeargs(struct svc_rqst *, __be32 *,
 				struct nfsd_writeargs *);
-int nfssvc_decode_createargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_createargs(struct svc_rqst *, __be32 *,
 				struct nfsd_createargs *);
-int nfssvc_decode_renameargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_renameargs(struct svc_rqst *, __be32 *,
 				struct nfsd_renameargs *);
-int nfssvc_decode_readlinkargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_readlinkargs(struct svc_rqst *, __be32 *,
 				struct nfsd_readlinkargs *);
-int nfssvc_decode_linkargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *,
 				struct nfsd_linkargs *);
-int nfssvc_decode_symlinkargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *,
 				struct nfsd_symlinkargs *);
-int nfssvc_decode_readdirargs(struct svc_rqst *, u32 *,
+int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *,
 				struct nfsd_readdirargs *);
-int nfssvc_encode_void(struct svc_rqst *, u32 *, void *);
-int nfssvc_encode_attrstat(struct svc_rqst *, u32 *, struct nfsd_attrstat *);
-int nfssvc_encode_diropres(struct svc_rqst *, u32 *, struct nfsd_diropres *);
-int nfssvc_encode_readlinkres(struct svc_rqst *, u32 *, struct nfsd_readlinkres *);
-int nfssvc_encode_readres(struct svc_rqst *, u32 *, struct nfsd_readres *);
-int nfssvc_encode_statfsres(struct svc_rqst *, u32 *, struct nfsd_statfsres *);
-int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *);
+int nfssvc_encode_void(struct svc_rqst *, __be32 *, void *);
+int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *, struct nfsd_attrstat *);
+int nfssvc_encode_diropres(struct svc_rqst *, __be32 *, struct nfsd_diropres *);
+int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *, struct nfsd_readlinkres *);
+int nfssvc_encode_readres(struct svc_rqst *, __be32 *, struct nfsd_readres *);
+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_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
+int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
 
 /* Helper functions for NFSv2 ACL code */
-u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp);
-u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp);
+__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp);
+__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp);
 
 #endif /* LINUX_NFSD_H */
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 474d882..7996386 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -51,7 +51,7 @@
 	int			len;
 	int			createmode;
 	struct iattr		attrs;
-	__u32 *			verf;
+	__be32 *		verf;
 };
 
 struct nfsd3_mknodargs {
@@ -98,8 +98,8 @@
 	__u64			cookie;
 	__u32			dircount;
 	__u32			count;
-	__u32 *			verf;
-	u32 *			buffer;
+	__be32 *		verf;
+	__be32 *		buffer;
 };
 
 struct nfsd3_commitargs {
@@ -122,79 +122,79 @@
 };
 
 struct nfsd3_attrstat {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	struct kstat            stat;
 };
 
 /* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */
 struct nfsd3_diropres  {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		dirfh;
 	struct svc_fh		fh;
 };
 
 struct nfsd3_accessres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	__u32			access;
 };
 
 struct nfsd3_readlinkres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	__u32			len;
 };
 
 struct nfsd3_readres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	unsigned long		count;
 	int			eof;
 };
 
 struct nfsd3_writeres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	unsigned long		count;
 	int			committed;
 };
 
 struct nfsd3_renameres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		ffh;
 	struct svc_fh		tfh;
 };
 
 struct nfsd3_linkres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		tfh;
 	struct svc_fh		fh;
 };
 
 struct nfsd3_readdirres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	int			count;
-	__u32			verf[2];
+	__be32			verf[2];
 
 	struct readdir_cd	common;
-	u32 *			buffer;
+	__be32 *		buffer;
 	int			buflen;
-	u32 *			offset;
-	u32 *			offset1;
+	__be32 *		offset;
+	__be32 *		offset1;
 	struct svc_rqst *	rqstp;
 
 };
 
 struct nfsd3_fsstatres {
-	__u32			status;
+	__be32			status;
 	struct kstatfs		stats;
 	__u32			invarsec;
 };
 
 struct nfsd3_fsinfores {
-	__u32			status;
+	__be32			status;
 	__u32			f_rtmax;
 	__u32			f_rtpref;
 	__u32			f_rtmult;
@@ -207,7 +207,7 @@
 };
 
 struct nfsd3_pathconfres {
-	__u32			status;
+	__be32			status;
 	__u32			p_link_max;
 	__u32			p_name_max;
 	__u32			p_no_trunc;
@@ -217,12 +217,12 @@
 };
 
 struct nfsd3_commitres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 };
 
 struct nfsd3_getaclres {
-	__u32			status;
+	__be32			status;
 	struct svc_fh		fh;
 	int			mask;
 	struct posix_acl	*acl_access;
@@ -266,70 +266,70 @@
 
 #define NFS3_SVC_XDRSIZE		sizeof(union nfsd3_xdrstore)
 
-int nfs3svc_decode_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
-int nfs3svc_decode_sattrargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
+int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_sattrargs *);
-int nfs3svc_decode_diropargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_diropargs *);
-int nfs3svc_decode_accessargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_accessargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_accessargs *);
-int nfs3svc_decode_readargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_readargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_readargs *);
-int nfs3svc_decode_writeargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_writeargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_writeargs *);
-int nfs3svc_decode_createargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_createargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_createargs *);
-int nfs3svc_decode_mkdirargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_mkdirargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_createargs *);
-int nfs3svc_decode_mknodargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_mknodargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_mknodargs *);
-int nfs3svc_decode_renameargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_renameargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_renameargs *);
-int nfs3svc_decode_readlinkargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_readlinkargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_readlinkargs *);
-int nfs3svc_decode_linkargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_linkargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_linkargs *);
-int nfs3svc_decode_symlinkargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_symlinkargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_symlinkargs *);
-int nfs3svc_decode_readdirargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_readdirargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_readdirargs *);
-int nfs3svc_decode_readdirplusargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_readdirplusargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_readdirargs *);
-int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *,
+int nfs3svc_decode_commitargs(struct svc_rqst *, __be32 *,
 				struct nfsd3_commitargs *);
-int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *);
-int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *,
+int nfs3svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
+int nfs3svc_encode_attrstat(struct svc_rqst *, __be32 *,
 				struct nfsd3_attrstat *);
-int nfs3svc_encode_wccstat(struct svc_rqst *, u32 *,
+int nfs3svc_encode_wccstat(struct svc_rqst *, __be32 *,
 				struct nfsd3_attrstat *);
-int nfs3svc_encode_diropres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_diropres(struct svc_rqst *, __be32 *,
 				struct nfsd3_diropres *);
-int nfs3svc_encode_accessres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_accessres(struct svc_rqst *, __be32 *,
 				struct nfsd3_accessres *);
-int nfs3svc_encode_readlinkres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_readlinkres(struct svc_rqst *, __be32 *,
 				struct nfsd3_readlinkres *);
-int nfs3svc_encode_readres(struct svc_rqst *, u32 *, struct nfsd3_readres *);
-int nfs3svc_encode_writeres(struct svc_rqst *, u32 *, struct nfsd3_writeres *);
-int nfs3svc_encode_createres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_readres(struct svc_rqst *, __be32 *, struct nfsd3_readres *);
+int nfs3svc_encode_writeres(struct svc_rqst *, __be32 *, struct nfsd3_writeres *);
+int nfs3svc_encode_createres(struct svc_rqst *, __be32 *,
 				struct nfsd3_diropres *);
-int nfs3svc_encode_renameres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_renameres(struct svc_rqst *, __be32 *,
 				struct nfsd3_renameres *);
-int nfs3svc_encode_linkres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_linkres(struct svc_rqst *, __be32 *,
 				struct nfsd3_linkres *);
-int nfs3svc_encode_readdirres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_readdirres(struct svc_rqst *, __be32 *,
 				struct nfsd3_readdirres *);
-int nfs3svc_encode_fsstatres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_fsstatres(struct svc_rqst *, __be32 *,
 				struct nfsd3_fsstatres *);
-int nfs3svc_encode_fsinfores(struct svc_rqst *, u32 *,
+int nfs3svc_encode_fsinfores(struct svc_rqst *, __be32 *,
 				struct nfsd3_fsinfores *);
-int nfs3svc_encode_pathconfres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_pathconfres(struct svc_rqst *, __be32 *,
 				struct nfsd3_pathconfres *);
-int nfs3svc_encode_commitres(struct svc_rqst *, u32 *,
+int nfs3svc_encode_commitres(struct svc_rqst *, __be32 *,
 				struct nfsd3_commitres *);
 
-int nfs3svc_release_fhandle(struct svc_rqst *, u32 *,
+int nfs3svc_release_fhandle(struct svc_rqst *, __be32 *,
 				struct nfsd3_attrstat *);
-int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
+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,
@@ -338,9 +338,9 @@
 				int namlen, loff_t offset, ino_t ino,
 				unsigned int);
 /* Helper functions for NFSv3 ACL code */
-u32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p,
+__be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p,
 				struct svc_fh *fhp);
-u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp);
+__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp);
 
 
 #endif /* _LINUX_NFSD_XDR3_H */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 66e6427..45ca01b 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -258,9 +258,9 @@
 	struct svc_fh * rd_fhp;             /* response */
 
 	struct readdir_cd	common;
-	u32 *			buffer;
+	__be32 *		buffer;
 	int			buflen;
-	u32 *			offset;
+	__be32 *		offset;
 };
 
 struct nfsd4_release_lockowner {
@@ -334,7 +334,7 @@
 
 struct nfsd4_op {
 	int					opnum;
-	int					status;
+	__be32					status;
 	union {
 		struct nfsd4_access		access;
 		struct nfsd4_close		close;
@@ -371,12 +371,12 @@
 
 struct nfsd4_compoundargs {
 	/* scratch variables for XDR decode */
-	u32 *				p;
-	u32 *				end;
+	__be32 *			p;
+	__be32 *			end;
 	struct page **			pagelist;
 	int				pagelen;
-	u32				tmp[8];
-	u32 *				tmpp;
+	__be32				tmp[8];
+	__be32 *			tmpp;
 	struct tmpbuf {
 		struct tmpbuf *next;
 		void (*release)(const void *);
@@ -395,15 +395,15 @@
 
 struct nfsd4_compoundres {
 	/* scratch variables for XDR encode */
-	u32 *				p;
-	u32 *				end;
+	__be32 *			p;
+	__be32 *			end;
 	struct xdr_buf *		xbuf;
 	struct svc_rqst *		rqstp;
 
 	u32				taglen;
 	char *				tag;
 	u32				opcnt;
-	u32 *				tagp; /* where to encode tag and  opcount */
+	__be32 *			tagp; /* where to encode tag and  opcount */
 };
 
 #define NFS4_SVC_XDRSIZE		sizeof(struct nfsd4_compoundargs)
@@ -419,45 +419,45 @@
 	cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec;
 }
 
-int nfs4svc_encode_voidres(struct svc_rqst *, u32 *, void *);
-int nfs4svc_decode_compoundargs(struct svc_rqst *, u32 *, 
+int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
+int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *,
 		struct nfsd4_compoundargs *);
-int nfs4svc_encode_compoundres(struct svc_rqst *, u32 *, 
+int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *,
 		struct nfsd4_compoundres *);
 void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
 void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
-int nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
-		       struct dentry *dentry, u32 *buffer, int *countp, 
+__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+		       struct dentry *dentry, __be32 *buffer, int *countp,
 		       u32 *bmval, struct svc_rqst *);
-extern int nfsd4_setclientid(struct svc_rqst *rqstp, 
+extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
 		struct nfsd4_setclientid *setclid);
-extern int nfsd4_setclientid_confirm(struct svc_rqst *rqstp, 
+extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 		struct nfsd4_setclientid_confirm *setclientid_confirm);
-extern int nfsd4_process_open1(struct nfsd4_open *open);
-extern int nfsd4_process_open2(struct svc_rqst *rqstp, 
+extern __be32 nfsd4_process_open1(struct nfsd4_open *open);
+extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open *open);
-extern int nfsd4_open_confirm(struct svc_rqst *rqstp, 
+extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
 		struct nfs4_stateowner **);
-extern  int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
+extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 		struct nfsd4_close *close,
 		struct nfs4_stateowner **replay_owner);
-extern int nfsd4_open_downgrade(struct svc_rqst *rqstp, 
+extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
 		struct nfs4_stateowner **replay_owner);
-extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
+extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 		struct nfsd4_lock *lock,
 		struct nfs4_stateowner **replay_owner);
-extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
+extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 		struct nfsd4_lockt *lockt);
-extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
+extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 		struct nfsd4_locku *locku,
 		struct nfs4_stateowner **replay_owner);
-extern int
+extern __be32
 nfsd4_release_lockowner(struct svc_rqst *rqstp,
 		struct nfsd4_release_lockowner *rlockowner);
 extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
-extern int nfsd4_delegreturn(struct svc_rqst *rqstp,
+extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_delegreturn *dr);
 #endif
 
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 5dce5c2..b1063e9 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -8,8 +8,8 @@
  * See detailed comments in the file linux/bitmap.h describing the
  * data type on which these nodemasks are based.
  *
- * For details of nodemask_scnprintf() and nodemask_parse(),
- * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
+ * For details of nodemask_scnprintf() and nodemask_parse_user(),
+ * see bitmap_scnprintf() and bitmap_parse_user() in lib/bitmap.c.
  * For details of nodelist_scnprintf() and nodelist_parse(), see
  * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c.
@@ -51,7 +51,7 @@
  * unsigned long *nodes_addr(mask)	Array of unsigned long's in mask
  *
  * int nodemask_scnprintf(buf, len, mask) Format nodemask for printing
- * int nodemask_parse(ubuf, ulen, mask)	Parse ascii string as nodemask
+ * int nodemask_parse_user(ubuf, ulen, mask)	Parse ascii string as nodemask
  * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
  * int nodelist_parse(buf, map)		Parse ascii string as nodelist
  * int node_remap(oldbit, old, new)	newbit = map(old, new)(oldbit)
@@ -288,12 +288,12 @@
 	return bitmap_scnprintf(buf, len, srcp->bits, nbits);
 }
 
-#define nodemask_parse(ubuf, ulen, dst) \
-			__nodemask_parse((ubuf), (ulen), &(dst), MAX_NUMNODES)
-static inline int __nodemask_parse(const char __user *buf, int len,
+#define nodemask_parse_user(ubuf, ulen, dst) \
+		__nodemask_parse_user((ubuf), (ulen), &(dst), MAX_NUMNODES)
+static inline int __nodemask_parse_user(const char __user *buf, int len,
 					nodemask_t *dstp, int nbits)
 {
-	return bitmap_parse(buf, len, dstp->bits, nbits);
+	return bitmap_parse_user(buf, len, dstp->bits, nbits);
 }
 
 #define nodelist_scnprintf(buf, len, src) \
diff --git a/include/linux/oom.h b/include/linux/oom.h
new file mode 100644
index 0000000..ad76463
--- /dev/null
+++ b/include/linux/oom.h
@@ -0,0 +1,10 @@
+#ifndef __INCLUDE_LINUX_OOM_H
+#define __INCLUDE_LINUX_OOM_H
+
+/* /proc/<pid>/oom_adj set to -17 protects from the oom-killer */
+#define OOM_DISABLE (-17)
+/* inclusive */
+#define OOM_ADJUST_MIN (-16)
+#define OOM_ADJUST_MAX 15
+
+#endif
diff --git a/include/linux/parport.h b/include/linux/parport.h
index 5bf321e..80682aa 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -229,7 +229,7 @@
 	int (*preempt)(void *);
 	void (*wakeup)(void *);
 	void *private;
-	void (*irq_func)(int, void *, struct pt_regs *);
+	void (*irq_func)(int, void *);
 	unsigned int flags;
 	struct pardevice *next;
 	struct pardevice *prev;
@@ -375,7 +375,7 @@
 struct pardevice *parport_register_device(struct parport *port, 
 			  const char *name,
 			  int (*pf)(void *), void (*kf)(void *),
-			  void (*irq_func)(int, void *, struct pt_regs *), 
+			  void (*irq_func)(int, void *), 
 			  int flags, void *handle);
 
 /* parport_unregister unlinks a device from the chain. */
@@ -457,7 +457,7 @@
 #define PARPORT_FLAG_EXCL		(1<<1)	/* EXCL driver registered. */
 
 /* IEEE1284 functions */
-extern void parport_ieee1284_interrupt (int, void *, struct pt_regs *);
+extern void parport_ieee1284_interrupt (int, void *);
 extern int parport_negotiate (struct parport *, int mode);
 extern ssize_t parport_write (struct parport *, const void *buf, size_t len);
 extern ssize_t parport_read (struct parport *, void *buf, size_t len);
@@ -502,8 +502,7 @@
 extern struct pardevice *parport_open (int devnum, const char *name,
 				       int (*pf) (void *),
 				       void (*kf) (void *),
-				       void (*irqf) (int, void *,
-						     struct pt_regs *),
+				       void (*irqf) (int, void *),
 				       int flags, void *handle);
 extern void parport_close (struct pardevice *dev);
 extern ssize_t parport_device_id (int devnum, char *buffer, size_t len);
@@ -512,13 +511,12 @@
 extern int parport_daisy_select (struct parport *port, int daisy, int mode);
 
 /* Lowlevel drivers _can_ call this support function to handle irqs.  */
-static __inline__ void parport_generic_irq(int irq, struct parport *port,
-					   struct pt_regs *regs)
+static __inline__ void parport_generic_irq(int irq, struct parport *port)
 {
-	parport_ieee1284_interrupt (irq, port, regs);
+	parport_ieee1284_interrupt (irq, port);
 	read_lock(&port->cad_lock);
 	if (port->cad && port->cad->irq_func)
-		port->cad->irq_func(irq, port->cad->private, regs);
+		port->cad->irq_func(irq, port->cad->private);
 	read_unlock(&port->cad_lock);
 }
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5c604f5..09be0f8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -443,6 +443,7 @@
 extern void pci_remove_bus_device(struct pci_dev *dev);
 extern void pci_stop_bus_device(struct pci_dev *dev);
 void pci_setup_cardbus(struct pci_bus *bus);
+extern void pci_sort_breadthfirst(void);
 
 /* Generic PCI functions exported to card drivers */
 
@@ -452,13 +453,18 @@
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
 int pci_find_ext_capability (struct pci_dev *dev, int cap);
-struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
+struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
-struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
+struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+				struct pci_dev *from);
+struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
+				struct pci_dev *from);
+
 struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
 				unsigned int ss_vendor, unsigned int ss_device,
 				struct pci_dev *from);
 struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
+struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
 struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
 int pci_dev_present(const struct pci_device_id *ids);
 
@@ -658,7 +664,12 @@
 static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
 { return NULL; }
 
-static inline struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from)
+static inline struct pci_dev *pci_get_device(unsigned int vendor,
+				unsigned int device, struct pci_dev *from)
+{ return NULL; }
+
+static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
+				unsigned int device, struct pci_dev *from)
 { return NULL; }
 
 static inline struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/include/linux/pci_hotplug.h
similarity index 98%
rename from drivers/pci/hotplug/pci_hotplug.h
rename to include/linux/pci_hotplug.h
index 772523d..a675a05 100644
--- a/drivers/pci/hotplug/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <greg@kroah.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
  *
  */
 #ifndef _PCI_HOTPLUG_H
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f069df2..f3a168f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2351,3 +2351,5 @@
 #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
 
+#define PCI_VENDOR_ID_QUICKNET		0x15E2
+#define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 46ec72f..600e3d3 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -19,7 +19,7 @@
  * we force a syntax error here if it isn't.
  */
 #define get_cpu_var(var) (*({				\
-	extern int simple_indentifier_##var(void);	\
+	extern int simple_identifier_##var(void);	\
 	preempt_disable();				\
 	&__get_cpu_var(var); }))
 #define put_cpu_var(var) preempt_enable()
diff --git a/include/linux/personality.h b/include/linux/personality.h
index 80d780e..bf4cf20 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -1,6 +1,8 @@
 #ifndef _LINUX_PERSONALITY_H
 #define _LINUX_PERSONALITY_H
 
+#ifdef __KERNEL__
+
 /*
  * Handling of different ABIs (personalities).
  */
@@ -12,6 +14,8 @@
 extern int		unregister_exec_domain(struct exec_domain *);
 extern int		__set_personality(unsigned long);
 
+#endif /* __KERNEL__ */
+
 /*
  * Flags for bug emulation.
  *
@@ -71,6 +75,7 @@
 	PER_MASK =		0x00ff,
 };
 
+#ifdef __KERNEL__
 
 /*
  * Description of an execution domain.
@@ -111,4 +116,6 @@
 #define set_personality(pers) \
 	((current->personality == pers) ? 0 : __set_personality(pers))
 
+#endif /* __KERNEL__ */
+
 #endif /* _LINUX_PERSONALITY_H */
diff --git a/include/linux/profile.h b/include/linux/profile.h
index e633004..acce53f 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -17,7 +17,7 @@
 
 /* init basic kernel profiler */
 void __init profile_init(void);
-void profile_tick(int, struct pt_regs *);
+void profile_tick(int);
 void profile_hit(int, void *);
 #ifdef CONFIG_PROC_FS
 void create_prof_cpu_mask(struct proc_dir_entry *);
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 84d8877..ebd42a3 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -146,16 +146,16 @@
 
 /* the superblock at the front of the bitmap file -- little endian */
 typedef struct bitmap_super_s {
-	__u32 magic;        /*  0  BITMAP_MAGIC */
-	__u32 version;      /*  4  the bitmap major for now, could change... */
-	__u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
-	__u64 events;       /* 24  event counter for the bitmap (1)*/
-	__u64 events_cleared;/*32  event counter when last bit cleared (2) */
-	__u64 sync_size;    /* 40  the size of the md device's sync range(3) */
-	__u32 state;        /* 48  bitmap state information */
-	__u32 chunksize;    /* 52  the bitmap chunk size in bytes */
-	__u32 daemon_sleep; /* 56  seconds between disk flushes */
-	__u32 write_behind; /* 60  number of outstanding write-behind writes */
+	__le32 magic;        /*  0  BITMAP_MAGIC */
+	__le32 version;      /*  4  the bitmap major for now, could change... */
+	__u8  uuid[16];      /*  8  128 bit uuid - must match md device uuid */
+	__le64 events;       /* 24  event counter for the bitmap (1)*/
+	__le64 events_cleared;/*32  event counter when last bit cleared (2) */
+	__le64 sync_size;    /* 40  the size of the md device's sync range(3) */
+	__le32 state;        /* 48  bitmap state information */
+	__le32 chunksize;    /* 52  the bitmap chunk size in bytes */
+	__le32 daemon_sleep; /* 56  seconds between disk flushes */
+	__le32 write_behind; /* 60  number of outstanding write-behind writes */
 
 	__u8  pad[256 - 64]; /* set to zero */
 } bitmap_super_t;
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index b6ebc69b..3f2cd98 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -206,52 +206,52 @@
  */
 struct mdp_superblock_1 {
 	/* constant array information - 128 bytes */
-	__u32	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
-	__u32	major_version;	/* 1 */
-	__u32	feature_map;	/* bit 0 set if 'bitmap_offset' is meaningful */
-	__u32	pad0;		/* always set to 0 when writing */
+	__le32	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
+	__le32	major_version;	/* 1 */
+	__le32	feature_map;	/* bit 0 set if 'bitmap_offset' is meaningful */
+	__le32	pad0;		/* always set to 0 when writing */
 
 	__u8	set_uuid[16];	/* user-space generated. */
 	char	set_name[32];	/* set and interpreted by user-space */
 
-	__u64	ctime;		/* lo 40 bits are seconds, top 24 are microseconds or 0*/
-	__u32	level;		/* -4 (multipath), -1 (linear), 0,1,4,5 */
-	__u32	layout;		/* only for raid5 and raid10 currently */
-	__u64	size;		/* used size of component devices, in 512byte sectors */
+	__le64	ctime;		/* lo 40 bits are seconds, top 24 are microseconds or 0*/
+	__le32	level;		/* -4 (multipath), -1 (linear), 0,1,4,5 */
+	__le32	layout;		/* only for raid5 and raid10 currently */
+	__le64	size;		/* used size of component devices, in 512byte sectors */
 
-	__u32	chunksize;	/* in 512byte sectors */
-	__u32	raid_disks;
-	__u32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
+	__le32	chunksize;	/* in 512byte sectors */
+	__le32	raid_disks;
+	__le32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
 				 * NOTE: signed, so bitmap can be before superblock
 				 * only meaningful of feature_map[0] is set.
 				 */
 
 	/* These are only valid with feature bit '4' */
-	__u32	new_level;	/* new level we are reshaping to		*/
-	__u64	reshape_position;	/* next address in array-space for reshape */
-	__u32	delta_disks;	/* change in number of raid_disks		*/
-	__u32	new_layout;	/* new layout					*/
-	__u32	new_chunk;	/* new chunk size (bytes)			*/
+	__le32	new_level;	/* new level we are reshaping to		*/
+	__le64	reshape_position;	/* next address in array-space for reshape */
+	__le32	delta_disks;	/* change in number of raid_disks		*/
+	__le32	new_layout;	/* new layout					*/
+	__le32	new_chunk;	/* new chunk size (bytes)			*/
 	__u8	pad1[128-124];	/* set to 0 when written */
 
 	/* constant this-device information - 64 bytes */
-	__u64	data_offset;	/* sector start of data, often 0 */
-	__u64	data_size;	/* sectors in this device that can be used for data */
-	__u64	super_offset;	/* sector start of this superblock */
-	__u64	recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
-	__u32	dev_number;	/* permanent identifier of this  device - not role in raid */
-	__u32	cnt_corrected_read; /* number of read errors that were corrected by re-writing */
+	__le64	data_offset;	/* sector start of data, often 0 */
+	__le64	data_size;	/* sectors in this device that can be used for data */
+	__le64	super_offset;	/* sector start of this superblock */
+	__le64	recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+	__le32	dev_number;	/* permanent identifier of this  device - not role in raid */
+	__le32	cnt_corrected_read; /* number of read errors that were corrected by re-writing */
 	__u8	device_uuid[16]; /* user-space setable, ignored by kernel */
 	__u8	devflags;	/* per-device flags.  Only one defined...*/
 #define	WriteMostly1	1	/* mask for writemostly flag in above */
 	__u8	pad2[64-57];	/* set to 0 when writing */
 
 	/* array state information - 64 bytes */
-	__u64	utime;		/* 40 bits second, 24 btes microseconds */
-	__u64	events;		/* incremented when superblock updated */
-	__u64	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
-	__u32	sb_csum;	/* checksum upto devs[max_dev] */
-	__u32	max_dev;	/* size of devs[] array to consider */
+	__le64	utime;		/* 40 bits second, 24 btes microseconds */
+	__le64	events;		/* incremented when superblock updated */
+	__le64	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
+	__le32	sb_csum;	/* checksum upto devs[max_dev] */
+	__le32	max_dev;	/* size of devs[] array to consider */
 	__u8	pad3[64-32];	/* set to 0 when writing */
 
 	/* device state information. Indexed by dev_number.
@@ -260,7 +260,7 @@
 	 * into the 'roles' value.  If a device is spare or faulty, then it doesn't
 	 * have a meaningful role.
 	 */
-	__u16	dev_roles[0];	/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
+	__le16	dev_roles[0];	/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
 };
 
 /* feature_map bits */
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
index d0dd38b..d22ad39 100644
--- a/include/linux/raid_class.h
+++ b/include/linux/raid_class.h
@@ -77,5 +77,6 @@
 struct raid_template *raid_class_attach(struct raid_function_template *);
 void raid_class_release(struct raid_template *);
 
-void raid_component_add(struct raid_template *, struct device *,
-			struct device *);
+int __must_check raid_component_add(struct raid_template *, struct device *,
+				    struct device *);
+
diff --git a/include/linux/random.h b/include/linux/random.h
index 5d6456b..0248b30 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -69,6 +69,9 @@
 unsigned int get_random_int(void);
 unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
+u32 random32(void);
+void srandom32(u32 seed);
+
 #endif /* __KERNEL___ */
 
 #endif /* _LINUX_RANDOM_H */
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index b89f093..09ff4c3 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -208,7 +208,7 @@
 int rtc_unregister(rtc_task_t *task);
 int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
 void rtc_get_rtc_time(struct rtc_time *rtc_tm);
-irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t rtc_interrupt(int irq, void *dev_id);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 331f450..6735c1c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1065,9 +1065,10 @@
 }
 
 /**
- * is_init - check if a task structure is the first user space
- *	     task the kernel created.
- * @p: Task structure to be checked.
+ * is_init - check if a task structure is init
+ * @tsk: Task structure to be checked.
+ *
+ * Check if a task structure is the first user space task the kernel created.
  */
 static inline int is_init(struct task_struct *tsk)
 {
diff --git a/include/linux/security.h b/include/linux/security.h
index 9b5fea8..b200b98 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -882,7 +882,8 @@
  *	Check permission when a flow selects a xfrm_policy for processing
  *	XFRMs on a packet.  The hook is called when selecting either a
  *	per-socket policy or a generic xfrm policy.
- *	Return 0 if permission is granted.
+ *	Return 0 if permission is granted, -ESRCH otherwise, or -errno
+ *	on other errors.
  * @xfrm_state_pol_flow_match:
  *	@x contains the state to match.
  *	@xp contains the policy to check for a match.
@@ -891,6 +892,7 @@
  * @xfrm_flow_state_match:
  *	@fl contains the flow key to match.
  *	@xfrm points to the xfrm_state to match.
+ *	@xp points to the xfrm_policy to match.
  *	Return 1 if there is a match.
  * @xfrm_decode_session:
  *	@skb points to skb to decode.
@@ -1388,7 +1390,8 @@
 	int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
 	int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
 			struct xfrm_policy *xp, struct flowi *fl);
-	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm);
+	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm,
+			struct xfrm_policy *xp);
 	int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 
@@ -3120,11 +3123,6 @@
 	return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL);
 }
 
-static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
-{
-	return security_ops->xfrm_policy_alloc_security(xp, NULL, sk);
-}
-
 static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
 {
 	return security_ops->xfrm_policy_clone_security(old, new);
@@ -3175,9 +3173,10 @@
 	return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
 }
 
-static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+static inline int security_xfrm_flow_state_match(struct flowi *fl,
+			struct xfrm_state *xfrm, struct xfrm_policy *xp)
 {
-	return security_ops->xfrm_flow_state_match(fl, xfrm);
+	return security_ops->xfrm_flow_state_match(fl, xfrm, xp);
 }
 
 static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
@@ -3197,11 +3196,6 @@
 	return 0;
 }
 
-static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
-{
-	return 0;
-}
-
 static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
 {
 	return 0;
@@ -3249,7 +3243,7 @@
 }
 
 static inline int security_xfrm_flow_state_match(struct flowi *fl,
-                                struct xfrm_state *xfrm)
+			struct xfrm_state *xfrm, struct xfrm_policy *xp)
 {
 	return 1;
 }
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b661c19..463ab95 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -409,13 +409,12 @@
  * The following are helper functions for the low level drivers.
  */
 static inline int
-uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
-		       struct pt_regs *regs)
+uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
 {
 #ifdef SUPPORT_SYSRQ
 	if (port->sysrq) {
 		if (ch && time_before(jiffies, port->sysrq)) {
-			handle_sysrq(ch, regs, port->info->tty);
+			handle_sysrq(ch, port->info->tty);
 			port->sysrq = 0;
 			return 1;
 		}
@@ -425,7 +424,7 @@
 	return 0;
 }
 #ifndef SUPPORT_SYSRQ
-#define uart_handle_sysrq_char(port,ch,regs) uart_handle_sysrq_char(port, 0, NULL)
+#define uart_handle_sysrq_char(port,ch) uart_handle_sysrq_char(port, 0)
 #endif
 
 /*
diff --git a/include/linux/serio.h b/include/linux/serio.h
index c906931..b99c5ca 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -41,6 +41,7 @@
 	void (*stop)(struct serio *);
 
 	struct serio *parent, *child;
+	unsigned int depth;		/* level of nesting in serio hierarchy */
 
 	struct serio_driver *drv;	/* accessed from interrupt, must be protected by serio->lock and serio->sem */
 	struct mutex drv_mutex;		/* protects serio->drv so attributes can pin driver */
@@ -60,8 +61,7 @@
 	unsigned int manual_bind;
 
 	void (*write_wakeup)(struct serio *);
-	irqreturn_t (*interrupt)(struct serio *, unsigned char,
-			unsigned int, struct pt_regs *);
+	irqreturn_t (*interrupt)(struct serio *, unsigned char, unsigned int);
 	int  (*connect)(struct serio *, struct serio_driver *drv);
 	int  (*reconnect)(struct serio *);
 	void (*disconnect)(struct serio *);
@@ -75,7 +75,7 @@
 void serio_close(struct serio *serio);
 void serio_rescan(struct serio *serio);
 void serio_reconnect(struct serio *serio);
-irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
+irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags);
 
 void __serio_register_port(struct serio *serio, struct module *owner);
 static inline void serio_register_port(struct serio *serio)
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index 367d6c3..13b3af5 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -43,17 +43,17 @@
 
 /* macro names are short for word, double-word, long value (?) */
 #define WVAL(buf,pos) \
-	(le16_to_cpu(get_unaligned((u16 *)((u8 *)(buf) + (pos)))))
+	(le16_to_cpu(get_unaligned((__le16 *)((u8 *)(buf) + (pos)))))
 #define DVAL(buf,pos) \
-	(le32_to_cpu(get_unaligned((u32 *)((u8 *)(buf) + (pos)))))
+	(le32_to_cpu(get_unaligned((__le32 *)((u8 *)(buf) + (pos)))))
 #define LVAL(buf,pos) \
-	(le64_to_cpu(get_unaligned((u64 *)((u8 *)(buf) + (pos)))))
+	(le64_to_cpu(get_unaligned((__le64 *)((u8 *)(buf) + (pos)))))
 #define WSET(buf,pos,val) \
-	put_unaligned(cpu_to_le16((u16)(val)), (u16 *)((u8 *)(buf) + (pos)))
+	put_unaligned(cpu_to_le16((u16)(val)), (__le16 *)((u8 *)(buf) + (pos)))
 #define DSET(buf,pos,val) \
-	put_unaligned(cpu_to_le32((u32)(val)), (u32 *)((u8 *)(buf) + (pos)))
+	put_unaligned(cpu_to_le32((u32)(val)), (__le32 *)((u8 *)(buf) + (pos)))
 #define LSET(buf,pos,val) \
-	put_unaligned(cpu_to_le64((u64)(val)), (u64 *)((u8 *)(buf) + (pos)))
+	put_unaligned(cpu_to_le64((u64)(val)), (__le64 *)((u8 *)(buf) + (pos)))
 
 /* where to find the base of the SMB packet proper */
 #define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index 1e65f2d..606cb21 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -56,7 +56,9 @@
 	RPC_PROG_MISMATCH = 2,
 	RPC_PROC_UNAVAIL = 3,
 	RPC_GARBAGE_ARGS = 4,
-	RPC_SYSTEM_ERR = 5
+	RPC_SYSTEM_ERR = 5,
+	/* internal use only */
+	RPC_DROP_REPLY = 60000,
 };
 
 enum rpc_reject_stat {
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index d6288e8..965d6c2 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -57,7 +57,8 @@
 	struct svc_stat *	sv_stats;	/* RPC statistics */
 	spinlock_t		sv_lock;
 	unsigned int		sv_nrthreads;	/* # of server threads */
-	unsigned int		sv_bufsz;	/* datagram buffer size */
+	unsigned int		sv_max_payload;	/* datagram payload size */
+	unsigned int		sv_max_mesg;	/* max_payload + 1 page for overheads */
 	unsigned int		sv_xdrsize;	/* XDR buffer size */
 
 	struct list_head	sv_permsocks;	/* all permanent sockets */
@@ -334,7 +335,7 @@
 /*
  * RPC procedure info
  */
-typedef int	(*svc_procfunc)(struct svc_rqst *, void *argp, void *resp);
+typedef __be32	(*svc_procfunc)(struct svc_rqst *, void *argp, void *resp);
 struct svc_procedure {
 	svc_procfunc		pc_func;	/* process the request */
 	kxdrproc_t		pc_decode;	/* XDR decode args */
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 953723b..ac69e55 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -74,6 +74,7 @@
 #define	rpc_proc_unavail	__constant_htonl(RPC_PROC_UNAVAIL)
 #define	rpc_garbage_args	__constant_htonl(RPC_GARBAGE_ARGS)
 #define	rpc_system_err		__constant_htonl(RPC_SYSTEM_ERR)
+#define	rpc_drop_reply		__constant_htonl(RPC_DROP_REPLY)
 
 #define	rpc_auth_ok		__constant_htonl(RPC_AUTH_OK)
 #define	rpc_autherr_badcred	__constant_htonl(RPC_AUTH_BADCRED)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3efcfc7..1912c6c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -431,6 +431,10 @@
 				struct epoll_event __user *event);
 asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
 				int maxevents, int timeout);
+asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
+				int maxevents, int timeout,
+				const sigset_t __user *sigmask,
+				size_t sigsetsize);
 asmlinkage long sys_gethostname(char __user *name, int len);
 asmlinkage long sys_sethostname(char __user *name, int len);
 asmlinkage long sys_setdomainname(char __user *name, int len);
@@ -593,7 +597,7 @@
 asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
 					unsigned int flags);
 asmlinkage long sys_get_robust_list(int pid,
-				    struct robust_list_head __user **head_ptr,
+				    struct robust_list_head __user * __user *head_ptr,
 				    size_t __user *len_ptr);
 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
 				    size_t len);
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index e657e52..9df8833 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -29,7 +29,7 @@
 #define SYSRQ_ENABLE_RTNICE	0x0100
 
 struct sysrq_key_op {
-	void (*handler)(int, struct pt_regs *, struct tty_struct *);
+	void (*handler)(int, struct tty_struct *);
 	char *help_msg;
 	char *action_msg;
 	int enable_mask;
@@ -42,8 +42,8 @@
  * are available -- else NULL's).
  */
 
-void handle_sysrq(int, struct pt_regs *, struct tty_struct *);
-void __handle_sysrq(int, struct pt_regs *, struct tty_struct *, int check_mask);
+void handle_sysrq(int, struct tty_struct *);
+void __handle_sysrq(int, struct tty_struct *, int check_mask);
 int register_sysrq_key(int, struct sysrq_key_op *);
 int unregister_sysrq_key(int, struct sysrq_key_op *);
 struct sysrq_key_op *__sysrq_get_key_op(int key);
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 0e058a2..2d36f6d 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -342,6 +342,8 @@
 
 	unsigned long last_synq_overflow; 
 
+	__u32	tso_deferred;
+
 /* Receiver side RTT estimation */
 	struct {
 		__u32	rtt;
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index 203dd5e..dfb8052 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -17,6 +17,7 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/scatterlist.h>
 
 /* Host registers (relative to pci base address): */
 enum {
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 049dfe4..db501dc 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -293,6 +293,9 @@
 extern void update_ntp_one_tick(void);
 extern int do_adjtimex(struct timex *);
 
+/* Don't use! Compatibility define for existing users. */
+#define tickadj	(500/HZ ? : 1)
+
 #endif /* KERNEL */
 
 #endif /* LINUX_TIMEX_H */
diff --git a/include/linux/tipc.h b/include/linux/tipc.h
index 243a15f..bea4694 100644
--- a/include/linux/tipc.h
+++ b/include/linux/tipc.h
@@ -129,6 +129,7 @@
 
 #define TIPC_SUB_PORTS     	0x01  	/* filter for port availability */
 #define TIPC_SUB_SERVICE     	0x02  	/* filter for service availability */
+#define TIPC_SUB_CANCEL         0x04    /* cancel a subscription */
 #if 0
 /* The following filter options are not currently implemented */
 #define TIPC_SUB_NO_BIND_EVTS	0x04	/* filter out "publish" events */
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index fc62887..61eef50 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -351,6 +351,14 @@
 	__fs64   cs_spare[3];	/* future expansion */
 };
 
+struct ufs_csum_core {
+	__u64	cs_ndir;	/* number of directories */
+	__u64	cs_nbfree;	/* number of free blocks */
+	__u64	cs_nifree;	/* number of free inodes */
+	__u64	cs_nffree;	/* number of free frags */
+	__u64   cs_numclusters;	/* number of free clusters */
+};
+
 /*
  * File system flags
  */
@@ -715,7 +723,7 @@
 
 struct ufs_sb_private_info {
 	struct ufs_buffer_head s_ubh; /* buffer containing super block */
-	struct ufs2_csum_total cs_total;
+	struct ufs_csum_core cs_total;
 	__u32	s_sblkno;	/* offset of super-blocks in filesys */
 	__u32	s_cblkno;	/* offset of cg-block in filesys */
 	__u32	s_iblkno;	/* offset of inode-blocks in filesys */
diff --git a/include/linux/unwind.h b/include/linux/unwind.h
index 73e1751..749928c 100644
--- a/include/linux/unwind.h
+++ b/include/linux/unwind.h
@@ -26,6 +26,7 @@
  * Initialize unwind support.
  */
 extern void unwind_init(void);
+extern void unwind_setup(void);
 
 #ifdef CONFIG_MODULES
 
@@ -73,6 +74,7 @@
 struct unwind_frame_info {};
 
 static inline void unwind_init(void) {}
+static inline void unwind_setup(void) {}
 
 #ifdef CONFIG_MODULES
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 190cc1b..5482bfb 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -764,9 +764,8 @@
 };
 
 struct urb;
-struct pt_regs;
 
-typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
+typedef void (*usb_complete_t)(struct urb *);
 
 /**
  * struct urb - USB Request Block
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 91c983e..91b3ea2 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -226,10 +226,10 @@
 	int  (*tiocmget)	(struct usb_serial_port *port, struct file *file);
 	int  (*tiocmset)	(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
 
-	void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
-	void (*write_int_callback)(struct urb *urb, struct pt_regs *regs);
-	void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
-	void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
+	void (*read_int_callback)(struct urb *urb);
+	void (*write_int_callback)(struct urb *urb);
+	void (*read_bulk_callback)(struct urb *urb);
+	void (*write_bulk_callback)(struct urb *urb);
 };
 #define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
 
@@ -262,8 +262,8 @@
 extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write_room (struct usb_serial_port *port);
 extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
-extern void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-extern void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
+extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
+extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
 extern void usb_serial_generic_shutdown (struct usb_serial *serial);
 extern int usb_serial_generic_register (int debug);
 extern void usb_serial_generic_deregister (void);
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index c5fdf62..df5c465 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -243,7 +243,7 @@
 #define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y','U','1','2') /* 12  YUV 4:2:0     */
 #define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y','Y','U','V') /* 16  YUV 4:2:2     */
 #define V4L2_PIX_FMT_HI240   v4l2_fourcc('H','I','2','4') /*  8  8-bit color   */
-#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H','M','1','2') /*  8  YUV 4:1:1 16x16 macroblocks */
+#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H','M','1','2') /*  8  YUV 4:2:0 16x16 macroblocks */
 
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index a341c80..fc35e6b 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -85,7 +85,6 @@
 void laptop_io_completion(void);
 void laptop_sync_completion(void);
 void throttle_vm_writeout(void);
-void writeback_congestion_end(void);
 
 /* These are exported to sysctl. */
 extern int dirty_background_ratio;
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index cda8a96..0e7f1e2 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -41,6 +41,7 @@
 };
 
 ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
 int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
 int vfs_removexattr(struct dentry *, char *);
 
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index df22efc..c0fc396 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -153,6 +153,7 @@
 	__u8             mode;
 	__u8		 type;
 	__u8		 out;
+	__u8		 attempt;
 	__u8		 dev_class[3];
 	__u8             features[8];
 	__u16            interval;
@@ -289,6 +290,22 @@
 	return NULL;
 }
 
+static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
+					__u8 type, __u16 state)
+{
+	struct hci_conn_hash *h = &hdev->conn_hash;
+	struct list_head *p;
+	struct hci_conn  *c;
+
+	list_for_each(p, &h->list) {
+		c = list_entry(p, struct hci_conn, list);
+		if (c->type == type && c->state == state)
+			return c;
+	}
+	return NULL;
+}
+
+void hci_acl_connect(struct hci_conn *conn);
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
 void hci_add_sco(struct hci_conn *conn, __u16 handle);
 
diff --git a/include/net/dn.h b/include/net/dn.h
index 465b783..ac4ce90 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -199,11 +199,6 @@
 {
 	fl->uli_u.dnports.sport = scp->addrloc;
 	fl->uli_u.dnports.dport = scp->addrrem;
-	fl->uli_u.dnports.objnum = scp->addr.sdn_objnum;
-	if (fl->uli_u.dnports.objnum == 0) {
-		fl->uli_u.dnports.objnamel = (__u8)dn_ntohs(scp->addr.sdn_objnamel);
-		memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16);
-	}
 }
 
 extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu);
diff --git a/include/net/flow.h b/include/net/flow.h
index ddf5f3c..5cda27c 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -68,9 +68,6 @@
 		struct {
 			__le16	sport;
 			__le16	dport;
-			__u8	objnum;
-			__u8	objnamel; /* Not 16 bits since max val is 16 */
-			__u8	objname[16]; /* Not zero terminated */
 		} dnports;
 
 		__be32		spi;
@@ -97,7 +94,7 @@
 #define FLOW_DIR_FWD	2
 
 struct sock;
-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+typedef int (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
 			       void **objp, atomic_t **obj_refp);
 
 extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index 425b3a5..617b672 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -63,13 +63,11 @@
 
 /*
  * Information about association
- *
- * Do we need a lock for this?
- * We only ever use this structure inlined
- * into our global struct. I've used its lock,
- * but maybe we need a local one here?
  */
 struct ieee80211softmac_assoc_info {
+
+	struct mutex mutex;
+
 	/*
 	 * This is the requested ESSID. It is written
 	 * only by the WX handlers.
@@ -99,12 +97,13 @@
 	 *
 	 * bssfixed is used for SIOCSIWAP.
 	 */
-	u8 static_essid:1,
-	   short_preamble_available:1,
-	   associating:1,
-	   assoc_wait:1,
-	   bssvalid:1,
-	   bssfixed:1;
+	u8 static_essid;
+	u8 short_preamble_available;
+	u8 associating;
+	u8 associated;
+	u8 assoc_wait;
+	u8 bssvalid;
+	u8 bssfixed;
 
 	/* Scan retries remaining */
 	int scan_retry;
@@ -229,12 +228,10 @@
 	/* private stuff follows */
 	/* this lock protects this structure */
 	spinlock_t lock;
-	
-	/* couple of flags */
-	u8 scanning:1, /* protects scanning from being done multiple times at once */
-	   associated:1,
-	   running:1;
-	
+
+	u8 running; /* SoftMAC started? */
+	u8 scanning;
+
 	struct ieee80211softmac_scaninfo *scaninfo;
 	struct ieee80211softmac_assoc_info associnfo;
 	struct ieee80211softmac_bss_info bssinfo;
@@ -250,7 +247,7 @@
 
 	/* we need to keep a list of network structs we copied */
 	struct list_head network_list;
-	
+
 	/* This must be the last item so that it points to the data
 	 * allocated beyond this structure by alloc_ieee80211 */
 	u8 priv[0];
@@ -295,7 +292,7 @@
 {
 	struct ieee80211softmac_txrates *txrates = &mac->txrates;
 
-	if (!mac->associated)
+	if (!mac->associnfo.associated)
 		return txrates->mgt_mcast_rate;
 
 	/* We are associated, sending unicast frame */
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 6d14c22..5f48748 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -196,6 +196,7 @@
 {
 	if (atomic_dec_and_test(&tw->tw_refcnt)) {
 		struct module *owner = tw->tw_prot->owner;
+		twsk_destructor((struct sock *)tw);
 #ifdef SOCK_REFCNT_DEBUG
 		printk(KERN_DEBUG "%s timewait_sock %p released\n",
 		       tw->tw_prot->name, tw);
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 925573f..aa10a81 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -17,14 +17,15 @@
 
 struct inet_peer
 {
+	/* group together avl_left,avl_right,v4daddr to speedup lookups */
 	struct inet_peer	*avl_left, *avl_right;
-	struct inet_peer	*unused_next, **unused_prevp;
-	unsigned long		dtime;		/* the time of last use of not
-						 * referenced entries */
-	atomic_t		refcnt;
 	__be32			v4daddr;	/* peer's address */
 	__u16			avl_height;
 	__u16			ip_id_count;	/* IP ID for the next packet */
+	struct inet_peer	*unused_next, **unused_prevp;
+	__u32			dtime;		/* the time of last use of not
+						 * referenced entries */
+	atomic_t		refcnt;
 	atomic_t		rid;		/* Frag reception counter */
 	__u32			tcp_ts;
 	unsigned long		tcp_ts_stamp;
@@ -35,21 +36,8 @@
 /* can be called with or without local BH being disabled */
 struct inet_peer	*inet_getpeer(__be32 daddr, int create);
 
-extern spinlock_t inet_peer_unused_lock;
-extern struct inet_peer **inet_peer_unused_tailp;
 /* can be called from BH context or outside */
-static inline void	inet_putpeer(struct inet_peer *p)
-{
-	spin_lock_bh(&inet_peer_unused_lock);
-	if (atomic_dec_and_test(&p->refcnt)) {
-		p->unused_prevp = inet_peer_unused_tailp;
-		p->unused_next = NULL;
-		*inet_peer_unused_tailp = p;
-		inet_peer_unused_tailp = &p->unused_next;
-		p->dtime = jiffies;
-	}
-	spin_unlock_bh(&inet_peer_unused_lock);
-}
+extern void inet_putpeer(struct inet_peer *p);
 
 extern spinlock_t inet_peer_idlock;
 /* can be called with or without local BH being disabled */
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 6ca6b71..c14b70e 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -36,13 +36,6 @@
 #define RT6_LOOKUP_F_REACHABLE	0x2
 #define RT6_LOOKUP_F_HAS_SADDR	0x4
 
-struct pol_chain {
-	int			type;
-	int			priority;
-	struct fib6_node	*rules;
-	struct pol_chain	*next;
-};
-
 extern struct rt6_info	ip6_null_entry;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 8222914..949b932 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -21,17 +21,14 @@
 #include <net/fib_rules.h>
 
 struct fib_config {
-	u8			fc_family;
 	u8			fc_dst_len;
-	u8			fc_src_len;
 	u8			fc_tos;
 	u8			fc_protocol;
 	u8			fc_scope;
 	u8			fc_type;
-	/* 1 byte unused */
+	/* 3 bytes unused */
 	u32			fc_table;
 	__be32			fc_dst;
-	__be32			fc_src;
 	__be32			fc_gw;
 	int			fc_oif;
 	u32			fc_flags;
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index c63a580..12c214b 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -34,6 +34,7 @@
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <net/netlink.h>
+#include <asm/atomic.h>
 
 /*
  * NetLabel - A management interface for maintaining network packet label
@@ -106,6 +107,7 @@
 
 /* LSM security attributes */
 struct netlbl_lsm_cache {
+	atomic_t refcount;
 	void (*free) (const void *data);
 	void *data;
 };
@@ -117,7 +119,7 @@
 	unsigned char *mls_cat;
 	size_t mls_cat_len;
 
-	struct netlbl_lsm_cache cache;
+	struct netlbl_lsm_cache *cache;
 };
 
 /*
@@ -126,6 +128,43 @@
 
 
 /**
+ * netlbl_secattr_cache_alloc - Allocate and initialize a secattr cache
+ * @flags: the memory allocation flags
+ *
+ * Description:
+ * Allocate and initialize a netlbl_lsm_cache structure.  Returns a pointer
+ * on success, NULL on failure.
+ *
+ */
+static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
+{
+	struct netlbl_lsm_cache *cache;
+
+	cache = kzalloc(sizeof(*cache), flags);
+	if (cache)
+		atomic_set(&cache->refcount, 1);
+	return cache;
+}
+
+/**
+ * netlbl_secattr_cache_free - Frees a netlbl_lsm_cache struct
+ * @cache: the struct to free
+ *
+ * Description:
+ * Frees @secattr including all of the internal buffers.
+ *
+ */
+static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
+{
+	if (!atomic_dec_and_test(&cache->refcount))
+		return;
+
+	if (cache->free)
+		cache->free(cache->data);
+	kfree(cache);
+}
+
+/**
  * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct
  * @secattr: the struct to initialize
  *
@@ -143,20 +182,16 @@
 /**
  * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct
  * @secattr: the struct to clear
- * @clear_cache: cache clear flag
  *
  * Description:
  * Destroys the @secattr struct, including freeing all of the internal buffers.
- * If @clear_cache is true then free the cache fields, otherwise leave them
- * intact.  The struct must be reset with a call to netlbl_secattr_init()
- * before reuse.
+ * The struct must be reset with a call to netlbl_secattr_init() before reuse.
  *
  */
-static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr,
-					  u32 clear_cache)
+static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
 {
-	if (clear_cache && secattr->cache.data != NULL && secattr->cache.free)
-		secattr->cache.free(secattr->cache.data);
+	if (secattr->cache)
+		netlbl_secattr_cache_free(secattr->cache);
 	kfree(secattr->domain);
 	kfree(secattr->mls_cat);
 }
@@ -178,17 +213,14 @@
 /**
  * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct
  * @secattr: the struct to free
- * @clear_cache: cache clear flag
  *
  * Description:
- * Frees @secattr including all of the internal buffers.  If @clear_cache is
- * true then free the cache fields, otherwise leave them intact.
+ * Frees @secattr including all of the internal buffers.
  *
  */
-static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr,
-				       u32 clear_cache)
+static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
 {
-	netlbl_secattr_destroy(secattr, clear_cache);
+	netlbl_secattr_destroy(secattr);
 	kfree(secattr);
 }
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ee68a31..764e3af 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -139,6 +139,7 @@
 void sctp_write_space(struct sock *sk);
 unsigned int sctp_poll(struct file *file, struct socket *sock,
 		poll_table *wait);
+void sctp_sock_rfree(struct sk_buff *skb);
 
 /*
  * sctp/primitive.c
@@ -444,6 +445,19 @@
 	return result;
 }
 
+/* SCTP version of skb_set_owner_r.  We need this one because
+ * of the way we have to do receive buffer accounting on bundled
+ * chunks.
+ */
+static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+	struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+	skb->sk = sk;
+	skb->destructor = sctp_sock_rfree;
+	atomic_add(event->rmem_len, &sk->sk_rmem_alloc);
+}
+
 /* Tests if the list has one and only one entry. */
 static inline int sctp_list_single_entry(struct list_head *head)
 {
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 6c40cfc..1a4ddc1 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -63,6 +63,7 @@
 	__u32 cumtsn;
 	int msg_flags;
 	int iif;
+	unsigned int rmem_len;
 };
 
 /* Retrieve the skb this event sits inside of. */
diff --git a/include/net/sock.h b/include/net/sock.h
index 40bb90e..ac286a3 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -884,8 +884,7 @@
 
 /**
  *	sk_filter_release: Release a socket filter
- *	@sk: socket
- *	@fp: filter to remove
+ *	@rcu: rcu_head that contains the sk_filter info to remove
  *
  *	Remove a filter from a socket and release its resources.
  */
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
index 2544281..be293d7 100644
--- a/include/net/timewait_sock.h
+++ b/include/net/timewait_sock.h
@@ -19,6 +19,7 @@
 	unsigned int	twsk_obj_size;
 	int		(*twsk_unique)(struct sock *sk,
 				       struct sock *sktw, void *twp);
+	void		(*twsk_destructor)(struct sock *sk);
 };
 
 static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -28,4 +29,10 @@
 	return 0;
 }
 
+static inline void twsk_destructor(struct sock *sk)
+{
+	if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
+		sk->sk_prot->twsk_prot->twsk_destructor(sk);
+}
+
 #endif /* _TIMEWAIT_SOCK_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1e2a4dd..737fdb2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -995,7 +995,8 @@
 				  int create, unsigned short family);
 extern void xfrm_policy_flush(u8 type);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
-extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict);
+extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
+			  struct flowi *fl, int family, int strict);
 extern void xfrm_init_pmtu(struct dst_entry *dst);
 
 extern wait_queue_head_t km_waitq;
diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index 0a487fe..519c49a 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -11,26 +11,10 @@
 Original driver (sg.h):
 *       Copyright (C) 1992 Lawrence Foard
 Version 2 and 3 extensions to driver:
-*       Copyright (C) 1998 - 2003 Douglas Gilbert
+*       Copyright (C) 1998 - 2006 Douglas Gilbert
 
-    Version: 3.5.29 (20030529)
-    This version is for 2.5 series kernels.
-
-    Changes since 3.5.28 (20030308)
-	- fix bug introduced in version 3.1.24 (last segment of sgat list)
-    Changes since 3.5.27 (20020812)
-    	- remove procfs entries: hosts, host_hdr + host_strs (now in sysfs)
-	- add sysfs sg driver params: def_reserved_size, allow_dio, version
-	- new boot option: "sg_allow_dio" and module parameter: "allow_dio"
-        - multiple internal changes due to scsi subsystem rework	
-    Changes since 3.5.26 (20020708)
-	- re-add direct IO using Kai Makisara's work
-	- re-tab to 8, start using C99-isms
-	- simplify memory management
-    Changes since 3.5.25 (20020504)
-	- driverfs additions
-	- copy_to/from_user() fixes [William Stinson]
-	- disable kiobufs support
+    Version: 3.5.34 (20060920)
+    This version is for 2.6 series kernels.
 
     For a full changelog see http://www.torque.net/sg
 
@@ -40,7 +24,7 @@
        2.1.40            2.2.20
        3.0.x             optional version 3 sg driver for 2.2 series
        3.1.17++          2.4.0++
-       3.5.23++          2.5.0++
+       3.5.30++          2.6.0++
 
 Major new features in SG 3.x driver (cf SG 2.x drivers)
 	- SG_IO ioctl() combines function if write() and read()
@@ -51,14 +35,15 @@
  data into kernel buffers and then use the CPU to copy the data into the 
  user space (vice versa for writes). That is called "indirect" IO due to 
  the double handling of data. There are two methods offered to remove the
- redundant copy: 1) direct IO which uses the kernel kiobuf mechanism and 
- 2) using the mmap() system call to map the reserve buffer (this driver has 
- one reserve buffer per fd) into the user space. Both have their advantages.
+ redundant copy: 1) direct IO and 2) using the mmap() system call to map
+ the reserve buffer (this driver has one reserve buffer per fd) into the
+ user space. Both have their advantages.
  In terms of absolute speed mmap() is faster. If speed is not a concern, 
  indirect IO should be fine. Read the documentation for more information.
 
- ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' may be
-         needed. That pseudo file's content is defaulted to 0. **
+ ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' or
+         'echo 1 > /sys/module/sg/parameters/allow_dio' is needed.
+         That attribute is 0 by default. **
  
  Historical note: this SCSI pass-through driver has been known as "sg" for 
  a decade. In broader kernel discussions "sg" is used to refer to scatter
@@ -72,20 +57,17 @@
  	http://www.torque.net/sg/p/sg_v3_ho.html
  This is a rendering from DocBook source [change the extension to "sgml"
  or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon).
+ The SG_IO ioctl is now found in other parts kernel (e.g. the block layer).
+ For more information see http://www.torque.net/sg/sg_io.html
 
  The older, version 2 documents discuss the original sg interface in detail:
 	http://www.torque.net/sg/p/scsi-generic.txt
 	http://www.torque.net/sg/p/scsi-generic_long.txt
- A version of this document (potentially out of date) may also be found in
- the kernel source tree, probably at:
-        Documentation/scsi/scsi-generic.txt .
+ Also available: <kernel_source>/Documentation/scsi/scsi-generic.txt
 
  Utility and test programs are available at the sg web site. They are 
- bundled as sg_utils (for the lk 2.2 series) and sg3_utils (for the
- lk 2.4 series).
-
- There is a HOWTO on the Linux SCSI subsystem in the lk 2.4 series at:
- 	http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO
+ packaged as sg3_utils (for the lk 2.4 and 2.6 series) and sg_utils
+ (for the lk 2.2 series).
 */
 
 
@@ -238,13 +220,12 @@
 #define SG_GET_ACCESS_COUNT 0x2289  
 
 
-#define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
+#define SG_SCATTER_SZ (8 * 4096)
 /* Largest size (in bytes) a single scatter-gather list element can have.
-   The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
-   i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
-   by adapter then this value is the largest data block that can be
-   read/written by a single scsi command. The user can find the value of
-   PAGE_SIZE by calling getpagesize() defined in unistd.h . */
+   The value used by the driver is 'max(SG_SCATTER_SZ, PAGE_SIZE)'.
+   This value should be a power of 2 (and may be rounded up internally).
+   If scatter-gather is not supported by adapter then this value is the
+   largest data block that can be read/written by a single scsi command. */
 
 #define SG_DEFAULT_RETRIES 0
 
diff --git a/include/sound/core.h b/include/sound/core.h
index b056ea9..fa1ca01 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -89,10 +89,10 @@
 struct snd_monitor_file {
 	struct file *file;
 	struct snd_monitor_file *next;
+	const struct file_operations *disconnected_f_op;
+	struct list_head shutdown_list;
 };
 
-struct snd_shutdown_f_ops;	/* define it later in init.c */
-
 /* main structure for soundcard */
 
 struct snd_card {
diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h
index 60b5b92..ab51ce1 100644
--- a/include/sound/cs4231.h
+++ b/include/sound/cs4231.h
@@ -273,7 +273,7 @@
 void snd_cs4231_mce_up(struct snd_cs4231 *chip);
 void snd_cs4231_mce_down(struct snd_cs4231 *chip);
 
-irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id);
 
 const char *snd_cs4231_chip_id(struct snd_cs4231 *chip);
 
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 892e310..3d3c151 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1194,7 +1194,7 @@
 int snd_emu10k1_timer(struct snd_emu10k1 * emu, int device);
 int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep);
 
-irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id);
 
 void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int voice);
 int snd_emu10k1_init_efx(struct snd_emu10k1 *emu);
diff --git a/include/sound/gus.h b/include/sound/gus.h
index 68a664a..c49ea57 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -638,7 +638,7 @@
 
 /* gus_irq.c */
 
-irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t snd_gus_interrupt(int irq, void *dev_id);
 #ifdef CONFIG_SND_DEBUG
 void snd_gus_irq_profile_init(struct snd_gus_card *gus);
 #endif
diff --git a/include/sound/initval.h b/include/sound/initval.h
index 2ae76ef..e85b907 100644
--- a/include/sound/initval.h
+++ b/include/sound/initval.h
@@ -53,7 +53,7 @@
 #ifdef SNDRV_LEGACY_FIND_FREE_IRQ
 #include <linux/interrupt.h>
 
-static irqreturn_t snd_legacy_empty_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_legacy_empty_irq_handler(int irq, void *dev_id)
 {
 	return IRQ_HANDLED;
 }
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index ac50432..8c88267 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -106,10 +106,8 @@
 
  */
 
-irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs);
-irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id,
-					 struct pt_regs *regs);
+irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id);
+irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id);
 
 int snd_mpu401_uart_new(struct snd_card *card,
 			int device,
diff --git a/include/sound/sb.h b/include/sound/sb.h
index 431d066..2dd5c8e 100644
--- a/include/sound/sb.h
+++ b/include/sound/sb.h
@@ -100,7 +100,7 @@
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_substream *midi_substream_input;
 	struct snd_rawmidi_substream *midi_substream_output;
-	irqreturn_t (*rmidi_callback)(int irq, void *dev_id, struct pt_regs *regs);
+	irq_handler_t rmidi_callback;
 
 	spinlock_t reg_lock;
 	spinlock_t open_lock;
@@ -286,7 +286,7 @@
 int snd_sbdsp_create(struct snd_card *card,
 		     unsigned long port,
 		     int irq,
-		     irqreturn_t (*irq_handler)(int, void *, struct pt_regs *),
+		     irq_handler_t irq_handler,
 		     int dma8, int dma16,
 		     unsigned short hardware,
 		     struct snd_sb **r_chip);
@@ -316,7 +316,7 @@
 const struct snd_pcm_ops *snd_sb16dsp_get_pcm_ops(int direction);
 int snd_sb16dsp_configure(struct snd_sb *chip);
 /* sb16.c */
-irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id);
 
 /* exported mixer stuffs */
 enum {
diff --git a/include/sound/version.h b/include/sound/version.h
index 2ee849d..52fd687 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
-/* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "1.0.12rc1"
-#define CONFIG_SND_DATE " (Thu Jun 22 13:55:50 2006 UTC)"
+/* include/version.h.  Generated by alsa/ksync script.  */
+#define CONFIG_SND_VERSION "1.0.13"
+#define CONFIG_SND_DATE " (Sun Oct 22 08:56:16 2006 UTC)"
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index dbca141..2173946 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -228,7 +228,7 @@
 /*
  * interrupt handler; exported for pcmcia
  */
-irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs);
+irqreturn_t snd_vx_irq_handler(int irq, void *dev);
 
 /*
  * lowlevel functions
diff --git a/init/Kconfig b/init/Kconfig
index 1038293..c8b2624 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1,5 +1,6 @@
 config DEFCONFIG_LIST
 	string
+	depends on !UML
 	option defconfig_list
 	default "/lib/modules/$UNAME_RELEASE/.config"
 	default "/etc/kernel-config"
diff --git a/init/main.c b/init/main.c
index ee12324..36f608a 100644
--- a/init/main.c
+++ b/init/main.c
@@ -503,6 +503,7 @@
 	printk(KERN_NOTICE);
 	printk(linux_banner);
 	setup_arch(&command_line);
+	unwind_setup();
 	setup_per_cpu_areas();
 	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
 
diff --git a/kernel/audit.c b/kernel/audit.c
index f9889ee..98106f6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -340,7 +340,7 @@
 {
 	struct sk_buff *skb;
 
-	while (1) {
+	while (!kthread_should_stop()) {
 		skb = skb_dequeue(&audit_skb_queue);
 		wake_up(&audit_backlog_wait);
 		if (skb) {
@@ -369,6 +369,7 @@
 			remove_wait_queue(&kauditd_wait, &wait);
 		}
 	}
+	return 0;
 }
 
 int audit_send_list(void *_dest)
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 32c9662..27dd3ee 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -19,7 +19,7 @@
 static DEFINE_MUTEX(cpu_add_remove_lock);
 static DEFINE_MUTEX(cpu_bitmask_lock);
 
-static __cpuinitdata BLOCKING_NOTIFIER_HEAD(cpu_chain);
+static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
 
 /* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
  * Should always be manipulated under cpu_add_remove_lock
@@ -68,7 +68,11 @@
 /* Need to know about CPUs going up/down? */
 int __cpuinit register_cpu_notifier(struct notifier_block *nb)
 {
-	return blocking_notifier_chain_register(&cpu_chain, nb);
+	int ret;
+	mutex_lock(&cpu_add_remove_lock);
+	ret = raw_notifier_chain_register(&cpu_chain, nb);
+	mutex_unlock(&cpu_add_remove_lock);
+	return ret;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -77,7 +81,9 @@
 
 void unregister_cpu_notifier(struct notifier_block *nb)
 {
-	blocking_notifier_chain_unregister(&cpu_chain, nb);
+	mutex_lock(&cpu_add_remove_lock);
+	raw_notifier_chain_unregister(&cpu_chain, nb);
+	mutex_unlock(&cpu_add_remove_lock);
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
@@ -126,7 +132,7 @@
 	if (!cpu_online(cpu))
 		return -EINVAL;
 
-	err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
+	err = raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
 						(void *)(long)cpu);
 	if (err == NOTIFY_BAD) {
 		printk("%s: attempt to take down CPU %u failed\n",
@@ -146,7 +152,7 @@
 
 	if (IS_ERR(p)) {
 		/* CPU didn't die: tell everyone.  Can't complain. */
-		if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
+		if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
 				(void *)(long)cpu) == NOTIFY_BAD)
 			BUG();
 
@@ -169,7 +175,7 @@
 	put_cpu();
 
 	/* CPU is completely dead: tell everyone.  Too late to complain. */
-	if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD,
+	if (raw_notifier_call_chain(&cpu_chain, CPU_DEAD,
 			(void *)(long)cpu) == NOTIFY_BAD)
 		BUG();
 
@@ -206,7 +212,7 @@
 	if (cpu_online(cpu) || !cpu_present(cpu))
 		return -EINVAL;
 
-	ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
+	ret = raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
 	if (ret == NOTIFY_BAD) {
 		printk("%s: attempt to bring up CPU %u failed\n",
 				__FUNCTION__, cpu);
@@ -223,11 +229,11 @@
 	BUG_ON(!cpu_online(cpu));
 
 	/* Now call notifier in preparation. */
-	blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
+	raw_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
 
 out_notify:
 	if (ret != 0)
-		blocking_notifier_call_chain(&cpu_chain,
+		raw_notifier_call_chain(&cpu_chain,
 				CPU_UP_CANCELED, hcpu);
 
 	return ret;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 9d850ae..6313c38 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2137,7 +2137,7 @@
  * See also the previous routine cpuset_handle_cpuhp().
  */
 
-void cpuset_track_online_nodes()
+void cpuset_track_online_nodes(void)
 {
 	common_cpu_mem_hotplug_unplug();
 }
diff --git a/kernel/fork.c b/kernel/fork.c
index 7dc6140..29ebb30 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -984,6 +984,8 @@
 	if (!p)
 		goto fork_out;
 
+	rt_mutex_init_task(p);
+
 #ifdef CONFIG_TRACE_IRQFLAGS
 	DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
 	DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
@@ -1088,8 +1090,6 @@
 	p->lockdep_recursion = 0;
 #endif
 
-	rt_mutex_init_task(p);
-
 #ifdef CONFIG_DEBUG_MUTEXES
 	p->blocked_on = NULL; /* not blocked yet */
 #endif
diff --git a/kernel/futex.c b/kernel/futex.c
index 4aaf919..b364e00 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1612,10 +1612,10 @@
  * @len_ptr: pointer to a length field, the kernel fills in the header size
  */
 asmlinkage long
-sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
 		    size_t __user *len_ptr)
 {
-	struct robust_list_head *head;
+	struct robust_list_head __user *head;
 	unsigned long ret;
 
 	if (!pid)
@@ -1694,14 +1694,15 @@
  * Fetch a robust-list pointer. Bit 0 signals PI futexes:
  */
 static inline int fetch_robust_entry(struct robust_list __user **entry,
-				     struct robust_list __user **head, int *pi)
+				     struct robust_list __user * __user *head,
+				     int *pi)
 {
 	unsigned long uentry;
 
-	if (get_user(uentry, (unsigned long *)head))
+	if (get_user(uentry, (unsigned long __user *)head))
 		return -EFAULT;
 
-	*entry = (void *)(uentry & ~1UL);
+	*entry = (void __user *)(uentry & ~1UL);
 	*pi = uentry & 1;
 
 	return 0;
@@ -1739,7 +1740,7 @@
 		return;
 
 	if (pending)
-		handle_futex_death((void *)pending + futex_offset, curr, pip);
+		handle_futex_death((void __user *)pending + futex_offset, curr, pip);
 
 	while (entry != &head->list) {
 		/*
@@ -1747,7 +1748,7 @@
 		 * don't process it twice:
 		 */
 		if (entry != pending)
-			if (handle_futex_death((void *)entry + futex_offset,
+			if (handle_futex_death((void __user *)entry + futex_offset,
 						curr, pi))
 				return;
 		/*
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index c5cca3f..50f24ee 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -18,7 +18,7 @@
  */
 static inline int
 fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
-		   compat_uptr_t *head, int *pi)
+		   compat_uptr_t __user *head, int *pi)
 {
 	if (get_user(*uentry, head))
 		return -EFAULT;
@@ -62,7 +62,7 @@
 			       &head->list_op_pending, &pip))
 		return;
 	if (upending)
-		handle_futex_death((void *)pending + futex_offset, curr, pip);
+		handle_futex_death((void __user *)pending + futex_offset, curr, pip);
 
 	while (compat_ptr(uentry) != &head->list) {
 		/*
@@ -70,7 +70,7 @@
 		 * dont process it twice:
 		 */
 		if (entry != pending)
-			if (handle_futex_death((void *)entry + futex_offset,
+			if (handle_futex_death((void __user *)entry + futex_offset,
 						curr, pi))
 				return;
 
@@ -78,7 +78,7 @@
 		 * Fetch the next entry in the list:
 		 */
 		if (fetch_robust_entry(&uentry, &entry,
-				       (compat_uptr_t *)&entry->next, &pi))
+				       (compat_uptr_t __user *)&entry->next, &pi))
 			return;
 		/*
 		 * Avoid excessively long or circular lists:
@@ -103,10 +103,10 @@
 }
 
 asmlinkage long
-compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
+compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
 			   compat_size_t __user *len_ptr)
 {
-	struct compat_robust_list_head *head;
+	struct compat_robust_list_head __user *head;
 	unsigned long ret;
 
 	if (!pid)
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 4cf65f5..2d0dc3e 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -249,7 +249,6 @@
  *	handle_simple_irq - Simple and software-decoded IRQs.
  *	@irq:	the interrupt number
  *	@desc:	the interrupt description structure for this irq
- *	@regs:	pointer to a register structure
  *
  *	Simple interrupts are either sent from a demultiplexing interrupt
  *	handler or come from hardware, where no interrupt hardware control
@@ -259,7 +258,7 @@
  *	unmask issues if necessary.
  */
 void fastcall
-handle_simple_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 {
 	struct irqaction *action;
 	irqreturn_t action_ret;
@@ -279,9 +278,9 @@
 	desc->status |= IRQ_INPROGRESS;
 	spin_unlock(&desc->lock);
 
-	action_ret = handle_IRQ_event(irq, regs, action);
+	action_ret = handle_IRQ_event(irq, action);
 	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret, regs);
+		note_interrupt(irq, desc, action_ret);
 
 	spin_lock(&desc->lock);
 	desc->status &= ~IRQ_INPROGRESS;
@@ -293,7 +292,6 @@
  *	handle_level_irq - Level type irq handler
  *	@irq:	the interrupt number
  *	@desc:	the interrupt description structure for this irq
- *	@regs:	pointer to a register structure
  *
  *	Level type interrupts are active as long as the hardware line has
  *	the active level. This may require to mask the interrupt and unmask
@@ -301,7 +299,7 @@
  *	interrupt line is back to inactive.
  */
 void fastcall
-handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+handle_level_irq(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int cpu = smp_processor_id();
 	struct irqaction *action;
@@ -329,9 +327,9 @@
 	desc->status &= ~IRQ_PENDING;
 	spin_unlock(&desc->lock);
 
-	action_ret = handle_IRQ_event(irq, regs, action);
+	action_ret = handle_IRQ_event(irq, action);
 	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret, regs);
+		note_interrupt(irq, desc, action_ret);
 
 	spin_lock(&desc->lock);
 	desc->status &= ~IRQ_INPROGRESS;
@@ -345,7 +343,6 @@
  *	handle_fasteoi_irq - irq handler for transparent controllers
  *	@irq:	the interrupt number
  *	@desc:	the interrupt description structure for this irq
- *	@regs:	pointer to a register structure
  *
  *	Only a single callback will be issued to the chip: an ->eoi()
  *	call when the interrupt has been serviced. This enables support
@@ -353,8 +350,7 @@
  *	details in hardware, transparently.
  */
 void fastcall
-handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc,
-		   struct pt_regs *regs)
+handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int cpu = smp_processor_id();
 	struct irqaction *action;
@@ -382,9 +378,9 @@
 	desc->status &= ~IRQ_PENDING;
 	spin_unlock(&desc->lock);
 
-	action_ret = handle_IRQ_event(irq, regs, action);
+	action_ret = handle_IRQ_event(irq, action);
 	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret, regs);
+		note_interrupt(irq, desc, action_ret);
 
 	spin_lock(&desc->lock);
 	desc->status &= ~IRQ_INPROGRESS;
@@ -398,7 +394,6 @@
  *	handle_edge_irq - edge type IRQ handler
  *	@irq:	the interrupt number
  *	@desc:	the interrupt description structure for this irq
- *	@regs:	pointer to a register structure
  *
  *	Interrupt occures on the falling and/or rising edge of a hardware
  *	signal. The occurence is latched into the irq controller hardware
@@ -412,7 +407,7 @@
  *	loop is left.
  */
 void fastcall
-handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+handle_edge_irq(unsigned int irq, struct irq_desc *desc)
 {
 	const unsigned int cpu = smp_processor_id();
 
@@ -463,9 +458,9 @@
 
 		desc->status &= ~IRQ_PENDING;
 		spin_unlock(&desc->lock);
-		action_ret = handle_IRQ_event(irq, regs, action);
+		action_ret = handle_IRQ_event(irq, action);
 		if (!noirqdebug)
-			note_interrupt(irq, desc, action_ret, regs);
+			note_interrupt(irq, desc, action_ret);
 		spin_lock(&desc->lock);
 
 	} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
@@ -480,12 +475,11 @@
  *	handle_percpu_IRQ - Per CPU local irq handler
  *	@irq:	the interrupt number
  *	@desc:	the interrupt description structure for this irq
- *	@regs:	pointer to a register structure
  *
  *	Per CPU interrupts on SMP machines without locking requirements
  */
 void fastcall
-handle_percpu_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 {
 	irqreturn_t action_ret;
 
@@ -494,9 +488,9 @@
 	if (desc->chip->ack)
 		desc->chip->ack(irq);
 
-	action_ret = handle_IRQ_event(irq, regs, desc->action);
+	action_ret = handle_IRQ_event(irq, desc->action);
 	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret, regs);
+		note_interrupt(irq, desc, action_ret);
 
 	if (desc->chip->eoi)
 		desc->chip->eoi(irq);
@@ -505,10 +499,8 @@
 #endif /* CONFIG_SMP */
 
 void
-__set_irq_handler(unsigned int irq,
-		  void fastcall (*handle)(unsigned int, irq_desc_t *,
-					  struct pt_regs *),
-		  int is_chained)
+__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+		  const char *name)
 {
 	struct irq_desc *desc;
 	unsigned long flags;
@@ -549,6 +541,7 @@
 		desc->depth = 1;
 	}
 	desc->handle_irq = handle;
+	desc->name = name;
 
 	if (handle != handle_bad_irq && is_chained) {
 		desc->status &= ~IRQ_DISABLED;
@@ -561,36 +554,16 @@
 
 void
 set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
-			 void fastcall (*handle)(unsigned int,
-						 struct irq_desc *,
-						 struct pt_regs *))
+			 irq_flow_handler_t handle)
 {
 	set_irq_chip(irq, chip);
-	__set_irq_handler(irq, handle, 0);
+	__set_irq_handler(irq, handle, 0, NULL);
 }
 
-/*
- * Get a descriptive string for the highlevel handler, for
- * /proc/interrupts output:
- */
-const char *
-handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *,
-					struct pt_regs *))
+void
+set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
+			      irq_flow_handler_t handle, const char *name)
 {
-	if (handle == handle_level_irq)
-		return "level  ";
-	if (handle == handle_fasteoi_irq)
-		return "fasteoi";
-	if (handle == handle_edge_irq)
-		return "edge   ";
-	if (handle == handle_simple_irq)
-		return "simple ";
-#ifdef CONFIG_SMP
-	if (handle == handle_percpu_irq)
-		return "percpu ";
-#endif
-	if (handle == handle_bad_irq)
-		return "bad    ";
-
-	return NULL;
+	set_irq_chip(irq, chip);
+	__set_irq_handler(irq, handle, 0, name);
 }
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 4c6cdba..42aa6f1 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -27,7 +27,7 @@
  * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
  */
 void fastcall
-handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+handle_bad_irq(unsigned int irq, struct irq_desc *desc)
 {
 	print_irq_desc(irq, desc);
 	kstat_this_cpu.irqs[irq]++;
@@ -115,7 +115,7 @@
 /*
  * Special, empty irq handler:
  */
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
+irqreturn_t no_action(int cpl, void *dev_id)
 {
 	return IRQ_NONE;
 }
@@ -123,13 +123,11 @@
 /**
  * handle_IRQ_event - irq action chain handler
  * @irq:	the interrupt number
- * @regs:	pointer to a register structure
  * @action:	the interrupt action chain for this irq
  *
  * Handles the action chain of an irq event
  */
-irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
-			     struct irqaction *action)
+irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
 {
 	irqreturn_t ret, retval = IRQ_NONE;
 	unsigned int status = 0;
@@ -140,7 +138,7 @@
 		local_irq_enable_in_hardirq();
 
 	do {
-		ret = action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id);
 		if (ret == IRQ_HANDLED)
 			status |= action->flags;
 		retval |= ret;
@@ -158,7 +156,6 @@
 /**
  * __do_IRQ - original all in one highlevel IRQ handler
  * @irq:	the interrupt number
- * @regs:	pointer to a register structure
  *
  * __do_IRQ handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
@@ -167,7 +164,7 @@
  * This is the original x86 implementation which is used for every
  * interrupt type.
  */
-fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
+fastcall unsigned int __do_IRQ(unsigned int irq)
 {
 	struct irq_desc *desc = irq_desc + irq;
 	struct irqaction *action;
@@ -182,7 +179,7 @@
 		 */
 		if (desc->chip->ack)
 			desc->chip->ack(irq);
-		action_ret = handle_IRQ_event(irq, regs, desc->action);
+		action_ret = handle_IRQ_event(irq, desc->action);
 		desc->chip->end(irq);
 		return 1;
 	}
@@ -233,11 +230,11 @@
 
 		spin_unlock(&desc->lock);
 
-		action_ret = handle_IRQ_event(irq, regs, action);
+		action_ret = handle_IRQ_event(irq, action);
 
 		spin_lock(&desc->lock);
 		if (!noirqdebug)
-			note_interrupt(irq, desc, action_ret, regs);
+			note_interrupt(irq, desc, action_ret);
 		if (likely(!(desc->status & IRQ_PENDING)))
 			break;
 		desc->status &= ~IRQ_PENDING;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 92be519..6879202 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -427,8 +427,7 @@
  *	IRQF_SAMPLE_RANDOM	The interrupt can be used for entropy
  *
  */
-int request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+int request_irq(unsigned int irq, irq_handler_t handler,
 		unsigned long irqflags, const char *devname, void *dev_id)
 {
 	struct irqaction *action;
@@ -475,4 +474,3 @@
 	return retval;
 }
 EXPORT_SYMBOL(request_irq);
-
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 607c780..9a35266 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -57,7 +57,7 @@
 	if (!irq_desc[irq].chip->set_affinity || no_irq_affinity)
 		return -EIO;
 
-	err = cpumask_parse(buffer, count, new_value);
+	err = cpumask_parse_user(buffer, count, new_value);
 	if (err)
 		return err;
 
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 35f10f7..5bfeaed 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -38,7 +38,7 @@
 		clear_bit(irq, irqs_resend);
 		desc = irq_desc + irq;
 		local_irq_disable();
-		desc->handle_irq(irq, desc, NULL);
+		desc->handle_irq(irq, desc);
 		local_irq_enable();
 	}
 }
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 417e980..543ea2e 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -16,7 +16,7 @@
 /*
  * Recovery handler for misrouted interrupts.
  */
-static int misrouted_irq(int irq, struct pt_regs *regs)
+static int misrouted_irq(int irq)
 {
 	int i;
 	int ok = 0;
@@ -49,7 +49,7 @@
 		while (action) {
 			/* Only shared IRQ handlers are safe to call */
 			if (action->flags & IRQF_SHARED) {
-				if (action->handler(i, action->dev_id, regs) ==
+				if (action->handler(i, action->dev_id) ==
 						IRQ_HANDLED)
 					ok = 1;
 			}
@@ -70,7 +70,7 @@
 			 */
 			work = 1;
 			spin_unlock(&desc->lock);
-			handle_IRQ_event(i, regs, action);
+			handle_IRQ_event(i, action);
 			spin_lock(&desc->lock);
 			desc->status &= ~IRQ_PENDING;
 		}
@@ -136,7 +136,7 @@
 }
 
 void note_interrupt(unsigned int irq, struct irq_desc *desc,
-		    irqreturn_t action_ret, struct pt_regs *regs)
+		    irqreturn_t action_ret)
 {
 	if (unlikely(action_ret != IRQ_HANDLED)) {
 		desc->irqs_unhandled++;
@@ -147,7 +147,7 @@
 	if (unlikely(irqfixup)) {
 		/* Don't punish working computers */
 		if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
-			int ok = misrouted_irq(irq, regs);
+			int ok = misrouted_irq(irq);
 			if (action_ret == IRQ_NONE)
 				desc->irqs_unhandled -= ok;
 		}
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 4c05534..b739be2 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -575,6 +575,8 @@
 	return 0;
 }
 
+#define RECURSION_LIMIT 40
+
 static int noinline print_infinite_recursion_bug(void)
 {
 	__raw_spin_unlock(&hash_lock);
@@ -595,7 +597,7 @@
 	debug_atomic_inc(&nr_cyclic_check_recursions);
 	if (depth > max_recursion_depth)
 		max_recursion_depth = depth;
-	if (depth >= 20)
+	if (depth >= RECURSION_LIMIT)
 		return print_infinite_recursion_bug();
 	/*
 	 * Check this lock's dependency list:
@@ -645,7 +647,7 @@
 
 	if (depth > max_recursion_depth)
 		max_recursion_depth = depth;
-	if (depth >= 20)
+	if (depth >= RECURSION_LIMIT)
 		return print_infinite_recursion_bug();
 
 	debug_atomic_inc(&nr_find_usage_forwards_checks);
@@ -684,7 +686,7 @@
 
 	if (depth > max_recursion_depth)
 		max_recursion_depth = depth;
-	if (depth >= 20)
+	if (depth >= RECURSION_LIMIT)
 		return print_infinite_recursion_bug();
 
 	debug_atomic_inc(&nr_find_usage_backwards_checks);
@@ -1114,8 +1116,6 @@
 	return count + 1;
 }
 
-extern void __error_too_big_MAX_LOCKDEP_SUBCLASSES(void);
-
 /*
  * Register a lock's class in the hash-table, if the class is not present
  * yet. Otherwise we look it up. We cache the result in the lock object
@@ -1153,8 +1153,7 @@
 	 * (or spin_lock_init()) call - which acts as the key. For static
 	 * locks we use the lock object itself as the key.
 	 */
-	if (sizeof(struct lock_class_key) > sizeof(struct lock_class))
-		__error_too_big_MAX_LOCKDEP_SUBCLASSES();
+	BUILD_BUG_ON(sizeof(struct lock_class_key) > sizeof(struct lock_class));
 
 	key = lock->key->subkeys + subclass;
 
@@ -1177,7 +1176,7 @@
  * itself, so actual lookup of the hash should be once per lock object.
  */
 static inline struct lock_class *
-register_lock_class(struct lockdep_map *lock, unsigned int subclass)
+register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
 {
 	struct lockdep_subclass_key *key;
 	struct list_head *hash_head;
@@ -1249,7 +1248,7 @@
 out_unlock_set:
 	__raw_spin_unlock(&hash_lock);
 
-	if (!subclass)
+	if (!subclass || force)
 		lock->class_cache = class;
 
 	DEBUG_LOCKS_WARN_ON(class->subclass != subclass);
@@ -1937,7 +1936,7 @@
  * Initialize a lock instance's lock-class mapping info:
  */
 void lockdep_init_map(struct lockdep_map *lock, const char *name,
-		      struct lock_class_key *key)
+		      struct lock_class_key *key, int subclass)
 {
 	if (unlikely(!debug_locks))
 		return;
@@ -1957,6 +1956,8 @@
 	lock->name = name;
 	lock->key = key;
 	lock->class_cache = NULL;
+	if (subclass)
+		register_lock_class(lock, subclass, 1);
 }
 
 EXPORT_SYMBOL_GPL(lockdep_init_map);
@@ -1995,7 +1996,7 @@
 	 * Not cached yet or subclass?
 	 */
 	if (unlikely(!class)) {
-		class = register_lock_class(lock, subclass);
+		class = register_lock_class(lock, subclass, 0);
 		if (!class)
 			return 0;
 	}
diff --git a/kernel/module.c b/kernel/module.c
index 7f60e78..67009bd 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -87,6 +87,12 @@
 	return try_module_get(mod);
 }
 
+static inline void add_taint_module(struct module *mod, unsigned flag)
+{
+	add_taint(flag);
+	mod->taints |= flag;
+}
+
 /* A thread that wants to hold a reference to a module only while it
  * is running can call ths to safely exit.
  * nfsd and lockd use this.
@@ -847,12 +853,10 @@
 		return 0;
 	}
 	/* Not in module's version table.  OK, but that taints the kernel. */
-	if (!(tainted & TAINT_FORCED_MODULE)) {
+	if (!(tainted & TAINT_FORCED_MODULE))
 		printk("%s: no version for \"%s\" found: kernel tainted.\n",
 		       mod->name, symname);
-		add_taint(TAINT_FORCED_MODULE);
-		mod->taints |= TAINT_FORCED_MODULE;
-	}
+	add_taint_module(mod, TAINT_FORCED_MODULE);
 	return 1;
 }
 
@@ -910,7 +914,8 @@
 	unsigned long ret;
 	const unsigned long *crc;
 
-	ret = __find_symbol(name, &owner, &crc, mod->license_gplok);
+	ret = __find_symbol(name, &owner, &crc,
+			!(mod->taints & TAINT_PROPRIETARY_MODULE));
 	if (ret) {
 		/* use_module can fail due to OOM, or module unloading */
 		if (!check_version(sechdrs, versindex, name, mod, crc) ||
@@ -1335,12 +1340,11 @@
 	if (!license)
 		license = "unspecified";
 
-	mod->license_gplok = license_is_gpl_compatible(license);
-	if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) {
-		printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
-		       mod->name, license);
-		add_taint(TAINT_PROPRIETARY_MODULE);
-		mod->taints |= TAINT_PROPRIETARY_MODULE;
+	if (!license_is_gpl_compatible(license)) {
+		if (!(tainted & TAINT_PROPRIETARY_MODULE))
+			printk(KERN_WARNING "%s: module license '%s' taints"
+				"kernel.\n", mod->name, license);
+		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
 	}
 }
 
@@ -1619,8 +1623,7 @@
 	modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
 	/* This is allowed: modprobe --force will invalidate it. */
 	if (!modmagic) {
-		add_taint(TAINT_FORCED_MODULE);
-		mod->taints |= TAINT_FORCED_MODULE;
+		add_taint_module(mod, TAINT_FORCED_MODULE);
 		printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
 		       mod->name);
 	} else if (!same_magic(modmagic, vermagic)) {
@@ -1714,14 +1717,10 @@
 	/* Set up license info based on the info section */
 	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
-	if (strcmp(mod->name, "ndiswrapper") == 0) {
-		add_taint(TAINT_PROPRIETARY_MODULE);
-		mod->taints |= TAINT_PROPRIETARY_MODULE;
-	}
-	if (strcmp(mod->name, "driverloader") == 0) {
-		add_taint(TAINT_PROPRIETARY_MODULE);
-		mod->taints |= TAINT_PROPRIETARY_MODULE;
-	}
+	if (strcmp(mod->name, "ndiswrapper") == 0)
+		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
+	if (strcmp(mod->name, "driverloader") == 0)
+		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
 
 	/* Set up MODINFO_ATTR fields */
 	setup_modinfo(mod, sechdrs, infoindex);
@@ -1766,8 +1765,7 @@
 	    (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
 		printk(KERN_WARNING "%s: No versions for exported symbols."
 		       " Tainting kernel.\n", mod->name);
-		add_taint(TAINT_FORCED_MODULE);
-		mod->taints |= TAINT_FORCED_MODULE;
+		add_taint_module(mod, TAINT_FORCED_MODULE);
 	}
 #endif
 
@@ -2132,9 +2130,33 @@
 	mutex_unlock(&module_mutex);
 }
 
+static char *taint_flags(unsigned int taints, char *buf)
+{
+	int bx = 0;
+
+	if (taints) {
+		buf[bx++] = '(';
+		if (taints & TAINT_PROPRIETARY_MODULE)
+			buf[bx++] = 'P';
+		if (taints & TAINT_FORCED_MODULE)
+			buf[bx++] = 'F';
+		/*
+		 * TAINT_FORCED_RMMOD: could be added.
+		 * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
+		 * apply to modules.
+		 */
+		buf[bx++] = ')';
+	}
+	buf[bx] = '\0';
+
+	return buf;
+}
+
 static int m_show(struct seq_file *m, void *p)
 {
 	struct module *mod = list_entry(p, struct module, list);
+	char buf[8];
+
 	seq_printf(m, "%s %lu",
 		   mod->name, mod->init_size + mod->core_size);
 	print_unload_info(m, mod);
@@ -2147,6 +2169,10 @@
 	/* Used by oprofile and other similar tools. */
 	seq_printf(m, " 0x%p", mod->module_core);
 
+	/* Taints info */
+	if (mod->taints)
+		seq_printf(m, " %s", taint_flags(mod->taints, buf));
+
 	seq_printf(m, "\n");
 	return 0;
 }
@@ -2235,28 +2261,6 @@
 	return mod;
 }
 
-static char *taint_flags(unsigned int taints, char *buf)
-{
-	*buf = '\0';
-	if (taints) {
-		int bx;
-
-		buf[0] = '(';
-		bx = 1;
-		if (taints & TAINT_PROPRIETARY_MODULE)
-			buf[bx++] = 'P';
-		if (taints & TAINT_FORCED_MODULE)
-			buf[bx++] = 'F';
-		/*
-		 * TAINT_FORCED_RMMOD: could be added.
-		 * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
-		 * apply to modules.
-		 */
-		buf[bx] = ')';
-	}
-	return buf;
-}
-
 /* Don't grab lock, we're oopsing. */
 void print_modules(void)
 {
diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c
index e3203c6..1865164 100644
--- a/kernel/mutex-debug.c
+++ b/kernel/mutex-debug.c
@@ -91,7 +91,7 @@
 	 * Make sure we are not reinitializing a held lock:
 	 */
 	debug_check_no_locks_freed((void *)lock, sizeof(*lock));
-	lockdep_init_map(&lock->dep_map, name, key);
+	lockdep_init_map(&lock->dep_map, name, key, 0);
 #endif
 	lock->owner = NULL;
 	lock->magic = lock;
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 6ebdb82..674aceb 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -44,11 +44,9 @@
 {
 	struct nsproxy *ns;
 
-	ns = kmalloc(sizeof(struct nsproxy), GFP_KERNEL);
-	if (ns) {
-		memcpy(ns, orig, sizeof(struct nsproxy));
+	ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
+	if (ns)
 		atomic_set(&ns->count, 1);
-	}
 	return ns;
 }
 
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 479b16b..7c3e1e6 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -88,6 +88,19 @@
 }
 
 /*
+ * Divide and limit the result to res >= 1
+ *
+ * This is necessary to prevent signal delivery starvation, when the result of
+ * the division would be rounded down to 0.
+ */
+static inline cputime_t cputime_div_non_zero(cputime_t time, unsigned long div)
+{
+	cputime_t res = cputime_div(time, div);
+
+	return max_t(cputime_t, res, 1);
+}
+
+/*
  * Update expiry time from increment, and increase overrun count,
  * given the current clock sample.
  */
@@ -483,8 +496,8 @@
 		BUG();
 		break;
 	case CPUCLOCK_PROF:
-		left = cputime_div(cputime_sub(expires.cpu, val.cpu),
-				   nthreads);
+		left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu),
+				       nthreads);
 		do {
 			if (likely(!(t->flags & PF_EXITING))) {
 				ticks = cputime_add(prof_ticks(t), left);
@@ -498,8 +511,8 @@
 		} while (t != p);
 		break;
 	case CPUCLOCK_VIRT:
-		left = cputime_div(cputime_sub(expires.cpu, val.cpu),
-				   nthreads);
+		left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu),
+				       nthreads);
 		do {
 			if (likely(!(t->flags & PF_EXITING))) {
 				ticks = cputime_add(virt_ticks(t), left);
@@ -515,6 +528,7 @@
 	case CPUCLOCK_SCHED:
 		nsleft = expires.sched - val.sched;
 		do_div(nsleft, nthreads);
+		nsleft = max_t(unsigned long long, nsleft, 1);
 		do {
 			if (likely(!(t->flags & PF_EXITING))) {
 				ns = t->sched_time + nsleft;
@@ -1159,12 +1173,13 @@
 
 		prof_left = cputime_sub(prof_expires, utime);
 		prof_left = cputime_sub(prof_left, stime);
-		prof_left = cputime_div(prof_left, nthreads);
+		prof_left = cputime_div_non_zero(prof_left, nthreads);
 		virt_left = cputime_sub(virt_expires, utime);
-		virt_left = cputime_div(virt_left, nthreads);
+		virt_left = cputime_div_non_zero(virt_left, nthreads);
 		if (sched_expires) {
 			sched_left = sched_expires - sched_time;
 			do_div(sched_left, nthreads);
+			sched_left = max_t(unsigned long long, sched_left, 1);
 		} else {
 			sched_left = 0;
 		}
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index d722349..d3a158a 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -18,6 +18,7 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/pm.h>
+#include <linux/console.h>
 #include <linux/cpu.h>
 
 #include "power.h"
@@ -119,8 +120,10 @@
 	if (error)
 		return error;
 
+	suspend_console();
 	error = device_suspend(PMSG_FREEZE);
 	if (error) {
+		resume_console();
 		printk("Some devices failed to suspend\n");
 		unprepare_processes();
 		return error;
@@ -133,6 +136,7 @@
 
 	if (in_suspend) {
 		device_resume();
+		resume_console();
 		pr_debug("PM: writing image.\n");
 		error = swsusp_write();
 		if (!error)
@@ -148,6 +152,7 @@
 	swsusp_free();
  Done:
 	device_resume();
+	resume_console();
 	unprepare_processes();
 	return error;
 }
@@ -212,7 +217,9 @@
 
 	pr_debug("PM: Preparing devices for restore.\n");
 
+	suspend_console();
 	if ((error = device_suspend(PMSG_PRETHAW))) {
+		resume_console();
 		printk("Some devices failed to suspend\n");
 		swsusp_free();
 		goto Thaw;
@@ -224,6 +231,7 @@
 	swsusp_resume();
 	pr_debug("PM: Restore failed, recovering.n");
 	device_resume();
+	resume_console();
  Thaw:
 	unprepare_processes();
  Done:
diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c
index 7a4144b..f1f900a 100644
--- a/kernel/power/poweroff.c
+++ b/kernel/power/poweroff.c
@@ -23,8 +23,7 @@
 
 static DECLARE_WORK(poweroff_work, do_poweroff, NULL);
 
-static void handle_poweroff(int key, struct pt_regs *pt_regs,
-				struct tty_struct *tty)
+static void handle_poweroff(int key, struct tty_struct *tty)
 {
 	schedule_work(&poweroff_work);
 }
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 9b2ee53..1a3b0dd 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -425,7 +425,8 @@
 			bio_set_pages_dirty(bio);
 		bio_put(bio);
 	} else {
-		get_page(page);
+		if (rw == READ)
+			get_page(page);	/* These pages are freed later */
 		bio->bi_private = *bio_chain;
 		*bio_chain = bio;
 		submit_bio(rw | (1 << BIO_RW_SYNC), bio);
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 72825c8..d991d3b 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -19,6 +19,7 @@
 #include <linux/swapops.h>
 #include <linux/pm.h>
 #include <linux/fs.h>
+#include <linux/console.h>
 #include <linux/cpu.h>
 
 #include <asm/uaccess.h>
@@ -145,10 +146,10 @@
 			error = freeze_processes();
 			if (error) {
 				thaw_processes();
+				enable_nonboot_cpus();
 				error = -EBUSY;
 			}
 		}
-		enable_nonboot_cpus();
 		up(&pm_sem);
 		if (!error)
 			data->frozen = 1;
@@ -173,12 +174,14 @@
 		/* Free memory before shutting down devices. */
 		error = swsusp_shrink_memory();
 		if (!error) {
+			suspend_console();
 			error = device_suspend(PMSG_FREEZE);
 			if (!error) {
 				in_suspend = 1;
 				error = swsusp_suspend();
 				device_resume();
 			}
+			resume_console();
 		}
 		up(&pm_sem);
 		if (!error)
@@ -196,11 +199,13 @@
 		snapshot_free_unused_memory(&data->handle);
 		down(&pm_sem);
 		pm_prepare_console();
+		suspend_console();
 		error = device_suspend(PMSG_PRETHAW);
 		if (!error) {
 			error = swsusp_resume();
 			device_resume();
 		}
+		resume_console();
 		pm_restore_console();
 		up(&pm_sem);
 		break;
@@ -289,6 +294,7 @@
 		}
 
 		/* Put devices to sleep */
+		suspend_console();
 		error = device_suspend(PMSG_SUSPEND);
 		if (error) {
 			printk(KERN_ERR "Failed to suspend some devices.\n");
@@ -299,7 +305,7 @@
 			/* Wake up devices */
 			device_resume();
 		}
-
+		resume_console();
 		if (pm_ops->finish)
 			pm_ops->finish(PM_SUSPEND_MEM);
 
diff --git a/kernel/printk.c b/kernel/printk.c
index 771f5e8..f7d427e 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -820,15 +820,8 @@
 	console_locked = 0;
 	up(&console_sem);
 	spin_unlock_irqrestore(&logbuf_lock, flags);
-	if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) {
-		/*
-		 * If we printk from within the lock dependency code,
-		 * from within the scheduler code, then do not lock
-		 * up due to self-recursion:
-		 */
-		if (!lockdep_internal())
-			wake_up_interruptible(&log_wait);
-	}
+	if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait))
+		wake_up_interruptible(&log_wait);
 }
 EXPORT_SYMBOL(release_console_sem);
 
diff --git a/kernel/profile.c b/kernel/profile.c
index fb660c7..f940b46 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <asm/sections.h>
 #include <asm/semaphore.h>
+#include <asm/irq_regs.h>
 
 struct profile_hit {
 	u32 pc, hits;
@@ -366,8 +367,10 @@
 }
 #endif /* !CONFIG_SMP */
 
-void profile_tick(int type, struct pt_regs *regs)
+void profile_tick(int type)
 {
+	struct pt_regs *regs = get_irq_regs();
+
 	if (type == CPU_PROFILING && timer_hook)
 		timer_hook(regs);
 	if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask))
@@ -396,7 +399,7 @@
 	unsigned long full_count = count, err;
 	cpumask_t new_value;
 
-	err = cpumask_parse(buffer, count, new_value);
+	err = cpumask_parse_user(buffer, count, new_value);
 	if (err)
 		return err;
 
diff --git a/kernel/relay.c b/kernel/relay.c
index 1d63ecd..f04bbdb 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -887,7 +887,7 @@
 
 	from = buf->start + read_start;
 	ret = avail;
-	if (copy_to_user(desc->arg.data, from, avail)) {
+	if (copy_to_user(desc->arg.buf, from, avail)) {
 		desc->error = -EFAULT;
 		ret = 0;
 	}
@@ -946,24 +946,17 @@
  */
 static inline ssize_t relay_file_read_subbufs(struct file *filp,
 					      loff_t *ppos,
-					      size_t count,
 					      subbuf_actor_t subbuf_actor,
 					      read_actor_t actor,
-					      void *target)
+					      read_descriptor_t *desc)
 {
 	struct rchan_buf *buf = filp->private_data;
 	size_t read_start, avail;
-	read_descriptor_t desc;
 	int ret;
 
-	if (!count)
+	if (!desc->count)
 		return 0;
 
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
 	mutex_lock(&filp->f_dentry->d_inode->i_mutex);
 	do {
 		if (!relay_file_read_avail(buf, *ppos))
@@ -974,19 +967,19 @@
 		if (!avail)
 			break;
 
-		avail = min(desc.count, avail);
-		ret = subbuf_actor(read_start, buf, avail, &desc, actor);
-		if (desc.error < 0)
+		avail = min(desc->count, avail);
+		ret = subbuf_actor(read_start, buf, avail, desc, actor);
+		if (desc->error < 0)
 			break;
 
 		if (ret) {
 			relay_file_read_consume(buf, read_start, ret);
 			*ppos = relay_file_read_end_pos(buf, read_start, ret);
 		}
-	} while (desc.count && ret);
+	} while (desc->count && ret);
 	mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
 
-	return desc.written;
+	return desc->written;
 }
 
 static ssize_t relay_file_read(struct file *filp,
@@ -994,8 +987,13 @@
 			       size_t count,
 			       loff_t *ppos)
 {
-	return relay_file_read_subbufs(filp, ppos, count, subbuf_read_actor,
-				       NULL, buffer);
+	read_descriptor_t desc;
+	desc.written = 0;
+	desc.count = count;
+	desc.arg.buf = buffer;
+	desc.error = 0;
+	return relay_file_read_subbufs(filp, ppos, subbuf_read_actor,
+				       NULL, &desc);
 }
 
 static ssize_t relay_file_sendfile(struct file *filp,
@@ -1004,8 +1002,13 @@
 				   read_actor_t actor,
 				   void *target)
 {
-	return relay_file_read_subbufs(filp, ppos, count, subbuf_send_actor,
-				       actor, target);
+	read_descriptor_t desc;
+	desc.written = 0;
+	desc.count = count;
+	desc.arg.data = target;
+	desc.error = 0;
+	return relay_file_read_subbufs(filp, ppos, subbuf_send_actor,
+				       actor, &desc);
 }
 
 struct file_operations relay_file_operations = {
diff --git a/kernel/sched.c b/kernel/sched.c
index 53608a5..3399701 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -160,15 +160,6 @@
 #define TASK_PREEMPTS_CURR(p, rq) \
 	((p)->prio < (rq)->curr->prio)
 
-/*
- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
- * to time slice values: [800ms ... 100ms ... 5ms]
- *
- * The higher a thread's priority, the bigger timeslices
- * it gets during one round of execution. But even the lowest
- * priority thread gets MIN_TIMESLICE worth of execution time.
- */
-
 #define SCALE_PRIO(x, prio) \
 	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
 
@@ -180,6 +171,15 @@
 		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
 }
 
+/*
+ * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * to time slice values: [800ms ... 100ms ... 5ms]
+ *
+ * The higher a thread's priority, the bigger timeslices
+ * it gets during one round of execution. But even the lowest
+ * priority thread gets MIN_TIMESLICE worth of execution time.
+ */
+
 static inline unsigned int task_timeslice(struct task_struct *p)
 {
 	return static_prio_timeslice(p->static_prio);
@@ -1822,14 +1822,14 @@
 	struct mm_struct *mm = next->mm;
 	struct mm_struct *oldmm = prev->active_mm;
 
-	if (unlikely(!mm)) {
+	if (!mm) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
 		enter_lazy_tlb(oldmm, next);
 	} else
 		switch_mm(oldmm, mm, next);
 
-	if (unlikely(!prev->mm)) {
+	if (!prev->mm) {
 		prev->active_mm = NULL;
 		WARN_ON(rq->prev_mm);
 		rq->prev_mm = oldmm;
@@ -3491,7 +3491,7 @@
 	 * If there is a non-zero preempt_count or interrupts are disabled,
 	 * we do not want to preempt the current task.  Just return..
 	 */
-	if (unlikely(ti->preempt_count || irqs_disabled()))
+	if (likely(ti->preempt_count || irqs_disabled()))
 		return;
 
 need_resched:
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 7a3b2e75..0e53314 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -49,6 +49,7 @@
 cond_syscall(sys_epoll_create);
 cond_syscall(sys_epoll_ctl);
 cond_syscall(sys_epoll_wait);
+cond_syscall(sys_epoll_pwait);
 cond_syscall(sys_semget);
 cond_syscall(sys_semop);
 cond_syscall(sys_semtimedop);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8020fb2..8bff2c1 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -136,8 +136,10 @@
 static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
 
+#ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
 
 static ctl_table root_table[];
 static struct ctl_table_header root_table_header =
@@ -542,6 +544,7 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+#ifdef CONFIG_PROC_SYSCTL
 	{
 		.ctl_name	= KERN_CADPID,
 		.procname	= "cad_pid",
@@ -550,6 +553,7 @@
 		.mode		= 0600,
 		.proc_handler	= &proc_do_cad_pid,
 	},
+#endif
 	{
 		.ctl_name	= KERN_MAX_THREADS,
 		.procname	= "threads-max",
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index 126bb30..a99b2a6 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -57,7 +57,7 @@
 
 struct clocksource clocksource_jiffies = {
 	.name		= "jiffies",
-	.rating		= 0, /* lowest rating*/
+	.rating		= 1, /* lowest valid rating*/
 	.read		= jiffies_read,
 	.mask		= 0xffffffff, /*32bits*/
 	.mult		= NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
diff --git a/kernel/unwind.c b/kernel/unwind.c
index 2e23686..f7e50d1 100644
--- a/kernel/unwind.c
+++ b/kernel/unwind.c
@@ -11,13 +11,15 @@
 
 #include <linux/unwind.h>
 #include <linux/module.h>
-#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/sort.h>
 #include <linux/stop_machine.h>
 #include <asm/sections.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 extern char __start_unwind[], __end_unwind[];
+extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
 
 #define MAX_STACK_DEPTH 8
 
@@ -100,6 +102,8 @@
 	} core, init;
 	const void *address;
 	unsigned long size;
+	const unsigned char *header;
+	unsigned long hdrsz;
 	struct unwind_table *link;
 	const char *name;
 } root_table;
@@ -145,6 +149,10 @@
 	return table;
 }
 
+static unsigned long read_pointer(const u8 **pLoc,
+                                  const void *end,
+                                  signed ptrType);
+
 static void init_unwind_table(struct unwind_table *table,
                               const char *name,
                               const void *core_start,
@@ -152,14 +160,30 @@
                               const void *init_start,
                               unsigned long init_size,
                               const void *table_start,
-                              unsigned long table_size)
+                              unsigned long table_size,
+                              const u8 *header_start,
+                              unsigned long header_size)
 {
+	const u8 *ptr = header_start + 4;
+	const u8 *end = header_start + header_size;
+
 	table->core.pc = (unsigned long)core_start;
 	table->core.range = core_size;
 	table->init.pc = (unsigned long)init_start;
 	table->init.range = init_size;
 	table->address = table_start;
 	table->size = table_size;
+	/* See if the linker provided table looks valid. */
+	if (header_size <= 4
+	    || header_start[0] != 1
+	    || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
+	    || header_start[2] == DW_EH_PE_omit
+	    || read_pointer(&ptr, end, header_start[2]) <= 0
+	    || header_start[3] == DW_EH_PE_omit)
+		header_start = NULL;
+	table->hdrsz = header_size;
+	smp_wmb();
+	table->header = header_start;
 	table->link = NULL;
 	table->name = name;
 }
@@ -169,7 +193,143 @@
 	init_unwind_table(&root_table, "kernel",
 	                  _text, _end - _text,
 	                  NULL, 0,
-	                  __start_unwind, __end_unwind - __start_unwind);
+	                  __start_unwind, __end_unwind - __start_unwind,
+	                  __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
+}
+
+static const u32 bad_cie, not_fde;
+static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
+static signed fde_pointer_type(const u32 *cie);
+
+struct eh_frame_hdr_table_entry {
+	unsigned long start, fde;
+};
+
+static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
+{
+	const struct eh_frame_hdr_table_entry *e1 = p1;
+	const struct eh_frame_hdr_table_entry *e2 = p2;
+
+	return (e1->start > e2->start) - (e1->start < e2->start);
+}
+
+static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
+{
+	struct eh_frame_hdr_table_entry *e1 = p1;
+	struct eh_frame_hdr_table_entry *e2 = p2;
+	unsigned long v;
+
+	v = e1->start;
+	e1->start = e2->start;
+	e2->start = v;
+	v = e1->fde;
+	e1->fde = e2->fde;
+	e2->fde = v;
+}
+
+static void __init setup_unwind_table(struct unwind_table *table,
+					void *(*alloc)(unsigned long))
+{
+	const u8 *ptr;
+	unsigned long tableSize = table->size, hdrSize;
+	unsigned n;
+	const u32 *fde;
+	struct {
+		u8 version;
+		u8 eh_frame_ptr_enc;
+		u8 fde_count_enc;
+		u8 table_enc;
+		unsigned long eh_frame_ptr;
+		unsigned int fde_count;
+		struct eh_frame_hdr_table_entry table[];
+	} __attribute__((__packed__)) *header;
+
+	if (table->header)
+		return;
+
+	if (table->hdrsz)
+		printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
+		       table->name);
+
+	if (tableSize & (sizeof(*fde) - 1))
+		return;
+
+	for (fde = table->address, n = 0;
+	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
+	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+		const u32 *cie = cie_for_fde(fde, table);
+		signed ptrType;
+
+		if (cie == &not_fde)
+			continue;
+		if (cie == NULL
+		    || cie == &bad_cie
+		    || (ptrType = fde_pointer_type(cie)) < 0)
+			return;
+		ptr = (const u8 *)(fde + 2);
+		if (!read_pointer(&ptr,
+		                  (const u8 *)(fde + 1) + *fde,
+		                  ptrType))
+			return;
+		++n;
+	}
+
+	if (tableSize || !n)
+		return;
+
+	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
+	        + 2 * n * sizeof(unsigned long);
+	header = alloc(hdrSize);
+	if (!header)
+		return;
+	header->version          = 1;
+	header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
+	header->fde_count_enc    = DW_EH_PE_abs|DW_EH_PE_data4;
+	header->table_enc        = DW_EH_PE_abs|DW_EH_PE_native;
+	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
+	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
+	             % __alignof(typeof(header->fde_count)));
+	header->fde_count        = n;
+
+	BUILD_BUG_ON(offsetof(typeof(*header), table)
+	             % __alignof(typeof(*header->table)));
+	for (fde = table->address, tableSize = table->size, n = 0;
+	     tableSize;
+	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+		const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
+
+		if (!fde[1])
+			continue; /* this is a CIE */
+		ptr = (const u8 *)(fde + 2);
+		header->table[n].start = read_pointer(&ptr,
+		                                      (const u8 *)(fde + 1) + *fde,
+		                                      fde_pointer_type(cie));
+		header->table[n].fde = (unsigned long)fde;
+		++n;
+	}
+	WARN_ON(n != header->fde_count);
+
+	sort(header->table,
+	     n,
+	     sizeof(*header->table),
+	     cmp_eh_frame_hdr_table_entries,
+	     swap_eh_frame_hdr_table_entries);
+
+	table->hdrsz = hdrSize;
+	smp_wmb();
+	table->header = (const void *)header;
+}
+
+static void *__init balloc(unsigned long sz)
+{
+	return __alloc_bootmem_nopanic(sz,
+	                               sizeof(unsigned int),
+	                               __pa(MAX_DMA_ADDRESS));
+}
+
+void __init unwind_setup(void)
+{
+	setup_unwind_table(&root_table, balloc);
 }
 
 #ifdef CONFIG_MODULES
@@ -193,7 +353,8 @@
 	init_unwind_table(table, module->name,
 	                  module->module_core, module->core_size,
 	                  module->module_init, module->init_size,
-	                  table_start, table_size);
+	                  table_start, table_size,
+	                  NULL, 0);
 
 	if (last_table)
 		last_table->link = table;
@@ -303,6 +464,26 @@
 	return value;
 }
 
+static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
+{
+	const u32 *cie;
+
+	if (!*fde || (*fde & (sizeof(*fde) - 1)))
+		return &bad_cie;
+	if (!fde[1])
+		return &not_fde; /* this is a CIE */
+	if ((fde[1] & (sizeof(*fde) - 1))
+	    || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
+		return NULL; /* this is not a valid FDE */
+	cie = fde + 1 - fde[1] / sizeof(*fde);
+	if (*cie <= sizeof(*cie) + 4
+	    || *cie >= fde[1] - sizeof(*fde)
+	    || (*cie & (sizeof(*cie) - 1))
+	    || cie[1])
+		return NULL; /* this is not a (valid) CIE */
+	return cie;
+}
+
 static unsigned long read_pointer(const u8 **pLoc,
                                   const void *end,
                                   signed ptrType)
@@ -610,49 +791,108 @@
 	unsigned i;
 	signed ptrType = -1;
 	uleb128_t retAddrReg = 0;
-	struct unwind_table *table;
+	const struct unwind_table *table;
 	struct unwind_state state;
 
 	if (UNW_PC(frame) == 0)
 		return -EINVAL;
 	if ((table = find_table(pc)) != NULL
 	    && !(table->size & (sizeof(*fde) - 1))) {
-		unsigned long tableSize = table->size;
+		const u8 *hdr = table->header;
+		unsigned long tableSize;
 
-		for (fde = table->address;
-		     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
-		     tableSize -= sizeof(*fde) + *fde,
-		     fde += 1 + *fde / sizeof(*fde)) {
-			if (!*fde || (*fde & (sizeof(*fde) - 1)))
-				break;
-			if (!fde[1])
-				continue; /* this is a CIE */
-			if ((fde[1] & (sizeof(*fde) - 1))
-			    || fde[1] > (unsigned long)(fde + 1)
-			                - (unsigned long)table->address)
-				continue; /* this is not a valid FDE */
-			cie = fde + 1 - fde[1] / sizeof(*fde);
-			if (*cie <= sizeof(*cie) + 4
-			    || *cie >= fde[1] - sizeof(*fde)
-			    || (*cie & (sizeof(*cie) - 1))
-			    || cie[1]
-			    || (ptrType = fde_pointer_type(cie)) < 0) {
-				cie = NULL; /* this is not a (valid) CIE */
-				continue;
+		smp_rmb();
+		if (hdr && hdr[0] == 1) {
+			switch(hdr[3] & DW_EH_PE_FORM) {
+			case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
+			case DW_EH_PE_data2: tableSize = 2; break;
+			case DW_EH_PE_data4: tableSize = 4; break;
+			case DW_EH_PE_data8: tableSize = 8; break;
+			default: tableSize = 0; break;
 			}
+			ptr = hdr + 4;
+			end = hdr + table->hdrsz;
+			if (tableSize
+			    && read_pointer(&ptr, end, hdr[1])
+			       == (unsigned long)table->address
+			    && (i = read_pointer(&ptr, end, hdr[2])) > 0
+			    && i == (end - ptr) / (2 * tableSize)
+			    && !((end - ptr) % (2 * tableSize))) {
+				do {
+					const u8 *cur = ptr + (i / 2) * (2 * tableSize);
+
+					startLoc = read_pointer(&cur,
+					                        cur + tableSize,
+					                        hdr[3]);
+					if (pc < startLoc)
+						i /= 2;
+					else {
+						ptr = cur - tableSize;
+						i = (i + 1) / 2;
+					}
+				} while (startLoc && i > 1);
+				if (i == 1
+				    && (startLoc = read_pointer(&ptr,
+				                                ptr + tableSize,
+				                                hdr[3])) != 0
+				    && pc >= startLoc)
+					fde = (void *)read_pointer(&ptr,
+					                           ptr + tableSize,
+					                           hdr[3]);
+			}
+		}
+
+		if (fde != NULL) {
+			cie = cie_for_fde(fde, table);
 			ptr = (const u8 *)(fde + 2);
-			startLoc = read_pointer(&ptr,
-			                        (const u8 *)(fde + 1) + *fde,
-			                        ptrType);
-			endLoc = startLoc
-			         + read_pointer(&ptr,
-			                        (const u8 *)(fde + 1) + *fde,
-			                        ptrType & DW_EH_PE_indirect
-			                        ? ptrType
-			                        : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
-			if (pc >= startLoc && pc < endLoc)
-				break;
-			cie = NULL;
+			if(cie != NULL
+			   && cie != &bad_cie
+			   && cie != &not_fde
+			   && (ptrType = fde_pointer_type(cie)) >= 0
+			   && read_pointer(&ptr,
+			                   (const u8 *)(fde + 1) + *fde,
+			                   ptrType) == startLoc) {
+				if (!(ptrType & DW_EH_PE_indirect))
+					ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
+				endLoc = startLoc
+				         + read_pointer(&ptr,
+				                        (const u8 *)(fde + 1) + *fde,
+				                        ptrType);
+				if(pc >= endLoc)
+					fde = NULL;
+			} else
+				fde = NULL;
+		}
+		if (fde == NULL) {
+			for (fde = table->address, tableSize = table->size;
+			     cie = NULL, tableSize > sizeof(*fde)
+			     && tableSize - sizeof(*fde) >= *fde;
+			     tableSize -= sizeof(*fde) + *fde,
+			     fde += 1 + *fde / sizeof(*fde)) {
+				cie = cie_for_fde(fde, table);
+				if (cie == &bad_cie) {
+					cie = NULL;
+					break;
+				}
+				if (cie == NULL
+				    || cie == &not_fde
+				    || (ptrType = fde_pointer_type(cie)) < 0)
+					continue;
+				ptr = (const u8 *)(fde + 2);
+				startLoc = read_pointer(&ptr,
+				                        (const u8 *)(fde + 1) + *fde,
+				                        ptrType);
+				if (!startLoc)
+					continue;
+				if (!(ptrType & DW_EH_PE_indirect))
+					ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
+				endLoc = startLoc
+				         + read_pointer(&ptr,
+				                        (const u8 *)(fde + 1) + *fde,
+				                        ptrType);
+				if (pc >= startLoc && pc < endLoc)
+					break;
+			}
 		}
 	}
 	if (cie != NULL) {
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index cfc737b..3df9bfc 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -28,6 +28,7 @@
 #include <linux/notifier.h>
 #include <linux/kthread.h>
 #include <linux/hardirq.h>
+#include <linux/mempolicy.h>
 
 /*
  * The per-CPU workqueue (if single thread, we always use the first
@@ -245,6 +246,12 @@
 	sigprocmask(SIG_BLOCK, &blocked, NULL);
 	flush_signals(current);
 
+	/*
+	 * We inherited MPOL_INTERLEAVE from the booting kernel.
+	 * Set MPOL_DEFAULT to insure node local allocations.
+	 */
+	numa_default_policy();
+
 	/* SIG_IGN makes children autoreap: see do_notify_parent(). */
 	sa.sa.sa_handler = SIG_IGN;
 	sa.sa.sa_flags = 0;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 756a908..77491e3 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -71,7 +71,7 @@
 
 config DETECT_SOFTLOCKUP
 	bool "Detect Soft Lockups"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL && !S390
 	default y
 	help
 	  Say Y here to enable the kernel to detect "soft lockups",
@@ -371,6 +371,20 @@
 	  become the default in the future, until then this option is there to
 	  test gcc for this.
 
+config HEADERS_CHECK
+	bool "Run 'make headers_check' when building vmlinux"
+	depends on !UML
+	help
+	  This option will extract the user-visible kernel headers whenever
+	  building the kernel, and will run basic sanity checks on them to
+	  ensure that exported files do not attempt to include files which
+	  were not exported, etc.
+
+	  If you're making modifications to header files which are
+	  relevant for userspace, say 'Y', and check the headers
+	  exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
+	  your build tree), to make sure they're suitable.
+
 config RCU_TORTURE_TEST
 	tristate "torture tests for RCU"
 	depends on DEBUG_KERNEL
diff --git a/lib/Makefile b/lib/Makefile
index b036175..cf98fab 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,14 +5,14 @@
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
-	 sha1.o
+	 sha1.o irq_regs.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
 
 lib-y	+= kobject.o kref.o kobject_uevent.o klist.o
 
-obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o
+obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o random32.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/bitmap.c b/lib/bitmap.c
index d71e38c..037fa9a 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -316,10 +316,11 @@
 EXPORT_SYMBOL(bitmap_scnprintf);
 
 /**
- * bitmap_parse - convert an ASCII hex string into a bitmap.
- * @ubuf: pointer to buffer in user space containing string.
- * @ubuflen: buffer size in bytes.  If string is smaller than this
+ * __bitmap_parse - convert an ASCII hex string into a bitmap.
+ * @buf: pointer to buffer containing string.
+ * @buflen: buffer size in bytes.  If string is smaller than this
  *    then it must be terminated with a \0.
+ * @is_user: location of buffer, 0 indicates kernel space
  * @maskp: pointer to bitmap array that will contain result.
  * @nmaskbits: size of bitmap, in bits.
  *
@@ -330,11 +331,13 @@
  * characters and for grouping errors such as "1,,5", ",44", "," and "".
  * Leading and trailing whitespace accepted, but not embedded whitespace.
  */
-int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
-        unsigned long *maskp, int nmaskbits)
+int __bitmap_parse(const char *buf, unsigned int buflen,
+		int is_user, unsigned long *maskp,
+		int nmaskbits)
 {
 	int c, old_c, totaldigits, ndigits, nchunks, nbits;
 	u32 chunk;
+	const char __user *ubuf = buf;
 
 	bitmap_zero(maskp, nmaskbits);
 
@@ -343,11 +346,15 @@
 		chunk = ndigits = 0;
 
 		/* Get the next chunk of the bitmap */
-		while (ubuflen) {
+		while (buflen) {
 			old_c = c;
-			if (get_user(c, ubuf++))
-				return -EFAULT;
-			ubuflen--;
+			if (is_user) {
+				if (__get_user(c, ubuf++))
+					return -EFAULT;
+			}
+			else
+				c = *buf++;
+			buflen--;
 			if (isspace(c))
 				continue;
 
@@ -388,11 +395,36 @@
 		nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
 		if (nbits > nmaskbits)
 			return -EOVERFLOW;
-	} while (ubuflen && c == ',');
+	} while (buflen && c == ',');
 
 	return 0;
 }
-EXPORT_SYMBOL(bitmap_parse);
+EXPORT_SYMBOL(__bitmap_parse);
+
+/**
+ * bitmap_parse_user()
+ *
+ * @ubuf: pointer to user buffer containing string.
+ * @ulen: buffer size in bytes.  If string is smaller than this
+ *    then it must be terminated with a \0.
+ * @maskp: pointer to bitmap array that will contain result.
+ * @nmaskbits: size of bitmap, in bits.
+ *
+ * Wrapper for __bitmap_parse(), providing it with user buffer.
+ *
+ * We cannot have this as an inline function in bitmap.h because it needs
+ * linux/uaccess.h to get the access_ok() declaration and this causes
+ * cyclic dependencies.
+ */
+int bitmap_parse_user(const char __user *ubuf,
+			unsigned int ulen, unsigned long *maskp,
+			int nmaskbits)
+{
+	if (!access_ok(VERIFY_READ, ubuf, ulen))
+		return -EFAULT;
+	return __bitmap_parse((const char *)ubuf, ulen, 1, maskp, nmaskbits);
+}
+EXPORT_SYMBOL(bitmap_parse_user);
 
 /*
  * bscnl_emit(buf, buflen, rbot, rtop, bp)
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 7a2a73f..3a67dc5 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -43,19 +43,3 @@
 	return cpu;
 }
 EXPORT_SYMBOL(__any_online_cpu);
-
-#if MAX_NUMNODES > 1
-/*
- * Find the highest possible node id.
- */
-int highest_possible_node_id(void)
-{
-	unsigned int node;
-	unsigned int highest = 0;
-
-	for_each_node_mask(node, node_possible_map)
-		highest = node;
-	return highest;
-}
-EXPORT_SYMBOL(highest_possible_node_id);
-#endif
diff --git a/lib/irq_regs.c b/lib/irq_regs.c
new file mode 100644
index 0000000..753880a
--- /dev/null
+++ b/lib/irq_regs.c
@@ -0,0 +1,17 @@
+/* saved per-CPU IRQ register pointer
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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 <asm/irq_regs.h>
+
+#ifndef ARCH_HAS_OWN_IRQ_REGS
+DEFINE_PER_CPU(struct pt_regs *, __irq_regs);
+EXPORT_PER_CPU_SYMBOL(__irq_regs);
+#endif
diff --git a/lib/kobject.c b/lib/kobject.c
index 1699eb9..7dd5c0e 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -119,6 +119,7 @@
 
 	return path;
 }
+EXPORT_SYMBOL_GPL(kobject_get_path);
 
 /**
  *	kobject_init - initialize object.
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 637d556..aa9bfd0 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -160,13 +160,13 @@
 
 static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag)
 {
-	root->gfp_mask |= (1 << (tag + __GFP_BITS_SHIFT));
+	root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT));
 }
 
 
 static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag)
 {
-	root->gfp_mask &= ~(1 << (tag + __GFP_BITS_SHIFT));
+	root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT));
 }
 
 static inline void root_tag_clear_all(struct radix_tree_root *root)
@@ -176,7 +176,7 @@
 
 static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag)
 {
-	return root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT));
+	return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT));
 }
 
 /*
diff --git a/lib/random32.c b/lib/random32.c
new file mode 100644
index 0000000..4a15ce5
--- /dev/null
+++ b/lib/random32.c
@@ -0,0 +1,142 @@
+/*
+  This is a maximally equidistributed combined Tausworthe generator
+  based on code from GNU Scientific Library 1.5 (30 Jun 2004)
+
+   x_n = (s1_n ^ s2_n ^ s3_n)
+
+   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
+   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
+   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
+
+   The period of this generator is about 2^88.
+
+   From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
+   Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
+
+   This is available on the net from L'Ecuyer's home page,
+
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
+   ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
+
+   There is an erratum in the paper "Tables of Maximally
+   Equidistributed Combined LFSR Generators", Mathematics of
+   Computation, 68, 225 (1999), 261--269:
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
+
+        ... the k_j most significant bits of z_j must be non-
+        zero, for each j. (Note: this restriction also applies to the
+        computer code given in [4], but was mistakenly not mentioned in
+        that paper.)
+
+   This affects the seeding procedure by imposing the requirement
+   s1 > 1, s2 > 7, s3 > 15.
+
+*/
+
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/module.h>
+#include <linux/random.h>
+
+struct rnd_state {
+	u32 s1, s2, s3;
+};
+
+static DEFINE_PER_CPU(struct rnd_state, net_rand_state);
+
+static u32 __random32(struct rnd_state *state)
+{
+#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
+
+	state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
+	state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
+	state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
+
+	return (state->s1 ^ state->s2 ^ state->s3);
+}
+
+static void __set_random32(struct rnd_state *state, unsigned long s)
+{
+	if (s == 0)
+		s = 1;      /* default seed is 1 */
+
+#define LCG(n) (69069 * n)
+	state->s1 = LCG(s);
+	state->s2 = LCG(state->s1);
+	state->s3 = LCG(state->s2);
+
+	/* "warm it up" */
+	__random32(state);
+	__random32(state);
+	__random32(state);
+	__random32(state);
+	__random32(state);
+	__random32(state);
+}
+
+/**
+ *	random32 - pseudo random number generator
+ *
+ *	A 32 bit pseudo-random number is generated using a fast
+ *	algorithm suitable for simulation. This algorithm is NOT
+ *	considered safe for cryptographic use.
+ */
+u32 random32(void)
+{
+	unsigned long r;
+	struct rnd_state *state = &get_cpu_var(net_rand_state);
+	r = __random32(state);
+	put_cpu_var(state);
+	return r;
+}
+EXPORT_SYMBOL(random32);
+
+/**
+ *	srandom32 - add entropy to pseudo random number generator
+ *	@seed: seed value
+ *
+ *	Add some additional seeding to the random32() pool.
+ *	Note: this pool is per cpu so it only affects current CPU.
+ */
+void srandom32(u32 entropy)
+{
+	struct rnd_state *state = &get_cpu_var(net_rand_state);
+	__set_random32(state, state->s1 ^ entropy);
+	put_cpu_var(state);
+}
+EXPORT_SYMBOL(srandom32);
+
+/*
+ *	Generate some initially weak seeding values to allow
+ *	to start the random32() engine.
+ */
+static int __init random32_init(void)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		struct rnd_state *state = &per_cpu(net_rand_state,i);
+		__set_random32(state, i + jiffies);
+	}
+	return 0;
+}
+core_initcall(random32_init);
+
+/*
+ *	Generate better values after random number generator
+ *	is fully initalized.
+ */
+static int __init random32_reseed(void)
+{
+	int i;
+	unsigned long seed;
+
+	for_each_possible_cpu(i) {
+		struct rnd_state *state = &per_cpu(net_rand_state,i);
+
+		get_random_bytes(&seed, sizeof(seed));
+		__set_random32(state, seed);
+	}
+	return 0;
+}
+late_initcall(random32_reseed);
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
index db4fed7..c4cfd6c 100644
--- a/lib/rwsem-spinlock.c
+++ b/lib/rwsem-spinlock.c
@@ -28,7 +28,7 @@
 	 * Make sure we are not reinitializing a held semaphore:
 	 */
 	debug_check_no_locks_freed((void *)sem, sizeof(*sem));
-	lockdep_init_map(&sem->dep_map, name, key);
+	lockdep_init_map(&sem->dep_map, name, key, 0);
 #endif
 	sem->activity = 0;
 	spin_lock_init(&sem->wait_lock);
diff --git a/lib/rwsem.c b/lib/rwsem.c
index 901d0e7..cdb4e3d 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -19,7 +19,7 @@
 	 * Make sure we are not reinitializing a held semaphore:
 	 */
 	debug_check_no_locks_freed((void *)sem, sizeof(*sem));
-	lockdep_init_map(&sem->dep_map, name, key);
+	lockdep_init_map(&sem->dep_map, name, key, 0);
 #endif
 	sem->count = RWSEM_UNLOCKED_VALUE;
 	spin_lock_init(&sem->wait_lock);
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index dafaf1d..b6c4f89 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -20,7 +20,7 @@
 	 * Make sure we are not reinitializing a held lock:
 	 */
 	debug_check_no_locks_freed((void *)lock, sizeof(*lock));
-	lockdep_init_map(&lock->dep_map, name, key);
+	lockdep_init_map(&lock->dep_map, name, key, 0);
 #endif
 	lock->raw_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
 	lock->magic = SPINLOCK_MAGIC;
@@ -38,7 +38,7 @@
 	 * Make sure we are not reinitializing a held lock:
 	 */
 	debug_check_no_locks_freed((void *)lock, sizeof(*lock));
-	lockdep_init_map(&lock->dep_map, name, key);
+	lockdep_init_map(&lock->dep_map, name, key, 0);
 #endif
 	lock->raw_lock = (raw_rwlock_t) __RAW_RW_LOCK_UNLOCKED;
 	lock->magic = RWLOCK_MAGIC;
diff --git a/mm/Makefile b/mm/Makefile
index 12b3a4e..f3c077e 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -10,7 +10,8 @@
 obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
 			   page_alloc.o page-writeback.o pdflush.o \
 			   readahead.o swap.o truncate.o vmscan.o \
-			   prio_tree.o util.o mmzone.o vmstat.o $(mmu-y)
+			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
+			   $(mmu-y)
 
 ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy)
 obj-y			+= bounce.o
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
new file mode 100644
index 0000000..f50a281
--- /dev/null
+++ b/mm/backing-dev.c
@@ -0,0 +1,69 @@
+
+#include <linux/wait.h>
+#include <linux/backing-dev.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+
+static wait_queue_head_t congestion_wqh[2] = {
+		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
+		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
+	};
+
+
+void clear_bdi_congested(struct backing_dev_info *bdi, int rw)
+{
+	enum bdi_state bit;
+	wait_queue_head_t *wqh = &congestion_wqh[rw];
+
+	bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
+	clear_bit(bit, &bdi->state);
+	smp_mb__after_clear_bit();
+	if (waitqueue_active(wqh))
+		wake_up(wqh);
+}
+EXPORT_SYMBOL(clear_bdi_congested);
+
+void set_bdi_congested(struct backing_dev_info *bdi, int rw)
+{
+	enum bdi_state bit;
+
+	bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
+	set_bit(bit, &bdi->state);
+}
+EXPORT_SYMBOL(set_bdi_congested);
+
+/**
+ * congestion_wait - wait for a backing_dev to become uncongested
+ * @rw: READ or WRITE
+ * @timeout: timeout in jiffies
+ *
+ * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit
+ * write congestion.  If no backing_devs are congested then just wait for the
+ * next write to be completed.
+ */
+long congestion_wait(int rw, long timeout)
+{
+	long ret;
+	DEFINE_WAIT(wait);
+	wait_queue_head_t *wqh = &congestion_wqh[rw];
+
+	prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
+	ret = io_schedule_timeout(timeout);
+	finish_wait(wqh, &wait);
+	return ret;
+}
+EXPORT_SYMBOL(congestion_wait);
+
+/**
+ * congestion_end - wake up sleepers on a congested backing_dev_info
+ * @rw: READ or WRITE
+ */
+void congestion_end(int rw)
+{
+	wait_queue_head_t *wqh = &congestion_wqh[rw];
+
+	if (waitqueue_active(wqh))
+		wake_up(wqh);
+}
+EXPORT_SYMBOL(congestion_end);
diff --git a/mm/filemap.c b/mm/filemap.c
index 3464b68..cb26e33 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -75,8 +75,8 @@
  *  ->mmap_sem
  *    ->lock_page		(access_process_vm)
  *
- *  ->mmap_sem
- *    ->i_mutex			(msync)
+ *  ->i_mutex			(generic_file_buffered_write)
+ *    ->mmap_sem		(fault_in_pages_readable->do_page_fault)
  *
  *  ->i_mutex
  *    ->i_alloc_sem             (various)
@@ -1884,11 +1884,10 @@
  *	if suid or (sgid and xgrp)
  *		remove privs
  */
-int remove_suid(struct dentry *dentry)
+int should_remove_suid(struct dentry *dentry)
 {
 	mode_t mode = dentry->d_inode->i_mode;
 	int kill = 0;
-	int result = 0;
 
 	/* suid always must be killed */
 	if (unlikely(mode & S_ISUID))
@@ -1901,13 +1900,28 @@
 	if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
 		kill |= ATTR_KILL_SGID;
 
-	if (unlikely(kill && !capable(CAP_FSETID))) {
-		struct iattr newattrs;
+	if (unlikely(kill && !capable(CAP_FSETID)))
+		return kill;
 
-		newattrs.ia_valid = ATTR_FORCE | kill;
-		result = notify_change(dentry, &newattrs);
-	}
-	return result;
+	return 0;
+}
+
+int __remove_suid(struct dentry *dentry, int kill)
+{
+	struct iattr newattrs;
+
+	newattrs.ia_valid = ATTR_FORCE | kill;
+	return notify_change(dentry, &newattrs);
+}
+
+int remove_suid(struct dentry *dentry)
+{
+	int kill = should_remove_suid(dentry);
+
+	if (unlikely(kill))
+		return __remove_suid(dentry, kill);
+
+	return 0;
 }
 EXPORT_SYMBOL(remove_suid);
 
@@ -2222,7 +2236,7 @@
 				unsigned long nr_segs, loff_t *ppos)
 {
 	struct file *file = iocb->ki_filp;
-	const struct address_space * mapping = file->f_mapping;
+	struct address_space * mapping = file->f_mapping;
 	size_t ocount;		/* original count */
 	size_t count;		/* after file limit checks */
 	struct inode 	*inode = mapping->host;
@@ -2275,8 +2289,11 @@
 
 	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
 	if (unlikely(file->f_flags & O_DIRECT)) {
-		written = generic_file_direct_write(iocb, iov,
-				&nr_segs, pos, ppos, count, ocount);
+		loff_t endbyte;
+		ssize_t written_buffered;
+
+		written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
+							ppos, count, ocount);
 		if (written < 0 || written == count)
 			goto out;
 		/*
@@ -2285,10 +2302,46 @@
 		 */
 		pos += written;
 		count -= written;
-	}
+		written_buffered = generic_file_buffered_write(iocb, iov,
+						nr_segs, pos, ppos, count,
+						written);
+		/*
+		 * If generic_file_buffered_write() retuned a synchronous error
+		 * then we want to return the number of bytes which were
+		 * direct-written, or the error code if that was zero.  Note
+		 * that this differs from normal direct-io semantics, which
+		 * will return -EFOO even if some bytes were written.
+		 */
+		if (written_buffered < 0) {
+			err = written_buffered;
+			goto out;
+		}
 
-	written = generic_file_buffered_write(iocb, iov, nr_segs,
-			pos, ppos, count, written);
+		/*
+		 * We need to ensure that the page cache pages are written to
+		 * disk and invalidated to preserve the expected O_DIRECT
+		 * semantics.
+		 */
+		endbyte = pos + written_buffered - written - 1;
+		err = do_sync_file_range(file, pos, endbyte,
+					 SYNC_FILE_RANGE_WAIT_BEFORE|
+					 SYNC_FILE_RANGE_WRITE|
+					 SYNC_FILE_RANGE_WAIT_AFTER);
+		if (err == 0) {
+			written = written_buffered;
+			invalidate_mapping_pages(mapping,
+						 pos >> PAGE_CACHE_SHIFT,
+						 endbyte >> PAGE_CACHE_SHIFT);
+		} else {
+			/*
+			 * We don't know how much we wrote, so just return
+			 * the number of bytes which were direct-written
+			 */
+		}
+	} else {
+		written = generic_file_buffered_write(iocb, iov, nr_segs,
+				pos, ppos, count, written);
+	}
 out:
 	current->backing_dev_info = NULL;
 	return written ? written : err;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 1d709ff..2dbec90 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -356,8 +356,8 @@
 	return -ENOMEM;
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
-			  unsigned long end)
+void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
+			    unsigned long end)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
@@ -398,6 +398,24 @@
 	}
 }
 
+void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
+			  unsigned long end)
+{
+	/*
+	 * It is undesirable to test vma->vm_file as it should be non-null
+	 * for valid hugetlb area. However, vm_file will be NULL in the error
+	 * cleanup path of do_mmap_pgoff. When hugetlbfs ->mmap method fails,
+	 * do_mmap_pgoff() nullifies vma->vm_file before calling this function
+	 * to clean up. Since no pte has actually been setup, it is safe to
+	 * do nothing in this case.
+	 */
+	if (vma->vm_file) {
+		spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
+		__unmap_hugepage_range(vma, start, end);
+		spin_unlock(&vma->vm_file->f_mapping->i_mmap_lock);
+	}
+}
+
 static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, pte_t *ptep, pte_t pte)
 {
diff --git a/mm/memory.c b/mm/memory.c
index 9cf3f34..156861f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1086,6 +1086,7 @@
 				default:
 					BUG();
 				}
+				cond_resched();
 			}
 			if (pages) {
 				pages[i] = page;
@@ -1451,6 +1452,7 @@
 		if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
 			memset(kaddr, 0, PAGE_SIZE);
 		kunmap_atomic(kaddr, KM_USER0);
+		flush_dcache_page(dst);
 		return;
 		
 	}
@@ -2169,11 +2171,13 @@
 	 * after the next truncate_count read.
 	 */
 
-	/* no page was available -- either SIGBUS or OOM */
-	if (new_page == NOPAGE_SIGBUS)
+	/* no page was available -- either SIGBUS, OOM or REFAULT */
+	if (unlikely(new_page == NOPAGE_SIGBUS))
 		return VM_FAULT_SIGBUS;
-	if (new_page == NOPAGE_OOM)
+	else if (unlikely(new_page == NOPAGE_OOM))
 		return VM_FAULT_OOM;
+	else if (unlikely(new_page == NOPAGE_REFAULT))
+		return VM_FAULT_MINOR;
 
 	/*
 	 * Should we do an early C-O-W break?
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 25788b1..617fb31 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -727,7 +727,7 @@
 	return -ENOSYS;
 }
 
-static struct page *new_vma_page(struct page *page, unsigned long private)
+static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
 {
 	return NULL;
 }
diff --git a/mm/mmap.c b/mm/mmap.c
index eea8eef..497e502 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -900,17 +900,6 @@
 	int accountable = 1;
 	unsigned long charged = 0, reqprot = prot;
 
-	if (file) {
-		if (is_file_hugepages(file))
-			accountable = 0;
-
-		if (!file->f_op || !file->f_op->mmap)
-			return -ENODEV;
-
-		if ((prot & PROT_EXEC) &&
-		    (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
-			return -EPERM;
-	}
 	/*
 	 * Does the application expect PROT_READ to imply PROT_EXEC?
 	 *
@@ -1000,6 +989,16 @@
 		case MAP_PRIVATE:
 			if (!(file->f_mode & FMODE_READ))
 				return -EACCES;
+			if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+				if (vm_flags & VM_EXEC)
+					return -EPERM;
+				vm_flags &= ~VM_MAYEXEC;
+			}
+			if (is_file_hugepages(file))
+				accountable = 0;
+
+			if (!file->f_op || !file->f_op->mmap)
+				return -ENODEV;
 			break;
 
 		default:
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 20f41b0..2e3ce3a 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -15,6 +15,7 @@
  *  kernel subsystems and hints as to where to find out what things do.
  */
 
+#include <linux/oom.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/swap.h>
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index a0f3390..8d9b19f 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -222,7 +222,7 @@
 			if (pages_written >= write_chunk)
 				break;		/* We've done our duty */
 		}
-		blk_congestion_wait(WRITE, HZ/10);
+		congestion_wait(WRITE, HZ/10);
 	}
 
 	if (nr_reclaimable + global_page_state(NR_WRITEBACK)
@@ -314,7 +314,7 @@
                 if (global_page_state(NR_UNSTABLE_NFS) +
 			global_page_state(NR_WRITEBACK) <= dirty_thresh)
                         	break;
-                blk_congestion_wait(WRITE, HZ/10);
+                congestion_wait(WRITE, HZ/10);
         }
 }
 
@@ -351,7 +351,7 @@
 		min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
 		if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
 			/* Wrote less than expected */
-			blk_congestion_wait(WRITE, HZ/10);
+			congestion_wait(WRITE, HZ/10);
 			if (!wbc.encountered_congestion)
 				break;
 		}
@@ -422,7 +422,7 @@
 		writeback_inodes(&wbc);
 		if (wbc.nr_to_write > 0) {
 			if (wbc.encountered_congestion)
-				blk_congestion_wait(WRITE, HZ/10);
+				congestion_wait(WRITE, HZ/10);
 			else
 				break;	/* All the old data is written */
 		}
@@ -956,15 +956,6 @@
 EXPORT_SYMBOL(test_set_page_writeback);
 
 /*
- * Wakes up tasks that are being throttled due to writeback congestion
- */
-void writeback_congestion_end(void)
-{
-	blk_congestion_end(WRITE);
-}
-EXPORT_SYMBOL(writeback_congestion_end);
-
-/*
  * Return true if any of the pages in the mapping are marged with the
  * passed tag.
  */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a8c003e..f5fc454 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -39,6 +39,7 @@
 #include <linux/stop_machine.h>
 #include <linux/sort.h>
 #include <linux/pfn.h>
+#include <linux/backing-dev.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -495,17 +496,16 @@
 	int i;
 	int reserved = 0;
 
-	arch_free_page(page, order);
-	if (!PageHighMem(page))
-		debug_check_no_locks_freed(page_address(page),
-					   PAGE_SIZE<<order);
-
 	for (i = 0 ; i < (1 << order) ; ++i)
 		reserved += free_pages_check(page + i);
 	if (reserved)
 		return;
 
+	if (!PageHighMem(page))
+		debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order);
+	arch_free_page(page, order);
 	kernel_map_pages(page, 1 << order, 0);
+
 	local_irq_save(flags);
 	__count_vm_events(PGFREE, 1 << order);
 	free_one_page(page_zone(page), page, order);
@@ -781,13 +781,14 @@
 	struct per_cpu_pages *pcp;
 	unsigned long flags;
 
-	arch_free_page(page, 0);
-
 	if (PageAnon(page))
 		page->mapping = NULL;
 	if (free_pages_check(page))
 		return;
 
+	if (!PageHighMem(page))
+		debug_check_no_locks_freed(page_address(page), PAGE_SIZE);
+	arch_free_page(page, 0);
 	kernel_map_pages(page, 1, 0);
 
 	pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
@@ -1050,7 +1051,7 @@
 			if (page)
 				goto got_pg;
 			if (gfp_mask & __GFP_NOFAIL) {
-				blk_congestion_wait(WRITE, HZ/50);
+				congestion_wait(WRITE, HZ/50);
 				goto nofail_alloc;
 			}
 		}
@@ -1113,7 +1114,7 @@
 			do_retry = 1;
 	}
 	if (do_retry) {
-		blk_congestion_wait(WRITE, HZ/50);
+		congestion_wait(WRITE, HZ/50);
 		goto rebalance;
 	}
 
@@ -1688,6 +1689,8 @@
 	for (pfn = start_pfn; pfn < end_pfn; pfn++) {
 		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);
@@ -2294,19 +2297,6 @@
 	return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
 }
 
-/* Return the zone index a PFN is in */
-int memmap_zone_idx(struct page *lmem_map)
-{
-	int i;
-	unsigned long phys_addr = virt_to_phys(lmem_map);
-	unsigned long pfn = phys_addr >> PAGE_SHIFT;
-
-	for (i = 0; i < MAX_NR_ZONES; i++)
-		if (pfn < arch_zone_highest_possible_pfn[i])
-			break;
-
-	return i;
-}
 #else
 static inline unsigned long zone_spanned_pages_in_node(int nid,
 					unsigned long zone_type,
@@ -2325,10 +2315,6 @@
 	return zholes_size[zone_type];
 }
 
-static inline int memmap_zone_idx(struct page *lmem_map)
-{
-	return MAX_NR_ZONES;
-}
 #endif
 
 static void __init calculate_node_totalpages(struct pglist_data *pgdat,
@@ -3136,3 +3122,19 @@
 EXPORT_SYMBOL(pfn_to_page);
 EXPORT_SYMBOL(page_to_pfn);
 #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
+
+#if MAX_NUMNODES > 1
+/*
+ * Find the highest possible node id.
+ */
+int highest_possible_node_id(void)
+{
+	unsigned int node;
+	unsigned int highest = 0;
+
+	for_each_node_mask(node, node_possible_map)
+		highest = node;
+	return highest;
+}
+EXPORT_SYMBOL(highest_possible_node_id);
+#endif
diff --git a/mm/rmap.c b/mm/rmap.c
index e2155d7..d8a842a 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -21,27 +21,21 @@
  * Lock ordering in mm:
  *
  * inode->i_mutex	(while writing or truncating, not reading or faulting)
- *   inode->i_alloc_sem
- *
- * When a page fault occurs in writing from user to file, down_read
- * of mmap_sem nests within i_mutex; in sys_msync, i_mutex nests within
- * down_read of mmap_sem; i_mutex and down_write of mmap_sem are never
- * taken together; in truncation, i_mutex is taken outermost.
- *
- * mm->mmap_sem
- *   page->flags PG_locked (lock_page)
- *     mapping->i_mmap_lock
- *       anon_vma->lock
- *         mm->page_table_lock or pte_lock
- *           zone->lru_lock (in mark_page_accessed, isolate_lru_page)
- *           swap_lock (in swap_duplicate, swap_info_get)
- *             mmlist_lock (in mmput, drain_mmlist and others)
- *             mapping->private_lock (in __set_page_dirty_buffers)
- *             inode_lock (in set_page_dirty's __mark_inode_dirty)
- *               sb_lock (within inode_lock in fs/fs-writeback.c)
- *               mapping->tree_lock (widely used, in set_page_dirty,
- *                         in arch-dependent flush_dcache_mmap_lock,
- *                         within inode_lock in __sync_single_inode)
+ *   inode->i_alloc_sem (vmtruncate_range)
+ *   mm->mmap_sem
+ *     page->flags PG_locked (lock_page)
+ *       mapping->i_mmap_lock
+ *         anon_vma->lock
+ *           mm->page_table_lock or pte_lock
+ *             zone->lru_lock (in mark_page_accessed, isolate_lru_page)
+ *             swap_lock (in swap_duplicate, swap_info_get)
+ *               mmlist_lock (in mmput, drain_mmlist and others)
+ *               mapping->private_lock (in __set_page_dirty_buffers)
+ *               inode_lock (in set_page_dirty's __mark_inode_dirty)
+ *                 sb_lock (within inode_lock in fs/fs-writeback.c)
+ *                 mapping->tree_lock (widely used, in set_page_dirty,
+ *                           in arch-dependent flush_dcache_mmap_lock,
+ *                           within inode_lock in __sync_single_inode)
  */
 
 #include <linux/mm.h>
@@ -576,15 +570,14 @@
 void page_remove_rmap(struct page *page)
 {
 	if (atomic_add_negative(-1, &page->_mapcount)) {
-#ifdef CONFIG_DEBUG_VM
 		if (unlikely(page_mapcount(page) < 0)) {
 			printk (KERN_EMERG "Eeek! page_mapcount(page) went negative! (%d)\n", page_mapcount(page));
 			printk (KERN_EMERG "  page->flags = %lx\n", page->flags);
 			printk (KERN_EMERG "  page->count = %x\n", page_count(page));
 			printk (KERN_EMERG "  page->mapping = %p\n", page->mapping);
+			BUG();
 		}
-#endif
-		BUG_ON(page_mapcount(page) < 0);
+
 		/*
 		 * It would be tidy to reset the PageAnon mapping here,
 		 * but that might overwrite a racing page_add_anon_rmap
diff --git a/mm/shmem.c b/mm/shmem.c
index bb8ca7e..4959535 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -48,6 +48,7 @@
 #include <linux/ctype.h>
 #include <linux/migrate.h>
 #include <linux/highmem.h>
+#include <linux/backing-dev.h>
 
 #include <asm/uaccess.h>
 #include <asm/div64.h>
@@ -1131,7 +1132,7 @@
 			page_cache_release(swappage);
 			if (error == -ENOMEM) {
 				/* let kswapd refresh zone for GFP_ATOMICs */
-				blk_congestion_wait(WRITE, HZ/50);
+				congestion_wait(WRITE, HZ/50);
 			}
 			goto repeat;
 		}
@@ -1362,6 +1363,7 @@
 		inode->i_mapping->a_ops = &shmem_aops;
 		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_generation = get_seconds();
 		info = SHMEM_I(inode);
 		memset(info, 0, (char *)inode - (char *)info);
 		spin_lock_init(&info->lock);
@@ -1956,6 +1958,85 @@
 };
 #endif
 
+static struct dentry *shmem_get_parent(struct dentry *child)
+{
+	return ERR_PTR(-ESTALE);
+}
+
+static int shmem_match(struct inode *ino, void *vfh)
+{
+	__u32 *fh = vfh;
+	__u64 inum = fh[2];
+	inum = (inum << 32) | fh[1];
+	return ino->i_ino == inum && fh[0] == ino->i_generation;
+}
+
+static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh)
+{
+	struct dentry *de = NULL;
+	struct inode *inode;
+	__u32 *fh = vfh;
+	__u64 inum = fh[2];
+	inum = (inum << 32) | fh[1];
+
+	inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh);
+	if (inode) {
+		de = d_find_alias(inode);
+		iput(inode);
+	}
+
+	return de? de: ERR_PTR(-ESTALE);
+}
+
+static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh,
+		int len, int type,
+		int (*acceptable)(void *context, struct dentry *de),
+		void *context)
+{
+	if (len < 3)
+		return ERR_PTR(-ESTALE);
+
+	return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable,
+							context);
+}
+
+static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
+				int connectable)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (*len < 3)
+		return 255;
+
+	if (hlist_unhashed(&inode->i_hash)) {
+		/* Unfortunately insert_inode_hash is not idempotent,
+		 * so as we hash inodes here rather than at creation
+		 * time, we need a lock to ensure we only try
+		 * to do it once
+		 */
+		static DEFINE_SPINLOCK(lock);
+		spin_lock(&lock);
+		if (hlist_unhashed(&inode->i_hash))
+			__insert_inode_hash(inode,
+					    inode->i_ino + inode->i_generation);
+		spin_unlock(&lock);
+	}
+
+	fh[0] = inode->i_generation;
+	fh[1] = inode->i_ino;
+	fh[2] = ((__u64)inode->i_ino) >> 32;
+
+	*len = 3;
+	return 1;
+}
+
+static struct export_operations shmem_export_ops = {
+	.get_parent     = shmem_get_parent,
+	.get_dentry     = shmem_get_dentry,
+	.encode_fh      = shmem_encode_fh,
+	.decode_fh      = shmem_decode_fh,
+};
+
 static int shmem_parse_options(char *options, int *mode, uid_t *uid,
 	gid_t *gid, unsigned long *blocks, unsigned long *inodes,
 	int *policy, nodemask_t *policy_nodes)
@@ -2128,6 +2209,7 @@
 					&inodes, &policy, &policy_nodes))
 			return -EINVAL;
 	}
+	sb->s_export_op = &shmem_export_ops;
 #else
 	sb->s_flags |= MS_NOUSER;
 #endif
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
index c946bf4..f5664c5 100644
--- a/mm/shmem_acl.c
+++ b/mm/shmem_acl.c
@@ -35,7 +35,7 @@
 }
 
 /**
- * shmem_get_acl  -   generic_acl_operations->setacl() operation
+ * shmem_set_acl  -   generic_acl_operations->setacl() operation
  */
 static void
 shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
diff --git a/mm/slab.c b/mm/slab.c
index e9a63b5..84c631f 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1106,15 +1106,18 @@
 	int nodeid = slabp->nodeid;
 	struct kmem_list3 *l3;
 	struct array_cache *alien = NULL;
+	int node;
+
+	node = numa_node_id();
 
 	/*
 	 * Make sure we are not freeing a object from another node to the array
 	 * cache on this cpu.
 	 */
-	if (likely(slabp->nodeid == numa_node_id()))
+	if (likely(slabp->nodeid == node))
 		return 0;
 
-	l3 = cachep->nodelists[numa_node_id()];
+	l3 = cachep->nodelists[node];
 	STATS_INC_NODEFREES(cachep);
 	if (l3->alien && l3->alien[nodeid]) {
 		alien = l3->alien[nodeid];
@@ -1325,7 +1328,6 @@
 {
 	struct kmem_list3 *ptr;
 
-	BUG_ON(cachep->nodelists[nodeid] != list);
 	ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, nodeid);
 	BUG_ON(!ptr);
 
@@ -1352,6 +1354,7 @@
 	struct cache_names *names;
 	int i;
 	int order;
+	int node;
 
 	for (i = 0; i < NUM_INIT_LISTS; i++) {
 		kmem_list3_init(&initkmem_list3[i]);
@@ -1386,12 +1389,14 @@
 	 * 6) Resize the head arrays of the kmalloc caches to their final sizes.
 	 */
 
+	node = numa_node_id();
+
 	/* 1) create the cache_cache */
 	INIT_LIST_HEAD(&cache_chain);
 	list_add(&cache_cache.next, &cache_chain);
 	cache_cache.colour_off = cache_line_size();
 	cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
-	cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE];
+	cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];
 
 	cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
 					cache_line_size());
@@ -1496,19 +1501,18 @@
 	}
 	/* 5) Replace the bootstrap kmem_list3's */
 	{
-		int node;
-		/* Replace the static kmem_list3 structures for the boot cpu */
-		init_list(&cache_cache, &initkmem_list3[CACHE_CACHE],
-			  numa_node_id());
+		int nid;
 
-		for_each_online_node(node) {
+		/* Replace the static kmem_list3 structures for the boot cpu */
+		init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], node);
+
+		for_each_online_node(nid) {
 			init_list(malloc_sizes[INDEX_AC].cs_cachep,
-				  &initkmem_list3[SIZE_AC + node], node);
+				  &initkmem_list3[SIZE_AC + nid], nid);
 
 			if (INDEX_AC != INDEX_L3) {
 				init_list(malloc_sizes[INDEX_L3].cs_cachep,
-					  &initkmem_list3[SIZE_L3 + node],
-					  node);
+					  &initkmem_list3[SIZE_L3 + nid], nid);
 			}
 		}
 	}
@@ -2918,6 +2922,9 @@
 	int batchcount;
 	struct kmem_list3 *l3;
 	struct array_cache *ac;
+	int node;
+
+	node = numa_node_id();
 
 	check_irq_off();
 	ac = cpu_cache_get(cachep);
@@ -2931,7 +2938,7 @@
 		 */
 		batchcount = BATCHREFILL_LIMIT;
 	}
-	l3 = cachep->nodelists[numa_node_id()];
+	l3 = cachep->nodelists[node];
 
 	BUG_ON(ac->avail > 0 || !l3);
 	spin_lock(&l3->list_lock);
@@ -2961,7 +2968,7 @@
 			STATS_SET_HIGH(cachep);
 
 			ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
-							    numa_node_id());
+							    node);
 		}
 		check_slabp(cachep, slabp);
 
@@ -2980,7 +2987,7 @@
 
 	if (unlikely(!ac->avail)) {
 		int x;
-		x = cache_grow(cachep, flags, numa_node_id());
+		x = cache_grow(cachep, flags, node);
 
 		/* cache_grow can reenable interrupts, then ac could change. */
 		ac = cpu_cache_get(cachep);
@@ -3145,12 +3152,15 @@
 	struct zone **z;
 	void *obj = NULL;
 
-	for (z = zonelist->zones; *z && !obj; z++)
+	for (z = zonelist->zones; *z && !obj; z++) {
+		int nid = zone_to_nid(*z);
+
 		if (zone_idx(*z) <= ZONE_NORMAL &&
-				cpuset_zone_allowed(*z, flags))
+				cpuset_zone_allowed(*z, flags) &&
+				cache->nodelists[nid])
 			obj = __cache_alloc_node(cache,
-					flags | __GFP_THISNODE,
-					zone_to_nid(*z));
+					flags | __GFP_THISNODE, nid);
+	}
 	return obj;
 }
 
diff --git a/mm/truncate.c b/mm/truncate.c
index f4edbc1..e07b1e6 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -96,7 +96,6 @@
 		return 0;
 
 	ret = remove_mapping(mapping, page);
-	ClearPageUptodate(page);
 
 	return ret;
 }
@@ -302,7 +301,7 @@
 	if (page->mapping != mapping)
 		return 0;
 
-	if (PagePrivate(page) && !try_to_release_page(page, 0))
+	if (PagePrivate(page) && !try_to_release_page(page, GFP_KERNEL))
 		return 0;
 
 	write_lock_irq(&mapping->tree_lock);
@@ -396,6 +395,7 @@
 		pagevec_release(&pvec);
 		cond_resched();
 	}
+	WARN_ON_ONCE(ret);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 750ab6e..1133dd3 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -428,8 +428,11 @@
 	if (array_size > PAGE_SIZE) {
 		pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node);
 		area->flags |= VM_VPAGES;
-	} else
-		pages = kmalloc_node(array_size, (gfp_mask & ~__GFP_HIGHMEM), node);
+	} else {
+		pages = kmalloc_node(array_size,
+				(gfp_mask & ~(__GFP_HIGHMEM | __GFP_ZERO)),
+				node);
+	}
 	area->pages = pages;
 	if (!area->pages) {
 		remove_vm_area(area->addr);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index eca7031..f05527b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -378,6 +378,12 @@
 	return PAGE_CLEAN;
 }
 
+/*
+ * Attempt to detach a locked page from its ->mapping.  If it is dirty or if
+ * someone else has a ref on the page, abort and return 0.  If it was
+ * successfully detached, return 1.  Assumes the caller has a single ref on
+ * this page.
+ */
 int remove_mapping(struct address_space *mapping, struct page *page)
 {
 	BUG_ON(!PageLocked(page));
@@ -1053,7 +1059,7 @@
 
 		/* Take a nap, wait for some writeback to complete */
 		if (sc.nr_scanned && priority < DEF_PRIORITY - 2)
-			blk_congestion_wait(WRITE, HZ/10);
+			congestion_wait(WRITE, HZ/10);
 	}
 	/* top priority shrink_caches still had more to do? don't OOM, then */
 	if (!sc.all_unreclaimable)
@@ -1208,7 +1214,7 @@
 		 * another pass across the zones.
 		 */
 		if (total_scanned && priority < DEF_PRIORITY - 2)
-			blk_congestion_wait(WRITE, HZ/10);
+			congestion_wait(WRITE, HZ/10);
 
 		/*
 		 * We do this so kswapd doesn't build up large priorities for
@@ -1452,7 +1458,7 @@
 				goto out;
 
 			if (sc.nr_scanned && prio < DEF_PRIORITY - 2)
-				blk_congestion_wait(WRITE, HZ / 10);
+				congestion_wait(WRITE, HZ / 10);
 		}
 
 		lru_pages = 0;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index da9cfe9..60a508e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -62,7 +62,7 @@
 	default:
 		printk(VLAN_DBG
 		       "%s: unable to resolve type %X addresses.\n", 
-		       dev->name, (int)veth->h_vlan_encapsulated_proto);
+		       dev->name, ntohs(veth->h_vlan_encapsulated_proto));
 	 
 		memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
 		break;
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index c0a4ae2..62f6ed1 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -141,7 +141,7 @@
 int atm_register_sysfs(struct atm_dev *adev)
 {
 	struct class_device *cdev = &adev->class_dev;
-	int i, err;
+	int i, j, err;
 
 	cdev->class = &atm_class;
 	class_set_devdata(cdev, adev);
@@ -151,10 +151,19 @@
 	if (err < 0)
 		return err;
 
-	for (i = 0; atm_attrs[i]; i++)
-		class_device_create_file(cdev, atm_attrs[i]);
+	for (i = 0; atm_attrs[i]; i++) {
+		err = class_device_create_file(cdev, atm_attrs[i]);
+		if (err)
+			goto err_out;
+	}
 
 	return 0;
+
+err_out:
+	for (j = 0; j < i; j++)
+		class_device_remove_file(cdev, atm_attrs[j]);
+	class_device_del(cdev);
+	return err;
 }
 
 void atm_unregister_sysfs(struct atm_dev *adev)
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 305a099..67df99e 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -48,41 +48,56 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.10"
+#define VERSION "2.11"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO	8
 static struct net_proto_family *bt_proto[BT_MAX_PROTO];
+static DEFINE_RWLOCK(bt_proto_lock);
 
 int bt_sock_register(int proto, struct net_proto_family *ops)
 {
+	int err = 0;
+
 	if (proto < 0 || proto >= BT_MAX_PROTO)
 		return -EINVAL;
 
-	if (bt_proto[proto])
-		return -EEXIST;
+	write_lock(&bt_proto_lock);
 
-	bt_proto[proto] = ops;
-	return 0;
+	if (bt_proto[proto])
+		err = -EEXIST;
+	else
+		bt_proto[proto] = ops;
+
+	write_unlock(&bt_proto_lock);
+
+	return err;
 }
 EXPORT_SYMBOL(bt_sock_register);
 
 int bt_sock_unregister(int proto)
 {
+	int err = 0;
+
 	if (proto < 0 || proto >= BT_MAX_PROTO)
 		return -EINVAL;
 
-	if (!bt_proto[proto])
-		return -ENOENT;
+	write_lock(&bt_proto_lock);
 
-	bt_proto[proto] = NULL;
-	return 0;
+	if (!bt_proto[proto])
+		err = -ENOENT;
+	else
+		bt_proto[proto] = NULL;
+
+	write_unlock(&bt_proto_lock);
+
+	return err;
 }
 EXPORT_SYMBOL(bt_sock_unregister);
 
 static int bt_sock_create(struct socket *sock, int proto)
 {
-	int err = 0;
+	int err;
 
 	if (proto < 0 || proto >= BT_MAX_PROTO)
 		return -EINVAL;
@@ -92,11 +107,18 @@
 		request_module("bt-proto-%d", proto);
 	}
 #endif
+
 	err = -EPROTONOSUPPORT;
+
+	read_lock(&bt_proto_lock);
+
 	if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
 		err = bt_proto[proto]->create(sock, proto);
 		module_put(bt_proto[proto]->owner);
 	}
+
+	read_unlock(&bt_proto_lock);
+
 	return err; 
 }
 
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 2312d05..4d3424c 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -528,12 +528,10 @@
 		return NULL;
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-	if (!conn)
-		return NULL;
 
 	hci_dev_put(hdev);
 
-	return &conn->dev;
+	return conn ? &conn->dev : NULL;
 }
 
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 28c5583..5563db1 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -43,6 +43,7 @@
 #include <linux/ioctl.h>
 #include <linux/file.h>
 #include <linux/init.h>
+#include <linux/compat.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -146,24 +147,56 @@
 	return 0;
 }
 
+#ifdef CONFIG_COMPAT
+static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	if (cmd == BNEPGETCONNLIST) {
+		struct bnep_connlist_req cl;
+		uint32_t uci;
+		int err;
+
+		if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+				get_user(uci, (u32 __user *) (arg + 4)))
+			return -EFAULT;
+
+		cl.ci = compat_ptr(uci);
+
+		if (cl.cnum <= 0)
+			return -EINVAL;
+	
+		err = bnep_get_connlist(&cl);
+
+		if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+			err = -EFAULT;
+
+		return err;
+	}
+
+	return bnep_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
 static const struct proto_ops bnep_sock_ops = {
-	.family     = PF_BLUETOOTH,
-	.owner      = THIS_MODULE,
-	.release    = bnep_sock_release,
-	.ioctl      = bnep_sock_ioctl,
-	.bind       = sock_no_bind,
-	.getname    = sock_no_getname,
-	.sendmsg    = sock_no_sendmsg,
-	.recvmsg    = sock_no_recvmsg,
-	.poll       = sock_no_poll,
-	.listen     = sock_no_listen,
-	.shutdown   = sock_no_shutdown,
-	.setsockopt = sock_no_setsockopt,
-	.getsockopt = sock_no_getsockopt,
-	.connect    = sock_no_connect,
-	.socketpair = sock_no_socketpair,
-	.accept     = sock_no_accept,
-	.mmap       = sock_no_mmap
+	.family		= PF_BLUETOOTH,
+	.owner		= THIS_MODULE,
+	.release	= bnep_sock_release,
+	.ioctl		= bnep_sock_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= bnep_sock_compat_ioctl,
+#endif
+	.bind		= sock_no_bind,
+	.getname	= sock_no_getname,
+	.sendmsg	= sock_no_sendmsg,
+	.recvmsg	= sock_no_recvmsg,
+	.poll		= sock_no_poll,
+	.listen		= sock_no_listen,
+	.shutdown	= sock_no_shutdown,
+	.setsockopt	= sock_no_setsockopt,
+	.getsockopt	= sock_no_getsockopt,
+	.connect	= sock_no_connect,
+	.socketpair	= sock_no_socketpair,
+	.accept		= sock_no_accept,
+	.mmap		= sock_no_mmap
 };
 
 static struct proto bnep_proto = {
@@ -181,7 +214,7 @@
 	if (sock->type != SOCK_RAW)
 		return -ESOCKTNOSUPPORT;
 
-	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
+	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
 	if (!sk)
 		return -ENOMEM;
 
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 10ad7fd..53295d3 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -34,6 +34,7 @@
 #include <linux/socket.h>
 #include <linux/ioctl.h>
 #include <linux/file.h>
+#include <linux/compat.h>
 #include <net/sock.h>
 
 #include <linux/isdn/capilli.h>
@@ -137,11 +138,43 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	if (cmd == CMTPGETCONNLIST) {
+		struct cmtp_connlist_req cl;
+		uint32_t uci;
+		int err;
+
+		if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+				get_user(uci, (u32 __user *) (arg + 4)))
+			return -EFAULT;
+
+		cl.ci = compat_ptr(uci);
+
+		if (cl.cnum <= 0)
+			return -EINVAL;
+	
+		err = cmtp_get_connlist(&cl);
+
+		if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+			err = -EFAULT;
+
+		return err;
+	}
+
+	return cmtp_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
 static const struct proto_ops cmtp_sock_ops = {
 	.family		= PF_BLUETOOTH,
 	.owner		= THIS_MODULE,
 	.release	= cmtp_sock_release,
 	.ioctl		= cmtp_sock_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= cmtp_sock_compat_ioctl,
+#endif
 	.bind		= sock_no_bind,
 	.getname	= sock_no_getname,
 	.sendmsg	= sock_no_sendmsg,
@@ -172,7 +205,7 @@
 	if (sock->type != SOCK_RAW)
 		return -ESOCKTNOSUPPORT;
 
-	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
+	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
 	if (!sk)
 		return -ENOMEM;
 
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 90e3a28..6cd5711 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -51,7 +51,7 @@
 #define BT_DBG(D...)
 #endif
 
-static void hci_acl_connect(struct hci_conn *conn)
+void hci_acl_connect(struct hci_conn *conn)
 {
 	struct hci_dev *hdev = conn->hdev;
 	struct inquiry_entry *ie;
@@ -63,6 +63,8 @@
 	conn->out   = 1;
 	conn->link_mode = HCI_LM_MASTER;
 
+	conn->attempt++;
+
 	memset(&cp, 0, sizeof(cp));
 	bacpy(&cp.bdaddr, &conn->dst);
 	cp.pscan_rep_mode = 0x02;
@@ -80,7 +82,7 @@
 		cp.role_switch	= 0x01;
 	else
 		cp.role_switch	= 0x00;
-		
+
 	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
 }
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d43d0c8..65f0948 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -414,9 +414,12 @@
 
 	if (status) {
 		if (conn && conn->state == BT_CONNECT) {
-			conn->state = BT_CLOSED;
-			hci_proto_connect_cfm(conn, status);
-			hci_conn_del(conn);
+			if (status != 0x0c || conn->attempt > 2) {
+				conn->state = BT_CLOSED;
+				hci_proto_connect_cfm(conn, status);
+				hci_conn_del(conn);
+			} else
+				conn->state = BT_CONNECT2;
 		}
 	} else {
 		if (!conn) {
@@ -728,7 +731,7 @@
 static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
-	struct hci_conn *conn;
+	struct hci_conn *conn, *pend;
 
 	BT_DBG("%s", hdev->name);
 
@@ -801,6 +804,10 @@
 	if (ev->status)
 		hci_conn_del(conn);
 
+	pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+	if (pend)
+		hci_acl_connect(pend);
+
 	hci_dev_unlock(hdev);
 }
 
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 1a35d34..f26a9eb 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -618,7 +618,7 @@
 
 	sock->ops = &hci_sock_ops;
 
-	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
+	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
 	if (!sk)
 		return -ENOMEM;
 
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 989b22d..954eb74 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -242,10 +242,14 @@
 	struct hci_conn *conn = data;
 	int i;
 
-	device_register(&conn->dev);
+	if (device_register(&conn->dev) < 0) {
+		BT_ERR("Failed to register connection device");
+		return;
+	}
 
 	for (i = 0; conn_attrs[i]; i++)
-		device_create_file(&conn->dev, conn_attrs[i]);
+		if (device_create_file(&conn->dev, conn_attrs[i]) < 0)
+			BT_ERR("Failed to create connection attribute");
 }
 
 void hci_conn_add_sysfs(struct hci_conn *conn)
@@ -295,11 +299,7 @@
 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
 	dev->class = bt_class;
-
-	if (hdev->parent)
-		dev->parent = hdev->parent;
-	else
-		dev->parent = &bt_platform->dev;
+	dev->parent = hdev->parent;
 
 	strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
 
@@ -312,7 +312,8 @@
 		return err;
 
 	for (i = 0; bt_attrs[i]; i++)
-		device_create_file(dev, bt_attrs[i]);
+		if (device_create_file(dev, bt_attrs[i]) < 0)
+			BT_ERR("Failed to create device attribute");
 
 	return 0;
 }
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 03b5dad..6678201 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -507,15 +507,13 @@
 
 	hidp_del_timer(session);
 
-	if (intr_sk->sk_state != BT_CONNECTED)
-		wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
+	fput(session->intr_sock->file);
+
+	wait_event_timeout(*(ctrl_sk->sk_sleep),
+		(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
 
 	fput(session->ctrl_sock->file);
 
-	wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
-
-	fput(session->intr_sock->file);
-
 	__hidp_unlink_session(session);
 
 	if (session->input) {
@@ -541,12 +539,10 @@
 		return NULL;
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-	if (!conn)
-		return NULL;
 
 	hci_dev_put(hdev);
 
-	return &conn->dev;
+	return conn ? &conn->dev : NULL;
 }
 
 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 099646e..407fba4 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -35,6 +35,7 @@
 #include <linux/ioctl.h>
 #include <linux/file.h>
 #include <linux/init.h>
+#include <linux/compat.h>
 #include <net/sock.h>
 
 #include "hidp.h"
@@ -143,11 +144,88 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_hidp_connadd_req {
+	int   ctrl_sock;	// Connected control socket
+	int   intr_sock;	// Connteted interrupt socket
+	__u16 parser;
+	__u16 rd_size;
+	compat_uptr_t rd_data;
+	__u8  country;
+	__u8  subclass;
+	__u16 vendor;
+	__u16 product;
+	__u16 version;
+	__u32 flags;
+	__u32 idle_to;
+	char  name[128];
+};
+
+static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	if (cmd == HIDPGETCONNLIST) {
+		struct hidp_connlist_req cl;
+		uint32_t uci;
+		int err;
+
+		if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+				get_user(uci, (u32 __user *) (arg + 4)))
+			return -EFAULT;
+
+		cl.ci = compat_ptr(uci);
+
+		if (cl.cnum <= 0)
+			return -EINVAL;
+
+		err = hidp_get_connlist(&cl);
+
+		if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+			err = -EFAULT;
+
+		return err;
+	} else if (cmd == HIDPCONNADD) {
+		struct compat_hidp_connadd_req ca;
+		struct hidp_connadd_req __user *uca;
+
+		uca = compat_alloc_user_space(sizeof(*uca));
+
+		if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
+			return -EFAULT;
+
+		if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
+				put_user(ca.intr_sock, &uca->intr_sock) ||
+				put_user(ca.parser, &uca->parser) ||
+				put_user(ca.rd_size, &uca->parser) ||
+				put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
+				put_user(ca.country, &uca->country) ||
+				put_user(ca.subclass, &uca->subclass) ||
+				put_user(ca.vendor, &uca->vendor) ||
+				put_user(ca.product, &uca->product) ||
+				put_user(ca.version, &uca->version) ||
+				put_user(ca.flags, &uca->flags) ||
+				put_user(ca.idle_to, &uca->idle_to) ||
+				copy_to_user(&uca->name[0], &ca.name[0], 128))
+			return -EFAULT;
+		
+		arg = (unsigned long) uca;
+
+		/* Fall through. We don't actually write back any _changes_
+		   to the structure anyway, so there's no need to copy back
+		   into the original compat version */
+	}
+
+	return hidp_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
 static const struct proto_ops hidp_sock_ops = {
 	.family		= PF_BLUETOOTH,
 	.owner		= THIS_MODULE,
 	.release	= hidp_sock_release,
 	.ioctl		= hidp_sock_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= hidp_sock_compat_ioctl,
+#endif
 	.bind		= sock_no_bind,
 	.getname	= sock_no_getname,
 	.sendmsg	= sock_no_sendmsg,
@@ -178,7 +256,7 @@
 	if (sock->type != SOCK_RAW)
 		return -ESOCKTNOSUPPORT;
 
-	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
+	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
 	if (!sk)
 		return -ENOMEM;
 
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index d56f60b..2b3dcb8 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -559,7 +559,7 @@
 
 	sock->ops = &l2cap_sock_ops;
 
-	sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
+	sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
 	if (!sk)
 		return -ENOMEM;
 
@@ -2216,7 +2216,8 @@
 		goto error;
 	}
 
-	class_create_file(bt_class, &class_attr_l2cap);
+	if (class_create_file(bt_class, &class_attr_l2cap) < 0)
+		BT_ERR("Failed to create L2CAP info file");
 
 	BT_INFO("L2CAP ver %s", VERSION);
 	BT_INFO("L2CAP socket layer initialized");
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 468df3b..ddc4e9d 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2058,7 +2058,8 @@
 
 	kernel_thread(rfcomm_run, NULL, CLONE_KERNEL);
 
-	class_create_file(bt_class, &class_attr_rfcomm_dlc);
+	if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
+		BT_ERR("Failed to create RFCOMM info file");
 
 	rfcomm_init_sockets();
 
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 220fee0..544d65b 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -336,7 +336,8 @@
 
 	sock->ops = &rfcomm_sock_ops;
 
-	if (!(sk = rfcomm_sock_alloc(sock, protocol, GFP_KERNEL)))
+	sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
+	if (!sk)
 		return -ENOMEM;
 
 	rfcomm_sock_init(sk, NULL);
@@ -944,7 +945,8 @@
 	if (err < 0)
 		goto error;
 
-	class_create_file(bt_class, &class_attr_rfcomm);
+	if (class_create_file(bt_class, &class_attr_rfcomm) < 0)
+		BT_ERR("Failed to create RFCOMM info file");
 
 	BT_INFO("RFCOMM socket layer initialized");
 
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 1958ad1..b8e3a5f 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -172,12 +172,10 @@
 		return NULL;
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
-	if (!conn)
-		return NULL;
 
 	hci_dev_put(hdev);
 
-	return &conn->dev;
+	return conn ? &conn->dev : NULL;
 }
 
 static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
@@ -767,6 +765,9 @@
 
 	BT_DBG("tty %p termios %p", tty, old);
 
+	if (!dev)
+		return;
+
 	/* Handle turning off CRTSCTS */
 	if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) 
 		BT_DBG("Turning off CRTSCTS unsupported");
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 7714a2e..5d13d4f 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -452,7 +452,8 @@
 
 	sock->ops = &sco_sock_ops;
 
-	if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL)))
+	sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
+	if (!sk)
 		return -ENOMEM;
 
 	sco_sock_init(sk, NULL);
@@ -967,7 +968,8 @@
 		goto error;
 	}
 
-	class_create_file(bt_class, &class_attr_sco);
+	if (class_create_file(bt_class, &class_attr_sco) < 0)
+		BT_ERR("Failed to create SCO info file");
 
 	BT_INFO("SCO (Voice Link) ver %s", VERSION);
 	BT_INFO("SCO socket layer initialized");
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 3a73b8c..d9f0486 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -128,7 +128,10 @@
 	mod_timer(&br->gc_timer, jiffies + HZ/10);
 }
 
-void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
+
+void br_fdb_delete_by_port(struct net_bridge *br,
+			   const struct net_bridge_port *p,
+			   int do_all)
 {
 	int i;
 
@@ -142,6 +145,8 @@
 			if (f->dst != p) 
 				continue;
 
+			if (f->is_static && !do_all)
+				continue;
 			/*
 			 * if multiple ports all have the same device address
 			 * then when one port is deleted, assign
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index b1211d534..f753c40 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -163,7 +163,7 @@
 	br_stp_disable_port(p);
 	spin_unlock_bh(&br->lock);
 
-	br_fdb_delete_by_port(br, p);
+	br_fdb_delete_by_port(br, p, 1);
 
 	list_del_rcu(&p->list);
 
@@ -448,7 +448,7 @@
 
 	return 0;
 err2:
-	br_fdb_delete_by_port(br, p);
+	br_fdb_delete_by_port(br, p, 1);
 err1:
 	kobject_del(&p->kobj);
 err0:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c491fb2..74258d8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -143,7 +143,7 @@
 			      const unsigned char *newaddr);
 extern void br_fdb_cleanup(unsigned long arg);
 extern void br_fdb_delete_by_port(struct net_bridge *br,
-			   struct net_bridge_port *p);
+				  const struct net_bridge_port *p, int do_all);
 extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
 						 const unsigned char *addr);
 extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 14cd025..d294224 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -113,6 +113,8 @@
 	del_timer(&p->forward_delay_timer);
 	del_timer(&p->hold_timer);
 
+	br_fdb_delete_by_port(br, p, 0);
+
 	br_configuration_update(br);
 
 	br_port_state_selection(br);
diff --git a/net/compat.c b/net/compat.c
index d5d69fa..52d32f1 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -285,8 +285,7 @@
 
 	if (i > 0) {
 		int cmlen = CMSG_COMPAT_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		err = put_user(SOL_SOCKET, &cm->cmsg_level);
 		if (!err)
 			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
 		if (!err)
diff --git a/net/core/dev.c b/net/core/dev.c
index 4d891be..81c426a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3502,8 +3502,6 @@
 
 	BUG_ON(!dev_boot_phase);
 
-	net_random_init();
-
 	if (dev_proc_init())
 		goto out;
 
diff --git a/net/core/flow.c b/net/core/flow.c
index f23e7e3..b16d31a 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -85,6 +85,14 @@
 	add_timer(&flow_hash_rnd_timer);
 }
 
+static void flow_entry_kill(int cpu, struct flow_cache_entry *fle)
+{
+	if (fle->object)
+		atomic_dec(fle->object_ref);
+	kmem_cache_free(flow_cachep, fle);
+	flow_count(cpu)--;
+}
+
 static void __flow_cache_shrink(int cpu, int shrink_to)
 {
 	struct flow_cache_entry *fle, **flp;
@@ -100,10 +108,7 @@
 		}
 		while ((fle = *flp) != NULL) {
 			*flp = fle->next;
-			if (fle->object)
-				atomic_dec(fle->object_ref);
-			kmem_cache_free(flow_cachep, fle);
-			flow_count(cpu)--;
+			flow_entry_kill(cpu, fle);
 		}
 	}
 }
@@ -220,24 +225,33 @@
 
 nocache:
 	{
+		int err;
 		void *obj;
 		atomic_t *obj_ref;
 
-		resolver(key, family, dir, &obj, &obj_ref);
+		err = resolver(key, family, dir, &obj, &obj_ref);
 
 		if (fle) {
-			fle->genid = atomic_read(&flow_cache_genid);
+			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->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();
 
+		if (err)
+			obj = ERR_PTR(err);
 		return obj;
 	}
 }
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index ead5920..9308af0 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -335,13 +335,13 @@
 	memcpy(skb->data, msg, len);
 	skb->len += len;
 
-	udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
+	skb->h.uh = udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
 	udph->source = htons(np->local_port);
 	udph->dest = htons(np->remote_port);
 	udph->len = htons(udp_len);
 	udph->check = 0;
 
-	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
+	skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
 
 	/* iph->version = 4; iph->ihl = 5; */
 	put_unaligned(0x45, (unsigned char *)iph);
@@ -357,8 +357,8 @@
 	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
 
 	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-
-	eth->h_proto = htons(ETH_P_IP);
+	skb->mac.raw = skb->data;
+	skb->protocol = eth->h_proto = htons(ETH_P_IP);
 	memcpy(eth->h_source, np->local_mac, 6);
 	memcpy(eth->h_dest, np->remote_mac, 6);
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 221e403..02f3c79 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -602,7 +602,7 @@
 		goto errout;
 	}
 
-	err = rtnl_unicast(skb, NETLINK_CB(skb).pid);
+	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
 	kfree(iw_buf);
 	dev_put(dev);
diff --git a/net/core/scm.c b/net/core/scm.c
index 649d01e..271cf06 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -245,8 +245,7 @@
 	if (i > 0)
 	{
 		int cmlen = CMSG_LEN(i*sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		err = put_user(SOL_SOCKET, &cm->cmsg_level);
 		if (!err)
 			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
 		if (!err)
diff --git a/net/core/sock.c b/net/core/sock.c
index b77e155..d472db4 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -823,7 +823,7 @@
 				   af_family_slock_key_strings[sk->sk_family]);
 	lockdep_init_map(&sk->sk_lock.dep_map,
 			 af_family_key_strings[sk->sk_family],
-			 af_family_keys + sk->sk_family);
+			 af_family_keys + sk->sk_family, 0);
 }
 
 /**
diff --git a/net/core/utils.c b/net/core/utils.c
index 94c5d76..d93fe64 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -30,119 +30,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-/*
-  This is a maximally equidistributed combined Tausworthe generator
-  based on code from GNU Scientific Library 1.5 (30 Jun 2004)
-
-   x_n = (s1_n ^ s2_n ^ s3_n) 
-
-   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
-   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
-   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
-
-   The period of this generator is about 2^88.
-
-   From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
-   Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
-
-   This is available on the net from L'Ecuyer's home page,
-
-   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
-   ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps 
-
-   There is an erratum in the paper "Tables of Maximally
-   Equidistributed Combined LFSR Generators", Mathematics of
-   Computation, 68, 225 (1999), 261--269:
-   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
-
-        ... the k_j most significant bits of z_j must be non-
-        zero, for each j. (Note: this restriction also applies to the 
-        computer code given in [4], but was mistakenly not mentioned in
-        that paper.)
-   
-   This affects the seeding procedure by imposing the requirement
-   s1 > 1, s2 > 7, s3 > 15.
-
-*/
-struct nrnd_state {
-	u32 s1, s2, s3;
-};
-
-static DEFINE_PER_CPU(struct nrnd_state, net_rand_state);
-
-static u32 __net_random(struct nrnd_state *state)
-{
-#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
-
-	state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
-	state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
-	state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
-
-	return (state->s1 ^ state->s2 ^ state->s3);
-}
-
-static void __net_srandom(struct nrnd_state *state, unsigned long s)
-{
-	if (s == 0)
-		s = 1;      /* default seed is 1 */
-
-#define LCG(n) (69069 * n)
-	state->s1 = LCG(s);
-	state->s2 = LCG(state->s1);
-	state->s3 = LCG(state->s2);
-
-	/* "warm it up" */
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-}
-
-
-unsigned long net_random(void)
-{
-	unsigned long r;
-	struct nrnd_state *state = &get_cpu_var(net_rand_state);
-	r = __net_random(state);
-	put_cpu_var(state);
-	return r;
-}
-
-
-void net_srandom(unsigned long entropy)
-{
-	struct nrnd_state *state = &get_cpu_var(net_rand_state);
-	__net_srandom(state, state->s1^entropy);
-	put_cpu_var(state);
-}
-
-void __init net_random_init(void)
-{
-	int i;
-
-	for_each_possible_cpu(i) {
-		struct nrnd_state *state = &per_cpu(net_rand_state,i);
-		__net_srandom(state, i+jiffies);
-	}
-}
-
-static int net_random_reseed(void)
-{
-	int i;
-	unsigned long seed;
-
-	for_each_possible_cpu(i) {
-		struct nrnd_state *state = &per_cpu(net_rand_state,i);
-
-		get_random_bytes(&seed, sizeof(seed));
-		__net_srandom(state, seed);
-	}
-	return 0;
-}
-late_initcall(net_random_reseed);
-
 int net_msg_cost = 5*HZ;
 int net_msg_burst = 10;
 
@@ -153,10 +40,7 @@
 {
 	return __printk_ratelimit(net_msg_cost, net_msg_burst);
 }
-
-EXPORT_SYMBOL(net_random);
 EXPORT_SYMBOL(net_ratelimit);
-EXPORT_SYMBOL(net_srandom);
 
 /*
  * Convert an ASCII string to binary IP.
diff --git a/net/core/wireless.c b/net/core/wireless.c
index ffff0da..cb1b872 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -748,11 +748,39 @@
 		int	extra_size;
 		int	user_length = 0;
 		int	err;
+		int	essid_compat = 0;
 
 		/* Calculate space needed by arguments. Always allocate
 		 * for max space. Easier, and won't last long... */
 		extra_size = descr->max_tokens * descr->token_size;
 
+		/* Check need for ESSID compatibility for WE < 21 */
+		switch (cmd) {
+		case SIOCSIWESSID:
+		case SIOCGIWESSID:
+		case SIOCSIWNICKN:
+		case SIOCGIWNICKN:
+			if (iwr->u.data.length == descr->max_tokens + 1)
+				essid_compat = 1;
+			else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
+				char essid[IW_ESSID_MAX_SIZE + 1];
+
+				err = copy_from_user(essid, iwr->u.data.pointer,
+						     iwr->u.data.length *
+						     descr->token_size);
+				if (err)
+					return -EFAULT;
+
+				if (essid[iwr->u.data.length - 1] == '\0')
+					essid_compat = 1;
+			}
+			break;
+		default:
+			break;
+		}
+
+		iwr->u.data.length -= essid_compat;
+
 		/* Check what user space is giving us */
 		if(IW_IS_SET(cmd)) {
 			/* Check NULL pointer */
@@ -795,7 +823,8 @@
 #endif	/* WE_IOCTL_DEBUG */
 
 		/* Create the kernel buffer */
-		extra = kmalloc(extra_size, GFP_KERNEL);
+		/*    kzalloc ensures NULL-termination for essid_compat */
+		extra = kzalloc(extra_size, GFP_KERNEL);
 		if (extra == NULL) {
 			return -ENOMEM;
 		}
@@ -819,6 +848,8 @@
 		/* Call the handler */
 		ret = handler(dev, &info, &(iwr->u), extra);
 
+		iwr->u.data.length += essid_compat;
+
 		/* If we have something to return to the user */
 		if (!ret && IW_IS_GET(cmd)) {
 			/* Check if there is enough buffer up there */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index bf692c1..aaaf4d0 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -311,7 +311,7 @@
 	}
 
 	if (sk->sk_state == DCCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -449,6 +449,8 @@
 					   dccp_hdr(skb)->dccph_sport);
 }
 
+static struct request_sock_ops dccp_request_sock_ops;
+
 int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 {
 	struct inet_request_sock *ireq;
@@ -489,7 +491,7 @@
 	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
 		goto drop;
 
-	req = reqsk_alloc(sk->sk_prot->rsk_prot);
+	req = reqsk_alloc(&dccp_request_sock_ops);
 	if (req == NULL)
 		goto drop;
 
@@ -614,7 +616,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -980,7 +982,7 @@
 	goto discard_it;
 
 do_time_wait:
-	inet_twsk_put((struct inet_timewait_sock *)sk);
+	inet_twsk_put(inet_twsk(sk));
 	goto no_dccp_socket;
 }
 
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 7a47399..c8bf89b 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -285,7 +285,7 @@
 	}
 
 	if (sk->sk_state == DCCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -663,7 +663,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -672,7 +672,6 @@
 
 static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 {
-	struct inet_request_sock *ireq;
 	struct dccp_sock dp;
 	struct request_sock *req;
 	struct dccp_request_sock *dreq;
@@ -701,7 +700,7 @@
 	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
 		goto drop;
 
-	req = inet6_reqsk_alloc(sk->sk_prot->rsk_prot);
+	req = inet6_reqsk_alloc(&dccp6_request_sock_ops);
 	if (req == NULL)
 		goto drop;
 
@@ -713,7 +712,6 @@
 		goto drop_and_free;
 
 	ireq6 = inet6_rsk(req);
-	ireq = inet_rsk(req);
 	ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
 	ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
 	req->rcv_wnd	= dccp_feat_default_sequence_window;
@@ -997,6 +995,10 @@
 	if (sk->sk_state == DCCP_OPEN) { /* Fast path */
 		if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
 			goto reset;
+		if (opt_skb) {
+			/* This is where we would goto ipv6_pktoptions. */
+			__kfree_skb(opt_skb);
+		}
 		return 0;
 	}
 
@@ -1021,6 +1023,10 @@
 
 	if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
 		goto reset;
+	if (opt_skb) {
+		/* This is where we would goto ipv6_pktoptions. */
+		__kfree_skb(opt_skb);
+	}
 	return 0;
 
 reset:
@@ -1109,7 +1115,7 @@
 	goto discard_it;
 
 do_time_wait:
-	inet_twsk_put((struct inet_timewait_sock *)sk);
+	inet_twsk_put(inet_twsk(sk));
 	goto no_dccp_socket;
 }
 
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 70e0273..3456cd3 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1178,8 +1178,10 @@
 	if (peer) {
 		if ((sock->state != SS_CONNECTED && 
 		     sock->state != SS_CONNECTING) && 
-		    scp->accept_mode == ACC_IMMED)
+		    scp->accept_mode == ACC_IMMED) {
+		    	release_sock(sk);
 			return -ENOTCONN;
+		}
 
 		memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn));
 	} else {
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index dd0761e..23489f7 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -267,9 +267,14 @@
 
 static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
 {
-	return memcmp(&fl1->nl_u.dn_u, &fl2->nl_u.dn_u, sizeof(fl1->nl_u.dn_u)) == 0 &&
-		fl1->oif == fl2->oif &&
-		fl1->iif == fl2->iif;
+	return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) |
+		(fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) |
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+		(fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) |
+#endif
+		(fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) |
+		(fl1->oif ^ fl2->oif) |
+		(fl1->iif ^ fl2->iif)) == 0;
 }
 
 static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
@@ -1270,7 +1275,6 @@
 			goto e_inval;
 
 		res.type = RTN_LOCAL;
-		flags |= RTCF_DIRECTSRC;
 	} else {
 		__le16 src_map = fl.fld_src;
 		free_res = 1;
@@ -1341,7 +1345,7 @@
 			goto make_route;
 
 		/* Packet was intra-ethernet, so we know its on-link */
-		if (cb->rt_flags | DN_RT_F_IE) {
+		if (cb->rt_flags & DN_RT_F_IE) {
 			gateway = cb->src;
 			flags |= RTCF_DIRECTSRC;
 			goto make_route;
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 589f6d2..cf51c87 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -48,7 +48,7 @@
 	dprintk(KERN_INFO PFX "sent association request!\n");
 
 	spin_lock_irqsave(&mac->lock, flags);
-	mac->associated = 0; /* just to make sure */
+	mac->associnfo.associated = 0; /* just to make sure */
 
 	/* Set a timer for timeout */
 	/* FIXME: make timeout configurable */
@@ -62,24 +62,22 @@
 {
 	struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
 	struct ieee80211softmac_network *n;
-	unsigned long flags;
 
-	spin_lock_irqsave(&mac->lock, flags);
+	mutex_lock(&mac->associnfo.mutex);
 	/* we might race against ieee80211softmac_handle_assoc_response,
 	 * so make sure only one of us does something */
-	if (!mac->associnfo.associating) {
-		spin_unlock_irqrestore(&mac->lock, flags);
-		return;
-	}
+	if (!mac->associnfo.associating)
+		goto out;
 	mac->associnfo.associating = 0;
 	mac->associnfo.bssvalid = 0;
-	mac->associated = 0;
+	mac->associnfo.associated = 0;
 
 	n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
-	spin_unlock_irqrestore(&mac->lock, flags);
 
 	dprintk(KERN_INFO PFX "assoc request timed out!\n");
 	ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
+out:
+	mutex_unlock(&mac->associnfo.mutex);
 }
 
 void
@@ -93,7 +91,7 @@
 
 	netif_carrier_off(mac->dev);
 
-	mac->associated = 0;
+	mac->associnfo.associated = 0;
 	mac->associnfo.bssvalid = 0;
 	mac->associnfo.associating = 0;
 	ieee80211softmac_init_bss(mac);
@@ -107,7 +105,7 @@
 {
 	struct ieee80211softmac_network *found;
 
-	if (mac->associnfo.bssvalid && mac->associated) {
+	if (mac->associnfo.bssvalid && mac->associnfo.associated) {
 		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
 		if (found)
 			ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
@@ -196,17 +194,18 @@
 	int bssvalid;
 	unsigned long flags;
 
+	mutex_lock(&mac->associnfo.mutex);
+
+	if (!mac->associnfo.associating)
+		goto out;
+
 	/* ieee80211_disassoc might clear this */
 	bssvalid = mac->associnfo.bssvalid;
 
 	/* meh */
-	if (mac->associated)
+	if (mac->associnfo.associated)
 		ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
 
-	spin_lock_irqsave(&mac->lock, flags);
-	mac->associnfo.associating = 1;
-	spin_unlock_irqrestore(&mac->lock, flags);
-
 	/* try to find the requested network in our list, if we found one already */
 	if (bssvalid || mac->associnfo.bssfixed)
 		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);	
@@ -260,10 +259,8 @@
 
 	if (!found) {
 		if (mac->associnfo.scan_retry > 0) {
-			spin_lock_irqsave(&mac->lock, flags);
 			mac->associnfo.scan_retry--;
-			spin_unlock_irqrestore(&mac->lock, flags);
-		
+
 			/* We know of no such network. Let's scan. 
 			 * NB: this also happens if we had no memory to copy the network info...
 			 * Maybe we can hope to have more memory after scanning finishes ;)
@@ -272,19 +269,17 @@
 			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
 			if (ieee80211softmac_start_scan(mac))
 				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
-			return;
+			goto out;
 		} else {
-			spin_lock_irqsave(&mac->lock, flags);
 			mac->associnfo.associating = 0;
-			mac->associated = 0;
-			spin_unlock_irqrestore(&mac->lock, flags);
+			mac->associnfo.associated = 0;
 
 			dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
 			/* reset the retry counter for the next user request since we
 			 * break out and don't reschedule ourselves after this point. */
 			mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
 			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
-			return;
+			goto out;
 		}
 	}
 
@@ -297,7 +292,7 @@
 	/* copy the ESSID for displaying it */
 	mac->associnfo.associate_essid.len = found->essid.len;
 	memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
-	
+
 	/* we found a network! authenticate (if necessary) and associate to it. */
 	if (found->authenticating) {
 		dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
@@ -305,7 +300,7 @@
 			mac->associnfo.assoc_wait = 1;
 			ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
 		}
-		return;
+		goto out;
 	}
 	if (!found->authenticated && !found->authenticating) {
 		/* This relies on the fact that _auth_req only queues the work,
@@ -321,11 +316,14 @@
 			mac->associnfo.assoc_wait = 0;
 			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
 		}
-		return;
+		goto out;
 	}
 	/* finally! now we can start associating */
 	mac->associnfo.assoc_wait = 0;
 	ieee80211softmac_assoc(mac, found);
+
+out:
+	mutex_unlock(&mac->associnfo.mutex);
 }
 
 /* call this to do whatever is necessary when we're associated */
@@ -341,7 +339,7 @@
 	mac->bssinfo.supported_rates = net->supported_rates;
 	ieee80211softmac_recalc_txrates(mac);
 
-	mac->associated = 1;
+	mac->associnfo.associated = 1;
 
 	mac->associnfo.short_preamble_available =
 		(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
@@ -421,7 +419,7 @@
 			dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
 			mac->associnfo.associating = 0;
 			mac->associnfo.bssvalid = 0;
-			mac->associated = 0;
+			mac->associnfo.associated = 0;
 			ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
 	}
 	
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index 82bfddb..b969310 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -304,7 +304,7 @@
 		2 +		/* Auth Transaction Seq */
 		2 +		/* Status Code */
 		 /* Challenge Text IE */
-		is_shared_response ? 0 : 1 + 1 + net->challenge_len
+		(is_shared_response ? 1 + 1 + net->challenge_len : 0)
 	);
 	if (unlikely((*pkt) == NULL))
 		return 0;
@@ -475,8 +475,13 @@
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 
-	if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
-		ieee80211softmac_process_erp(mac, network->erp_value);
+	/* This might race, but we don't really care and it's not worth
+	 * adding heavyweight locking in this fastpath.
+	 */
+	if (mac->associnfo.associated) {
+		if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
+			ieee80211softmac_process_erp(mac, network->erp_value);
+	}
 
 	return 0;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index addea1c..33aff4f 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -57,6 +57,7 @@
 	INIT_LIST_HEAD(&softmac->network_list);
 	INIT_LIST_HEAD(&softmac->events);
 
+	mutex_init(&softmac->associnfo.mutex);
 	INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac);
 	INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac);
 	softmac->start_scan = ieee80211softmac_start_scan_implementation;
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 2aa779d..23068a8 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -73,13 +73,14 @@
 	struct ieee80211softmac_network *n;
 	struct ieee80211softmac_auth_queue_item *authptr;
 	int length = 0;
-	unsigned long flags;
+
+	mutex_lock(&sm->associnfo.mutex);
 
 	/* Check if we're already associating to this or another network
 	 * If it's another network, cancel and start over with our new network
 	 * If it's our network, ignore the change, we're already doing it!
 	 */
-	if((sm->associnfo.associating || sm->associated) &&
+	if((sm->associnfo.associating || sm->associnfo.associated) &&
 	   (data->essid.flags && data->essid.length)) {
 		/* Get the associating network */
 		n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
@@ -87,10 +88,9 @@
 		   !memcmp(n->essid.data, extra, n->essid.len)) {
 			dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
 				MAC_ARG(sm->associnfo.bssid));
-			return 0;
+			goto out;
 		} else {
 			dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
-			spin_lock_irqsave(&sm->lock,flags);
 			/* Cancel assoc work */
 			cancel_delayed_work(&sm->associnfo.work);
 			/* We don't have to do this, but it's a little cleaner */
@@ -98,14 +98,13 @@
 				cancel_delayed_work(&authptr->work);
 			sm->associnfo.bssvalid = 0;
 			sm->associnfo.bssfixed = 0;
-			spin_unlock_irqrestore(&sm->lock,flags);
 			flush_scheduled_work();
+			sm->associnfo.associating = 0;
+			sm->associnfo.associated = 0;
 		}
 	}
 
 
-	spin_lock_irqsave(&sm->lock, flags);
-
 	sm->associnfo.static_essid = 0;
 	sm->associnfo.assoc_wait = 0;
 
@@ -121,10 +120,12 @@
 	 * If applicable, we have already copied the data in */
 	sm->associnfo.req_essid.len = length;
 
+	sm->associnfo.associating = 1;
 	/* queue lower level code to do work (if necessary) */
 	schedule_work(&sm->associnfo.work);
+out:
+	mutex_unlock(&sm->associnfo.mutex);
 
-	spin_unlock_irqrestore(&sm->lock, flags);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
@@ -136,10 +137,8 @@
 			      char *extra)
 {
 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
-	unsigned long flags;
 
-	/* avoid getting inconsistent information */
-	spin_lock_irqsave(&sm->lock, flags);
+	mutex_lock(&sm->associnfo.mutex);
 	/* If all fails, return ANY (empty) */
 	data->essid.length = 0;
 	data->essid.flags = 0;  /* active */
@@ -152,12 +151,13 @@
 	}
 	
 	/* If we're associating/associated, return that */
-	if (sm->associated || sm->associnfo.associating) {
+	if (sm->associnfo.associated || sm->associnfo.associating) {
 		data->essid.length = sm->associnfo.associate_essid.len;
 		data->essid.flags = 1;  /* active */
 		memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
 	}
-	spin_unlock_irqrestore(&sm->lock, flags);
+	mutex_unlock(&sm->associnfo.mutex);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
@@ -322,15 +322,15 @@
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
 	int err = 0;
-	unsigned long flags;
 
-	spin_lock_irqsave(&mac->lock, flags);
+	mutex_lock(&mac->associnfo.mutex);
 	if (mac->associnfo.bssvalid)
 		memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
 	else
 		memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
 	data->ap_addr.sa_family = ARPHRD_ETHER;
-	spin_unlock_irqrestore(&mac->lock, flags);
+	mutex_unlock(&mac->associnfo.mutex);
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
@@ -342,28 +342,27 @@
 			    char *extra)
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
-	unsigned long flags;
 
 	/* sanity check */
 	if (data->ap_addr.sa_family != ARPHRD_ETHER) {
 		return -EINVAL;
 	}
 
-	spin_lock_irqsave(&mac->lock, flags);
+	mutex_lock(&mac->associnfo.mutex);
 	if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
 		/* the bssid we have is not to be fixed any longer,
 		 * and we should reassociate to the best AP. */
 		mac->associnfo.bssfixed = 0;
 		/* force reassociation */
 		mac->associnfo.bssvalid = 0;
-		if (mac->associated)
+		if (mac->associnfo.associated)
 			schedule_work(&mac->associnfo.work);
 	} else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
 		/* the bssid we have is no longer fixed */
 		mac->associnfo.bssfixed = 0;
         } else {
 		if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
-			if (mac->associnfo.associating || mac->associated) {
+			if (mac->associnfo.associating || mac->associnfo.associated) {
 			/* bssid unchanged and associated or associating - just return */
 				goto out;
 			}
@@ -378,7 +377,8 @@
         }
 
  out:
-	spin_unlock_irqrestore(&mac->lock, flags);
+	mutex_unlock(&mac->associnfo.mutex);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
@@ -394,7 +394,8 @@
 	int err = 0;
 	char *buf;
 	int i;
-	
+
+	mutex_lock(&mac->associnfo.mutex);
 	spin_lock_irqsave(&mac->lock, flags);
 	/* bleh. shouldn't be locked for that kmalloc... */
 
@@ -432,6 +433,8 @@
 
  out:	
 	spin_unlock_irqrestore(&mac->lock, flags);
+	mutex_unlock(&mac->associnfo.mutex);
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
@@ -446,7 +449,8 @@
 	unsigned long flags;
 	int err = 0;
 	int space = wrqu->data.length;
-	
+
+	mutex_lock(&mac->associnfo.mutex);
 	spin_lock_irqsave(&mac->lock, flags);
 	
 	wrqu->data.length = 0;
@@ -459,6 +463,8 @@
 			err = -E2BIG;
 	}
 	spin_unlock_irqrestore(&mac->lock, flags);
+	mutex_lock(&mac->associnfo.mutex);
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
@@ -473,10 +479,13 @@
 	struct iw_mlme *mlme = (struct iw_mlme *)extra;
 	u16 reason = cpu_to_le16(mlme->reason_code);
 	struct ieee80211softmac_network *net;
+	int err = -EINVAL;
+
+	mutex_lock(&mac->associnfo.mutex);
 
 	if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
 		printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
-		return -EINVAL;
+		goto out;
 	}
 
 	switch (mlme->cmd) {
@@ -484,14 +493,22 @@
 		net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
 		if (!net) {
 			printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
-			return -EINVAL;
+			goto out;
 		}
 		return ieee80211softmac_deauth_req(mac, net, reason);
 	case IW_MLME_DISASSOC:
 		ieee80211softmac_send_disassoc_req(mac, reason);
-		return 0;
+		mac->associnfo.associated = 0;
+		mac->associnfo.associating = 0;
+		err = 0;
+		goto out;
 	default:
-		return -EOPNOTSUPP;
+		err = -EOPNOTSUPP;
 	}
+
+out:
+	mutex_unlock(&mac->associnfo.mutex);
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index a8e2e87..e2077a3 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -43,6 +43,7 @@
 #include <net/tcp.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
+#include <asm/atomic.h>
 #include <asm/bug.h>
 
 struct cipso_v4_domhsh_entry {
@@ -79,7 +80,7 @@
 	unsigned char *key;
 	size_t key_len;
 
-	struct netlbl_lsm_cache lsm_data;
+	struct netlbl_lsm_cache *lsm_data;
 
 	u32 activity;
 	struct list_head list;
@@ -188,13 +189,14 @@
  * @entry: the entry to free
  *
  * Description:
- * This function frees the memory associated with a cache entry.
+ * This function frees the memory associated with a cache entry including the
+ * LSM cache data if there are no longer any users, i.e. reference count == 0.
  *
  */
 static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
 {
-	if (entry->lsm_data.free)
-		entry->lsm_data.free(entry->lsm_data.data);
+	if (entry->lsm_data)
+		netlbl_secattr_cache_free(entry->lsm_data);
 	kfree(entry->key);
 	kfree(entry);
 }
@@ -315,8 +317,8 @@
 		    entry->key_len == key_len &&
 		    memcmp(entry->key, key, key_len) == 0) {
 			entry->activity += 1;
-			secattr->cache.free = entry->lsm_data.free;
-			secattr->cache.data = entry->lsm_data.data;
+			atomic_inc(&entry->lsm_data->refcount);
+			secattr->cache = entry->lsm_data;
 			if (prev_entry == NULL) {
 				spin_unlock_bh(&cipso_v4_cache[bkt].lock);
 				return 0;
@@ -383,8 +385,8 @@
 	memcpy(entry->key, cipso_ptr, cipso_ptr_len);
 	entry->key_len = cipso_ptr_len;
 	entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
-	entry->lsm_data.free = secattr->cache.free;
-	entry->lsm_data.data = secattr->cache.data;
+	atomic_inc(&secattr->cache->refcount);
+	entry->lsm_data = secattr->cache;
 
 	bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
 	spin_lock_bh(&cipso_v4_cache[bkt].lock);
@@ -771,13 +773,15 @@
 {
 	int cat = -1;
 	u32 bitmap_len_bits = bitmap_len * 8;
-	u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
-	u32 *cipso_array = doi_def->map.std->cat.cipso;
+	u32 cipso_cat_size;
+	u32 *cipso_array;
 
 	switch (doi_def->type) {
 	case CIPSO_V4_MAP_PASS:
 		return 0;
 	case CIPSO_V4_MAP_STD:
+		cipso_cat_size = doi_def->map.std->cat.cipso_size;
+		cipso_array = doi_def->map.std->cat.cipso;
 		for (;;) {
 			cat = cipso_v4_bitmap_walk(bitmap,
 						   bitmap_len_bits,
@@ -823,19 +827,21 @@
 	u32 net_spot_max = 0;
 	u32 host_clen_bits = host_cat_len * 8;
 	u32 net_clen_bits = net_cat_len * 8;
-	u32 host_cat_size = doi_def->map.std->cat.local_size;
-	u32 *host_cat_array = doi_def->map.std->cat.local;
+	u32 host_cat_size;
+	u32 *host_cat_array;
 
 	switch (doi_def->type) {
 	case CIPSO_V4_MAP_PASS:
-		net_spot_max = host_cat_len - 1;
-		while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
+		net_spot_max = host_cat_len;
+		while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0)
 			net_spot_max--;
 		if (net_spot_max > net_cat_len)
 			return -EINVAL;
 		memcpy(net_cat, host_cat, net_spot_max);
 		return net_spot_max;
 	case CIPSO_V4_MAP_STD:
+		host_cat_size = doi_def->map.std->cat.local_size;
+		host_cat_array = doi_def->map.std->cat.local;
 		for (;;) {
 			host_spot = cipso_v4_bitmap_walk(host_cat,
 							 host_clen_bits,
@@ -891,8 +897,8 @@
 	int net_spot = -1;
 	u32 net_clen_bits = net_cat_len * 8;
 	u32 host_clen_bits = host_cat_len * 8;
-	u32 net_cat_size = doi_def->map.std->cat.cipso_size;
-	u32 *net_cat_array = doi_def->map.std->cat.cipso;
+	u32 net_cat_size;
+	u32 *net_cat_array;
 
 	switch (doi_def->type) {
 	case CIPSO_V4_MAP_PASS:
@@ -901,6 +907,8 @@
 		memcpy(host_cat, net_cat, net_cat_len);
 		return net_cat_len;
 	case CIPSO_V4_MAP_STD:
+		net_cat_size = doi_def->map.std->cat.cipso_size;
+		net_cat_array = doi_def->map.std->cat.cipso;
 		for (;;) {
 			net_spot = cipso_v4_bitmap_walk(net_cat,
 							net_clen_bits,
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 9c399a7..af0190d 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -482,9 +482,7 @@
 	memset(cfg, 0, sizeof(*cfg));
 
 	rtm = nlmsg_data(nlh);
-	cfg->fc_family = rtm->rtm_family;
 	cfg->fc_dst_len = rtm->rtm_dst_len;
-	cfg->fc_src_len = rtm->rtm_src_len;
 	cfg->fc_tos = rtm->rtm_tos;
 	cfg->fc_table = rtm->rtm_table;
 	cfg->fc_protocol = rtm->rtm_protocol;
@@ -501,9 +499,6 @@
 		case RTA_DST:
 			cfg->fc_dst = nla_get_be32(attr);
 			break;
-		case RTA_SRC:
-			cfg->fc_src = nla_get_be32(attr);
-			break;
 		case RTA_OIF:
 			cfg->fc_oif = nla_get_u32(attr);
 			break;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 2b1a54b..f072f38 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -94,10 +94,8 @@
 int inet_peer_maxttl = 10 * 60 * HZ;	/* usual time to live: 10 min */
 
 static struct inet_peer *inet_peer_unused_head;
-/* Exported for inet_putpeer inline function.  */
-struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
-DEFINE_SPINLOCK(inet_peer_unused_lock);
-#define PEER_MAX_CLEANUP_WORK 30
+static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
+static DEFINE_SPINLOCK(inet_peer_unused_lock);
 
 static void peer_check_expire(unsigned long dummy);
 static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
@@ -340,7 +338,8 @@
 	spin_lock_bh(&inet_peer_unused_lock);
 	p = inet_peer_unused_head;
 	if (p != NULL) {
-		if (time_after(p->dtime + ttl, jiffies)) {
+		__u32 delta = (__u32)jiffies - p->dtime;
+		if (delta < ttl) {
 			/* Do not prune fresh entries. */
 			spin_unlock_bh(&inet_peer_unused_lock);
 			return -1;
@@ -432,7 +431,7 @@
 /* Called with local BH disabled. */
 static void peer_check_expire(unsigned long dummy)
 {
-	int i;
+	unsigned long now = jiffies;
 	int ttl;
 
 	if (peer_total >= inet_peer_threshold)
@@ -441,7 +440,10 @@
 		ttl = inet_peer_maxttl
 				- (inet_peer_maxttl - inet_peer_minttl) / HZ *
 					peer_total / inet_peer_threshold * HZ;
-	for (i = 0; i < PEER_MAX_CLEANUP_WORK && !cleanup_once(ttl); i++);
+	while (!cleanup_once(ttl)) {
+		if (jiffies != now)
+			break;
+	}
 
 	/* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
 	 * interval depending on the total number of entries (more entries,
@@ -455,3 +457,16 @@
 				peer_total / inet_peer_threshold * HZ;
 	add_timer(&peer_periodic_timer);
 }
+
+void inet_putpeer(struct inet_peer *p)
+{
+	spin_lock_bh(&inet_peer_unused_lock);
+	if (atomic_dec_and_test(&p->refcnt)) {
+		p->unused_prevp = inet_peer_unused_tailp;
+		p->unused_next = NULL;
+		*inet_peer_unused_tailp = p;
+		inet_peer_unused_tailp = &p->unused_next;
+		p->dtime = (__u32)jiffies;
+	}
+	spin_unlock_bh(&inet_peer_unused_lock);
+}
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f5fba05..d5b5dec 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -611,8 +611,8 @@
 		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
 		 */
 		if (flags == 0 &&
-		    skb->protocol == __constant_htons(ETH_P_WCCP)) {
-			skb->protocol = __constant_htons(ETH_P_IP);
+		    skb->protocol == htons(ETH_P_WCCP)) {
+			skb->protocol = htons(ETH_P_IP);
 			if ((*(h + offset) & 0xF0) != 0x40) 
 				offset += 4;
 		}
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index e433cb0..6d398f1 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -274,7 +274,7 @@
 	while (data <= data_limit - 6) {
 		if (strnicmp(data, "PASV\r\n", 6) == 0) {
 			/* Passive mode on */
-			IP_VS_DBG(7, "got PASV at %zd of %zd\n",
+			IP_VS_DBG(7, "got PASV at %td of %td\n",
 				  data - data_start,
 				  data_limit - data_start);
 			cp->app_data = &ip_vs_ftp_pasv;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 17e1a68..0849f1c 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1196,6 +1196,8 @@
 static void __exit arp_tables_fini(void)
 {
 	nf_unregister_sockopt(&arpt_sockopts);
+	xt_unregister_target(&arpt_error_target);
+	xt_unregister_target(&arpt_standard_target);
 	xt_proto_fini(NF_ARP);
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 53b6dff..262d0d4 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -44,13 +44,6 @@
 
 static char __initdata version[] = "0.90";
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-
 static inline int
 ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
 			    const struct ip_conntrack_tuple *tuple,
@@ -398,7 +391,6 @@
 
 static int ctnetlink_done(struct netlink_callback *cb)
 {
-	DEBUGP("entered %s\n", __FUNCTION__);
 	if (cb->args[1])
 		ip_conntrack_put((struct ip_conntrack *)cb->args[1]);
 	return 0;
@@ -411,9 +403,6 @@
 	struct ip_conntrack_tuple_hash *h;
 	struct list_head *i;
 
-	DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, 
-			cb->args[0], *id);
-
 	read_lock_bh(&ip_conntrack_lock);
 	last = (struct ip_conntrack *)cb->args[1];
 	for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
@@ -452,7 +441,6 @@
 	if (last)
 		ip_conntrack_put(last);
 
-	DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
 	return skb->len;
 }
 
@@ -466,8 +454,6 @@
 {
 	struct nfattr *tb[CTA_IP_MAX];
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_IP_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
@@ -481,8 +467,6 @@
 		return -EINVAL;
 	tuple->dst.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
 
-	DEBUGP("leaving\n");
-
 	return 0;
 }
 
@@ -503,8 +487,6 @@
 	struct ip_conntrack_protocol *proto;
 	int ret = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
@@ -531,8 +513,6 @@
 	struct nfattr *tb[CTA_TUPLE_MAX];
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	memset(tuple, 0, sizeof(*tuple));
 
 	nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
@@ -557,10 +537,6 @@
 	else
 		tuple->dst.dir = IP_CT_DIR_ORIGINAL;
 
-	DUMP_TUPLE(tuple);
-
-	DEBUGP("leaving\n");
-
 	return 0;
 }
 
@@ -577,8 +553,6 @@
 	struct nfattr *tb[CTA_PROTONAT_MAX];
 	struct ip_nat_protocol *npt;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
@@ -597,7 +571,6 @@
 
 	ip_nat_proto_put(npt);
 
-	DEBUGP("leaving\n");
 	return 0;
 }
 
@@ -613,8 +586,6 @@
 	struct nfattr *tb[CTA_NAT_MAX];
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	memset(range, 0, sizeof(*range));
 	
 	nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
@@ -640,7 +611,6 @@
 	if (err < 0)
 		return err;
 
-	DEBUGP("leaving\n");
 	return 0;
 }
 #endif
@@ -650,8 +620,6 @@
 {
 	struct nfattr *tb[CTA_HELP_MAX];
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
 
 	if (!tb[CTA_HELP_NAME-1])
@@ -679,8 +647,6 @@
 	struct ip_conntrack *ct;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nfattr_bad_size(cda, CTA_MAX, cta_min))
 		return -EINVAL;
 
@@ -698,10 +664,8 @@
 		return err;
 
 	h = ip_conntrack_find_get(&tuple, NULL);
-	if (!h) {
-		DEBUGP("tuple not found in conntrack hash\n");
+	if (!h)
 		return -ENOENT;
-	}
 
 	ct = tuplehash_to_ctrack(h);
 	
@@ -716,7 +680,6 @@
 		ct->timeout.function((unsigned long)ct);
 
 	ip_conntrack_put(ct);
-	DEBUGP("leaving\n");
 
 	return 0;
 }
@@ -731,8 +694,6 @@
 	struct sk_buff *skb2 = NULL;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct nfgenmsg *msg = NLMSG_DATA(nlh);
 		u32 rlen;
@@ -770,11 +731,9 @@
 		return err;
 
 	h = ip_conntrack_find_get(&tuple, NULL);
-	if (!h) {
-		DEBUGP("tuple not found in conntrack hash");
+	if (!h)
 		return -ENOENT;
-	}
-	DEBUGP("tuple found\n");
+
 	ct = tuplehash_to_ctrack(h);
 
 	err = -ENOMEM;
@@ -795,7 +754,6 @@
 	if (err < 0)
 		goto out;
 
-	DEBUGP("leaving\n");
 	return 0;
 
 free:
@@ -866,8 +824,6 @@
 	char *helpname;
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	/* don't change helper of sibling connections */
 	if (ct->master)
 		return -EINVAL;
@@ -938,8 +894,6 @@
 {
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (cda[CTA_HELP-1]) {
 		err = ctnetlink_change_helper(ct, cda);
 		if (err < 0)
@@ -969,7 +923,6 @@
 		ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
-	DEBUGP("all done\n");
 	return 0;
 }
 
@@ -981,8 +934,6 @@
 	struct ip_conntrack *ct;
 	int err = -EINVAL;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	ct = ip_conntrack_alloc(otuple, rtuple);
 	if (ct == NULL || IS_ERR(ct))
 		return -ENOMEM;	
@@ -1017,7 +968,6 @@
 	if (ct->helper)
 		ip_conntrack_helper_put(ct->helper);
 
-	DEBUGP("conntrack with id %u inserted\n", ct->id);
 	return 0;
 
 err:	
@@ -1033,8 +983,6 @@
 	struct ip_conntrack_tuple_hash *h = NULL;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nfattr_bad_size(cda, CTA_MAX, cta_min))
 		return -EINVAL;
 
@@ -1058,7 +1006,6 @@
 
 	if (h == NULL) {
 		write_unlock_bh(&ip_conntrack_lock);
-		DEBUGP("no such conntrack, create new\n");
 		err = -ENOENT;
 		if (nlh->nlmsg_flags & NLM_F_CREATE)
 			err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
@@ -1074,7 +1021,6 @@
 
 	/* We manipulate the conntrack inside the global conntrack table lock,
 	 * so there's no need to increase the refcount */
-	DEBUGP("conntrack found\n");
 	err = -EEXIST;
 	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
 		err = ctnetlink_change_conntrack(tuplehash_to_ctrack(h), cda);
@@ -1249,8 +1195,6 @@
 	struct list_head *i;
 	u_int32_t *id = (u_int32_t *) &cb->args[0];
 
-	DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
-
 	read_lock_bh(&ip_conntrack_lock);
 	list_for_each_prev(i, &ip_conntrack_expect_list) {
 		exp = (struct ip_conntrack_expect *) i;
@@ -1266,8 +1210,6 @@
 out:	
 	read_unlock_bh(&ip_conntrack_lock);
 
-	DEBUGP("leaving, last id=%llu\n", *id);
-
 	return skb->len;
 }
 
@@ -1285,8 +1227,6 @@
 	struct sk_buff *skb2;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
 		return -EINVAL;
 
@@ -1437,8 +1377,6 @@
 	struct ip_conntrack *ct;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	/* caller guarantees that those three CTA_EXPECT_* exist */
 	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
 	if (err < 0)
@@ -1490,8 +1428,6 @@
 	struct ip_conntrack_expect *exp;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);	
-
 	if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
 		return -EINVAL;
 
@@ -1520,8 +1456,6 @@
 		err = ctnetlink_change_expect(exp, cda);
 	write_unlock_bh(&ip_conntrack_lock);
 
-	DEBUGP("leaving\n");
-	
 	return err;
 }
 
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 78a44b0..4b90927 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1932,6 +1932,9 @@
 {
 	int ret;
 
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
 	switch (cmd) {
 	case IPT_SO_GET_INFO:
 		ret = get_info(user, len, 1);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 12a818a..1aa4517 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -28,7 +28,7 @@
 set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
-	__be16 oldtos;
+	u_int16_t oldtos;
 
 	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
 		if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -37,8 +37,8 @@
 		oldtos = iph->tos;
 		iph->tos &= ~IPT_ECN_IP_MASK;
 		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
-		iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
-					    iph->check);
+		iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF),
+					    htons(iph->tos), iph->check);
 	} 
 	return 1;
 }
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 6b8b14c..83b80b3 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -30,7 +30,7 @@
 {
 	const struct ipt_tos_target_info *tosinfo = targinfo;
 	struct iphdr *iph = (*pskb)->nh.iph;
-	__be16 oldtos;
+	u_int16_t oldtos;
 
 	if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
 		if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -38,8 +38,8 @@
 		iph = (*pskb)->nh.iph;
 		oldtos = iph->tos;
 		iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
-		iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
-					    iph->check);
+		iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF),
+					    htons(iph->tos), iph->check);
 	}
 	return IPT_CONTINUE;
 }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index c41ddba..925ee4d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -566,9 +566,15 @@
 
 static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
 {
-	return memcmp(&fl1->nl_u.ip4_u, &fl2->nl_u.ip4_u, sizeof(fl1->nl_u.ip4_u)) == 0 &&
-	       fl1->oif     == fl2->oif &&
-	       fl1->iif     == fl2->iif;
+	return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
+		(fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) |
+#ifdef CONFIG_IP_ROUTE_FWMARK
+		(fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) |
+#endif
+		(*(u16 *)&fl1->nl_u.ip4_u.tos ^
+		 *(u16 *)&fl2->nl_u.ip4_u.tos) |
+		(fl1->oif ^ fl2->oif) |
+		(fl1->iif ^ fl2->iif)) == 0;
 }
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c83938b..22ef8bd 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -355,7 +355,7 @@
 		return;
 	}
 	if (sk->sk_state == TCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -373,7 +373,7 @@
 	seq = ntohl(th->seq);
 	if (sk->sk_state != TCP_LISTEN &&
 	    !between(seq, tp->snd_una, tp->snd_nxt)) {
-		NET_INC_STATS(LINUX_MIB_OUTOFWINDOWICMPS);
+		NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
 		goto out;
 	}
 
@@ -578,7 +578,7 @@
 	struct tcphdr *th = skb->h.th;
 	struct {
 		struct tcphdr th;
-		u32 tsopt[3];
+		u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2];
 	} rep;
 	struct ip_reply_arg arg;
 
@@ -960,7 +960,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -1154,26 +1154,24 @@
 
 do_time_wait:
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-		inet_twsk_put((struct inet_timewait_sock *) sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
 
 	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TCP_MIB_INERRS);
-		inet_twsk_put((struct inet_timewait_sock *) sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
-	switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
-					   skb, th)) {
+	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
 	case TCP_TW_SYN: {
 		struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
 							skb->nh.iph->daddr,
 							th->dest,
 							inet_iif(skb));
 		if (sk2) {
-			inet_twsk_deschedule((struct inet_timewait_sock *)sk,
-					     &tcp_death_row);
-			inet_twsk_put((struct inet_timewait_sock *)sk);
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
 			sk = sk2;
 			goto process;
 		}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9a253fa..ca40615 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -273,10 +273,10 @@
 					 __u32 tstamp)
 {
 	if (tp->rx_opt.tstamp_ok) {
-		*ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
-					  (TCPOPT_NOP << 16) |
-					  (TCPOPT_TIMESTAMP << 8) |
-					  TCPOLEN_TIMESTAMP);
+		*ptr++ = htonl((TCPOPT_NOP << 24) |
+			       (TCPOPT_NOP << 16) |
+			       (TCPOPT_TIMESTAMP << 8) |
+			       TCPOLEN_TIMESTAMP);
 		*ptr++ = htonl(tstamp);
 		*ptr++ = htonl(tp->rx_opt.ts_recent);
 	}
@@ -325,18 +325,27 @@
 	*ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
 	if (ts) {
 		if(sack)
-			*ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
-						  (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+			*ptr++ = htonl((TCPOPT_SACK_PERM << 24) |
+				       (TCPOLEN_SACK_PERM << 16) |
+				       (TCPOPT_TIMESTAMP << 8) |
+				       TCPOLEN_TIMESTAMP);
 		else
-			*ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
-						  (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+			*ptr++ = htonl((TCPOPT_NOP << 24) |
+				       (TCPOPT_NOP << 16) |
+				       (TCPOPT_TIMESTAMP << 8) |
+				       TCPOLEN_TIMESTAMP);
 		*ptr++ = htonl(tstamp);		/* TSVAL */
 		*ptr++ = htonl(ts_recent);	/* TSECR */
 	} else if(sack)
-		*ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
-					  (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+		*ptr++ = htonl((TCPOPT_NOP << 24) |
+			       (TCPOPT_NOP << 16) |
+			       (TCPOPT_SACK_PERM << 8) |
+			       TCPOLEN_SACK_PERM);
 	if (offer_wscale)
-		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+		*ptr++ = htonl((TCPOPT_NOP << 24) |
+			       (TCPOPT_WINDOW << 16) |
+			       (TCPOLEN_WINDOW << 8) |
+			       (wscale));
 }
 
 /* This routine actually transmits TCP packets queued in by
@@ -1087,10 +1096,14 @@
 	u32 send_win, cong_win, limit, in_flight;
 
 	if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
-		return 0;
+		goto send_now;
 
 	if (icsk->icsk_ca_state != TCP_CA_Open)
-		return 0;
+		goto send_now;
+
+	/* Defer for less than two clock ticks. */
+	if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1)
+		goto send_now;
 
 	in_flight = tcp_packets_in_flight(tp);
 
@@ -1106,7 +1119,7 @@
 
 	/* If a full-sized TSO skb can be sent, do it. */
 	if (limit >= 65536)
-		return 0;
+		goto send_now;
 
 	if (sysctl_tcp_tso_win_divisor) {
 		u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
@@ -1116,7 +1129,7 @@
 		 */
 		chunk /= sysctl_tcp_tso_win_divisor;
 		if (limit >= chunk)
-			return 0;
+			goto send_now;
 	} else {
 		/* Different approach, try not to defer past a single
 		 * ACK.  Receiver should ACK every other full sized
@@ -1124,11 +1137,17 @@
 		 * then send now.
 		 */
 		if (limit > tcp_max_burst(tp) * tp->mss_cache)
-			return 0;
+			goto send_now;
 	}
 
 	/* Ok, it looks like it is advisable to defer.  */
+	tp->tso_deferred = 1 | (jiffies<<1);
+
 	return 1;
+
+send_now:
+	tp->tso_deferred = 0;
+	return 0;
 }
 
 /* Create a new MTU probe if we are ready.
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7a7a001..1bed0cd 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -52,7 +52,7 @@
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
 	    	    xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
-		    xfrm_bundle_ok(xdst, fl, AF_INET, 0)) {
+		    xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
 			dst_clone(dst);
 			break;
 		}
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index a460e81..6e48f52 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -153,6 +153,19 @@
 	---help---
 	  Support for MIPv6 route optimization mode.
 
+config IPV6_SIT
+	tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
+	depends on IPV6
+	default y
+	---help---
+	  Tunneling means encapsulating data of one protocol type within
+	  another protocol and sending it over a channel that understands the
+	  encapsulating protocol. This driver implements encapsulation of IPv6
+	  into IPv4 packets. This is useful if you want to connect two IPv6
+	  networks over an IPv4-only path.
+
+	  Saying M here will produce a module called sit.ko. If unsure, say Y.
+
 config IPV6_TUNNEL
 	tristate "IPv6: IPv6-in-IPv6 tunnel"
 	select INET6_TUNNEL
@@ -162,9 +175,16 @@
 
 	  If unsure, say N.
 
+config IPV6_MULTIPLE_TABLES
+	bool "IPv6: Multiple Routing Tables"
+	depends on IPV6 && EXPERIMENTAL
+	select FIB_RULES
+	---help---
+	  Support multiple routing tables.
+
 config IPV6_SUBTREES
 	bool "IPv6: source address based routing"
-	depends on IPV6 && EXPERIMENTAL
+	depends on IPV6_MULTIPLE_TABLES
 	---help---
 	  Enable routing by source address or prefix.
 
@@ -176,13 +196,6 @@
 
 	  If unsure, say N.
 
-config IPV6_MULTIPLE_TABLES
-	bool "IPv6: Multiple Routing Tables"
-	depends on IPV6 && EXPERIMENTAL
-	select FIB_RULES
-	---help---
-	  Support multiple routing tables.
-
 config IPV6_ROUTE_FWMARK
 	bool "IPv6: use netfilter MARK value as routing key"
 	depends on IPV6_MULTIPLE_TABLES && NETFILTER
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 87274e4..addcc01 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_IPV6) += ipv6.o
 
-ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
+ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
 		route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
 		protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
@@ -29,6 +29,7 @@
 obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
+obj-$(CONFIG_IPV6_SIT) += sit.o
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 
 obj-y += exthdrs_core.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e03c33b..b312a5f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -396,8 +396,10 @@
 	ndev->regen_timer.data = (unsigned long) ndev;
 	if ((dev->flags&IFF_LOOPBACK) ||
 	    dev->type == ARPHRD_TUNNEL ||
-	    dev->type == ARPHRD_NONE ||
-	    dev->type == ARPHRD_SIT) {
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+	    dev->type == ARPHRD_SIT ||
+#endif
+	    dev->type == ARPHRD_NONE) {
 		printk(KERN_INFO
 		       "%s: Disabled Privacy Extensions\n",
 		       dev->name);
@@ -1546,8 +1548,10 @@
 	   This thing is done here expecting that the whole
 	   class of non-broadcast devices need not cloning.
 	 */
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 	if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
 		cfg.fc_flags |= RTF_NONEXTHOP;
+#endif
 
 	ip6_route_add(&cfg);
 }
@@ -1569,6 +1573,7 @@
 	ip6_route_add(&cfg);
 }
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 static void sit_route_add(struct net_device *dev)
 {
 	struct fib6_config cfg = {
@@ -1582,6 +1587,7 @@
 	/* prefix length - 96 bits "::d.d.d.d" */
 	ip6_route_add(&cfg);
 }
+#endif
 
 static void addrconf_add_lroute(struct net_device *dev)
 {
@@ -1852,6 +1858,7 @@
 	if (dev == NULL)
 		goto err_exit;
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 	if (dev->type == ARPHRD_SIT) {
 		struct ifreq ifr;
 		mm_segment_t	oldfs;
@@ -1881,6 +1888,7 @@
 			err = dev_open(dev);
 		}
 	}
+#endif
 
 err_exit:
 	rtnl_unlock();
@@ -2010,6 +2018,7 @@
 	return err;
 }
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 static void sit_add_v4_addrs(struct inet6_dev *idev)
 {
 	struct inet6_ifaddr * ifp;
@@ -2078,6 +2087,7 @@
 		}
         }
 }
+#endif
 
 static void init_loopback(struct net_device *dev)
 {
@@ -2141,6 +2151,7 @@
 		addrconf_add_linklocal(idev, &addr);
 }
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 static void addrconf_sit_config(struct net_device *dev)
 {
 	struct inet6_dev *idev;
@@ -2166,6 +2177,7 @@
 	} else
 		sit_route_add(dev);
 }
+#endif
 
 static inline int
 ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
@@ -2260,9 +2272,11 @@
 		}
 
 		switch(dev->type) {
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 		case ARPHRD_SIT:
 			addrconf_sit_config(dev);
 			break;
+#endif
 		case ARPHRD_TUNNEL6:
 			addrconf_ip6_tnl_config(dev);
 			break;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e94eccb..858cae2 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -850,7 +850,6 @@
 	err = addrconf_init();
 	if (err)
 		goto addrconf_fail;
-	sit_init();
 
 	/* Init v6 extension headers. */
 	ipv6_rthdr_init();
@@ -927,7 +926,6 @@
 	mip6_fini();
 #endif
 	/* Cleanup code parts. */
-	sit_cleanup();
 	ip6_flowlabel_cleanup();
 	addrconf_cleanup();
 	ip6_route_cleanup();
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d8c1057..1896ecb 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -117,12 +117,15 @@
 {
 	struct fib6_rule *r = (struct fib6_rule *) rule;
 
-	if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
+	if (r->dst.plen &&
+	    !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
 		return 0;
 
-	if ((flags & RT6_LOOKUP_F_HAS_SADDR) &&
-	    !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
-		return 0;
+	if (r->src.plen) {
+		if (!(flags & RT6_LOOKUP_F_HAS_SADDR) ||
+		    !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
+			return 0;
+	}
 
 	if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
 		return 0;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 8fcae7a..f98ca30 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -169,7 +169,6 @@
 
 static struct fib6_table fib6_main_tbl = {
 	.tb6_id		= RT6_TABLE_MAIN,
-	.tb6_lock	= RW_LOCK_UNLOCKED,
 	.tb6_root	= {
 		.leaf		= &ip6_null_entry,
 		.fn_flags	= RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -187,6 +186,12 @@
 {
 	unsigned int h;
 
+	/*
+	 * Initialize table lock at a single place to give lockdep a key,
+	 * tables aren't visible prior to being linked to the list.
+	 */
+	rwlock_init(&tb->tb6_lock);
+
 	h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
 
 	/*
@@ -199,7 +204,6 @@
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 static struct fib6_table fib6_local_tbl = {
 	.tb6_id		= RT6_TABLE_LOCAL,
-	.tb6_lock	= RW_LOCK_UNLOCKED,
 	.tb6_root 	= {
 		.leaf		= &ip6_null_entry,
 		.fn_flags	= RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -213,7 +217,6 @@
 	table = kzalloc(sizeof(*table), GFP_ATOMIC);
 	if (table != NULL) {
 		table->tb6_id = id;
-		table->tb6_lock = RW_LOCK_UNLOCKED;
 		table->tb6_root.leaf = &ip6_null_entry;
 		table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 	}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0304b5f..41a8a5f 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -967,8 +967,6 @@
 		    ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
 		    pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
 			/* XXX: idev->cnf.prixy_ndp */
-			WARN_ON(skb->dst != NULL &&
-				((struct rt6_info *)skb->dst)->rt6i_idev);
 			goto out;
 		}
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d6b4b4f..c953466 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -141,6 +141,10 @@
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
+static int ip6_pkt_prohibit(struct sk_buff *skb);
+static int ip6_pkt_prohibit_out(struct sk_buff *skb);
+static int ip6_pkt_blk_hole(struct sk_buff *skb);
+
 struct rt6_info ip6_prohibit_entry = {
 	.u = {
 		.dst = {
@@ -150,8 +154,8 @@
 			.obsolete	= -1,
 			.error		= -EACCES,
 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
-			.input		= ip6_pkt_discard,
-			.output		= ip6_pkt_discard_out,
+			.input		= ip6_pkt_prohibit,
+			.output		= ip6_pkt_prohibit_out,
 			.ops		= &ip6_dst_ops,
 			.path		= (struct dst_entry*)&ip6_prohibit_entry,
 		}
@@ -170,8 +174,8 @@
 			.obsolete	= -1,
 			.error		= -EINVAL,
 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
-			.input		= ip6_pkt_discard,
-			.output		= ip6_pkt_discard_out,
+			.input		= ip6_pkt_blk_hole,
+			.output		= ip6_pkt_blk_hole,
 			.ops		= &ip6_dst_ops,
 			.path		= (struct dst_entry*)&ip6_blk_hole_entry,
 		}
@@ -484,7 +488,7 @@
 do { \
 	if (rt == &ip6_null_entry) { \
 		struct fib6_node *pn; \
-		while (fn) { \
+		while (1) { \
 			if (fn->fn_flags & RTN_TL_ROOT) \
 				goto out; \
 			pn = fn->parent; \
@@ -529,13 +533,17 @@
 		.nl_u = {
 			.ip6_u = {
 				.daddr = *daddr,
-				/* TODO: saddr */
 			},
 		},
 	};
 	struct dst_entry *dst;
 	int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
 
+	if (saddr) {
+		memcpy(&fl.fl6_src, saddr, sizeof(*saddr));
+		flags |= RT6_LOOKUP_F_HAS_SADDR;
+	}
+
 	dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
 	if (dst->error == 0)
 		return (struct rt6_info *) dst;
@@ -614,8 +622,6 @@
 		ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
 		rt->rt6i_dst.plen = 128;
 		rt->rt6i_flags |= RTF_CACHE;
-		if (rt->rt6i_flags & RTF_REJECT)
-			rt->u.dst.error = ort->u.dst.error;
 		rt->u.dst.flags |= DST_HOST;
 		rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
 	}
@@ -697,6 +703,7 @@
 void ip6_route_input(struct sk_buff *skb)
 {
 	struct ipv6hdr *iph = skb->nh.ipv6h;
+	int flags = RT6_LOOKUP_F_HAS_SADDR;
 	struct flowi fl = {
 		.iif = skb->dev->ifindex,
 		.nl_u = {
@@ -711,7 +718,9 @@
 		},
 		.proto = iph->nexthdr,
 	};
-	int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0;
+
+	if (rt6_need_strict(&iph->daddr))
+		flags |= RT6_LOOKUP_F_IFACE;
 
 	skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
 }
@@ -794,6 +803,9 @@
 	if (rt6_need_strict(&fl->fl6_dst))
 		flags |= RT6_LOOKUP_F_IFACE;
 
+	if (!ipv6_addr_any(&fl->fl6_src))
+		flags |= RT6_LOOKUP_F_HAS_SADDR;
+
 	return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
 }
 
@@ -1345,6 +1357,7 @@
 					   struct in6_addr *gateway,
 					   struct net_device *dev)
 {
+	int flags = RT6_LOOKUP_F_HAS_SADDR;
 	struct ip6rd_flowi rdfl = {
 		.fl = {
 			.oif = dev->ifindex,
@@ -1357,7 +1370,9 @@
 		},
 		.gateway = *gateway,
 	};
-	int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0;
+
+	if (rt6_need_strict(dest))
+		flags |= RT6_LOOKUP_F_IFACE;
 
 	return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
 }
@@ -1527,6 +1542,7 @@
 		rt->u.dst.output = ort->u.dst.output;
 
 		memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
+		rt->u.dst.error = ort->u.dst.error;
 		rt->u.dst.dev = ort->u.dst.dev;
 		if (rt->u.dst.dev)
 			dev_hold(rt->u.dst.dev);
@@ -1730,24 +1746,50 @@
  *	Drop the packet on the floor
  */
 
-static int ip6_pkt_discard(struct sk_buff *skb)
+static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
 {
 	int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
 	if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
 		IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
 
 	IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
-	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
+	icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
 	kfree_skb(skb);
 	return 0;
 }
 
+static int ip6_pkt_discard(struct sk_buff *skb)
+{
+	return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
+}
+
 static int ip6_pkt_discard_out(struct sk_buff *skb)
 {
 	skb->dev = skb->dst->dev;
 	return ip6_pkt_discard(skb);
 }
 
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+
+static int ip6_pkt_prohibit(struct sk_buff *skb)
+{
+	return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
+}
+
+static int ip6_pkt_prohibit_out(struct sk_buff *skb)
+{
+	skb->dev = skb->dst->dev;
+	return ip6_pkt_prohibit(skb);
+}
+
+static int ip6_pkt_blk_hole(struct sk_buff *skb)
+{
+	kfree_skb(skb);
+	return 0;
+}
+
+#endif
+
 /*
  *	Allocate a dst for local (unicast / anycast) address.
  */
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 836eecd..b481a4d 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -850,3 +850,7 @@
 	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
 	goto out;
 }
+
+module_init(sit_init);
+module_exit(sit_cleanup);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3b65754..4c2a7c0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -329,7 +329,7 @@
 	}
 
 	if (sk->sk_state == TCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -653,7 +653,7 @@
 	int tot_len = sizeof(struct tcphdr);
 
 	if (ts)
-		tot_len += 3*4;
+		tot_len += TCPOLEN_TSTAMP_ALIGNED;
 
 	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
 			 GFP_ATOMIC);
@@ -749,7 +749,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -1283,18 +1283,17 @@
 
 do_time_wait:
 	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
 
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TCP_MIB_INERRS);
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
 
-	switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
-					   skb, th)) {
+	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
 	case TCP_TW_SYN:
 	{
 		struct sock *sk2;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6a252e2..d400f8f 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -25,12 +25,14 @@
 static struct dst_ops xfrm6_dst_ops;
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
-static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
 {
-	int err = 0;
-	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
-	if (!*dst)
-		err = -ENETUNREACH;
+	struct dst_entry *dst = ip6_route_output(NULL, fl);
+	int err = dst->error;
+	if (!err)
+		*xdst = (struct xfrm_dst *) dst;
+	else
+		dst_release(dst);
 	return err;
 }
 
@@ -73,7 +75,7 @@
 				 xdst->u.rt6.rt6i_src.plen);
 		if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
 		    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
-		    xfrm_bundle_ok(xdst, fl, AF_INET6,
+		    xfrm_bundle_ok(policy, xdst, fl, AF_INET6,
 				   (xdst->u.rt6.rt6i_dst.plen != 128 ||
 				    xdst->u.rt6.rt6i_src.plen != 128))) {
 			dst_clone(dst);
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index a154b1d..56292ab 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -43,7 +43,7 @@
  *
  * Faster, check boundary... Jean II
  */
-static char *strndup(char *str, int max)
+static char *strndup(char *str, size_t max)
 {
 	char *new_str;
 	int len;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ff98e70..20ff7cc 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2928,11 +2928,6 @@
 		if (*dir)
 			goto out;
 	}
-	else {
-		*dir = security_xfrm_sock_policy_alloc(xp, sk);
-		if (*dir)
-			goto out;
-	}
 
 	*dir = pol->sadb_x_policy_dir-1;
 	return xp;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index ce94732..f619c65 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -209,7 +209,9 @@
 
 config NETFILTER_XT_TARGET_CONNSECMARK
 	tristate '"CONNSECMARK" target support'
-	depends on NETFILTER_XTABLES && (NF_CONNTRACK_SECMARK || IP_NF_CONNTRACK_SECMARK)
+	depends on NETFILTER_XTABLES && \
+		   ((NF_CONNTRACK && NF_CONNTRACK_SECMARK) || \
+		    (IP_NF_CONNTRACK && IP_NF_CONNTRACK_SECMARK))
 	help
 	  The CONNSECMARK target copies security markings from packets
 	  to connections, and restores security markings from connections
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 1721f7c..bd0156a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -47,13 +47,6 @@
 
 static char __initdata version[] = "0.93";
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-
 static inline int
 ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
 			    const struct nf_conntrack_tuple *tuple,
@@ -410,7 +403,6 @@
 {
 	if (cb->args[1])
 		nf_ct_put((struct nf_conn *)cb->args[1]);
-	DEBUGP("entered %s\n", __FUNCTION__);
 	return 0;
 }
 
@@ -425,9 +417,6 @@
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
-	DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, 
-			cb->args[0], *id);
-
 	read_lock_bh(&nf_conntrack_lock);
 	last = (struct nf_conn *)cb->args[1];
 	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
@@ -471,7 +460,6 @@
 	if (last)
 		nf_ct_put(last);
 
-	DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
 	return skb->len;
 }
 
@@ -482,8 +470,6 @@
 	struct nf_conntrack_l3proto *l3proto;
 	int ret = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_IP_MAX, attr);
 
 	l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
@@ -493,8 +479,6 @@
 
 	nf_ct_l3proto_put(l3proto);
 
-	DEBUGP("leaving\n");
-
 	return ret;
 }
 
@@ -510,8 +494,6 @@
 	struct nf_conntrack_protocol *proto;
 	int ret = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
@@ -538,8 +520,6 @@
 	struct nfattr *tb[CTA_TUPLE_MAX];
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	memset(tuple, 0, sizeof(*tuple));
 
 	nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
@@ -566,10 +546,6 @@
 	else
 		tuple->dst.dir = IP_CT_DIR_ORIGINAL;
 
-	NF_CT_DUMP_TUPLE(tuple);
-
-	DEBUGP("leaving\n");
-
 	return 0;
 }
 
@@ -586,8 +562,6 @@
 	struct nfattr *tb[CTA_PROTONAT_MAX];
 	struct ip_nat_protocol *npt;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
 
 	if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
@@ -606,7 +580,6 @@
 
 	ip_nat_proto_put(npt);
 
-	DEBUGP("leaving\n");
 	return 0;
 }
 
@@ -622,8 +595,6 @@
 	struct nfattr *tb[CTA_NAT_MAX];
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	memset(range, 0, sizeof(*range));
 	
 	nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
@@ -649,7 +620,6 @@
 	if (err < 0)
 		return err;
 
-	DEBUGP("leaving\n");
 	return 0;
 }
 #endif
@@ -659,8 +629,6 @@
 {
 	struct nfattr *tb[CTA_HELP_MAX];
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
 
 	if (!tb[CTA_HELP_NAME-1])
@@ -690,8 +658,6 @@
 	u_int8_t u3 = nfmsg->nfgen_family;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nfattr_bad_size(cda, CTA_MAX, cta_min))
 		return -EINVAL;
 
@@ -709,10 +675,8 @@
 		return err;
 
 	h = nf_conntrack_find_get(&tuple, NULL);
-	if (!h) {
-		DEBUGP("tuple not found in conntrack hash\n");
+	if (!h)
 		return -ENOENT;
-	}
 
 	ct = nf_ct_tuplehash_to_ctrack(h);
 	
@@ -727,7 +691,6 @@
 		ct->timeout.function((unsigned long)ct);
 
 	nf_ct_put(ct);
-	DEBUGP("leaving\n");
 
 	return 0;
 }
@@ -744,8 +707,6 @@
 	u_int8_t u3 = nfmsg->nfgen_family;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		u32 rlen;
 
@@ -779,11 +740,9 @@
 		return err;
 
 	h = nf_conntrack_find_get(&tuple, NULL);
-	if (!h) {
-		DEBUGP("tuple not found in conntrack hash");
+	if (!h)
 		return -ENOENT;
-	}
-	DEBUGP("tuple found\n");
+
 	ct = nf_ct_tuplehash_to_ctrack(h);
 
 	err = -ENOMEM;
@@ -804,7 +763,6 @@
 	if (err < 0)
 		goto out;
 
-	DEBUGP("leaving\n");
 	return 0;
 
 free:
@@ -876,8 +834,6 @@
 	char *helpname;
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (!help) {
 		/* FIXME: we need to reallocate and rehash */
 		return -EBUSY;
@@ -954,8 +910,6 @@
 {
 	int err;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (cda[CTA_HELP-1]) {
 		err = ctnetlink_change_helper(ct, cda);
 		if (err < 0)
@@ -985,7 +939,6 @@
 		ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
-	DEBUGP("all done\n");
 	return 0;
 }
 
@@ -997,8 +950,6 @@
 	struct nf_conn *ct;
 	int err = -EINVAL;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	ct = nf_conntrack_alloc(otuple, rtuple);
 	if (ct == NULL || IS_ERR(ct))
 		return -ENOMEM;	
@@ -1028,7 +979,6 @@
 	add_timer(&ct->timeout);
 	nf_conntrack_hash_insert(ct);
 
-	DEBUGP("conntrack with id %u inserted\n", ct->id);
 	return 0;
 
 err:	
@@ -1046,8 +996,6 @@
 	u_int8_t u3 = nfmsg->nfgen_family;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nfattr_bad_size(cda, CTA_MAX, cta_min))
 		return -EINVAL;
 
@@ -1071,7 +1019,6 @@
 
 	if (h == NULL) {
 		write_unlock_bh(&nf_conntrack_lock);
-		DEBUGP("no such conntrack, create new\n");
 		err = -ENOENT;
 		if (nlh->nlmsg_flags & NLM_F_CREATE)
 			err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
@@ -1087,7 +1034,6 @@
 
 	/* We manipulate the conntrack inside the global conntrack table lock,
 	 * so there's no need to increase the refcount */
-	DEBUGP("conntrack found\n");
 	err = -EEXIST;
 	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
 		err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), cda);
@@ -1268,8 +1214,6 @@
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
-	DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
-
 	read_lock_bh(&nf_conntrack_lock);
 	list_for_each_prev(i, &nf_conntrack_expect_list) {
 		exp = (struct nf_conntrack_expect *) i;
@@ -1287,8 +1231,6 @@
 out:	
 	read_unlock_bh(&nf_conntrack_lock);
 
-	DEBUGP("leaving, last id=%llu\n", *id);
-
 	return skb->len;
 }
 
@@ -1308,8 +1250,6 @@
 	u_int8_t u3 = nfmsg->nfgen_family;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
 		return -EINVAL;
 
@@ -1460,8 +1400,6 @@
 	struct nf_conn_help *help;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);
-
 	/* caller guarantees that those three CTA_EXPECT_* exist */
 	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
 	if (err < 0)
@@ -1516,8 +1454,6 @@
 	u_int8_t u3 = nfmsg->nfgen_family;
 	int err = 0;
 
-	DEBUGP("entered %s\n", __FUNCTION__);	
-
 	if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
 		return -EINVAL;
 
@@ -1546,8 +1482,6 @@
 		err = ctnetlink_change_expect(exp, cda);
 	write_unlock_bh(&nf_conntrack_lock);
 
-	DEBUGP("leaving\n");
-	
 	return err;
 }
 
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index db9b896..39e1175 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -68,7 +68,7 @@
 
 static void __exit xt_nfqueue_fini(void)
 {
-	xt_register_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
+	xt_unregister_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
 }
 
 module_init(xt_nfqueue_init);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 92a5726..a8f0305 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -147,7 +147,7 @@
 
 static void __exit xt_connmark_fini(void)
 {
-	xt_register_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
+	xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
 }
 
 module_init(xt_connmark_init);
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 54fb7de..ff97110 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -200,7 +200,7 @@
 int netlbl_cache_add(const struct sk_buff *skb,
 		     const struct netlbl_lsm_secattr *secattr)
 {
-	if (secattr->cache.data == NULL)
+	if (secattr->cache == NULL)
 		return -ENOMSG;
 
 	if (CIPSO_V4_OPTEXIST(skb))
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index bb3ddd4..9b9c555 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -786,11 +786,10 @@
 	for (i = 0; i < 500; i++) {
 		struct htb_class *cl;
 		long diff;
-		struct rb_node *p = q->wait_pq[level].rb_node;
+		struct rb_node *p = rb_first(&q->wait_pq[level]);
+
 		if (!p)
 			return 0;
-		while (p->rb_left)
-			p = p->rb_left;
 
 		cl = rb_entry(p, struct htb_class, pq_node);
 		if (time_after(cl->pq_key, q->jiffies)) {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 45939ba..ef8874b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -170,6 +170,8 @@
 		return NET_XMIT_BYPASS;
 	}
 
+	skb_orphan(skb);
+
 	/*
 	 * If we need to duplicate packet, then re-insert at top of the
 	 * qdisc tree, since parent queuer expects that only one
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 249e503..78071c6 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -215,17 +215,17 @@
 	}
 
 	dst = ip6_route_output(NULL, &fl);
-	if (dst) {
+	if (!dst->error) {
 		struct rt6_info *rt;
 		rt = (struct rt6_info *)dst;
 		SCTP_DEBUG_PRINTK(
 			"rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
 			NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
-	} else {
-		SCTP_DEBUG_PRINTK("NO ROUTE\n");
+		return dst;
 	}
-
-	return dst;
+	SCTP_DEBUG_PRINTK("NO ROUTE\n");
+	dst_release(dst);
+	return NULL;
 }
 
 /* Returns the number of consecutive initial bits that match in the 2 ipv6
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index a356d8d..7f49e76 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -344,7 +344,7 @@
 			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
 			   assoc->state, hash, assoc->assoc_id,
 			   assoc->sndbuf_used,
-			   (sk->sk_rcvbuf - assoc->rwnd),
+			   atomic_read(&assoc->rmem_alloc),
 			   sock_i_uid(sk), sock_i_ino(sk),
 			   epb->bind_addr.port,
 			   assoc->peer.port);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 3fe906d..9f34dec 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -821,7 +821,7 @@
  * addrs is a pointer to an array of one or more socket addresses. Each
  * address is contained in its appropriate structure (i.e. struct
  * sockaddr_in or struct sockaddr_in6) the family of the address type
- * must be used to distengish the address length (note that this
+ * must be used to distinguish the address length (note that this
  * representation is termed a "packed array" of addresses). The caller
  * specifies the number of addresses in the array with addrcnt.
  *
@@ -5362,6 +5362,20 @@
 	sctp_association_put(asoc);
 }
 
+/* Do accounting for the receive space on the socket.
+ * Accounting for the association is done in ulpevent.c
+ * We set this as a destructor for the cloned data skbs so that
+ * accounting is done at the correct time.
+ */
+void sctp_sock_rfree(struct sk_buff *skb)
+{
+	struct sock *sk = skb->sk;
+	struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+	atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
+}
+
+
 /* Helper function to wait for space in the sndbuf.  */
 static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
 				size_t msg_len)
@@ -5634,10 +5648,10 @@
 	sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
 		event = sctp_skb2event(skb);
 		if (event->asoc == assoc) {
-			sock_rfree(skb);
+			sctp_sock_rfree(skb);
 			__skb_unlink(skb, &oldsk->sk_receive_queue);
 			__skb_queue_tail(&newsk->sk_receive_queue, skb);
-			skb_set_owner_r(skb, newsk);
+			sctp_skb_set_owner_r(skb, newsk);
 		}
 	}
 
@@ -5665,10 +5679,10 @@
 		sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
 			event = sctp_skb2event(skb);
 			if (event->asoc == assoc) {
-				sock_rfree(skb);
+				sctp_sock_rfree(skb);
 				__skb_unlink(skb, &oldsp->pd_lobby);
 				__skb_queue_tail(queue, skb);
-				skb_set_owner_r(skb, newsk);
+				sctp_skb_set_owner_r(skb, newsk);
 			}
 		}
 
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index ee23678..a015283 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -55,10 +55,13 @@
 
 
 /* Initialize an ULP event from an given skb.  */
-SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
+SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event,
+				    int msg_flags,
+				    unsigned int len)
 {
 	memset(event, 0, sizeof(struct sctp_ulpevent));
 	event->msg_flags = msg_flags;
+	event->rmem_len = len;
 }
 
 /* Create a new sctp_ulpevent.  */
@@ -73,7 +76,7 @@
 		goto fail;
 
 	event = sctp_skb2event(skb);
-	sctp_ulpevent_init(event, msg_flags);
+	sctp_ulpevent_init(event, msg_flags, skb->truesize);
 
 	return event;
 
@@ -101,17 +104,16 @@
 	sctp_association_hold((struct sctp_association *)asoc);
 	skb = sctp_event2skb(event);
 	event->asoc = (struct sctp_association *)asoc;
-	atomic_add(skb->truesize, &event->asoc->rmem_alloc);
-	skb_set_owner_r(skb, asoc->base.sk);
+	atomic_add(event->rmem_len, &event->asoc->rmem_alloc);
+	sctp_skb_set_owner_r(skb, asoc->base.sk);
 }
 
 /* A simple destructor to give up the reference to the association. */
 static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
 {
 	struct sctp_association *asoc = event->asoc;
-	struct sk_buff *skb = sctp_event2skb(event);
 
-	atomic_sub(skb->truesize, &asoc->rmem_alloc);
+	atomic_sub(event->rmem_len, &asoc->rmem_alloc);
 	sctp_association_put(asoc);
 }
 
@@ -372,7 +374,7 @@
 
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
-	sctp_ulpevent_init(event, MSG_NOTIFICATION);
+	sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
 
 	sre = (struct sctp_remote_error *)
 		skb_push(skb, sizeof(struct sctp_remote_error));
@@ -464,7 +466,7 @@
 
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
-	sctp_ulpevent_init(event, MSG_NOTIFICATION);
+	sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
 
 	ssf = (struct sctp_send_failed *)
 		skb_push(skb, sizeof(struct sctp_send_failed));
@@ -682,8 +684,11 @@
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
 
-	/* Initialize event with flags 0.  */
-	sctp_ulpevent_init(event, 0);
+	/* Initialize event with flags 0  and correct length
+	 * Since this is a clone of the original skb, only account for
+	 * the data of this chunk as other chunks will be accounted separately.
+	 */
+	sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff));
 
 	sctp_ulpevent_receive_data(event, asoc);
 
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 575e556..e1d1442 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -309,7 +309,7 @@
  			if (!new)
  				return NULL;	/* try again later */
 
- 			new->sk = f_frag->sk;
+ 			sctp_skb_set_owner_r(new, f_frag->sk);
 
  			skb_shinfo(new)->frag_list = pos;
  		} else
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 447d9ae..1f0f079 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1146,10 +1146,11 @@
 	return ret;
 }
 
-u32 *
+static __be32 *
 svcauth_gss_prepare_to_wrap(struct xdr_buf *resbuf, struct gss_svc_data *gsd)
 {
-	u32 *p, verf_len;
+	__be32 *p;
+	u32 verf_len;
 
 	p = gsd->verf_start;
 	gsd->verf_start = NULL;
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 919d5ba..e52afab 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -101,11 +101,13 @@
 	/* Autobind on cloned rpc clients is discouraged */
 	BUG_ON(clnt->cl_parent != clnt);
 
-	if (xprt_test_and_set_binding(xprt)) {
-		task->tk_status = -EACCES;	/* tell caller to check again */
-		rpc_sleep_on(&xprt->binding, task, NULL, NULL);
-		return;
-	}
+	/* Put self on queue before sending rpcbind request, in case
+	 * pmap_getport_done completes before we return from rpc_run_task */
+	rpc_sleep_on(&xprt->binding, task, NULL, NULL);
+
+	status = -EACCES;		/* tell caller to check again */
+	if (xprt_test_and_set_binding(xprt))
+		goto bailout_nofree;
 
 	/* Someone else may have bound if we slept */
 	status = 0;
@@ -134,8 +136,6 @@
 		goto bailout;
 	rpc_release_task(child);
 
-	rpc_sleep_on(&xprt->binding, task, NULL, NULL);
-
 	task->tk_xprt->stat.bind_count++;
 	return;
 
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index c2c8bb2..eb44ec9 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -282,7 +282,10 @@
 	serv->sv_program   = prog;
 	serv->sv_nrthreads = 1;
 	serv->sv_stats     = prog->pg_stats;
-	serv->sv_bufsz	   = bufsize? bufsize : 4096;
+	if (bufsize > RPCSVC_MAXPAYLOAD)
+		bufsize = RPCSVC_MAXPAYLOAD;
+	serv->sv_max_payload = bufsize? bufsize : 4096;
+	serv->sv_max_mesg  = roundup(serv->sv_max_payload + PAGE_SIZE, PAGE_SIZE);
 	serv->sv_shutdown  = shutdown;
 	xdrsize = 0;
 	while (prog) {
@@ -414,9 +417,9 @@
 	int pages;
 	int arghi;
 	
-	if (size > RPCSVC_MAXPAYLOAD)
-		size = RPCSVC_MAXPAYLOAD;
-	pages = 2 + (size+ PAGE_SIZE -1) / PAGE_SIZE;
+	pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
+				       * We assume one is at most one page
+				       */
 	arghi = 0;
 	BUG_ON(pages > RPCSVC_MAXPAGES);
 	while (pages) {
@@ -463,7 +466,7 @@
 
 	if (!(rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
 	 || !(rqstp->rq_resp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
-	 || !svc_init_buffer(rqstp, serv->sv_bufsz))
+	 || !svc_init_buffer(rqstp, serv->sv_max_mesg))
 		goto out_thread;
 
 	serv->sv_nrthreads++;
@@ -825,6 +828,11 @@
 		*statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
 
 		/* Encode reply */
+		if (*statp == rpc_drop_reply) {
+			if (procp->pc_release)
+				procp->pc_release(rqstp, NULL, rqstp->rq_resp);
+			goto dropit;
+		}
 		if (*statp == rpc_success && (xdr = procp->pc_encode)
 		 && !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) {
 			dprintk("svc: failed to encode reply\n");
@@ -938,8 +946,8 @@
 
 	if (rqstp->rq_sock->sk_sock->type == SOCK_DGRAM)
 		max = RPCSVC_MAXPAYLOAD_UDP;
-	if (rqstp->rq_server->sv_bufsz < max)
-		max = rqstp->rq_server->sv_bufsz;
+	if (rqstp->rq_server->sv_max_payload < max)
+		max = rqstp->rq_server->sv_max_payload;
 	return max;
 }
 EXPORT_SYMBOL_GPL(svc_max_payload);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index b39e7e2..96521f1 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -192,13 +192,13 @@
 	svsk->sk_pool = pool;
 
 	set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
-	if (((atomic_read(&svsk->sk_reserved) + serv->sv_bufsz)*2
+	if (((atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg)*2
 	     > svc_sock_wspace(svsk))
 	    && !test_bit(SK_CLOSE, &svsk->sk_flags)
 	    && !test_bit(SK_CONN, &svsk->sk_flags)) {
 		/* Don't enqueue while not enough space for reply */
 		dprintk("svc: socket %p  no space, %d*2 > %ld, not enqueued\n",
-			svsk->sk_sk, atomic_read(&svsk->sk_reserved)+serv->sv_bufsz,
+			svsk->sk_sk, atomic_read(&svsk->sk_reserved)+serv->sv_max_mesg,
 			svc_sock_wspace(svsk));
 		svsk->sk_pool = NULL;
 		clear_bit(SK_BUSY, &svsk->sk_flags);
@@ -220,7 +220,7 @@
 				rqstp, rqstp->rq_sock);
 		rqstp->rq_sock = svsk;
 		atomic_inc(&svsk->sk_inuse);
-		rqstp->rq_reserved = serv->sv_bufsz;
+		rqstp->rq_reserved = serv->sv_max_mesg;
 		atomic_add(rqstp->rq_reserved, &svsk->sk_reserved);
 		BUG_ON(svsk->sk_pool != pool);
 		wake_up(&rqstp->rq_wait);
@@ -639,8 +639,8 @@
 	     * which will access the socket.
 	     */
 	    svc_sock_setbufsize(svsk->sk_sock,
-				(serv->sv_nrthreads+3) * serv->sv_bufsz,
-				(serv->sv_nrthreads+3) * serv->sv_bufsz);
+				(serv->sv_nrthreads+3) * serv->sv_max_mesg,
+				(serv->sv_nrthreads+3) * serv->sv_max_mesg);
 
 	if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) {
 		svc_sock_received(svsk);
@@ -749,8 +749,8 @@
 	 * svc_udp_recvfrom will re-adjust if necessary
 	 */
 	svc_sock_setbufsize(svsk->sk_sock,
-			    3 * svsk->sk_server->sv_bufsz,
-			    3 * svsk->sk_server->sv_bufsz);
+			    3 * svsk->sk_server->sv_max_mesg,
+			    3 * svsk->sk_server->sv_max_mesg);
 
 	set_bit(SK_DATA, &svsk->sk_flags); /* might have come in before data_ready set up */
 	set_bit(SK_CHNGBUF, &svsk->sk_flags);
@@ -973,7 +973,7 @@
 		return 0;
 	}
 
-	if (test_bit(SK_CONN, &svsk->sk_flags)) {
+	if (svsk->sk_sk->sk_state == TCP_LISTEN) {
 		svc_tcp_accept(svsk);
 		svc_sock_received(svsk);
 		return 0;
@@ -993,8 +993,8 @@
 		 * as soon a a complete request arrives.
 		 */
 		svc_sock_setbufsize(svsk->sk_sock,
-				    (serv->sv_nrthreads+3) * serv->sv_bufsz,
-				    3 * serv->sv_bufsz);
+				    (serv->sv_nrthreads+3) * serv->sv_max_mesg,
+				    3 * serv->sv_max_mesg);
 
 	clear_bit(SK_DATA, &svsk->sk_flags);
 
@@ -1032,7 +1032,7 @@
 		}
 		svsk->sk_reclen &= 0x7fffffff;
 		dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
-		if (svsk->sk_reclen > serv->sv_bufsz) {
+		if (svsk->sk_reclen > serv->sv_max_mesg) {
 			printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx (large)\n",
 			       (unsigned long) svsk->sk_reclen);
 			goto err_delete;
@@ -1171,8 +1171,8 @@
 		 * svc_tcp_recvfrom will re-adjust if necessary
 		 */
 		svc_sock_setbufsize(svsk->sk_sock,
-				    3 * svsk->sk_server->sv_bufsz,
-				    3 * svsk->sk_server->sv_bufsz);
+				    3 * svsk->sk_server->sv_max_mesg,
+				    3 * svsk->sk_server->sv_max_mesg);
 
 		set_bit(SK_CHNGBUF, &svsk->sk_flags);
 		set_bit(SK_DATA, &svsk->sk_flags);
@@ -1234,7 +1234,7 @@
 
 
 	/* now allocate needed pages.  If we get a failure, sleep briefly */
-	pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE;
+	pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE;
 	for (i=0; i < pages ; i++)
 		while (rqstp->rq_pages[i] == NULL) {
 			struct page *p = alloc_page(GFP_KERNEL);
@@ -1263,7 +1263,7 @@
 	if ((svsk = svc_sock_dequeue(pool)) != NULL) {
 		rqstp->rq_sock = svsk;
 		atomic_inc(&svsk->sk_inuse);
-		rqstp->rq_reserved = serv->sv_bufsz;	
+		rqstp->rq_reserved = serv->sv_max_mesg;
 		atomic_add(rqstp->rq_reserved, &svsk->sk_reserved);
 	} else {
 		/* No data pending. Go to sleep */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 28100e0..757fc91 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1366,7 +1366,7 @@
 	if (xprt->slot == NULL)
 		return -ENOMEM;
 
-	if (ntohs(addr->sin_port != 0))
+	if (ntohs(addr->sin_port) != 0)
 		xprt_set_bound(xprt);
 	xprt->port = xs_get_random_port();
 
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 75a5968..39744a3 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -2,7 +2,7 @@
  * net/tipc/bearer.c: TIPC bearer code
  * 
  * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -191,14 +191,14 @@
 	if ((i < media_count) && (m_ptr->addr2str != NULL)) {
 		char addr_str[MAX_ADDR_STR];
 
-		tipc_printf(pb, "%s(%s) ", m_ptr->name, 
+		tipc_printf(pb, "%s(%s)", m_ptr->name,
 			    m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
 	} else {
 		unchar *addr = (unchar *)&a->dev_addr;
 
-		tipc_printf(pb, "UNKNOWN(%u):", media_type);
+		tipc_printf(pb, "UNKNOWN(%u)", media_type);
 		for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
-			tipc_printf(pb, "%02x ", addr[i]);
+			tipc_printf(pb, "-%02x", addr[i]);
 		}
 	}
 }
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 285e1bc..ed1351e 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -2,7 +2,7 @@
  * net/tipc/config.c: TIPC configuration management code
  * 
  * Copyright (c) 2002-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -613,7 +613,8 @@
 		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
 		break;
 	default:
-		rep_tlv_buf = NULL;
+		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+							  " (unknown command)");
 		break;
 	}
 
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 0539a83..6f5b7ee 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -57,7 +57,7 @@
 int  tipc_netlink_start(void);
 void tipc_netlink_stop(void);
 
-#define TIPC_MOD_VER "1.6.1"
+#define TIPC_MOD_VER "1.6.2"
 
 #ifndef CONFIG_TIPC_ZONES
 #define CONFIG_TIPC_ZONES 3
@@ -90,7 +90,7 @@
 atomic_t tipc_user_count = ATOMIC_INIT(0);
 
 const char tipc_alphabet[] = 
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
 
 /* configurable TIPC parameters */
 
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 762aac2..4638947c 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -65,7 +65,7 @@
 #define assert(i)  BUG_ON(!(i))
 
 struct tipc_msg;
-extern struct print_buf *TIPC_CONS, *TIPC_LOG;
+extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG;
 extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
 void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
 void tipc_printf(struct print_buf *, const char *fmt, ...);
@@ -83,9 +83,9 @@
 #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
 #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
 
-#define dbg(fmt, arg...)  do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
-#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
-#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
+#define dbg(fmt, arg...)  do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
+#define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
+#define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
 
 
 /*	
@@ -94,11 +94,11 @@
  * here, or on a per .c file basis, by redefining these symbols.  The following
  * print buffer options are available:
  *
- * NULL				: Output to null print buffer (i.e. print nowhere)
- * TIPC_CONS			: Output to system console
- * TIPC_LOG			: Output to TIPC log buffer 
- * &buf				: Output to user-defined buffer (struct print_buf *)
- * TIPC_TEE(&buf_a,&buf_b)	: Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) )
+ * TIPC_NULL		   : null buffer (i.e. print nowhere)
+ * TIPC_CONS		   : system console
+ * TIPC_LOG		   : TIPC log buffer
+ * &buf			   : user-defined buffer (struct print_buf *)
+ * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG))
  */
 
 #ifndef TIPC_OUTPUT
@@ -106,7 +106,7 @@
 #endif
 
 #ifndef DBG_OUTPUT
-#define DBG_OUTPUT NULL
+#define DBG_OUTPUT TIPC_NULL
 #endif
 
 #else
@@ -136,7 +136,7 @@
 #define TIPC_OUTPUT TIPC_CONS
 
 #undef  DBG_OUTPUT
-#define DBG_OUTPUT NULL
+#define DBG_OUTPUT TIPC_NULL
 
 #endif			  
 
@@ -275,11 +275,15 @@
 /*
  * TIPC message buffer code
  *
- * TIPC message buffer headroom leaves room for 14 byte Ethernet header, 
+ * TIPC message buffer headroom reserves space for a link-level header
+ * (in case the message is sent off-node),
  * while ensuring TIPC header is word aligned for quicker access
+ *
+ * The largest header currently supported is 18 bytes, which is used when
+ * the standard 14 byte Ethernet header has 4 added bytes for VLAN info
  */
 
-#define BUF_HEADROOM 16u 
+#define BUF_HEADROOM 20u
 
 struct tipc_skb_cb {
 	void *handle;
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 5513065..d8af4c2 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -1,8 +1,8 @@
 /*
- * net/tipc/dbg.c: TIPC print buffer routines for debuggign
+ * net/tipc/dbg.c: TIPC print buffer routines for debugging
  * 
  * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,11 +38,12 @@
 #include "config.h"
 #include "dbg.h"
 
-#define MAX_STRING 512
-
-static char print_string[MAX_STRING];
+static char print_string[TIPC_PB_MAX_STR];
 static DEFINE_SPINLOCK(print_lock);
 
+static struct print_buf null_buf = { NULL, 0, NULL, NULL };
+struct print_buf *TIPC_NULL = &null_buf;
+
 static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
 struct print_buf *TIPC_CONS = &cons_buf;
 
@@ -62,68 +63,83 @@
 /*
  * Locking policy when using print buffers.
  *
- * 1) Routines of the form printbuf_XXX() rely on the caller to prevent
- *    simultaneous use of the print buffer(s) being manipulated.
- * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
- *    'print_string' and to protect its print buffer(s).
- * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s).
- * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG.
+ * The following routines use 'print_lock' for protection:
+ * 1) tipc_printf()  - to protect its print buffer(s) and 'print_string'
+ * 2) TIPC_TEE()     - to protect its print buffer(s)
+ * 3) tipc_dump()    - to protect its print buffer(s) and 'print_string'
+ * 4) tipc_log_XXX() - to protect TIPC_LOG
+ *
+ * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent
+ * simultaneous use of the print buffer(s) being manipulated.
  */
 
 /**
  * tipc_printbuf_init - initialize print buffer to empty
+ * @pb: pointer to print buffer structure
+ * @raw: pointer to character array used by print buffer
+ * @size: size of character array
+ *
+ * Makes the print buffer a null device that discards anything written to it
+ * if the character array is too small (or absent).
  */
 
-void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz)
+void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size)
 {
-	if (!pb || !raw || (sz < (MAX_STRING + 1)))
-		return;
-
-	pb->crs = pb->buf = raw;
-	pb->size = sz;
+	pb->buf = raw;
+	pb->crs = raw;
+	pb->size = size;
 	pb->next = NULL;
-	pb->buf[0] = 0;
-	pb->buf[sz-1] = ~0;
+
+	if (size < TIPC_PB_MIN_SIZE) {
+		pb->buf = NULL;
+	} else if (raw) {
+		pb->buf[0] = 0;
+		pb->buf[size-1] = ~0;
+	}
 }
 
 /**
  * tipc_printbuf_reset - reinitialize print buffer to empty state
+ * @pb: pointer to print buffer structure
  */
 
 void tipc_printbuf_reset(struct print_buf *pb)
 {
-	if (pb && pb->buf)
-		tipc_printbuf_init(pb, pb->buf, pb->size);
+	tipc_printbuf_init(pb, pb->buf, pb->size);
 }
 
 /**
  * tipc_printbuf_empty - test if print buffer is in empty state
+ * @pb: pointer to print buffer structure
+ *
+ * Returns non-zero if print buffer is empty.
  */
 
 int tipc_printbuf_empty(struct print_buf *pb)
 {
-	return (!pb || !pb->buf || (pb->crs == pb->buf));
+	return (!pb->buf || (pb->crs == pb->buf));
 }
 
 /**
  * tipc_printbuf_validate - check for print buffer overflow
+ * @pb: pointer to print buffer structure
  * 
  * Verifies that a print buffer has captured all data written to it. 
  * If data has been lost, linearize buffer and prepend an error message
  * 
- * Returns length of print buffer data string (including trailing NULL)
+ * Returns length of print buffer data string (including trailing NUL)
  */
 
 int tipc_printbuf_validate(struct print_buf *pb)
 {
-        char *err = "             *** PRINT BUFFER WRAPPED AROUND ***\n";
+        char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
         char *cp_buf;
         struct print_buf cb;
 
-	if (!pb || !pb->buf)
+	if (!pb->buf)
 		return 0;
 
-	if (pb->buf[pb->size - 1] == '\0') {
+	if (pb->buf[pb->size - 1] == 0) {
                 cp_buf = kmalloc(pb->size, GFP_ATOMIC);
                 if (cp_buf != NULL){
                         tipc_printbuf_init(&cb, cp_buf, pb->size);
@@ -141,6 +157,8 @@
 
 /**
  * tipc_printbuf_move - move print buffer contents to another print buffer
+ * @pb_to: pointer to destination print buffer structure
+ * @pb_from: pointer to source print buffer structure
  * 
  * Current contents of destination print buffer (if any) are discarded.
  * Source print buffer becomes empty if a successful move occurs.
@@ -152,21 +170,22 @@
 
 	/* Handle the cases where contents can't be moved */
 
-	if (!pb_to || !pb_to->buf)
+	if (!pb_to->buf)
 		return;
 
-	if (!pb_from || !pb_from->buf) {
+	if (!pb_from->buf) {
 		tipc_printbuf_reset(pb_to);
 		return;
 	}
 
 	if (pb_to->size < pb_from->size) {
 		tipc_printbuf_reset(pb_to);
-		tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
+		tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***");
 		return;
 	}
 
 	/* Copy data from char after cursor to end (if used) */
+
 	len = pb_from->buf + pb_from->size - pb_from->crs - 2;
 	if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
 		strcpy(pb_to->buf, pb_from->crs + 1);
@@ -175,6 +194,7 @@
 		pb_to->crs = pb_to->buf;
 
 	/* Copy data from start to cursor (always) */
+
 	len = pb_from->crs - pb_from->buf;
 	strcpy(pb_to->crs, pb_from->buf);
 	pb_to->crs += len;
@@ -184,6 +204,8 @@
 
 /**
  * tipc_printf - append formatted output to print buffer chain
+ * @pb: pointer to chain of print buffers (may be NULL)
+ * @fmt: formatted info to be printed
  */
 
 void tipc_printf(struct print_buf *pb, const char *fmt, ...)
@@ -195,8 +217,8 @@
 
 	spin_lock_bh(&print_lock);
 	FORMAT(print_string, chars_to_add, fmt);
-	if (chars_to_add >= MAX_STRING)
-		strcpy(print_string, "*** STRING TOO LONG ***");
+	if (chars_to_add >= TIPC_PB_MAX_STR)
+		strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***");
 
 	while (pb) {
 		if (pb == TIPC_CONS)
@@ -206,6 +228,10 @@
 			if (chars_to_add <= chars_left) {
 				strcpy(pb->crs, print_string);
 				pb->crs += chars_to_add;
+			} else if (chars_to_add >= (pb->size - 1)) {
+				strcpy(pb->buf, print_string + chars_to_add + 1
+				       - pb->size);
+				pb->crs = pb->buf + pb->size - 1;
 			} else {
 				strcpy(pb->buf, print_string + chars_left);
                                 save_char = print_string[chars_left];
@@ -224,6 +250,10 @@
 
 /**
  * TIPC_TEE - perform next output operation on both print buffers  
+ * @b0: pointer to chain of print buffers (may be NULL)
+ * @b1: pointer to print buffer to add to chain
+ *
+ * Returns pointer to print buffer chain.
  */
 
 struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
@@ -232,8 +262,6 @@
 
 	if (!b0 || (b0 == b1))
 		return b1;
-	if (!b1)
-		return b0;
 
 	spin_lock_bh(&print_lock);
 	while (pb->next) {
@@ -256,7 +284,7 @@
 	int rest = len;
 
 	while (rest > 0) {
-		int sz = rest < MAX_STRING ? rest : MAX_STRING;
+		int sz = rest < TIPC_PB_MAX_STR ? rest : TIPC_PB_MAX_STR;
 		char c = crs[sz];
 
 		crs[sz] = 0;
@@ -275,36 +303,48 @@
 {
 	int len;
 
+	if (!pb->buf) {
+		printk("*** PRINT BUFFER NOT ALLOCATED ***");
+		return;
+	}
+
 	/* Dump print buffer from char after cursor to end (if used) */
+
 	len = pb->buf + pb->size - pb->crs - 2;
 	if ((pb->buf[pb->size - 1] == 0) && (len > 0))
 		print_to_console(pb->crs + 1, len);
 
 	/* Dump print buffer from start to cursor (always) */
+
 	len = pb->crs - pb->buf;
 	print_to_console(pb->buf, len);
 }
 
 /**
  * tipc_dump - dump non-console print buffer(s) to console
+ * @pb: pointer to chain of print buffers
  */
 
 void tipc_dump(struct print_buf *pb, const char *fmt, ...)
 {
+	struct print_buf *pb_next;
 	int len;
 
 	spin_lock_bh(&print_lock);
-	FORMAT(TIPC_CONS->buf, len, fmt);
-	printk(TIPC_CONS->buf);
+	FORMAT(print_string, len, fmt);
+	printk(print_string);
 
 	for (; pb; pb = pb->next) {
-		if (pb == TIPC_CONS)
-			continue;
-		printk("\n---- Start of dump,%s log ----\n\n", 
-		       (pb == TIPC_LOG) ? "global" : "local");
-		printbuf_dump(pb);
-		tipc_printbuf_reset(pb);
-		printk("\n-------- End of dump --------\n");
+		if (pb != TIPC_CONS) {
+			printk("\n---- Start of %s log dump ----\n\n",
+			       (pb == TIPC_LOG) ? "global" : "local");
+			printbuf_dump(pb);
+			tipc_printbuf_reset(pb);
+			printk("\n---- End of dump ----\n");
+		}
+		pb_next = pb->next;
+		pb->next = NULL;
+		pb = pb_next;
 	}
 	spin_unlock_bh(&print_lock);
 }
@@ -324,7 +364,8 @@
 }
 
 /**
- * tipc_log_reinit - set TIPC log print buffer to specified size
+ * tipc_log_reinit - (re)initialize TIPC log print buffer
+ * @log_size: print buffer size to use
  */
 
 void tipc_log_reinit(int log_size)
@@ -332,10 +373,11 @@
 	tipc_log_stop();
 
 	if (log_size) {
-		if (log_size <= MAX_STRING)
-			log_size = MAX_STRING + 1;
+		if (log_size < TIPC_PB_MIN_SIZE)
+			log_size = TIPC_PB_MIN_SIZE;
 		spin_lock_bh(&print_lock);
-		tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
+		tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC),
+				   log_size);
 		spin_unlock_bh(&print_lock);
 	}
 }
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index 227f050..467c0bc 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -2,7 +2,7 @@
  * net/tipc/dbg.h: Include file for TIPC print buffer routines
  * 
  * Copyright (c) 1997-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,14 @@
 #ifndef _TIPC_DBG_H
 #define _TIPC_DBG_H
 
+/**
+ * struct print_buf - TIPC print buffer structure
+ * @buf: pointer to character array containing print buffer contents
+ * @size: size of character array
+ * @crs: pointer to first unused space in character array (i.e. final NUL)
+ * @next: used to link print buffers when printing to more than one at a time
+ */
+
 struct print_buf {
 	char *buf;
 	u32 size;
@@ -44,7 +52,10 @@
 	struct print_buf *next;
 };
 
-void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz);
+#define TIPC_PB_MIN_SIZE 64	/* minimum size for a print buffer's array */
+#define TIPC_PB_MAX_STR 512	/* max printable string (with trailing NUL) */
+
+void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size);
 void tipc_printbuf_reset(struct print_buf *pb);
 int  tipc_printbuf_empty(struct print_buf *pb);
 int  tipc_printbuf_validate(struct print_buf *pb);
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index ee94de9..3b0cd12 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -132,6 +132,28 @@
 }
 
 /**
+ * disc_dupl_alert - issue node address duplication alert
+ * @b_ptr: pointer to bearer detecting duplication
+ * @node_addr: duplicated node address
+ * @media_addr: media address advertised by duplicated node
+ */
+
+static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
+			    struct tipc_media_addr *media_addr)
+{
+	char node_addr_str[16];
+	char media_addr_str[64];
+	struct print_buf pb;
+
+	addr_string_fill(node_addr_str, node_addr);
+	tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str));
+	tipc_media_addr_printf(&pb, media_addr);
+	tipc_printbuf_validate(&pb);
+	warn("Duplicate %s using %s seen on <%s>\n",
+	     node_addr_str, media_addr_str, b_ptr->publ.name);
+}
+
+/**
  * tipc_disc_recv_msg - handle incoming link setup message (request or response)
  * @buf: buffer containing message
  */
@@ -157,8 +179,11 @@
 		return;
 	if (!tipc_addr_node_valid(orig))
 		return;
-	if (orig == tipc_own_addr)
+	if (orig == tipc_own_addr) {
+		if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr)))
+			disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
 		return;
+	}
 	if (!in_scope(dest, tipc_own_addr))
 		return;
 	if (is_slave(tipc_own_addr) && is_slave(orig))
@@ -170,7 +195,8 @@
 		struct sk_buff *rbuf;
 		struct tipc_media_addr *addr;
 		struct node *n_ptr = tipc_node_find(orig);
-		int link_up;
+		int link_fully_up;
+
 		dbg(" in own cluster\n");
 		if (n_ptr == NULL) {
 			n_ptr = tipc_node_create(orig);
@@ -190,14 +216,19 @@
 		}
 		addr = &link->media_addr;
 		if (memcmp(addr, &media_addr, sizeof(*addr))) {
+			if (tipc_link_is_up(link) || (!link->started)) {
+				disc_dupl_alert(b_ptr, orig, &media_addr);
+				spin_unlock_bh(&n_ptr->lock);
+				return;
+			}
 			warn("Resetting link <%s>, peer interface address changed\n",
 			     link->name);
 			memcpy(addr, &media_addr, sizeof(*addr));
 			tipc_link_reset(link);     
 		}
-		link_up = tipc_link_is_up(link);
+		link_fully_up = (link->state == WORKING_WORKING);
 		spin_unlock_bh(&n_ptr->lock);                
-		if ((type == DSC_RESP_MSG) || link_up)
+		if ((type == DSC_RESP_MSG) || link_fully_up)
 			return;
 		rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
 		if (rbuf != NULL) {
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 53bc8cb..1bb983c 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -132,7 +132,7 @@
  * allow the output from multiple links to be intermixed.  For this reason
  * routines of the form "dbg_link_XXX()" have been created that will capture
  * debug info into a link's personal print buffer, which can then be dumped
- * into the TIPC system log (LOG) upon request.
+ * into the TIPC system log (TIPC_LOG) upon request.
  *
  * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
  * of the print buffer used by each link.  If LINK_LOG_BUF_SIZE is set to 0,
@@ -141,7 +141,7 @@
  * when there is only a single link in the system being debugged.
  *
  * Notes:
- * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes)
+ * - When enabled, LINK_LOG_BUF_SIZE should be set to at least TIPC_PB_MIN_SIZE
  * - "l_ptr" must be valid when using dbg_link_XXX() macros  
  */
 
@@ -159,13 +159,13 @@
 
 static void dbg_print_link(struct link *l_ptr, const char *str)
 {
-	if (DBG_OUTPUT)
+	if (DBG_OUTPUT != TIPC_NULL)
 		link_print(l_ptr, DBG_OUTPUT, str);
 }
 
 static void dbg_print_buf_chain(struct sk_buff *root_buf)
 {
-	if (DBG_OUTPUT) {
+	if (DBG_OUTPUT != TIPC_NULL) {
 		struct sk_buff *buf = root_buf;
 
 		while (buf) {
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index f0b063b..03bd659 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -122,7 +122,7 @@
 	struct sk_buff *buf;
 	struct distr_item *item;
 
-	list_add(&publ->local_list, &publ_root);
+	list_add_tail(&publ->local_list, &publ_root);
 	publ_cnt++;
 
 	buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index fc6d096..886bda5 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -648,7 +648,7 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (network address)");
 
-        if (!tipc_nodes)
+        if (tipc_mode != TIPC_NET_MODE)
                 return tipc_cfg_reply_none();
 	
 	/* Get space for all unicast links + multicast link */
diff --git a/net/tipc/port.c b/net/tipc/port.c
index b9c8c6b..c1a1a767 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -505,9 +505,14 @@
 	struct port *p_ptr = tipc_port_lock(ref);
 	struct sk_buff *buf = NULL;
 
-	if (!p_ptr || !p_ptr->publ.connected)
+	if (!p_ptr)
 		return;
 
+	if (!p_ptr->publ.connected) {
+		tipc_port_unlock(p_ptr);
+		return;
+	}
+
 	/* Last probe answered ? */
 	if (p_ptr->probing_state == PROBING) {
 		buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 32d7784..2a6a5a6 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2,7 +2,7 @@
  * net/tipc/socket.c: TIPC socket API
  * 
  * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -629,6 +629,9 @@
                         return -ENOTCONN;
         }
 
+	if (unlikely(m->msg_name))
+		return -EISCONN;
+
 	/* 
 	 * Send each iovec entry using one or more messages
 	 *
@@ -641,6 +644,8 @@
 	curr_iovlen = m->msg_iovlen;
 	my_msg.msg_iov = &my_iov;
 	my_msg.msg_iovlen = 1;
+	my_msg.msg_flags = m->msg_flags;
+	my_msg.msg_name = NULL;
 	bytes_sent = 0;
 
 	while (curr_iovlen--) {
@@ -941,7 +946,7 @@
 	int sz_to_copy;
 	int sz_copied = 0;
 	int needed;
-	char *crs = m->msg_iov->iov_base;
+	char __user *crs = m->msg_iov->iov_base;
 	unsigned char *buf_crs;
 	u32 err;
 	int res;
@@ -1203,7 +1208,8 @@
 	atomic_inc(&tipc_queue_size);
 	skb_queue_tail(&sock->sk->sk_receive_queue, buf);
 
-        wake_up_interruptible(sock->sk->sk_sleep);
+	if (waitqueue_active(sock->sk->sk_sleep))
+		wake_up_interruptible(sock->sk->sk_sleep);
 	return TIPC_OK;
 }
 
@@ -1218,7 +1224,8 @@
 {
 	struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
 
-        wake_up_interruptible(tsock->sk.sk_sleep);
+	if (waitqueue_active(tsock->sk.sk_sleep))
+		wake_up_interruptible(tsock->sk.sk_sleep);
 }
 
 /**
@@ -1496,7 +1503,7 @@
 		return -ENOPROTOOPT;
 	if (ol < sizeof(value))
 		return -EINVAL;
-        if ((res = get_user(value, (u32 *)ov)))
+        if ((res = get_user(value, (u32 __user *)ov)))
 		return res;
 
 	if (down_interruptible(&tsock->sem)) 
@@ -1541,7 +1548,7 @@
  */
 
 static int getsockopt(struct socket *sock, 
-		      int lvl, int opt, char __user *ov, int *ol)
+		      int lvl, int opt, char __user *ov, int __user *ol)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
         int len;
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index c51600b..7a918f1 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -155,7 +155,7 @@
 	    sub->seq.upper, found_lower, found_upper);
 	if (!tipc_subscr_overlap(sub, found_lower, found_upper))
 		return;
-	if (!must && (sub->filter != TIPC_SUB_PORTS))
+	if (!must && !(sub->filter & TIPC_SUB_PORTS))
 		return;
 	subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
 }
@@ -176,6 +176,13 @@
 	if (subscriber == NULL)
 		return;
 
+	/* Validate timeout (in case subscription is being cancelled) */
+
+	if (sub->timeout == TIPC_WAIT_FOREVER) {
+		tipc_ref_unlock(subscriber_ref);
+		return;
+	}
+
 	/* Unlink subscription from name table */
 
 	tipc_nametbl_unsubscribe(sub);
@@ -199,6 +206,20 @@
 }
 
 /**
+ * subscr_del - delete a subscription within a subscription list
+ *
+ * Called with subscriber locked.
+ */
+
+static void subscr_del(struct subscription *sub)
+{
+	tipc_nametbl_unsubscribe(sub);
+	list_del(&sub->subscription_list);
+	kfree(sub);
+	atomic_dec(&topsrv.subscription_count);
+}
+
+/**
  * subscr_terminate - terminate communication with a subscriber
  * 
  * Called with subscriber locked.  Routine must temporarily release this lock
@@ -227,12 +248,9 @@
 			k_cancel_timer(&sub->timer);
 			k_term_timer(&sub->timer);
 		}
-		tipc_nametbl_unsubscribe(sub);
-		list_del(&sub->subscription_list);
-		dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
+		dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n",
 		    sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
-		kfree(sub);
-		atomic_dec(&topsrv.subscription_count);
+		subscr_del(sub);
 	}
 
 	/* Sever connection to subscriber */
@@ -253,6 +271,49 @@
 }
 
 /**
+ * subscr_cancel - handle subscription cancellation request
+ *
+ * Called with subscriber locked.  Routine must temporarily release this lock
+ * to enable the subscription timeout routine to finish without deadlocking;
+ * the lock is then reclaimed to allow caller to release it upon return.
+ *
+ * Note that fields of 's' use subscriber's endianness!
+ */
+
+static void subscr_cancel(struct tipc_subscr *s,
+			  struct subscriber *subscriber)
+{
+	struct subscription *sub;
+	struct subscription *sub_temp;
+	int found = 0;
+
+	/* Find first matching subscription, exit if not found */
+
+	list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
+				 subscription_list) {
+		if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		return;
+
+	/* Cancel subscription timer (if used), then delete subscription */
+
+	if (sub->timeout != TIPC_WAIT_FOREVER) {
+		sub->timeout = TIPC_WAIT_FOREVER;
+		spin_unlock_bh(subscriber->lock);
+		k_cancel_timer(&sub->timer);
+		k_term_timer(&sub->timer);
+		spin_lock_bh(subscriber->lock);
+	}
+	dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n",
+	    sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
+	subscr_del(sub);
+}
+
+/**
  * subscr_subscribe - create subscription for subscriber
  * 
  * Called with subscriber locked
@@ -263,6 +324,21 @@
 {
 	struct subscription *sub;
 
+	/* Determine/update subscriber's endianness */
+
+	if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE))
+		subscriber->swap = 0;
+	else
+		subscriber->swap = 1;
+
+	/* Detect & process a subscription cancellation request */
+
+	if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) {
+		s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap);
+		subscr_cancel(s, subscriber);
+		return;
+	}
+
 	/* Refuse subscription if global limit exceeded */
 
 	if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
@@ -281,13 +357,6 @@
 		return;
 	}
 
-	/* Determine/update subscriber's endianness */
-
-	if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
-		subscriber->swap = 0;
-	else
-		subscriber->swap = 1;
-
 	/* Initialize subscription object */
 
 	memset(sub, 0, sizeof(*sub));
@@ -296,8 +365,8 @@
 	sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
 	sub->timeout = htohl(s->timeout, subscriber->swap);
 	sub->filter = htohl(s->filter, subscriber->swap);
-	if ((((sub->filter != TIPC_SUB_PORTS) 
-	      && (sub->filter != TIPC_SUB_SERVICE)))
+	if ((!(sub->filter & TIPC_SUB_PORTS)
+	     == !(sub->filter & TIPC_SUB_SERVICE))
 	    || (sub->seq.lower > sub->seq.upper)) {
 		warn("Subscription rejected, illegal request\n");
 		kfree(sub);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 2a78616..7736b23 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -883,30 +883,32 @@
 }
 EXPORT_SYMBOL(xfrm_policy_walk);
 
-/* Find policy to apply to this flow. */
-
+/*
+ * Find policy to apply to this flow.
+ *
+ * Returns 0 if policy found, else an -errno.
+ */
 static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
 			     u8 type, u16 family, int dir)
 {
 	struct xfrm_selector *sel = &pol->selector;
-	int match;
+	int match, ret = -ESRCH;
 
 	if (pol->family != family ||
 	    pol->type != type)
-		return 0;
+		return ret;
 
 	match = xfrm_selector_match(sel, fl, family);
-	if (match) {
-		if (!security_xfrm_policy_lookup(pol, fl->secid, dir))
-			return 1;
-	}
+	if (match)
+		ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
 
-	return 0;
+	return ret;
 }
 
 static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
 						     u16 family, u8 dir)
 {
+	int err;
 	struct xfrm_policy *pol, *ret;
 	xfrm_address_t *daddr, *saddr;
 	struct hlist_node *entry;
@@ -922,7 +924,15 @@
 	chain = policy_hash_direct(daddr, saddr, family, dir);
 	ret = NULL;
 	hlist_for_each_entry(pol, entry, chain, bydst) {
-		if (xfrm_policy_match(pol, fl, type, family, dir)) {
+		err = xfrm_policy_match(pol, fl, type, family, dir);
+		if (err) {
+			if (err == -ESRCH)
+				continue;
+			else {
+				ret = ERR_PTR(err);
+				goto fail;
+			}
+		} else {
 			ret = pol;
 			priority = ret->priority;
 			break;
@@ -930,36 +940,53 @@
 	}
 	chain = &xfrm_policy_inexact[dir];
 	hlist_for_each_entry(pol, entry, chain, bydst) {
-		if (xfrm_policy_match(pol, fl, type, family, dir) &&
-		    pol->priority < priority) {
+		err = xfrm_policy_match(pol, fl, type, family, dir);
+		if (err) {
+			if (err == -ESRCH)
+				continue;
+			else {
+				ret = ERR_PTR(err);
+				goto fail;
+			}
+		} else if (pol->priority < priority) {
 			ret = pol;
 			break;
 		}
 	}
 	if (ret)
 		xfrm_pol_hold(ret);
+fail:
 	read_unlock_bh(&xfrm_policy_lock);
 
 	return ret;
 }
 
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
 			       void **objp, atomic_t **obj_refp)
 {
 	struct xfrm_policy *pol;
+	int err = 0;
 
 #ifdef CONFIG_XFRM_SUB_POLICY
 	pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir);
-	if (pol)
+	if (IS_ERR(pol)) {
+		err = PTR_ERR(pol);
+		pol = NULL;
+	}
+	if (pol || err)
 		goto end;
 #endif
 	pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir);
-
+	if (IS_ERR(pol)) {
+		err = PTR_ERR(pol);
+		pol = NULL;
+	}
 #ifdef CONFIG_XFRM_SUB_POLICY
 end:
 #endif
 	if ((*objp = (void *) pol) != NULL)
 		*obj_refp = &pol->refcnt;
+	return err;
 }
 
 static inline int policy_to_flow_dir(int dir)
@@ -989,12 +1016,16 @@
 						sk->sk_family);
  		int err = 0;
 
-		if (match)
-		  err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir));
-
- 		if (match && !err)
-			xfrm_pol_hold(pol);
-		else
+		if (match) {
+			err = security_xfrm_policy_lookup(pol, fl->secid,
+					policy_to_flow_dir(dir));
+			if (!err)
+				xfrm_pol_hold(pol);
+			else if (err == -ESRCH)
+				pol = NULL;
+			else
+				pol = ERR_PTR(err);
+		} else
 			pol = NULL;
 	}
 	read_unlock_bh(&xfrm_policy_lock);
@@ -1286,8 +1317,11 @@
 	pol_dead = 0;
 	xfrm_nr = 0;
 
-	if (sk && sk->sk_policy[1])
+	if (sk && sk->sk_policy[1]) {
 		policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
+		if (IS_ERR(policy))
+			return PTR_ERR(policy);
+	}
 
 	if (!policy) {
 		/* To accelerate a bit...  */
@@ -1297,6 +1331,8 @@
 
 		policy = flow_cache_lookup(fl, dst_orig->ops->family,
 					   dir, xfrm_policy_lookup);
+		if (IS_ERR(policy))
+			return PTR_ERR(policy);
 	}
 
 	if (!policy)
@@ -1343,6 +1379,10 @@
 							    fl, family,
 							    XFRM_POLICY_OUT);
 			if (pols[1]) {
+				if (IS_ERR(pols[1])) {
+					err = PTR_ERR(pols[1]);
+					goto error;
+				}
 				if (pols[1]->action == XFRM_POLICY_BLOCK) {
 					err = -EPERM;
 					goto error;
@@ -1574,13 +1614,19 @@
 	}
 
 	pol = NULL;
-	if (sk && sk->sk_policy[dir])
+	if (sk && sk->sk_policy[dir]) {
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
+		if (IS_ERR(pol))
+			return 0;
+	}
 
 	if (!pol)
 		pol = flow_cache_lookup(&fl, family, fl_dir,
 					xfrm_policy_lookup);
 
+	if (IS_ERR(pol))
+		return 0;
+
 	if (!pol) {
 		if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
 			xfrm_secpath_reject(xerr_idx, skb, &fl);
@@ -1599,6 +1645,8 @@
 						    &fl, family,
 						    XFRM_POLICY_IN);
 		if (pols[1]) {
+			if (IS_ERR(pols[1]))
+				return 0;
 			pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec;
 			npols ++;
 		}
@@ -1706,7 +1754,7 @@
 
 static int stale_bundle(struct dst_entry *dst)
 {
-	return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
+	return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
 }
 
 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
@@ -1828,7 +1876,8 @@
  * still valid.
  */
 
-int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict)
+int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
+		struct flowi *fl, int family, int strict)
 {
 	struct dst_entry *dst = &first->u.dst;
 	struct xfrm_dst *last;
@@ -1845,7 +1894,7 @@
 
 		if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
 			return 0;
-		if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm))
+		if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
 			return 0;
 		if (dst->xfrm->km.state != XFRM_STATE_VALID)
 			return 0;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 39b8bf3..84bbf84 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -614,6 +614,14 @@
 	return x;
 }
 
+static void xfrm_hash_grow_check(int have_hash_collision)
+{
+	if (have_hash_collision &&
+	    (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
+	    xfrm_state_num > xfrm_state_hmask)
+		schedule_work(&xfrm_hash_work);
+}
+
 static void __xfrm_state_insert(struct xfrm_state *x)
 {
 	unsigned int h;
@@ -642,10 +650,7 @@
 
 	xfrm_state_num++;
 
-	if (x->bydst.next != NULL &&
-	    (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
-	    xfrm_state_num > xfrm_state_hmask)
-		schedule_work(&xfrm_hash_work);
+	xfrm_hash_grow_check(x->bydst.next != NULL);
 }
 
 /* xfrm_state_lock is held */
@@ -753,6 +758,10 @@
 		h = xfrm_src_hash(daddr, saddr, family);
 		hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
 		wake_up(&km_waitq);
+
+		xfrm_state_num++;
+
+		xfrm_hash_grow_check(x->bydst.next != NULL);
 	}
 
 	return x;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d54b3a7..2b2e59d 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1992,15 +1992,6 @@
 	xp->type = XFRM_POLICY_TYPE_MAIN;
 	copy_templates(xp, ut, nr);
 
-	if (!xp->security) {
-		int err = security_xfrm_sock_policy_alloc(xp, sk);
-		if (err) {
-			kfree(xp);
-			*dir = err;
-			return NULL;
-		}
-	}
-
 	*dir = p->dir;
 
 	return xp;
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 6a026f6..4241e0d 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -168,7 +168,7 @@
 	$(call cmd,gen)
 
 else
-$(objhdr-y) :		$(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES)
+$(objhdr-y) :		$(INSTALL_HDR_PATH)/$(_dst)/%.h: $(objtree)/$(obj)/%.h $(KBUILDFILES)
 	$(call cmd,o_hdr_install)
 
 $(header-y) :		$(INSTALL_HDR_PATH)/$(_dst)/%.h: $(srctree)/$(obj)/%.h $(KBUILDFILES)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 6c5469b..65e0a79 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -44,7 +44,7 @@
 include scripts/Makefile.lib
 
 kernelsymfile := $(objtree)/Module.symvers
-modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
+modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
 __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index 8dea47f..fd695e1 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -24,6 +24,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 
 #ifdef __sun__
 #define CURS_MACROS
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 00d1ad1..187f5de 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1262,7 +1262,9 @@
 }
 
 ##
-# generic output function for typedefs
+# generic output function for all types (function, struct/union, typedef, enum);
+# calls the generated, variable output_ function name based on
+# functype and output_mode
 sub output_declaration {
     no strict 'refs';
     my $name = shift;
@@ -1278,8 +1280,7 @@
 }
 
 ##
-# generic output function - calls the right one based
-# on current output mode.
+# generic output function - calls the right one based on current output mode.
 sub output_intro {
     no strict 'refs';
     my $func = "output_intro_".$output_mode;
@@ -1518,6 +1519,9 @@
     $prototype =~ s/^asmlinkage +//;
     $prototype =~ s/^inline +//;
     $prototype =~ s/^__inline__ +//;
+    $prototype =~ s/^__inline +//;
+    $prototype =~ s/^__always_inline +//;
+    $prototype =~ s/^noinline +//;
     $prototype =~ s/__devinit +//;
     $prototype =~ s/^#define +//; #ak added
     $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//;
@@ -1778,8 +1782,9 @@
 		$in_doc_sect = 1;
 		$contents = $newcontents;
 		if ($contents ne "") {
-		    if (substr($contents, 0, 1) eq " ") {
-			$contents = substr($contents, 1);
+		    while ((substr($contents, 0, 1) eq " ") ||
+			substr($contents, 0, 1) eq "\t") {
+			    $contents = substr($contents, 1);
 		    }
 		    $contents .= "\n";
 		}
diff --git a/security/dummy.c b/security/dummy.c
index aeee705..43874c1 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -881,7 +881,8 @@
 	return 1;
 }
 
-static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+				struct xfrm_policy *xp)
 {
 	return 1;
 }
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 81eb598..526b280 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,8 @@
 int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
 int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
 			struct xfrm_policy *xp, struct flowi *fl);
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm);
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+			struct xfrm_policy *xp);
 
 
 /*
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index cfed1d3..d539346 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -93,11 +93,15 @@
 	size_t bitmap_byte;
 	unsigned char bitmask;
 
+	if (src->highbit == 0) {
+		*dst = NULL;
+		*dst_len = 0;
+		return 0;
+	}
+
 	bitmap_len = src->highbit / 8;
 	if (src->highbit % 7)
 		bitmap_len += 1;
-	if (bitmap_len == 0)
-		return -EINVAL;
 
 	bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
 			 sizeof(MAPTYPE),
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index c713af2..2cca8e2 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -640,8 +640,13 @@
 {
 	int rc = -EPERM;
 
-	if (!selinux_mls_enabled)
+	if (!selinux_mls_enabled) {
+		*low = NULL;
+		*low_len = 0;
+		*high = NULL;
+		*high_len = 0;
 		return 0;
+	}
 
 	if (low != NULL) {
 		rc = ebitmap_export(&context->range.level[0].cat,
@@ -661,10 +666,16 @@
 	return 0;
 
 export_cat_failure:
-	if (low != NULL)
+	if (low != NULL) {
 		kfree(*low);
-	if (high != NULL)
+		*low = NULL;
+		*low_len = 0;
+	}
+	if (high != NULL) {
 		kfree(*high);
+		*high = NULL;
+		*high_len = 0;
+	}
 	return rc;
 }
 
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index b188953..ba48961 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -618,6 +618,7 @@
 			c = c->next;
 			ocontext_destroy(ctmp,i);
 		}
+		p->ocontexts[i] = NULL;
 	}
 
 	g = p->genfs;
@@ -633,6 +634,7 @@
 		g = g->next;
 		kfree(gtmp);
 	}
+	p->genfs = NULL;
 
 	cond_policydb_destroy(p);
 
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 0c219a1..b1f6fb3 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2172,7 +2172,12 @@
  */
 static void selinux_netlbl_cache_free(const void *data)
 {
-	struct netlbl_cache *cache = NETLBL_CACHE(data);
+	struct netlbl_cache *cache;
+
+	if (data == NULL)
+		return;
+
+	cache = NETLBL_CACHE(data);
 	switch (cache->type) {
 	case NETLBL_CACHE_T_MLS:
 		ebitmap_destroy(&cache->data.mls_label.level[0].cat);
@@ -2197,17 +2202,20 @@
 	struct netlbl_lsm_secattr secattr;
 
 	netlbl_secattr_init(&secattr);
+	secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
+	if (secattr.cache == NULL)
+		goto netlbl_cache_add_return;
 
 	cache = kzalloc(sizeof(*cache),	GFP_ATOMIC);
 	if (cache == NULL)
-		goto netlbl_cache_add_failure;
-	secattr.cache.free = selinux_netlbl_cache_free;
-	secattr.cache.data = (void *)cache;
+		goto netlbl_cache_add_return;
+	secattr.cache->free = selinux_netlbl_cache_free;
+	secattr.cache->data = (void *)cache;
 
 	cache->type = NETLBL_CACHE_T_MLS;
 	if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
 			&ctx->range.level[0].cat) != 0)
-		goto netlbl_cache_add_failure;
+		goto netlbl_cache_add_return;
 	cache->data.mls_label.level[1].cat.highbit =
 		cache->data.mls_label.level[0].cat.highbit;
 	cache->data.mls_label.level[1].cat.node =
@@ -2215,13 +2223,10 @@
 	cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
 	cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
 
-	if (netlbl_cache_add(skb, &secattr) != 0)
-		goto netlbl_cache_add_failure;
+	netlbl_cache_add(skb, &secattr);
 
-	return;
-
-netlbl_cache_add_failure:
-	netlbl_secattr_destroy(&secattr, 1);
+netlbl_cache_add_return:
+	netlbl_secattr_destroy(&secattr);
 }
 
 /**
@@ -2263,8 +2268,8 @@
 
 	POLICY_RDLOCK;
 
-	if (secattr->cache.data) {
-		cache = NETLBL_CACHE(secattr->cache.data);
+	if (secattr->cache) {
+		cache = NETLBL_CACHE(secattr->cache->data);
 		switch (cache->type) {
 		case NETLBL_CACHE_T_SID:
 			*sid = cache->data.sid;
@@ -2331,7 +2336,7 @@
 			selinux_netlbl_cache_add(skb, &ctx_new);
 		ebitmap_destroy(&ctx_new.range.level[0].cat);
 	} else {
-		*sid = SECINITSID_UNLABELED;
+		*sid = SECSID_NULL;
 		rc = 0;
 	}
 
@@ -2369,7 +2374,7 @@
 						   &secattr,
 						   base_sid,
 						   sid);
-	netlbl_secattr_destroy(&secattr, 0);
+	netlbl_secattr_destroy(&secattr);
 
 	return rc;
 }
@@ -2394,31 +2399,33 @@
 	if (!ss_initialized)
 		return 0;
 
+	netlbl_secattr_init(&secattr);
+
 	POLICY_RDLOCK;
 
 	ctx = sidtab_search(&sidtab, sid);
 	if (ctx == NULL)
 		goto netlbl_socket_setsid_return;
 
-	netlbl_secattr_init(&secattr);
 	secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
 				 GFP_ATOMIC);
 	mls_export_lvl(ctx, &secattr.mls_lvl, NULL);
 	secattr.mls_lvl_vld = 1;
-	mls_export_cat(ctx,
-		       &secattr.mls_cat,
-		       &secattr.mls_cat_len,
-		       NULL,
-		       NULL);
+	rc = mls_export_cat(ctx,
+			    &secattr.mls_cat,
+			    &secattr.mls_cat_len,
+			    NULL,
+			    NULL);
+	if (rc != 0)
+		goto netlbl_socket_setsid_return;
 
 	rc = netlbl_socket_setattr(sock, &secattr);
 	if (rc == 0)
 		sksec->nlbl_state = NLBL_LABELED;
 
-	netlbl_secattr_destroy(&secattr, 0);
-
 netlbl_socket_setsid_return:
 	POLICY_RDUNLOCK;
+	netlbl_secattr_destroy(&secattr);
 	return rc;
 }
 
@@ -2514,10 +2521,10 @@
 	if (netlbl_sock_getattr(sk, &secattr) == 0 &&
 	    selinux_netlbl_secattr_to_sid(NULL,
 					  &secattr,
-					  sksec->sid,
+					  SECINITSID_UNLABELED,
 					  &nlbl_peer_sid) == 0)
 		sksec->peer_sid = nlbl_peer_sid;
-	netlbl_secattr_destroy(&secattr, 0);
+	netlbl_secattr_destroy(&secattr);
 
 	sksec->nlbl_state = NLBL_REQUIRE;
 
@@ -2547,9 +2554,6 @@
 	if (rc != 0)
 		return SECSID_NULL;
 
-	if (peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
 	return peer_sid;
 }
 
@@ -2611,11 +2615,13 @@
 	u32 netlbl_sid;
 	u32 recv_perm;
 
-	rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid);
+	rc = selinux_netlbl_skbuff_getsid(skb,
+					  SECINITSID_UNLABELED,
+					  &netlbl_sid);
 	if (rc != 0)
 		return rc;
 
-	if (netlbl_sid == SECINITSID_UNLABELED)
+	if (netlbl_sid == SECSID_NULL)
 		return 0;
 
 	switch (sksec->sclass) {
@@ -2653,10 +2659,6 @@
 u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
 {
 	struct sk_security_struct *sksec = sock->sk->sk_security;
-
-	if (sksec->peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
 	return sksec->peer_sid;
 }
 
@@ -2672,16 +2674,10 @@
 u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
 {
 	int peer_sid;
-	struct sock *sk = skb->sk;
-	struct inode_security_struct *isec;
 
-	if (sk == NULL || sk->sk_socket == NULL)
-		return SECSID_NULL;
-
-	isec = SOCK_INODE(sk->sk_socket)->i_security;
-	if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
-		return SECSID_NULL;
-	if (peer_sid == SECINITSID_UNLABELED)
+	if (selinux_netlbl_skbuff_getsid(skb,
+					 SECINITSID_UNLABELED,
+					 &peer_sid) != 0)
 		return SECSID_NULL;
 
 	return peer_sid;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 3e742b8..675b995 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -77,8 +77,8 @@
  */
 int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
 {
-	int rc = 0;
-	u32 sel_sid = SECINITSID_UNLABELED;
+	int rc;
+	u32 sel_sid;
 	struct xfrm_sec_ctx *ctx;
 
 	/* Context sid is either set to label or ANY_ASSOC */
@@ -88,11 +88,21 @@
 
 		sel_sid = ctx->ctx_sid;
 	}
+	else
+		/*
+		 * All flows should be treated as polmatch'ing an
+		 * otherwise applicable "non-labeled" policy. This
+		 * would prevent inadvertent "leaks".
+		 */
+		return 0;
 
 	rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__POLMATCH,
 			  NULL);
 
+	if (rc == -EACCES)
+		rc = -ESRCH;
+
 	return rc;
 }
 
@@ -108,15 +118,20 @@
 	u32 pol_sid;
 	int err;
 
-	if (x->security)
-		state_sid = x->security->ctx_sid;
-	else
-		state_sid = SECINITSID_UNLABELED;
-
-	if (xp->security)
+	if (xp->security) {
+		if (!x->security)
+			/* unlabeled SA and labeled policy can't match */
+			return 0;
+		else
+			state_sid = x->security->ctx_sid;
 		pol_sid = xp->security->ctx_sid;
-	else
-		pol_sid = SECINITSID_UNLABELED;
+	} else
+		if (x->security)
+			/* unlabeled policy and labeled SA can't match */
+			return 0;
+		else
+			/* unlabeled policy and unlabeled SA match all flows */
+			return 1;
 
 	err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__POLMATCH,
@@ -125,7 +140,11 @@
 	if (err)
 		return 0;
 
-	return selinux_xfrm_flow_state_match(fl, x);
+	err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
+			  ASSOCIATION__SENDTO,
+			  NULL)? 0:1;
+
+	return err;
 }
 
 /*
@@ -133,12 +152,22 @@
  * can use a given security association.
  */
 
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+				  struct xfrm_policy *xp)
 {
 	int rc = 0;
 	u32 sel_sid = SECINITSID_UNLABELED;
 	struct xfrm_sec_ctx *ctx;
 
+	if (!xp->security)
+		if (!xfrm->security)
+			return 1;
+		else
+			return 0;
+	else
+		if (!xfrm->security)
+			return 0;
+
 	/* Context sid is either set to label or ANY_ASSOC */
 	if ((ctx = xfrm->security)) {
 		if (!selinux_authorizable_ctx(ctx))
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
index 7c26089..40eb47e 100644
--- a/sound/aoa/core/snd-aoa-gpio-feature.c
+++ b/sound/aoa/core/snd-aoa-gpio-feature.c
@@ -283,9 +283,7 @@
 	mutex_destroy(&rt->line_out_notify.mutex);
 }
 
-static irqreturn_t ftr_handle_notify_irq(int xx,
-					 void *data,
-					 struct pt_regs *regs)
+static irqreturn_t ftr_handle_notify_irq(int xx, void *data)
 {
 	struct gpio_notification *notif = data;
 
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
index 23190aa..e593a13 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -93,7 +93,7 @@
 	kfree(i2sdev);
 }
 
-static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t i2sbus_bus_intr(int irq, void *devid)
 {
 	struct i2sbus_dev *dev = devid;
 	u32 intreg;
@@ -165,8 +165,7 @@
 	static const char *rnames[] = { "i2sbus: %s (control)",
 					"i2sbus: %s (tx)",
 					"i2sbus: %s (rx)" };
-	static irqreturn_t (*ints[])(int irq, void *devid,
-				     struct pt_regs *regs) = {
+	static irq_handler_t ints[] = {
 		i2sbus_bus_intr,
 		i2sbus_tx_intr,
 		i2sbus_rx_intr
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
index 3049015..5eff30b 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
@@ -642,13 +642,13 @@
 	spin_unlock(&i2sdev->low_lock);
 }
 
-irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs)
+irqreturn_t i2sbus_tx_intr(int irq, void *devid)
 {
 	handle_interrupt((struct i2sbus_dev *)devid, 0);
 	return IRQ_HANDLED;
 }
 
-irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs)
+irqreturn_t i2sbus_rx_intr(int irq, void *devid)
 {
 	handle_interrupt((struct i2sbus_dev *)devid, 1);
 	return IRQ_HANDLED;
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index 0c69d20..ec20ee6 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -97,9 +97,9 @@
 extern void
 i2sbus_detach_codec(struct soundbus_dev *dev, void *data);
 extern irqreturn_t
-i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs);
+i2sbus_tx_intr(int irq, void *devid);
 extern irqreturn_t
-i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs);
+i2sbus_rx_intr(int irq, void *devid);
 
 /* control specific functions */
 extern int i2sbus_control_init(struct macio_dev* dev,
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 8435fdd..53675cf 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -221,7 +221,7 @@
 	}
 }
 
-static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t aaci_irq(int irq, void *devid)
 {
 	struct aaci *aaci = devid;
 	u32 mask;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 599aff8..dede954 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -152,7 +152,7 @@
 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
 }
 
-static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
 {
 	long status;
 
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 4938ef1..e8cf904 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -137,7 +137,7 @@
 	return ret;
 }
 
-static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id, struct pt_regs *regs)
+static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
 {
 	struct snd_pcm_substream *substream = dev_id;
 	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
diff --git a/sound/core/control.c b/sound/core/control.c
index 6973a96..48ef0a0 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1018,10 +1018,6 @@
 	}
 	switch (info->type) {
 	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
-		private_size = sizeof(char);
-		if (info->count > 128)
-			return -EINVAL;
-		break;
 	case SNDRV_CTL_ELEM_TYPE_INTEGER:
 		private_size = sizeof(long);
 		if (info->count > 128)
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 9aa9d94..46b4768 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -158,6 +158,7 @@
 {
 	int err = -ENXIO;
 	struct snd_hwdep *hw = file->private_data;
+	struct module *mod = hw->card->module;
 	mutex_lock(&hw->open_mutex);
 	if (hw->ops.release) {
 		err = hw->ops.release(hw, file);
@@ -167,7 +168,7 @@
 		hw->used--;
 	snd_card_file_remove(hw->card, file);
 	mutex_unlock(&hw->open_mutex);
-	module_put(hw->card->module);
+	module_put(mod);
 	return err;
 }
 
diff --git a/sound/core/hwdep_compat.c b/sound/core/hwdep_compat.c
index 938f775..3827c0c 100644
--- a/sound/core/hwdep_compat.c
+++ b/sound/core/hwdep_compat.c
@@ -33,7 +33,7 @@
 static int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw,
 				     struct snd_hwdep_dsp_image32 __user *src)
 {
-	struct snd_hwdep_dsp_image *dst;
+	struct snd_hwdep_dsp_image __user *dst;
 	compat_caddr_t ptr;
 	u32 val;
 
diff --git a/sound/core/info.c b/sound/core/info.c
index e43662b..0b4aab3 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -120,7 +120,10 @@
 	len = buffer->len - buffer->size;
 	va_start(args, fmt);
 	for (;;) {
-		res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args);
+		va_list ap;
+		va_copy(ap, args);
+		res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap);
+		va_end(ap);
 		if (res < len)
 			break;
 		err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE);
diff --git a/sound/core/init.c b/sound/core/init.c
index d7607a2..3058d62 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -33,10 +33,10 @@
 #include <sound/control.h>
 #include <sound/info.h>
 
-struct snd_shutdown_f_ops {
-	struct file_operations f_ops;
-	struct snd_shutdown_f_ops *next;
-};
+static DEFINE_SPINLOCK(shutdown_lock);
+static LIST_HEAD(shutdown_files);
+
+static struct file_operations snd_shutdown_f_ops;
 
 static unsigned int snd_cards_lock;	/* locked for registering/using */
 struct snd_card *snd_cards[SNDRV_CARDS];
@@ -198,6 +198,25 @@
 	return -ENODEV;
 }
 
+static int snd_disconnect_release(struct inode *inode, struct file *file)
+{
+	struct snd_monitor_file *df = NULL, *_df;
+
+	spin_lock(&shutdown_lock);
+	list_for_each_entry(_df, &shutdown_files, shutdown_list) {
+		if (_df->file == file) {
+			df = _df;
+			break;
+		}
+	}
+	spin_unlock(&shutdown_lock);
+
+	if (likely(df))
+		return df->disconnected_f_op->release(inode, file);
+
+	panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
+}
+
 static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
 {
 	return POLLERR | POLLNVAL;
@@ -219,6 +238,22 @@
 	return -ENODEV;
 }
 
+static struct file_operations snd_shutdown_f_ops =
+{
+	.owner = 	THIS_MODULE,
+	.llseek =	snd_disconnect_llseek,
+	.read = 	snd_disconnect_read,
+	.write =	snd_disconnect_write,
+	.release =	snd_disconnect_release,
+	.poll =		snd_disconnect_poll,
+	.unlocked_ioctl = snd_disconnect_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = snd_disconnect_ioctl,
+#endif
+	.mmap =		snd_disconnect_mmap,
+	.fasync =	snd_disconnect_fasync
+};
+
 /**
  *  snd_card_disconnect - disconnect all APIs from the file-operations (user space)
  *  @card: soundcard structure
@@ -234,9 +269,6 @@
 {
 	struct snd_monitor_file *mfile;
 	struct file *file;
-	struct snd_shutdown_f_ops *s_f_ops;
-	struct file_operations *f_ops;
-	const struct file_operations *old_f_ops;
 	int err;
 
 	spin_lock(&card->files_lock);
@@ -261,34 +293,14 @@
 
 		/* it's critical part, use endless loop */
 		/* we have no room to fail */
-		s_f_ops = kmalloc(sizeof(struct snd_shutdown_f_ops), GFP_ATOMIC);
-		if (s_f_ops == NULL)
-			panic("Atomic allocation failed for snd_shutdown_f_ops!");
+		mfile->disconnected_f_op = mfile->file->f_op;
 
-		f_ops = &s_f_ops->f_ops;
+		spin_lock(&shutdown_lock);
+		list_add(&mfile->shutdown_list, &shutdown_files);
+		spin_unlock(&shutdown_lock);
 
-		memset(f_ops, 0, sizeof(*f_ops));
-		f_ops->owner = file->f_op->owner;
-		f_ops->release = file->f_op->release;
-		f_ops->llseek = snd_disconnect_llseek;
-		f_ops->read = snd_disconnect_read;
-		f_ops->write = snd_disconnect_write;
-		f_ops->poll = snd_disconnect_poll;
-		f_ops->unlocked_ioctl = snd_disconnect_ioctl;
-#ifdef CONFIG_COMPAT
-		f_ops->compat_ioctl = snd_disconnect_ioctl;
-#endif
-		f_ops->mmap = snd_disconnect_mmap;
-		f_ops->fasync = snd_disconnect_fasync;
-
-		s_f_ops->next = card->s_f_ops;
-		card->s_f_ops = s_f_ops;
-		
-		f_ops = fops_get(f_ops);
-
-		old_f_ops = file->f_op;
-		file->f_op = f_ops;	/* must be atomic */
-		fops_put(old_f_ops);
+		fops_get(&snd_shutdown_f_ops);
+		mfile->file->f_op = &snd_shutdown_f_ops;
 		
 		mfile = mfile->next;
 	}
@@ -326,8 +338,6 @@
  */
 static int snd_card_do_free(struct snd_card *card)
 {
-	struct snd_shutdown_f_ops *s_f_ops;
-
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
 	if (snd_mixer_oss_notify_callback)
 		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -351,11 +361,6 @@
 		snd_printk(KERN_WARNING "unable to free card info\n");
 		/* Not fatal error */
 	}
-	while (card->s_f_ops) {
-		s_f_ops = card->s_f_ops;
-		card->s_f_ops = s_f_ops->next;
-		kfree(s_f_ops);
-	}
 	kfree(card);
 	return 0;
 }
@@ -670,6 +675,7 @@
 	if (mfile == NULL)
 		return -ENOMEM;
 	mfile->file = file;
+	mfile->disconnected_f_op = NULL;
 	mfile->next = NULL;
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
@@ -716,6 +722,12 @@
 		pfile = mfile;
 		mfile = mfile->next;
 	}
+	if (mfile && mfile->disconnected_f_op) {
+		fops_put(mfile->disconnected_f_op);
+		spin_lock(&shutdown_lock);
+		list_del(&mfile->shutdown_list);
+		spin_unlock(&shutdown_lock);
+	}
 	if (card->files == NULL)
 		last_close = 1;
 	spin_unlock(&card->files_lock);
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 4bf07ca..3daa9fa 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -125,12 +125,10 @@
  * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
  * @irq: the irq number
  * @dev_id: mpu401 instance
- * @regs: the reigster
  *
  * Processes the interrupt for MPU401-UART i/o.
  */
-irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id)
 {
 	struct snd_mpu401 *mpu = dev_id;
 	
@@ -146,12 +144,10 @@
  * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler
  * @irq: the irq number
  * @dev_id: mpu401 instance
- * @regs: the reigster
  *
  * Processes the interrupt for MPU401-UART output.
  */
-irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id,
-					 struct pt_regs *regs)
+irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id)
 {
 	struct snd_mpu401 *mpu = dev_id;
 	
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index e064d6c..a9ff391 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -570,7 +570,7 @@
 	} while (sbyt & SIGS_BYTE);
 }
 
-static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
 {
 	struct mtpav *mcard = dev_id;
 
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index ab8d4ef..5327c6f 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -838,7 +838,7 @@
 /*********************************************************************
  * parport stuff
  *********************************************************************/
-static void snd_mts64_interrupt(int irq, void *private, struct pt_regs *r)
+static void snd_mts64_interrupt(int irq, void *private)
 {
 	struct mts64 *mts = ((struct snd_card*)private)->private_data;
 	u16 ret;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 52afb4b..74028b2 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -292,7 +292,7 @@
  * Note that some devices need OUT2 to be set before they will generate
  * interrupts at all. (Possibly tied to an internal pull-up on CTS?)
  */
-static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id)
 {
 	snd_uart16550_t *uart;
 
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index a601682..ed19bc1 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -537,7 +537,7 @@
 /**
  * snd_vx_irq_handler - interrupt handler
  */
-irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t snd_vx_irq_handler(int irq, void *dev)
 {
 	struct vx_core *chip = dev;
 
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 557c4de..57371f1 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -13,6 +13,7 @@
 
 config SND_ADLIB
 	tristate "AdLib FM card"
+	depends on SND
 	select SND_OPL3_LIB
 	help
 	  Say Y here to include support for AdLib FM cards.
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index b33a5fb..5903450 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -120,6 +120,8 @@
 	struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
 	int err;
 
+	if (!cfg)
+		return -ENOMEM;
 	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
 	if (acard->dev == NULL) {
 		kfree(cfg);
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index fd9b61e..b524e0d 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -315,7 +315,7 @@
 }
 
 
-static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id)
 {
 	struct snd_ad1816a *chip = dev_id;
 	unsigned char status;
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index a6fbd5d..666b3bc 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -583,7 +583,7 @@
 	return 0;
 }
 
-static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
 {
 	struct snd_ad1848 *chip = dev_id;
 
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 3c1e9fd..d1f6dfc 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -289,6 +289,8 @@
 	struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
 	int err;
 
+	if (!cfg)
+		return -ENOMEM;
 	acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL);
 	if (acard->cap == NULL) {
 		kfree(cfg);
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index fbb2017..75c7c5f 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -920,7 +920,7 @@
 		chip->capture_substream->runtime->overrange++;
 }
 
-irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id)
 {
 	struct snd_cs4231 *chip = dev_id;
 	unsigned char status;
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 7e985d3..a2ab99f 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -479,7 +479,7 @@
 	return snd_es1688_trigger(chip, cmd, 0x0f);
 }
 
-static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id)
 {
 	struct snd_es1688 *chip = dev_id;
 
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 8581820..725c115 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -754,7 +754,7 @@
 		return snd_es18xx_playback2_trigger(chip, substream, cmd);
 }
 
-static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
 {
 	struct snd_es18xx *chip = dev_id;
 	unsigned char status;
@@ -799,7 +799,7 @@
 
 	/* MPU */
 	if ((status & MPU_IRQ) && chip->rmidi)
-		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 
 	/* Hardware volume */
 	if (status & HWV_IRQ) {
@@ -2154,6 +2154,7 @@
 	}
 	/* Control port initialization */
 	if (pnp_activate_dev(acard->devc) < 0) {
+		kfree(cfg);
 		snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
 		return -EAGAIN;
 	}
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index 42db375..537d3cf 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -30,7 +30,7 @@
 #define STAT_ADD(x)	while (0) { ; }
 #endif
 
-irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t snd_gus_interrupt(int irq, void *dev_id)
 {
 	struct snd_gus_card * gus = dev_id;
 	unsigned char status;
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index ac11cae..c1c69e3 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -105,9 +105,9 @@
 	return 0;
 }
 
-static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
 {
-	struct snd_gusmax *maxcard = (struct snd_gusmax *) dev_id;
+	struct snd_gusmax *maxcard = dev_id;
 	int loop, max = 5;
 	int handled = 0;
 
@@ -115,12 +115,12 @@
 		loop = 0;
 		if (inb(maxcard->gus_status_reg)) {
 			handled = 1;
-			snd_gus_interrupt(irq, maxcard->gus, regs);
+			snd_gus_interrupt(irq, maxcard->gus);
 			loop++;
 		}
 		if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
 			handled = 1;
-			snd_cs4231_interrupt(irq, maxcard->cs4231, regs);
+			snd_cs4231_interrupt(irq, maxcard->cs4231);
 			loop++;
 		}
 	} while (loop && --max > 0);
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index ea69f25..4ec2d79 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -299,9 +299,9 @@
 	return -ENODEV;
 }
 
-static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id)
 {
-	struct snd_interwave *iwcard = (struct snd_interwave *) dev_id;
+	struct snd_interwave *iwcard = dev_id;
 	int loop, max = 5;
 	int handled = 0;
 
@@ -309,12 +309,12 @@
 		loop = 0;
 		if (inb(iwcard->gus_status_reg)) {
 			handled = 1;
-			snd_gus_interrupt(irq, iwcard->gus, regs);
+			snd_gus_interrupt(irq, iwcard->gus);
 			loop++;
 		}
 		if (inb(iwcard->pcm_status_reg) & 0x01) {	/* IRQ bit is set? */
 			handled = 1;
-			snd_cs4231_interrupt(irq, iwcard->cs4231, regs);
+			snd_cs4231_interrupt(irq, iwcard->cs4231);
 			loop++;
 		}
 	} while (loop && --max > 0);
@@ -564,6 +564,8 @@
 	struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
 	int err;
 
+	if (!cfg)
+		return -ENOMEM;
 	iwcard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
 	if (iwcard->dev == NULL) {
 		kfree(cfg);
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index da92bf6..419b4eb 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -294,7 +294,7 @@
 	return 0;
 }
 
-static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
 {
 	unsigned short status;
 	struct snd_opl3sa2 *chip = dev_id;
@@ -312,12 +312,12 @@
 
 	if ((status & 0x10) && chip->rmidi != NULL) {
 		handled = 1;
-		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 	}
 
 	if (status & 0x07) {	/* TI,CI,PI */
 		handled = 1;
-		snd_cs4231_interrupt(irq, chip->cs4231, regs);
+		snd_cs4231_interrupt(irq, chip->cs4231);
 	}
 
 	if (status & 0x40) { /* hardware volume change */
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 9d528ae..df22737 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -1090,7 +1090,7 @@
 	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
-static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 {
 	struct snd_opti93x *codec = dev_id;
 	unsigned char status;
@@ -1683,6 +1683,8 @@
 	struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
 	int err;
 
+	if (!cfg)
+		return -ENOMEM;
 	chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
 	if (chip->dev == NULL) {
 		kfree(cfg);
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
index d4d65b8..d4b2187 100644
--- a/sound/isa/sb/es968.c
+++ b/sound/isa/sb/es968.c
@@ -70,8 +70,7 @@
 
 #define	DRIVER_NAME	"snd-card-es968"
 
-static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id,
-					    struct pt_regs *regs)
+static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id)
 {
 	struct snd_sb *chip = dev_id;
 
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index f183f18..383911b 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -395,7 +395,7 @@
 	return result;
 }
 
-irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id)
 {
 	struct snd_sb *chip = dev_id;
 	unsigned char status;
@@ -405,7 +405,7 @@
 	status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS);
 	spin_unlock(&chip->mixer_lock);
 	if ((status & SB_IRQTYPE_MPUIN) && chip->rmidi_callback)
-		chip->rmidi_callback(irq, chip->rmidi->private_data, regs);
+		chip->rmidi_callback(irq, chip->rmidi->private_data);
 	if (status & SB_IRQTYPE_8BIT) {
 		ok = 0;
 		if (chip->mode & SB_MODE_PLAYBACK_8) {
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 141400c..268ebd3 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -63,7 +63,7 @@
 	struct snd_sb *chip;
 };
 
-static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
 {
 	struct snd_sb *chip = dev_id;
 
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index f17de2b..c62a9e3 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -205,7 +205,7 @@
 int snd_sbdsp_create(struct snd_card *card,
 		     unsigned long port,
 		     int irq,
-		     irqreturn_t (*irq_handler)(int, void *, struct pt_regs *),
+		     irq_handler_t irq_handler,
 		     int dma8,
 		     int dma16,
 		     unsigned short hardware,
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 8742fa5..4fcd0f4 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -109,7 +109,7 @@
 	return 0;
 }
 
-static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
 {
 	return IRQ_NONE;
 }
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index a8f8d2f..85db535 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -263,9 +263,7 @@
 
 #endif /* CONFIG_PNP */
 
-static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, 
-					    void *dev_id, 
-					    struct pt_regs *regs)
+static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, void *dev_id)
 {
 	snd_wavefront_card_t *acard;
 
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index ff6e6fc..8a61a11 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -220,7 +220,7 @@
 }
 
 static irqreturn_t
-au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+au1000_dma_interrupt(int irq, void *dev_id)
 {
 	struct audio_stream *stream = (struct audio_stream *) dev_id;
 	struct snd_pcm_substream *substream = stream->substream;
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c
index 2905783..caabf31 100644
--- a/sound/oss/ad1816.c
+++ b/sound/oss/ad1816.c
@@ -521,7 +521,7 @@
 /* Interrupt handler */
 
 
-static irqreturn_t ad1816_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
+static irqreturn_t ad1816_interrupt (int irq, void *dev_id)
 {
 	unsigned char	status;
 	ad1816_info	*devc = (ad1816_info *)dev_id;
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 257b753..0ffa997 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -195,7 +195,7 @@
 static void     ad1848_halt_input(int dev);
 static void     ad1848_halt_output(int dev);
 static void     ad1848_trigger(int dev, int bits);
-static irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy);
+static irqreturn_t adintr(int irq, void *dev_id);
 
 #ifndef EXCLUDE_TIMERS
 static int ad1848_tmr_install(int dev);
@@ -2196,7 +2196,7 @@
 		printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base);
 }
 
-static irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy)
+static irqreturn_t adintr(int irq, void *dev_id)
 {
 	unsigned char status;
 	ad1848_info *devc;
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index f56f870..09263d7 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -929,7 +929,7 @@
 };
 MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
 
-static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ad1889_interrupt(int irq, void *dev_id)
 {
 	u32 stat;
 	ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
index 324a81f..6ad3841 100644
--- a/sound/oss/btaudio.c
+++ b/sound/oss/btaudio.c
@@ -824,7 +824,7 @@
 			    "RISCI", "FBUS", "FTRGT", "FDSR", "PPERR",
 			    "RIPERR", "PABORT", "OCERR", "SCERR" };
 
-static irqreturn_t btaudio_irq(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t btaudio_irq(int irq, void *dev_id)
 {
 	int count = 0;
 	u32 stat,astat;
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index 4319358..6e3c41f 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -1613,7 +1613,7 @@
                 wake_up(&card->midi.owait);
 }
 
-static irqreturn_t cs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cs_interrupt(int irq, void *dev_id)
 {
 	struct cs_card *card = (struct cs_card *)dev_id;
 	/* Single channel card */
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index dc31373..285239d 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -133,7 +133,7 @@
 static int FalconSetVolume(int volume);
 static void AtaPlayNextFrame(int index);
 static void AtaPlay(void);
-static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t AtaInterrupt(int irq, void *dummy);
 
 /*** Mid level stuff *********************************************************/
 
@@ -1257,7 +1257,7 @@
 }
 
 
-static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t AtaInterrupt(int irq, void *dummy)
 {
 #if 0
 	/* ++TeSche: if you should want to test this... */
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 9ae659f..37773b1 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -281,9 +281,9 @@
 static int PMacSetVolume(int volume);
 static void PMacPlay(void);
 static void PMacRecord(void);
-static irqreturn_t pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs);
-static irqreturn_t pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs);
-static irqreturn_t pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs);
+static irqreturn_t pmac_awacs_tx_intr(int irq, void *devid);
+static irqreturn_t pmac_awacs_rx_intr(int irq, void *devid);
+static irqreturn_t pmac_awacs_intr(int irq, void *devid);
 static void awacs_write(int val);
 static int awacs_get_volume(int reg, int lshift);
 static int awacs_volume_setter(int volume, int n, int mute, int lshift);
@@ -398,7 +398,7 @@
  * Headphone interrupt via GPIO (Tumbler, Snapper, DACA)
  */
 static irqreturn_t
-headphone_intr(int irq, void *devid, struct pt_regs *regs)
+headphone_intr(int irq, void *devid)
 {
 	unsigned long flags;
 
@@ -465,7 +465,7 @@
 			val = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_headphone_detect, 0);
 			pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio_headphone_detect, val | 0x80);
 			/* Trigger it */
-  			headphone_intr(0,NULL,NULL);
+  			headphone_intr(0, NULL);
   		}
   	}
   	if (!gpio_headphone_irq) {
@@ -1037,7 +1037,7 @@
 */
 
 static irqreturn_t
-pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs)
+pmac_awacs_tx_intr(int irq, void *devid)
 {
 	int i = write_sq.front;
 	int stat;
@@ -1129,7 +1129,7 @@
 
 
 static irqreturn_t
-pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs)
+pmac_awacs_rx_intr(int irq, void *devid)
 {
 	int stat ;
 	/* For some reason on my PowerBook G3, I get one interrupt
@@ -1212,7 +1212,7 @@
 
 
 static irqreturn_t
-pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs)
+pmac_awacs_intr(int irq, void *devid)
 {
 	int ctrl;
 	int status;
@@ -1499,7 +1499,7 @@
 				write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol);
 				msleep(150);
 				tas_leave_sleep(); /* Stub for now */
-				headphone_intr(0,NULL,NULL);
+				headphone_intr(0, NULL);
 				break;
 			case AWACS_DACA:
 				msleep(10); /* Check this !!! */
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index 68e1d8f..90fc058 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -82,7 +82,7 @@
 static int AmiSetTreble(int treble);
 static void AmiPlayNextFrame(int index);
 static void AmiPlay(void);
-static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t AmiInterrupt(int irq, void *dummy);
 
 #ifdef CONFIG_HEARTBEAT
 
@@ -556,7 +556,7 @@
 }
 
 
-static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t AmiInterrupt(int irq, void *dummy)
 {
 	int minframes = 1;
 
diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c
index e2081f3..b3379dd 100644
--- a/sound/oss/dmasound/dmasound_q40.c
+++ b/sound/oss/dmasound/dmasound_q40.c
@@ -48,8 +48,8 @@
 static int Q40SetVolume(int volume);
 static void Q40PlayNextFrame(int index);
 static void Q40Play(void);
-static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp);
-static irqreturn_t Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t Q40StereoInterrupt(int irq, void *dummy);
+static irqreturn_t Q40MonoInterrupt(int irq, void *dummy);
 static void Q40Interrupt(void);
 
 
@@ -451,7 +451,7 @@
 	spin_unlock_irqrestore(&dmasound.lock, flags);
 }
 
-static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t Q40StereoInterrupt(int irq, void *dummy)
 {
 	spin_lock(&dmasound.lock);
         if (q40_sc>1){
@@ -463,7 +463,7 @@
 	spin_unlock(&dmasound.lock);
 	return IRQ_HANDLED;
 }
-static irqreturn_t Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t Q40MonoInterrupt(int irq, void *dummy)
 {
 	spin_lock(&dmasound.lock);
         if (q40_sc>0){
diff --git a/sound/oss/emu10k1/irqmgr.c b/sound/oss/emu10k1/irqmgr.c
index d19b464..fb2ce63 100644
--- a/sound/oss/emu10k1/irqmgr.c
+++ b/sound/oss/emu10k1/irqmgr.c
@@ -37,7 +37,7 @@
 
 /* Interrupt handler */
 
-irqreturn_t emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t emu10k1_interrupt(int irq, void *dev_id)
 {
 	struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
 	u32 irqstatus, irqstatus_tmp;
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index c4ce94d..6c59df7 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -167,7 +167,7 @@
 static struct midi_operations emu10k1_midi_operations;
 #endif
 
-extern irqreturn_t emu10k1_interrupt(int, void *, struct pt_regs *s);
+extern irqreturn_t emu10k1_interrupt(int, void *);
 
 static int __devinit emu10k1_audio_init(struct emu10k1_card *card)
 {
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index a2ffe72..ddf6b0a 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -1100,9 +1100,9 @@
 	outb((s->midi.ocnt > 0) ? UCTRL_RXINTEN | UCTRL_ENA_TXINT : UCTRL_RXINTEN, s->io+ES1371_REG_UART_CONTROL);
 }
 
-static irqreturn_t es1371_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t es1371_interrupt(int irq, void *dev_id)
 {
-        struct es1371_state *s = (struct es1371_state *)dev_id;
+        struct es1371_state *s = dev_id;
 	unsigned int intsrc, sctl;
 	
 	/* fastpath out, to ease interrupt sharing */
diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c
index 80ab402..784bdd7 100644
--- a/sound/oss/hal2.c
+++ b/sound/oss/hal2.c
@@ -370,9 +370,9 @@
 	wake_up(&adc->dma_wait);
 }
 
-static irqreturn_t hal2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hal2_interrupt(int irq, void *dev_id)
 {
-	struct hal2_card *hal2 = (struct hal2_card*)dev_id;
+	struct hal2_card *hal2 = dev_id;
 	irqreturn_t ret = IRQ_NONE;
 
 	/* decide what caused this interrupt */
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index ddcddc2..240cc79 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -1523,9 +1523,9 @@
 #endif
 }
 
-static irqreturn_t i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i810_interrupt(int irq, void *dev_id)
 {
-	struct i810_card *card = (struct i810_card *)dev_id;
+	struct i810_card *card = dev_id;
 	u32 status;
 
 	spin_lock(&card->lock);
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 162d07c..e962205 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -432,10 +432,10 @@
 	devc->m_busy = 0;
 }
 
-static irqreturn_t mpuintr(int irq, void *dev_id, struct pt_regs *dummy)
+static irqreturn_t mpuintr(int irq, void *dev_id)
 {
 	struct mpu_config *devc;
-	int dev = (int) dev_id;
+	int dev = (int)(unsigned long) dev_id;
 	int handled = 0;
 
 	devc = &dev_conf[dev];
diff --git a/sound/oss/mpu401.h b/sound/oss/mpu401.h
index 84c0e95..0ad1e9e 100644
--- a/sound/oss/mpu401.h
+++ b/sound/oss/mpu401.h
@@ -3,10 +3,9 @@
 int probe_uart401 (struct address_info *hw_config, struct module *owner);
 void unload_uart401 (struct address_info *hw_config);
 
-irqreturn_t uart401intr (int irq, void *dev_id, struct pt_regs * dummy);
+irqreturn_t uart401intr (int irq, void *dev_id);
 
 /*	From mpu401.c */
 int probe_mpu401(struct address_info *hw_config, struct resource *ports);
 int attach_mpu401(struct address_info * hw_config, struct module *owner);
 void unload_mpu401(struct address_info *hw_info);
-
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 6d7763d..d514679 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1087,7 +1087,7 @@
 	}
 }
 
-static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t intr(int irq, void *dev_id)
 {
 	/* Send ack to DSP */
 	msnd_inb(dev.io + HP_RXL);
diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c
index 6f7f2f0..da9728e 100644
--- a/sound/oss/nec_vrc5477.c
+++ b/sound/oss/nec_vrc5477.c
@@ -848,7 +848,7 @@
 		wake_up_interruptible(&dac->wait);
 }
 
-static irqreturn_t vrc5477_ac97_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t vrc5477_ac97_interrupt(int irq, void *dev_id)
 {
 	struct vrc5477_ac97_state *s = (struct vrc5477_ac97_state *)dev_id;
 	u32 irqStatus;
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h
index 21e07b5..1dade90 100644
--- a/sound/oss/nm256.h
+++ b/sound/oss/nm256.h
@@ -115,7 +115,7 @@
     int has_irq;
 
     /* The card interrupt service routine. */
-    irqreturn_t (*introutine) (int, void *, struct pt_regs *);
+    irq_handler_t introutine;
 
     /* Current audio config, cached. */
     struct sinfo {
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
index 7760ddd..44cd155 100644
--- a/sound/oss/nm256_audio.c
+++ b/sound/oss/nm256_audio.c
@@ -45,8 +45,8 @@
 
 static int nm256_grabInterrupt (struct nm256_info *card);
 static int nm256_releaseInterrupt (struct nm256_info *card);
-static irqreturn_t nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy);
-static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy);
+static irqreturn_t nm256_interrupt (int irq, void *dev_id);
+static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id);
 
 /* These belong in linux/pci.h. */
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
@@ -526,7 +526,7 @@
  */
 
 static irqreturn_t
-nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
+nm256_interrupt (int irq, void *dev_id)
 {
     struct nm256_info *card = (struct nm256_info *)dev_id;
     u16 status;
@@ -629,7 +629,7 @@
  */
 
 static irqreturn_t
-nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy)
+nm256_interrupt_zx (int irq, void *dev_id)
 {
     struct nm256_info *card = (struct nm256_info *)dev_id;
     u32 status;
diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c
index 4ebb963..25f3a22 100644
--- a/sound/oss/pas2_card.c
+++ b/sound/oss/pas2_card.c
@@ -88,7 +88,7 @@
 
 /******************* Begin of the Interrupt Handler ********************/
 
-static irqreturn_t pasintr(int irq, void *dev_id, struct pt_regs *dummy)
+static irqreturn_t pasintr(int irq, void *dev_id)
 {
 	int             status;
 
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index bbe5b75..440537c 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -132,7 +132,7 @@
 
 		if (src & 4)						/* MPU401 interrupt */
 			if(devc->midi_irq_cookie)
-				uart401intr(devc->irq, devc->midi_irq_cookie, NULL);
+				uart401intr(devc->irq, devc->midi_irq_cookie);
 
 		if (!(src & 3))
 			return;	/* Not a DSP interrupt */
@@ -200,7 +200,7 @@
 		sb_intr(devc);
 }
 
-static irqreturn_t sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+static irqreturn_t sbintr(int irq, void *dev_id)
 {
 	sb_devc *devc = dev_id;
 
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index 83ff8a7..51f5541 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -26,7 +26,7 @@
 #include <asm/cpu/dac.h>
 #include <asm/cpu/timer.h>
 #include <asm/machvec.h>
-#include <asm/hp6xx/hp6xx.h>
+#include <asm/hp6xx.h>
 #include <asm/hd64461.h>
 
 #define MODNAME "sh_dac_audio"
@@ -263,7 +263,7 @@
       .release =	dac_audio_release,
 };
 
-static irqreturn_t timer1_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t timer1_interrupt(int irq, void *dev)
 {
 	unsigned long timer_status;
 
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index 3edf8d4..471c274 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -2505,7 +2505,7 @@
 	.release	= cs4297a_release,
 };
 
-static void cs4297a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void cs4297a_interrupt(int irq, void *dev_id)
 {
 	struct cs4297a_state *s = (struct cs4297a_state *) dev_id;
         u32 status;
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 147c816..7a363a1 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -1811,7 +1811,7 @@
 }
 
 static irqreturn_t
-trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+trident_interrupt(int irq, void *dev_id)
 {
 	struct trident_card *card = (struct trident_card *) dev_id;
 	u32 event;
diff --git a/sound/oss/uart401.c b/sound/oss/uart401.c
index 8e18b6e..a446b82 100644
--- a/sound/oss/uart401.c
+++ b/sound/oss/uart401.c
@@ -96,7 +96,7 @@
 		printk(KERN_WARNING "Too much work in interrupt on uart401 (0x%X). UART jabbering ??\n", devc->base);
 }
 
-irqreturn_t uart401intr(int irq, void *dev_id, struct pt_regs *dummy)
+irqreturn_t uart401intr(int irq, void *dev_id)
 {
 	uart401_devc *devc = dev_id;
 
diff --git a/sound/oss/uart6850.c b/sound/oss/uart6850.c
index 501d3e6..f3f914a 100644
--- a/sound/oss/uart6850.c
+++ b/sound/oss/uart6850.c
@@ -104,7 +104,7 @@
 	}
 }
 
-static irqreturn_t m6850intr(int irq, void *dev_id, struct pt_regs *dummy)
+static irqreturn_t m6850intr(int irq, void *dev_id)
 {
 	if (input_avail())
 		uart6850_input_loop();
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
index 2fec42f..17837d4 100644
--- a/sound/oss/via82cxxx_audio.c
+++ b/sound/oss/via82cxxx_audio.c
@@ -1912,7 +1912,7 @@
 }
 
 
-static irqreturn_t  via_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t  via_interrupt(int irq, void *dev_id)
 {
 	struct via_info *card = dev_id;
 	u32 status32;
@@ -1927,7 +1927,7 @@
         {
 #ifdef CONFIG_MIDI_VIA82CXXX
 	    	 if (card->midi_devc)
-                    	uart401intr(irq, card->midi_devc, regs);
+                    	uart401intr(irq, card->midi_devc);
 #endif
 		return IRQ_HANDLED;
     	}
@@ -1950,7 +1950,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t via_new_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t via_new_interrupt(int irq, void *dev_id)
 {
 	struct via_info *card = dev_id;
 	u32 status32;
diff --git a/sound/oss/vidc.c b/sound/oss/vidc.c
index 8932d89..bb4a096 100644
--- a/sound/oss/vidc.c
+++ b/sound/oss/vidc.c
@@ -372,7 +372,7 @@
 			adev->flags |= DMA_ACTIVE;
 
 			dma_interrupt = vidc_audio_dma_interrupt;
-			vidc_sound_dma_irq(0, NULL, NULL);
+			vidc_sound_dma_irq(0, NULL);
 			iomd_writeb(DMA_CR_E | 0x10, IOMD_SD0CR);
 
 			local_irq_restore(flags);
diff --git a/sound/oss/vidc.h b/sound/oss/vidc.h
index d5b8064..0d14247 100644
--- a/sound/oss/vidc.h
+++ b/sound/oss/vidc.h
@@ -33,7 +33,7 @@
  * DMA Interrupt handler
  */
 
-extern irqreturn_t vidc_sound_dma_irq(int irqnr, void *ref, struct pt_regs *regs);
+extern irqreturn_t vidc_sound_dma_irq(int irqnr, void *ref);
 
 /*
  * Filler routine pointer
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index 5f140c7..6dfb9f4 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -2233,12 +2233,12 @@
 		pcm_output(devc, underflown, 0);
 }
 
-static irqreturn_t vwsnd_audio_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t vwsnd_audio_intr(int irq, void *dev_id)
 {
-	vwsnd_dev_t *devc = (vwsnd_dev_t *) dev_id;
+	vwsnd_dev_t *devc = dev_id;
 	unsigned int status;
 
-	DBGEV("(irq=%d, dev_id=0x%p, regs=0x%p)\n", irq, dev_id, regs);
+	DBGEV("(irq=%d, dev_id=0x%p)\n", irq, dev_id);
 
 	status = li_get_clear_intr_status(&devc->lith);
 	vwsnd_audio_read_intr(devc, status);
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index 59a2f28..c5bf363 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -833,7 +833,7 @@
 
 
 static irqreturn_t
-waveartist_intr(int irq, void *dev_id, struct pt_regs *regs)
+waveartist_intr(int irq, void *dev_id)
 {
 	wavnc_info *devc = (wavnc_info *)dev_id;
 	int	   irqstatus, status;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index ce73f3ea..cf60333 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -193,7 +193,7 @@
 }
 
 static irqreturn_t
-snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
+snd_harmony_interrupt(int irq, void *dev)
 {
 	u32 dstatus;
 	struct snd_harmony *h = dev;
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index a79e918..6577b23 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -570,8 +570,7 @@
 			ac97->power_up &= ~(1 << (reg>>1));
 		else
 			ac97->power_up |= 1 << (reg>>1);
-		if (power_save)
-			update_power_regs(ac97);
+		update_power_regs(ac97);
 	}
 #endif
 	return err;
@@ -2337,10 +2336,7 @@
 		}
 	}
 
-	if (! power_save)
-		return 0;
-
-	if (! powerup && ac97->power_workq)
+	if (power_save && !powerup && ac97->power_workq)
 		/* adjust power-down bits after two seconds delay
 		 * (for avoiding loud click noises for many (OSS) apps
 		 *  that open/close frequently)
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index dc28b11..15be6ba 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -530,7 +530,7 @@
 AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
 
 AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
-AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
+AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
 AC97_ENUM("Out3 Mux", wm9711_enum[2]),
 AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
 AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
@@ -575,13 +575,14 @@
 
 AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
 AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
-AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 1),
+AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
 AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
 
 AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
 AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
 AC97_ENUM("Mic Select Source", wm9711_enum[7]),
-AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 32, 1),
+AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
+AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
 AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
 
 AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 0786d0e..cbf8331c 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -596,9 +596,7 @@
 };
 
 static irqreturn_t
-snd_ad1889_interrupt(int irq, 
-		     void *dev_id, 
-		     struct pt_regs *regs)
+snd_ad1889_interrupt(int irq, void *dev_id)
 {
 	unsigned long st;
 	struct snd_ad1889 *chip = dev_id;
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 7466839..a7edd56 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1047,9 +1047,7 @@
 }
 
 
-static irqreturn_t snd_ali_card_interrupt(int irq,
-				   void *dev_id,
-				   struct pt_regs *regs)
+static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id)
 {
 	struct snd_ali 	*codec = dev_id;
 
@@ -2034,8 +2032,10 @@
 	outl(0xffffffff, ALI_REG(chip, ALI_STOP));
 
 	spin_unlock_irq(&chip->reg_lock);
+
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2050,8 +2050,15 @@
 	if (! im)
 		return 0;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "ali5451: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
+	pci_set_master(pci);
 
 	spin_lock_irq(&chip->reg_lock);
 	
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 96cfb8a..95f70f3 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -204,8 +204,7 @@
 	return snd_als300_free(chip);
 }
 
-static irqreturn_t snd_als300_interrupt(int irq, void *dev_id,
-						struct pt_regs *regs)
+static irqreturn_t snd_als300_interrupt(int irq, void *dev_id)
 {
 	u8 status;
 	struct snd_als300 *chip = dev_id;
@@ -236,8 +235,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id,
-						struct pt_regs *regs)
+static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
 {
 	u8 general, mpu, dram;
 	struct snd_als300 *chip = dev_id;
@@ -770,9 +768,9 @@
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -781,9 +779,14 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_als300 *chip = card->private_data;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "als300: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_als300_init(chip);
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 9e596f7..8fb55d3 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -385,7 +385,7 @@
  * SB IRQ status.
  * And do we *really* need the lock here for *reading* SB_DSP4_IRQSTATUS??
  * */
-static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id)
 {
 	struct snd_sb *chip = dev_id;
 	unsigned gcr_status;
@@ -399,7 +399,7 @@
 	if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */
 		snd_pcm_period_elapsed(chip->capture_substream);
 	if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */
-		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 	/* release the gcr */
 	outb(gcr_status, chip->alt_port + 0xe);
 	
@@ -804,9 +804,9 @@
 	snd_pcm_suspend_all(chip->pcm);
 	snd_sbmixer_suspend(chip);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -816,9 +816,14 @@
 	struct snd_card_als4000 *acard = card->private_data;
 	struct snd_sb *chip = acard->chip;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "als4000: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_als4000_configure(chip);
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 347e25f..e3e99f3 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1300,7 +1300,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
 {
 	struct atiixp *chip = dev_id;
 	unsigned int status;
@@ -1442,9 +1442,9 @@
 	snd_atiixp_aclink_down(chip);
 	snd_atiixp_chip_stop(chip);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1454,9 +1454,14 @@
 	struct atiixp *chip = card->private_data;
 	int i;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "atiixp: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_atiixp_aclink_reset(chip);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index a89d67c..dc54f2c 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1017,7 +1017,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
 {
 	struct atiixp_modem *chip = dev_id;
 	unsigned int status;
@@ -1128,9 +1128,9 @@
 	snd_atiixp_aclink_down(chip);
 	snd_atiixp_chip_stop(chip);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1140,9 +1140,14 @@
 	struct atiixp_modem *chip = card->private_data;
 	int i;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "atiixp-modem: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_atiixp_aclink_reset(chip);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index ef189d7..6ed5ad5 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -128,6 +128,7 @@
 	// Take down PCI interface.
 	synchronize_irq(vortex->irq);
 	free_irq(vortex->irq, vortex);
+	iounmap(vortex->mmio);
 	pci_release_regions(vortex->pci_dev);
 	pci_disable_device(vortex->pci_dev);
 	kfree(vortex);
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index b1cfc3c..5ccf0b1 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -236,8 +236,7 @@
 static int vortex_core_init(vortex_t * card);
 static int vortex_core_shutdown(vortex_t * card);
 static void vortex_enable_int(vortex_t * card);
-static irqreturn_t vortex_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs);
+static irqreturn_t vortex_interrupt(int irq, void *dev_id);
 static int vortex_alsafmt_aspfmt(int alsafmt);
 
 /* Connection  stuff. */
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 5299cce..4a336ea 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2385,7 +2385,7 @@
 		hwread(card->mmio, VORTEX_CTRL) & ~CTRL_IRQ_ENABLE);
 }
 
-static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t vortex_interrupt(int irq, void *dev_id)
 {
 	vortex_t *vortex = dev_id;
 	int i, handled;
@@ -2462,7 +2462,7 @@
 	}
 	if (source & IRQ_MIDI) {
 		snd_mpu401_uart_interrupt(vortex->irq,
-					  vortex->rmidi->private_data, regs);
+					  vortex->rmidi->private_data);
 		handled = 1;
 	}
 
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index bac8e9c..2414ee6 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1191,7 +1191,7 @@
 }
 
 static irqreturn_t
-snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+snd_azf3328_interrupt(int irq, void *dev_id)
 {
 	struct snd_azf3328 *chip = dev_id;
 	u8 status, which;
@@ -1256,7 +1256,7 @@
 	/* MPU401 has less critical IRQ requirements
 	 * than timer and playback/recording, right? */
 	if (status & IRQ_MPU401) {
-		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 
 		/* hmm, do we have to ack the IRQ here somehow?
 		 * If so, then I don't know how... */
@@ -1903,9 +1903,9 @@
 	for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
 		chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1916,9 +1916,14 @@
 	struct snd_azf3328 *chip = card->private_data;
 	int reg;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "azt3328: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 97a280a..d33a370 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -269,7 +269,7 @@
 	}
 }
 
-static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id)
 {
 	struct snd_bt87x *chip = dev_id;
 	unsigned int status, irq_status;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 12bbbb6..6fa4a30 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1058,8 +1058,7 @@
 	return snd_ca0106_free(chip);
 }
 
-static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
-					  struct pt_regs *regs)
+static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
 {
 	unsigned int status;
 
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 876b644..0093cd1 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -1294,7 +1294,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id)
 {
 	struct cmipci *cm = dev_id;
 	unsigned int status, mask = 0;
@@ -1315,7 +1315,7 @@
 	spin_unlock(&cm->reg_lock);
 
 	if (cm->rmidi && (status & CM_UARTINT))
-		snd_mpu401_uart_interrupt(irq, cm->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, cm->rmidi->private_data);
 
 	if (cm->pcm) {
 		if ((status & CM_CHINT0) && cm->channel[0].running)
@@ -3122,9 +3122,9 @@
 	/* disable ints */
 	snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -3134,9 +3134,14 @@
 	struct cmipci *cm = card->private_data;
 	int i;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "cmipci: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	/* reset / initialize to a sane state */
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 1990430..0905fa8 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -493,7 +493,7 @@
 
 };
 
-static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_cs4281_ids[] = {
 	{ 0x1013, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	/* CS4281 */
@@ -1814,7 +1814,7 @@
  *  Interrupt handler
  */
 
-static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id)
 {
 	struct cs4281 *chip = dev_id;
 	unsigned int status, dma, val;
@@ -2050,6 +2050,7 @@
 
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2060,8 +2061,14 @@
 	unsigned int i;
 	u32 ulCLK;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "cs4281: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 4851847..2807b97 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1149,7 +1149,7 @@
 	return 0;
 }
 
-static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id)
 {
 	struct snd_cs46xx *chip = dev_id;
 	u32 status1;
@@ -3687,8 +3687,10 @@
 	/* disable CLKRUN */
 	chip->active_ctrl(chip, -chip->amplifier);
 	chip->amplifier = amp_saved; /* restore the status */
+
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -3698,9 +3700,16 @@
 	struct snd_cs46xx *chip = card->private_data;
 	int amp_saved;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "cs46xx: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
+
 	amp_saved = chip->amplifier;
 	chip->amplifier = 0;
 	chip->active_ctrl(chip, 1); /* force to on */
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 64c7826..2441238 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -203,8 +203,7 @@
 	}
 }
 
-static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id,
-					     struct pt_regs *regs)
+static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
 {
 	u16 acc_irq_stat;
 	u8 bm_stat;
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
index aad0e69..3e4d198 100644
--- a/sound/pci/cs5535audio/cs5535audio_pm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -73,9 +73,10 @@
 	snd_ac97_suspend(cs5535au->ac97);
 	/* save important regs, then disable aclink in hw */
 	snd_cs5535audio_stop_hardware(cs5535au);
+
 	pci_disable_device(pci);
 	pci_save_state(pci);
-
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -87,8 +88,14 @@
 	int timeout;
 	int i;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "cs5535audio: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	/* set LNK_WRM_RST to reset AC link */
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index c3dafa2..e5e88fe 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1818,8 +1818,7 @@
 	IRQ Handler
 ******************************************************************************/
 
-static irqreturn_t snd_echo_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
 {
 	struct echoaudio *chip = dev_id;
 	struct snd_pcm_substream *substream;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 493ec08..55caf34 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -226,9 +226,9 @@
 
 	snd_emu10k1_done(emu);
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -237,11 +237,16 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_emu10k1 *emu = card->private_data;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "emu10k1: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
-	
+
 	snd_emu10k1_resume_init(emu);
 	snd_emu10k1_efx_resume(emu);
 	snd_ac97_resume(emu->ac97);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index be65d4d..8058059 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1461,8 +1461,8 @@
 
 	/* resore for spdif */
 	if (emu->audigy)
-		outl(emu->port + A_IOCFG, emu->saved_a_iocfg);
-	outl(emu->port + HCFG, emu->saved_hcfg);
+		outl(emu->saved_a_iocfg, emu->port + A_IOCFG);
+	outl(emu->saved_hcfg, emu->port + HCFG);
 
 	val = emu->saved_ptr;
 	for (reg = saved_regs; *reg != 0xff; reg++)
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index da1610a..c46905a 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -780,8 +780,7 @@
 	return snd_emu10k1x_free(chip);
 }
 
-static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id,
-					  struct pt_regs *regs)
+static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
 {
 	unsigned int status;
 
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index 1076af4..4f18f7e 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -30,7 +30,7 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id)
 {
 	struct snd_emu10k1 *emu = dev_id;
 	unsigned int status, status2, orig_status, orig_status2;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index a8a601f..d2a811f 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -444,7 +444,7 @@
 #endif
 };
 
-static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_audiopci_ids[] = {
 #ifdef CHIP1370
@@ -2072,9 +2072,10 @@
 	udelay(100);
 	snd_ak4531_suspend(ensoniq->u.es1370.ak4531);
 #endif	
-	pci_set_power_state(pci, PCI_D3hot);
+
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2083,9 +2084,14 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct ensoniq *ensoniq = card->private_data;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR DRIVER_NAME ": pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_ensoniq_chip_init(ensoniq);
@@ -2404,7 +2410,7 @@
  *  Interrupt handler
  */
 
-static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id)
 {
 	struct ensoniq *ensoniq = dev_id;
 	unsigned int status, sctrl;
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 3ce5a4e..1a8d36d 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -241,7 +241,7 @@
 #endif
 };
 
-static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_es1938_ids[] = {
         { 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* Solo-1 */
@@ -1481,10 +1481,14 @@
 		*d = snd_es1938_reg_read(chip, *s);
 
 	outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
+		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
+		chip->irq = -1;
+	}
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1494,10 +1498,22 @@
 	struct es1938 *chip = card->private_data;
 	unsigned char *s, *d;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
-	request_irq(pci->irq, snd_es1938_interrupt,
-		    IRQF_DISABLED|IRQF_SHARED, "ES1938", chip);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "es1938: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
+
+	if (request_irq(pci->irq, snd_es1938_interrupt,
+			IRQF_DISABLED|IRQF_SHARED, "ES1938", chip)) {
+		printk(KERN_ERR "es1938: unable to grab IRQ %d, "
+		       "disabling device\n", pci->irq);
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	chip->irq = pci->irq;
 	snd_es1938_chip_init(chip);
 
@@ -1556,8 +1572,10 @@
 
 	snd_es1938_free_gameport(chip);
 
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
+		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
+	}
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
@@ -1602,6 +1620,7 @@
 	spin_lock_init(&chip->mixer_lock);
 	chip->card = card;
 	chip->pci = pci;
+	chip->irq = -1;
 	if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) {
 		kfree(chip);
 		pci_disable_device(pci);
@@ -1642,7 +1661,7 @@
 /* --------------------------------------------------------------------
  * Interrupt handler
  * -------------------------------------------------------------------- */
-static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id)
 {
 	struct es1938 *chip = dev_id;
 	unsigned char status, audiostatus;
@@ -1714,7 +1733,7 @@
 		// snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0); /* ack? */
 		if (chip->rmidi) {
 			handled = 1;
-			snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+			snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 		}
 	}
 	return IRQ_RETVAL(handled);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index f3c4038..092da53e 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -432,46 +432,6 @@
 #define ESM_MODE_PLAY		0
 #define ESM_MODE_CAPTURE	1
 
-/* acpi states */
-enum {
-	ACPI_D0=0,
-	ACPI_D1,
-	ACPI_D2,
-	ACPI_D3
-};
-
-/* bits in the acpi masks */
-#define ACPI_12MHZ	( 1 << 15)
-#define ACPI_24MHZ	( 1 << 14)
-#define ACPI_978	( 1 << 13)
-#define ACPI_SPDIF	( 1 << 12)
-#define ACPI_GLUE	( 1 << 11)
-#define ACPI__10	( 1 << 10) /* reserved */
-#define ACPI_PCIINT	( 1 << 9)
-#define ACPI_HV		( 1 << 8) /* hardware volume */
-#define ACPI_GPIO	( 1 << 7)
-#define ACPI_ASSP	( 1 << 6)
-#define ACPI_SB		( 1 << 5) /* sb emul */
-#define ACPI_FM		( 1 << 4) /* fm emul */
-#define ACPI_RB		( 1 << 3) /* ringbus / aclink */
-#define ACPI_MIDI	( 1 << 2) 
-#define ACPI_GP		( 1 << 1) /* game port */
-#define ACPI_WP		( 1 << 0) /* wave processor */
-
-#define ACPI_ALL	(0xffff)
-#define ACPI_SLEEP	(~(ACPI_SPDIF|ACPI_ASSP|ACPI_SB|ACPI_FM| \
-			ACPI_MIDI|ACPI_GP|ACPI_WP))
-#define ACPI_NONE	(ACPI__10)
-
-/* these masks indicate which units we care about at
-	which states */
-static u16 acpi_state_mask[] = {
-	[ACPI_D0] = ACPI_ALL,
-	[ACPI_D1] = ACPI_SLEEP,
-	[ACPI_D2] = ACPI_SLEEP,
-	[ACPI_D3] = ACPI_NONE
-};
-
 
 /* APU use in the driver */
 enum snd_enum_apu_type {
@@ -590,7 +550,7 @@
 #endif
 };
 
-static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_es1968_ids[] = {
 	/* Maestro 1 */
@@ -1962,7 +1922,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
 {
 	struct es1968 *chip = dev_id;
 	u32 event;
@@ -1979,7 +1939,7 @@
 	outb(0xFF, chip->io_port + 0x1A);
 
 	if ((event & ESM_MPU401_IRQ) && chip->rmidi) {
-		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 	}
 
 	if (event & ESM_SOUND_IRQ) {
@@ -2160,21 +2120,6 @@
 }
 
 /*
- * power management
- */
-static void snd_es1968_set_acpi(struct es1968 *chip, int state)
-{
-	u16 active_mask = acpi_state_mask[state];
-
-	pci_set_power_state(chip->pci, state);
-	/* make sure the units we care about are on 
-		XXX we might want to do this before state flipping? */
-	pci_write_config_word(chip->pci, 0x54, ~ active_mask);
-	pci_write_config_word(chip->pci, 0x56, ~ active_mask);
-}
-
-
-/*
  * initialize maestro chip
  */
 static void snd_es1968_chip_init(struct es1968 *chip)
@@ -2196,9 +2141,6 @@
 	 * IRQs.
 	 */
 	
-	/* do config work at full power */
-	snd_es1968_set_acpi(chip, ACPI_D0);
-
 	/* Config Reg A */
 	pci_read_config_word(pci, ESM_CONFIG_A, &w);
 
@@ -2397,9 +2339,10 @@
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
 	snd_es1968_bob_stop(chip);
-	snd_es1968_set_acpi(chip, ACPI_D3);
+
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2413,9 +2356,16 @@
 		return 0;
 
 	/* restore all our config */
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "es1968: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
+
 	snd_es1968_chip_init(chip);
 
 	/* need to restore the base pointers.. */ 
@@ -2514,7 +2464,6 @@
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
 	snd_es1968_free_gameport(chip);
-	snd_es1968_set_acpi(chip, ACPI_D3);
 	chip->master_switch = NULL;
 	chip->master_volume = NULL;
 	pci_release_regions(chip->pci);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index bdfda19..77e3d5c 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -520,7 +520,7 @@
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
-static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id)
 {
 	struct fm801 *chip = dev_id;
 	unsigned short status;
@@ -561,7 +561,7 @@
 		snd_pcm_period_elapsed(chip->capture_substream);
 	}
 	if (chip->rmidi && (status & FM801_IRQ_MPU))
-		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 	if (status & FM801_IRQ_VOLUME)
 		;/* TODO */
 
@@ -1531,9 +1531,9 @@
 		chip->saved_regs[i] = inw(chip->port + saved_regs[i]);
 	/* FIXME: tea575x suspend */
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1543,9 +1543,14 @@
 	struct fm801 *chip = card->private_data;
 	int i;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "fm801: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_fm801_chip_init(chip, 1);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index e9d4cb4..0e292dc 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -86,6 +86,7 @@
 			 "{ATI, SB450},"
 			 "{ATI, SB600},"
 			 "{ATI, RS600},"
+			 "{ATI, RS690},"
 			 "{VIA, VT8251},"
 			 "{VIA, VT8237A},"
 			 "{SiS, SIS966},"
@@ -336,6 +337,7 @@
 	unsigned int initialized :1;
 	unsigned int single_cmd :1;
 	unsigned int polling_mode :1;
+	unsigned int msi :1;
 };
 
 /* driver types */
@@ -396,6 +398,7 @@
  */
 #define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
 
+static int azx_acquire_irq(struct azx *chip, int do_disconnect);
 
 /*
  * Interface for HD codec
@@ -535,6 +538,18 @@
 		schedule_timeout_interruptible(1);
 	} while (time_after_eq(timeout, jiffies));
 
+	if (chip->msi) {
+		snd_printk(KERN_WARNING "hda_intel: No response from codec, "
+			   "disabling MSI...\n");
+		free_irq(chip->irq, chip);
+		chip->irq = -1;
+		pci_disable_msi(chip->pci);
+		chip->msi = 0;
+		if (azx_acquire_irq(chip, 1) < 0)
+			return -1;
+		goto again;
+	}
+
 	if (!chip->polling_mode) {
 		snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, "
 			   "switching to polling mode...\n");
@@ -811,7 +826,7 @@
 /*
  * interrupt handler
  */
-static irqreturn_t azx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t azx_interrupt(int irq, void *dev_id)
 {
 	struct azx *chip = dev_id;
 	struct azx_dev *azx_dev;
@@ -1363,6 +1378,20 @@
 	return 0;
 }
 
+static int azx_acquire_irq(struct azx *chip, int do_disconnect)
+{
+	if (request_irq(chip->pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
+			"HDA Intel", chip)) {
+		printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
+		       "disabling device\n", chip->pci->irq);
+		if (do_disconnect)
+			snd_card_disconnect(chip->card);
+		return -1;
+	}
+	chip->irq = chip->pci->irq;
+	return 0;
+}
+
 
 #ifdef CONFIG_PM
 /*
@@ -1379,12 +1408,16 @@
 		snd_pcm_suspend_all(chip->pcm[i]);
 	snd_hda_suspend(chip->bus, state);
 	azx_free_cmd_io(chip);
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
+		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
-	if (!disable_msi)
+		chip->irq = -1;
+	}
+	if (chip->msi)
 		pci_disable_msi(chip->pci);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1393,15 +1426,20 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct azx *chip = card->private_data;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
-	if (!disable_msi)
-		pci_enable_msi(pci);
-	/* FIXME: need proper error handling */
-	request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
-		    "HDA Intel", chip);
-	chip->irq = pci->irq;
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "hda-intel: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
+	if (chip->msi)
+		if (pci_enable_msi(pci) < 0)
+			chip->msi = 0;
+	if (azx_acquire_irq(chip, 1) < 0)
+		return -EIO;
 	azx_init_chip(chip);
 	snd_hda_resume(chip->bus);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1431,15 +1469,14 @@
 		/* disable position buffer */
 		azx_writel(chip, DPLBASE, 0);
 		azx_writel(chip, DPUBASE, 0);
-
-		synchronize_irq(chip->irq);
 	}
 
 	if (chip->irq >= 0) {
+		synchronize_irq(chip->irq);
 		free_irq(chip->irq, (void*)chip);
-		if (!disable_msi)
-			pci_disable_msi(chip->pci);
 	}
+	if (chip->msi)
+		pci_disable_msi(chip->pci);
 	if (chip->remap_addr)
 		iounmap(chip->remap_addr);
 
@@ -1494,6 +1531,7 @@
 	chip->pci = pci;
 	chip->irq = -1;
 	chip->driver_type = driver_type;
+	chip->msi = !disable_msi;
 
 	chip->position_fix = position_fix;
 	chip->single_cmd = single_cmd;
@@ -1523,16 +1561,14 @@
 		goto errout;
 	}
 
-	if (!disable_msi)
-		pci_enable_msi(pci);
+	if (chip->msi)
+		if (pci_enable_msi(pci) < 0)
+			chip->msi = 0;
 
-	if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
-			"HDA Intel", (void*)chip)) {
-		snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
+	if (azx_acquire_irq(chip, 0) < 0) {
 		err = -EBUSY;
 		goto errout;
 	}
-	chip->irq = pci->irq;
 
 	pci_set_master(pci);
 	synchronize_irq(chip->irq);
@@ -1677,11 +1713,13 @@
 	{ 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 */
+	{ 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
 	{ 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 */
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 511df07..edd22de 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -818,6 +818,8 @@
 	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7,
 	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1263,
+	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5F */
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1297,
 	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index a27440f..7333f27 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -161,5 +161,6 @@
  */
 struct hda_codec_preset snd_hda_preset_atihdmi[] = {
 	{ .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
+	{ .id = 0x1002791a, .name = "ATI RS690 HDMI", .patch = patch_atihdmi },
 	{} /* terminator */
 };
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d08d2e3..0d728c6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1799,7 +1799,7 @@
 	/* SPDIF for stream index #1 */
 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
 		codec->num_pcms = 2;
-		info++;
+		info = spec->pcm_rec + 1;
 		info->name = spec->stream_name_digital;
 		if (spec->multiout.dig_out_nid &&
 		    spec->stream_digital_playback) {
@@ -1820,7 +1820,7 @@
 	if (spec->num_adc_nids > 1 && spec->stream_analog_capture &&
 	    spec->adc_nids) {
 		codec->num_pcms = 3;
-		info++;
+		info = spec->pcm_rec + 2;
 		info->name = spec->stream_name_analog;
 		/* No playback stream for second PCM */
 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
@@ -5076,6 +5076,10 @@
 	{ .modelname = "acer", .config = ALC883_ACER },
 	{ .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/,
 	  .config = ALC883_ACER },
+	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0102,
+	  .config = ALC883_ACER },
+	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x009f,
+	  .config = ALC883_ACER },
 	{ .modelname = "auto", .config = ALC883_AUTO },
 	{}
 };
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 76ec3d7..cc87dff 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -297,8 +297,13 @@
 struct hda_codec_preset snd_hda_preset_si3054[] = {
  	{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
  	{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
+ 	{ .id = 0x11c11040, .name = "Si3054", .patch = patch_si3054 },
  	{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
+ 	{ .id = 0x11c13055, .name = "Si3054", .patch = patch_si3054 },
+ 	{ .id = 0x11c13155, .name = "Si3054", .patch = patch_si3054 },
+ 	{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
  	{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
+ 	{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
 	{}
 };
 
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index dc69392..8a576b7 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -420,7 +420,7 @@
  *  Interrupt handler
  */
 
-static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id)
 {
 	struct snd_ice1712 *ice = dev_id;
 	unsigned char status;
@@ -433,7 +433,7 @@
 		handled = 1;
 		if (status & ICE1712_IRQ_MPU1) {
 			if (ice->rmidi[0])
-				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data, regs);
+				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
 			outb(ICE1712_IRQ_MPU1, ICEREG(ice, IRQSTAT));
 			status &= ~ICE1712_IRQ_MPU1;
 		}
@@ -441,7 +441,7 @@
 			outb(ICE1712_IRQ_TIMER, ICEREG(ice, IRQSTAT));
 		if (status & ICE1712_IRQ_MPU2) {
 			if (ice->rmidi[1])
-				snd_mpu401_uart_interrupt(irq, ice->rmidi[1]->private_data, regs);
+				snd_mpu401_uart_interrupt(irq, ice->rmidi[1]->private_data);
 			outb(ICE1712_IRQ_MPU2, ICEREG(ice, IRQSTAT));
 			status &= ~ICE1712_IRQ_MPU2;
 		}
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 71d6aed..e9cbfdf 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -218,7 +218,7 @@
  *  Interrupt handler
  */
 
-static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
 {
 	struct snd_ice1712 *ice = dev_id;
 	unsigned char status;
@@ -236,7 +236,7 @@
 		 */
 		if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
 			if (ice->rmidi[0])
-				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data, regs);
+				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
 			outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
 			status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
 		}
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 72dbaed..7f22dab 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -801,7 +801,7 @@
 		 status & (ICH_FIFOE | ICH_BCIS | ICH_LVBCI));
 }
 
-static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
 {
 	struct intel8x0 *chip = dev_id;
 	struct ichdev *ichdev;
@@ -2476,10 +2476,14 @@
 	if (chip->device_type == DEVICE_INTEL_ICH4)
 		chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
 
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
+		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
+		chip->irq = -1;
+	}
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2489,11 +2493,22 @@
 	struct intel8x0 *chip = card->private_data;
 	int i;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "intel8x0: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
-	request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED,
-		    card->shortname, chip);
+	if (request_irq(pci->irq, snd_intel8x0_interrupt,
+			IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) {
+		printk(KERN_ERR "intel8x0: unable to grab IRQ %d, "
+		       "disabling device\n", pci->irq);
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	chip->irq = pci->irq;
 	synchronize_irq(chip->irq);
 	snd_intel8x0_chip_init(chip, 0);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 268e2f7..bd467c5 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -511,7 +511,7 @@
 	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
 }
 
-static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
 {
 	struct intel8x0m *chip = dev_id;
 	struct ichdev *ichdev;
@@ -1045,10 +1045,14 @@
 	for (i = 0; i < chip->pcm_devs; i++)
 		snd_pcm_suspend_all(chip->pcm[i]);
 	snd_ac97_suspend(chip->ac97);
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
+		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
+		chip->irq = -1;
+	}
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1057,11 +1061,22 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct intel8x0m *chip = card->private_data;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "intel8x0m: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
-	request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED,
-		    card->shortname, chip);
+	if (request_irq(pci->irq, snd_intel8x0_interrupt,
+			IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) {
+		printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "
+		       "disabling device\n", pci->irq);
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	chip->irq = pci->irq;
 	snd_intel8x0_chip_init(chip, 0);
 	snd_ac97_resume(chip->ac97);
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index cfea51f..fa8cd8c 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1119,14 +1119,11 @@
 	snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_COMPLETE);
 }
 
-static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id)
 {
         u32 doorbellValue;
         struct snd_korg1212 *korg1212 = dev_id;
 
-	if(irq != korg1212->irq)
-		return IRQ_NONE;
-
         doorbellValue = readl(korg1212->inDoorbellPtr);
 
         if (!doorbellValue)
@@ -1140,7 +1137,6 @@
 
 	korg1212->inIRQ++;
 
-
         switch (doorbellValue) {
                 case K1212_DB_DSPDownloadDone:
                         K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n",
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 45214b3..8cab342 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -1685,8 +1685,7 @@
 	spin_unlock_irqrestore(&chip->ac97_lock, flags);
 }
 
-static irqreturn_t
-snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
 {
 	struct snd_m3 *chip = dev_id;
 	u8 status;
@@ -2590,12 +2589,9 @@
 		chip->suspend_mem[index++] = 
 			snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i);
 
-	/* power down apci registers */
-	snd_m3_outw(chip, 0xffff, 0x54);
-	snd_m3_outw(chip, 0xffff, 0x56);
-
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2608,8 +2604,14 @@
 	if (chip->suspend_mem == NULL)
 		return 0;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "maestor3: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	/* first lets just bring everything back. .*/
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index 406ac3a..d544573 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -408,7 +408,7 @@
 }
 
 
-irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
 {
 	struct mixart_mgr *mgr = dev_id;
 	int err;
diff --git a/sound/pci/mixart/mixart_core.h b/sound/pci/mixart/mixart_core.h
index 1fe2bcf..c919b73 100644
--- a/sound/pci/mixart/mixart_core.h
+++ b/sound/pci/mixart/mixart_core.h
@@ -563,7 +563,7 @@
 int  snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *request, u32 notif_event);
 int  snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request);
 
-irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t snd_mixart_interrupt(int irq, void *dev_id);
 void snd_mixart_msg_tasklet(unsigned long arg);
 
 void snd_mixart_reset_board(struct mixart_mgr *mgr);
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 101eee0..945d21b 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -236,7 +236,7 @@
 
 	int irq;
 	int irq_acks;
-	irqreturn_t (*interrupt)(int, void *, struct pt_regs *);
+	irq_handler_t interrupt;
 	int badintrcount;		/* counter to check bogus interrupts */
 	struct mutex irq_mutex;
 
@@ -1004,7 +1004,7 @@
  */
 
 static irqreturn_t
-snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
+snd_nm256_interrupt(int irq, void *dev_id)
 {
 	struct nm256 *chip = dev_id;
 	u16 status;
@@ -1069,7 +1069,7 @@
  */
 
 static irqreturn_t
-snd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy)
+snd_nm256_interrupt_zx(int irq, void *dev_id)
 {
 	struct nm256 *chip = dev_id;
 	u32 status;
@@ -1390,6 +1390,7 @@
 	chip->coeffs_current = 0;
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1401,8 +1402,17 @@
 
 	/* Perform a full reset on the hardware */
 	chip->in_resume = 1;
+
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "nm256: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
+	pci_set_master(pci);
+
 	snd_nm256_init_chip(chip);
 
 	/* restore ac97 */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index c40f590..0ff8dc3 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -1131,7 +1131,7 @@
 }
 
 
-irqreturn_t pcxhr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
 {
 	struct pcxhr_mgr *mgr = dev_id;
 	unsigned int reg;
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
index e7415d6..d9a4ab6 100644
--- a/sound/pci/pcxhr/pcxhr_core.h
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -194,7 +194,7 @@
 
 
 /* interrupt handling */
-irqreturn_t pcxhr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t pcxhr_interrupt(int irq, void *dev_id);
 void pcxhr_msg_tasklet(unsigned long arg);
 
 #endif /* __SOUND_PCXHR_CORE_H */
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index fe210c8..56e0c01 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1178,9 +1178,9 @@
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1189,9 +1189,14 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_riptide *chip = card->private_data;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "riptide: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 	snd_riptide_initialize(chip);
 	snd_ac97_resume(chip->ac97);
@@ -1736,7 +1741,7 @@
 }
 
 static irqreturn_t
-snd_riptide_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+snd_riptide_interrupt(int irq, void *dev_id)
 {
 	struct snd_riptide *chip = dev_id;
 	struct cmdif *cif = chip->cif;
@@ -1751,8 +1756,7 @@
 		if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
 			chip->handled_irqs++;
 			snd_mpu401_uart_interrupt(irq,
-						  chip->rmidi->private_data,
-						  regs);
+						  chip->rmidi->private_data);
 		}
 		SET_AIACK(cif->hwport);
 	}
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 2a71499..dc8d130 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -818,8 +818,7 @@
 		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 }
 
-static irqreturn_t
-snd_rme32_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id)
 {
 	struct rme32 *rme32 = (struct rme32 *) dev_id;
 
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index f8de7c9..106110a 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1117,8 +1117,7 @@
 
 static irqreturn_t
 snd_rme96_interrupt(int irq,
-		    void *dev_id,
-		    struct pt_regs *regs)
+		    void *dev_id)
 {
 	struct rme96 *rme96 = (struct rme96 *)dev_id;
 
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index d3e07de..694aa05 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3603,7 +3603,7 @@
 		snd_hdsp_midi_input_read (&hdsp->midi[1]);
 } 
 
-static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
 {
 	struct hdsp *hdsp = (struct hdsp *) dev_id;
 	unsigned int status;
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 7d03ae0..7055d89 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2556,8 +2556,7 @@
    interupt 
  ------------------------------------------------------------*/
 
-static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
-				       struct pt_regs *regs)
+static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
 {
 	struct hdspm *hdspm = (struct hdspm *) dev_id;
 	unsigned int status;
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index fc15f61..cf0427b 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1882,7 +1882,7 @@
 	rme9652_set_rate(rme9652, 48000);
 }
 
-static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id)
 {
 	struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) dev_id;
 
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index e5d4def..f9b8afa 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -580,7 +580,7 @@
 	return result;
 }
 
-static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id)
 {
 	struct sonicvibes *sonic = dev_id;
 	unsigned char status;
@@ -601,7 +601,7 @@
 	}
 	if (sonic->rmidi) {
 		if (status & SV_MIDI_IRQ)
-			snd_mpu401_uart_interrupt(irq, sonic->rmidi->private_data, regs);
+			snd_mpu401_uart_interrupt(irq, sonic->rmidi->private_data);
 	}
 	if (status & SV_UD_IRQ) {
 		unsigned char udreg;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index ebbe12d..1fbc432 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -52,8 +52,7 @@
 static int snd_trident_pcm_mixer_free(struct snd_trident *trident,
 				      struct snd_trident_voice * voice,
 				      struct snd_pcm_substream *substream);
-static irqreturn_t snd_trident_interrupt(int irq, void *dev_id,
-					 struct pt_regs *regs);
+static irqreturn_t snd_trident_interrupt(int irq, void *dev_id);
 static int snd_trident_sis_reset(struct snd_trident *trident);
 
 static void snd_trident_clear_voices(struct snd_trident * trident,
@@ -3737,7 +3736,7 @@
   
   ---------------------------------------------------------------------------*/
 
-static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_trident_interrupt(int irq, void *dev_id)
 {
 	struct snd_trident *trident = dev_id;
 	unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
@@ -3825,7 +3824,7 @@
 	}
 	if (audio_int & MPU401_IRQ) {
 		if (trident->rmidi) {
-			snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data, regs);
+			snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data);
 		} else {
 			inb(TRID_REG(trident, T4D_MPUR0));
 		}
@@ -3967,15 +3966,9 @@
 	snd_ac97_suspend(trident->ac97);
 	snd_ac97_suspend(trident->ac97_sec);
 
-	switch (trident->device) {
-	case TRIDENT_DEVICE_ID_DX:
-	case TRIDENT_DEVICE_ID_NX:
-		break;			/* TODO */
-	case TRIDENT_DEVICE_ID_SI7018:
-		break;
-	}
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -3984,9 +3977,15 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_trident *trident = card->private_data;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
-	pci_set_master(pci); /* to be sure */
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "trident: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
+	pci_set_master(pci);
 
 	switch (trident->device) {
 	case TRIDENT_DEVICE_ID_DX:
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 6db3d4c..92b0736 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -613,7 +613,7 @@
  *  Interrupt handler
  *  Used for 686 and 8233A
  */
-static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_via686_interrupt(int irq, void *dev_id)
 {
 	struct via82xx *chip = dev_id;
 	unsigned int status;
@@ -623,7 +623,7 @@
 	if (! (status & chip->intr_mask)) {
 		if (chip->rmidi)
 			/* check mpu401 interrupt */
-			return snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+			return snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 		return IRQ_NONE;
 	}
 
@@ -659,7 +659,7 @@
 /*
  *  Interrupt handler
  */
-static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id)
 {
 	struct via82xx *chip = dev_id;
 	unsigned int status;
@@ -2185,9 +2185,9 @@
 		chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
 	}
 
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2197,9 +2197,15 @@
 	struct via82xx *chip = card->private_data;
 	int i;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "via82xx: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
+	pci_set_master(pci);
 
 	snd_via82xx_chip_init(chip);
 
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 016f9da..feb27c9 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -475,7 +475,7 @@
  *  Interrupt handler
  */
 
-static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id)
 {
 	struct via82xx_modem *chip = dev_id;
 	unsigned int status;
@@ -1032,9 +1032,10 @@
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
 	synchronize_irq(chip->irq);
 	snd_ac97_suspend(chip->ac97);
-	pci_set_power_state(pci, PCI_D3hot);
+
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -1044,9 +1045,14 @@
 	struct via82xx_modem *chip = card->private_data;
 	int i;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "via82xx-modem: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 
 	snd_via82xx_chip_init(chip);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index e7cd8ac..af49e8a 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -266,9 +266,9 @@
 	int err;
 
 	err = snd_vx_suspend(&vx->core, state);
-	pci_set_power_state(pci, PCI_D3hot);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return err;
 }
 
@@ -277,9 +277,14 @@
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_vx222 *vx = card->private_data;
 
-	pci_restore_state(pci);
-	pci_enable_device(pci);
 	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "vx222: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 	return snd_vx_resume(&vx->core);
 }
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 24f6fc5..a40c108 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -753,7 +753,7 @@
 	}
 }
 
-static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id)
 {
 	struct snd_ymfpci *chip = dev_id;
 	u32 status, nvoice, mode;
@@ -799,7 +799,7 @@
 	snd_ymfpci_writew(chip, YDSXGR_INTFLAG, status);
 
 	if (chip->rawmidi)
-		snd_mpu401_uart_interrupt(irq, chip->rawmidi->private_data, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rawmidi->private_data);
 	return IRQ_HANDLED;
 }
 
@@ -2218,6 +2218,7 @@
 	snd_ymfpci_disable_dsp(chip);
 	pci_disable_device(pci);
 	pci_save_state(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
 	return 0;
 }
 
@@ -2227,8 +2228,14 @@
 	struct snd_ymfpci *chip = card->private_data;
 	unsigned int i;
 
+	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
-	pci_enable_device(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "ymfpci: pci_enable_device failed, "
+		       "disabling device\n");
+		snd_card_disconnect(card);
+		return -EIO;
+	}
 	pci_set_master(pci);
 	snd_ymfpci_aclink_reset(pci);
 	snd_ymfpci_codec_ready(chip, 0);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 9a14a4f..206e2f5 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -138,7 +138,7 @@
 int snd_pdacf_resume(struct snd_pdacf *chip);
 #endif
 int snd_pdacf_pcm_new(struct snd_pdacf *chip);
-irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs);
+irqreturn_t pdacf_interrupt(int irq, void *dev);
 void pdacf_tasklet(unsigned long private_data);
 void pdacf_reinit(struct snd_pdacf *chip, int resume);
 
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index 7c5f21e..5bd6920 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -22,11 +22,12 @@
 #include <sound/core.h>
 #include "pdaudiocf.h"
 #include <sound/initval.h>
+#include <asm/irq_regs.h>
 
 /*
  *
  */
-irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t pdacf_interrupt(int irq, void *dev)
 {
 	struct snd_pdacf *chip = dev;
 	unsigned short stat;
@@ -45,7 +46,7 @@
 		if (!(stat & PDAUDIOCF_IRQAKM))
 			stat |= PDAUDIOCF_IRQAKM;	/* check rate */
 	}
-	if (regs != NULL)
+	if (get_irq_regs() != NULL)
 		snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
 	return IRQ_HANDLED;
 }
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 6414306..c64af55 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -713,7 +713,7 @@
  * interrupt handlers
  */
 static irqreturn_t
-snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs)
+snd_pmac_tx_intr(int irq, void *devid)
 {
 	struct snd_pmac *chip = devid;
 	snd_pmac_pcm_update(chip, &chip->playback);
@@ -722,7 +722,7 @@
 
 
 static irqreturn_t
-snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs)
+snd_pmac_rx_intr(int irq, void *devid)
 {
 	struct snd_pmac *chip = devid;
 	snd_pmac_pcm_update(chip, &chip->capture);
@@ -731,7 +731,7 @@
 
 
 static irqreturn_t
-snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs)
+snd_pmac_ctrl_intr(int irq, void *devid)
 {
 	struct snd_pmac *chip = devid;
 	int ctrl = in_le32(&chip->awacs->control);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index cdff53e..2fbe1d1 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1017,7 +1017,7 @@
 
 
 /* interrupt - headphone plug changed */
-static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs)
+static irqreturn_t headphone_intr(int irq, void *devid)
 {
 	struct snd_pmac *chip = devid;
 	if (chip->update_automute && chip->initialized) {
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index be0bd50..c899786 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -491,7 +491,7 @@
 	__amd7930_write_map(amd);
 }
 
-static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id)
 {
 	struct snd_amd7930 *amd = dev_id;
 	unsigned int elapsed;
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 9a06c3bd..edeb3d3 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1753,7 +1753,7 @@
 
 #ifdef SBUS_SUPPORT
 
-static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id)
 {
 	unsigned long flags;
 	unsigned char status;
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 5a97be6..4ceb09d 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -1903,8 +1903,7 @@
 	}
 }
 
-static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id)
 {
 	struct snd_dbri *dbri = dev_id;
 	static int errcnt = 0;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index a42acf6..c82b01c 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -653,7 +653,7 @@
 /*
  * complete callback from data urb
  */
-static void snd_complete_urb(struct urb *urb, struct pt_regs *regs)
+static void snd_complete_urb(struct urb *urb)
 {
 	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
 	struct snd_usb_substream *subs = ctx->subs;
@@ -676,7 +676,7 @@
 /*
  * complete callback from sync urb
  */
-static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs)
+static void snd_complete_sync_urb(struct urb *urb)
 {
 	struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
 	struct snd_usb_substream *subs = ctx->subs;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 0dcf78a..b7c5e59 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -223,7 +223,7 @@
 /*
  * Processes the data read from the device.
  */
-static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
+static void snd_usbmidi_in_urb_complete(struct urb* urb)
 {
 	struct snd_usb_midi_in_endpoint* ep = urb->context;
 
@@ -247,7 +247,7 @@
 	snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
 }
 
-static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
+static void snd_usbmidi_out_urb_complete(struct urb* urb)
 {
 	struct snd_usb_midi_out_endpoint* ep = urb->context;
 
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index e516d6a..1024c17 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1710,7 +1710,7 @@
 	}
 }
 
-static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs)
+static void snd_usb_mixer_status_complete(struct urb *urb)
 {
 	struct usb_mixer_interface *mixer = urb->context;
 
@@ -1772,8 +1772,7 @@
 	return 0;
 }
 
-static void snd_usb_soundblaster_remote_complete(struct urb *urb,
-						 struct pt_regs *regs)
+static void snd_usb_soundblaster_remote_complete(struct urb *urb)
 {
 	struct usb_mixer_interface *mixer = urb->context;
 	const struct rc_config *rc = mixer->rc_cfg;
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cfec38d..e011fca 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -172,7 +172,7 @@
 /* 
  * pipe 4 is used for switching the lamps, setting samplerate, volumes ....   
  */
-static void i_usX2Y_Out04Int(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_Out04Int(struct urb *urb)
 {
 #ifdef CONFIG_SND_DEBUG
 	if (urb->status) {
@@ -184,7 +184,7 @@
 #endif
 }
 
-static void i_usX2Y_In04Int(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_In04Int(struct urb *urb)
 {
 	int			err = 0;
 	struct usX2Ydev		*usX2Y = urb->context;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index f6bd0de..367f8a3 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -306,7 +306,7 @@
 	usX2Y_clients_stop(usX2Y);
 }
 
-static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_urb_complete(struct urb *urb)
 {
 	struct snd_usX2Y_substream *subs = urb->context;
 	struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -322,7 +322,7 @@
 		usX2Y_error_urb_status(usX2Y, subs, urb);
 		return;
 	}
-	if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame))
+	if (likely(urb->start_frame == usX2Y->wait_iso_frame))
 		subs->completed_urb = urb;
 	else {
 		usX2Y_error_sequence(usX2Y, subs, urb);
@@ -335,13 +335,9 @@
 		    atomic_read(&capsubs->state) >= state_PREPARED &&
 		    (playbacksubs->completed_urb ||
 		     atomic_read(&playbacksubs->state) < state_PREPARED)) {
-			if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) {
-				if (nr_of_packs() <= urb->start_frame &&
-				    urb->start_frame <= (2 * nr_of_packs() - 1))	// uhci and ohci
-					usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
-				else
-					usX2Y->wait_iso_frame +=  nr_of_packs();
-			} else {
+			if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame))
+				usX2Y->wait_iso_frame += nr_of_packs();
+			else {
 				snd_printdd("\n");
 				usX2Y_clients_stop(usX2Y);
 			}
@@ -350,7 +346,7 @@
 }
 
 static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y,
-				    void (*complete)(struct urb *, struct pt_regs *))
+				    void (*complete)(struct urb *))
 {
 	int s, u;
 	for (s = 0; s < 4; s++) {
@@ -370,7 +366,7 @@
 	usX2Y->prepare_subs = NULL;
 }
 
-static void i_usX2Y_subs_startup(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_subs_startup(struct urb *urb)
 {
 	struct snd_usX2Y_substream *subs = urb->context;
 	struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -382,7 +378,7 @@
 			wake_up(&usX2Y->prepare_wait_queue);
 		}
 
-	i_usX2Y_urb_complete(urb, regs);
+	i_usX2Y_urb_complete(urb);
 }
 
 static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs)
@@ -495,7 +491,6 @@
 		if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
 			goto start;
 	}
-	usX2Y->wait_iso_frame = -1;
 
  start:
 	usX2Y_subs_startup(subs);
@@ -516,10 +511,9 @@
 				snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
 				err = -EPIPE;
 				goto cleanup;
-			} else {
-				if (0 > usX2Y->wait_iso_frame)
+			} else
+				if (i == 0)
 					usX2Y->wait_iso_frame = urb->start_frame;
-			}
 			urb->transfer_flags = 0;
 		} else {
 			atomic_set(&subs->state, state_STARTING1);
@@ -663,7 +657,7 @@
 };
 #define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000)
 
-static void i_usX2Y_04Int(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_04Int(struct urb *urb)
 {
 	struct usX2Ydev *usX2Y = urb->context;
 	
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 88b72b5..8f3e35e 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -226,7 +226,7 @@
 }
 
 
-static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
 {
 	struct snd_usX2Y_substream *subs = urb->context;
 	struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -243,7 +243,7 @@
 		usX2Y_error_urb_status(usX2Y, subs, urb);
 		return;
 	}
-	if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame))
+	if (likely(urb->start_frame == usX2Y->wait_iso_frame))
 		subs->completed_urb = urb;
 	else {
 		usX2Y_error_sequence(usX2Y, subs, urb);
@@ -256,13 +256,9 @@
 	if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
 	    (NULL == capsubs2 || capsubs2->completed_urb) &&
 	    (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
-		if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) {
-			if (nr_of_packs() <= urb->start_frame &&
-			    urb->start_frame <= (2 * nr_of_packs() - 1))	// uhci and ohci
-				usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
-			else
-				usX2Y->wait_iso_frame +=  nr_of_packs();
-		} else {
+		if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame))
+			usX2Y->wait_iso_frame += nr_of_packs();
+		else {
 			snd_printdd("\n");
 			usX2Y_clients_stop(usX2Y);
 		}
@@ -294,7 +290,7 @@
 	usX2Y->prepare_subs = NULL;
 }
 
-static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs)
+static void i_usX2Y_usbpcm_subs_startup(struct urb *urb)
 {
 	struct snd_usX2Y_substream *subs = urb->context;
 	struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -311,7 +307,7 @@
 		wake_up(&usX2Y->prepare_wait_queue);
 	}
 
-	i_usX2Y_usbpcm_urb_complete(urb, regs);
+	i_usX2Y_usbpcm_urb_complete(urb);
 }
 
 /*
@@ -433,7 +429,6 @@
 		if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
 			goto start;
 	}
-	usX2Y->wait_iso_frame = -1;
 
  start:
 	usX2Y_usbpcm_subs_startup(subs);
@@ -459,7 +454,7 @@
 						goto cleanup;
 					}  else {
 						snd_printdd("%i\n", urb->start_frame);
-						if (0 > usX2Y->wait_iso_frame)
+						if (u == 0)
 							usX2Y->wait_iso_frame = urb->start_frame;
 					}
 					urb->transfer_flags = 0;
@@ -632,7 +627,7 @@
 		for (s = 0; s < 2; ++s) {
 			struct snd_pcm_substream *substream;
 			substream = pcm->streams[s].substream;
-			if (SUBSTREAM_BUSY(substream))
+			if (substream && SUBSTREAM_BUSY(substream))
 				err = -EBUSY;
 		}
 	}